diff options
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 115 |
1 files changed, 75 insertions, 40 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 87c3a47..684d5e1 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -193,6 +193,11 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto syncState(); + // Functors break the tiling extension in pretty spectacular ways + // This ensures we don't use tiling when a functor is going to be + // invoked during the frame + mSuppressTiling = mCaches.hasRegisteredFunctors(); + mTilingSnapshot = mSnapshot; startTiling(mTilingSnapshot, true); @@ -221,17 +226,19 @@ void OpenGLRenderer::syncState() { } void OpenGLRenderer::startTiling(const sp<Snapshot>& s, bool opaque) { - Rect* clip = mTilingSnapshot->clipRect; - if (s->flags & Snapshot::kFlagIsFboLayer) { - clip = s->clipRect; - } + if (!mSuppressTiling) { + Rect* clip = mTilingSnapshot->clipRect; + if (s->flags & Snapshot::kFlagIsFboLayer) { + clip = s->clipRect; + } - mCaches.startTiling(clip->left, s->height - clip->bottom, - clip->right - clip->left, clip->bottom - clip->top, opaque); + mCaches.startTiling(clip->left, s->height - clip->bottom, + clip->right - clip->left, clip->bottom - clip->top, opaque); + } } void OpenGLRenderer::endTiling() { - mCaches.endTiling(); + if (!mSuppressTiling) mCaches.endTiling(); } void OpenGLRenderer::finish() { @@ -1248,6 +1255,15 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl return !clip.intersects(transformed); } +bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint) { + if (paint->getStyle() != SkPaint::kFill_Style) { + float outset = paint->getStrokeWidth() * 0.5f; + return quickReject(left - outset, top - outset, right + outset, bottom + outset); + } else { + return quickReject(left, top, right, bottom); + } +} + bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { if (mSnapshot->isIgnored()) { return true; @@ -1490,7 +1506,7 @@ void OpenGLRenderer::setupDrawTextGammaUniforms() { void OpenGLRenderer::setupDrawSimpleMesh() { bool force = mCaches.bindMeshBuffer(); - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0); + mCaches.bindPositionVertexPointer(force, 0); mCaches.unbindIndicesBuffer(); } @@ -1523,9 +1539,9 @@ void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint v force = mCaches.unbindMeshBuffer(); } - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices); + mCaches.bindPositionVertexPointer(force, vertices); if (mCaches.currentProgram->texCoords >= 0) { - mCaches.bindTexCoordsVertexPointer(force, mCaches.currentProgram->texCoords, texCoords); + mCaches.bindTexCoordsVertexPointer(force, texCoords); } mCaches.unbindIndicesBuffer(); @@ -1533,16 +1549,15 @@ void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint v void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords) { bool force = mCaches.unbindMeshBuffer(); - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices); + mCaches.bindPositionVertexPointer(force, vertices); if (mCaches.currentProgram->texCoords >= 0) { - mCaches.bindTexCoordsVertexPointer(force, mCaches.currentProgram->texCoords, texCoords); + mCaches.bindTexCoordsVertexPointer(force, texCoords); } } void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) { bool force = mCaches.unbindMeshBuffer(); - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, - vertices, gVertexStride); + mCaches.bindPositionVertexPointer(force, vertices, gVertexStride); mCaches.unbindIndicesBuffer(); } @@ -1560,8 +1575,7 @@ void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) { void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords, GLvoid* lengthCoords, float boundaryWidthProportion, int& widthSlot, int& lengthSlot) { bool force = mCaches.unbindMeshBuffer(); - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, - vertices, gAAVertexStride); + mCaches.bindPositionVertexPointer(force, vertices, gAAVertexStride); mCaches.resetTexCoordsVertexPointer(); mCaches.unbindIndicesBuffer(); @@ -1919,15 +1933,23 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const } /** - * This function uses a similar approach to that of AA lines in the drawLines() function. - * We expand the rectangle by a half pixel in screen space on all sides. However, instead of using - * a fragment shader to compute the translucency of the color from its position, we simply use a - * varying parameter to define how far a given pixel is into the region. + * Renders a convex path via tessellation. For AA paths, this function uses a similar approach to + * that of AA lines in the drawLines() function. We expand the convex path by a half pixel in + * screen space in all directions. However, instead of using a fragment shader to compute the + * translucency of the color from its position, we simply use a varying parameter to define how far + * a given pixel is from the edge. For non-AA paths, the expansion and alpha varying are not used. + * + * Doesn't yet support joins, caps, or path effects. */ -void OpenGLRenderer::drawConvexPath(const SkPath& path, int color, SkXfermode::Mode mode, bool isAA) { +void OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) { + int color = paint->getColor(); + SkPaint::Style style = paint->getStyle(); + SkXfermode::Mode mode = getXfermode(paint->getXfermode()); + bool isAA = paint->isAntiAlias(); + VertexBuffer vertexBuffer; // TODO: try clipping large paths to viewport - PathRenderer::convexPathFillVertices(path, mSnapshot->transform, vertexBuffer, isAA); + PathRenderer::convexPathVertices(path, paint, mSnapshot->transform, vertexBuffer); setupDraw(); setupDrawNoTexture(); @@ -1938,15 +1960,14 @@ void OpenGLRenderer::drawConvexPath(const SkPath& path, int color, SkXfermode::M setupDrawShader(); setupDrawBlending(isAA, mode); setupDrawProgram(); - setupDrawModelViewIdentity(true); + setupDrawModelViewIdentity(); setupDrawColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderIdentityUniforms(); void* vertices = vertexBuffer.getBuffer(); bool force = mCaches.unbindMeshBuffer(); - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, - vertices, isAA ? gAlphaVertexStride : gVertexStride); + mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride); mCaches.resetTexCoordsVertexPointer(); mCaches.unbindIndicesBuffer(); @@ -1960,7 +1981,7 @@ void OpenGLRenderer::drawConvexPath(const SkPath& path, int color, SkXfermode::M glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords); } - SkRect bounds = path.getBounds(); + SkRect bounds = PathRenderer::computePathBounds(path, paint); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize()); @@ -2050,7 +2071,7 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { setupDrawShader(); setupDrawBlending(isAA, mode); setupDrawProgram(); - setupDrawModelViewIdentity(true); + setupDrawModelViewIdentity(); setupDrawColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderIdentityUniforms(); @@ -2330,11 +2351,11 @@ status_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* tex status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, SkPaint* p) { - if (mSnapshot->isIgnored() || quickReject(left, top, right, bottom)) { + if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) { return DrawGlInfo::kStatusDone; } - if (p->getStyle() != SkPaint::kFill_Style) { + if (p->getPathEffect() != 0) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect( right - left, bottom - top, rx, ry, p); @@ -2343,37 +2364,47 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float 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); - drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), p->isAntiAlias()); + drawConvexPath(path, p); return DrawGlInfo::kStatusDrew; } status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { - if (mSnapshot->isIgnored() || quickReject(x - radius, y - radius, x + radius, y + radius)) { + if (mSnapshot->isIgnored() || quickRejectPreStroke(x - radius, y - radius, + x + radius, y + radius, p)) { return DrawGlInfo::kStatusDone; } - - if (p->getStyle() != SkPaint::kFill_Style) { + if (p->getPathEffect() != 0) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, p); return drawShape(x - radius, y - radius, texture, p); } SkPath path; - path.addCircle(x, y, radius); - drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), p->isAntiAlias()); + if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { + path.addCircle(x, y, radius + p->getStrokeWidth() / 2); + } else { + path.addCircle(x, y, radius); + } + drawConvexPath(path, p); return DrawGlInfo::kStatusDrew; } status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, SkPaint* p) { - if (mSnapshot->isIgnored() || quickReject(left, top, right, bottom)) { + if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) { return DrawGlInfo::kStatusDone; } - if (p->getStyle() != SkPaint::kFill_Style) { + if (p->getPathEffect() != 0) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, p); return drawShape(left, top, texture, p); @@ -2381,8 +2412,11 @@ status_t OpenGLRenderer::drawOval(float left, float top, float right, float bott SkPath path; SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); + if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { + rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2); + } path.addOval(rect); - drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), p->isAntiAlias()); + drawConvexPath(path, p); return DrawGlInfo::kStatusDrew; } @@ -2402,10 +2436,11 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto } status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { - if (mSnapshot->isIgnored() || quickReject(left, top, right, bottom)) { + if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) { return DrawGlInfo::kStatusDone; } + // only fill style is supported by drawConvexPath, since others have to handle joins if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.rectShapeCache.getRect(right - left, bottom - top, p); @@ -2415,7 +2450,7 @@ status_t OpenGLRenderer::drawRect(float left, float top, float right, float bott if (p->isAntiAlias() && !mSnapshot->transform->isSimple()) { SkPath path; path.addRect(left, top, right, bottom); - drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), true); + drawConvexPath(path, p); } else { drawColorRect(left, top, right, bottom, p->getColor(), getXfermode(p->getXfermode())); } |