diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/FontRenderer.cpp | 13 | ||||
| -rw-r--r-- | libs/hwui/FrameInfo.cpp | 16 | ||||
| -rw-r--r-- | libs/hwui/FrameInfo.h | 9 | ||||
| -rw-r--r-- | libs/hwui/FrameInfoVisualizer.cpp | 104 | ||||
| -rw-r--r-- | libs/hwui/FrameInfoVisualizer.h | 40 | ||||
| -rw-r--r-- | libs/hwui/Glop.h | 47 | ||||
| -rw-r--r-- | libs/hwui/GlopBuilder.cpp | 91 | ||||
| -rw-r--r-- | libs/hwui/GlopBuilder.h | 24 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 97 | ||||
| -rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 17 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.cpp | 15 | ||||
| -rw-r--r-- | libs/hwui/SkiaShader.h | 2 | ||||
| -rw-r--r-- | libs/hwui/renderstate/RenderState.cpp | 16 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 16 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 13 |
15 files changed, 312 insertions, 208 deletions
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index c79ae777d051..9664f58b1752 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -51,17 +51,20 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) { - int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + int textureFillFlags = TextureFillFlags::None; + if (texture.getFormat() == GL_ALPHA) { + textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; + } if (linearFiltering) { - textureFillFlags |= TextureFillFlags::kForceFilter; + textureFillFlags |= TextureFillFlags::ForceFilter; } - const Matrix4& transform = pureTranslate ? Matrix4::identity() : *(renderer->currentTransform()); + int transformFlags = pureTranslate + ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None; Glop glop; GlopBuilder(renderer->mRenderState, renderer->mCaches, &glop) .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount()) .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, renderer->currentSnapshot()->alpha) - .setTransform(renderer->currentSnapshot()->getOrthoMatrix(), transform, false) + .setTransform(*(renderer->currentSnapshot()), transformFlags) .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0)) .setRoundRectClipState(renderer->currentSnapshot()->roundRectClipState) .build(); diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp index 6da1fa808d0a..c24833bf3509 100644 --- a/libs/hwui/FrameInfo.cpp +++ b/libs/hwui/FrameInfo.cpp @@ -20,6 +20,22 @@ namespace android { namespace uirenderer { +std::string FrameInfoNames[] = { + "Flags", + "IntendedVsync", + "Vsync", + "OldestInputEvent", + "NewestInputEvent", + "HandleInputStart", + "AnimationStart", + "PerformTraversalsStart", + "DrawStart", + "SyncStart", + "IssueDrawCommandsStart", + "SwapBuffers", + "FrameCompleted", +}; + void FrameInfo::importUiThreadInfo(int64_t* info) { memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); } diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index c8189b8df955..bcfae1b9e901 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -22,6 +22,7 @@ #include <utils/Timers.h> #include <memory.h> +#include <string> namespace android { namespace uirenderer { @@ -49,6 +50,8 @@ enum class FrameInfoIndex { kNumIndexes }; +extern std::string FrameInfoNames[]; + enum class FrameInfoFlags { kWindowLayoutChanged = 1 << 0, kRTAnimation = 1 << 1, @@ -66,6 +69,12 @@ public: UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) { set(FrameInfoIndex::kVsync) = vsyncTime; set(FrameInfoIndex::kIntendedVsync) = intendedVsync; + // Pretend the other fields are all at vsync, too, so that naive + // duration calculations end up being 0 instead of very large + set(FrameInfoIndex::kHandleInputStart) = vsyncTime; + set(FrameInfoIndex::kAnimationStart) = vsyncTime; + set(FrameInfoIndex::kPerformTraversalsStart) = vsyncTime; + set(FrameInfoIndex::kDrawStart) = vsyncTime; return *this; } diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp index 041174265348..95b099542f44 100644 --- a/libs/hwui/FrameInfoVisualizer.cpp +++ b/libs/hwui/FrameInfoVisualizer.cpp @@ -18,6 +18,7 @@ #include "OpenGLRenderer.h" #include <cutils/compiler.h> +#include <array> #define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == ProfileType::None)) return #define RETURN_IF_DISABLED() if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return @@ -26,19 +27,10 @@ #define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2 #define PROFILE_DRAW_DP_PER_MS 7 -// Number of floats we want to display from FrameTimingData -// If this is changed make sure to update the indexes below -#define NUM_ELEMENTS 4 - -#define RECORD_INDEX 0 -#define PREPARE_INDEX 1 -#define PLAYBACK_INDEX 2 -#define SWAPBUFFERS_INDEX 3 - // Must be NUM_ELEMENTS in size -static const SkColor ELEMENT_COLORS[] = { 0xcf3e66cc, 0xcf8f00ff, 0xcfdc3912, 0xcfe69800 }; static const SkColor CURRENT_FRAME_COLOR = 0xcf5faa4d; static const SkColor THRESHOLD_COLOR = 0xff5faa4d; +static const SkColor BAR_ALPHA = 0xCF000000; // We could get this from TimeLord and use the actual frame interval, but // this is good enough @@ -47,6 +39,24 @@ static const SkColor THRESHOLD_COLOR = 0xff5faa4d; namespace android { namespace uirenderer { +struct BarSegment { + FrameInfoIndex start; + FrameInfoIndex end; + SkColor color; +}; + +static const std::array<BarSegment,9> Bar {{ + { FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync, 0x00695C }, + { FrameInfoIndex::kVsync, FrameInfoIndex::kHandleInputStart, 0x00796B }, + { FrameInfoIndex::kHandleInputStart, FrameInfoIndex::kAnimationStart, 0x00897B }, + { FrameInfoIndex::kAnimationStart, FrameInfoIndex::kPerformTraversalsStart, 0x009688 }, + { FrameInfoIndex::kPerformTraversalsStart, FrameInfoIndex::kDrawStart, 0x26A69A}, + { FrameInfoIndex::kDrawStart, FrameInfoIndex::kSyncStart, 0x2196F3}, + { FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart, 0x4FC3F7}, + { FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kSwapBuffers, 0xF44336}, + { FrameInfoIndex::kSwapBuffers, FrameInfoIndex::kFrameCompleted, 0xFF9800}, +}}; + static int dpToPx(int dp, float density) { return (int) (dp * density + 0.5f); } @@ -93,9 +103,9 @@ void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) { } if (mType == ProfileType::Bars) { - prepareShapes(canvas->getViewportHeight()); + initializeRects(canvas->getViewportHeight()); drawGraph(canvas); - drawCurrentFrame(canvas); + drawCurrentFrame(canvas->getViewportHeight(), canvas); drawThreshold(canvas); } } @@ -103,57 +113,61 @@ void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) { void FrameInfoVisualizer::createData() { if (mRects.get()) return; - mRects.reset(new float*[mFrameSource.capacity()]); - for (int i = 0; i < NUM_ELEMENTS; i++) { - // 4 floats per rect - mRects.get()[i] = (float*) calloc(mFrameSource.capacity(), 4 * sizeof(float)); - } + mRects.reset(new float[mFrameSource.capacity() * 4]); } void FrameInfoVisualizer::destroyData() { mRects.reset(nullptr); } -void FrameInfoVisualizer::addRect(Rect& r, float data, float* shapeOutput) { - r.top = r.bottom - (data * mVerticalUnit); - shapeOutput[0] = r.left; - shapeOutput[1] = r.top; - shapeOutput[2] = r.right; - shapeOutput[3] = r.bottom; - r.bottom = r.top; +void FrameInfoVisualizer::initializeRects(const int baseline) { + float left = 0; + // Set the bottom of all the shapes to the baseline + for (size_t i = 0; i < (mFrameSource.capacity() * 4); i += 4) { + // Rects are LTRB + mRects[i + 0] = left; + mRects[i + 1] = baseline; + left += mHorizontalUnit; + mRects[i + 2] = left; + mRects[i + 3] = baseline; + } } -void FrameInfoVisualizer::prepareShapes(const int baseline) { - Rect r; - r.right = mHorizontalUnit; - for (size_t i = 0; i < mFrameSource.size(); i++) { - const int shapeIndex = i * 4; - r.bottom = baseline; - addRect(r, recordDuration(i), mRects.get()[RECORD_INDEX] + shapeIndex); - addRect(r, prepareDuration(i), mRects.get()[PREPARE_INDEX] + shapeIndex); - addRect(r, issueDrawDuration(i), mRects.get()[PLAYBACK_INDEX] + shapeIndex); - addRect(r, swapBuffersDuration(i), mRects.get()[SWAPBUFFERS_INDEX] + shapeIndex); - r.translate(mHorizontalUnit, 0); +void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex end) { + for (size_t fi = 0, ri = 0; fi < mFrameSource.size(); fi++, ri += 4) { + // TODO: Skipped frames will leave little holes in the graph, but this + // is better than bogus and freaky lines, so... + if (mFrameSource[fi][FrameInfoIndex::kFlags] & FrameInfoFlags::kSkippedFrame) { + continue; + } + + // Set the bottom to the old top (build upwards) + mRects[ri + 3] = mRects[ri + 1]; + // Move the top up by the duration + mRects[ri + 1] -= mVerticalUnit * duration(fi, start, end); } } void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) { SkPaint paint; - for (int i = 0; i < NUM_ELEMENTS; i++) { - paint.setColor(ELEMENT_COLORS[i]); - canvas->drawRects(mRects.get()[i], mFrameSource.capacity() * 4, &paint); + for (size_t i = 0; i < Bar.size(); i++) { + paint.setColor(Bar[i].color | BAR_ALPHA); + nextBarSegment(Bar[i].start, Bar[i].end); + canvas->drawRects(mRects.get(), (mFrameSource.size() - 1) * 4, &paint); } } -void FrameInfoVisualizer::drawCurrentFrame(OpenGLRenderer* canvas) { +void FrameInfoVisualizer::drawCurrentFrame(const int baseline, OpenGLRenderer* canvas) { // This draws a solid rect over the entirety of the current frame's shape // To do so we use the bottom of mRects[0] and the top of mRects[NUM_ELEMENTS-1] // which will therefore fully overlap the previously drawn rects SkPaint paint; paint.setColor(CURRENT_FRAME_COLOR); - const int i = (mFrameSource.size() - 1) * 4; - canvas->drawRect(mRects.get()[0][i], mRects.get()[NUM_ELEMENTS-1][i+1], - mRects.get()[0][i+2], mRects.get()[0][i+3], &paint); + size_t fi = mFrameSource.size() - 1; + size_t ri = fi * 4; + float top = baseline - (mVerticalUnit * duration(fi, + FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kIssueDrawCommandsStart)); + canvas->drawRect(mRects[ri], top, mRects[ri + 2], baseline, &paint); } void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) { @@ -205,8 +219,10 @@ void FrameInfoVisualizer::dumpData(int fd) { } mLastFrameLogged = mFrameSource[i][FrameInfoIndex::kIntendedVsync]; fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n", - recordDuration(i), prepareDuration(i), - issueDrawDuration(i), swapBuffersDuration(i)); + duration(i, FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kSyncStart), + duration(i, FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart), + duration(i, FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kSwapBuffers), + duration(i, FrameInfoIndex::kSwapBuffers, FrameInfoIndex::kFrameCompleted)); } fflush(file); diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h index f62e34dacbf4..3fa458659124 100644 --- a/libs/hwui/FrameInfoVisualizer.h +++ b/libs/hwui/FrameInfoVisualizer.h @@ -54,41 +54,21 @@ private: void createData(); void destroyData(); - void addRect(Rect& r, float data, float* shapeOutput); - void prepareShapes(const int baseline); + void initializeRects(const int baseline); + void nextBarSegment(FrameInfoIndex start, FrameInfoIndex end); void drawGraph(OpenGLRenderer* canvas); - void drawCurrentFrame(OpenGLRenderer* canvas); + void drawCurrentFrame(const int baseline, OpenGLRenderer* canvas); void drawThreshold(OpenGLRenderer* canvas); - static inline float duration(nsecs_t start, nsecs_t end) { - float duration = ((end - start) * 0.000001f); + inline float duration(size_t index, FrameInfoIndex start, FrameInfoIndex end) { + nsecs_t ns_start = mFrameSource[index][start]; + nsecs_t ns_end = mFrameSource[index][end]; + float duration = ((ns_end - ns_start) * 0.000001f); + // Clamp to large to avoid spiking off the top of the screen + duration = duration > 50.0f ? 50.0f : duration; return duration > 0.0f ? duration : 0.0f; } - inline float recordDuration(size_t index) { - return duration( - mFrameSource[index][FrameInfoIndex::kIntendedVsync], - mFrameSource[index][FrameInfoIndex::kSyncStart]); - } - - inline float prepareDuration(size_t index) { - return duration( - mFrameSource[index][FrameInfoIndex::kSyncStart], - mFrameSource[index][FrameInfoIndex::kIssueDrawCommandsStart]); - } - - inline float issueDrawDuration(size_t index) { - return duration( - mFrameSource[index][FrameInfoIndex::kIssueDrawCommandsStart], - mFrameSource[index][FrameInfoIndex::kSwapBuffers]); - } - - inline float swapBuffersDuration(size_t index) { - return duration( - mFrameSource[index][FrameInfoIndex::kSwapBuffers], - mFrameSource[index][FrameInfoIndex::kFrameCompleted]); - } - ProfileType mType = ProfileType::None; float mDensity = 0; @@ -105,7 +85,7 @@ private: * OpenGLRenderer:drawRects() that makes up all the FrameTimingData:record * information. */ - std::unique_ptr<float*> mRects; + std::unique_ptr<float[]> mRects; bool mShowDirtyRegions = false; SkRect mDirtyRegion; diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h index 2c6f6c120d16..fa20b0807a88 100644 --- a/libs/hwui/Glop.h +++ b/libs/hwui/Glop.h @@ -41,13 +41,32 @@ class Texture; * Position is always enabled by MeshState, these other attributes * are enabled/disabled dynamically based on mesh content. */ -enum class VertexAttribFlags { - kNone = 0, - kTextureCoord = 1 << 0, - kColor = 1 << 1, - kAlpha = 1 << 2, + +namespace VertexAttribFlags { + enum { + None = 0, + TextureCoord = 1 << 0, + Color = 1 << 1, + Alpha = 1 << 2, + }; +}; + +/* + * Enumerates transform features + */ +namespace TransformFlags { + enum { + None = 0, + + // offset the eventual drawing matrix by a tiny amount to + // disambiguate sampling patterns with non-AA rendering + OffsetByFudgeFactor = 1 << 0, + + // Canvas transform isn't applied to the mesh at draw time, + //since it's already built in. + MeshIgnoresCanvasTransform = 1 << 1, + }; }; -MAKE_FLAGS_ENUM(VertexAttribFlags) /** * Structure containing all data required to issue an OpenGL draw @@ -116,10 +135,22 @@ struct Glop { } fill; struct Transform { - Matrix4 ortho; // TODO: out of op, since this is static per FBO + // Orthographic projection matrix for current FBO + // TODO: move out of Glop, since this is static per FBO + Matrix4 ortho; + + // modelView transform, accounting for delta between mesh transform and content of the mesh + // often represents x/y offsets within command, or scaling for mesh unit size Matrix4 modelView; + + // Canvas transform of Glop - not necessarily applied to geometry (see flags) Matrix4 canvas; - bool fudgingOffset; + int transformFlags; + + const Matrix4& meshTransform() const { + return (transformFlags & TransformFlags::MeshIgnoresCanvasTransform) + ? Matrix4::identity() : canvas; + } } transform; const RoundRectClipState* roundRectClipState; diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index e25f81eaa8af..b7cdaa2abc81 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -66,7 +66,7 @@ GlopBuilder& GlopBuilder::setMeshUnitQuad() { mOutGlop->mesh.indices = { 0, nullptr }; mOutGlop->mesh.vertices = { mRenderState.meshState().getUnitQuadVBO(), - static_cast<int>(VertexAttribFlags::kNone), + VertexAttribFlags::None, nullptr, nullptr, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = 4; @@ -85,7 +85,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) { mOutGlop->mesh.indices = { 0, nullptr }; mOutGlop->mesh.vertices = { mRenderState.meshState().getUnitQuadVBO(), - static_cast<int>(VertexAttribFlags::kTextureCoord), + VertexAttribFlags::TextureCoord, nullptr, (const void*) kMeshTextureOffset, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = 4; @@ -105,7 +105,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedUvQuad(const UvMapper* uvMapper, Rect u mOutGlop->mesh.indices = { 0, nullptr }; mOutGlop->mesh.vertices = { 0, - static_cast<int>(VertexAttribFlags::kTextureCoord), + VertexAttribFlags::TextureCoord, &textureVertex[0].x, &textureVertex[0].u, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = 4; @@ -119,7 +119,7 @@ GlopBuilder& GlopBuilder::setMeshIndexedQuads(Vertex* vertexData, int quadCount) mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr }; mOutGlop->mesh.vertices = { 0, - static_cast<int>(VertexAttribFlags::kNone), + VertexAttribFlags::None, vertexData, nullptr, nullptr, kVertexStride }; mOutGlop->mesh.elementCount = 6 * quadCount; @@ -133,7 +133,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData, mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr }; mOutGlop->mesh.vertices = { 0, - static_cast<int>(VertexAttribFlags::kTextureCoord), + VertexAttribFlags::TextureCoord, &vertexData[0].x, &vertexData[0].u, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; @@ -147,7 +147,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedMesh(TextureVertex* vertexData, int ele mOutGlop->mesh.indices = { 0, nullptr }; mOutGlop->mesh.vertices = { 0, - static_cast<int>(VertexAttribFlags::kTextureCoord), + VertexAttribFlags::TextureCoord, &vertexData[0].x, &vertexData[0].u, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; @@ -161,7 +161,7 @@ GlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexD mOutGlop->mesh.indices = { 0, nullptr }; mOutGlop->mesh.vertices = { 0, - VertexAttribFlags::kTextureCoord | VertexAttribFlags::kColor, + VertexAttribFlags::TextureCoord | VertexAttribFlags::Color, &vertexData[0].x, &vertexData[0].u, &vertexData[0].r, kColorTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; @@ -180,7 +180,7 @@ GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, mOutGlop->mesh.indices = { 0, vertexBuffer.getIndices() }; mOutGlop->mesh.vertices = { 0, - static_cast<int>(alphaVertex ? VertexAttribFlags::kAlpha : VertexAttribFlags::kNone), + alphaVertex ? VertexAttribFlags::Alpha : VertexAttribFlags::None, vertexBuffer.getBuffer(), nullptr, nullptr, alphaVertex ? kAlphaVertexStride : kVertexStride }; mOutGlop->mesh.elementCount = indices @@ -197,7 +197,7 @@ GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) { mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr }; mOutGlop->mesh.vertices = { mCaches.patchCache.getMeshBuffer(), - static_cast<int>(VertexAttribFlags::kTextureCoord), + VertexAttribFlags::TextureCoord, (void*)patch.positionOffset, (void*)patch.textureOffset, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = patch.indexCount; @@ -230,7 +230,7 @@ void GlopBuilder::setFill(int color, float alphaScale, mOutGlop->blend = { GL_ZERO, GL_ZERO }; if (mOutGlop->fill.color.a < 1.0f - || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha) + || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha) || (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend) || mOutGlop->roundRectClipState || PaintUtils::isBlendedShader(shader) @@ -298,12 +298,12 @@ void GlopBuilder::setFill(int color, float alphaScale, } } -GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillFlags, - const SkPaint* paint, float alphaScale) { +GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, + const int textureFillFlags, const SkPaint* paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); - GLenum filter = (textureFillFlags & TextureFillFlags::kForceFilter) + GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter) ? GL_LINEAR : PaintUtils::getFilter(paint); mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, filter, GL_CLAMP_TO_EDGE, nullptr }; @@ -312,7 +312,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF int color = paint->getColor(); SkShader* shader = paint->getShader(); - if (!(textureFillFlags & TextureFillFlags::kIsAlphaMaskTexture)) { + if (!(textureFillFlags & TextureFillFlags::IsAlphaMaskTexture)) { // Texture defines color, so disable shaders, and reset all non-alpha color channels color |= 0x00FFFFFF; shader = nullptr; @@ -324,7 +324,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; if (alphaScale < 1.0f - || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha) + || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha) || texture.blend || mOutGlop->roundRectClipState) { Blend::getFactors(SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap, @@ -334,7 +334,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF } } - if (textureFillFlags & TextureFillFlags::kIsAlphaMaskTexture) { + if (textureFillFlags & TextureFillFlags::IsAlphaMaskTexture) { mDescription.modulate = mOutGlop->fill.color.isNotBlack(); mDescription.hasAlpha8Texture = true; } else { @@ -452,14 +452,13 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) { // Transform //////////////////////////////////////////////////////////////////////////////// -GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho, - const Matrix4& transform, bool fudgingOffset) { +void GlopBuilder::setTransform(const Matrix4& ortho, const Matrix4& canvas, + const int transformFlags) { TRIGGER_STAGE(kTransformStage); mOutGlop->transform.ortho.load(ortho); - mOutGlop->transform.canvas.load(transform); - mOutGlop->transform.fudgingOffset = fudgingOffset; - return *this; + mOutGlop->transform.canvas.load(canvas); + mOutGlop->transform.transformFlags = transformFlags; } //////////////////////////////////////////////////////////////////////////////// @@ -482,11 +481,11 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) float left = destination.left; float top = destination.top; - const Matrix4& canvasTransform = mOutGlop->transform.canvas; - if (CC_LIKELY(canvasTransform.isPureTranslate())) { + const Matrix4& meshTransform = mOutGlop->transform.meshTransform(); + if (CC_LIKELY(meshTransform.isPureTranslate())) { // snap by adjusting the model view matrix - const float translateX = canvasTransform.getTranslateX(); - const float translateY = canvasTransform.getTranslateY(); + const float translateX = meshTransform.getTranslateX(); + const float translateY = meshTransform.getTranslateY(); left = (int) floorf(left + translateX + 0.5f) - translateX; top = (int) floorf(top + translateY + 0.5f) - translateY; @@ -512,11 +511,11 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offset TRIGGER_STAGE(kModelViewStage); REQUIRE_STAGES(kTransformStage | kFillStage); - const Matrix4& canvasTransform = mOutGlop->transform.canvas; - if (CC_LIKELY(canvasTransform.isPureTranslate())) { + const Matrix4& meshTransform = mOutGlop->transform.meshTransform(); + if (CC_LIKELY(meshTransform.isPureTranslate())) { // snap by adjusting the model view matrix - const float translateX = canvasTransform.getTranslateX(); - const float translateY = canvasTransform.getTranslateY(); + const float translateX = meshTransform.getTranslateX(); + const float translateY = meshTransform.getTranslateY(); offsetX = (int) floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left; offsetY = (int) floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top; @@ -549,7 +548,7 @@ void verify(const ProgramDescription& description, const Glop& glop) { if (glop.fill.texture.texture != nullptr) { LOG_ALWAYS_FATAL_IF(((description.hasTexture && description.hasExternalTexture) || (!description.hasTexture && !description.hasExternalTexture) - || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::kTextureCoord) == 0)), + || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) == 0)), "Texture %p, hT%d, hET %d, attribFlags %x", glop.fill.texture.texture, description.hasTexture, description.hasExternalTexture, @@ -557,13 +556,13 @@ void verify(const ProgramDescription& description, const Glop& glop) { } else { LOG_ALWAYS_FATAL_IF((description.hasTexture || description.hasExternalTexture - || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::kTextureCoord) != 0)), + || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) != 0)), "No texture, hT%d, hET %d, attribFlags %x", description.hasTexture, description.hasExternalTexture, glop.mesh.vertices.attribFlags); } - if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::kAlpha) + if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::Alpha) && glop.mesh.vertices.bufferObject) { LOG_ALWAYS_FATAL("VBO and alpha attributes are not currently compatible"); } @@ -575,16 +574,16 @@ void verify(const ProgramDescription& description, const Glop& glop) { void GlopBuilder::build() { REQUIRE_STAGES(kAllStages); - if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kTextureCoord) { + if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) { if (mOutGlop->fill.texture.target == GL_TEXTURE_2D) { mDescription.hasTexture = true; } else { mDescription.hasExternalTexture = true; } - } - mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kColor; - mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha; + + mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color; + mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha; // Enable debug highlight when what we're about to draw is tested against // the stencil buffer and if stencil highlight debugging is on @@ -594,8 +593,22 @@ void GlopBuilder::build() { // serialize shader info into ShaderData GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0; - SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView, - &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData)); + + if (CC_LIKELY(!mShader)) { + mOutGlop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType; + } else { + Matrix4 shaderMatrix; + if (mOutGlop->transform.transformFlags & TransformFlags::MeshIgnoresCanvasTransform) { + // canvas level transform was built into the modelView and geometry, + // so the shader matrix must reverse this + shaderMatrix.loadInverse(mOutGlop->transform.canvas); + shaderMatrix.multiply(mOutGlop->transform.modelView); + } else { + shaderMatrix.load(mOutGlop->transform.modelView); + } + SkiaShader::store(mCaches, *mShader, shaderMatrix, + &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData)); + } // duplicates ProgramCache's definition of color uniform presence const bool singleColor = !mDescription.hasTexture @@ -608,7 +621,7 @@ void GlopBuilder::build() { // Final step: populate program and map bounds into render target space mOutGlop->fill.program = mCaches.programCache.get(mDescription); - mOutGlop->transform.canvas.mapRect(mOutGlop->bounds); + mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds); } } /* namespace uirenderer */ diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index b335a2c5a25e..549bb21e5f8d 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -16,6 +16,7 @@ #ifndef RENDERSTATE_GLOPBUILDER_H #define RENDERSTATE_GLOPBUILDER_H +#include "Glop.h" #include "OpenGLRenderer.h" #include "Program.h" #include "renderstate/Blend.h" @@ -32,14 +33,14 @@ class Matrix4; class RenderState; class Texture; class VertexBuffer; -struct Glop; -enum class TextureFillFlags { - kNone = 0, - kIsAlphaMaskTexture = 1 << 0, - kForceFilter = 1 << 1, -}; -MAKE_FLAGS_ENUM(TextureFillFlags); +namespace TextureFillFlags { + enum { + None = 0, + IsAlphaMaskTexture = 1 << 0, + ForceFilter = 1 << 1, + }; +} class GlopBuilder { PREVENT_COPY_AND_ASSIGN(GlopBuilder); @@ -57,7 +58,7 @@ public: GlopBuilder& setMeshPatchQuads(const Patch& patch); GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale); - GlopBuilder& setFillTexturePaint(Texture& texture, int textureFillFlags, + GlopBuilder& setFillTexturePaint(Texture& texture, const int textureFillFlags, const SkPaint* paint, float alphaScale); GlopBuilder& setFillPathTexturePaint(PathTexture& texture, const SkPaint& paint, float alphaScale); @@ -69,7 +70,10 @@ public: float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage); GlopBuilder& setFillTextureLayer(Layer& layer, float alpha); - GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); + GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) { + setTransform(snapshot.getOrthoMatrix(), *snapshot.transform, transformFlags); + return *this; + } GlopBuilder& setModelViewMapUnitToRect(const Rect destination); GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination); @@ -98,6 +102,8 @@ private: void setFill(int color, float alphaScale, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage, const SkShader* shader, const SkColorFilter* colorFilter); + void setTransform(const Matrix4& ortho, const Matrix4& canvas, + const int transformFlags); enum StageFlags { kInitialStage = 0, diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8f916202e9e6..576937655f7a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -827,7 +827,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto // the layer contains screen buffer content that shouldn't be alpha modulated // (and any necessary alpha modulation was handled drawing into the layer) writableSnapshot()->alpha = 1.0f; - composeLayerRect(layer, rect, true); + composeLayerRectSwapped(layer, rect); restore(); } @@ -849,31 +849,40 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO .setFillTextureLayer(*layer, getLayerAlpha(layer)) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); renderGlop(glop); } -void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { +void OpenGLRenderer::composeLayerRectSwapped(Layer* layer, const Rect& rect) { + Glop glop; + GlopBuilder(mRenderState, mCaches, &glop) + .setMeshTexturedUvQuad(nullptr, layer->texCoords) + .setFillLayer(layer->getTexture(), layer->getColorFilter(), + getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::Swap) + .setTransform(*currentSnapshot(), TransformFlags::MeshIgnoresCanvasTransform) + .setModelViewMapUnitToRect(rect) + .setRoundRectClipState(currentSnapshot()->roundRectClipState) + .build(); + renderGlop(glop); +} + +void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect) { if (layer->isTextureLayer()) { EVENT_LOGD("composeTextureLayerRect"); drawTextureLayer(layer, rect); } else { EVENT_LOGD("composeHardwareLayerRect"); - Blend::ModeOrderSwap modeUsage = swap ? - Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap; - const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform(); - const bool tryToSnap = !swap - && layer->getWidth() == static_cast<uint32_t>(rect.getWidth()) + const bool tryToSnap = 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) + .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1014,7 +1023,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { 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) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewOffsetRectSnap(rect.left, rect.top, modelRect) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1128,11 +1137,12 @@ void OpenGLRenderer::clearLayerRegions() { // stencil setup from doing the same thing again mLayers.clear(); + const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshIndexedQuads(&mesh[0], quadCount) .setFillClear() - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect())) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1316,13 +1326,13 @@ void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) { mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom, scissorBox.getWidth(), scissorBox.getHeight()); - + const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform; Glop glop; Vertex* vertices = &rectangleVertices[0]; GlopBuilder(mRenderState, mCaches, &glop) .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4) .setFillBlack() - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(0, 0, scissorBox) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1518,13 +1528,15 @@ void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entr 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); + + const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType) + ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; + const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedMesh(vertices, bitmapCount * 6) .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight())) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1541,13 +1553,13 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { if (!texture) return; const AutoTexture autoCleanup(texture); - int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType) + ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedUnitQuad(texture->uvMapper) .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1632,11 +1644,12 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m * TODO: handle alpha_8 textures correctly by applying paint color, but *not* * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh. */ + const int textureFillFlags = TextureFillFlags::None; 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) + .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1657,16 +1670,15 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, cons fmin(1.0f, src.right / texture->width), fmin(1.0f, src.bottom / texture->height)); - const int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType) - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType) + ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; const bool tryToSnap = MathUtils::areEqual(src.getWidth(), dst.getWidth()) && MathUtils::areEqual(src.getHeight(), dst.getHeight()); - Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedUvQuad(texture->uvMapper, uv) .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, dst) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1684,15 +1696,15 @@ void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh, if (!texture) return; // 9 patches are built for stretching - always filter - int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter); + int textureFillFlags = TextureFillFlags::ForceFilter; if (bitmap->colorType() == kAlpha_8_SkColorType) { - textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture; + textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; } Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshPatchQuads(*mesh) .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1712,16 +1724,17 @@ void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entr const AutoTexture autoCleanup(texture); // TODO: get correct bounds from caller + const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform; // 9 patches are built for stretching - always filter - int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter); + int textureFillFlags = TextureFillFlags::ForceFilter; if (bitmap->colorType() == kAlpha_8_SkColorType) { - textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture; + textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; } Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedIndexedQuads(vertices, elementCount) .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -1736,13 +1749,13 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, return; } - bool fudgeOffset = displayFlags & kVertexBuffer_Offset; bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp; + const int transformFlags = TransformFlags::OffsetByFudgeFactor; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshVertexBuffer(vertexBuffer, shadowInterp) .setFillPaint(*paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -2028,7 +2041,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedUnitQuad(nullptr) .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -2353,7 +2366,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { 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) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight())) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -2411,7 +2424,7 @@ void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y, GlopBuilder(mRenderState, mCaches, &glop) .setMeshTexturedUnitQuad(nullptr) .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false) + .setTransform(*currentSnapshot(), TransformFlags::None) .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -2543,12 +2556,13 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint return; } - const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); + const int transformFlags = ignoreTransform + ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshIndexedQuads(&mesh[0], count / 4) .setFillPaint(*paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); @@ -2557,12 +2571,13 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, const SkPaint* paint, bool ignoreTransform) { - const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); + const int transformFlags = ignoreTransform + ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setMeshUnitQuad() .setFillPaint(*paint, currentSnapshot()->alpha) - .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setTransform(*currentSnapshot(), transformFlags) .setModelViewMapUnitToRect(Rect(left, top, right, bottom)) .setRoundRectClipState(currentSnapshot()->roundRectClipState) .build(); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 8dae82c5b114..29fbf0c985d7 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -640,13 +640,20 @@ private: void composeLayerRegion(Layer* layer, const Rect& rect); /** - * Compose the specified layer as a simple rectangle. + * Restores the content in layer to the screen, swapping the blend mode, + * specifically used in the restore() of a saveLayerAlpha(). * - * @param layer The layer to compose - * @param rect The layer's bounds - * @param swap If true, the source and destination are swapped + * This allows e.g. a layer that would have been drawn on top of existing content (with SrcOver) + * to be drawn underneath. + * + * This will always ignore the canvas transform. + */ + void composeLayerRectSwapped(Layer* layer, const Rect& rect); + + /** + * Draws the content in layer to the screen. */ - void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false); + void composeLayerRect(Layer* layer, const Rect& rect); /** * Clears all the regions corresponding to the current list of layers. diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index ecf8b6ba8219..2cfb9e1dc8c1 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -346,33 +346,28 @@ void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) { glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]); } -void SkiaShader::store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix, +void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix, GLuint* textureUnit, ProgramDescription* description, SkiaShaderData* outData) { - if (!shader) { - outData->skiaShaderType = kNone_SkiaShaderType; - return; - } - - if (tryStoreGradient(caches, *shader, modelViewMatrix, + if (tryStoreGradient(caches, shader, modelViewMatrix, textureUnit, description, &outData->gradientData)) { outData->skiaShaderType = kGradient_SkiaShaderType; return; } - if (tryStoreBitmap(caches, *shader, modelViewMatrix, + if (tryStoreBitmap(caches, shader, modelViewMatrix, textureUnit, description, &outData->bitmapData)) { outData->skiaShaderType = kBitmap_SkiaShaderType; return; } - if (tryStoreCompose(caches, *shader, modelViewMatrix, + if (tryStoreCompose(caches, shader, modelViewMatrix, textureUnit, description, outData)) { outData->skiaShaderType = kCompose_SkiaShaderType; return; } - if (tryStoreLayer(caches, *shader, modelViewMatrix, + if (tryStoreLayer(caches, shader, modelViewMatrix, textureUnit, description, &outData->layerData)) { outData->skiaShaderType = kLayer_SkiaShaderType; } diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index 5b8aa86aaf5f..884196d9fc62 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -87,7 +87,7 @@ struct SkiaShaderData { class SkiaShader { public: - static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix, + 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); diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index df12e63017f4..3ebd57b33c81 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -217,8 +217,8 @@ void RenderState::render(const Glop& glop) { fill.program->set(glop.transform.ortho, glop.transform.modelView, - glop.transform.canvas, - glop.transform.fudgingOffset); + glop.transform.meshTransform(), + glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor); // Color filter uniforms if (fill.filterMode == ProgramDescription::kColorBlend) { @@ -260,7 +260,7 @@ void RenderState::render(const Glop& glop) { // indices meshState().bindIndicesBufferInternal(indices.bufferObject); - if (vertices.attribFlags & VertexAttribFlags::kTextureCoord) { + if (vertices.attribFlags & VertexAttribFlags::TextureCoord) { const Glop::Fill::TextureData& texture = fill.texture; // texture always takes slot 0, shader samplers increment from there mCaches->textureState().activateTexture(0); @@ -284,13 +284,13 @@ void RenderState::render(const Glop& glop) { meshState().disableTexCoordsVertexArray(); } int colorLocation = -1; - if (vertices.attribFlags & VertexAttribFlags::kColor) { + if (vertices.attribFlags & VertexAttribFlags::Color) { colorLocation = fill.program->getAttrib("colors"); glEnableVertexAttribArray(colorLocation); glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride, vertices.color); } int alphaLocation = -1; - if (vertices.attribFlags & VertexAttribFlags::kAlpha) { + if (vertices.attribFlags & VertexAttribFlags::Alpha) { // NOTE: alpha vertex position is computed assuming no VBO const void* alphaCoords = ((const GLbyte*) vertices.position) + kVertexAlphaOffset; alphaLocation = fill.program->getAttrib("vtxAlpha"); @@ -318,7 +318,7 @@ void RenderState::render(const Glop& glop) { // rebind pointers without forcing, since initial bind handled above meshState().bindPositionVertexPointer(false, vertexData, vertices.stride); - if (vertices.attribFlags & VertexAttribFlags::kTextureCoord) { + if (vertices.attribFlags & VertexAttribFlags::TextureCoord) { meshState().bindTexCoordsVertexPointer(false, vertexData + kMeshTextureOffset, vertices.stride); } @@ -336,10 +336,10 @@ void RenderState::render(const Glop& glop) { // ----------------------------------- // ---------- Mesh teardown ---------- // ----------------------------------- - if (vertices.attribFlags & VertexAttribFlags::kAlpha) { + if (vertices.attribFlags & VertexAttribFlags::Alpha) { glDisableVertexAttribArray(alphaLocation); } - if (vertices.attribFlags & VertexAttribFlags::kColor) { + if (vertices.attribFlags & VertexAttribFlags::Color) { glDisableVertexAttribArray(colorLocation); } } diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 706e14ed7316..f8490b6c9aba 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -156,10 +156,18 @@ void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) { } } +static bool wasSkipped(FrameInfo* info) { + return info && ((*info)[FrameInfoIndex::kFlags] & FrameInfoFlags::kSkippedFrame); +} + void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) { mRenderThread.removeFrameCallback(this); - mCurrentFrameInfo = &mFrames.next(); + // If the previous frame was dropped we don't need to hold onto it, so + // just keep using the previous frame's structure instead + if (!wasSkipped(mCurrentFrameInfo)) { + mCurrentFrameInfo = &mFrames.next(); + } mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo); mCurrentFrameInfo->markSyncStart(); @@ -391,7 +399,11 @@ void CanvasContext::setTextureAtlas(RenderThread& thread, void CanvasContext::dumpFrames(int fd) { FILE* file = fdopen(fd, "a"); - fprintf(file, "\n\n---PROFILEDATA---"); + fprintf(file, "\n\n---PROFILEDATA---\n"); + for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::kNumIndexes); i++) { + fprintf(file, FrameInfoNames[i].c_str()); + fprintf(file, ","); + } for (size_t i = 0; i < mFrames.size(); i++) { FrameInfo& frame = mFrames[i]; if (frame[FrameInfoIndex::kSyncStart] == 0) { diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index d8a9921c0854..6d9acd429279 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -52,11 +52,12 @@ namespace renderthread { MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \ ARGS(method) *args = (ARGS(method) *) task->payload() -enum class DumpFlags { - kFrameStats = 1 << 0, - kReset = 1 << 1, +namespace DumpFlags { + enum { + FrameStats = 1 << 0, + Reset = 1 << 1, + }; }; -MAKE_FLAGS_ENUM(DumpFlags) CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) { @@ -409,10 +410,10 @@ CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, int fd, int dumpFlags) { args->context->profiler().dumpData(args->fd); args->thread->jankTracker().dump(args->fd); - if (args->dumpFlags & DumpFlags::kFrameStats) { + if (args->dumpFlags & DumpFlags::FrameStats) { args->context->dumpFrames(args->fd); } - if (args->dumpFlags & DumpFlags::kReset) { + if (args->dumpFlags & DumpFlags::Reset) { args->context->resetFrameStats(); } return nullptr; |