diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 74 | ||||
| -rw-r--r-- | libs/androidfw/tests/Android.mk | 30 | ||||
| -rw-r--r-- | libs/androidfw/tests/ResTable_test.cpp | 81 | ||||
| -rw-r--r-- | libs/hwui/AmbientShadow.cpp | 15 | ||||
| -rw-r--r-- | libs/hwui/FontRenderer.cpp | 82 | ||||
| -rw-r--r-- | libs/hwui/FontRenderer.h | 14 | ||||
| -rw-r--r-- | libs/hwui/GlopBuilder.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/JankTracker.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/JankTracker.h | 3 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 1525 | ||||
| -rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 173 | ||||
| -rw-r--r-- | libs/hwui/ProgramCache.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/RenderBufferCache.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/SkiaCanvasProxy.cpp | 1 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.cpp | 372 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.h | 65 | ||||
| -rw-r--r-- | libs/hwui/Snapshot.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/SpotShadow.cpp | 11 |
19 files changed, 412 insertions, 2063 deletions
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index e2471505182c..04ebe70304a6 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -17,6 +17,16 @@ #define LOG_TAG "ResourceType" //#define LOG_NDEBUG 0 +#include <ctype.h> +#include <memory.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <limits> +#include <type_traits> + #include <androidfw/ByteBucketArray.h> #include <androidfw/ResourceTypes.h> #include <androidfw/TypeWrappers.h> @@ -27,17 +37,10 @@ #include <utils/String16.h> #include <utils/String8.h> -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ #include <binder/TextOutput.h> #endif -#include <stdlib.h> -#include <string.h> -#include <memory.h> -#include <ctype.h> -#include <stdint.h> -#include <stddef.h> - #ifndef INT32_MAX #define INT32_MAX ((int32_t)(2147483647)) #endif @@ -4615,8 +4618,7 @@ static bool parse_unit(const char* str, Res_value* outValue, return false; } - -bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) +bool U16StringToInt(const char16_t* s, size_t len, Res_value* outValue) { while (len > 0 && isspace16(*s)) { s++; @@ -4628,7 +4630,7 @@ bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) } size_t i = 0; - int32_t val = 0; + int64_t val = 0; bool neg = false; if (*s == '-') { @@ -4640,28 +4642,50 @@ bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) return false; } + static_assert(std::is_same<uint32_t, Res_value::data_type>::value, + "Res_value::data_type has changed. The range checks in this " + "function are no longer correct."); + // Decimal or hex? - if (s[i] == '0' && s[i+1] == 'x') { - if (outValue) - outValue->dataType = outValue->TYPE_INT_HEX; + bool isHex; + if (len > 1 && s[i] == '0' && s[i+1] == 'x') { + isHex = true; i += 2; + + if (neg) { + return false; + } + + if (i == len) { + // Just u"0x" + return false; + } + bool error = false; while (i < len && !error) { val = (val*16) + get_hex(s[i], &error); i++; + + if (val > std::numeric_limits<uint32_t>::max()) { + return false; + } } if (error) { return false; } } else { - if (outValue) - outValue->dataType = outValue->TYPE_INT_DEC; + isHex = false; while (i < len) { if (s[i] < '0' || s[i] > '9') { return false; } val = (val*10) + s[i]-'0'; i++; + + if ((neg && -val < std::numeric_limits<int32_t>::min()) || + (!neg && val > std::numeric_limits<int32_t>::max())) { + return false; + } } } @@ -4671,13 +4695,21 @@ bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) i++; } - if (i == len) { - if (outValue) - outValue->data = val; - return true; + if (i != len) { + return false; } - return false; + if (outValue) { + outValue->dataType = + isHex ? outValue->TYPE_INT_HEX : outValue->TYPE_INT_DEC; + outValue->data = static_cast<Res_value::data_type>(val); + } + return true; +} + +bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) +{ + return U16StringToInt(s, len, outValue); } bool ResTable::stringToFloat(const char16_t* s, size_t len, Res_value* outValue) diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk index 58b78b5f4469..a353575b4073 100644 --- a/libs/androidfw/tests/Android.mk +++ b/libs/androidfw/tests/Android.mk @@ -19,6 +19,7 @@ # targets here. # ========================================================== LOCAL_PATH:= $(call my-dir) + testFiles := \ AttributeFinder_test.cpp \ ByteBucketArray_test.cpp \ @@ -32,27 +33,33 @@ testFiles := \ TypeWrappers_test.cpp \ ZipUtils_test.cpp +androidfw_test_cflags := \ + -Wall \ + -Werror \ + -Wunused \ + -Wunreachable-code \ + -Wno-missing-field-initializers \ + +# gtest is broken. +androidfw_test_cflags += -Wno-unnamed-type-template-args + # ========================================================== # Build the host tests: libandroidfw_tests # ========================================================== include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests - -LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -# gtest is broken. -LOCAL_CFLAGS += -Wno-unnamed-type-template-args - +LOCAL_CFLAGS := $(androidfw_test_cflags) LOCAL_SRC_FILES := $(testFiles) LOCAL_STATIC_LIBRARIES := \ libandroidfw \ libutils \ libcutils \ - liblog + liblog \ + libz \ include $(BUILD_HOST_NATIVE_TEST) - # ========================================================== # Build the device tests: libandroidfw_tests # ========================================================== @@ -60,14 +67,11 @@ ifneq ($(SDK_ONLY),true) include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests - -LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -# gtest is broken. -LOCAL_CFLAGS += -Wno-unnamed-type-template-args - +LOCAL_CFLAGS := $(androidfw_test_cflags) LOCAL_SRC_FILES := $(testFiles) \ BackupData_test.cpp \ - ObbFile_test.cpp + ObbFile_test.cpp \ + LOCAL_SHARED_LIBRARIES := \ libandroidfw \ libcutils \ diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp index 6a9314e5ffb8..dcfe91e3866d 100644 --- a/libs/androidfw/tests/ResTable_test.cpp +++ b/libs/androidfw/tests/ResTable_test.cpp @@ -16,6 +16,10 @@ #include <androidfw/ResourceTypes.h> +#include <codecvt> +#include <locale> +#include <string> + #include <utils/String8.h> #include <utils/String16.h> #include "TestHelpers.h" @@ -201,4 +205,81 @@ TEST(ResTableTest, emptyTableHasSensibleDefaults) { ASSERT_LT(table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG), 0); } +void testU16StringToInt(const char16_t* str, uint32_t expectedValue, + bool expectSuccess, bool expectHex) { + size_t len = std::char_traits<char16_t>::length(str); + + // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :( + std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; + std::string s = convert.to_bytes(std::u16string(str, len)); + + Res_value out = {}; + ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out)) + << "Failed with " << s; + + if (!expectSuccess) { + ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s; + return; + } + + if (expectHex) { + ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s; + } else { + ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s; + } + + ASSERT_EQ(expectedValue, out.data) << "Failed with " << s; +} + +TEST(ResTableTest, U16StringToInt) { + testU16StringToInt(u"", 0U, false, false); + testU16StringToInt(u" ", 0U, false, false); + testU16StringToInt(u"\t\n", 0U, false, false); + + testU16StringToInt(u"abcd", 0U, false, false); + testU16StringToInt(u"10abcd", 0U, false, false); + testU16StringToInt(u"42 42", 0U, false, false); + testU16StringToInt(u"- 42", 0U, false, false); + testU16StringToInt(u"-", 0U, false, false); + + testU16StringToInt(u"0x", 0U, false, true); + testU16StringToInt(u"0xnope", 0U, false, true); + testU16StringToInt(u"0X42", 0U, false, true); + testU16StringToInt(u"0x42 0x42", 0U, false, true); + testU16StringToInt(u"-0x0", 0U, false, true); + testU16StringToInt(u"-0x42", 0U, false, true); + testU16StringToInt(u"- 0x42", 0U, false, true); + + // Note that u" 42" would pass. This preserves the old behavior, but it may + // not be desired. + testU16StringToInt(u"42 ", 0U, false, false); + testU16StringToInt(u"0x42 ", 0U, false, true); + + // Decimal cases. + testU16StringToInt(u"0", 0U, true, false); + testU16StringToInt(u"-0", 0U, true, false); + testU16StringToInt(u"42", 42U, true, false); + testU16StringToInt(u" 42", 42U, true, false); + testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false); + testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false); + testU16StringToInt(u"042", 42U, true, false); + testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false); + + // Hex cases. + testU16StringToInt(u"0x0", 0x0, true, true); + testU16StringToInt(u"0x42", 0x42, true, true); + testU16StringToInt(u" 0x42", 0x42, true, true); + + // Just before overflow cases: + testU16StringToInt(u"2147483647", INT_MAX, true, false); + testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true, + false); + testU16StringToInt(u"0xffffffff", UINT_MAX, true, true); + + // Overflow cases: + testU16StringToInt(u"2147483648", 0U, false, false); + testU16StringToInt(u"-2147483649", 0U, false, false); + testU16StringToInt(u"0x1ffffffff", 0U, false, true); +} + } diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp index 0a210d6927dc..a4100a2d44fb 100644 --- a/libs/hwui/AmbientShadow.cpp +++ b/libs/hwui/AmbientShadow.cpp @@ -45,8 +45,9 @@ /** * Other constants: */ -// For the edge of the penumbra, the opacity is 0. -#define OUTER_OPACITY (0.0f) +// For the edge of the penumbra, the opacity is 0. After transform (1 - alpha), +// it is 1. +#define TRANSFORMED_OUTER_OPACITY (1.0f) // Once the alpha difference is greater than this threshold, we will allocate extra // edge vertices. @@ -83,11 +84,13 @@ inline float getAlphaFromFactoredZ(float factoredZ) { return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f)); } +// The shader is using gaussian function e^-(1-x)*(1-x)*4, therefore, we transform +// the alpha value to (1 - alpha) inline float getTransformedAlphaFromAlpha(float alpha) { - return acosf(1.0f - 2.0f * alpha); + return 1.0f - alpha; } -// The output is ranged from 0 to M_PI. +// The output is ranged from 0 to 1. inline float getTransformedAlphaFromFactoredZ(float factoredZ) { return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ)); } @@ -249,7 +252,7 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque, indexBuffer[indexBufferIndex++] = vertexBufferIndex; indexBuffer[indexBufferIndex++] = currentInnerVertexIndex; AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x, - outerVertex.y, OUTER_OPACITY); + outerVertex.y, TRANSFORMED_OUTER_OPACITY); if (j == 0) { outerStart = outerVertex; @@ -285,7 +288,7 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque, (outerLast * startWeight + outerNext * k) / extraVerticesNumber; indexBuffer[indexBufferIndex++] = vertexBufferIndex; AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x, - currentOuter.y, OUTER_OPACITY); + currentOuter.y, TRANSFORMED_OUTER_OPACITY); if (!isCasterOpaque) { umbraVertices[umbraIndex++] = vertexBufferIndex; diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 6bef7c7a807f..c79ae777d051 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -46,51 +46,11 @@ namespace uirenderer { // blur inputs smaller than this constant will bypass renderscript #define RS_MIN_INPUT_CUTOFF 10000 -#define USE_GLOPS true - /////////////////////////////////////////////////////////////////////////////// // TextSetupFunctor /////////////////////////////////////////////////////////////////////////////// -void TextSetupFunctor::setup(GLenum glyphFormat) { - renderer->setupDraw(); - renderer->setupDrawTextGamma(paint); - renderer->setupDrawDirtyRegionsDisabled(); - renderer->setupDrawWithTexture(glyphFormat == GL_ALPHA); - switch (glyphFormat) { - case GL_ALPHA: { - renderer->setupDrawAlpha8Color(paint->getColor(), alpha); - break; - } - case GL_RGBA: { - float floatAlpha = alpha / 255.0f; - renderer->setupDrawColor(floatAlpha, floatAlpha, floatAlpha, floatAlpha); - break; - } - default: { -#if DEBUG_FONT_RENDERER - ALOGD("TextSetupFunctor: called with unknown glyph format %x", glyphFormat); -#endif - break; - } - } - renderer->setupDrawColorFilter(paint->getColorFilter()); - renderer->setupDrawShader(paint->getShader()); - renderer->setupDrawBlending(paint); - renderer->setupDrawProgram(); - renderer->setupDrawModelView(kModelViewMode_Translate, false, - 0.0f, 0.0f, 0.0f, 0.0f, pureTranslate); - // Calling setupDrawTexture with the name 0 will enable the - // uv attributes and increase the texture unit count - // texture binding will be performed by the font renderer as - // needed - renderer->setupDrawTexture(0); - renderer->setupDrawPureColorUniforms(); - renderer->setupDrawColorFilterUniforms(paint->getColorFilter()); - renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate); - renderer->setupDrawTextGammaUniforms(); -} -void TextSetupFunctor::draw(CacheTexture& texture, bool linearFiltering) { +void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) { int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); if (linearFiltering) { @@ -204,6 +164,8 @@ void FontRenderer::flushAllAndInvalidate() { for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { mRGBACacheTextures[i]->init(); } + + mDrawn = false; } void FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) { @@ -508,11 +470,6 @@ void FontRenderer::checkTextureUpdate() { void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { if (!mFunctor) return; -#if !USE_GLOPS - Caches& caches = mFunctor->renderer->getCaches(); - RenderState& renderState = mFunctor->renderer->renderState(); -#endif - bool first = true; bool forceRebind = false; for (uint32_t i = 0; i < cacheTextures.size(); i++) { @@ -520,37 +477,12 @@ void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { if (texture->canDraw()) { if (first) { checkTextureUpdate(); -#if !USE_GLOPS - mFunctor->setup(texture->getFormat()); - - renderState.meshState().bindQuadIndicesBuffer(); - - // If returns true, a VBO was bound and we must - // rebind our vertex attrib pointers even if - // they have the same values as the current pointers - forceRebind = renderState.meshState().unbindMeshBuffer(); - - caches.textureState().activateTexture(0); -#endif first = false; mDrawn = true; } -#if USE_GLOPS - mFunctor->draw(*texture, mLinearFiltering); -#endif -#if !USE_GLOPS - caches.textureState().bindTexture(texture->getTextureId()); - texture->setLinearFiltering(mLinearFiltering); - - TextureVertex* mesh = texture->mesh(); - MeshState& meshState = renderState.meshState(); - meshState.bindPositionVertexPointer(forceRebind, &mesh[0].x); - meshState.bindTexCoordsVertexPointer(forceRebind, &mesh[0].u); + mFunctor->draw(*texture, mLinearFiltering); - glDrawElements(GL_TRIANGLES, texture->meshElementCount(), - GL_UNSIGNED_SHORT, texture->indices()); -#endif texture->resetMesh(); forceRebind = false; } @@ -689,7 +621,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co return image; } -void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor) { +void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor) { checkInit(); mDrawn = false; @@ -717,7 +649,7 @@ void FontRenderer::endPrecaching() { bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, - const float* positions, Rect* bounds, TextSetupFunctor* functor, bool forceFinish) { + const float* positions, Rect* bounds, TextDrawFunctor* functor, bool forceFinish) { if (!mCurrentFont) { ALOGE("No font set"); return false; @@ -735,7 +667,7 @@ bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const c bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path, - float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor) { + float hOffset, float vOffset, Rect* bounds, TextDrawFunctor* functor) { if (!mCurrentFont) { ALOGE("No font set"); return false; diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index 0603389d1b70..dfb107c99bc5 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -46,9 +46,9 @@ namespace uirenderer { class OpenGLRenderer; -class TextSetupFunctor { +class TextDrawFunctor { public: - TextSetupFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate, + TextDrawFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate, int alpha, SkXfermode::Mode mode, const SkPaint* paint) : renderer(renderer) , x(x) @@ -59,8 +59,6 @@ public: , paint(paint) { } - void setup(GLenum glyphFormat); - void draw(CacheTexture& texture, bool linearFiltering); OpenGLRenderer* renderer; @@ -92,12 +90,12 @@ public: // bounds is an out parameter bool renderPosText(const SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, - Rect* bounds, TextSetupFunctor* functor, bool forceFinish = true); + Rect* bounds, TextDrawFunctor* functor, bool forceFinish = true); // bounds is an out parameter bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path, - float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor); + float hOffset, float vOffset, Rect* bounds, TextDrawFunctor* functor); struct DropShadow { uint32_t width; @@ -135,7 +133,7 @@ private: void flushAllAndInvalidate(); void checkInit(); - void initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor); + void initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor); void finishRender(); void issueDrawCommand(Vector<CacheTexture*>& cacheTextures); @@ -176,7 +174,7 @@ private: bool mUploadTexture; - TextSetupFunctor* mFunctor; + TextDrawFunctor* mFunctor; const Rect* mClip; Rect* mBounds; bool mDrawn; diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 0a46014a9f7d..9ca6bc635338 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -586,6 +586,12 @@ void GlopBuilder::build() { mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kColor; mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha; + // Enable debug highlight when what we're about to draw is tested against + // the stencil buffer and if stencil highlight debugging is on + mDescription.hasDebugHighlight = !mCaches.debugOverdraw + && mCaches.debugStencilClip == Caches::kStencilShowHighlight + && mRenderState.stencil().isTestEnabled(); + // serialize shader info into ShaderData GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0; SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView, diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index 65be9e19a56a..cc5c403f4c67 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -169,6 +169,10 @@ void JankTracker::switchStorageToAshmem(int ashmemfd) { newData->jankFrameCount += mData->jankFrameCount; newData->totalFrameCount >>= divider; newData->totalFrameCount += mData->totalFrameCount; + if (newData->statStartTime > mData->statStartTime + || newData->statStartTime == 0) { + newData->statStartTime = mData->statStartTime; + } freeData(); mData = newData; @@ -235,6 +239,7 @@ void JankTracker::dumpBuffer(const void* buffer, size_t bufsize, int fd) { } void JankTracker::dumpData(const ProfileData* data, int fd) { + dprintf(fd, "\nStats since: %" PRIu64 "ns", data->statStartTime); dprintf(fd, "\nTotal frames rendered: %u", data->totalFrameCount); dprintf(fd, "\nJanky frames: %u (%.2f%%)", data->jankFrameCount, (float) data->jankFrameCount / (float) data->totalFrameCount * 100.0f); @@ -252,6 +257,7 @@ void JankTracker::reset() { mData->frameCounts.fill(0); mData->totalFrameCount = 0; mData->jankFrameCount = 0; + mData->statStartTime = systemTime(CLOCK_MONOTONIC); } uint32_t JankTracker::findPercentile(const ProfileData* data, int percentile) { diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h index 478300143553..3887e5e65d60 100644 --- a/libs/hwui/JankTracker.h +++ b/libs/hwui/JankTracker.h @@ -44,10 +44,11 @@ enum JankType { struct ProfileData { std::array<uint32_t, NUM_BUCKETS> jankTypeCounts; // See comments on kBucket* constants for what this holds - std::array<uint32_t, 57> frameCounts; + std::array<uint32_t, 55> frameCounts; uint32_t totalFrameCount; uint32_t jankFrameCount; + nsecs_t statStartTime; }; // TODO: Replace DrawProfiler with this diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 02fbd89dbc50..d06534ef9d9c 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -57,8 +57,6 @@ #define EVENT_LOGD(...) #endif -#define USE_GLOPS true - namespace android { namespace uirenderer { @@ -82,8 +80,6 @@ OpenGLRenderer::OpenGLRenderer(RenderState& renderState) // *set* draw modifiers to be 0 memset(&mDrawModifiers, 0, sizeof(mDrawModifiers)); mDrawModifiers.mOverrideLayerAlpha = 1.0f; - - memcpy(mMeshVertices, kUnitQuadVertices, sizeof(kUnitQuadVertices)); } OpenGLRenderer::~OpenGLRenderer() { @@ -846,124 +842,42 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto } void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { - if (USE_GLOPS) { - bool snap = !layer->getForceFilter() - && layer->getWidth() == (uint32_t) rect.getWidth() - && layer->getHeight() == (uint32_t) rect.getHeight(); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO - .setFillTextureLayer(*layer, getLayerAlpha(layer)) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewMapUnitToRectOptionalSnap(snap, rect) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - float alpha = getLayerAlpha(layer); - setupDraw(); - if (layer->getRenderTarget() == GL_TEXTURE_2D) { - setupDrawWithTexture(); - } else { - setupDrawWithExternalTexture(); - } - setupDrawTextureTransform(); - setupDrawColor(alpha, alpha, alpha, alpha); - setupDrawColorFilter(layer->getColorFilter()); - setupDrawBlending(layer); - setupDrawProgram(); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(layer->getColorFilter()); - if (layer->getRenderTarget() == GL_TEXTURE_2D) { - setupDrawTexture(layer->getTextureId()); - } else { - setupDrawExternalTexture(layer->getTextureId()); - } - if (currentTransform()->isPureTranslate() - && !layer->getForceFilter() + bool snap = !layer->getForceFilter() && layer->getWidth() == (uint32_t) rect.getWidth() - && layer->getHeight() == (uint32_t) rect.getHeight()) { - const float x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f); - const float y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f); - - layer->setFilter(GL_NEAREST); - setupDrawModelView(kModelViewMode_TranslateAndScale, false, - x, y, x + rect.getWidth(), y + rect.getHeight(), true); - } else { - layer->setFilter(GL_LINEAR); - setupDrawModelView(kModelViewMode_TranslateAndScale, false, - rect.left, rect.top, rect.right, rect.bottom); - } - setupDrawTextureTransformUniforms(layer->getTexTransform()); - setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount); + && layer->getHeight() == (uint32_t) rect.getHeight(); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO + .setFillTextureLayer(*layer, getLayerAlpha(layer)) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRectOptionalSnap(snap, rect) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { if (layer->isTextureLayer()) { EVENT_LOGD("composeTextureLayerRect"); - resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); drawTextureLayer(layer, rect); - resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); } else { EVENT_LOGD("composeHardwareLayerRect"); - if (USE_GLOPS) { - Blend::ModeOrderSwap modeUsage = swap ? - Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap; - const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform(); - bool snap = !swap - && layer->getWidth() == static_cast<uint32_t>(rect.getWidth()) - && layer->getHeight() == static_cast<uint32_t>(rect.getHeight()); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedUvQuad(nullptr, layer->texCoords) - .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage) - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) - .setModelViewMapUnitToRectOptionalSnap(snap, rect) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - const Rect& texCoords = layer->texCoords; - resetDrawTextureTexCoords(texCoords.left, texCoords.top, - texCoords.right, texCoords.bottom); - - float x = rect.left; - float y = rect.top; - bool simpleTransform = currentTransform()->isPureTranslate() - && layer->getWidth() == (uint32_t) rect.getWidth() - && layer->getHeight() == (uint32_t) rect.getHeight(); - - if (simpleTransform) { - // When we're swapping, the layer is already in screen coordinates - if (!swap) { - x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f); - y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f); - } - - layer->setFilter(GL_NEAREST, true); - } else { - layer->setFilter(GL_LINEAR, true); - } - - SkPaint layerPaint; - layerPaint.setAlpha(getLayerAlpha(layer) * 255); - layerPaint.setXfermodeMode(layer->getMode()); - layerPaint.setColorFilter(layer->getColorFilter()); - - bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f; - drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(), - layer->getTextureId(), &layerPaint, blend, - &mMeshVertices[0].x, &mMeshVertices[0].u, - GL_TRIANGLE_STRIP, kUnitQuadCount, swap, swap || simpleTransform); - - resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + Blend::ModeOrderSwap modeUsage = swap ? + Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap; + const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform(); + bool snap = !swap + && layer->getWidth() == static_cast<uint32_t>(rect.getWidth()) + && layer->getHeight() == static_cast<uint32_t>(rect.getHeight()); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUvQuad(nullptr, layer->texCoords) + .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage) + .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setModelViewMapUnitToRectOptionalSnap(snap, rect) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } } @@ -1079,69 +993,8 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { const float texY = 1.0f / float(layer->getHeight()); const float height = rect.getHeight(); - if (USE_GLOPS) { - TextureVertex quadVertices[count * 4]; - //std::unique_ptr<TextureVertex[]> quadVertices(new TextureVertex[count * 4]); - TextureVertex* mesh = &quadVertices[0]; - for (size_t i = 0; i < count; i++) { - const android::Rect* r = &rects[i]; - - const float u1 = r->left * texX; - const float v1 = (height - r->top) * texY; - const float u2 = r->right * texX; - const float v2 = (height - r->bottom) * texY; - - // TODO: Reject quads outside of the clip - TextureVertex::set(mesh++, r->left, r->top, u1, v1); - TextureVertex::set(mesh++, r->right, r->top, u2, v1); - TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); - TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); - } - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6) - .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewOffsetRectSnap(0, 0, rect) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop)); - return; - } - - const float alpha = getLayerAlpha(layer); - - setupDraw(); - - // We must get (and therefore bind) the region mesh buffer - // after we setup drawing in case we need to mess with the - // stencil buffer in setupDraw() - TextureVertex* mesh = mCaches.getRegionMesh(); - uint32_t numQuads = 0; - - setupDrawWithTexture(); - setupDrawColor(alpha, alpha, alpha, alpha); - setupDrawColorFilter(layer->getColorFilter()); - setupDrawBlending(layer); - setupDrawProgram(); - setupDrawDirtyRegionsDisabled(); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(layer->getColorFilter()); - setupDrawTexture(layer->getTextureId()); - if (currentTransform()->isPureTranslate()) { - const float x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f); - const float y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f); - - layer->setFilter(GL_NEAREST); - setupDrawModelView(kModelViewMode_Translate, false, - x, y, x + rect.getWidth(), y + rect.getHeight(), true); - } else { - layer->setFilter(GL_LINEAR); - setupDrawModelView(kModelViewMode_Translate, false, - rect.left, rect.top, rect.right, rect.bottom); - } - setupDrawMeshIndices(&mesh[0].x, &mesh[0].u); - + TextureVertex quadVertices[count * 4]; + TextureVertex* mesh = &quadVertices[0]; for (size_t i = 0; i < count; i++) { const android::Rect* r = &rects[i]; @@ -1155,21 +1008,17 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { TextureVertex::set(mesh++, r->right, r->top, u2, v1); TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); - - numQuads++; - - if (numQuads >= kMaxNumberOfQuads) { - DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6, - GL_UNSIGNED_SHORT, nullptr)); - numQuads = 0; - mesh = mCaches.getRegionMesh(); - } - } - - if (numQuads > 0) { - DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6, - GL_UNSIGNED_SHORT, nullptr)); } + Rect modelRect = Rect(rect.getWidth(), rect.getHeight()); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6) + .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewOffsetRectSnap(rect.left, rect.top, modelRect) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop)); #if DEBUG_LAYERS_AS_REGIONS drawRegionRectsDebug(layer->region); @@ -1248,21 +1097,6 @@ void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { } } -void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) { - GLsizei elementsCount = quadsCount * 6; - while (elementsCount > 0) { - GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); - - setupDrawIndexedVertices(&mesh[0].x); - glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr); - - elementsCount -= drawCount; - // Though there are 4 vertices in a quad, we use 6 indices per - // quad to draw with GL_TRIANGLES - mesh += (drawCount / 6) * 4; - } -} - void OpenGLRenderer::clearLayerRegions() { const size_t quadCount = mLayers.size(); if (quadCount == 0) return; @@ -1290,34 +1124,19 @@ void OpenGLRenderer::clearLayerRegions() { Vertex::set(vertex++, bounds.right, bounds.bottom); } // We must clear the list of dirty rects before we - // call setupDraw() to prevent stencil setup to do - // the same thing again + // call clearLayerRegions() in renderGlop to prevent + // stencil setup from doing the same thing again mLayers.clear(); - if (USE_GLOPS) { - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshIndexedQuads(&mesh[0], quadCount) - .setFillClear() - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) - .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect())) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop, false); - } else { - SkPaint clearPaint; - clearPaint.setXfermodeMode(SkXfermode::kClear_Mode); - - setupDraw(false); - setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f); - setupDrawBlending(&clearPaint, true); - setupDrawProgram(); - setupDrawPureColorUniforms(); - setupDrawModelView(kModelViewMode_Translate, false, - 0.0f, 0.0f, 0.0f, 0.0f, true); - - issueIndexedQuadDraw(&mesh[0], quadCount); - } + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshIndexedQuads(&mesh[0], quadCount) + .setFillClear() + .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect())) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop, false); if (scissorChanged) mRenderState.scissor().setEnabled(true); } else { @@ -1498,35 +1317,16 @@ void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) { mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom, scissorBox.getWidth(), scissorBox.getHeight()); - if (USE_GLOPS) { - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshIndexedQuads(&rectangleVertices[0], rectangleVertices.size() / 4) - .setFillBlack() - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) - .setModelViewOffsetRect(0, 0, scissorBox) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - const SkPaint* paint = nullptr; - setupDraw(); - setupDrawNoTexture(); - setupDrawColor(0, 0xff * currentSnapshot()->alpha); - setupDrawShader(getShader(paint)); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawBlending(paint); - setupDrawProgram(); - setupDrawDirtyRegionsDisabled(); - setupDrawModelView(kModelViewMode_Translate, false, - 0.0f, 0.0f, 0.0f, 0.0f, true); - setupDrawColorUniforms(getShader(paint)); - setupDrawShaderUniforms(getShader(paint)); - setupDrawColorFilterUniforms(getColorFilter(paint)); - - issueIndexedQuadDraw(&rectangleVertices[0], rectangleVertices.size() / 4); + Glop glop; + Vertex* vertices = &rectangleVertices[0]; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4) + .setFillBlack() + .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setModelViewOffsetRect(0, 0, scissorBox) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::setStencilFromClip() { @@ -1666,355 +1466,6 @@ void OpenGLRenderer::renderGlop(const Glop& glop, bool clearLayer) { } /////////////////////////////////////////////////////////////////////////////// -// Drawing commands -/////////////////////////////////////////////////////////////////////////////// - -void OpenGLRenderer::setupDraw(bool clearLayer) { - // TODO: It would be best if we could do this before quickRejectSetupScissor() - // changes the scissor test state - if (clearLayer) clearLayerRegions(); - // Make sure setScissor & setStencil happen at the beginning of - // this method - if (mState.getDirtyClip()) { - if (mRenderState.scissor().isEnabled()) { - setScissorFromClip(); - } - - setStencilFromClip(); - } - - mDescription.reset(); - - mSetShaderColor = false; - mColorSet = false; - mColor.a = mColor.r = mColor.g = mColor.b = 0.0f; - mTextureUnit = 0; - mTrackDirtyRegions = true; - - // Enable debug highlight when what we're about to draw is tested against - // the stencil buffer and if stencil highlight debugging is on - mDescription.hasDebugHighlight = !mCaches.debugOverdraw - && mCaches.debugStencilClip == Caches::kStencilShowHighlight - && mRenderState.stencil().isTestEnabled(); -} - -void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { - mDescription.hasTexture = true; - mDescription.hasAlpha8Texture = isAlpha8; -} - -void OpenGLRenderer::setupDrawWithTextureAndColor(bool isAlpha8) { - mDescription.hasTexture = true; - mDescription.hasColors = true; - mDescription.hasAlpha8Texture = isAlpha8; -} - -void OpenGLRenderer::setupDrawWithExternalTexture() { - mDescription.hasExternalTexture = true; -} - -void OpenGLRenderer::setupDrawNoTexture() { - mRenderState.meshState().disableTexCoordsVertexArray(); -} - -void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) { - mDescription.hasVertexAlpha = true; - mDescription.useShadowAlphaInterp = useShadowAlphaInterp; -} - -void OpenGLRenderer::setupDrawColor(int color, int alpha) { - mColor.a = alpha / 255.0f; - mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f; - mColor.g = mColor.a * ((color >> 8) & 0xFF) / 255.0f; - mColor.b = mColor.a * ((color ) & 0xFF) / 255.0f; - mColorSet = true; - mSetShaderColor = mDescription.setColorModulate(mColor.a); -} - -void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) { - mColor.a = alpha / 255.0f; - mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f; - mColor.g = mColor.a * ((color >> 8) & 0xFF) / 255.0f; - mColor.b = mColor.a * ((color ) & 0xFF) / 255.0f; - mColorSet = true; - mSetShaderColor = mDescription.setAlpha8ColorModulate(mColor.r, mColor.g, mColor.b, mColor.a); -} - -void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) { - mCaches.fontRenderer->describe(mDescription, paint); -} - -void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) { - mColor.a = a; - mColor.r = r; - mColor.g = g; - mColor.b = b; - mColorSet = true; - mSetShaderColor = mDescription.setColorModulate(a); -} - -void OpenGLRenderer::setupDrawShader(const SkShader* shader) { - if (shader != nullptr) { - SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader); - } -} - -void OpenGLRenderer::setupDrawColorFilter(const SkColorFilter* filter) { - if (filter == nullptr) { - return; - } - - SkXfermode::Mode mode; - if (filter->asColorMode(nullptr, &mode)) { - mDescription.colorOp = ProgramDescription::kColorBlend; - mDescription.colorMode = mode; - } else if (filter->asColorMatrix(nullptr)) { - mDescription.colorOp = ProgramDescription::kColorMatrix; - } -} - -void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) { - if (mColorSet && mode == SkXfermode::kClear_Mode) { - mColor.a = 1.0f; - mColor.r = mColor.g = mColor.b = 0.0f; - mSetShaderColor = mDescription.modulate = true; - } -} - -void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) { - SkXfermode::Mode mode = layer->getMode(); - // When the blending mode is kClear_Mode, we need to use a modulate color - // argb=1,0,0,0 - accountForClear(mode); - // TODO: check shader blending, once we have shader drawing support for layers. - bool blend = layer->isBlend() - || getLayerAlpha(layer) < 1.0f - || (mColorSet && mColor.a < 1.0f) - || PaintUtils::isBlendedColorFilter(layer->getColorFilter()); - chooseBlending(blend, mode, mDescription, swapSrcDst); -} - -void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool swapSrcDst) { - SkXfermode::Mode mode = getXfermodeDirect(paint); - // When the blending mode is kClear_Mode, we need to use a modulate color - // argb=1,0,0,0 - accountForClear(mode); - blend |= (mColorSet && mColor.a < 1.0f) - || (getShader(paint) && !getShader(paint)->isOpaque()) - || PaintUtils::isBlendedColorFilter(getColorFilter(paint)); - chooseBlending(blend, mode, mDescription, swapSrcDst); -} - -void OpenGLRenderer::setupDrawProgram() { - mCaches.setProgram(mDescription); - if (mDescription.hasRoundRectClip) { - // TODO: avoid doing this repeatedly, stashing state pointer in program - const RoundRectClipState* state = writableSnapshot()->roundRectClipState; - const Rect& innerRect = state->innerRect; - glUniform4f(mCaches.program().getUniform("roundRectInnerRectLTRB"), - innerRect.left, innerRect.top, - innerRect.right, innerRect.bottom); - glUniformMatrix4fv(mCaches.program().getUniform("roundRectInvTransform"), - 1, GL_FALSE, &state->matrix.data[0]); - - // add half pixel to round out integer rect space to cover pixel centers - float roundedOutRadius = state->radius + 0.5f; - glUniform1f(mCaches.program().getUniform("roundRectRadius"), - roundedOutRadius); - } -} - -void OpenGLRenderer::setupDrawDirtyRegionsDisabled() { - mTrackDirtyRegions = false; -} - -void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset, - float left, float top, float right, float bottom, bool ignoreTransform) { - mModelViewMatrix.loadTranslate(left, top, 0.0f); - if (mode == kModelViewMode_TranslateAndScale) { - mModelViewMatrix.scale(right - left, bottom - top, 1.0f); - } - - bool dirty = right - left > 0.0f && bottom - top > 0.0f; - const Matrix4& transformMatrix = ignoreTransform ? Matrix4::identity() : *currentTransform(); - - mCaches.program().set(currentSnapshot()->getOrthoMatrix(), - mModelViewMatrix, transformMatrix, offset); - if (dirty && mTrackDirtyRegions) { - if (!ignoreTransform) { - dirtyLayer(left, top, right, bottom, *currentTransform()); - } else { - dirtyLayer(left, top, right, bottom); - } - } -} - -void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) { - if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) { - mCaches.program().setColor(mColor); - } -} - -void OpenGLRenderer::setupDrawPureColorUniforms() { - if (mSetShaderColor) { - mCaches.program().setColor(mColor); - } -} - -void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform) { - if (shader == nullptr) { - return; - } - - if (ignoreTransform) { - // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform() - // because it was built into modelView / the geometry, and the description needs to - // compensate. - mat4 modelViewWithoutTransform; - modelViewWithoutTransform.loadInverse(*currentTransform()); - modelViewWithoutTransform.multiply(mModelViewMatrix); - mModelViewMatrix.load(modelViewWithoutTransform); - } - - SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit, - mCaches.extensions(), *shader); -} - -void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) { - if (nullptr == filter) { - return; - } - - SkColor color; - SkXfermode::Mode mode; - if (filter->asColorMode(&color, &mode)) { - const int alpha = SkColorGetA(color); - const GLfloat a = alpha / 255.0f; - const GLfloat r = a * SkColorGetR(color) / 255.0f; - const GLfloat g = a * SkColorGetG(color) / 255.0f; - const GLfloat b = a * SkColorGetB(color) / 255.0f; - glUniform4f(mCaches.program().getUniform("colorBlend"), r, g, b, a); - return; - } - - SkScalar srcColorMatrix[20]; - if (filter->asColorMatrix(srcColorMatrix)) { - - float colorMatrix[16]; - memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float)); - memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float)); - memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float)); - memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float)); - - // Skia uses the range [0..255] for the addition vector, but we need - // the [0..1] range to apply the vector in GLSL - float colorVector[4]; - colorVector[0] = srcColorMatrix[4] / 255.0f; - colorVector[1] = srcColorMatrix[9] / 255.0f; - colorVector[2] = srcColorMatrix[14] / 255.0f; - colorVector[3] = srcColorMatrix[19] / 255.0f; - - glUniformMatrix4fv(mCaches.program().getUniform("colorMatrix"), 1, - GL_FALSE, colorMatrix); - glUniform4fv(mCaches.program().getUniform("colorMatrixVector"), 1, colorVector); - return; - } - - // it is an error if we ever get here -} - -void OpenGLRenderer::setupDrawTextGammaUniforms() { - mCaches.fontRenderer->setupProgram(mDescription, mCaches.program()); -} - -void OpenGLRenderer::setupDrawSimpleMesh() { - bool force = mRenderState.meshState().bindMeshBuffer(); - mRenderState.meshState().bindPositionVertexPointer(force, nullptr); - mRenderState.meshState().unbindIndicesBuffer(); -} - -void OpenGLRenderer::setupDrawTexture(GLuint texture) { - if (texture) mCaches.textureState().bindTexture(texture); - mTextureUnit++; - mRenderState.meshState().enableTexCoordsVertexArray(); -} - -void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) { - mCaches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, texture); - mTextureUnit++; - mRenderState.meshState().enableTexCoordsVertexArray(); -} - -void OpenGLRenderer::setupDrawTextureTransform() { - mDescription.hasTextureTransform = true; -} - -void OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) { - glUniformMatrix4fv(mCaches.program().getUniform("mainTextureTransform"), 1, - GL_FALSE, &transform.data[0]); -} - -void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices, - const GLvoid* texCoords, GLuint vbo) { - bool force = false; - if (!vertices || vbo) { - force = mRenderState.meshState().bindMeshBuffer(vbo); - } else { - force = mRenderState.meshState().unbindMeshBuffer(); - } - - mRenderState.meshState().bindPositionVertexPointer(force, vertices); - if (mCaches.program().texCoords >= 0) { - mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords); - } - - mRenderState.meshState().unbindIndicesBuffer(); -} - -void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices, - const GLvoid* texCoords, const GLvoid* colors) { - bool force = mRenderState.meshState().unbindMeshBuffer(); - GLsizei stride = sizeof(ColorTextureVertex); - - mRenderState.meshState().bindPositionVertexPointer(force, vertices, stride); - if (mCaches.program().texCoords >= 0) { - mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords, stride); - } - int slot = mCaches.program().getAttrib("colors"); - if (slot >= 0) { - glEnableVertexAttribArray(slot); - glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors); - } - - mRenderState.meshState().unbindIndicesBuffer(); -} - -void OpenGLRenderer::setupDrawMeshIndices(const GLvoid* vertices, - const GLvoid* texCoords, GLuint vbo) { - bool force = false; - // If vbo is != 0 we want to treat the vertices parameter as an offset inside - // a VBO. However, if vertices is set to NULL and vbo == 0 then we want to - // use the default VBO found in RenderState - if (!vertices || vbo) { - force = mRenderState.meshState().bindMeshBuffer(vbo); - } else { - force = mRenderState.meshState().unbindMeshBuffer(); - } - mRenderState.meshState().bindQuadIndicesBuffer(); - - mRenderState.meshState().bindPositionVertexPointer(force, vertices); - if (mCaches.program().texCoords >= 0) { - mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords); - } -} - -void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) { - bool force = mRenderState.meshState().unbindMeshBuffer(); - mRenderState.meshState().bindQuadIndicesBuffer(); - mRenderState.meshState().bindPositionVertexPointer(force, vertices, kVertexStride); -} - -/////////////////////////////////////////////////////////////////////////////// // Drawing /////////////////////////////////////////////////////////////////////////////// @@ -2049,30 +1500,6 @@ void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t } } -void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) { - float x = 0; - float y = 0; - - texture->setWrap(GL_CLAMP_TO_EDGE, true); - - bool ignoreTransform = false; - if (currentTransform()->isPureTranslate()) { - x = floorf(currentTransform()->getTranslateX() + 0.5f); - y = floorf(currentTransform()->getTranslateY() + 0.5f); - ignoreTransform = true; - - texture->setFilter(GL_NEAREST, true); - } else { - texture->setFilter(PaintUtils::getFilter(paint), true); - } - - // No need to check for a UV mapper on the texture object, only ARGB_8888 - // bitmaps get packed in the atlas - drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id, - paint, (GLvoid*) nullptr, (GLvoid*) kMeshTextureOffset, - GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform); -} - /** * Important note: this method is intended to draw batches of bitmaps and * will not set the scissor enable or dirty the current layer, if any. @@ -2086,45 +1513,22 @@ void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entr const AutoTexture autoCleanup(texture); - if (USE_GLOPS) { - // TODO: remove layer dirty in multi-draw callers - // TODO: snap doesn't need to touch transform, only texture filter. - bool snap = pureTranslate; - const float x = floorf(bounds.left + 0.5f); - const float y = floorf(bounds.top + 0.5f); - int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedMesh(vertices, bitmapCount * 6) - .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) - .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight())) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - mCaches.textureState().activateTexture(0); - texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(pureTranslate ? GL_NEAREST : PaintUtils::getFilter(paint), true); - + // TODO: remove layer dirty in multi-draw callers + // TODO: snap doesn't need to touch transform, only texture filter. + bool snap = pureTranslate; const float x = floorf(bounds.left + 0.5f); const float y = floorf(bounds.top + 0.5f); - if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) { - drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(), - texture->id, paint, &vertices[0].x, &vertices[0].u, - GL_TRIANGLES, bitmapCount * 6, true, - kModelViewMode_Translate, false); - } else { - drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(), - texture->id, paint, texture->blend, &vertices[0].x, &vertices[0].u, - GL_TRIANGLES, bitmapCount * 6, false, true, 0, - kModelViewMode_Translate, false); - } - - mDirty = true; + int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) + ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedMesh(vertices, bitmapCount * 6) + .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight())) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { @@ -2137,28 +1541,17 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { if (!texture) return; const AutoTexture autoCleanup(texture); - if (USE_GLOPS) { - int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedUnitQuad(texture->uvMapper) - .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) { - drawAlphaBitmap(texture, paint); - } else { - drawTextureRect(texture, paint); - } - - mDirty = true; + int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) + ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUnitQuad(texture->uvMapper) + .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight, @@ -2235,56 +1628,19 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m } const AutoTexture autoCleanup(texture); - if (USE_GLOPS) { - /* - * TODO: handle alpha_8 textures correctly by applying paint color, but *not* - * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh. - */ - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshColoredTexturedMesh(mesh.get(), elementCount) - .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - mCaches.textureState().activateTexture(0); - texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(PaintUtils::getFilter(paint), true); - - int alpha; - SkXfermode::Mode mode; - getAlphaAndMode(paint, &alpha, &mode); - - - dirtyLayer(left, top, right, bottom, *currentTransform()); - - float a = alpha / 255.0f; - setupDraw(); - setupDrawWithTextureAndColor(); - setupDrawColor(a, a, a, a); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawBlending(paint, true); - setupDrawProgram(); - setupDrawDirtyRegionsDisabled(); - setupDrawModelView(kModelViewMode_Translate, false, 0, 0, 0, 0); - setupDrawTexture(texture->id); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawMesh(&mesh[0].x, &mesh[0].u, &mesh[0].r); - - glDrawArrays(GL_TRIANGLES, 0, elementCount); - - int slot = mCaches.program().getAttrib("colors"); - if (slot >= 0) { - glDisableVertexAttribArray(slot); - } - - mDirty = true; + /* + * TODO: handle alpha_8 textures correctly by applying paint color, but *not* + * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh. + */ + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshColoredTexturedMesh(mesh.get(), elementCount) + .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, const SkPaint* paint) { @@ -2296,80 +1652,22 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, cons if (!texture) return; const AutoTexture autoCleanup(texture); - if (USE_GLOPS) { - Rect uv(fmax(0.0f, src.left / texture->width), - fmax(0.0f, src.top / texture->height), - fmin(1.0f, src.right / texture->width), - fmin(1.0f, src.bottom / texture->height)); + Rect uv(fmax(0.0f, src.left / texture->width), + fmax(0.0f, src.top / texture->height), + fmin(1.0f, src.right / texture->width), + fmin(1.0f, src.bottom / texture->height)); - int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedUvQuad(texture->uvMapper, uv) - .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewMapUnitToRectSnap(dst) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - mCaches.textureState().activateTexture(0); - - const float width = texture->width; - const float height = texture->height; - - float u1 = fmax(0.0f, src.left / width); - float v1 = fmax(0.0f, src.top / height); - float u2 = fmin(1.0f, src.right / width); - float v2 = fmin(1.0f, src.bottom / height); - - getMapper(texture).map(u1, v1, u2, v2); - - mRenderState.meshState().unbindMeshBuffer(); - resetDrawTextureTexCoords(u1, v1, u2, v2); - - texture->setWrap(GL_CLAMP_TO_EDGE, true); - - float scaleX = (dst.right - dst.left) / (src.right - src.left); - float scaleY = (dst.bottom - dst.top) / (src.bottom - src.top); - - bool scaled = scaleX != 1.0f || scaleY != 1.0f; - bool ignoreTransform = false; - - if (CC_LIKELY(currentTransform()->isPureTranslate())) { - float x = floorf(dst.left + currentTransform()->getTranslateX() + 0.5f); - float y = floorf(dst.top + currentTransform()->getTranslateY() + 0.5f); - - dst.right = x + (dst.right - dst.left); - dst.bottom = y + (dst.bottom - dst.top); - - dst.left = x; - dst.top = y; - - texture->setFilter(scaled ? PaintUtils::getFilter(paint) : GL_NEAREST, true); - ignoreTransform = true; - } else { - texture->setFilter(PaintUtils::getFilter(paint), true); - } - - if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) { - drawAlpha8TextureMesh(dst.left, dst.top, dst.right, dst.bottom, - texture->id, paint, - &mMeshVertices[0].x, &mMeshVertices[0].u, - GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform); - } else { - drawTextureMesh(dst.left, dst.top, dst.right, dst.bottom, - texture->id, paint, texture->blend, - &mMeshVertices[0].x, &mMeshVertices[0].u, - GL_TRIANGLE_STRIP, kUnitQuadCount, false, ignoreTransform); - } - - resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); - - mDirty = true; + int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) + ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUvQuad(texture->uvMapper, uv) + .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRectSnap(dst) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh, @@ -2382,66 +1680,20 @@ void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh, Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap); if (!texture) return; - if (USE_GLOPS) { - // 9 patches are built for stretching - always filter - int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter); - if (bitmap->colorType() == kAlpha_8_SkColorType) { - textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture; - } - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshPatchQuads(*mesh) - .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - mCaches.textureState().activateTexture(0); - const AutoTexture autoCleanup(texture); - - texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(GL_LINEAR, true); - - const bool pureTranslate = currentTransform()->isPureTranslate(); - // Mark the current layer dirty where we are going to draw the patch - if (hasLayer() && mesh->hasEmptyQuads) { - const float offsetX = left + currentTransform()->getTranslateX(); - const float offsetY = top + currentTransform()->getTranslateY(); - const size_t count = mesh->quads.size(); - for (size_t i = 0; i < count; i++) { - const Rect& bounds = mesh->quads.itemAt(i); - if (CC_LIKELY(pureTranslate)) { - const float x = floorf(bounds.left + offsetX + 0.5f); - const float y = floorf(bounds.top + offsetY + 0.5f); - dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight()); - } else { - dirtyLayer(left + bounds.left, top + bounds.top, - left + bounds.right, top + bounds.bottom, *currentTransform()); - } - } + // 9 patches are built for stretching - always filter + int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter); + if (bitmap->colorType() == kAlpha_8_SkColorType) { + textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture; } - - bool ignoreTransform = false; - if (CC_LIKELY(pureTranslate)) { - const float x = floorf(left + currentTransform()->getTranslateX() + 0.5f); - const float y = floorf(top + currentTransform()->getTranslateY() + 0.5f); - - right = x + right - left; - bottom = y + bottom - top; - left = x; - top = y; - ignoreTransform = true; - } - drawIndexedTextureMesh(left, top, right, bottom, texture->id, paint, - texture->blend, (GLvoid*) mesh->positionOffset, (GLvoid*) mesh->textureOffset, - GL_TRIANGLES, mesh->indexCount, false, ignoreTransform, - mCaches.patchCache.getMeshBuffer(), kModelViewMode_Translate, !mesh->hasEmptyQuads); - - mDirty = true; + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshPatchQuads(*mesh) + .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } /** @@ -2456,33 +1708,21 @@ void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entr if (!texture) return; const AutoTexture autoCleanup(texture); - if (USE_GLOPS) { - // TODO: get correct bounds from caller - // 9 patches are built for stretching - always filter - int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter); - if (bitmap->colorType() == kAlpha_8_SkColorType) { - textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture; - } - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedIndexedQuads(vertices, elementCount) - .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) - .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; + // TODO: get correct bounds from caller + // 9 patches are built for stretching - always filter + int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter); + if (bitmap->colorType() == kAlpha_8_SkColorType) { + textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture; } - - texture->setWrap(GL_CLAMP_TO_EDGE, true); - texture->setFilter(GL_LINEAR, true); - - drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, paint, - texture->blend, &vertices[0].x, &vertices[0].u, - GL_TRIANGLES, elementCount, false, true, 0, kModelViewMode_Translate, false); - - mDirty = true; + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedIndexedQuads(vertices, elementCount) + .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, @@ -2493,72 +1733,17 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, return; } - if (USE_GLOPS) { - bool fudgeOffset = displayFlags & kVertexBuffer_Offset; - bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp; - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshVertexBuffer(vertexBuffer, shadowInterp) - .setFillPaint(*paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset) - .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - const VertexBuffer::MeshFeatureFlags meshFeatureFlags = vertexBuffer.getMeshFeatureFlags(); - Rect bounds(vertexBuffer.getBounds()); - bounds.translate(translateX, translateY); - dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform()); - - int color = paint->getColor(); - bool isAA = meshFeatureFlags & VertexBuffer::kAlpha; - - setupDraw(); - setupDrawNoTexture(); - if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp)); - setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawShader(getShader(paint)); - setupDrawBlending(paint, isAA); - setupDrawProgram(); - setupDrawModelView(kModelViewMode_Translate, (displayFlags & kVertexBuffer_Offset), - translateX, translateY, 0, 0); - setupDrawColorUniforms(getShader(paint)); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawShaderUniforms(getShader(paint)); - - const void* vertices = vertexBuffer.getBuffer(); - mRenderState.meshState().unbindMeshBuffer(); - mRenderState.meshState().bindPositionVertexPointer(true, vertices, - isAA ? kAlphaVertexStride : kVertexStride); - mRenderState.meshState().resetTexCoordsVertexPointer(); - - int alphaSlot = -1; - if (isAA) { - void* alphaCoords = ((GLbyte*) vertices) + kVertexAlphaOffset; - alphaSlot = mCaches.program().getAttrib("vtxAlpha"); - // TODO: avoid enable/disable in back to back uses of the alpha attribute - glEnableVertexAttribArray(alphaSlot); - glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords); - } - - if (meshFeatureFlags & VertexBuffer::kIndices) { - mRenderState.meshState().unbindIndicesBuffer(); - glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(), - GL_UNSIGNED_SHORT, vertexBuffer.getIndices()); - } else { - mRenderState.meshState().unbindIndicesBuffer(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount()); - } - - if (isAA) { - glDisableVertexAttribArray(alphaSlot); - } - - mDirty = true; + bool fudgeOffset = displayFlags & kVertexBuffer_Offset; + bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp; + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshVertexBuffer(vertexBuffer, shadowInterp) + .setFillPaint(*paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset) + .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } /** @@ -2813,40 +1998,15 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, const float sx = x - texture->left + textShadow.dx; const float sy = y - texture->top + textShadow.dy; - if (USE_GLOPS) { - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedUnitQuad(nullptr) - .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * currentSnapshot()->alpha; - if (getShader(paint)) { - textShadow.color = SK_ColorWHITE; - } - - setupDraw(); - setupDrawWithTexture(true); - setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawShader(getShader(paint)); - setupDrawBlending(paint, true); - setupDrawProgram(); - setupDrawModelView(kModelViewMode_TranslateAndScale, false, - sx, sy, sx + texture->width, sy + texture->height); - setupDrawTexture(texture->id); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawShaderUniforms(getShader(paint)); - setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUnitQuad(nullptr) + .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } bool OpenGLRenderer::canSkipText(const SkPaint* paint) const { @@ -2898,7 +2058,7 @@ void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, const Rect& clip(pureTranslate ? writableSnapshot()->getClipRect() : writableSnapshot()->getLocalClip()); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); - TextSetupFunctor functor(this, x, y, pureTranslate, alpha, mode, paint); + TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint); if (fontRenderer.renderPosText(paint, &clip, text, 0, bytesCount, count, x, y, positions, hasLayer() ? &bounds : nullptr, &functor)) { dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform()); @@ -3050,7 +2210,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); bool status; - TextSetupFunctor functor(this, x, y, pureTranslate, alpha, mode, paint); + TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint); // don't call issuedrawcommand, do it at end of batch bool forceFinish = (drawOpMode != DrawOpMode::kDefer); @@ -3092,7 +2252,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - TextSetupFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint); + TextDrawFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint); const Rect* clip = &writableSnapshot()->getLocalClip(); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); @@ -3159,56 +2319,15 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, composeLayerRect(layer, layer->regionRect)); } else if (layer->mesh) { - if (USE_GLOPS) { - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount) - .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight())) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop)); - } else { - const float a = getLayerAlpha(layer); - setupDraw(); - setupDrawWithTexture(); - setupDrawColor(a, a, a, a); - setupDrawColorFilter(layer->getColorFilter()); - setupDrawBlending(layer); - setupDrawProgram(); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(layer->getColorFilter()); - setupDrawTexture(layer->getTextureId()); - if (CC_LIKELY(currentTransform()->isPureTranslate())) { - int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f); - int ty = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f); - - layer->setFilter(GL_NEAREST); - setupDrawModelView(kModelViewMode_Translate, false, tx, ty, - tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true); - } else { - layer->setFilter(GL_LINEAR); - setupDrawModelView(kModelViewMode_Translate, false, x, y, - x + layer->layer.getWidth(), y + layer->layer.getHeight()); - } - - TextureVertex* mesh = &layer->mesh[0]; - GLsizei elementsCount = layer->meshElementCount; - - while (elementsCount > 0) { - GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); - - setupDrawMeshIndices(&mesh[0].x, &mesh[0].u); - DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, - glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr)); - - elementsCount -= drawCount; - // Though there are 4 vertices in a quad, we use 6 indices per - // quad to draw with GL_TRIANGLES - mesh += (drawCount / 6) * 4; - } - } + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount) + .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight())) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop)); #if DEBUG_LAYERS_AS_REGIONS drawRegionRectsDebug(layer->region); #endif @@ -3258,40 +2377,15 @@ void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y, return; } - if (USE_GLOPS) { - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshTexturedUnitQuad(nullptr) - .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) - .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - - int alpha; - SkXfermode::Mode mode; - getAlphaAndMode(paint, &alpha, &mode); - - setupDraw(); - setupDrawWithTexture(true); - setupDrawAlpha8Color(paint->getColor(), alpha); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawShader(getShader(paint)); - setupDrawBlending(paint, true); - setupDrawProgram(); - setupDrawModelView(kModelViewMode_TranslateAndScale, false, - x, y, x + texture->width, y + texture->height); - setupDrawTexture(texture->id); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawShaderUniforms(getShader(paint)); - setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUnitQuad(nullptr) + .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } // Same values used by Skia @@ -3419,249 +2513,30 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint return; } - if (USE_GLOPS) { - const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshIndexedQuads(&mesh[0], count / 4) - .setFillPaint(*paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) - .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - int color = paint->getColor(); - // If a shader is set, preserve only the alpha - if (getShader(paint)) { - color |= 0x00ffffff; - } - - setupDraw(); - setupDrawNoTexture(); - setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha); - setupDrawShader(getShader(paint)); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawBlending(paint); - setupDrawProgram(); - setupDrawDirtyRegionsDisabled(); - setupDrawModelView(kModelViewMode_Translate, false, - 0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform); - setupDrawColorUniforms(getShader(paint)); - setupDrawShaderUniforms(getShader(paint)); - setupDrawColorFilterUniforms(getColorFilter(paint)); - - if (dirty && hasLayer()) { - dirtyLayer(left, top, right, bottom, *currentTransform()); - } - - issueIndexedQuadDraw(&mesh[0], count / 4); - - mDirty = true; + const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshIndexedQuads(&mesh[0], count / 4) + .setFillPaint(*paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, const SkPaint* paint, bool ignoreTransform) { - - if (USE_GLOPS) { - const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); - Glop glop; - GlopBuilder(mRenderState, mCaches, &glop) - .setMeshUnitQuad() - .setFillPaint(*paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) - .setModelViewMapUnitToRect(Rect(left, top, right, bottom)) - .setRoundRectClipState(currentSnapshot()->roundRectClipState) - .build(); - renderGlop(glop); - return; - } - - int color = paint->getColor(); - // If a shader is set, preserve only the alpha - if (getShader(paint)) { - color |= 0x00ffffff; - } - - setupDraw(); - setupDrawNoTexture(); - setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha); - setupDrawShader(getShader(paint)); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawBlending(paint); - setupDrawProgram(); - setupDrawModelView(kModelViewMode_TranslateAndScale, false, - left, top, right, bottom, ignoreTransform); - setupDrawColorUniforms(getShader(paint)); - setupDrawShaderUniforms(getShader(paint), ignoreTransform); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawSimpleMesh(); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount); -} - -void OpenGLRenderer::drawTextureRect(Texture* texture, const SkPaint* paint) { - texture->setWrap(GL_CLAMP_TO_EDGE, true); - - GLvoid* vertices = (GLvoid*) nullptr; - GLvoid* texCoords = (GLvoid*) kMeshTextureOffset; - - if (texture->uvMapper) { - vertices = &mMeshVertices[0].x; - texCoords = &mMeshVertices[0].u; - - Rect uvs(0.0f, 0.0f, 1.0f, 1.0f); - texture->uvMapper->map(uvs); - - resetDrawTextureTexCoords(uvs.left, uvs.top, uvs.right, uvs.bottom); - } - - if (CC_LIKELY(currentTransform()->isPureTranslate())) { - const float x = floorf(currentTransform()->getTranslateX() + 0.5f); - const float y = floorf(currentTransform()->getTranslateY() + 0.5f); - - texture->setFilter(GL_NEAREST, true); - drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id, - paint, texture->blend, vertices, texCoords, - GL_TRIANGLE_STRIP, kUnitQuadCount, false, true); - } else { - texture->setFilter(PaintUtils::getFilter(paint), true); - drawTextureMesh(0, 0, texture->width, texture->height, texture->id, paint, - texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount); - } - - if (texture->uvMapper) { - resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); - } -} - -void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom, - GLuint texture, const SkPaint* paint, bool blend, - GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, - bool swapSrcDst, bool ignoreTransform, GLuint vbo, - ModelViewMode modelViewMode, bool dirty) { - - int a; - SkXfermode::Mode mode; - getAlphaAndMode(paint, &a, &mode); - const float alpha = a / 255.0f; - - setupDraw(); - setupDrawWithTexture(); - setupDrawColor(alpha, alpha, alpha, alpha); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawBlending(paint, blend, swapSrcDst); - setupDrawProgram(); - if (!dirty) setupDrawDirtyRegionsDisabled(); - setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform); - setupDrawTexture(texture); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawMesh(vertices, texCoords, vbo); - - glDrawArrays(drawMode, 0, elementsCount); -} - -void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom, - GLuint texture, const SkPaint* paint, bool blend, - GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, - bool swapSrcDst, bool ignoreTransform, GLuint vbo, - ModelViewMode modelViewMode, bool dirty) { - - int a; - SkXfermode::Mode mode; - getAlphaAndMode(paint, &a, &mode); - const float alpha = a / 255.0f; - - setupDraw(); - setupDrawWithTexture(); - setupDrawColor(alpha, alpha, alpha, alpha); - setupDrawColorFilter(getColorFilter(paint)); - setupDrawBlending(paint, blend, swapSrcDst); - setupDrawProgram(); - if (!dirty) setupDrawDirtyRegionsDisabled(); - setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform); - setupDrawTexture(texture); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawMeshIndices(vertices, texCoords, vbo); - - glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, nullptr); -} - -void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom, - GLuint texture, const SkPaint* paint, - GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, - bool ignoreTransform, ModelViewMode modelViewMode, bool dirty) { - - int color = paint != nullptr ? paint->getColor() : 0; - int alpha; - SkXfermode::Mode mode; - getAlphaAndMode(paint, &alpha, &mode); - - setupDraw(); - setupDrawWithTexture(true); - if (paint != nullptr) { - setupDrawAlpha8Color(color, alpha); - } - setupDrawColorFilter(getColorFilter(paint)); - setupDrawShader(getShader(paint)); - setupDrawBlending(paint, true); - setupDrawProgram(); - if (!dirty) setupDrawDirtyRegionsDisabled(); - setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform); - setupDrawTexture(texture); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(getColorFilter(paint)); - setupDrawShaderUniforms(getShader(paint), ignoreTransform); - setupDrawMesh(vertices, texCoords); - - glDrawArrays(drawMode, 0, elementsCount); -} - -void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, - ProgramDescription& description, bool swapSrcDst) { - - if (currentSnapshot()->roundRectClipState != nullptr /*&& !mSkipOutlineClip*/) { - blend = true; - mDescription.hasRoundRectClip = true; - } - mSkipOutlineClip = true; - - blend = blend || mode != SkXfermode::kSrcOver_Mode; - - if (blend) { - // These blend modes are not supported by OpenGL directly and have - // to be implemented using shaders. Since the shader will perform - // the blending, turn blending off here - // If the blend mode cannot be implemented using shaders, fall - // back to the default SrcOver blend mode instead - if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) { - if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) { - description.framebufferMode = mode; - description.swapSrcDst = swapSrcDst; - - mRenderState.blend().disable(); - return; - } else { - mode = SkXfermode::kSrcOver_Mode; - } - } - mRenderState.blend().enable(mode, - swapSrcDst ? Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap); - } else { - mRenderState.blend().disable(); - } -} - -void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { - TextureVertex* v = &mMeshVertices[0]; - TextureVertex::setUV(v++, u1, v1); - TextureVertex::setUV(v++, u2, v1); - TextureVertex::setUV(v++, u1, v2); - TextureVertex::setUV(v++, u2, v2); + const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshUnitQuad() + .setFillPaint(*paint, currentSnapshot()->alpha) + .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setModelViewMapUnitToRect(Rect(left, top, right, bottom)) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); } void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index f4acad068903..5f8960a71282 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -65,7 +65,7 @@ class DeferredDisplayState; struct Glop; class RenderState; class RenderNode; -class TextSetupFunctor; +class TextDrawFunctor; class VertexBuffer; struct DrawModifiers { @@ -727,15 +727,6 @@ private: void drawShape(float left, float top, PathTexture* texture, const SkPaint* paint); /** - * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey - * different compositing rules. - * - * @param texture The texture to draw with - * @param paint The paint to render with - */ - void drawAlphaBitmap(Texture* texture, const SkPaint* paint); - - /** * Renders a strip of polygons with the specified paint, used for tessellated geometry. * * @param vertexBuffer The VertexBuffer to be drawn @@ -762,60 +753,6 @@ private: void drawConvexPath(const SkPath& path, const SkPaint* paint); /** - * Draws a textured rectangle with the specified texture. - * - * @param texture The texture to use - * @param paint The paint containing the alpha, blending mode, etc. - */ - void drawTextureRect(Texture* texture, const SkPaint* paint); - - /** - * Draws a textured mesh with the specified texture. If the indices are omitted, - * the mesh is drawn as a simple quad. The mesh pointers become offsets when a - * VBO is bound. - * - * @param left The left coordinate of the rectangle - * @param top The top coordinate of the rectangle - * @param right The right coordinate of the rectangle - * @param bottom The bottom coordinate of the rectangle - * @param texture The texture name to map onto the rectangle - * @param paint The paint containing the alpha, blending mode, colorFilter, etc. - * @param blend True if the texture contains an alpha channel - * @param vertices The vertices that define the mesh - * @param texCoords The texture coordinates of each vertex - * @param elementsCount The number of elements in the mesh, required by indices - * @param swapSrcDst Whether or not the src and dst blending operations should be swapped - * @param ignoreTransform True if the current transform should be ignored - * @param vbo The VBO used to draw the mesh - * @param modelViewMode Defines whether the model view matrix should be scaled - * @param dirty True if calling this method should dirty the current layer - */ - void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture, - const SkPaint* paint, bool blend, - GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, - bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0, - ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true); - - void drawIndexedTextureMesh(float left, float top, float right, float bottom, GLuint texture, - const SkPaint* paint, bool blend, - GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, - bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0, - ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true); - - void drawAlpha8TextureMesh(float left, float top, float right, float bottom, - GLuint texture, const SkPaint* paint, - GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, - bool ignoreTransform, ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, - bool dirty = true); - - /** - * Draws the specified list of vertices as quads using indexed GL_TRIANGLES. - * If the number of vertices to draw exceeds the number of indices we have - * pre-allocated, this method will generate several glDrawElements() calls. - */ - void issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount); - - /** * Draws text underline and strike-through if needed. * * @param text The text to decor @@ -873,78 +810,6 @@ private: */ bool canSkipText(const SkPaint* paint) const; - /** - * Enable or disable blending as necessary. This function sets the appropriate - * blend function based on the specified xfermode. - */ - inline void chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description, - bool swapSrcDst = false); - - /** - * Invoked before any drawing operation. This sets required state. - */ - void setupDraw(bool clear = true); - - /** - * Various methods to setup OpenGL rendering. - */ - void setupDrawWithTexture(bool isAlpha8 = false); - void setupDrawWithTextureAndColor(bool isAlpha8 = false); - void setupDrawWithExternalTexture(); - void setupDrawNoTexture(); - void setupDrawVertexAlpha(bool useShadowAlphaInterp); - void setupDrawColor(int color, int alpha); - void setupDrawColor(float r, float g, float b, float a); - void setupDrawAlpha8Color(int color, int alpha); - void setupDrawTextGamma(const SkPaint* paint); - void setupDrawShader(const SkShader* shader); - void setupDrawColorFilter(const SkColorFilter* filter); - void setupDrawBlending(const Layer* layer, bool swapSrcDst = false); - void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false); - void setupDrawProgram(); - void setupDrawDirtyRegionsDisabled(); - - /** - * Setup the current program matrices based upon the nature of the geometry. - * - * @param mode If kModelViewMode_Translate, the geometry must be translated by the left and top - * parameters. If kModelViewMode_TranslateAndScale, the geometry that exists in the (0,0, 1,1) - * space must be scaled up and translated to fill the quad provided in (l,t,r,b). These - * transformations are stored in the modelView matrix and uploaded to the shader. - * - * @param offset Set to true if the the matrix should be fudged (translated) slightly to - * disambiguate geometry pixel positioning. See Vertex::GeometryFudgeFactor(). - * - * @param ignoreTransform Set to true if l,t,r,b coordinates already in layer space, - * currentTransform() will be ignored. (e.g. when drawing clip in layer coordinates to stencil, - * or when simple translation has been extracted) - */ - void setupDrawModelView(ModelViewMode mode, bool offset, - float left, float top, float right, float bottom, bool ignoreTransform = false); - void setupDrawColorUniforms(bool hasShader); - void setupDrawPureColorUniforms(); - - /** - * Setup uniforms for the current shader. - * - * @param shader SkShader on the current paint. - * - * @param ignoreTransform Set to true to ignore the transform in shader. - */ - void setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform = false); - void setupDrawColorFilterUniforms(const SkColorFilter* paint); - void setupDrawSimpleMesh(); - void setupDrawTexture(GLuint texture); - void setupDrawExternalTexture(GLuint texture); - void setupDrawTextureTransform(); - void setupDrawTextureTransformUniforms(mat4& transform); - void setupDrawTextGammaUniforms(); - void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords = nullptr, GLuint vbo = 0); - void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords, const GLvoid* colors); - void setupDrawMeshIndices(const GLvoid* vertices, const GLvoid* texCoords, GLuint vbo = 0); - void setupDrawIndexedVertices(GLvoid* vertices); - void accountForClear(SkXfermode::Mode mode); - bool updateLayer(Layer* layer, bool inFrame); void updateLayers(); void flushLayers(); @@ -993,22 +858,6 @@ private: inline Snapshot* writableSnapshot() { return mState.writableSnapshot(); } inline const Snapshot* currentSnapshot() const { return mState.currentSnapshot(); } - /** - * Model-view matrix used to position/size objects - * - * Stores operation-local modifications to the draw matrix that aren't incorporated into the - * currentTransform(). - * - * If generated with kModelViewMode_Translate, mModelViewMatrix will reflect an x/y offset, - * e.g. the offset in drawLayer(). If generated with kModelViewMode_TranslateAndScale, - * mModelViewMatrix will reflect a translation and scale, e.g. the translation and scale - * required to make VBO 0 (a rect of (0,0,1,1)) scaled to match the x,y offset, and width/height - * of a bitmap. - * - * Used as input to SkiaShader transformation. - */ - mat4 mModelViewMatrix; - // State used to define the clipping region Rect mTilingClip; // Is the target render surface opaque @@ -1016,9 +865,6 @@ private: // Is a frame currently being rendered bool mFrameStarted; - // Used to draw textured quads - TextureVertex mMeshVertices[4]; - // Default UV mapper const UvMapper mUvMapper; @@ -1031,21 +877,6 @@ private: // List of layers to update at the beginning of a frame Vector< sp<Layer> > mLayerUpdates; - // The following fields are used to setup drawing - // Used to describe the shaders to generate - ProgramDescription mDescription; - // Color description - bool mColorSet; - FloatColor mColor; - // Indicates that the shader should get a color - bool mSetShaderColor; - // Current texture unit - GLuint mTextureUnit; - // Track dirty regions, true by default - bool mTrackDirtyRegions; - // Indicate whether we are drawing an opaque frame - bool mOpaqueFrame; - // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in // Properties.h bool mScissorOptimizationDisabled; @@ -1070,7 +901,7 @@ private: std::vector<std::unique_ptr<SkPath>> mTempPaths; friend class Layer; - friend class TextSetupFunctor; + friend class TextDrawFunctor; friend class DrawBitmapOp; friend class DrawPatchOp; diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index e9b22e20bc18..41adda15f367 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -240,8 +240,9 @@ const char* gFS_Main_ModulateColor = const char* gFS_Main_ApplyVertexAlphaLinearInterp = " fragColor *= alpha;\n"; const char* gFS_Main_ApplyVertexAlphaShadowInterp = - " fragColor *= (1.0 - cos(alpha)) / 2.0;\n"; - + // Use a gaussian function for the shadow fall off. Note that alpha here + // is actually (1.0 - alpha) for saving computation. + " fragColor *= exp(- alpha * alpha * 4.0) - 0.018;\n"; const char* gFS_Main_FetchTexture[2] = { // Don't modulate " fragColor = texture2D(baseSampler, outTexCoords);\n", diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp index 0380c51cbbc8..d0812c96afd7 100644 --- a/libs/hwui/RenderBufferCache.cpp +++ b/libs/hwui/RenderBufferCache.cpp @@ -158,6 +158,11 @@ bool RenderBufferCache::put(RenderBuffer* buffer) { buffer->getWidth(), buffer->getHeight()); return true; + } else { + RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d", + RenderBuffer::formatName(buffer->getFormat()), + buffer->getWidth(), buffer->getHeight(), size, mMaxSize); + delete buffer; } return false; } diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 71088b7129a4..8b1175707c81 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -709,7 +709,7 @@ void SkiaCanvas::drawPosText(const uint16_t* text, const float* positions, int c void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) { - mCanvas->drawTextOnPathHV(glyphs, count, path, hOffset, vOffset, paint); + mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint); } } // namespace android diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index ec1bb909e6f9..8a6c8c50d30d 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -289,6 +289,7 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S // but even more conservative bounds if this is too slow. SkRect bounds; glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds); + bounds.offset(x, y); SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats); mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y, diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 2fcf7f391470..ecf8b6ba8219 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -47,15 +47,6 @@ static inline bool isPowerOfTwo(unsigned int n) { return !(n & (n - 1)); } -static inline void bindUniformColor(int slot, uint32_t color) { - const float a = ((color >> 24) & 0xff) / 255.0f; - glUniform4f(slot, - a * ((color >> 16) & 0xff) / 255.0f, - a * ((color >> 8) & 0xff) / 255.0f, - a * ((color ) & 0xff) / 255.0f, - a); -} - static inline void bindUniformColor(int slot, FloatColor color) { glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color)); } @@ -83,229 +74,11 @@ static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatr screenSpace.multiply(modelViewMatrix); } -// Returns true if one is a bitmap and the other is a gradient -static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) { - return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType) - || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType); -} - -SkiaShaderType SkiaShader::getType(const SkShader& shader) { - // First check for a gradient shader. - switch (shader.asAGradient(nullptr)) { - case SkShader::kNone_GradientType: - // Not a gradient shader. Fall through to check for other types. - break; - case SkShader::kLinear_GradientType: - case SkShader::kRadial_GradientType: - case SkShader::kSweep_GradientType: - return kGradient_SkiaShaderType; - default: - // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip. - return kNone_SkiaShaderType; - } - - // The shader is not a gradient. Check for a bitmap shader. - if (shader.asABitmap(nullptr, nullptr, nullptr) == SkShader::kDefault_BitmapType) { - return kBitmap_SkiaShaderType; - } - - // Check for a ComposeShader. - SkShader::ComposeRec rec; - if (shader.asACompose(&rec)) { - const SkiaShaderType shaderAType = getType(*rec.fShaderA); - const SkiaShaderType shaderBType = getType(*rec.fShaderB); - - // Compose is only supported if one is a bitmap and the other is a - // gradient. Otherwise, return None to skip. - if (!bitmapAndGradient(shaderAType, shaderBType)) { - return kNone_SkiaShaderType; - } - return kCompose_SkiaShaderType; - } - - if (shader.asACustomShader(nullptr)) { - return kLayer_SkiaShaderType; - } - - return kNone_SkiaShaderType; -} - -typedef void (*describeProc)(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader); - -describeProc gDescribeProc[] = { - InvalidSkiaShader::describe, - SkiaBitmapShader::describe, - SkiaGradientShader::describe, - SkiaComposeShader::describe, - SkiaLayerShader::describe, -}; - -typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); - -setupProgramProc gSetupProgramProc[] = { - InvalidSkiaShader::setupProgram, - SkiaBitmapShader::setupProgram, - SkiaGradientShader::setupProgram, - SkiaComposeShader::setupProgram, - SkiaLayerShader::setupProgram, -}; - -void SkiaShader::describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader) { - gDescribeProc[getType(shader)](caches, description, extensions, shader); -} - -void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { - - gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader); -} - -/////////////////////////////////////////////////////////////////////////////// -// Layer shader -/////////////////////////////////////////////////////////////////////////////// - -void SkiaLayerShader::describe(Caches*, ProgramDescription& description, - const Extensions&, const SkShader& shader) { - description.hasBitmap = true; -} - -void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions&, const SkShader& shader) { - Layer* layer; - if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) { - LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!"); - } - - GLuint textureSlot = (*textureUnit)++; - caches->textureState().activateTexture(textureSlot); - - const float width = layer->getWidth(); - const float height = layer->getHeight(); - - mat4 textureTransform; - computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(), - modelViewMatrix); - - - // Uniforms - layer->bindTexture(); - layer->setWrap(GL_CLAMP_TO_EDGE); - layer->setFilter(GL_LINEAR); - - Program& program = caches->program(); - glUniform1i(program.getUniform("bitmapSampler"), textureSlot); - glUniformMatrix4fv(program.getUniform("textureTransform"), 1, - GL_FALSE, &textureTransform.data[0]); - glUniform2f(program.getUniform("textureDimension"), 1.0f / width, 1.0f / height); -} - /////////////////////////////////////////////////////////////////////////////// -// Bitmap shader +// gradient shader matrix helpers /////////////////////////////////////////////////////////////////////////////// -struct BitmapShaderInfo { - float width; - float height; - GLenum wrapS; - GLenum wrapT; - Texture* texture; -}; - -static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description, - BitmapShaderInfo* shaderInfo, - const Extensions& extensions, - const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) { - Texture* texture = caches->textureCache.get(&bitmap); - if (!texture) return false; - - const float width = texture->width; - const float height = texture->height; - GLenum wrapS, wrapT; - - if (description) { - description->hasBitmap = true; - } - // The driver does not support non-power of two mirrored/repeated - // textures, so do it ourselves - if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) && - (tileModes[0] != SkShader::kClamp_TileMode || - tileModes[1] != SkShader::kClamp_TileMode)) { - if (description) { - description->isBitmapNpot = true; - description->bitmapWrapS = gTileModes[tileModes[0]]; - description->bitmapWrapT = gTileModes[tileModes[1]]; - } - wrapS = GL_CLAMP_TO_EDGE; - wrapT = GL_CLAMP_TO_EDGE; - } else { - wrapS = gTileModes[tileModes[0]]; - wrapT = gTileModes[tileModes[1]]; - } - - if (shaderInfo) { - shaderInfo->width = width; - shaderInfo->height = height; - shaderInfo->wrapS = wrapS; - shaderInfo->wrapT = wrapT; - shaderInfo->texture = texture; - } - return true; -} - -void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader) { - SkBitmap bitmap; - SkShader::TileMode xy[2]; - if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) { - LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!"); - } - bitmapShaderHelper(caches, &description, nullptr, extensions, bitmap, xy); -} - -void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { - SkBitmap bitmap; - SkShader::TileMode xy[2]; - if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) { - LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!"); - } - - GLuint textureSlot = (*textureUnit)++; - caches->textureState().activateTexture(textureSlot); - - BitmapShaderInfo shaderInfo; - if (!bitmapShaderHelper(caches, nullptr, &shaderInfo, extensions, bitmap, xy)) { - return; - } - - Program& program = caches->program(); - Texture* texture = shaderInfo.texture; - - const AutoTexture autoCleanup(texture); - - mat4 textureTransform; - computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(), - modelViewMatrix); - - // Uniforms - bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT); - texture->setFilter(GL_LINEAR); - - glUniform1i(program.getUniform("bitmapSampler"), textureSlot); - glUniformMatrix4fv(program.getUniform("textureTransform"), 1, - GL_FALSE, &textureTransform.data[0]); - glUniform2f(program.getUniform("textureDimension"), 1.0f / shaderInfo.width, - 1.0f / shaderInfo.height); -} - -/////////////////////////////////////////////////////////////////////////////// -// Linear gradient shader -/////////////////////////////////////////////////////////////////////////////// - -static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { +static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { SkVector vec = pts[1] - pts[0]; const float mag = vec.length(); const float inv = mag ? 1.0f / mag : 0; @@ -316,10 +89,6 @@ static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { matrix->postScale(inv, inv); } -/////////////////////////////////////////////////////////////////////////////// -// Circular gradient shader -/////////////////////////////////////////////////////////////////////////////// - static void toCircularUnitMatrix(const float x, const float y, const float radius, SkMatrix* matrix) { const float inv = 1.0f / radius; @@ -327,10 +96,6 @@ static void toCircularUnitMatrix(const float x, const float y, const float radiu matrix->postScale(inv, inv); } -/////////////////////////////////////////////////////////////////////////////// -// Sweep gradient shader -/////////////////////////////////////////////////////////////////////////////// - static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) { matrix->setTranslate(-x, -y); } @@ -343,137 +108,6 @@ static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) { return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode; } -void SkiaGradientShader::describe(Caches*, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader) { - SkShader::GradientInfo gradInfo; - gradInfo.fColorCount = 0; - gradInfo.fColors = nullptr; - gradInfo.fColorOffsets = nullptr; - - switch (shader.asAGradient(&gradInfo)) { - case SkShader::kLinear_GradientType: - description.gradientType = ProgramDescription::kGradientLinear; - break; - case SkShader::kRadial_GradientType: - description.gradientType = ProgramDescription::kGradientCircular; - break; - case SkShader::kSweep_GradientType: - description.gradientType = ProgramDescription::kGradientSweep; - break; - default: - // Do nothing. This shader is unsupported. - return; - } - description.hasGradient = true; - description.isSimpleGradient = isSimpleGradient(gradInfo); -} - -void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions&, const SkShader& shader) { - // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient - // how much space has been allocated for fColors and fColorOffsets. 10 was chosen - // arbitrarily, but should be >= 2. - // As output, it tells the number of actual colors/offsets in the gradient. - const int COLOR_COUNT = 10; - SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT); - SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT); - - SkShader::GradientInfo gradInfo; - gradInfo.fColorCount = COLOR_COUNT; - gradInfo.fColors = colorStorage.get(); - gradInfo.fColorOffsets = positionStorage.get(); - - SkShader::GradientType gradType = shader.asAGradient(&gradInfo); - - Program& program = caches->program(); - if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) { - if (gradInfo.fColorCount > COLOR_COUNT) { - // There was not enough room in our arrays for all the colors and offsets. Try again, - // now that we know the true number of colors. - gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount); - gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount); - - shader.asAGradient(&gradInfo); - } - GLuint textureSlot = (*textureUnit)++; - caches->textureState().activateTexture(textureSlot); - -#ifndef SK_SCALAR_IS_FLOAT - #error Need to convert gradInfo.fColorOffsets to float! -#endif - Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets, - gradInfo.fColorCount); - - // Uniforms - bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]); - glUniform1i(program.getUniform("gradientSampler"), textureSlot); - } else { - bindUniformColor(program.getUniform("startColor"), gradInfo.fColors[0]); - bindUniformColor(program.getUniform("endColor"), gradInfo.fColors[1]); - } - - caches->dither.setupProgram(program, textureUnit); - - SkMatrix unitMatrix; - switch (gradType) { - case SkShader::kLinear_GradientType: - toUnitMatrix(gradInfo.fPoint, &unitMatrix); - break; - case SkShader::kRadial_GradientType: - toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, - gradInfo.fRadius[0], &unitMatrix); - break; - case SkShader::kSweep_GradientType: - toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix); - break; - default: - LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType); - } - - mat4 screenSpace; - computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix); - glUniformMatrix4fv(program.getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); -} - -/////////////////////////////////////////////////////////////////////////////// -// Compose shader -/////////////////////////////////////////////////////////////////////////////// - -void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader) { - SkShader::ComposeRec rec; - if (!shader.asACompose(&rec)) { - LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!"); - } - SkiaShader::describe(caches, description, extensions, *rec.fShaderA); - SkiaShader::describe(caches, description, extensions, *rec.fShaderB); - if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) { - description.isBitmapFirst = true; - } - if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) { - // TODO: Support other modes. - description.shadersMode = SkXfermode::kSrcOver_Mode; - } -} - -void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { - SkShader::ComposeRec rec; - if (!shader.asACompose(&rec)) { - LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!"); - } - - // Apply this compose shader's local transform and pass it down to - // the child shaders. They will in turn apply their local transform - // to this matrix. - mat4 transform; - computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), - modelViewMatrix); - - SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA); - SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB); -} - /////////////////////////////////////////////////////////////////////////////// // Store / apply /////////////////////////////////////////////////////////////////////////////// @@ -491,7 +125,7 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode case SkShader::kLinear_GradientType: description->gradientType = ProgramDescription::kGradientLinear; - toUnitMatrix(gradInfo.fPoint, &unitMatrix); + toLinearUnitMatrix(gradInfo.fPoint, &unitMatrix); break; case SkShader::kRadial_GradientType: description->gradientType = ProgramDescription::kGradientCircular; diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index 2962441c6da2..5b8aa86aaf5f 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -87,77 +87,12 @@ struct SkiaShaderData { class SkiaShader { public: - static SkiaShaderType getType(const SkShader& shader); - static void describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader); - static void setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); - - // new SkiaShader interaction model - store into ShaderData, and apply to Caches/Program/GL static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix, GLuint* textureUnit, ProgramDescription* description, SkiaShaderData* outData); static void apply(Caches& caches, const SkiaShaderData& data); }; -class InvalidSkiaShader { -public: - static void describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader) { - // This shader is unsupported. Skip it. - } - static void setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) { - // This shader is unsupported. Skip it. - } - -}; -/** - * A shader that draws a layer. - */ -class SkiaLayerShader { -public: - static void describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader); - static void setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); -}; // class SkiaLayerShader - -/** - * A shader that draws a bitmap. - */ -class SkiaBitmapShader { -public: - static void describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader); - static void setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); - - -}; // class SkiaBitmapShader - -/** - * A shader that draws one of three types of gradient, depending on shader param. - */ -class SkiaGradientShader { -public: - static void describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader); - static void setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); -}; - -/** - * A shader that draws two shaders, composited with an xfermode. - */ -class SkiaComposeShader { -public: - static void describe(Caches* caches, ProgramDescription& description, - const Extensions& extensions, const SkShader& shader); - static void setupProgram(Caches* caches, const mat4& modelViewMatrix, - GLuint* textureUnit, const Extensions& extensions, const SkShader& shader); -}; // class SkiaComposeShader - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index 597d95ce7973..9e7faee69fba 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -203,8 +203,9 @@ void Snapshot::dump() const { ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d", this, flags, previous.get(), getViewportHeight(), isIgnored(), !mClipArea->isSimple()); const Rect& clipRect(mClipArea->getClipRect()); - ALOGD(" ClipRect %.1f %.1f %.1f %.1f", - clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); + ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d", + clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple()); + ALOGD(" Transform (at %p):", transform); transform->dump(); } diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp index b3b06d672dc7..db3c2d9a5060 100644 --- a/libs/hwui/SpotShadow.cpp +++ b/libs/hwui/SpotShadow.cpp @@ -44,6 +44,9 @@ // For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals. #define SPOT_CORNER_RADIANS_DIVISOR (M_PI / SPOT_EXTRA_CORNER_VERTEX_PER_PI) +// For performance, we use (1 - alpha) value for the shader input. +#define TRANSFORMED_PENUMBRA_ALPHA 1.0f +#define TRANSFORMED_UMBRA_ALPHA 0.0f #include <math.h> #include <stdlib.h> @@ -964,11 +967,11 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength // Fill the IB and VB for the penumbra area. for (int i = 0; i < newPenumbraLength; i++) { AlphaVertex::set(&shadowVertices[vertexBufferIndex++], newPenumbra[i].x, - newPenumbra[i].y, 0.0f); + newPenumbra[i].y, TRANSFORMED_PENUMBRA_ALPHA); } for (int i = 0; i < umbraLength; i++) { AlphaVertex::set(&shadowVertices[vertexBufferIndex++], umbra[i].x, umbra[i].y, - M_PI); + TRANSFORMED_UMBRA_ALPHA); } for (int i = 0; i < verticesPairIndex; i++) { @@ -1008,14 +1011,14 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength indexBuffer[indexBufferIndex++] = newPenumbraLength + i; indexBuffer[indexBufferIndex++] = vertexBufferIndex; AlphaVertex::set(&shadowVertices[vertexBufferIndex++], - closerVertex.x, closerVertex.y, M_PI); + closerVertex.x, closerVertex.y, TRANSFORMED_UMBRA_ALPHA); } } else { // If there is no occluded umbra at all, then draw the triangle fan // starting from the centroid to all umbra vertices. int lastCentroidIndex = vertexBufferIndex; AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid.x, - centroid.y, M_PI); + centroid.y, TRANSFORMED_UMBRA_ALPHA); for (int i = 0; i < umbraLength; i++) { indexBuffer[indexBufferIndex++] = newPenumbraLength + i; indexBuffer[indexBufferIndex++] = lastCentroidIndex; |