Loading core/jni/android_view_GLES20Canvas.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -298,7 +298,7 @@ static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject cl static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz, static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) { OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) { return renderer->quickRejectNoScissor(left, top, right, bottom); return renderer->quickRejectConservative(left, top, right, bottom); } } static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz, static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz, Loading libs/hwui/DisplayList.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -526,7 +526,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) setViewProperties<T>(renderer, handler, level + 1); setViewProperties<T>(renderer, handler, level + 1); if (mClipToBounds && renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { if (mClipToBounds && renderer.quickRejectConservative(0, 0, mWidth, mHeight)) { DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); renderer.restoreToCount(restoreTo); renderer.restoreToCount(restoreTo); Loading libs/hwui/DisplayListOp.h +6 −3 Original line number Original line Diff line number Diff line Loading @@ -182,9 +182,12 @@ public: } } inline float strokeWidthOutset() { inline float strokeWidthOutset() { float width = mPaint->getStrokeWidth(); // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced if (width == 0) return 0.5f; // account for hairline // 1.0 stroke, treat 1.0 as minimum. return width * 0.5f; // TODO: it would be nice if this could take scale into account, but scale isn't stable // since higher levels of the view hierarchy can change scale out from underneath it. return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f; } } protected: protected: Loading libs/hwui/DisplayListRenderer.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -506,7 +506,7 @@ void DisplayListRenderer::addStateOp(StateOp* op) { void DisplayListRenderer::addDrawOp(DrawOp* op) { void DisplayListRenderer::addDrawOp(DrawOp* op) { Rect localBounds; Rect localBounds; if (op->getLocalBounds(mDrawModifiers, localBounds)) { if (op->getLocalBounds(mDrawModifiers, localBounds)) { bool rejected = quickRejectNoScissor(localBounds.left, localBounds.top, bool rejected = quickRejectConservative(localBounds.left, localBounds.top, localBounds.right, localBounds.bottom); localBounds.right, localBounds.bottom); op->setQuickRejected(rejected); op->setQuickRejected(rejected); } } Loading libs/hwui/OpenGLRenderer.cpp +83 −36 Original line number Original line Diff line number Diff line Loading @@ -1032,7 +1032,8 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer; const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer; bool clipRequired = false; bool clipRequired = false; quickRejectNoScissor(rect, &clipRequired); // safely ignore return, should never be rejected calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom, &clipRequired, false); // safely ignore return, should never be rejected mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); if (fboLayer) { if (fboLayer) { Loading Loading @@ -1629,8 +1630,18 @@ const Rect& OpenGLRenderer::getClipBounds() { return mSnapshot->getLocalClip(); return mSnapshot->getLocalClip(); } } bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom, /** bool snapOut, bool* clipRequired) { * Calculates whether content drawn within the passed bounds would be outside of, or intersect with * the clipRect. Does not modify the scissor. * * @param clipRequired if not null, will be set to true if element intersects clip * (and wasn't rejected) * * @param snapOut if set, the geometry will be treated as having an AA ramp. * See Rect::snapGeometryToPixelBoundaries() */ bool OpenGLRenderer::calculateQuickRejectForScissor(float left, float top, float right, float bottom, bool* clipRequired, bool snapOut) const { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { return true; return true; } } Loading @@ -1644,31 +1655,65 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl if (!clipRect.intersects(r)) return true; if (!clipRect.intersects(r)) return true; // clip is required if geometry intersects clip rect if (clipRequired) *clipRequired = !clipRect.contains(r); if (clipRequired) *clipRequired = !clipRect.contains(r); return false; return false; } } bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, /** * Returns false if drawing won't be clipped out. * * Makes the decision conservatively, by rounding out the mapped rect before comparing with the * clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but * rejection is still desired. * * This function, unlike quickRejectSetupScissor, should be used where precise geometry information * isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass * rejection where precise rejection isn't important, or precise information isn't available. */ bool OpenGLRenderer::quickRejectConservative(float left, float top, float right, float bottom) const { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { return true; } Rect r(left, top, right, bottom); currentTransform().mapRect(r); r.roundOut(); // rounded out to be conservative Rect clipRect(*mSnapshot->clipRect); clipRect.snapToPixelBoundaries(); if (!clipRect.intersects(r)) return true; return false; } /** * Returns false and sets scissor enable based upon bounds if drawing won't be clipped out. * * @param paint if not null, the bounds will be expanded to account for stroke depending on paint * style, and tessellated AA ramp */ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, float bottom, SkPaint* paint) { SkPaint* paint) { // AA geometry will likely have a ramp around it (not accounted for in local bounds). Snap out bool clipRequired = false; // the final mapped rect to ensure correct clipping behavior for the ramp. bool snapOut = paint && paint->isAntiAlias(); bool snapOut = paint->isAntiAlias(); if (paint->getStyle() != SkPaint::kFill_Style) { if (paint && paint->getStyle() != SkPaint::kFill_Style) { float outset = paint->getStrokeWidth() * 0.5f; float outset = paint->getStrokeWidth() * 0.5f; return quickReject(left - outset, top - outset, right + outset, bottom + outset, snapOut); left -= outset; } else { top -= outset; return quickReject(left, top, right, bottom, snapOut); right += outset; } bottom += outset; } } bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom, bool snapOut) { if (calculateQuickRejectForScissor(left, top, right, bottom, &clipRequired, snapOut)) { bool clipRequired = false; if (quickRejectNoScissor(left, top, right, bottom, snapOut, &clipRequired)) { return true; return true; } } if (!isDeferred()) { if (!isDeferred()) { // not quick rejected, so enable the scissor if clipRequired mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); } } return false; return false; Loading Loading @@ -1743,7 +1788,7 @@ Rect* OpenGLRenderer::getClipRect() { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setupDraw(bool clear) { void OpenGLRenderer::setupDraw(bool clear) { // TODO: It would be best if we could do this before quickReject() // TODO: It would be best if we could do this before quickRejectSetupScissor() // changes the scissor test state // changes the scissor test state if (clear) clearLayerRegions(); if (clear) clearLayerRegions(); // Make sure setScissor & setStencil happen at the beginning of // Make sure setScissor & setStencil happen at the beginning of Loading Loading @@ -2123,7 +2168,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkP const float right = left + bitmap->width(); const float right = left + bitmap->width(); const float bottom = top + bitmap->height(); const float bottom = top + bitmap->height(); if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2146,7 +2191,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* const mat4 transform(*matrix); const mat4 transform(*matrix); transform.mapRect(r); transform.mapRect(r); if (quickReject(r.left, r.top, r.right, r.bottom)) { if (quickRejectSetupScissor(r.left, r.top, r.right, r.bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2173,7 +2218,7 @@ status_t OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top, const float right = left + bitmap->width(); const float right = left + bitmap->width(); const float bottom = top + bitmap->height(); const float bottom = top + bitmap->height(); if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2256,7 +2301,7 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes } } } } if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { if (cleanupColors) delete[] colors; if (cleanupColors) delete[] colors; return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2312,7 +2357,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) { SkPaint* paint) { if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) { if (quickRejectSetupScissor(dstLeft, dstTop, dstRight, dstBottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2402,7 +2447,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint) { float left, float top, float right, float bottom, SkPaint* paint) { if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2415,7 +2460,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, SkPaint* paint) { float left, float top, float right, float bottom, SkPaint* paint) { if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2564,7 +2609,7 @@ status_t OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) { if (hasLayer()) { if (hasLayer()) { SkRect bounds = path.getBounds(); SkRect bounds = path.getBounds(); PathTessellator::expandBoundsForStroke(bounds, paint, false); PathTessellator::expandBoundsForStroke(bounds, paint); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); } } Loading @@ -2591,7 +2636,8 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { SkRect bounds; SkRect bounds; PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer); PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer); if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { // 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)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2610,7 +2656,8 @@ status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) { SkRect bounds; SkRect bounds; PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer); PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer); if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { // 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)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2647,7 +2694,7 @@ status_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* tex status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, SkPaint* p) { float rx, float ry, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2672,7 +2719,7 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float } } status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(x - radius, y - radius, if (mSnapshot->isIgnored() || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p) || x + radius, y + radius, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; Loading @@ -2694,7 +2741,7 @@ status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, SkPaint* p) { SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2716,7 +2763,7 @@ status_t OpenGLRenderer::drawOval(float left, float top, float right, float bott status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, SkPaint* p) { float startAngle, float sweepAngle, bool useCenter, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2753,7 +2800,7 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto #define SkPaintDefaults_MiterLimit SkIntToScalar(4) #define SkPaintDefaults_MiterLimit SkIntToScalar(4) status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2917,7 +2964,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f // The checks for corner-case ignorable text and quick rejection is only done for immediate // The checks for corner-case ignorable text and quick rejection is only done for immediate // drawing as ops from DeferredDisplayList are already filtered for these // drawing as ops from DeferredDisplayList are already filtered for these if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint) || if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint) || quickReject(bounds)) { quickRejectSetupScissor(bounds)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } } } Loading Loading @@ -3062,8 +3109,8 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { } } bool clipRequired = false; bool clipRequired = false; const bool rejected = quickRejectNoScissor(x, y, const bool rejected = calculateQuickRejectForScissor(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), false, &clipRequired); x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired, false); if (rejected) { if (rejected) { if (transform && !transform->isIdentity()) { if (transform && !transform->isIdentity()) { Loading Loading @@ -3235,7 +3282,7 @@ Texture* OpenGLRenderer::getTexture(SkBitmap* bitmap) { void OpenGLRenderer::drawPathTexture(const PathTexture* texture, void OpenGLRenderer::drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint) { float x, float y, SkPaint* paint) { if (quickReject(x, y, x + texture->width, y + texture->height)) { if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) { return; return; } } Loading Loading @@ -3356,7 +3403,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color bottom = fmaxf(bottom, b); bottom = fmaxf(bottom, b); } } if (clip && quickReject(left, top, right, bottom)) { if (clip && quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading
core/jni/android_view_GLES20Canvas.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -298,7 +298,7 @@ static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject cl static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz, static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) { OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) { return renderer->quickRejectNoScissor(left, top, right, bottom); return renderer->quickRejectConservative(left, top, right, bottom); } } static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz, static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz, Loading
libs/hwui/DisplayList.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -526,7 +526,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) setViewProperties<T>(renderer, handler, level + 1); setViewProperties<T>(renderer, handler, level + 1); if (mClipToBounds && renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { if (mClipToBounds && renderer.quickRejectConservative(0, 0, mWidth, mHeight)) { DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); renderer.restoreToCount(restoreTo); renderer.restoreToCount(restoreTo); Loading
libs/hwui/DisplayListOp.h +6 −3 Original line number Original line Diff line number Diff line Loading @@ -182,9 +182,12 @@ public: } } inline float strokeWidthOutset() { inline float strokeWidthOutset() { float width = mPaint->getStrokeWidth(); // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced if (width == 0) return 0.5f; // account for hairline // 1.0 stroke, treat 1.0 as minimum. return width * 0.5f; // TODO: it would be nice if this could take scale into account, but scale isn't stable // since higher levels of the view hierarchy can change scale out from underneath it. return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f; } } protected: protected: Loading
libs/hwui/DisplayListRenderer.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -506,7 +506,7 @@ void DisplayListRenderer::addStateOp(StateOp* op) { void DisplayListRenderer::addDrawOp(DrawOp* op) { void DisplayListRenderer::addDrawOp(DrawOp* op) { Rect localBounds; Rect localBounds; if (op->getLocalBounds(mDrawModifiers, localBounds)) { if (op->getLocalBounds(mDrawModifiers, localBounds)) { bool rejected = quickRejectNoScissor(localBounds.left, localBounds.top, bool rejected = quickRejectConservative(localBounds.left, localBounds.top, localBounds.right, localBounds.bottom); localBounds.right, localBounds.bottom); op->setQuickRejected(rejected); op->setQuickRejected(rejected); } } Loading
libs/hwui/OpenGLRenderer.cpp +83 −36 Original line number Original line Diff line number Diff line Loading @@ -1032,7 +1032,8 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer; const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer; bool clipRequired = false; bool clipRequired = false; quickRejectNoScissor(rect, &clipRequired); // safely ignore return, should never be rejected calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom, &clipRequired, false); // safely ignore return, should never be rejected mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); if (fboLayer) { if (fboLayer) { Loading Loading @@ -1629,8 +1630,18 @@ const Rect& OpenGLRenderer::getClipBounds() { return mSnapshot->getLocalClip(); return mSnapshot->getLocalClip(); } } bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom, /** bool snapOut, bool* clipRequired) { * Calculates whether content drawn within the passed bounds would be outside of, or intersect with * the clipRect. Does not modify the scissor. * * @param clipRequired if not null, will be set to true if element intersects clip * (and wasn't rejected) * * @param snapOut if set, the geometry will be treated as having an AA ramp. * See Rect::snapGeometryToPixelBoundaries() */ bool OpenGLRenderer::calculateQuickRejectForScissor(float left, float top, float right, float bottom, bool* clipRequired, bool snapOut) const { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { return true; return true; } } Loading @@ -1644,31 +1655,65 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl if (!clipRect.intersects(r)) return true; if (!clipRect.intersects(r)) return true; // clip is required if geometry intersects clip rect if (clipRequired) *clipRequired = !clipRect.contains(r); if (clipRequired) *clipRequired = !clipRect.contains(r); return false; return false; } } bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, /** * Returns false if drawing won't be clipped out. * * Makes the decision conservatively, by rounding out the mapped rect before comparing with the * clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but * rejection is still desired. * * This function, unlike quickRejectSetupScissor, should be used where precise geometry information * isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass * rejection where precise rejection isn't important, or precise information isn't available. */ bool OpenGLRenderer::quickRejectConservative(float left, float top, float right, float bottom) const { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { return true; } Rect r(left, top, right, bottom); currentTransform().mapRect(r); r.roundOut(); // rounded out to be conservative Rect clipRect(*mSnapshot->clipRect); clipRect.snapToPixelBoundaries(); if (!clipRect.intersects(r)) return true; return false; } /** * Returns false and sets scissor enable based upon bounds if drawing won't be clipped out. * * @param paint if not null, the bounds will be expanded to account for stroke depending on paint * style, and tessellated AA ramp */ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, float bottom, SkPaint* paint) { SkPaint* paint) { // AA geometry will likely have a ramp around it (not accounted for in local bounds). Snap out bool clipRequired = false; // the final mapped rect to ensure correct clipping behavior for the ramp. bool snapOut = paint && paint->isAntiAlias(); bool snapOut = paint->isAntiAlias(); if (paint->getStyle() != SkPaint::kFill_Style) { if (paint && paint->getStyle() != SkPaint::kFill_Style) { float outset = paint->getStrokeWidth() * 0.5f; float outset = paint->getStrokeWidth() * 0.5f; return quickReject(left - outset, top - outset, right + outset, bottom + outset, snapOut); left -= outset; } else { top -= outset; return quickReject(left, top, right, bottom, snapOut); right += outset; } bottom += outset; } } bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom, bool snapOut) { if (calculateQuickRejectForScissor(left, top, right, bottom, &clipRequired, snapOut)) { bool clipRequired = false; if (quickRejectNoScissor(left, top, right, bottom, snapOut, &clipRequired)) { return true; return true; } } if (!isDeferred()) { if (!isDeferred()) { // not quick rejected, so enable the scissor if clipRequired mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); } } return false; return false; Loading Loading @@ -1743,7 +1788,7 @@ Rect* OpenGLRenderer::getClipRect() { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setupDraw(bool clear) { void OpenGLRenderer::setupDraw(bool clear) { // TODO: It would be best if we could do this before quickReject() // TODO: It would be best if we could do this before quickRejectSetupScissor() // changes the scissor test state // changes the scissor test state if (clear) clearLayerRegions(); if (clear) clearLayerRegions(); // Make sure setScissor & setStencil happen at the beginning of // Make sure setScissor & setStencil happen at the beginning of Loading Loading @@ -2123,7 +2168,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkP const float right = left + bitmap->width(); const float right = left + bitmap->width(); const float bottom = top + bitmap->height(); const float bottom = top + bitmap->height(); if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2146,7 +2191,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* const mat4 transform(*matrix); const mat4 transform(*matrix); transform.mapRect(r); transform.mapRect(r); if (quickReject(r.left, r.top, r.right, r.bottom)) { if (quickRejectSetupScissor(r.left, r.top, r.right, r.bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2173,7 +2218,7 @@ status_t OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top, const float right = left + bitmap->width(); const float right = left + bitmap->width(); const float bottom = top + bitmap->height(); const float bottom = top + bitmap->height(); if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2256,7 +2301,7 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes } } } } if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { if (cleanupColors) delete[] colors; if (cleanupColors) delete[] colors; return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2312,7 +2357,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) { SkPaint* paint) { if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) { if (quickRejectSetupScissor(dstLeft, dstTop, dstRight, dstBottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2402,7 +2447,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint) { float left, float top, float right, float bottom, SkPaint* paint) { if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2415,7 +2460,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, SkPaint* paint) { float left, float top, float right, float bottom, SkPaint* paint) { if (quickReject(left, top, right, bottom)) { if (quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2564,7 +2609,7 @@ status_t OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) { if (hasLayer()) { if (hasLayer()) { SkRect bounds = path.getBounds(); SkRect bounds = path.getBounds(); PathTessellator::expandBoundsForStroke(bounds, paint, false); PathTessellator::expandBoundsForStroke(bounds, paint); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform()); } } Loading @@ -2591,7 +2636,8 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { SkRect bounds; SkRect bounds; PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer); PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer); if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { // 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)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2610,7 +2656,8 @@ status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) { SkRect bounds; SkRect bounds; PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer); PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer); if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) { // 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)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2647,7 +2694,7 @@ status_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* tex status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, SkPaint* p) { float rx, float ry, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2672,7 +2719,7 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float } } status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(x - radius, y - radius, if (mSnapshot->isIgnored() || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p) || x + radius, y + radius, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; Loading @@ -2694,7 +2741,7 @@ status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom, SkPaint* p) { SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading @@ -2716,7 +2763,7 @@ status_t OpenGLRenderer::drawOval(float left, float top, float right, float bott status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, SkPaint* p) { float startAngle, float sweepAngle, bool useCenter, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2753,7 +2800,7 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto #define SkPaintDefaults_MiterLimit SkIntToScalar(4) #define SkPaintDefaults_MiterLimit SkIntToScalar(4) status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) { if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) || if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading Loading @@ -2917,7 +2964,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f // The checks for corner-case ignorable text and quick rejection is only done for immediate // The checks for corner-case ignorable text and quick rejection is only done for immediate // drawing as ops from DeferredDisplayList are already filtered for these // drawing as ops from DeferredDisplayList are already filtered for these if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint) || if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint) || quickReject(bounds)) { quickRejectSetupScissor(bounds)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } } } Loading Loading @@ -3062,8 +3109,8 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { } } bool clipRequired = false; bool clipRequired = false; const bool rejected = quickRejectNoScissor(x, y, const bool rejected = calculateQuickRejectForScissor(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), false, &clipRequired); x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired, false); if (rejected) { if (rejected) { if (transform && !transform->isIdentity()) { if (transform && !transform->isIdentity()) { Loading Loading @@ -3235,7 +3282,7 @@ Texture* OpenGLRenderer::getTexture(SkBitmap* bitmap) { void OpenGLRenderer::drawPathTexture(const PathTexture* texture, void OpenGLRenderer::drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint) { float x, float y, SkPaint* paint) { if (quickReject(x, y, x + texture->width, y + texture->height)) { if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) { return; return; } } Loading Loading @@ -3356,7 +3403,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color bottom = fmaxf(bottom, b); bottom = fmaxf(bottom, b); } } if (clip && quickReject(left, top, right, bottom)) { if (clip && quickRejectSetupScissor(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone; } } Loading