diff options
author | Chris Craik <ccraik@google.com> | 2015-02-06 15:25:51 -0800 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2015-02-09 11:04:31 -0800 |
commit | 2ab95d780b023152556d9f8659de734ec7b55047 (patch) | |
tree | 9739704a8a0a8f16b59d1f04af4a3022b02a1998 /libs/hwui | |
parent | 92b2fe5d0d9781d57f3a2520eecc83682e9aa8ed (diff) | |
download | frameworks_base-2ab95d780b023152556d9f8659de734ec7b55047.zip frameworks_base-2ab95d780b023152556d9f8659de734ec7b55047.tar.gz frameworks_base-2ab95d780b023152556d9f8659de734ec7b55047.tar.bz2 |
Glop support for indexed quads
bug:19014311
Change-Id: If35a873421b41cc4508b0d8ac1b4d900c9bb3717
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/Glop.h | 2 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.cpp | 50 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.h | 5 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 37 | ||||
-rw-r--r-- | libs/hwui/renderstate/MeshState.cpp | 38 | ||||
-rw-r--r-- | libs/hwui/renderstate/MeshState.h | 1 | ||||
-rw-r--r-- | libs/hwui/renderstate/RenderState.cpp | 39 | ||||
-rw-r--r-- | libs/hwui/renderstate/Stencil.h | 4 |
8 files changed, 123 insertions, 53 deletions
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h index 9150869..e2adff8 100644 --- a/libs/hwui/Glop.h +++ b/libs/hwui/Glop.h @@ -65,7 +65,7 @@ struct Glop { * Stores mesh - vertex and index data. * * buffer objects and void*s are mutually exclusive - * indices are optional + * indices are optional, currently only GL_UNSIGNED_SHORT supported */ struct Mesh { VertexAttribFlags vertexFlags; diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index e22af40..e0f2ec4 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -78,6 +78,21 @@ GlopBuilder& GlopBuilder::setMeshUnitQuad() { return *this; } +GlopBuilder& GlopBuilder::setMeshIndexedQuads(void* vertexData, int quadCount) { + TRIGGER_STAGE(kMeshStage); + + mOutGlop->mesh.vertexFlags = kNone_Attrib; + mOutGlop->mesh.primitiveMode = GL_TRIANGLES; + mOutGlop->mesh.vertexBufferObject = 0; + mOutGlop->mesh.vertices = vertexData; + mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO(); + mOutGlop->mesh.indices = nullptr; + mOutGlop->mesh.vertexCount = 6 * quadCount; + mOutGlop->mesh.stride = kVertexStride; + + return *this; +} + GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset) { TRIGGER_STAGE(kTransformStage); @@ -90,6 +105,7 @@ GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho, 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; @@ -98,22 +114,42 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) { 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::setPaint(const SkPaint* paint, float alphaScale) { +GlopBuilder& GlopBuilder::setOptionalPaint(const SkPaint* paint, float alphaScale) { + if (paint) { + return setPaint(*paint, alphaScale); + } + TRIGGER_STAGE(kFillStage); - // TODO: support null paint - const SkShader* shader = paint->getShader(); - const SkColorFilter* colorFilter = paint->getColorFilter(); + mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale }; + + const bool SWAP_SRC_DST = false; + // TODO: account for texture blend + if (alphaScale < 1.0f) { + Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST, + &mOutGlop->blend.src, &mOutGlop->blend.dst); + } else { + mOutGlop->blend = { GL_ZERO, GL_ZERO }; + } - SkXfermode::Mode mode = PaintUtils::getXfermode(paint->getXfermode()); + return *this; +} +GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) { + TRIGGER_STAGE(kFillStage); + + const SkShader* shader = paint.getShader(); + const SkColorFilter* colorFilter = paint.getColorFilter(); + + SkXfermode::Mode mode = PaintUtils::getXfermode(paint.getXfermode()); if (mode != SkXfermode::kClear_Mode) { - int color = paint->getColor(); + int color = paint.getColor(); float alpha = (SkColorGetA(color) / 255.0f) * alphaScale; if (!shader) { float colorScale = alpha / 255.0f; @@ -195,6 +231,8 @@ GlopBuilder& GlopBuilder::setPaint(const SkPaint* paint, float alphaScale) { colorVector[1] = srcColorMatrix[9] / 255.0f; colorVector[2] = srcColorMatrix[14] / 255.0f; colorVector[3] = srcColorMatrix[19] / 255.0f; + } else { + LOG_ALWAYS_FATAL("unsupported ColorFilter"); } } else { mOutGlop->fill.filterMode = ProgramDescription::kColorNone; diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index c7464cd..48ce81a 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -36,15 +36,18 @@ class GlopBuilder { PREVENT_COPY_AND_ASSIGN(GlopBuilder); public: GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop); + GlopBuilder& setMeshUnitQuad(); GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp); + GlopBuilder& setMeshIndexedQuads(void* vertexData, int quadCount); GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset); GlopBuilder& setModelViewMapUnitToRect(const Rect destination); GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source); - GlopBuilder& setPaint(const SkPaint* paint, float alphaScale); + GlopBuilder& setOptionalPaint(const SkPaint* paint, float alphaScale); + GlopBuilder& setPaint(const SkPaint& paint, float alphaScale); void build(); private: enum StageFlags { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 5a0cc1e..61cd16f 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1581,7 +1581,12 @@ void OpenGLRenderer::renderGlop(const Glop& glop) { setStencilFromClip(); } mRenderState.render(glop); - dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom); + + if (!mRenderState.stencil().isWriteEnabled()) { + // TODO: specify more clearly when a draw should dirty the layer. + // is writing to the stencil the only time we should ignore this? + dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom); + } } /////////////////////////////////////////////////////////////////////////////// @@ -2353,13 +2358,12 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, aBuilder.setMeshVertexBuffer(vertexBuffer, shadowInterp) .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset) .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) - .setPaint(paint, currentSnapshot()->alpha) + .setPaint(*paint, currentSnapshot()->alpha) .build(); renderGlop(glop); return; } - const VertexBuffer::MeshFeatureFlags meshFeatureFlags = vertexBuffer.getMeshFeatureFlags(); Rect bounds(vertexBuffer.getBounds()); bounds.translate(translateX, translateY); @@ -3218,12 +3222,6 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint return; } - int color = paint->getColor(); - // If a shader is set, preserve only the alpha - if (getShader(paint)) { - color |= 0x00ffffff; - } - float left = FLT_MAX; float top = FLT_MAX; float right = FLT_MIN; @@ -3253,6 +3251,25 @@ void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint return; } + if (!paint->getShader() && !currentSnapshot()->roundRectClipState) { + const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform(); + Glop glop; + GlopBuilder aBuilder(mRenderState, mCaches, &glop); + aBuilder.setMeshIndexedQuads(&mesh[0], count / 4) + .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) + .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom)) + .setPaint(*paint, currentSnapshot()->alpha) + .build(); + renderGlop(glop); + return; + } + + int color = paint->getColor(); + // If a shader is set, preserve only the alpha + if (getShader(paint)) { + color |= 0x00ffffff; + } + setupDraw(); setupDrawNoTexture(); setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha); @@ -3286,7 +3303,7 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot aBuilder.setMeshUnitQuad() .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false) .setModelViewMapUnitToRect(Rect(left, top, right, bottom)) - .setPaint(paint, currentSnapshot()->alpha) + .setPaint(*paint, currentSnapshot()->alpha) .build(); renderGlop(glop); return; diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp index ce6030d..5efac0e 100644 --- a/libs/hwui/renderstate/MeshState.cpp +++ b/libs/hwui/renderstate/MeshState.cpp @@ -31,13 +31,29 @@ MeshState::MeshState() , mCurrentTexCoordsStride(0) , mTexCoordsArrayEnabled(false) , mQuadListIndices(0) { - glGenBuffers(1, &mUnitQuadBuffer); glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW); mCurrentBuffer = mUnitQuadBuffer; + std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]); + for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) { + uint16_t quad = i * 4; + int index = i * 6; + regionIndices[index ] = quad; // top-left + regionIndices[index + 1] = quad + 1; // top-right + regionIndices[index + 2] = quad + 2; // bottom-left + regionIndices[index + 3] = quad + 2; // bottom-left + regionIndices[index + 4] = quad + 1; // top-right + regionIndices[index + 5] = quad + 3; // bottom-right + } + glGenBuffers(1, &mQuadListIndices); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t), + regionIndices.get(), GL_STATIC_DRAW); + mCurrentIndicesBuffer = mQuadListIndices; + // position attribute always enabled glEnableVertexAttribArray(Program::kBindingPosition); } @@ -138,26 +154,6 @@ bool MeshState::bindIndicesBufferInternal(const GLuint buffer) { } bool MeshState::bindQuadIndicesBuffer() { - if (!mQuadListIndices) { - std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]); - for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) { - uint16_t quad = i * 4; - int index = i * 6; - regionIndices[index ] = quad; // top-left - regionIndices[index + 1] = quad + 1; // top-right - regionIndices[index + 2] = quad + 2; // bottom-left - regionIndices[index + 3] = quad + 2; // bottom-left - regionIndices[index + 4] = quad + 1; // top-right - regionIndices[index + 5] = quad + 3; // bottom-right - } - - glGenBuffers(1, &mQuadListIndices); - bool force = bindIndicesBufferInternal(mQuadListIndices); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t), - regionIndices.get(), GL_STATIC_DRAW); - return force; - } - return bindIndicesBufferInternal(mQuadListIndices); } diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h index afc6267..3c92ad8 100644 --- a/libs/hwui/renderstate/MeshState.h +++ b/libs/hwui/renderstate/MeshState.h @@ -114,6 +114,7 @@ public: // Getters - for use in Glop building /////////////////////////////////////////////////////////////////////////////// GLuint getUnitQuadVBO() { return mUnitQuadBuffer; } + GLuint getQuadListIBO() { return mQuadListIndices; } private: MeshState(); bool bindMeshBufferInternal(const GLuint buffer); diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index ba49833..6394dc1 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -204,12 +204,7 @@ void RenderState::postDecStrong(VirtualLightRefBase* object) { * * Textures + coordinates * SkiaShader - * ColorFilter - * - // TODO: texture coord - // TODO: texture support - // TODO: skiashader support - // TODO: color filter support + * RoundRect clipping */ void RenderState::render(const Glop& glop) { @@ -251,18 +246,18 @@ void RenderState::render(const Glop& glop) { // indices meshState().bindIndicesBufferInternal(mesh.indexBufferObject); - if (glop.mesh.vertexFlags & kTextureCoord_Attrib) { + if (mesh.vertexFlags & kTextureCoord_Attrib) { // TODO: support textures LOG_ALWAYS_FATAL("textures not yet supported"); } else { meshState().disableTexCoordsVertexArray(); } - if (glop.mesh.vertexFlags & kColor_Attrib) { + if (mesh.vertexFlags & kColor_Attrib) { LOG_ALWAYS_FATAL("color vertex attribute not yet supported"); // TODO: enable color, disable when done } int alphaSlot = -1; - if (glop.mesh.vertexFlags & kAlpha_Attrib) { + if (mesh.vertexFlags & kAlpha_Attrib) { const void* alphaCoords = ((const GLbyte*) glop.mesh.vertices) + kVertexAlphaOffset; alphaSlot = shader.program->getAttrib("vtxAlpha"); glEnableVertexAttribArray(alphaSlot); @@ -275,15 +270,31 @@ void RenderState::render(const Glop& glop) { blend().setFactors(glop.blend.src, glop.blend.dst); // ------------------------------------ - // ---------- GL state setup ---------- + // ---------- Actual drawing ---------- // ------------------------------------ - if (mesh.indexBufferObject || mesh.indices) { - glDrawElements(glop.mesh.primitiveMode, glop.mesh.vertexCount, - GL_UNSIGNED_SHORT, mesh.indices); + if (mesh.indexBufferObject == meshState().getQuadListIBO()) { + // Since the indexed quad list is of limited length, we loop over + // the glDrawXXX method while updating the vertex pointer + GLsizei elementsCount = mesh.vertexCount; + const GLbyte* vertices = static_cast<const GLbyte*>(mesh.vertices); + while (elementsCount > 0) { + GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6); + + // TODO: this double binds on first pass + meshState().bindPositionVertexPointer(true, vertices, mesh.stride); + glDrawElements(mesh.primitiveMode, drawCount, GL_UNSIGNED_SHORT, nullptr); + elementsCount -= drawCount; + vertices += (drawCount / 6) * 4 * mesh.stride; + } + } else if (mesh.indexBufferObject || mesh.indices) { + glDrawElements(mesh.primitiveMode, mesh.vertexCount, GL_UNSIGNED_SHORT, mesh.indices); } else { - glDrawArrays(glop.mesh.primitiveMode, 0, glop.mesh.vertexCount); + glDrawArrays(mesh.primitiveMode, 0, mesh.vertexCount); } + // ----------------------------------- + // ---------- Mesh teardown ---------- + // ----------------------------------- if (glop.mesh.vertexFlags & kAlpha_Attrib) { glDisableVertexAttribArray(alphaSlot); } diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h index a88beae..e4f0f3f 100644 --- a/libs/hwui/renderstate/Stencil.h +++ b/libs/hwui/renderstate/Stencil.h @@ -98,6 +98,10 @@ public: return mState == kTest; } + bool isWriteEnabled() { + return mState == kWrite; + } + void dump(); private: |