summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2015-02-06 15:25:51 -0800
committerChris Craik <ccraik@google.com>2015-02-09 11:04:31 -0800
commit2ab95d780b023152556d9f8659de734ec7b55047 (patch)
tree9739704a8a0a8f16b59d1f04af4a3022b02a1998 /libs/hwui
parent92b2fe5d0d9781d57f3a2520eecc83682e9aa8ed (diff)
downloadframeworks_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.h2
-rw-r--r--libs/hwui/GlopBuilder.cpp50
-rw-r--r--libs/hwui/GlopBuilder.h5
-rw-r--r--libs/hwui/OpenGLRenderer.cpp37
-rw-r--r--libs/hwui/renderstate/MeshState.cpp38
-rw-r--r--libs/hwui/renderstate/MeshState.h1
-rw-r--r--libs/hwui/renderstate/RenderState.cpp39
-rw-r--r--libs/hwui/renderstate/Stencil.h4
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: