Merge scaled bitmaps with translated bitmaps
Change-Id: I03089f48f97b69fcb4a0171984d3ff548d41c4a8
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 9323a3a..0ff6ae9 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -145,7 +145,10 @@
* dropped, so we make simplifying qualifications on the ops that can merge, per op type.
*/
bool canMergeWith(DrawOp* op) {
- if (!op->state.mMatrix.isPureTranslate()) return false;
+ if (getBatchId() == DeferredDisplayList::kOpBatch_Bitmap) {
+ // Bitmap batches can handle translate and scaling
+ if (!op->state.mMatrix.isSimple()) return false;
+ } else if (!op->state.mMatrix.isPureTranslate()) return false;
bool isTextBatch = getBatchId() == DeferredDisplayList::kOpBatch_Text ||
getBatchId() == DeferredDisplayList::kOpBatch_ColorText;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 990372e..a6f9999 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -757,10 +757,16 @@
TextureVertex vertices[6 * ops.size()];
TextureVertex* vertex = &vertices[0];
+ bool transformed = false;
+
// TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
// and allowing them to be merged in getBatchId()
for (unsigned int i = 0; i < ops.size(); i++) {
const Rect& opBounds = ops[i]->state.mBounds;
+ // When we reach multiDraw(), the matrix can be either
+ // pureTranslate or simple (translate and/or scale).
+ // If the matrix is not pureTranslate, then we have a scale
+ if (!ops[i]->state.mMatrix.isPureTranslate()) transformed = true;
Rect texCoords(0, 0, 1, 1);
((DrawBitmapOp*) ops[i])->mUvMapper.map(texCoords);
@@ -774,7 +780,8 @@
SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
}
- return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], bounds, mPaint);
+ return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0],
+ transformed, bounds, mPaint);
}
virtual void output(int level, uint32_t logFlags) {
@@ -783,13 +790,18 @@
virtual const char* name() { return "DrawBitmap"; }
+ bool bitmapMergeAllowed() {
+ return state.mMatrix.isSimple() && !state.mClipped &&
+ OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
+ }
+
virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
*batchId = DeferredDisplayList::kOpBatch_Bitmap;
*mergeId = mAtlasEntry ? (mergeid_t) &mAtlasEntry->atlas : (mergeid_t) mBitmap;
// don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
// MergingDrawBatch::canMergeWith
- return mergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config);
+ return bitmapMergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config);
}
const SkBitmap* bitmap() { return mBitmap; }
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 038df07..884c0a7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1359,11 +1359,15 @@
// state has bounds initialized in local coordinates
if (!state.mBounds.isEmpty()) {
currentMatrix.mapRect(state.mBounds);
+ state.mClipped = !currentClip.contains(state.mBounds);
if (!state.mBounds.intersect(currentClip)) {
// quick rejected
return true;
}
} else {
+ // If we don't have bounds, let's assume we're clipped
+ // to prevent merging
+ state.mClipped = true;
state.mBounds.set(currentClip);
}
}
@@ -2010,7 +2014,7 @@
}
status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
- const Rect& bounds, SkPaint* paint) {
+ bool transformed, const Rect& bounds, SkPaint* paint) {
// merged draw operations don't need scissor, but clip should still be valid
mCaches.setScissorEnabled(mScissorOptimizationDisabled);
@@ -2026,7 +2030,7 @@
getAlphaAndMode(paint, &alpha, &mode);
texture->setWrap(GL_CLAMP_TO_EDGE, true);
- texture->setFilter(GL_NEAREST, true); // merged ops are always pure-translation for now
+ texture->setFilter(transformed ? FILTER(paint) : GL_NEAREST, true);
const float x = (int) floorf(bounds.left + 0.5f);
const float y = (int) floorf(bounds.top + 0.5f);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 597e458..43535e1 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -87,6 +87,7 @@
// the below are set and used by the OpenGLRenderer at record and deferred playback
bool mClipValid;
Rect mClip;
+ bool mClipped;
mat4 mMatrix;
DrawModifiers mDrawModifiers;
float mAlpha;
@@ -252,7 +253,7 @@
virtual status_t drawLayer(Layer* layer, float x, float y);
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
status_t drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
- const Rect& bounds, SkPaint* paint);
+ bool transformed, const Rect& bounds, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index f50ac3c..689fe6c0 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -125,11 +125,11 @@
return intersect(r.left, r.top, r.right, r.bottom);
}
- inline bool contains(float l, float t, float r, float b) {
+ inline bool contains(float l, float t, float r, float b) const {
return l >= left && t >= top && r <= right && b <= bottom;
}
- inline bool contains(const Rect& r) {
+ inline bool contains(const Rect& r) const {
return contains(r.left, r.top, r.right, r.bottom);
}