From 78dd96d5af20f489f0e8b288617d57774ec284f7 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Fri, 3 May 2013 14:24:16 -0700 Subject: Add an on-screen overdraw counter The counter can be enabled by setting the system property called debug.hwui.overdraw to the string "count". If the string is set to "show", overdraw will be highlighted on screen instead of printing out a simple counter. Change-Id: I9a9c970d54bffab43138bbb7682f6c04bc2c40bd --- libs/hwui/ProgramCache.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'libs/hwui/ProgramCache.cpp') diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 8eb85e5547eb..367294cb677d 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -342,6 +342,12 @@ const char* gFS_Main_ApplyColorOp[4] = { }; const char* gFS_Main_DebugHighlight = " gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n"; +const char* gFS_Main_EmulateStencil = + " gl_FragColor.rgba = vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 1.0);\n" + " return;\n" + " /*\n"; +const char* gFS_Footer_EmulateStencil = + " */\n"; const char* gFS_Footer = "}\n\n"; @@ -603,7 +609,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Optimization for common cases if (!description.isAA && !blendFramebuffer && !description.hasColors && description.colorOp == ProgramDescription::kColorNone && - !description.isPoint && !description.hasDebugHighlight) { + !description.isPoint && !description.hasDebugHighlight && + !description.emulateStencil) { bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; @@ -683,6 +690,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Begin the shader shader.append(gFS_Main); { + if (description.emulateStencil) { + shader.append(gFS_Main_EmulateStencil); + } // Stores the result in fragColor directly if (description.hasTexture || description.hasExternalTexture) { if (description.hasAlpha8Texture) { @@ -757,6 +767,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_DebugHighlight); } } + if (description.emulateStencil) { + shader.append(gFS_Footer_EmulateStencil); + } // End the shader shader.append(gFS_Footer); -- cgit v1.2.3-59-g8ed1b From 6d29c8d5218cac0fb35f3b7c253f2bdebd44f15a Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Wed, 8 May 2013 18:35:44 -0700 Subject: Add tessellation path for points bug:4351353 bug:8185479 Point tessellation is similar to line special case, except that we only tessellate one point (as a circle or rect) and duplicate it across other instances. Additionally: Fixes square caps for AA=false lines Cleanup in CanvasCompare, disabling interpolation on zoomed-in comparison view Change-Id: I0756fcc4b20f77878fed0d8057297c80e82ed9dc --- libs/hwui/OpenGLRenderer.cpp | 77 ++--------- libs/hwui/OpenGLRenderer.h | 2 - libs/hwui/PathTessellator.cpp | 145 ++++++++++++++------- libs/hwui/PathTessellator.h | 35 +++-- libs/hwui/Program.h | 27 ++-- libs/hwui/ProgramCache.cpp | 42 +----- libs/hwui/Vertex.h | 17 +++ tests/CanvasCompare/res/layout/manual_layout.xml | 2 +- .../android/test/hwuicompare/DisplayModifier.java | 2 +- .../android/test/hwuicompare/NearestImageView.java | 47 +++++++ 10 files changed, 217 insertions(+), 179 deletions(-) create mode 100644 tests/CanvasCompare/src/com/android/test/hwuicompare/NearestImageView.java (limited to 'libs/hwui/ProgramCache.cpp') diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index f220e4f44e6a..038df07e0cfd 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1703,11 +1703,6 @@ void OpenGLRenderer::setupDrawAA() { mDescription.isAA = true; } -void OpenGLRenderer::setupDrawPoint(float pointSize) { - mDescription.isPoint = true; - mDescription.pointSize = pointSize; -} - void OpenGLRenderer::setupDrawColor(int color, int alpha) { mColorA = alpha / 255.0f; mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f; @@ -1822,11 +1817,6 @@ void OpenGLRenderer::setupDrawModelView(float left, float top, float right, floa } } -void OpenGLRenderer::setupDrawPointUniforms() { - int slot = mCaches.currentProgram->getUniform("pointSize"); - glUniform1f(slot, mDescription.pointSize); -} - void OpenGLRenderer::setupDrawColorUniforms() { if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) { mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA); @@ -2409,7 +2399,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint, bool useOffset) { - if (!vertexBuffer.getSize()) { + if (!vertexBuffer.getVertexCount()) { // no vertices to draw return DrawGlInfo::kStatusDone; } @@ -2447,7 +2437,7 @@ status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPa glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords); } - glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount()); if (isAA) { glDisableVertexAttribArray(alphaSlot); @@ -2510,65 +2500,22 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) { - if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; - - // 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 meaning in Skia: - // it draws an unscaled 1px point - float strokeWidth = paint->getStrokeWidth(); - const bool isHairLine = paint->getStrokeWidth() == 0.0f; - if (isHairLine) { - // Now that we know it's hairline, we can set the effective width, to be used later - strokeWidth = 1.0f; - } - const float halfWidth = strokeWidth / 2; - - int alpha; - SkXfermode::Mode mode; - getAlphaAndMode(paint, &alpha, &mode); + if (mSnapshot->isIgnored() || count < 2) return DrawGlInfo::kStatusDone; - int verticesCount = count >> 1; - int generatedVerticesCount = 0; + count &= ~0x1; // round down to nearest two - TextureVertex pointsData[verticesCount]; - TextureVertex* vertex = &pointsData[0]; - - // TODO: We should optimize this method to not generate vertices for points - // that lie outside of the clip. - mCaches.enableScissor(); - - setupDraw(); - setupDrawNoTexture(); - setupDrawPoint(strokeWidth); - setupDrawColor(paint->getColor(), alpha); - setupDrawColorFilter(); - setupDrawShader(); - setupDrawBlending(mode); - setupDrawProgram(); - setupDrawModelViewIdentity(true); - setupDrawColorUniforms(); - setupDrawColorFilterUniforms(); - setupDrawPointUniforms(); - setupDrawShaderIdentityUniforms(); - setupDrawMesh(vertex); - - for (int i = 0; i < count; i += 2) { - TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f); - generatedVerticesCount++; - - float left = points[i] - halfWidth; - float right = points[i] + halfWidth; - float top = points[i + 1] - halfWidth; - float bottom = points [i + 1] + halfWidth; + VertexBuffer buffer; + SkRect bounds; + PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer); - dirtyLayer(left, top, right, bottom, currentTransform()); + if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { + return DrawGlInfo::kStatusDone; } - glDrawArrays(GL_POINTS, 0, generatedVerticesCount); + dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); - return DrawGlInfo::kStatusDrew; + bool useOffset = !paint->isAntiAlias(); + return drawVertexBuffer(buffer, paint, useOffset); } status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index df275d7b45fe..597e458b9fe8 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -927,7 +927,6 @@ private: void setupDrawWithExternalTexture(); void setupDrawNoTexture(); void setupDrawAA(); - void setupDrawPoint(float pointSize); void setupDrawColor(int color, int alpha); void setupDrawColor(float r, float g, float b, float a); void setupDrawAlpha8Color(int color, int alpha); @@ -945,7 +944,6 @@ private: bool ignoreTransform = false, bool ignoreModelView = false); void setupDrawModelViewTranslate(float left, float top, float right, float bottom, bool ignoreTransform = false); - void setupDrawPointUniforms(); void setupDrawColorUniforms(); void setupDrawPureColorUniforms(); void setupDrawShaderIdentityUniforms(); diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp index 0879b1b240ed..3970913814c6 100644 --- a/libs/hwui/PathTessellator.cpp +++ b/libs/hwui/PathTessellator.cpp @@ -66,11 +66,11 @@ void PathTessellator::expandBoundsForStroke(SkRect& bounds, const SkPaint* paint } } -inline void copyVertex(Vertex* destPtr, const Vertex* srcPtr) { +inline static void copyVertex(Vertex* destPtr, const Vertex* srcPtr) { Vertex::set(destPtr, srcPtr->position[0], srcPtr->position[1]); } -inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) { +inline static void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) { AlphaVertex::set(destPtr, srcPtr->position[0], srcPtr->position[1], srcPtr->alpha); } @@ -84,7 +84,7 @@ inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) { * * NOTE: assumes angles between normals 90 degrees or less */ -inline vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) { +inline static vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) { return (normalA + normalB) / (1 + fabs(normalA.dot(normalB))); } @@ -224,6 +224,20 @@ void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo, const Vector& vertices, VertexBuffer& vertexBuffer) { const int extra = paintInfo.capExtraDivisions(); const int allocSize = (vertices.size() + extra) * 2; - Vertex* buffer = vertexBuffer.alloc(allocSize); + const int lastIndex = vertices.size() - 1; if (extra > 0) { // tessellate both round caps - const int last = vertices.size() - 1; float beginTheta = atan2( - - (vertices[0].position[0] - vertices[1].position[0]), - vertices[0].position[1] - vertices[1].position[1]); + - (vertices[0].position[0] - vertices[1].position[0]), + vertices[0].position[1] - vertices[1].position[1]); float endTheta = atan2( - - (vertices[last].position[0] - vertices[last - 1].position[0]), - vertices[last].position[1] - vertices[last - 1].position[1]); - + - (vertices[lastIndex].position[0] - vertices[lastIndex - 1].position[0]), + vertices[lastIndex].position[1] - vertices[lastIndex - 1].position[1]); const float dTheta = PI / (extra + 1); const float radialScale = 2.0f / (1 + cos(dTheta)); @@ -270,56 +282,45 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo, vec2 endRadialOffset(cos(endTheta), sin(endTheta)); paintInfo.scaleOffsetForStrokeWidth(endRadialOffset); Vertex::set(&buffer[allocSize - 1 - capOffset], - vertices[last].position[0] + endRadialOffset.x, - vertices[last].position[1] + endRadialOffset.y); + vertices[lastIndex].position[0] + endRadialOffset.x, + vertices[lastIndex].position[1] + endRadialOffset.y); } } int currentIndex = extra; - const Vertex* current = &(vertices[0]); - vec2 lastNormal; - for (unsigned int i = 0; i < vertices.size() - 1; i++) { + const Vertex* last = &(vertices[0]); + const Vertex* current = &(vertices[1]); + vec2 lastNormal(current->position[1] - last->position[1], + last->position[0] - current->position[0]); + lastNormal.normalize(); + + storeBeginEnd(paintInfo, vertices[0], lastNormal, buffer, currentIndex, true); + + for (unsigned int i = 1; i < vertices.size() - 1; i++) { const Vertex* next = &(vertices[i + 1]); vec2 nextNormal(next->position[1] - current->position[1], current->position[0] - next->position[0]); nextNormal.normalize(); - vec2 totalOffset; - if (i == 0) { - totalOffset = nextNormal; - } else { - totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - } - paintInfo.scaleOffsetForStrokeWidth(totalOffset); + vec2 strokeOffset = totalOffsetFromNormals(lastNormal, nextNormal); + paintInfo.scaleOffsetForStrokeWidth(strokeOffset); - Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.x, - current->position[1] + totalOffset.y); - - Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.x, - current->position[1] - totalOffset.y); + vec2 center(current->position[0], current->position[1]); + Vertex::set(&buffer[currentIndex++], center + strokeOffset); + Vertex::set(&buffer[currentIndex++], center - strokeOffset); current = next; lastNormal = nextNormal; } - vec2 totalOffset = lastNormal; - paintInfo.scaleOffsetForStrokeWidth(totalOffset); - - Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.x, - current->position[1] + totalOffset.y); - Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.x, - current->position[1] - totalOffset.y); + storeBeginEnd(paintInfo, vertices[lastIndex], lastNormal, buffer, currentIndex, false); DEBUG_DUMP_BUFFER(); } /** * Populates a vertexBuffer with AlphaVertices to create an anti-aliased fill shape tessellation - * + * * 1 - create the AA perimeter of unit width, by zig-zagging at each point around the perimeter of * the shape (using 2 * perimeter.size() vertices) * @@ -389,7 +390,7 @@ void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo, const Vector& vertices, +inline static void storeCapAA(const PaintInfo& paintInfo, const Vector& vertices, AlphaVertex* buffer, bool isFirst, vec2 normal, int offset) { const int extra = paintInfo.capExtraDivisions(); const int extraOffset = (extra + 1) / 2; @@ -772,11 +773,67 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint, } } +static void expandRectToCoverVertex(SkRect& rect, float x, float y) { + rect.fLeft = fminf(rect.fLeft, x); + rect.fTop = fminf(rect.fTop, y); + rect.fRight = fmaxf(rect.fRight, x); + rect.fBottom = fmaxf(rect.fBottom, y); +} static void expandRectToCoverVertex(SkRect& rect, const Vertex& vertex) { - rect.fLeft = fminf(rect.fLeft, vertex.position[0]); - rect.fTop = fminf(rect.fTop, vertex.position[1]); - rect.fRight = fmaxf(rect.fRight, vertex.position[0]); - rect.fBottom = fmaxf(rect.fBottom, vertex.position[1]); + expandRectToCoverVertex(rect, vertex.position[0], vertex.position[1]); +} + +template +static void instanceVertices(VertexBuffer& srcBuffer, VertexBuffer& dstBuffer, + const float* points, int count, SkRect& bounds) { + bounds.set(points[0], points[1], points[0], points[1]); + + int numPoints = count / 2; + int verticesPerPoint = srcBuffer.getVertexCount(); + dstBuffer.alloc(numPoints * verticesPerPoint + (numPoints - 1) * 2); + + for (int i = 0; i < count; i += 2) { + expandRectToCoverVertex(bounds, points[i + 0], points[i + 1]); + dstBuffer.copyInto(srcBuffer, points[i + 0], points[i + 1]); + } + dstBuffer.createDegenerateSeparators(verticesPerPoint); +} + +void PathTessellator::tessellatePoints(const float* points, int count, SkPaint* paint, + const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer) { + const PaintInfo paintInfo(paint, transform); + + // determine point shape + SkPath path; + float radius = paintInfo.halfStrokeWidth; + if (radius == 0.0f) radius = 0.25f; + + if (paintInfo.cap == SkPaint::kRound_Cap) { + path.addCircle(0, 0, radius); + } else { + path.addRect(-radius, -radius, radius, radius); + } + + // calculate outline + Vector outlineVertices; + approximatePathOutlineVertices(path, true, + paintInfo.inverseScaleX * paintInfo.inverseScaleX, + paintInfo.inverseScaleY * paintInfo.inverseScaleY, outlineVertices); + + if (!outlineVertices.size()) return; + + // tessellate, then duplicate outline across points + int numPoints = count / 2; + VertexBuffer tempBuffer; + if (!paintInfo.isAA) { + getFillVerticesFromPerimeter(outlineVertices, tempBuffer); + instanceVertices(tempBuffer, vertexBuffer, points, count, bounds); + } else { + getFillVerticesFromPerimeterAA(paintInfo, outlineVertices, tempBuffer); + instanceVertices(tempBuffer, vertexBuffer, points, count, bounds); + } + + expandBoundsForStroke(bounds, paint, true); // force-expand bounds to incorporate stroke } void PathTessellator::tessellateLines(const float* points, int count, SkPaint* paint, diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h index 596d49d8f876..85797fcf8538 100644 --- a/libs/hwui/PathTessellator.h +++ b/libs/hwui/PathTessellator.h @@ -30,7 +30,7 @@ class VertexBuffer { public: VertexBuffer(): mBuffer(0), - mSize(0), + mVertexCount(0), mCleanupMethod(NULL) {} @@ -44,30 +44,42 @@ public: multiple regions within a single VertexBuffer, such as with PathTessellator::tesselateLines() */ template - TYPE* alloc(int size) { - if (mSize) { + TYPE* alloc(int vertexCount) { + if (mVertexCount) { TYPE* reallocBuffer = (TYPE*)mReallocBuffer; // already have allocated the buffer, re-allocate space within if (mReallocBuffer != mBuffer) { // not first re-allocation, leave space for degenerate triangles to separate strips reallocBuffer += 2; } - mReallocBuffer = reallocBuffer + size; + mReallocBuffer = reallocBuffer + vertexCount; return reallocBuffer; } - mSize = size; - mReallocBuffer = mBuffer = (void*)new TYPE[size]; + mVertexCount = vertexCount; + mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount]; mCleanupMethod = &(cleanup); return (TYPE*)mBuffer; } - void* getBuffer() const { return mBuffer; } - unsigned int getSize() const { return mSize; } + template + void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) { + int verticesToCopy = srcBuffer.getVertexCount(); + + TYPE* dst = alloc(verticesToCopy); + TYPE* src = (TYPE*)srcBuffer.getBuffer(); + + for (int i = 0; i < verticesToCopy; i++) { + TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset); + } + } + + void* getBuffer() const { return mBuffer; } // shouldn't be const, since not a const ptr? + unsigned int getVertexCount() const { return mVertexCount; } template void createDegenerateSeparators(int allocSize) { - TYPE* end = (TYPE*)mBuffer + mSize; + TYPE* end = (TYPE*)mBuffer + mVertexCount; for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) { memcpy(degen, degen - 1, sizeof(TYPE)); memcpy(degen + 1, degen + 2, sizeof(TYPE)); @@ -81,7 +93,7 @@ private: } void* mBuffer; - unsigned int mSize; + unsigned int mVertexCount; void* mReallocBuffer; // used for multi-allocation @@ -95,6 +107,9 @@ public: static void tessellatePath(const SkPath& path, const SkPaint* paint, const mat4 *transform, VertexBuffer& vertexBuffer); + static void tessellatePoints(const float* points, int count, SkPaint* paint, + const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer); + static void tessellateLines(const float* points, int count, SkPaint* paint, const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer); diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index dd1aaa2a76bd..4f94afce9164 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -68,24 +68,22 @@ namespace uirenderer { #define PROGRAM_BITMAP_WRAPS_SHIFT 9 #define PROGRAM_BITMAP_WRAPT_SHIFT 11 -#define PROGRAM_GRADIENT_TYPE_SHIFT 33 +#define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type #define PROGRAM_MODULATE_SHIFT 35 -#define PROGRAM_IS_POINT_SHIFT 36 +#define PROGRAM_HAS_AA_SHIFT 36 -#define PROGRAM_HAS_AA_SHIFT 37 +#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 37 +#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 38 -#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 -#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39 +#define PROGRAM_HAS_GAMMA_CORRECTION 39 -#define PROGRAM_HAS_GAMMA_CORRECTION 40 +#define PROGRAM_IS_SIMPLE_GRADIENT 40 -#define PROGRAM_IS_SIMPLE_GRADIENT 41 +#define PROGRAM_HAS_COLORS 41 -#define PROGRAM_HAS_COLORS 42 - -#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43 -#define PROGRAM_EMULATE_STENCIL 44 +#define PROGRAM_HAS_DEBUG_HIGHLIGHT 42 +#define PROGRAM_EMULATE_STENCIL 43 /////////////////////////////////////////////////////////////////////////////// // Types @@ -157,9 +155,6 @@ struct ProgramDescription { SkXfermode::Mode framebufferMode; bool swapSrcDst; - bool isPoint; - float pointSize; - bool hasGammaCorrection; float gamma; @@ -201,9 +196,6 @@ struct ProgramDescription { framebufferMode = SkXfermode::kClear_Mode; swapSrcDst = false; - isPoint = false; - pointSize = 0.0f; - hasGammaCorrection = false; gamma = 2.2f; @@ -269,7 +261,6 @@ struct ProgramDescription { key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT; 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 (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT; if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT; diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 367294cb677d..a5ce6f603663 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -53,8 +53,6 @@ const char* gVS_Header_Uniforms_TextureTransform = const char* gVS_Header_Uniforms = "uniform mat4 projection;\n" \ "uniform mat4 transform;\n"; -const char* gVS_Header_Uniforms_IsPoint = - "uniform mediump float pointSize;\n"; const char* gVS_Header_Uniforms_HasGradient = "uniform mat4 screenSpace;\n"; const char* gVS_Header_Uniforms_HasBitmap = @@ -68,8 +66,6 @@ const char* gVS_Header_Varyings_IsAAVertexShape = "varying float alpha;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying highp vec2 outBitmapTexCoords;\n"; -const char* gVS_Header_Varyings_PointHasBitmap = - "varying highp vec2 outPointBitmapTexCoords;\n"; const char* gVS_Header_Varyings_HasGradient[6] = { // Linear "varying highp vec2 linear;\n" @@ -118,12 +114,8 @@ const char* gVS_Main_OutGradient[6] = { }; const char* gVS_Main_OutBitmapTexCoords = " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; -const char* gVS_Main_OutPointBitmapTexCoords = - " outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; const char* gVS_Main_Position = " gl_Position = projection * transform * position;\n"; -const char* gVS_Main_PointSize = - " gl_PointSize = pointSize;\n"; const char* gVS_Main_AAVertexShape = " alpha = vtxAlpha;\n"; const char* gVS_Footer = @@ -141,9 +133,6 @@ const char* gFS_Header = "precision mediump float;\n\n"; const char* gFS_Uniforms_Color = "uniform vec4 color;\n"; -const char* gFS_Header_Uniforms_PointHasBitmap = - "uniform vec2 textureDimension;\n" - "uniform float pointSize;\n"; const char* gFS_Uniforms_TextureSampler = "uniform sampler2D baseSampler;\n"; const char* gFS_Uniforms_ExternalTextureSampler = @@ -178,10 +167,6 @@ const char* gFS_Main = "\nvoid main(void) {\n" " lowp vec4 fragColor;\n"; -const char* gFS_Main_PointBitmapTexCoords = - " highp vec2 outBitmapTexCoords = outPointBitmapTexCoords + " - "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n"; - const char* gFS_Main_Dither[2] = { // ES 2.0 "texture2D(ditherSampler, ditherTexCoords).a * " STR(DITHER_KERNEL_SIZE_INV_SQUARE), @@ -484,9 +469,6 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasBitmap) { shader.append(gVS_Header_Uniforms_HasBitmap); } - if (description.isPoint) { - shader.append(gVS_Header_Uniforms_IsPoint); - } // Varyings if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); @@ -501,9 +483,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]); } if (description.hasBitmap) { - shader.append(description.isPoint ? - gVS_Header_Varyings_PointHasBitmap : - gVS_Header_Varyings_HasBitmap); + shader.append(gVS_Header_Varyings_HasBitmap); } // Begin the shader @@ -520,12 +500,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Main_OutColors); } if (description.hasBitmap) { - shader.append(description.isPoint ? - gVS_Main_OutPointBitmapTexCoords : - gVS_Main_OutBitmapTexCoords); - } - if (description.isPoint) { - shader.append(gVS_Main_PointSize); + shader.append(gVS_Main_OutBitmapTexCoords); } // Output transformed position shader.append(gVS_Main_Position); @@ -576,9 +551,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]); } if (description.hasBitmap) { - shader.append(description.isPoint ? - gVS_Header_Varyings_PointHasBitmap : - gVS_Header_Varyings_HasBitmap); + shader.append(gVS_Header_Varyings_HasBitmap); } // Uniforms @@ -599,9 +572,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient], gFS_Uniforms_Dither); } - if (description.hasBitmap && description.isPoint) { - shader.append(gFS_Header_Uniforms_PointHasBitmap); - } if (description.hasGammaCorrection) { shader.append(gFS_Uniforms_Gamma); } @@ -609,8 +579,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Optimization for common cases if (!description.isAA && !blendFramebuffer && !description.hasColors && description.colorOp == ProgramDescription::kColorNone && - !description.isPoint && !description.hasDebugHighlight && - !description.emulateStencil) { + !description.hasDebugHighlight && !description.emulateStencil) { bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; @@ -713,9 +682,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.appendFormat(gFS_Main_AddDitherToGradient, gFS_Main_Dither[mHasES3]); } if (description.hasBitmap) { - if (description.isPoint) { - shader.append(gFS_Main_PointBitmapTexCoords); - } if (!description.isBitmapNpot) { shader.append(gFS_Main_FetchBitmap); } else { diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h index 523120e358ba..c06762f7609a 100644 --- a/libs/hwui/Vertex.h +++ b/libs/hwui/Vertex.h @@ -17,6 +17,8 @@ #ifndef ANDROID_HWUI_VERTEX_H #define ANDROID_HWUI_VERTEX_H +#include "Vector.h" + namespace android { namespace uirenderer { @@ -30,6 +32,15 @@ struct Vertex { vertex[0].position[0] = x; vertex[0].position[1] = y; } + + static inline void set(Vertex* vertex, vec2 val) { + set(vertex, val.x, val.y); + } + + static inline void copyWithOffset(Vertex* vertex, const Vertex& src, float x, float y) { + set(vertex, src.position[0] + x, src.position[1] + y); + } + }; // struct Vertex /** @@ -81,6 +92,12 @@ struct AlphaVertex : Vertex { vertex[0].alpha = alpha; } + static inline void copyWithOffset(AlphaVertex* vertex, const AlphaVertex& src, + float x, float y) { + Vertex::set(vertex, src.position[0] + x, src.position[1] + y); + vertex[0].alpha = src.alpha; + } + static inline void setColor(AlphaVertex* vertex, float alpha) { vertex[0].alpha = alpha; } diff --git a/tests/CanvasCompare/res/layout/manual_layout.xml b/tests/CanvasCompare/res/layout/manual_layout.xml index 1a9288ce1993..d7838eb65401 100644 --- a/tests/CanvasCompare/res/layout/manual_layout.xml +++ b/tests/CanvasCompare/res/layout/manual_layout.xml @@ -64,7 +64,7 @@ -