diff options
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 134 |
1 files changed, 28 insertions, 106 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 71836dd..31f399a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -287,6 +287,7 @@ void OpenGLRenderer::finish() { // of the current frame if (getTargetFbo() == 0) { mCaches.pathCache.trim(); + mCaches.tessellationCache.trim(); } if (!suppressErrorChecks()) { @@ -2390,7 +2391,7 @@ status_t OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* return DrawGlInfo::kStatusDrew; } -status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode, +status_t OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, const VertexBuffer& vertexBuffer, const SkPaint* paint, bool useOffset) { // not missing call to quickReject/dirtyLayer, always done at a higher level if (!vertexBuffer.getVertexCount()) { @@ -2398,6 +2399,9 @@ status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode, return DrawGlInfo::kStatusDone; } + const Rect& bounds = vertexBuffer.getBounds(); + dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform()); + int color = paint->getColor(); bool isAA = paint->isAntiAlias(); @@ -2409,7 +2413,7 @@ status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode, setupDrawShader(getShader(paint)); setupDrawBlending(paint, isAA); setupDrawProgram(); - setupDrawModelView(kModelViewMode_Translate, useOffset, 0, 0, 0, 0); + setupDrawModelView(kModelViewMode_Translate, useOffset, translateX, translateY, 0, 0); setupDrawColorUniforms(getShader(paint)); setupDrawColorFilterUniforms(getColorFilter(paint)); setupDrawShaderUniforms(getShader(paint)); @@ -2429,13 +2433,14 @@ status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode, glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords); } - if (mode == kVertexBufferMode_Standard) { + const VertexBuffer::Mode mode = vertexBuffer.getMode(); + if (mode == VertexBuffer::kStandard) { mCaches.unbindIndicesBuffer(); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount()); - } else if (mode == kVertexBufferMode_OnePolyRingShadow) { + } else if (mode == VertexBuffer::kOnePolyRingShadow) { mCaches.bindShadowIndicesBuffer(); glDrawElements(GL_TRIANGLE_STRIP, ONE_POLY_RING_SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0); - } else if (mode == kVertexBufferMode_TwoPolyRingShadow) { + } else if (mode == VertexBuffer::kTwoPolyRingShadow) { mCaches.bindShadowIndicesBuffer(); glDrawElements(GL_TRIANGLE_STRIP, TWO_POLY_RING_SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0); } @@ -2460,14 +2465,7 @@ status_t OpenGLRenderer::drawConvexPath(const SkPath& path, const SkPaint* paint VertexBuffer vertexBuffer; // TODO: try clipping large paths to viewport PathTessellator::tessellatePath(path, paint, *currentTransform(), vertexBuffer); - - if (hasLayer()) { - SkRect bounds = path.getBounds(); - PathTessellator::expandBoundsForStroke(bounds, paint); - dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform()); - } - - return drawVertexBuffer(kVertexBufferMode_Standard, vertexBuffer, paint); + return drawVertexBuffer(vertexBuffer, paint); } /** @@ -2487,18 +2485,15 @@ status_t OpenGLRenderer::drawLines(const float* points, int count, const SkPaint count &= ~0x3; // round down to nearest four VertexBuffer buffer; - SkRect bounds; - PathTessellator::tessellateLines(points, count, paint, *currentTransform(), bounds, buffer); + PathTessellator::tessellateLines(points, count, paint, *currentTransform(), buffer); + const Rect& bounds = buffer.getBounds(); - // can't pass paint, since style would be checked for outset. outset done by tessellation. - if (quickRejectSetupScissor(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { + if (quickRejectSetupScissor(bounds.left, bounds.top, bounds.right, bounds.bottom)) { return DrawGlInfo::kStatusDone; } - dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform()); - bool useOffset = !paint->isAntiAlias(); - return drawVertexBuffer(kVertexBufferMode_Standard, buffer, paint, useOffset); + return drawVertexBuffer(buffer, paint, useOffset); } status_t OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) { @@ -2507,18 +2502,15 @@ status_t OpenGLRenderer::drawPoints(const float* points, int count, const SkPain count &= ~0x1; // round down to nearest two VertexBuffer buffer; - SkRect bounds; - PathTessellator::tessellatePoints(points, count, paint, *currentTransform(), bounds, buffer); + PathTessellator::tessellatePoints(points, count, paint, *currentTransform(), buffer); - // can't pass paint, since style would be checked for outset. outset done by tessellation. - if (quickRejectSetupScissor(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { + const Rect& bounds = buffer.getBounds(); + if (quickRejectSetupScissor(bounds.left, bounds.top, bounds.right, bounds.bottom)) { return DrawGlInfo::kStatusDone; } - dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform()); - bool useOffset = !paint->isAntiAlias(); - return drawVertexBuffer(kVertexBufferMode_Standard, buffer, paint, useOffset); + return drawVertexBuffer(buffer, paint, useOffset); } status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { @@ -2564,16 +2556,9 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float return drawShape(left, top, texture, p); } - SkPath path; - SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); - if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { - float outset = p->getStrokeWidth() / 2; - rect.outset(outset, outset); - rx += outset; - ry += outset; - } - path.addRoundRect(rect, rx, ry); - return drawConvexPath(path, p); + const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(*currentTransform(), + right - left, bottom - top, rx, ry, p); + return drawVertexBuffer(left, top, *vertexBuffer, p); } status_t OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) { @@ -3192,8 +3177,8 @@ static void mapPointFakeZ(Vector3& point, const mat4& transformXY, const mat4& t transformXY.mapPoint(point.x, point.y); } -status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ, - float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter) { +status_t OpenGLRenderer::drawShadow(float casterAlpha, + const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) { if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone; // TODO: use quickRejectWithScissor. For now, always force enable scissor. @@ -3202,77 +3187,14 @@ status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& c SkPaint paint; paint.setAntiAlias(true); // want to use AlphaVertex - // tessellate caster outline into a 2d polygon - Vector<Vertex> casterVertices2d; - const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value - PathTessellator::approximatePathOutlineVertices(*casterPerimeter, - casterRefinementThresholdSquared, casterVertices2d); - if (!ShadowTessellator::isClockwisePath(*casterPerimeter)) { - ShadowTessellator::reverseVertexArray(casterVertices2d.editArray(), - casterVertices2d.size()); - } - - if (casterVertices2d.size() == 0) { - // empty caster polygon computed from path - return DrawGlInfo::kStatusDone; - } - - // map 2d caster poly into 3d - const int casterVertexCount = casterVertices2d.size(); - Vector3 casterPolygon[casterVertexCount]; - float minZ = FLT_MAX; - float maxZ = -FLT_MAX; - for (int i = 0; i < casterVertexCount; i++) { - const Vertex& point2d = casterVertices2d[i]; - casterPolygon[i] = Vector3(point2d.x, point2d.y, 0); - mapPointFakeZ(casterPolygon[i], casterTransformXY, casterTransformZ); - minZ = fmin(minZ, casterPolygon[i].z); - maxZ = fmax(maxZ, casterPolygon[i].z); - } - - // map the centroid of the caster into 3d - Vector2 centroid = ShadowTessellator::centroid2d( - reinterpret_cast<const Vector2*>(casterVertices2d.array()), - casterVertexCount); - Vector3 centroid3d(centroid.x, centroid.y, 0); - mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ); - - // if the caster intersects the z=0 plane, lift it in Z so it doesn't - if (minZ < SHADOW_MIN_CASTER_Z) { - float casterLift = SHADOW_MIN_CASTER_Z - minZ; - for (int i = 0; i < casterVertexCount; i++) { - casterPolygon[i].z += casterLift; - } - centroid3d.z += casterLift; - } - - // Check whether we want to draw the shadow at all by checking the caster's - // bounds against clip. - // We only have ortho projection, so we can just ignore the Z in caster for - // simple rejection calculation. - Rect localClip = mSnapshot->getLocalClip(); - Rect casterBounds(casterPerimeter->getBounds()); - casterTransformXY.mapRect(casterBounds); - - bool isCasterOpaque = (casterAlpha == 1.0f) && casterUnclipped; - // draw caster's shadows - if (mCaches.propertyAmbientShadowStrength > 0) { + if (ambientShadowVertexBuffer && mCaches.propertyAmbientShadowStrength > 0) { paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0); - VertexBuffer ambientShadowVertexBuffer; - VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateAmbientShadow( - isCasterOpaque, casterPolygon, casterVertexCount, centroid3d, - casterBounds, localClip, maxZ, ambientShadowVertexBuffer); - drawVertexBuffer(vertexBufferMode, ambientShadowVertexBuffer, &paint); + drawVertexBuffer(*ambientShadowVertexBuffer, &paint); } - if (mCaches.propertySpotShadowStrength > 0) { + if (spotShadowVertexBuffer && mCaches.propertySpotShadowStrength > 0) { paint.setARGB(casterAlpha * mCaches.propertySpotShadowStrength, 0, 0, 0); - VertexBuffer spotShadowVertexBuffer; - VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateSpotShadow( - isCasterOpaque, casterPolygon, casterVertexCount, - *currentTransform(), mLightCenter, mLightRadius, casterBounds, localClip, - spotShadowVertexBuffer); - drawVertexBuffer(vertexBufferMode, spotShadowVertexBuffer, &paint); + drawVertexBuffer(*spotShadowVertexBuffer, &paint); } return DrawGlInfo::kStatusDrew; |