summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2012-02-16 19:24:51 -0800
committerRomain Guy <romainguy@google.com>2012-02-17 13:10:00 -0800
commit33f6beb10f98e8ba96250e284876d607055d278d (patch)
tree215fc7d5624b6b41a018374f5d19f7dac84cf72b /libs/hwui
parent445c83c7755fae179cf3328e89307e2775e97a5e (diff)
downloadframeworks_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.cpp164
-rw-r--r--libs/hwui/DisplayListRenderer.h61
-rw-r--r--libs/hwui/OpenGLRenderer.cpp8
-rw-r--r--libs/hwui/OpenGLRenderer.h2
-rw-r--r--libs/hwui/PathCache.cpp20
-rw-r--r--libs/hwui/ShapeCache.h20
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);