diff options
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 233 |
1 files changed, 96 insertions, 137 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 9b9ca12e954a..44b153e7c2b6 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -33,6 +33,7 @@ #include "OpenGLRenderer.h" #include "DisplayListRenderer.h" +#include "PathRenderer.h" #include "Vector.h" namespace android { @@ -473,15 +474,7 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, if (p) { alpha = p->getAlpha(); - if (!mCaches.extensions.hasFramebufferFetch()) { - const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); - if (!isMode) { - // Assume SRC_OVER - mode = SkXfermode::kSrcOver_Mode; - } - } else { - mode = getXfermode(p->getXfermode()); - } + mode = getXfermode(p->getXfermode()); } else { mode = SkXfermode::kSrcOver_Mode; } @@ -1193,12 +1186,12 @@ void OpenGLRenderer::setupDrawNoTexture() { mCaches.disbaleTexCoordsVertexArray(); } -void OpenGLRenderer::setupDrawAALine() { +void OpenGLRenderer::setupDrawAA() { mDescription.isAA = true; } -void OpenGLRenderer::setupDrawAARect() { - mDescription.isAARect = true; +void OpenGLRenderer::setupDrawVertexShape() { + mDescription.isVertexShape = true; } void OpenGLRenderer::setupDrawPoint(float pointSize) { @@ -1805,97 +1798,48 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const * 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. */ -void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom, - int color, SkXfermode::Mode mode) { - float inverseScaleX = 1.0f; - float inverseScaleY = 1.0f; +void OpenGLRenderer::drawConvexPath(const SkPath& path, int color, SkXfermode::Mode mode, bool isAA) { + VertexBuffer vertexBuffer; + // TODO: try clipping large paths to viewport + PathRenderer::convexPathFillVertices(path, mSnapshot->transform, vertexBuffer, isAA); - // The quad that we use needs to account for scaling. - if (CC_UNLIKELY(!mSnapshot->transform->isPureTranslate())) { - Matrix4 *mat = mSnapshot->transform; - float m00 = mat->data[Matrix4::kScaleX]; - float m01 = mat->data[Matrix4::kSkewY]; - float m10 = mat->data[Matrix4::kSkewX]; - float m11 = mat->data[Matrix4::kScaleY]; - float scaleX = sqrt(m00 * m00 + m01 * m01); - float scaleY = sqrt(m10 * m10 + m11 * m11); - inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0; - inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0; - } - - float boundarySizeX = .5 * inverseScaleX; - float boundarySizeY = .5 * inverseScaleY; - - float innerLeft = left + boundarySizeX; - float innerRight = right - boundarySizeX; - float innerTop = top + boundarySizeY; - float innerBottom = bottom - boundarySizeY; - - // Adjust the rect by the AA boundary padding - left -= boundarySizeX; - right += boundarySizeX; - top -= boundarySizeY; - bottom += boundarySizeY; - - if (!quickReject(left, top, right, bottom)) { - setupDraw(); - setupDrawNoTexture(); - setupDrawAARect(); - setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); - setupDrawColorFilter(); - setupDrawShader(); - setupDrawBlending(true, mode); - setupDrawProgram(); - setupDrawModelViewIdentity(true); - setupDrawColorUniforms(); - setupDrawColorFilterUniforms(); - setupDrawShaderIdentityUniforms(); + setupDraw(); + setupDrawNoTexture(); + if (isAA) setupDrawAA(); + setupDrawVertexShape(); + setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); + setupDrawColorFilter(); + setupDrawShader(); + setupDrawBlending(isAA, mode); + setupDrawProgram(); + setupDrawModelViewIdentity(true); + setupDrawColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawShaderIdentityUniforms(); - AlphaVertex rects[14]; - AlphaVertex* aVertices = &rects[0]; - void* alphaCoords = ((GLbyte*) aVertices) + gVertexAlphaOffset; + void* vertices = vertexBuffer.getBuffer(); + bool force = mCaches.unbindMeshBuffer(); + mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, + vertices, isAA ? gAlphaVertexStride : gVertexStride); + mCaches.resetTexCoordsVertexPointer(); + mCaches.unbindIndicesBuffer(); - bool force = mCaches.unbindMeshBuffer(); - mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, - aVertices, gAlphaVertexStride); - mCaches.resetTexCoordsVertexPointer(); - mCaches.unbindIndicesBuffer(); + int alphaSlot = -1; + if (isAA) { + void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset; + alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha"); - int alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha"); + // TODO: avoid enable/disable in back to back uses of the alpha attribute glEnableVertexAttribArray(alphaSlot); glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords); + } - // draw left - AlphaVertex::set(aVertices++, left, bottom, 0); - AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1); - AlphaVertex::set(aVertices++, left, top, 0); - AlphaVertex::set(aVertices++, innerLeft, innerTop, 1); - - // draw top - AlphaVertex::set(aVertices++, right, top, 0); - AlphaVertex::set(aVertices++, innerRight, innerTop, 1); - - // draw right - AlphaVertex::set(aVertices++, right, bottom, 0); - AlphaVertex::set(aVertices++, innerRight, innerBottom, 1); - - // draw bottom - AlphaVertex::set(aVertices++, left, bottom, 0); - AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1); - - // draw inner rect (repeating last vertex to create degenerate bridge triangles) - // TODO: also consider drawing the inner rect without the blending-forced shader, if - // blending is expensive. Note: can't use drawColorRect() since it doesn't use vertex - // buffers like below, resulting in slightly different transformed coordinates. - AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1); - AlphaVertex::set(aVertices++, innerLeft, innerTop, 1); - AlphaVertex::set(aVertices++, innerRight, innerBottom, 1); - AlphaVertex::set(aVertices++, innerRight, innerTop, 1); + SkRect bounds = path.getBounds(); + dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform); - dirtyLayer(left, top, right, bottom, *mSnapshot->transform); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 14); + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize()); + if (isAA) { glDisableVertexAttribArray(alphaSlot); } } @@ -1973,7 +1917,7 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { setupDraw(); setupDrawNoTexture(); if (isAA) { - setupDrawAALine(); + setupDrawAA(); } setupDrawColor(paint->getColor(), alpha); setupDrawColorFilter(); @@ -2259,30 +2203,62 @@ 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* paint) { - if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; + float rx, float ry, SkPaint* p) { + if (mSnapshot->isIgnored() || quickReject(left, top, right, bottom)) { + return DrawGlInfo::kStatusDone; + } - mCaches.activeTexture(0); - const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect( - right - left, bottom - top, rx, ry, paint); - return drawShape(left, top, texture, paint); + if (p->getStyle() != SkPaint::kFill_Style) { + mCaches.activeTexture(0); + const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect( + right - left, bottom - top, rx, ry, p); + return drawShape(left, top, texture, p); + } + + SkPath path; + SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); + path.addRoundRect(rect, rx, ry); + drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), p->isAntiAlias()); + + return DrawGlInfo::kStatusDrew; } -status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) { - if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; +status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { + if (mSnapshot->isIgnored() || quickReject(x - radius, y - radius, x + radius, y + radius)) { + return DrawGlInfo::kStatusDone; + } - mCaches.activeTexture(0); - const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, paint); - return drawShape(x - radius, y - radius, texture, paint); + if (p->getStyle() != SkPaint::kFill_Style) { + 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()); + + return DrawGlInfo::kStatusDrew; } status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, - SkPaint* paint) { - if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; + SkPaint* p) { + if (mSnapshot->isIgnored() || quickReject(left, top, right, bottom)) { + return DrawGlInfo::kStatusDone; + } - mCaches.activeTexture(0); - const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, paint); - return drawShape(left, top, texture, paint); + if (p->getStyle() != SkPaint::kFill_Style) { + mCaches.activeTexture(0); + const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, p); + return drawShape(left, top, texture, p); + } + + SkPath path; + SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); + path.addOval(rect); + drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), p->isAntiAlias()); + + return DrawGlInfo::kStatusDrew; } status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, @@ -2299,40 +2275,23 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto return drawShape(left, top, texture, paint); } -status_t OpenGLRenderer::drawRectAsShape(float left, float top, float right, float bottom, - SkPaint* paint) { - if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; - - mCaches.activeTexture(0); - const PathTexture* texture = mCaches.rectShapeCache.getRect(right - left, bottom - top, paint); - return drawShape(left, top, texture, paint); -} - status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { - if (p->getStyle() != SkPaint::kFill_Style) { - return drawRectAsShape(left, top, right, bottom, p); - } - - if (quickReject(left, top, right, bottom)) { + if (mSnapshot->isIgnored() || quickReject(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; } - SkXfermode::Mode mode; - if (!mCaches.extensions.hasFramebufferFetch()) { - const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); - if (!isMode) { - // Assume SRC_OVER - mode = SkXfermode::kSrcOver_Mode; - } - } else { - mode = getXfermode(p->getXfermode()); + if (p->getStyle() != SkPaint::kFill_Style) { + mCaches.activeTexture(0); + const PathTexture* texture = mCaches.rectShapeCache.getRect(right - left, bottom - top, p); + return drawShape(left, top, texture, p); } - int color = p->getColor(); if (p->isAntiAlias() && !mSnapshot->transform->isSimple()) { - drawAARect(left, top, right, bottom, color, mode); + SkPath path; + path.addRect(left, top, right, bottom); + drawConvexPath(path, p->getColor(), getXfermode(p->getXfermode()), true); } else { - drawColorRect(left, top, right, bottom, color, mode); + drawColorRect(left, top, right, bottom, p->getColor(), getXfermode(p->getXfermode())); } return DrawGlInfo::kStatusDrew; |