Loading libs/hwui/DisplayListOp.h +2 −1 Original line number Diff line number Diff line Loading @@ -668,7 +668,8 @@ public: } virtual void output(int level, uint32_t logFlags) const override { OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top, OP_LOG("Draw bitmap %p of size %dx%d%s", mBitmap, mBitmap->width(), mBitmap->height(), mEntry ? " using AssetAtlas" : ""); } Loading libs/hwui/FloatColor.h 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FLOATCOLOR_H #define FLOATCOLOR_H #include "utils/Macros.h" namespace android { namespace uirenderer { struct FloatColor { float r; float g; float b; float a; }; REQUIRE_COMPATIBLE_LAYOUT(FloatColor); } /* namespace uirenderer */ } /* namespace android */ #endif /* FLOATCOLOR_H */ libs/hwui/Glop.h +17 −8 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef ANDROID_HWUI_GLOP_H #define ANDROID_HWUI_GLOP_H #include "FloatColor.h" #include "Matrix.h" #include "Rect.h" #include "utils/Macros.h" Loading @@ -29,6 +30,7 @@ namespace android { namespace uirenderer { class Program; class RoundRectClipState; /* * Enumerates optional vertex attributes Loading @@ -44,22 +46,23 @@ enum VertexAttribFlags { kAlpha_Attrib = 1 << 2, }; /** * Structure containing all data required to issue a single OpenGL draw * Structure containing all data required to issue an OpenGL draw * * Includes all of the mesh, fill, and GL state required to perform * the operation. Pieces of data are either directly copied into the * structure, or stored as a pointer or GL object reference to data * managed * managed. * * Eventually, a Glop should be able to be drawn multiple times from * a single construction, up until GL context destruction. Currently, * vertex/index/Texture/RoundRectClipState pointers prevent this from * being safe. */ // TODO: PREVENT_COPY_AND_ASSIGN(...) or similar struct Glop { struct FloatColor { float a, r, g, b; }; Rect bounds; const RoundRectClipState* roundRectClipState; /* * Stores mesh - vertex and index data. Loading @@ -74,12 +77,18 @@ struct Glop { GLuint indexBufferObject; const void* vertices; const void* indices; int vertexCount; int elementCount; GLsizei stride; GLvoid* texCoordOffset; TextureVertex mappedVertices[4]; } mesh; struct Fill { Program* program; Texture* texture; GLenum textureFilter; bool colorEnabled; FloatColor color; /* TODO Loading libs/hwui/GlopBuilder.cpp +208 −83 Original line number Diff line number Diff line Loading @@ -33,12 +33,19 @@ namespace uirenderer { #define TRIGGER_STAGE(stageFlag) \ LOG_ALWAYS_FATAL_IF(stageFlag & mStageFlags, "Stage %d cannot be run twice"); \ mStageFlags = static_cast<StageFlags>(mStageFlags | stageFlag) mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag)) #define REQUIRE_STAGES(requiredFlags) \ LOG_ALWAYS_FATAL_IF((mStageFlags & requiredFlags) != requiredFlags, \ LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \ "not prepared for current stage") static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {; TextureVertex::setUV(quadVertex++, uvs.left, uvs.top); TextureVertex::setUV(quadVertex++, uvs.right, uvs.top); TextureVertex::setUV(quadVertex++, uvs.left, uvs.bottom); TextureVertex::setUV(quadVertex++, uvs.right, uvs.bottom); } GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop) : mRenderState(renderState) , mCaches(caches) Loading @@ -46,39 +53,52 @@ GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop mStageFlags = kInitialStage; } GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) { TRIGGER_STAGE(kMeshStage); //////////////////////////////////////////////////////////////////////////////// // Mesh //////////////////////////////////////////////////////////////////////////////// const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags(); GlopBuilder& GlopBuilder::setMeshUnitQuad() { TRIGGER_STAGE(kMeshStage); bool alphaVertex = flags & VertexBuffer::kAlpha; bool indices = flags & VertexBuffer::kIndices; mOutGlop->mesh.vertexFlags = alphaVertex ? kAlpha_Attrib : kNone_Attrib; mOutGlop->mesh.vertexFlags = kNone_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; mOutGlop->mesh.vertexBufferObject = 0; mOutGlop->mesh.vertices = vertexBuffer.getBuffer(); mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); mOutGlop->mesh.vertices = nullptr; mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = vertexBuffer.getIndices(); mOutGlop->mesh.vertexCount = indices ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount(); mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride; mDescription.hasVertexAlpha = alphaVertex; mDescription.useShadowAlphaInterp = shadowInterp; mOutGlop->mesh.indices = nullptr; mOutGlop->mesh.elementCount = 4; mOutGlop->mesh.stride = kTextureVertexStride; mOutGlop->mesh.texCoordOffset = nullptr; return *this; } GlopBuilder& GlopBuilder::setMeshUnitQuad() { GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper, bool isAlphaMaskTexture) { TRIGGER_STAGE(kMeshStage); mOutGlop->mesh.vertexFlags = kNone_Attrib; mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; if (CC_UNLIKELY(uvMapper)) { Rect uvs(0, 0, 1, 1); uvMapper->map(uvs); setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]); mOutGlop->mesh.vertexBufferObject = 0; mOutGlop->mesh.vertices = &mOutGlop->mesh.mappedVertices[0]; } else { // standard UV coordinates, use regular unit quad VBO mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); mOutGlop->mesh.vertices = nullptr; } mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = nullptr; mOutGlop->mesh.vertexCount = 4; mOutGlop->mesh.elementCount = 4; mOutGlop->mesh.stride = kTextureVertexStride; mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset; mDescription.hasTexture = true; mDescription.hasAlpha8Texture = isAlphaMaskTexture; return *this; } Loading @@ -91,92 +111,64 @@ GlopBuilder& GlopBuilder::setMeshIndexedQuads(void* vertexData, int quadCount) { mOutGlop->mesh.vertices = vertexData; mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO(); mOutGlop->mesh.indices = nullptr; mOutGlop->mesh.vertexCount = 6 * quadCount; mOutGlop->mesh.elementCount = 6 * quadCount; mOutGlop->mesh.stride = kVertexStride; mOutGlop->mesh.texCoordOffset = nullptr; return *this; } GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset) { TRIGGER_STAGE(kTransformStage); mOutGlop->transform.ortho.load(ortho); mOutGlop->transform.canvas.load(transform); mOutGlop->transform.fudgingOffset = fudgingOffset; return *this; } GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) { TRIGGER_STAGE(kModelViewStage); GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) { TRIGGER_STAGE(kMeshStage); mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->bounds = destination; return *this; } const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags(); GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) { TRIGGER_STAGE(kModelViewStage); bool alphaVertex = flags & VertexBuffer::kAlpha; bool indices = flags & VertexBuffer::kIndices; mOutGlop->mesh.vertexFlags = alphaVertex ? kAlpha_Attrib : kNone_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; mOutGlop->mesh.vertexBufferObject = 0; mOutGlop->mesh.vertices = vertexBuffer.getBuffer(); mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = vertexBuffer.getIndices(); mOutGlop->mesh.elementCount = indices ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount(); mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride; mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); mOutGlop->bounds = source; mOutGlop->bounds.translate(offsetX, offsetY); mDescription.hasVertexAlpha = alphaVertex; mDescription.useShadowAlphaInterp = shadowInterp; return *this; } GlopBuilder& GlopBuilder::setOptionalPaint(const SkPaint* paint, float alphaScale) { if (paint) { return setPaint(*paint, alphaScale); } TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; const bool SWAP_SRC_DST = false; // TODO: account for texture blend if (alphaScale < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)) { Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, &mOutGlop->blend.src, &mOutGlop->blend.dst); } else { mOutGlop->blend = { GL_ZERO, GL_ZERO }; } return *this; } GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); //////////////////////////////////////////////////////////////////////////////// // Fill //////////////////////////////////////////////////////////////////////////////// const SkShader* shader = paint.getShader(); const SkColorFilter* colorFilter = paint.getColorFilter(); SkXfermode::Mode mode = PaintUtils::getXfermode(paint.getXfermode()); void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode, const SkShader* shader, const SkColorFilter* colorFilter) { if (mode != SkXfermode::kClear_Mode) { int color = paint.getColor(); float alpha = (SkColorGetA(color) / 255.0f) * alphaScale; if (!shader) { float colorScale = alpha / 255.0f; mOutGlop->fill.color = { alpha, colorScale * SkColorGetR(color), colorScale * SkColorGetG(color), colorScale * SkColorGetB(color) colorScale * SkColorGetB(color), alpha }; } else { mOutGlop->fill.color = { alpha, 1, 1, 1 }; mOutGlop->fill.color = { 1, 1, 1, alpha }; } } else { mOutGlop->fill.color = { 1, 0, 0, 0 }; mOutGlop->fill.color = { 0, 0, 0, 1 }; } const bool SWAP_SRC_DST = false; mOutGlop->blend = { GL_ZERO, GL_ZERO }; if (mOutGlop->fill.color.a < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib) || (mOutGlop->fill.texture && mOutGlop->fill.texture->blend) || mOutGlop->roundRectClipState || PaintUtils::isBlendedShader(shader) || PaintUtils::isBlendedColorFilter(colorFilter) || mode != SkXfermode::kSrcOver_Mode) { Loading Loading @@ -218,10 +210,10 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { const float alpha = SkColorGetA(color) / 255.0f; float colorScale = alpha / 255.0f; mOutGlop->fill.filter.color = { alpha, colorScale * SkColorGetR(color), colorScale * SkColorGetG(color), colorScale * SkColorGetB(color), alpha, }; } else if (colorFilter->asColorMatrix(srcColorMatrix)) { mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix; Loading @@ -245,18 +237,151 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { } else { mOutGlop->fill.filterMode = ProgramDescription::kColorNone; } } GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture, const SkPaint* paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); mOutGlop->fill.texture = &texture; mOutGlop->fill.textureFilter = PaintUtils::getFilter(paint); if (paint) { int color = paint->getColor(); SkShader* shader = paint->getShader(); if (!isAlphaMaskTexture) { // Texture defines color, so disable shaders, and reset all non-alpha color channels color |= 0x00FFFFFF; shader = nullptr; } setFill(color, alphaScale, PaintUtils::getXfermode(paint->getXfermode()), shader, paint->getColorFilter()); } else { mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; const bool SWAP_SRC_DST = false; if (alphaScale < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib) || texture.blend || mOutGlop->roundRectClipState) { Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, &mOutGlop->blend.src, &mOutGlop->blend.dst); } else { mOutGlop->blend = { GL_ZERO, GL_ZERO }; } } if (isAlphaMaskTexture) { mDescription.modulate = mOutGlop->fill.color.a < 1.0f || mOutGlop->fill.color.r > 0.0f || mOutGlop->fill.color.g > 0.0f || mOutGlop->fill.color.b > 0.0f; } else { mDescription.modulate = mOutGlop->fill.color.a < 1.0f; } return *this; } GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); mOutGlop->fill.texture = nullptr; mOutGlop->fill.textureFilter = GL_NEAREST; setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()), paint.getShader(), paint.getColorFilter()); mDescription.modulate = mOutGlop->fill.color.a < 1.0f; return *this; } //////////////////////////////////////////////////////////////////////////////// // Transform //////////////////////////////////////////////////////////////////////////////// GlopBuilder& GlopBuilder::setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset) { TRIGGER_STAGE(kTransformStage); mOutGlop->transform.ortho.load(ortho); mOutGlop->transform.canvas.load(transform); mOutGlop->transform.fudgingOffset = fudgingOffset; return *this; } //////////////////////////////////////////////////////////////////////////////// // ModelView //////////////////////////////////////////////////////////////////////////////// GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) { TRIGGER_STAGE(kModelViewStage); mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->bounds = destination; return *this; } GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) { TRIGGER_STAGE(kModelViewStage); REQUIRE_STAGES(kTransformStage | kFillStage); float left = destination.left; float top = destination.top; const Matrix4& canvasTransform = mOutGlop->transform.canvas; if (CC_LIKELY(canvasTransform.isPureTranslate())) { const float translateX = canvasTransform.getTranslateX(); const float translateY = canvasTransform.getTranslateY(); left = (int) floorf(left + translateX + 0.5f) - translateX; top = (int) floorf(top + translateY + 0.5f) - translateY; mOutGlop->fill.textureFilter = GL_NEAREST; } mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->bounds = destination; return *this; } GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) { TRIGGER_STAGE(kModelViewStage); mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); mOutGlop->bounds = source; mOutGlop->bounds.translate(offsetX, offsetY); return *this; } GlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundRectClipState) { TRIGGER_STAGE(kRoundRectClipStage); mOutGlop->roundRectClipState = roundRectClipState; mDescription.hasRoundRectClip = roundRectClipState != nullptr; return *this; } //////////////////////////////////////////////////////////////////////////////// // Build //////////////////////////////////////////////////////////////////////////////// void GlopBuilder::build() { REQUIRE_STAGES(kAllStages); mDescription.modulate = mOutGlop->fill.color.a < 1.0f; mOutGlop->fill.program = mCaches.programCache.get(mDescription); mOutGlop->transform.canvas.mapRect(mOutGlop->bounds); // duplicates ProgramCache's definition of color uniform presence const bool singleColor = !mDescription.hasTexture && !mDescription.hasExternalTexture && !mDescription.hasGradient && !mDescription.hasBitmap; mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor; } } /* namespace uirenderer */ } /* namespace android */ libs/hwui/GlopBuilder.h +14 −4 Original line number Diff line number Diff line Loading @@ -38,25 +38,35 @@ public: GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop); GlopBuilder& setMeshUnitQuad(); GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper, bool isAlphaMaskTexture); GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp); GlopBuilder& setMeshIndexedQuads(void* vertexData, int quadCount); GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale); GlopBuilder& setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture, const SkPaint* paint, float alphaScale); GlopBuilder& setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); GlopBuilder& setModelViewMapUnitToRect(const Rect destination); GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination); GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source); GlopBuilder& setOptionalPaint(const SkPaint* paint, float alphaScale); GlopBuilder& setPaint(const SkPaint& paint, float alphaScale); GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState); void build(); private: void setFill(int color, float alphaScale, SkXfermode::Mode mode, const SkShader* shader, const SkColorFilter* colorFilter); enum StageFlags { kInitialStage = 0, kMeshStage = 1 << 0, kTransformStage = 1 << 1, kModelViewStage = 1 << 2, kFillStage = 1 << 3, kAllStages = kMeshStage | kTransformStage | kModelViewStage | kFillStage, kRoundRectClipStage = 1 << 4, kAllStages = kMeshStage | kFillStage | kTransformStage | kModelViewStage | kRoundRectClipStage, } mStageFlags; ProgramDescription mDescription; Loading Loading
libs/hwui/DisplayListOp.h +2 −1 Original line number Diff line number Diff line Loading @@ -668,7 +668,8 @@ public: } virtual void output(int level, uint32_t logFlags) const override { OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top, OP_LOG("Draw bitmap %p of size %dx%d%s", mBitmap, mBitmap->width(), mBitmap->height(), mEntry ? " using AssetAtlas" : ""); } Loading
libs/hwui/FloatColor.h 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FLOATCOLOR_H #define FLOATCOLOR_H #include "utils/Macros.h" namespace android { namespace uirenderer { struct FloatColor { float r; float g; float b; float a; }; REQUIRE_COMPATIBLE_LAYOUT(FloatColor); } /* namespace uirenderer */ } /* namespace android */ #endif /* FLOATCOLOR_H */
libs/hwui/Glop.h +17 −8 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef ANDROID_HWUI_GLOP_H #define ANDROID_HWUI_GLOP_H #include "FloatColor.h" #include "Matrix.h" #include "Rect.h" #include "utils/Macros.h" Loading @@ -29,6 +30,7 @@ namespace android { namespace uirenderer { class Program; class RoundRectClipState; /* * Enumerates optional vertex attributes Loading @@ -44,22 +46,23 @@ enum VertexAttribFlags { kAlpha_Attrib = 1 << 2, }; /** * Structure containing all data required to issue a single OpenGL draw * Structure containing all data required to issue an OpenGL draw * * Includes all of the mesh, fill, and GL state required to perform * the operation. Pieces of data are either directly copied into the * structure, or stored as a pointer or GL object reference to data * managed * managed. * * Eventually, a Glop should be able to be drawn multiple times from * a single construction, up until GL context destruction. Currently, * vertex/index/Texture/RoundRectClipState pointers prevent this from * being safe. */ // TODO: PREVENT_COPY_AND_ASSIGN(...) or similar struct Glop { struct FloatColor { float a, r, g, b; }; Rect bounds; const RoundRectClipState* roundRectClipState; /* * Stores mesh - vertex and index data. Loading @@ -74,12 +77,18 @@ struct Glop { GLuint indexBufferObject; const void* vertices; const void* indices; int vertexCount; int elementCount; GLsizei stride; GLvoid* texCoordOffset; TextureVertex mappedVertices[4]; } mesh; struct Fill { Program* program; Texture* texture; GLenum textureFilter; bool colorEnabled; FloatColor color; /* TODO Loading
libs/hwui/GlopBuilder.cpp +208 −83 Original line number Diff line number Diff line Loading @@ -33,12 +33,19 @@ namespace uirenderer { #define TRIGGER_STAGE(stageFlag) \ LOG_ALWAYS_FATAL_IF(stageFlag & mStageFlags, "Stage %d cannot be run twice"); \ mStageFlags = static_cast<StageFlags>(mStageFlags | stageFlag) mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag)) #define REQUIRE_STAGES(requiredFlags) \ LOG_ALWAYS_FATAL_IF((mStageFlags & requiredFlags) != requiredFlags, \ LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \ "not prepared for current stage") static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {; TextureVertex::setUV(quadVertex++, uvs.left, uvs.top); TextureVertex::setUV(quadVertex++, uvs.right, uvs.top); TextureVertex::setUV(quadVertex++, uvs.left, uvs.bottom); TextureVertex::setUV(quadVertex++, uvs.right, uvs.bottom); } GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop) : mRenderState(renderState) , mCaches(caches) Loading @@ -46,39 +53,52 @@ GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop mStageFlags = kInitialStage; } GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) { TRIGGER_STAGE(kMeshStage); //////////////////////////////////////////////////////////////////////////////// // Mesh //////////////////////////////////////////////////////////////////////////////// const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags(); GlopBuilder& GlopBuilder::setMeshUnitQuad() { TRIGGER_STAGE(kMeshStage); bool alphaVertex = flags & VertexBuffer::kAlpha; bool indices = flags & VertexBuffer::kIndices; mOutGlop->mesh.vertexFlags = alphaVertex ? kAlpha_Attrib : kNone_Attrib; mOutGlop->mesh.vertexFlags = kNone_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; mOutGlop->mesh.vertexBufferObject = 0; mOutGlop->mesh.vertices = vertexBuffer.getBuffer(); mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); mOutGlop->mesh.vertices = nullptr; mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = vertexBuffer.getIndices(); mOutGlop->mesh.vertexCount = indices ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount(); mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride; mDescription.hasVertexAlpha = alphaVertex; mDescription.useShadowAlphaInterp = shadowInterp; mOutGlop->mesh.indices = nullptr; mOutGlop->mesh.elementCount = 4; mOutGlop->mesh.stride = kTextureVertexStride; mOutGlop->mesh.texCoordOffset = nullptr; return *this; } GlopBuilder& GlopBuilder::setMeshUnitQuad() { GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper, bool isAlphaMaskTexture) { TRIGGER_STAGE(kMeshStage); mOutGlop->mesh.vertexFlags = kNone_Attrib; mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; if (CC_UNLIKELY(uvMapper)) { Rect uvs(0, 0, 1, 1); uvMapper->map(uvs); setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]); mOutGlop->mesh.vertexBufferObject = 0; mOutGlop->mesh.vertices = &mOutGlop->mesh.mappedVertices[0]; } else { // standard UV coordinates, use regular unit quad VBO mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO(); mOutGlop->mesh.vertices = nullptr; } mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = nullptr; mOutGlop->mesh.vertexCount = 4; mOutGlop->mesh.elementCount = 4; mOutGlop->mesh.stride = kTextureVertexStride; mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset; mDescription.hasTexture = true; mDescription.hasAlpha8Texture = isAlphaMaskTexture; return *this; } Loading @@ -91,92 +111,64 @@ GlopBuilder& GlopBuilder::setMeshIndexedQuads(void* vertexData, int quadCount) { mOutGlop->mesh.vertices = vertexData; mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO(); mOutGlop->mesh.indices = nullptr; mOutGlop->mesh.vertexCount = 6 * quadCount; mOutGlop->mesh.elementCount = 6 * quadCount; mOutGlop->mesh.stride = kVertexStride; mOutGlop->mesh.texCoordOffset = nullptr; return *this; } GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset) { TRIGGER_STAGE(kTransformStage); mOutGlop->transform.ortho.load(ortho); mOutGlop->transform.canvas.load(transform); mOutGlop->transform.fudgingOffset = fudgingOffset; return *this; } GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) { TRIGGER_STAGE(kModelViewStage); GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) { TRIGGER_STAGE(kMeshStage); mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->bounds = destination; return *this; } const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags(); GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) { TRIGGER_STAGE(kModelViewStage); bool alphaVertex = flags & VertexBuffer::kAlpha; bool indices = flags & VertexBuffer::kIndices; mOutGlop->mesh.vertexFlags = alphaVertex ? kAlpha_Attrib : kNone_Attrib; mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP; mOutGlop->mesh.vertexBufferObject = 0; mOutGlop->mesh.vertices = vertexBuffer.getBuffer(); mOutGlop->mesh.indexBufferObject = 0; mOutGlop->mesh.indices = vertexBuffer.getIndices(); mOutGlop->mesh.elementCount = indices ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount(); mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride; mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); mOutGlop->bounds = source; mOutGlop->bounds.translate(offsetX, offsetY); mDescription.hasVertexAlpha = alphaVertex; mDescription.useShadowAlphaInterp = shadowInterp; return *this; } GlopBuilder& GlopBuilder::setOptionalPaint(const SkPaint* paint, float alphaScale) { if (paint) { return setPaint(*paint, alphaScale); } TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; const bool SWAP_SRC_DST = false; // TODO: account for texture blend if (alphaScale < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)) { Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, &mOutGlop->blend.src, &mOutGlop->blend.dst); } else { mOutGlop->blend = { GL_ZERO, GL_ZERO }; } return *this; } GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); //////////////////////////////////////////////////////////////////////////////// // Fill //////////////////////////////////////////////////////////////////////////////// const SkShader* shader = paint.getShader(); const SkColorFilter* colorFilter = paint.getColorFilter(); SkXfermode::Mode mode = PaintUtils::getXfermode(paint.getXfermode()); void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode, const SkShader* shader, const SkColorFilter* colorFilter) { if (mode != SkXfermode::kClear_Mode) { int color = paint.getColor(); float alpha = (SkColorGetA(color) / 255.0f) * alphaScale; if (!shader) { float colorScale = alpha / 255.0f; mOutGlop->fill.color = { alpha, colorScale * SkColorGetR(color), colorScale * SkColorGetG(color), colorScale * SkColorGetB(color) colorScale * SkColorGetB(color), alpha }; } else { mOutGlop->fill.color = { alpha, 1, 1, 1 }; mOutGlop->fill.color = { 1, 1, 1, alpha }; } } else { mOutGlop->fill.color = { 1, 0, 0, 0 }; mOutGlop->fill.color = { 0, 0, 0, 1 }; } const bool SWAP_SRC_DST = false; mOutGlop->blend = { GL_ZERO, GL_ZERO }; if (mOutGlop->fill.color.a < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib) || (mOutGlop->fill.texture && mOutGlop->fill.texture->blend) || mOutGlop->roundRectClipState || PaintUtils::isBlendedShader(shader) || PaintUtils::isBlendedColorFilter(colorFilter) || mode != SkXfermode::kSrcOver_Mode) { Loading Loading @@ -218,10 +210,10 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { const float alpha = SkColorGetA(color) / 255.0f; float colorScale = alpha / 255.0f; mOutGlop->fill.filter.color = { alpha, colorScale * SkColorGetR(color), colorScale * SkColorGetG(color), colorScale * SkColorGetB(color), alpha, }; } else if (colorFilter->asColorMatrix(srcColorMatrix)) { mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix; Loading @@ -245,18 +237,151 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { } else { mOutGlop->fill.filterMode = ProgramDescription::kColorNone; } } GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture, const SkPaint* paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); mOutGlop->fill.texture = &texture; mOutGlop->fill.textureFilter = PaintUtils::getFilter(paint); if (paint) { int color = paint->getColor(); SkShader* shader = paint->getShader(); if (!isAlphaMaskTexture) { // Texture defines color, so disable shaders, and reset all non-alpha color channels color |= 0x00FFFFFF; shader = nullptr; } setFill(color, alphaScale, PaintUtils::getXfermode(paint->getXfermode()), shader, paint->getColorFilter()); } else { mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; const bool SWAP_SRC_DST = false; if (alphaScale < 1.0f || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib) || texture.blend || mOutGlop->roundRectClipState) { Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, &mOutGlop->blend.src, &mOutGlop->blend.dst); } else { mOutGlop->blend = { GL_ZERO, GL_ZERO }; } } if (isAlphaMaskTexture) { mDescription.modulate = mOutGlop->fill.color.a < 1.0f || mOutGlop->fill.color.r > 0.0f || mOutGlop->fill.color.g > 0.0f || mOutGlop->fill.color.b > 0.0f; } else { mDescription.modulate = mOutGlop->fill.color.a < 1.0f; } return *this; } GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage); mOutGlop->fill.texture = nullptr; mOutGlop->fill.textureFilter = GL_NEAREST; setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()), paint.getShader(), paint.getColorFilter()); mDescription.modulate = mOutGlop->fill.color.a < 1.0f; return *this; } //////////////////////////////////////////////////////////////////////////////// // Transform //////////////////////////////////////////////////////////////////////////////// GlopBuilder& GlopBuilder::setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset) { TRIGGER_STAGE(kTransformStage); mOutGlop->transform.ortho.load(ortho); mOutGlop->transform.canvas.load(transform); mOutGlop->transform.fudgingOffset = fudgingOffset; return *this; } //////////////////////////////////////////////////////////////////////////////// // ModelView //////////////////////////////////////////////////////////////////////////////// GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) { TRIGGER_STAGE(kModelViewStage); mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->bounds = destination; return *this; } GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) { TRIGGER_STAGE(kModelViewStage); REQUIRE_STAGES(kTransformStage | kFillStage); float left = destination.left; float top = destination.top; const Matrix4& canvasTransform = mOutGlop->transform.canvas; if (CC_LIKELY(canvasTransform.isPureTranslate())) { const float translateX = canvasTransform.getTranslateX(); const float translateY = canvasTransform.getTranslateY(); left = (int) floorf(left + translateX + 0.5f) - translateX; top = (int) floorf(top + translateY + 0.5f) - translateY; mOutGlop->fill.textureFilter = GL_NEAREST; } mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); mOutGlop->bounds = destination; return *this; } GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) { TRIGGER_STAGE(kModelViewStage); mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); mOutGlop->bounds = source; mOutGlop->bounds.translate(offsetX, offsetY); return *this; } GlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundRectClipState) { TRIGGER_STAGE(kRoundRectClipStage); mOutGlop->roundRectClipState = roundRectClipState; mDescription.hasRoundRectClip = roundRectClipState != nullptr; return *this; } //////////////////////////////////////////////////////////////////////////////// // Build //////////////////////////////////////////////////////////////////////////////// void GlopBuilder::build() { REQUIRE_STAGES(kAllStages); mDescription.modulate = mOutGlop->fill.color.a < 1.0f; mOutGlop->fill.program = mCaches.programCache.get(mDescription); mOutGlop->transform.canvas.mapRect(mOutGlop->bounds); // duplicates ProgramCache's definition of color uniform presence const bool singleColor = !mDescription.hasTexture && !mDescription.hasExternalTexture && !mDescription.hasGradient && !mDescription.hasBitmap; mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor; } } /* namespace uirenderer */ } /* namespace android */
libs/hwui/GlopBuilder.h +14 −4 Original line number Diff line number Diff line Loading @@ -38,25 +38,35 @@ public: GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop); GlopBuilder& setMeshUnitQuad(); GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper, bool isAlphaMaskTexture); GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp); GlopBuilder& setMeshIndexedQuads(void* vertexData, int quadCount); GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale); GlopBuilder& setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture, const SkPaint* paint, float alphaScale); GlopBuilder& setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); GlopBuilder& setModelViewMapUnitToRect(const Rect destination); GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination); GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source); GlopBuilder& setOptionalPaint(const SkPaint* paint, float alphaScale); GlopBuilder& setPaint(const SkPaint& paint, float alphaScale); GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState); void build(); private: void setFill(int color, float alphaScale, SkXfermode::Mode mode, const SkShader* shader, const SkColorFilter* colorFilter); enum StageFlags { kInitialStage = 0, kMeshStage = 1 << 0, kTransformStage = 1 << 1, kModelViewStage = 1 << 2, kFillStage = 1 << 3, kAllStages = kMeshStage | kTransformStage | kModelViewStage | kFillStage, kRoundRectClipStage = 1 << 4, kAllStages = kMeshStage | kFillStage | kTransformStage | kModelViewStage | kRoundRectClipStage, } mStageFlags; ProgramDescription mDescription; Loading