From 53e51e4aa933f9603587e1780f446c18816bf9be Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Mon, 1 Jun 2015 10:35:35 -0700 Subject: [PATCH] Handle shader matrix correctly when ignoring canvas transform bug:20063841 Restores old SkShader matrix behavior from before the Glop refactor. Many drawing operations draw without sending the canvas transform to the GL shader. In such cases, we need to adapt the matrix sent to the SkShader logic to invert the canvas transform that's built into the mesh. Change-Id: I42b6f59df36ce46436322b95bf9ad2140795ee58 --- libs/hwui/FontRenderer.cpp | 15 ++-- libs/hwui/Glop.h | 47 ++++++++++--- libs/hwui/GlopBuilder.cpp | 91 +++++++++++++----------- libs/hwui/GlopBuilder.h | 24 ++++--- libs/hwui/OpenGLRenderer.cpp | 97 +++++++++++++++----------- libs/hwui/OpenGLRenderer.h | 17 +++-- libs/hwui/SkiaShader.cpp | 15 ++-- libs/hwui/SkiaShader.h | 2 +- libs/hwui/renderstate/RenderState.cpp | 16 ++--- libs/hwui/renderthread/RenderProxy.cpp | 13 ++-- 10 files changed, 204 insertions(+), 133 deletions(-) diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index c79ae777d051c..9664f58b1752e 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(texture.getFormat() == GL_ALPHA - ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); - if (linearFiltering) { - textureFillFlags |= TextureFillFlags::kForceFilter; + int textureFillFlags = TextureFillFlags::None; + if (texture.getFormat() == GL_ALPHA) { + textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; } - const Matrix4& transform = pureTranslate ? Matrix4::identity() : *(renderer->currentTransform()); + if (linearFiltering) { + textureFillFlags |= TextureFillFlags::ForceFilter; + } + 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/Glop.h b/libs/hwui/Glop.h index 2c6f6c120d168..fa20b0807a881 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 e25f81eaa8af2..b7cdaa2abc81d 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(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(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(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(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(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(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(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(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 b335a2c5a25e1..549bb21e5f8d5 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 8f916202e9e6b..576937655f7af 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(rect.getWidth()) + const bool tryToSnap = layer->getWidth() == static_cast(rect.getWidth()) && layer->getHeight() == static_cast(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((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((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(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((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(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(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 8dae82c5b114f..29fbf0c985d75 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 composeLayerRect(Layer* layer, const Rect& rect, bool swap = false); + void composeLayerRectSwapped(Layer* layer, const Rect& rect); + + /** + * Draws the content in layer to the screen. + */ + 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 ecf8b6ba82198..2cfb9e1dc8c19 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 5b8aa86aaf5f4..884196d9fc628 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 df12e63017f49..3ebd57b33c810 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/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index d8a9921c08541..6d9acd429279a 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;