Loading libs/hwui/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) LayerRenderer.cpp \ Matrix.cpp \ OpenGLRenderer.cpp \ PathRenderer.cpp \ Patch.cpp \ PatchCache.cpp \ PathCache.cpp \ Loading libs/hwui/LayerRenderer.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -349,7 +349,7 @@ void LayerRenderer::flushLayer(Layer* layer) { bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { Caches& caches = Caches::getInstance(); if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize && if (layer && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { GLuint fbo = caches.fboCache.get(); Loading @@ -362,6 +362,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { GLuint texture; GLuint previousFbo; GLuint previousViewport[4]; GLenum format; GLenum type; Loading Loading @@ -391,11 +392,13 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { float alpha = layer->getAlpha(); SkXfermode::Mode mode = layer->getMode(); GLuint previousLayerFbo = layer->getFbo(); layer->setAlpha(255, SkXfermode::kSrc_Mode); layer->setFbo(fbo); glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); glGetIntegerv(GL_VIEWPORT, (GLint*) &previousViewport); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenTextures(1, &texture); Loading Loading @@ -463,9 +466,11 @@ error: glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); layer->setAlpha(alpha, mode); layer->setFbo(0); layer->setFbo(previousLayerFbo); glDeleteTextures(1, &texture); caches.fboCache.put(fbo); glViewport(previousViewport[0], previousViewport[1], previousViewport[2], previousViewport[3]); return status; } Loading libs/hwui/Matrix.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -55,21 +55,21 @@ void Matrix4::loadIdentity() { mSimpleMatrix = true; } bool Matrix4::changesBounds() { bool Matrix4::changesBounds() const { return !(data[0] == 1.0f && data[1] == 0.0f && data[2] == 0.0f && data[4] == 0.0f && data[5] == 1.0f && data[6] == 0.0f && data[8] == 0.0f && data[9] == 0.0f && data[10] == 1.0f); } bool Matrix4::isPureTranslate() { bool Matrix4::isPureTranslate() const { return mSimpleMatrix && data[kScaleX] == 1.0f && data[kScaleY] == 1.0f; } bool Matrix4::isSimple() { bool Matrix4::isSimple() const { return mSimpleMatrix; } bool Matrix4::isIdentity() { bool Matrix4::isIdentity() const { return mIsIdentity; } Loading libs/hwui/Matrix.h +4 −4 Original line number Diff line number Diff line Loading @@ -112,11 +112,11 @@ public: multiply(u); } bool isPureTranslate(); bool isSimple(); bool isIdentity(); bool isPureTranslate() const; bool isSimple() const; bool isIdentity() const; bool changesBounds(); bool changesBounds() const; void copyTo(float* v) const; void copyTo(SkMatrix& v) const; Loading libs/hwui/OpenGLRenderer.cpp +96 −137 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "OpenGLRenderer.h" #include "DisplayListRenderer.h" #include "PathRenderer.h" #include "Vector.h" namespace android { Loading Loading @@ -540,15 +541,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()); } } else { mode = SkXfermode::kSrcOver_Mode; } Loading Loading @@ -1260,12 +1253,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) { Loading Loading @@ -1872,97 +1865,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; // 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; 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); if (!quickReject(left, top, right, bottom)) { setupDraw(); setupDrawNoTexture(); setupDrawAARect(); if (isAA) setupDrawAA(); setupDrawVertexShape(); setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); setupDrawColorFilter(); setupDrawShader(); setupDrawBlending(true, mode); 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, aVertices, gAlphaVertexStride); vertices, isAA ? gAlphaVertexStride : gVertexStride); mCaches.resetTexCoordsVertexPointer(); mCaches.unbindIndicesBuffer(); int alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha"); int alphaSlot = -1; if (isAA) { void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset; 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); dirtyLayer(left, top, right, bottom, *mSnapshot->transform); SkRect bounds = path.getBounds(); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform); glDrawArrays(GL_TRIANGLE_STRIP, 0, 14); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize()); if (isAA) { glDisableVertexAttribArray(alphaSlot); } } Loading Loading @@ -2040,7 +1984,7 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { setupDraw(); setupDrawNoTexture(); if (isAA) { setupDrawAALine(); setupDrawAA(); } setupDrawColor(paint->getColor(), alpha); setupDrawColorFilter(); Loading Loading @@ -2326,30 +2270,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; } if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect( right - left, bottom - top, rx, ry, paint); return drawShape(left, top, texture, paint); right - left, bottom - top, rx, ry, p); return drawShape(left, top, texture, p); } status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) { if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; 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* p) { if (mSnapshot->isIgnored() || quickReject(x - radius, y - radius, x + radius, y + radius)) { return DrawGlInfo::kStatusDone; } if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, paint); return drawShape(x - radius, y - radius, texture, paint); 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; } if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, paint); return drawShape(left, top, texture, paint); 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, Loading @@ -2366,40 +2342,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; Loading Loading
libs/hwui/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) LayerRenderer.cpp \ Matrix.cpp \ OpenGLRenderer.cpp \ PathRenderer.cpp \ Patch.cpp \ PatchCache.cpp \ PathCache.cpp \ Loading
libs/hwui/LayerRenderer.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -349,7 +349,7 @@ void LayerRenderer::flushLayer(Layer* layer) { bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { Caches& caches = Caches::getInstance(); if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize && if (layer && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { GLuint fbo = caches.fboCache.get(); Loading @@ -362,6 +362,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { GLuint texture; GLuint previousFbo; GLuint previousViewport[4]; GLenum format; GLenum type; Loading Loading @@ -391,11 +392,13 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { float alpha = layer->getAlpha(); SkXfermode::Mode mode = layer->getMode(); GLuint previousLayerFbo = layer->getFbo(); layer->setAlpha(255, SkXfermode::kSrc_Mode); layer->setFbo(fbo); glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); glGetIntegerv(GL_VIEWPORT, (GLint*) &previousViewport); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenTextures(1, &texture); Loading Loading @@ -463,9 +466,11 @@ error: glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); layer->setAlpha(alpha, mode); layer->setFbo(0); layer->setFbo(previousLayerFbo); glDeleteTextures(1, &texture); caches.fboCache.put(fbo); glViewport(previousViewport[0], previousViewport[1], previousViewport[2], previousViewport[3]); return status; } Loading
libs/hwui/Matrix.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -55,21 +55,21 @@ void Matrix4::loadIdentity() { mSimpleMatrix = true; } bool Matrix4::changesBounds() { bool Matrix4::changesBounds() const { return !(data[0] == 1.0f && data[1] == 0.0f && data[2] == 0.0f && data[4] == 0.0f && data[5] == 1.0f && data[6] == 0.0f && data[8] == 0.0f && data[9] == 0.0f && data[10] == 1.0f); } bool Matrix4::isPureTranslate() { bool Matrix4::isPureTranslate() const { return mSimpleMatrix && data[kScaleX] == 1.0f && data[kScaleY] == 1.0f; } bool Matrix4::isSimple() { bool Matrix4::isSimple() const { return mSimpleMatrix; } bool Matrix4::isIdentity() { bool Matrix4::isIdentity() const { return mIsIdentity; } Loading
libs/hwui/Matrix.h +4 −4 Original line number Diff line number Diff line Loading @@ -112,11 +112,11 @@ public: multiply(u); } bool isPureTranslate(); bool isSimple(); bool isIdentity(); bool isPureTranslate() const; bool isSimple() const; bool isIdentity() const; bool changesBounds(); bool changesBounds() const; void copyTo(float* v) const; void copyTo(SkMatrix& v) const; Loading
libs/hwui/OpenGLRenderer.cpp +96 −137 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "OpenGLRenderer.h" #include "DisplayListRenderer.h" #include "PathRenderer.h" #include "Vector.h" namespace android { Loading Loading @@ -540,15 +541,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()); } } else { mode = SkXfermode::kSrcOver_Mode; } Loading Loading @@ -1260,12 +1253,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) { Loading Loading @@ -1872,97 +1865,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; // 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; 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); if (!quickReject(left, top, right, bottom)) { setupDraw(); setupDrawNoTexture(); setupDrawAARect(); if (isAA) setupDrawAA(); setupDrawVertexShape(); setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); setupDrawColorFilter(); setupDrawShader(); setupDrawBlending(true, mode); 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, aVertices, gAlphaVertexStride); vertices, isAA ? gAlphaVertexStride : gVertexStride); mCaches.resetTexCoordsVertexPointer(); mCaches.unbindIndicesBuffer(); int alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha"); int alphaSlot = -1; if (isAA) { void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset; 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); dirtyLayer(left, top, right, bottom, *mSnapshot->transform); SkRect bounds = path.getBounds(); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *mSnapshot->transform); glDrawArrays(GL_TRIANGLE_STRIP, 0, 14); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize()); if (isAA) { glDisableVertexAttribArray(alphaSlot); } } Loading Loading @@ -2040,7 +1984,7 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { setupDraw(); setupDrawNoTexture(); if (isAA) { setupDrawAALine(); setupDrawAA(); } setupDrawColor(paint->getColor(), alpha); setupDrawColorFilter(); Loading Loading @@ -2326,30 +2270,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; } if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect( right - left, bottom - top, rx, ry, paint); return drawShape(left, top, texture, paint); right - left, bottom - top, rx, ry, p); return drawShape(left, top, texture, p); } status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) { if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; 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* p) { if (mSnapshot->isIgnored() || quickReject(x - radius, y - radius, x + radius, y + radius)) { return DrawGlInfo::kStatusDone; } if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, paint); return drawShape(x - radius, y - radius, texture, paint); 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; } if (p->getStyle() != SkPaint::kFill_Style) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.ovalShapeCache.getOval(right - left, bottom - top, paint); return drawShape(left, top, texture, paint); 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, Loading @@ -2366,40 +2342,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; Loading