Loading libs/hwui/Caches.h +3 −1 Original line number Diff line number Diff line Loading @@ -62,8 +62,10 @@ static const TextureVertex gMeshVertices[] = { static const GLsizei gMeshStride = sizeof(TextureVertex); static const GLsizei gVertexStride = sizeof(Vertex); static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex); static const GLsizei gAAVertexStride = sizeof(AAVertex); static const GLsizei gMeshTextureOffset = 2 * sizeof(float); static const GLsizei gVertexAlphaOffset = 2 * sizeof(float); static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float); static const GLsizei gVertexAALengthOffset = 3 * sizeof(float); static const GLsizei gMeshCount = 4; /////////////////////////////////////////////////////////////////////////////// Loading libs/hwui/OpenGLRenderer.cpp +60 −32 Original line number Diff line number Diff line Loading @@ -915,7 +915,7 @@ void OpenGLRenderer::setupDrawWithExternalTexture() { } void OpenGLRenderer::setupDrawAALine() { mDescription.hasWidth = true; mDescription.isAA = true; } void OpenGLRenderer::setupDrawPoint(float pointSize) { Loading Loading @@ -1121,25 +1121,30 @@ void OpenGLRenderer::setupDrawVertices(GLvoid* 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. * outer boundary that fades out to 0. The variables set in the shader define the proportion of * the width and length of the primitive occupied by the AA region. The vtxWidth and vtxLength * attributes (one per vertex) are values from zero to one that tells the fragment * shader where the fragment is in relation to the line width/length overall; these values are * then used to compute the proper color, based on whether the fragment lies in the fading AA * region of the line. * Note that we only pass down the width values in this setup function. The length coordinates * are set up for each individual segment. */ void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth) { void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords, GLvoid* lengthCoords, 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"); gAAVertexStride, vertices); int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth"); glEnableVertexAttribArray(widthSlot); glVertexAttribPointer(widthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, widthCoords); int lengthSlot = mCaches.currentProgram->getAttrib("vtxLength"); glEnableVertexAttribArray(lengthSlot); glVertexAttribPointer(lengthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, lengthCoords); int boundaryWidthSlot = mCaches.currentProgram->getUniform("boundaryWidth"); // Setting the inverse value saves computations per-fragment in the shader int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth"); float boundaryWidth = (1 - strokeWidth) / 2; glUniform1f(widthSlot, strokeWidth); glUniform1f(boundaryWidthSlot, boundaryWidth); glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidth)); } Loading Loading @@ -1480,20 +1485,21 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } Vertex lines[verticesCount]; Vertex* vertices = &lines[0]; AlphaVertex wLines[verticesCount]; AlphaVertex* aaVertices = &wLines[0]; AAVertex wLines[verticesCount]; AAVertex* aaVertices = &wLines[0]; if (!isAA) { setupDrawVertices(vertices); } else { void* alphaCoords = ((GLbyte*) aaVertices) + gVertexAlphaOffset; void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset; void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset; // 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, alphaCoords, innerProportion); setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, innerProportion); } AlphaVertex *prevAAVertex = NULL; AAVertex *prevAAVertex = NULL; Vertex *prevVertex = NULL; float inverseScaleX = 1.0f; float inverseScaleY = 1.0f; Loading @@ -1516,15 +1522,17 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } } int boundaryLengthSlot = -1; int inverseBoundaryLengthSlot = -1; 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]); float length = 0; // Find the normal to the line vec2 n = (b - a).copyNormalized() * strokeWidth; if (isHairLine) { n *= inverseScaleX; if (isAA) { float wideningFactor; if (fabs(n.x) >= fabs(n.y)) { Loading @@ -1534,27 +1542,35 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } n *= wideningFactor; } n.x *= inverseScaleX; n.y *= inverseScaleY; } float x = n.x; n.x = -n.y; n.y = x; // aa lines expand the endpoint vertices to encompass the AA boundary if (isAA) { vec2 abVector = (b - a); length = abVector.length(); abVector.normalize(); a -= abVector; b += abVector; } // 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 Loading @@ -1572,24 +1588,36 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { prevVertex = vertices - 1; generatedVerticesCount += 4; } else { if (boundaryLengthSlot < 0) { boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength"); inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength"); } float innerProportion = (length) / (length + 2); float boundaryLength = (1 - innerProportion) / 2; glUniform1f(boundaryLengthSlot, boundaryLength); glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryLength)); 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); AAVertex::set(aaVertices++,prevAAVertex->position[0], prevAAVertex->position[1], prevAAVertex->width, prevAAVertex->length); AAVertex::set(aaVertices++, p4.x, p4.y, 1, 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); AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1); AAVertex::set(aaVertices++, p1.x, p1.y, 1, 0); AAVertex::set(aaVertices++, p3.x, p3.y, 0, 1); AAVertex::set(aaVertices++, p2.x, p2.y, 0, 0); prevAAVertex = aaVertices - 1; generatedVerticesCount += 4; } dirtyLayer(left, top, right, bottom, *mSnapshot->transform); dirtyLayer(a.x == b.x ? left - 1 : left, a.y == b.y ? top - 1 : top, a.x == b.x ? right: right, a.y == b.y ? bottom: bottom, *mSnapshot->transform); } } if (generatedVerticesCount > 0) { Loading libs/hwui/OpenGLRenderer.h +2 −1 Original line number Diff line number Diff line Loading @@ -468,7 +468,8 @@ private: void setupDrawTextureTransform(mat4& transform); void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0); void setupDrawVertices(GLvoid* vertices); void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth); void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, GLvoid* lengthCoords, float strokeWidth); void finishDrawTexture(); void drawRegionRects(const Region& region); Loading libs/hwui/ProgramCache.cpp +36 −27 Original line number Diff line number Diff line Loading @@ -39,8 +39,9 @@ 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_Attributes_AAParameters = "attribute float vtxWidth;\n" "attribute float vtxLength;\n"; const char* gVS_Header_Uniforms_TextureTransform = "uniform mat4 mainTextureTransform;\n"; const char* gVS_Header_Uniforms = Loading @@ -60,8 +61,9 @@ 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_IsAA = "varying float widthProportion;\n" "varying float lengthProportion;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying vec2 outBitmapTexCoords;\n"; const char* gVS_Header_Varyings_PointHasBitmap = Loading Loading @@ -96,8 +98,9 @@ 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_Main_AA = " widthProportion = vtxWidth;\n" " lengthProportion = vtxLength;\n"; const char* gVS_Footer = "}\n\n"; Loading @@ -113,10 +116,11 @@ 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" const char* gFS_Uniforms_AA = "uniform float boundaryWidth;\n" "uniform float inverseBoundaryWidth;\n"; "uniform float inverseBoundaryWidth;\n" "uniform float boundaryLength;\n" "uniform float inverseBoundaryLength;\n"; const char* gFS_Header_Uniforms_PointHasBitmap = "uniform vec2 textureDimension;\n" "uniform float pointSize;\n"; Loading Loading @@ -189,11 +193,16 @@ const char* gFS_Main_FetchColor = " fragColor = color;\n"; const char* gFS_Main_ModulateColor = " fragColor *= color.a;\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" const char* gFS_Main_AccountForAA = " if (widthProportion < boundaryWidth) {\n" " fragColor *= (widthProportion * inverseBoundaryWidth);\n" " } else if (widthProportion > (1.0 - boundaryWidth)) {\n" " fragColor *= ((1.0 - widthProportion) * inverseBoundaryWidth);\n" " }\n" " if (lengthProportion < boundaryLength) {\n" " fragColor *= (lengthProportion * inverseBoundaryLength);\n" " } else if (lengthProportion > (1.0 - boundaryLength)) {\n" " fragColor *= ((1.0 - lengthProportion) * inverseBoundaryLength);\n" " }\n"; const char* gFS_Main_FetchTexture[2] = { // Don't modulate Loading Loading @@ -380,8 +389,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Attributes_TexCoords); } if (description.hasWidth) { shader.append(gVS_Header_Attributes_Distance); if (description.isAA) { shader.append(gVS_Header_Attributes_AAParameters); } // Uniforms shader.append(gVS_Header_Uniforms); Loading @@ -401,8 +410,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { shader.append(gVS_Header_Varyings_HasWidth); if (description.isAA) { shader.append(gVS_Header_Varyings_IsAA); } if (description.hasGradient) { shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); Loading @@ -421,8 +430,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasExternalTexture) { shader.append(gVS_Main_OutTransformedTexCoords); } if (description.hasWidth) { shader.append(gVS_Main_Width); if (description.isAA) { shader.append(gVS_Main_AA); } if (description.hasGradient) { shader.append(gVS_Main_OutGradient[description.gradientType]); Loading Loading @@ -464,8 +473,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { shader.append(gVS_Header_Varyings_HasWidth); if (description.isAA) { shader.append(gVS_Header_Varyings_IsAA); } if (description.hasGradient) { shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); Loading @@ -491,8 +500,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasExternalTexture) { shader.append(gFS_Uniforms_ExternalTextureSampler); } if (description.hasWidth) { shader.append(gFS_Uniforms_Width); if (description.isAA) { shader.append(gFS_Uniforms_AA); } if (description.hasGradient) { shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); Loading @@ -502,7 +511,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti } // Optimization for common cases if (!description.hasWidth && !blendFramebuffer && if (!description.isAA && !blendFramebuffer && description.colorOp == ProgramDescription::kColorNone && !description.isPoint) { bool fast = false; Loading Loading @@ -587,8 +596,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_FetchColor); } } if (description.hasWidth) { shader.append(gFS_Main_AccountForWidth); if (description.isAA) { shader.append(gFS_Main_AccountForAA); } if (description.hasGradient) { shader.append(gFS_Main_FetchGradient[description.gradientType]); Loading libs/hwui/ProgramCache.h +4 −4 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ namespace uirenderer { #define PROGRAM_IS_POINT_SHIFT 36 #define PROGRAM_HAS_WIDTH_SHIFT 37 #define PROGRAM_HAS_AA_SHIFT 37 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 Loading Loading @@ -124,7 +124,7 @@ struct ProgramDescription { bool hasBitmap; bool isBitmapNpot; bool hasWidth; bool isAA; bool hasGradient; Gradient gradientType; Loading Loading @@ -156,7 +156,7 @@ struct ProgramDescription { hasAlpha8Texture = false; hasExternalTexture = false; hasWidth = false; isAA = false; modulate = false; Loading Loading @@ -243,7 +243,7 @@ struct ProgramDescription { if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST; if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT; if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT; if (hasWidth) key |= programid(0x1) << PROGRAM_HAS_WIDTH_SHIFT; if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT; if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; return key; } Loading Loading
libs/hwui/Caches.h +3 −1 Original line number Diff line number Diff line Loading @@ -62,8 +62,10 @@ static const TextureVertex gMeshVertices[] = { static const GLsizei gMeshStride = sizeof(TextureVertex); static const GLsizei gVertexStride = sizeof(Vertex); static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex); static const GLsizei gAAVertexStride = sizeof(AAVertex); static const GLsizei gMeshTextureOffset = 2 * sizeof(float); static const GLsizei gVertexAlphaOffset = 2 * sizeof(float); static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float); static const GLsizei gVertexAALengthOffset = 3 * sizeof(float); static const GLsizei gMeshCount = 4; /////////////////////////////////////////////////////////////////////////////// Loading
libs/hwui/OpenGLRenderer.cpp +60 −32 Original line number Diff line number Diff line Loading @@ -915,7 +915,7 @@ void OpenGLRenderer::setupDrawWithExternalTexture() { } void OpenGLRenderer::setupDrawAALine() { mDescription.hasWidth = true; mDescription.isAA = true; } void OpenGLRenderer::setupDrawPoint(float pointSize) { Loading Loading @@ -1121,25 +1121,30 @@ void OpenGLRenderer::setupDrawVertices(GLvoid* 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. * outer boundary that fades out to 0. The variables set in the shader define the proportion of * the width and length of the primitive occupied by the AA region. The vtxWidth and vtxLength * attributes (one per vertex) are values from zero to one that tells the fragment * shader where the fragment is in relation to the line width/length overall; these values are * then used to compute the proper color, based on whether the fragment lies in the fading AA * region of the line. * Note that we only pass down the width values in this setup function. The length coordinates * are set up for each individual segment. */ void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth) { void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords, GLvoid* lengthCoords, 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"); gAAVertexStride, vertices); int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth"); glEnableVertexAttribArray(widthSlot); glVertexAttribPointer(widthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, widthCoords); int lengthSlot = mCaches.currentProgram->getAttrib("vtxLength"); glEnableVertexAttribArray(lengthSlot); glVertexAttribPointer(lengthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, lengthCoords); int boundaryWidthSlot = mCaches.currentProgram->getUniform("boundaryWidth"); // Setting the inverse value saves computations per-fragment in the shader int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth"); float boundaryWidth = (1 - strokeWidth) / 2; glUniform1f(widthSlot, strokeWidth); glUniform1f(boundaryWidthSlot, boundaryWidth); glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidth)); } Loading Loading @@ -1480,20 +1485,21 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } Vertex lines[verticesCount]; Vertex* vertices = &lines[0]; AlphaVertex wLines[verticesCount]; AlphaVertex* aaVertices = &wLines[0]; AAVertex wLines[verticesCount]; AAVertex* aaVertices = &wLines[0]; if (!isAA) { setupDrawVertices(vertices); } else { void* alphaCoords = ((GLbyte*) aaVertices) + gVertexAlphaOffset; void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset; void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset; // 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, alphaCoords, innerProportion); setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, innerProportion); } AlphaVertex *prevAAVertex = NULL; AAVertex *prevAAVertex = NULL; Vertex *prevVertex = NULL; float inverseScaleX = 1.0f; float inverseScaleY = 1.0f; Loading @@ -1516,15 +1522,17 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } } int boundaryLengthSlot = -1; int inverseBoundaryLengthSlot = -1; 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]); float length = 0; // Find the normal to the line vec2 n = (b - a).copyNormalized() * strokeWidth; if (isHairLine) { n *= inverseScaleX; if (isAA) { float wideningFactor; if (fabs(n.x) >= fabs(n.y)) { Loading @@ -1534,27 +1542,35 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } n *= wideningFactor; } n.x *= inverseScaleX; n.y *= inverseScaleY; } float x = n.x; n.x = -n.y; n.y = x; // aa lines expand the endpoint vertices to encompass the AA boundary if (isAA) { vec2 abVector = (b - a); length = abVector.length(); abVector.normalize(); a -= abVector; b += abVector; } // 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 Loading @@ -1572,24 +1588,36 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { prevVertex = vertices - 1; generatedVerticesCount += 4; } else { if (boundaryLengthSlot < 0) { boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength"); inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength"); } float innerProportion = (length) / (length + 2); float boundaryLength = (1 - innerProportion) / 2; glUniform1f(boundaryLengthSlot, boundaryLength); glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryLength)); 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); AAVertex::set(aaVertices++,prevAAVertex->position[0], prevAAVertex->position[1], prevAAVertex->width, prevAAVertex->length); AAVertex::set(aaVertices++, p4.x, p4.y, 1, 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); AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1); AAVertex::set(aaVertices++, p1.x, p1.y, 1, 0); AAVertex::set(aaVertices++, p3.x, p3.y, 0, 1); AAVertex::set(aaVertices++, p2.x, p2.y, 0, 0); prevAAVertex = aaVertices - 1; generatedVerticesCount += 4; } dirtyLayer(left, top, right, bottom, *mSnapshot->transform); dirtyLayer(a.x == b.x ? left - 1 : left, a.y == b.y ? top - 1 : top, a.x == b.x ? right: right, a.y == b.y ? bottom: bottom, *mSnapshot->transform); } } if (generatedVerticesCount > 0) { Loading
libs/hwui/OpenGLRenderer.h +2 −1 Original line number Diff line number Diff line Loading @@ -468,7 +468,8 @@ private: void setupDrawTextureTransform(mat4& transform); void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0); void setupDrawVertices(GLvoid* vertices); void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth); void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, GLvoid* lengthCoords, float strokeWidth); void finishDrawTexture(); void drawRegionRects(const Region& region); Loading
libs/hwui/ProgramCache.cpp +36 −27 Original line number Diff line number Diff line Loading @@ -39,8 +39,9 @@ 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_Attributes_AAParameters = "attribute float vtxWidth;\n" "attribute float vtxLength;\n"; const char* gVS_Header_Uniforms_TextureTransform = "uniform mat4 mainTextureTransform;\n"; const char* gVS_Header_Uniforms = Loading @@ -60,8 +61,9 @@ 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_IsAA = "varying float widthProportion;\n" "varying float lengthProportion;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying vec2 outBitmapTexCoords;\n"; const char* gVS_Header_Varyings_PointHasBitmap = Loading Loading @@ -96,8 +98,9 @@ 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_Main_AA = " widthProportion = vtxWidth;\n" " lengthProportion = vtxLength;\n"; const char* gVS_Footer = "}\n\n"; Loading @@ -113,10 +116,11 @@ 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" const char* gFS_Uniforms_AA = "uniform float boundaryWidth;\n" "uniform float inverseBoundaryWidth;\n"; "uniform float inverseBoundaryWidth;\n" "uniform float boundaryLength;\n" "uniform float inverseBoundaryLength;\n"; const char* gFS_Header_Uniforms_PointHasBitmap = "uniform vec2 textureDimension;\n" "uniform float pointSize;\n"; Loading Loading @@ -189,11 +193,16 @@ const char* gFS_Main_FetchColor = " fragColor = color;\n"; const char* gFS_Main_ModulateColor = " fragColor *= color.a;\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" const char* gFS_Main_AccountForAA = " if (widthProportion < boundaryWidth) {\n" " fragColor *= (widthProportion * inverseBoundaryWidth);\n" " } else if (widthProportion > (1.0 - boundaryWidth)) {\n" " fragColor *= ((1.0 - widthProportion) * inverseBoundaryWidth);\n" " }\n" " if (lengthProportion < boundaryLength) {\n" " fragColor *= (lengthProportion * inverseBoundaryLength);\n" " } else if (lengthProportion > (1.0 - boundaryLength)) {\n" " fragColor *= ((1.0 - lengthProportion) * inverseBoundaryLength);\n" " }\n"; const char* gFS_Main_FetchTexture[2] = { // Don't modulate Loading Loading @@ -380,8 +389,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Attributes_TexCoords); } if (description.hasWidth) { shader.append(gVS_Header_Attributes_Distance); if (description.isAA) { shader.append(gVS_Header_Attributes_AAParameters); } // Uniforms shader.append(gVS_Header_Uniforms); Loading @@ -401,8 +410,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { shader.append(gVS_Header_Varyings_HasWidth); if (description.isAA) { shader.append(gVS_Header_Varyings_IsAA); } if (description.hasGradient) { shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); Loading @@ -421,8 +430,8 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasExternalTexture) { shader.append(gVS_Main_OutTransformedTexCoords); } if (description.hasWidth) { shader.append(gVS_Main_Width); if (description.isAA) { shader.append(gVS_Main_AA); } if (description.hasGradient) { shader.append(gVS_Main_OutGradient[description.gradientType]); Loading Loading @@ -464,8 +473,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { shader.append(gVS_Header_Varyings_HasWidth); if (description.isAA) { shader.append(gVS_Header_Varyings_IsAA); } if (description.hasGradient) { shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); Loading @@ -491,8 +500,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasExternalTexture) { shader.append(gFS_Uniforms_ExternalTextureSampler); } if (description.hasWidth) { shader.append(gFS_Uniforms_Width); if (description.isAA) { shader.append(gFS_Uniforms_AA); } if (description.hasGradient) { shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); Loading @@ -502,7 +511,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti } // Optimization for common cases if (!description.hasWidth && !blendFramebuffer && if (!description.isAA && !blendFramebuffer && description.colorOp == ProgramDescription::kColorNone && !description.isPoint) { bool fast = false; Loading Loading @@ -587,8 +596,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_FetchColor); } } if (description.hasWidth) { shader.append(gFS_Main_AccountForWidth); if (description.isAA) { shader.append(gFS_Main_AccountForAA); } if (description.hasGradient) { shader.append(gFS_Main_FetchGradient[description.gradientType]); Loading
libs/hwui/ProgramCache.h +4 −4 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ namespace uirenderer { #define PROGRAM_IS_POINT_SHIFT 36 #define PROGRAM_HAS_WIDTH_SHIFT 37 #define PROGRAM_HAS_AA_SHIFT 37 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 Loading Loading @@ -124,7 +124,7 @@ struct ProgramDescription { bool hasBitmap; bool isBitmapNpot; bool hasWidth; bool isAA; bool hasGradient; Gradient gradientType; Loading Loading @@ -156,7 +156,7 @@ struct ProgramDescription { hasAlpha8Texture = false; hasExternalTexture = false; hasWidth = false; isAA = false; modulate = false; Loading Loading @@ -243,7 +243,7 @@ struct ProgramDescription { if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST; if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT; if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT; if (hasWidth) key |= programid(0x1) << PROGRAM_HAS_WIDTH_SHIFT; if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT; if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; return key; } Loading