summaryrefslogtreecommitdiffstats
path: root/libs/hwui/OpenGLRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r--libs/hwui/OpenGLRenderer.cpp115
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()));
}