diff options
author | Chet Haase <chet@google.com> | 2011-04-21 11:52:59 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-04-21 11:52:59 -0700 |
commit | bf96c356c02c430153c281fb81dc1a00f7ad0b43 (patch) | |
tree | ae1ac4bbd2c2c28b1b498dc87d47564806155c3a /libs | |
parent | 52c03d2cb9a782366e804d1910a7c8f072b05353 (diff) | |
parent | 5b0200bd47e8a9a4dc8d2e6c3a110d522b30bf82 (diff) | |
download | frameworks_base-bf96c356c02c430153c281fb81dc1a00f7ad0b43.zip frameworks_base-bf96c356c02c430153c281fb81dc1a00f7ad0b43.tar.gz frameworks_base-bf96c356c02c430153c281fb81dc1a00f7ad0b43.tar.bz2 |
Merge "Enable anti-aliasing for hw-accelerated lines"
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Caches.h | 3 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 289 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 16 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 38 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.h | 6 | ||||
-rw-r--r-- | libs/hwui/Vertex.h | 28 |
6 files changed, 294 insertions, 86 deletions
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 7d02cf8..faecadd 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -60,7 +60,10 @@ static const TextureVertex gMeshVertices[] = { FV(1.0f, 1.0f, 1.0f, 1.0f) }; static const GLsizei gMeshStride = sizeof(TextureVertex); +static const GLsizei gVertexStride = sizeof(Vertex); +static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex); static const GLsizei gMeshTextureOffset = 2 * sizeof(float); +static const GLsizei gVertexAlphaOffset = 2 * sizeof(float); static const GLsizei gMeshCount = 4; /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 6fabbef..7f28959 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -882,6 +882,10 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { mDescription.hasAlpha8Texture = isAlpha8; } +void OpenGLRenderer::setupDrawAALine() { + mDescription.hasWidth = true; +} + void OpenGLRenderer::setupDrawPoint(float pointSize) { mDescription.isPoint = true; mDescription.pointSize = pointSize; @@ -893,6 +897,7 @@ void OpenGLRenderer::setupDrawColor(int color) { void OpenGLRenderer::setupDrawColor(int color, int alpha) { mColorA = alpha / 255.0f; + // BUG on this next line? a is alpha divided by 255 *twice* const float a = mColorA / 255.0f; mColorR = a * ((color >> 16) & 0xFF); mColorG = a * ((color >> 8) & 0xFF); @@ -1060,6 +1065,37 @@ void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint v } } +void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) { + mCaches.unbindMeshBuffer(); + glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, + gVertexStride, vertices); +} + +/** + * Sets up the shader to draw an AA line. We draw AA lines with quads, where there is an + * outer boundary that fades out to 0. The variables set in the shader define the width of the + * core line primitive ("width") and the width of the fading boundary ("boundaryWidth"). The + * "vtxDistance" attribute (one per vertex) is a value from zero to one that tells the fragment + * shader where the fragment is in relation to the line width overall; this value is then used + * to compute the proper color, based on whether the fragment lies in the fading AA region of + * the line. + */ +void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth) { + mCaches.unbindMeshBuffer(); + glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, + gAlphaVertexStride, vertices); + int distanceSlot = mCaches.currentProgram->getAttrib("vtxDistance"); + glEnableVertexAttribArray(distanceSlot); + glVertexAttribPointer(distanceSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, distanceCoords); + int widthSlot = mCaches.currentProgram->getUniform("width"); + int boundaryWidthSlot = mCaches.currentProgram->getUniform("boundaryWidth"); + int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth"); + float boundaryWidth = (1 - strokeWidth) / 2; + glUniform1f(widthSlot, strokeWidth); + glUniform1f(boundaryWidthSlot, boundaryWidth); + glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidth)); +} + void OpenGLRenderer::finishDrawTexture() { glDisableVertexAttribArray(mTexCoordsSlot); } @@ -1350,114 +1386,199 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int } } +void OpenGLRenderer::drawLinesAsQuads(float *points, int count, bool isAA, bool isHairline, + float strokeWidth) { + int verticesCount = count; + if (count > 4) { + // Polyline: account for extra vertices needed for continous tri-strip + verticesCount += (count -4); + } + if (isAA) { + // Expand boundary to enable AA calculations on the quad border + strokeWidth += .5f; + } + Vertex lines[verticesCount]; + Vertex* vertices = &lines[0]; + AlphaVertex wLines[verticesCount]; + AlphaVertex* aaVertices = &wLines[0]; + if (!isAA) { + setupDrawVertices(vertices); + } else { + void *alphaCoords = ((void*) aaVertices) + gVertexAlphaOffset; + // innerProportion is the ratio of the inner (non-AA) port of the line to the total + // AA stroke width (the base stroke width expanded by a half pixel on either side). + // This value is used in the fragment shader to determine how to fill fragments. + float innerProportion = fmax(strokeWidth - 1.0f, 0) / (strokeWidth + .5f); + setupDrawAALine((void*) aaVertices, (void*) alphaCoords, innerProportion); + } + + int generatedVerticesCount = 0; + AlphaVertex *prevAAVertex = NULL; + Vertex *prevVertex = NULL; + float inverseScaleX, inverseScaleY; + if (isHairline) { + // The quad that we use for AA hairlines needs to account for scaling because the line + // should always be one pixel wide regardless of scale. + inverseScaleX = 1.0f; + inverseScaleY = 1.0f; + if (!mSnapshot->transform->isPureTranslate()) { + Matrix4 *mat = mSnapshot->transform; + float m00 = mat->data[Matrix4::kScaleX]; + float m01 = mat->data[Matrix4::kSkewY]; + float m02 = mat->data[2]; + float m10 = mat->data[Matrix4::kSkewX]; + float m11 = mat->data[Matrix4::kScaleX]; + float m12 = mat->data[6]; + float scaleX = sqrt(m00*m00 + m01*m01); + float scaleY = sqrt(m10*m10 + m11*m11); + inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0; + inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0; + } + } + for (int i = 0; i < count; i += 4) { + // a = start point, b = end point + vec2 a(points[i], points[i + 1]); + vec2 b(points[i + 2], points[i + 3]); + + // Bias to snap to the same pixels as Skia + a += 0.375; + b += 0.375; + + // Find the normal to the line + vec2 n = (b - a).copyNormalized() * strokeWidth; + if (isHairline) { + float wideningFactor; + if (fabs(n.x) >= fabs(n.y)) { + wideningFactor = fabs(1.0f / n.x); + } else { + wideningFactor = fabs(1.0f / n.y); + } + n.x *= inverseScaleX; + n.y *= inverseScaleY; + n *= wideningFactor; + } + float x = n.x; + n.x = -n.y; + n.y = x; + + // Four corners of the rectangle defining a thick line + vec2 p1 = a - n; + vec2 p2 = a + n; + vec2 p3 = b + n; + vec2 p4 = b - n; + + const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x))); + const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x))); + const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y))); + const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y))); + + if (!quickReject(left, top, right, bottom)) { + // Draw the line as 2 triangles, could be optimized + // by using only 4 vertices and the correct indices + // Also we should probably used non textured vertices + // when line AA is disabled to save on bandwidth + if (!isAA) { + if (prevVertex != NULL) { + // Issue two repeat vertices to create degenerate triangles to bridge + // between the previous line and the new one. This is necessary because + // we are creating a single triangle_strip which will contain + // potentially discontinuous line segments. + Vertex::set(vertices++, prevVertex->position[0], prevVertex->position[1]); + Vertex::set(vertices++, p1.x, p1.y); + generatedVerticesCount += 2; + } + Vertex::set(vertices++, p1.x, p1.y); + Vertex::set(vertices++, p2.x, p2.y); + Vertex::set(vertices++, p4.x, p4.y); + Vertex::set(vertices++, p3.x, p3.y); + prevVertex = vertices - 1; + generatedVerticesCount += 4; + } else { + if (prevAAVertex != NULL) { + // Issue two repeat vertices to create degenerate triangles to bridge + // between the previous line and the new one. This is necessary because + // we are creating a single triangle_strip which will contain + // potentially discontinuous line segments. + AlphaVertex::set(aaVertices++,prevAAVertex->position[0], + prevAAVertex->position[1], prevAAVertex->alpha); + AlphaVertex::set(aaVertices++, p4.x, p4.y, 1); + generatedVerticesCount += 2; + } + AlphaVertex::set(aaVertices++, p4.x, p4.y, 1); + AlphaVertex::set(aaVertices++, p1.x, p1.y, 1); + AlphaVertex::set(aaVertices++, p3.x, p3.y, 0); + AlphaVertex::set(aaVertices++, p2.x, p2.y, 0); + prevAAVertex = aaVertices - 1; + generatedVerticesCount += 4; + } + dirtyLayer(left, top, right, bottom, *mSnapshot->transform); + } + } + if (generatedVerticesCount > 0) { + glDrawArrays(GL_TRIANGLE_STRIP, 0, generatedVerticesCount); + } +} + void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { if (mSnapshot->isIgnored()) return; const bool isAA = paint->isAntiAlias(); const float strokeWidth = paint->getStrokeWidth() * 0.5f; - // A stroke width of 0 has a special meaningin Skia: - // it draws an unscaled 1px wide line - const bool isHairLine = paint->getStrokeWidth() == 0.0f; + // A stroke width of 0 has a special meaning in Skia: + // it draws a line 1 px wide regardless of current transform + bool isHairLine = paint->getStrokeWidth() == 0.0f; int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - - int verticesCount = count >> 2; int generatedVerticesCount = 0; - if (!isHairLine) { - // TODO: AA needs more vertices - verticesCount *= 6; - } else { - // TODO: AA will be different - verticesCount *= 2; - } - - TextureVertex lines[verticesCount]; - TextureVertex* vertex = &lines[0]; setupDraw(); + if (isAA) { + setupDrawAALine(); + } setupDrawColor(paint->getColor(), alpha); setupDrawColorFilter(); setupDrawShader(); - setupDrawBlending(mode); + if (isAA) { + setupDrawBlending(true, mode); + } else { + setupDrawBlending(mode); + } setupDrawProgram(); setupDrawModelViewIdentity(); setupDrawColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderIdentityUniforms(); - setupDrawMesh(vertex); if (!isHairLine) { - // TODO: Handle the AA case - for (int i = 0; i < count; i += 4) { - // a = start point, b = end point - vec2 a(points[i], points[i + 1]); - vec2 b(points[i + 2], points[i + 3]); - - // Bias to snap to the same pixels as Skia - a += 0.375; - b += 0.375; - - // Find the normal to the line - vec2 n = (b - a).copyNormalized() * strokeWidth; - float x = n.x; - n.x = -n.y; - n.y = x; - - // Four corners of the rectangle defining a thick line - vec2 p1 = a - n; - vec2 p2 = a + n; - vec2 p3 = b + n; - vec2 p4 = b - n; - - const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x))); - const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x))); - const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y))); - const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y))); - - if (!quickReject(left, top, right, bottom)) { - // Draw the line as 2 triangles, could be optimized - // by using only 4 vertices and the correct indices - // Also we should probably used non textured vertices - // when line AA is disabled to save on bandwidth - TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f); - TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f); - TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f); - TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f); - TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f); - TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f); - - generatedVerticesCount += 6; - - dirtyLayer(left, top, right, bottom, *mSnapshot->transform); - } - } - - if (generatedVerticesCount > 0) { - // GL_LINE does not give the result we want to match Skia - glDrawArrays(GL_TRIANGLES, 0, generatedVerticesCount); - } + drawLinesAsQuads(points, count, isAA, isHairLine, strokeWidth); } else { - // TODO: Handle the AA case - for (int i = 0; i < count; i += 4) { - TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f); - TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f); - - generatedVerticesCount += 2; - - const float left = fmin(points[i], points[i + 2]); - const float right = fmax(points[i], points[i + 2]); - const float top = fmin(points[i + 1], points[i + 3]); - const float bottom = fmax(points[i + 1], points[i + 3]); + if (isAA) { + drawLinesAsQuads(points, count, isAA, isHairLine, .5f); + } else { + int verticesCount = count >> 1; + Vertex lines[verticesCount]; + Vertex* vertices = &lines[0]; + setupDrawVertices(vertices); + for (int i = 0; i < count; i += 4) { + + const float left = fmin(points[i], points[i + 2]); + const float right = fmax(points[i], points[i + 2]); + const float top = fmin(points[i + 1], points[i + 3]); + const float bottom = fmax(points[i + 1], points[i + 3]); + + Vertex::set(vertices++, points[i], points[i + 1]); + Vertex::set(vertices++, points[i + 2], points[i + 3]); + generatedVerticesCount += 2; + dirtyLayer(left, top, + right == left ? left + 1 : right, bottom == top ? top + 1 : bottom, + *mSnapshot->transform); + } - dirtyLayer(left, top, - right == left ? left + 1 : right, bottom == top ? top + 1 : bottom, - *mSnapshot->transform); + glLineWidth(1.0f); + glDrawArrays(GL_LINES, 0, generatedVerticesCount); } - - glLineWidth(1.0f); - glDrawArrays(GL_LINES, 0, generatedVerticesCount); } } @@ -1467,7 +1588,7 @@ void OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) { // TODO: The paint's cap style defines whether the points are square or circular // TODO: Handle AA for round points - // A stroke width of 0 has a special meaningin Skia: + // A stroke width of 0 has a special meaning in Skia: // it draws an unscaled 1px point const bool isHairLine = paint->getStrokeWidth() == 0.0f; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 4b93b80..0276095 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -283,6 +283,19 @@ private: void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint); /** + * Draws a line as a quad. Called by drawLines() for all cases except hairline without AA. + * + * @param points The vertices of the lines. Every four entries specifies the x/y points + * of a single line segment. + * @param count The number of entries in the points array. + * @param isAA Whether the line is anti-aliased + * @param isHairline Whether the line has strokeWidth==0, which results in the line being + * one pixel wide on the display regardless of scale. + */ + void drawLinesAsQuads(float *points, int count, bool isAA, bool isHairline, + float strokeWidth); + + /** * Draws a textured rectangle with the specified texture. The specified coordinates * are transformed by the current snapshot's transform matrix. * @@ -425,6 +438,7 @@ private: * Various methods to setup OpenGL rendering. */ void setupDrawWithTexture(bool isAlpha8 = false); + void setupDrawAALine(); void setupDrawPoint(float pointSize); void setupDrawColor(int color); void setupDrawColor(int color, int alpha); @@ -453,6 +467,8 @@ private: void setupDrawSimpleMesh(); void setupDrawTexture(GLuint texture); void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0); + void setupDrawVertices(GLvoid* vertices); + void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth); void finishDrawTexture(); void drawRegionRects(const Region& region); diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index f0bc36b..b873bb8 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -39,6 +39,8 @@ const char* gVS_Header_Attributes = "attribute vec4 position;\n"; const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n"; +const char* gVS_Header_Attributes_Distance = + "attribute float vtxDistance;\n"; const char* gVS_Header_Uniforms = "uniform mat4 transform;\n"; const char* gVS_Header_Uniforms_IsPoint = @@ -56,6 +58,8 @@ const char* gVS_Header_Uniforms_HasBitmap = "uniform mediump vec2 textureDimension;\n"; const char* gVS_Header_Varyings_HasTexture = "varying vec2 outTexCoords;\n"; +const char* gVS_Header_Varyings_HasWidth = + "varying float distance;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying vec2 outBitmapTexCoords;\n"; const char* gVS_Header_Varyings_PointHasBitmap = @@ -88,6 +92,8 @@ const char* gVS_Main_Position = " gl_Position = transform * position;\n"; const char* gVS_Main_PointSize = " gl_PointSize = pointSize;\n"; +const char* gVS_Main_Width = + " distance = vtxDistance;\n"; const char* gVS_Footer = "}\n\n"; @@ -101,6 +107,10 @@ const char* gFS_Header = "precision mediump float;\n\n"; const char* gFS_Uniforms_Color = "uniform vec4 color;\n"; +const char* gFS_Uniforms_Width = + "uniform float width;\n" + "uniform float boundaryWidth;\n" + "uniform float inverseBoundaryWidth;\n"; const char* gFS_Header_Uniforms_PointHasBitmap = "uniform vec2 textureDimension;\n" "uniform float pointSize;\n"; @@ -169,6 +179,12 @@ const char* gFS_Fast_SingleModulateGradient = // General case const char* gFS_Main_FetchColor = " fragColor = color;\n"; +const char* gFS_Main_AccountForWidth = + " if (distance < boundaryWidth) {\n" + " fragColor *= (distance * inverseBoundaryWidth);\n" + " } else if (distance > (1.0 - boundaryWidth)) {\n" + " fragColor *= ((1.0 - distance) * inverseBoundaryWidth);\n" + " }\n"; const char* gFS_Main_FetchTexture[2] = { // Don't modulate " fragColor = texture2D(sampler, outTexCoords);\n", @@ -354,6 +370,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture) { shader.append(gVS_Header_Attributes_TexCoords); } + if (description.hasWidth) { + shader.append(gVS_Header_Attributes_Distance); + } // Uniforms shader.append(gVS_Header_Uniforms); if (description.hasGradient) { @@ -369,6 +388,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture) { shader.append(gVS_Header_Varyings_HasTexture); } + if (description.hasWidth) { + shader.append(gVS_Header_Varyings_HasWidth); + } if (description.hasGradient) { shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } @@ -383,6 +405,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture) { shader.append(gVS_Main_OutTexCoords); } + if (description.hasWidth) { + shader.append(gVS_Main_Width); + } if (description.hasGradient) { shader.append(gVS_Main_OutGradient[description.gradientType]); } @@ -420,6 +445,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture) { shader.append(gVS_Header_Varyings_HasTexture); } + if (description.hasWidth) { + shader.append(gVS_Header_Varyings_HasWidth); + } if (description.hasGradient) { shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } @@ -441,6 +469,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture) { shader.append(gFS_Uniforms_TextureSampler); } + if (description.hasWidth) { + shader.append(gFS_Uniforms_Width); + } if (description.hasGradient) { shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); } @@ -449,8 +480,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti } // Optimization for common cases - if (!blendFramebuffer && description.colorOp == ProgramDescription::kColorNone && - !description.isPoint) { + if (!description.hasWidth && !blendFramebuffer && + description.colorOp == ProgramDescription::kColorNone && !description.isPoint) { bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; @@ -534,6 +565,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_FetchColor); } } + if (description.hasWidth) { + shader.append(gFS_Main_AccountForWidth); + } if (description.hasGradient) { shader.append(gFS_Main_FetchGradient[description.gradientType]); } diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index 737d91b..cead75b 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -57,6 +57,7 @@ namespace uirenderer { #define PROGRAM_KEY_COLOR_BLEND 0x80 #define PROGRAM_KEY_BITMAP_NPOT 0x100 #define PROGRAM_KEY_SWAP_SRC_DST 0x2000 +#define PROGRAM_KEY_VERTEX_WIDTH 0x4000 #define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800 @@ -119,6 +120,8 @@ struct ProgramDescription { bool hasBitmap; bool isBitmapNpot; + bool hasWidth; + bool hasGradient; Gradient gradientType; @@ -148,6 +151,8 @@ struct ProgramDescription { hasTexture = false; hasAlpha8Texture = false; + hasWidth = false; + modulate = false; hasBitmap = false; @@ -200,6 +205,7 @@ struct ProgramDescription { programid key() const { programid key = 0; if (hasTexture) key |= PROGRAM_KEY_TEXTURE; + if (hasWidth) key |= PROGRAM_KEY_VERTEX_WIDTH; if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE; if (hasBitmap) { key |= PROGRAM_KEY_BITMAP; diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h index bbf4d4a..c120428 100644 --- a/libs/hwui/Vertex.h +++ b/libs/hwui/Vertex.h @@ -23,6 +23,18 @@ namespace uirenderer { /** * Simple structure to describe a vertex with a position and a texture. */ +struct Vertex { + float position[2]; + + static inline void set(Vertex* vertex, float x, float y) { + vertex[0].position[0] = x; + vertex[0].position[1] = y; + } +}; // struct Vertex + +/** + * Simple structure to describe a vertex with a position and a texture. + */ struct TextureVertex { float position[2]; float texture[2]; @@ -40,6 +52,22 @@ struct TextureVertex { } }; // struct TextureVertex +/** + * Simple structure to describe a vertex with a position and an alpha value. + */ +struct AlphaVertex : Vertex { + float alpha; + + static inline void set(AlphaVertex* vertex, float x, float y, float alpha) { + Vertex::set(vertex, x, y); + vertex[0].alpha = alpha; + } + + static inline void setColor(AlphaVertex* vertex, float alpha) { + vertex[0].alpha = alpha; + } +}; // struct AlphaVertex + }; // namespace uirenderer }; // namespace android |