diff options
author | Romain Guy <romainguy@google.com> | 2012-02-16 19:24:51 -0800 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2012-02-17 13:10:00 -0800 |
commit | 33f6beb10f98e8ba96250e284876d607055d278d (patch) | |
tree | 215fc7d5624b6b41a018374f5d19f7dac84cf72b /libs/hwui | |
parent | 445c83c7755fae179cf3328e89307e2775e97a5e (diff) | |
download | frameworks_base-33f6beb10f98e8ba96250e284876d607055d278d.zip frameworks_base-33f6beb10f98e8ba96250e284876d607055d278d.tar.gz frameworks_base-33f6beb10f98e8ba96250e284876d607055d278d.tar.bz2 |
Record possible clip rejects when recording display lists
This optimization allows us to quickly skip operations that lie
entirely outside of the known bounds of a display list. Because
of ViewGroup.setClipChildren, we must keep the operations recorded
in the display list. setClipChildren(false) is however a very
uncommon operation and we will therefore often benefit from this
new optimization.
Change-Id: I0942c864e55298e6dccd9977d15adefbce3ba3ad
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 164 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 61 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 2 | ||||
-rw-r--r-- | libs/hwui/PathCache.cpp | 20 | ||||
-rw-r--r-- | libs/hwui/ShapeCache.h | 20 |
6 files changed, 199 insertions, 76 deletions
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 1a11fbc..f9088ac 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -226,6 +226,11 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { while (!mReader.eof()) { int op = mReader.readInt(); + if (op & OP_MAY_BE_SKIPPED_MASK) { + int skip = mReader.readInt(); + ALOGD("%sSkip %d", (char*) indent, skip); + op &= ~OP_MAY_BE_SKIPPED_MASK; + } switch (op) { case DrawGLFunction: { @@ -316,8 +321,9 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { DisplayList* displayList = getDisplayList(); uint32_t width = getUInt(); uint32_t height = getUInt(); - ALOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op], - displayList, width, height, level + 1); + int32_t flags = getInt(); + ALOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op], + displayList, width, height, flags, level + 1); renderer.outputDisplayList(displayList, level + 1); } break; @@ -551,7 +557,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { * in the output() function, since that function processes the same list of opcodes for the * purposes of logging display list info for a given view. */ -bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) { +bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) { bool needsInvalidate = false; TextContainer text; mReader.rewind(); @@ -572,6 +578,18 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) int saveCount = renderer.getSaveCount() - 1; while (!mReader.eof()) { int op = mReader.readInt(); + if (op & OP_MAY_BE_SKIPPED_MASK) { + int32_t skip = mReader.readInt() * 4; + if (CC_LIKELY(flags & kReplayFlag_ClipChildren)) { + mReader.skip(skip); + DISPLAY_LIST_LOGD("%s%s skipping %d bytes", (char*) indent, + OP_NAMES[op & ~OP_MAY_BE_SKIPPED_MASK], skip); + continue; + } else { + op &= ~OP_MAY_BE_SKIPPED_MASK; + ALOGD("%s", OP_NAMES[op]); + } + } logBuffer.writeCommand(level, op); switch (op) { @@ -584,7 +602,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case Save: { - int rendererNum = getInt(); + int32_t rendererNum = getInt(); DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum); renderer.save(rendererNum); } @@ -595,7 +613,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case RestoreToCount: { - int restoreCount = saveCount + getInt(); + int32_t restoreCount = saveCount + getInt(); DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount); renderer.restoreToCount(restoreCount); } @@ -606,7 +624,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) float f3 = getFloat(); float f4 = getFloat(); SkPaint* paint = getPaint(renderer); - int flags = getInt(); + int32_t flags = getInt(); DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint, flags); renderer.saveLayer(f1, f2, f3, f4, paint, flags); @@ -617,8 +635,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) float f2 = getFloat(); float f3 = getFloat(); float f4 = getFloat(); - int alpha = getInt(); - int flags = getInt(); + int32_t alpha = getInt(); + int32_t flags = getInt(); DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent, OP_NAMES[op], f1, f2, f3, f4, alpha, flags); renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags); @@ -668,7 +686,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) float f2 = getFloat(); float f3 = getFloat(); float f4 = getFloat(); - int regionOp = getInt(); + int32_t regionOp = getInt(); DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op], f1, f2, f3, f4, regionOp); renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp); @@ -678,10 +696,11 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) DisplayList* displayList = getDisplayList(); uint32_t width = getUInt(); uint32_t height = getUInt(); - DISPLAY_LIST_LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op], - displayList, width, height, level + 1); + int32_t flags = getInt(); + DISPLAY_LIST_LOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op], + displayList, width, height, flags, level + 1); needsInvalidate |= renderer.drawDisplayList(displayList, width, height, - dirty, level + 1); + dirty, flags, level + 1); } break; case DrawLayer: { @@ -730,7 +749,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case DrawBitmapMesh: { - int verticesCount = 0; + int32_t verticesCount = 0; uint32_t colorsCount = 0; SkBitmap* bitmap = getBitmap(); @@ -738,7 +757,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) uint32_t meshHeight = getInt(); float* vertices = getFloats(verticesCount); bool hasColors = getInt(); - int* colors = hasColors ? getInts(colorsCount) : NULL; + int32_t* colors = hasColors ? getInts(colorsCount) : NULL; SkPaint* paint = getPaint(renderer); DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); @@ -771,8 +790,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case DrawColor: { - int color = getInt(); - int xferMode = getInt(); + int32_t color = getInt(); + int32_t xferMode = getInt(); DISPLAY_LIST_LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode); renderer.drawColor(color, (SkXfermode::Mode) xferMode); } @@ -829,7 +848,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) float f4 = getFloat(); float f5 = getFloat(); float f6 = getFloat(); - int i1 = getInt(); + int32_t i1 = getInt(); SkPaint* paint = getPaint(renderer); DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p", (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint); @@ -844,7 +863,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case DrawLines: { - int count = 0; + int32_t count = 0; float* points = getFloats(count); SkPaint* paint = getPaint(renderer); DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); @@ -852,7 +871,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case DrawPoints: { - int count = 0; + int32_t count = 0; float* points = getFloats(count); SkPaint* paint = getPaint(renderer); DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); @@ -861,7 +880,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) break; case DrawText: { getText(&text); - int count = getInt(); + int32_t count = getInt(); float x = getFloat(); float y = getFloat(); SkPaint* paint = getPaint(renderer); @@ -873,8 +892,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) break; case DrawPosText: { getText(&text); - int count = getInt(); - int positionsCount = 0; + int32_t count = getInt(); + int32_t positionsCount = 0; float* positions = getFloats(positionsCount); SkPaint* paint = getPaint(renderer); DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %p", (char*) indent, @@ -913,7 +932,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) float radius = getFloat(); float dx = getFloat(); float dy = getFloat(); - int color = getInt(); + int32_t color = getInt(); DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op], radius, dx, dy, color); renderer.setupShadow(radius, dx, dy, color); @@ -925,8 +944,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } break; case SetupPaintFilter: { - int clearBits = getInt(); - int setBits = getInt(); + int32_t clearBits = getInt(); + int32_t setBits = getInt(); DISPLAY_LIST_LOGD("%s%s 0x%x, 0x%x", (char*) indent, OP_NAMES[op], clearBits, setBits); renderer.setupPaintFilter(clearBits, setBits); @@ -949,7 +968,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) // Base structure /////////////////////////////////////////////////////////////////////////////// -DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE), mHasDrawOps(false) { +DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE), + mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), mHasDrawOps(false) { } DisplayListRenderer::~DisplayListRenderer() { @@ -1019,6 +1039,7 @@ void DisplayListRenderer::prepareDirty(float left, float top, void DisplayListRenderer::finish() { insertRestoreToCount(); + insertTranlate(); OpenGLRenderer::finish(); } @@ -1043,15 +1064,18 @@ int DisplayListRenderer::save(int flags) { void DisplayListRenderer::restore() { if (mRestoreSaveCount < 0) { - addOp(DisplayList::Restore); - } else { - mRestoreSaveCount--; + restoreToCount(getSaveCount() - 1); + return; } + + mRestoreSaveCount--; + insertTranlate(); OpenGLRenderer::restore(); } void DisplayListRenderer::restoreToCount(int saveCount) { mRestoreSaveCount = saveCount; + insertTranlate(); OpenGLRenderer::restoreToCount(saveCount); } @@ -1074,8 +1098,10 @@ int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, floa } void DisplayListRenderer::translate(float dx, float dy) { - addOp(DisplayList::Translate); - addPoint(dx, dy); + mHasTranslate = true; + mTranslateX += dx; + mTranslateY += dy; + insertRestoreToCount(); OpenGLRenderer::translate(dx, dy); } @@ -1118,12 +1144,15 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot } bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, - uint32_t width, uint32_t height, Rect& dirty, uint32_t level) { + uint32_t width, uint32_t height, Rect& dirty, int32_t flags, uint32_t level) { // dirty is an out parameter and should not be recorded, // it matters only when replaying the display list - addOp(DisplayList::DrawDisplayList); + const bool reject = quickReject(0.0f, 0.0f, width, height); + uint32_t* location = addOp(DisplayList::DrawDisplayList, reject); addDisplayList(displayList); addSize(width, height); + addInt(flags); + addSkip(location); return false; } @@ -1134,30 +1163,38 @@ void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pai addPaint(paint); } -void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, - SkPaint* paint) { - addOp(DisplayList::DrawBitmap); +void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) { + const bool reject = quickReject(left, top, left + bitmap->width(), top + bitmap->height()); + uint32_t* location = addOp(DisplayList::DrawBitmap, reject); addBitmap(bitmap); addPoint(left, top); addPaint(paint); + addSkip(location); } -void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, - SkPaint* paint) { - addOp(DisplayList::DrawBitmapMatrix); +void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) { + Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height()); + const mat4 transform(*matrix); + transform.mapRect(r); + + const bool reject = quickReject(r.left, r.top, r.right, r.bottom); + uint32_t* location = addOp(DisplayList::DrawBitmapMatrix, reject); addBitmap(bitmap); addMatrix(matrix); addPaint(paint); + addSkip(location); } void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) { - addOp(DisplayList::DrawBitmapRect); + const bool reject = quickReject(dstLeft, dstTop, dstRight, dstBottom); + uint32_t* location = addOp(DisplayList::DrawBitmapRect, reject); addBitmap(bitmap); addBounds(srcLeft, srcTop, srcRight, srcBottom); addBounds(dstLeft, dstTop, dstRight, dstBottom); addPaint(paint); + addSkip(location); } void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, @@ -1179,13 +1216,15 @@ void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int me void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint) { - addOp(DisplayList::DrawPatch); + const bool reject = quickReject(left, top, right, bottom); + uint32_t* location = addOp(DisplayList::DrawPatch, reject); addBitmap(bitmap); addInts(xDivs, width); addInts(yDivs, height); addUInts(colors, numColors); addBounds(left, top, right, bottom); addPaint(paint); + addSkip(location); } void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) { @@ -1196,17 +1235,23 @@ void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) { void DisplayListRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* paint) { - addOp(DisplayList::DrawRect); + const bool reject = paint->getStyle() == SkPaint::kFill_Style && + quickReject(left, top, right, bottom); + uint32_t* location = addOp(DisplayList::DrawRect, reject); addBounds(left, top, right, bottom); addPaint(paint); + addSkip(location); } void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, SkPaint* paint) { - addOp(DisplayList::DrawRoundRect); + const bool reject = paint->getStyle() == SkPaint::kFill_Style && + quickReject(left, top, right, bottom); + uint32_t* location = addOp(DisplayList::DrawRoundRect, reject); addBounds(left, top, right, bottom); addPoint(rx, ry); addPaint(paint); + addSkip(location); } void DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) { @@ -1233,9 +1278,15 @@ void DisplayListRenderer::drawArc(float left, float top, float right, float bott } void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) { - addOp(DisplayList::DrawPath); + float left, top, offset; + uint32_t width, height; + computePathBounds(path, paint, left, top, offset, width, height); + + const bool reject = quickReject(left - offset, top - offset, width, height); + uint32_t* location = addOp(DisplayList::DrawPath, reject); addPath(path); addPaint(paint); + addSkip(location); } void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) { @@ -1252,11 +1303,8 @@ void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) { void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint, float length) { - if (count <= 0) return; - addOp(DisplayList::DrawText); - addText(text, bytesCount); - addInt(count); - addPoint(x, y); + if (!text || count <= 0) return; + // TODO: We should probably make a copy of the paint instead of modifying // it; modifying the paint will change its generationID the first // time, which might impact caches. More investigation needed to @@ -1265,13 +1313,27 @@ void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, // its own copy as it does right now. // Beware: this needs Glyph encoding (already done on the Paint constructor) paint->setAntiAlias(true); + if (length < 0.0f) length = paint->measureText(text, bytesCount); + + bool reject = false; + if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) { + SkPaint::FontMetrics metrics; + paint->getFontMetrics(&metrics, 0.0f); + reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom); + } + + uint32_t* location = addOp(DisplayList::DrawText, reject); + addText(text, bytesCount); + addInt(count); + addPoint(x, y); addPaint(paint); - addFloat(length < 0.0f ? paint->measureText(text, bytesCount) : length); + addFloat(length); + addSkip(location); } void DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint) { - if (count <= 0) return; + if (!text || count <= 0) return; addOp(DisplayList::DrawPosText); addText(text, bytesCount); addInt(count); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 46506e4..6dd47be 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -42,6 +42,7 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// #define MIN_WRITER_SIZE 4096 +#define OP_MAY_BE_SKIPPED_MASK 0xff000000 // Debug #if DEBUG_DISPLAY_LIST @@ -110,13 +111,18 @@ public: DrawGLFunction, }; + // See flags defined in DisplayList.java + enum ReplayFlag { + kReplayFlag_ClipChildren = 0x1 + }; + static const char* OP_NAMES[]; void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); ANDROID_API size_t getSize(); - bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0); + bool replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0); void output(OpenGLRenderer& renderer, uint32_t level = 0); @@ -167,11 +173,11 @@ private: return (SkiaColorFilter*) getInt(); } - inline int getIndex() { + inline int32_t getIndex() { return mReader.readInt(); } - inline int getInt() { + inline int32_t getInt() { return mReader.readInt(); } @@ -209,7 +215,7 @@ private: return (uint32_t*) mReader.skip(count * sizeof(uint32_t)); } - float* getFloats(int& count) { + float* getFloats(int32_t& count) { count = getInt(); return (float*) mReader.skip(count * sizeof(float)); } @@ -279,7 +285,7 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, - Rect& dirty, uint32_t level = 0); + Rect& dirty, int32_t flags, uint32_t level = 0); virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); @@ -358,13 +364,45 @@ private: } } - inline void addOp(DisplayList::Op drawOp) { + void insertTranlate() { + if (mHasTranslate) { + if (mTranslateX != 0.0f || mTranslateY != 0.0f) { + mWriter.writeInt(DisplayList::Translate); + addPoint(mTranslateX, mTranslateY); + mTranslateX = mTranslateY = 0.0f; + } + mHasTranslate = false; + } + } + + inline void addOp(const DisplayList::Op drawOp) { insertRestoreToCount(); + insertTranlate(); mWriter.writeInt(drawOp); mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList; } - inline void addInt(int value) { + uint32_t* addOp(const DisplayList::Op drawOp, const bool reject) { + insertRestoreToCount(); + insertTranlate(); + mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList; + if (reject) { + mWriter.writeInt(OP_MAY_BE_SKIPPED_MASK | drawOp); + mWriter.writeInt(0); + uint32_t* location = reject ? mWriter.peek32(mWriter.size() - 4) : NULL; + return location; + } + mWriter.writeInt(drawOp); + return NULL; + } + + inline void addSkip(uint32_t* location) { + if (location) { + *location = (int32_t) (mWriter.peek32(mWriter.size() - 4) - location); + } + } + + inline void addInt(int32_t value) { mWriter.writeInt(value); } @@ -391,9 +429,9 @@ private: mWriter.writeScalar(value); } - void addFloats(const float* values, int count) { + void addFloats(const float* values, int32_t count) { mWriter.writeInt(count); - for (int i = 0; i < count; i++) { + for (int32_t i = 0; i < count; i++) { mWriter.writeScalar(values[i]); } } @@ -513,6 +551,11 @@ private: SkWriter32 mWriter; int mRestoreSaveCount; + + float mTranslateX; + float mTranslateY; + bool mHasTranslate; + bool mHasDrawOps; friend class DisplayList; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index afae70f..55e2ca5 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1321,7 +1321,7 @@ void OpenGLRenderer::finishDrawTexture() { /////////////////////////////////////////////////////////////////////////////// bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, - Rect& dirty, uint32_t level) { + Rect& dirty, int32_t flags, uint32_t level) { if (quickReject(0.0f, 0.0f, width, height)) { return false; } @@ -1329,7 +1329,7 @@ bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, u // All the usual checks and setup operations (quickReject, setupDraw, etc.) // will be performed by the display list itself if (displayList && displayList->isRenderable()) { - return displayList->replay(*this, dirty, level); + return displayList->replay(*this, dirty, flags, level); } return false; @@ -2189,8 +2189,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, SkPaint::FontMetrics metrics; paint->getFontMetrics(&metrics, 0.0f); // If no length was specified, just perform the hit test on the Y axis - if (quickReject(x, y + metrics.fTop, - x + (length >= 0.0f ? length : INT_MAX / 2), y + metrics.fBottom)) { + if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) { return; } @@ -2298,6 +2297,7 @@ void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { mCaches.activeTexture(0); + // TODO: Perform early clip test before we rasterize the path const PathTexture* texture = mCaches.pathCache.get(path, paint); if (!texture) return; const AutoTexture autoCleanup(texture); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 3c2d09e..3f63c3fe 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -98,7 +98,7 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, - Rect& dirty, uint32_t level = 0); + Rect& dirty, int32_t flags, uint32_t level = 0); virtual void outputDisplayList(DisplayList* displayList, uint32_t level = 0); virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index e893f7a..e09c243 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -24,6 +24,23 @@ namespace android { namespace uirenderer { +// Defined in ShapeCache.h +void computePathBounds(const SkPath *path, const SkPaint* paint, + float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { + const SkRect& bounds = path->getBounds(); + + const float pathWidth = fmax(bounds.width(), 1.0f); + const float pathHeight = fmax(bounds.height(), 1.0f); + + left = bounds.fLeft; + top = bounds.fTop; + + offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); + + width = uint32_t(pathWidth + offset * 2.0 + 0.5); + height = uint32_t(pathHeight + offset * 2.0 + 0.5); +} + /////////////////////////////////////////////////////////////////////////////// // Path cache /////////////////////////////////////////////////////////////////////////////// @@ -69,6 +86,9 @@ PathTexture* PathCache::get(SkPath* path, SkPaint* paint) { PathCacheEntry entry(path, paint); PathTexture* texture = mCache.get(entry); + float left, top, offset; + uint32_t width, height; + if (!texture) { texture = addTexture(entry, path, paint); } else if (path->getGenerationID() != texture->generation) { diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index 30ce690..f180e94 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -489,18 +489,16 @@ void ShapeCache<Entry>::removeTexture(PathTexture* texture) { } } +void computePathBounds(const SkPath *path, const SkPaint* paint, + float& left, float& top, float& offset, uint32_t& width, uint32_t& height); + template<class Entry> PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint) { - const SkRect& bounds = path->getBounds(); - - const float pathWidth = fmax(bounds.width(), 1.0f); - const float pathHeight = fmax(bounds.height(), 1.0f); - - const float offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); - const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5); - const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5); + float left, top, offset; + uint32_t width, height; + computePathBounds(path, paint, left, top, offset, width, height); if (width > mMaxTextureSize || height > mMaxTextureSize) { ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)", @@ -517,8 +515,8 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat } PathTexture* texture = new PathTexture; - texture->left = bounds.fLeft; - texture->top = bounds.fTop; + texture->left = left; + texture->top = top; texture->offset = offset; texture->width = width; texture->height = height; @@ -542,7 +540,7 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat SkSafeUnref(pathPaint.setXfermode(mode)); SkCanvas canvas(bitmap); - canvas.translate(-bounds.fLeft + offset, -bounds.fTop + offset); + canvas.translate(-left + offset, -top + offset); canvas.drawPath(*path, pathPaint); generateTexture(bitmap, texture); |