diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/DeferredDisplayList.cpp | 13 | ||||
| -rw-r--r-- | libs/hwui/DisplayListOp.h | 47 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 7 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.h | 3 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 49 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 12 | ||||
| -rw-r--r-- | libs/hwui/Rect.h | 4 |
7 files changed, 64 insertions, 71 deletions
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index 9323a3a..512d3b1 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -85,8 +85,8 @@ public: } virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) { - DEFER_LOGD("%d replaying DrawingBatch %p, with %d ops (batch id %x, merge id %p)", - index, this, mOps.size(), mOps[0]->getBatchId(), mOps[0]->getMergeId()); + DEFER_LOGD("%d replaying DrawBatch %p, with %d ops (batch id %x, merge id %p)", + index, this, mOps.size(), getBatchId(), getMergeId()); status_t status = DrawGlInfo::kStatusDone; DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); @@ -145,7 +145,10 @@ public: * 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; @@ -193,10 +196,10 @@ public: } virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) { - DEFER_LOGD("%d replaying DrawingBatch %p, with %d ops (batch id %x, merge id %p)", + DEFER_LOGD("%d replaying MergingDrawBatch %p, with %d ops (batch id %x, merge id %p)", index, this, mOps.size(), getBatchId(), getMergeId()); if (mOps.size() == 1) { - return DrawBatch::replay(renderer, dirty, false); + return DrawBatch::replay(renderer, dirty, 0); } DrawOp* op = mOps[0]; diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 990372e..6839b18 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -220,6 +220,9 @@ public: DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint) : DrawOp(paint), mLocalBounds(left, top, right, bottom) {} + DrawBoundedOp(const Rect& localBounds, SkPaint* paint) + : DrawOp(paint), mLocalBounds(localBounds) {} + // Calculates bounds as smallest rect encompassing all points // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in // subclass' constructor) @@ -757,10 +760,16 @@ public: 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 +783,8 @@ public: 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 +793,18 @@ public: 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; } @@ -1272,23 +1287,10 @@ private: class DrawTextOp : public DrawBoundedOp { public: DrawTextOp(const char* text, int bytesCount, int count, float x, float y, - const float* positions, SkPaint* paint, float length) - : DrawBoundedOp(paint), mText(text), mBytesCount(bytesCount), mCount(count), - mX(x), mY(y), mPositions(positions), mLength(length) { - // duplicates bounds calculation from OpenGLRenderer::drawText, but doesn't alter mX - SkPaint::FontMetrics metrics; - paint->getFontMetrics(&metrics, 0.0f); - switch (paint->getTextAlign()) { - case SkPaint::kCenter_Align: - x -= length / 2.0f; - break; - case SkPaint::kRight_Align: - x -= length; - break; - default: - break; - } - mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom); + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds) + : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count), + mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) { + mLocalBounds.translate(x,y); memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float)); } @@ -1314,7 +1316,7 @@ public: virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { return renderer.drawText(mText, mBytesCount, mCount, mX, mY, - mPositions, getPaint(renderer), mLength); + mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds); } virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, @@ -1327,7 +1329,8 @@ public: DrawTextOp& op = *((DrawTextOp*)ops[i]); status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY, - op.mPositions, op.getPaint(renderer), op.mLength, drawOpMode); + op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds, + drawOpMode); } return status; } @@ -1345,7 +1348,7 @@ private: float mX; float mY; const float* mPositions; - float mLength; + float mTotalAdvance; mat4 mPrecacheTransform; }; diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index bfd4086..6d85a16 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -420,17 +420,16 @@ status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, SkPaint* paint, - float length, DrawOpMode drawOpMode) { + float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) { if (!text || count <= 0) return DrawGlInfo::kStatusDone; - if (length < 0.0f) length = paint->measureText(text, bytesCount); - text = refText(text, bytesCount); positions = refBuffer<float>(positions, count * 2); paint = refPaint(paint); - DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, x, y, positions, paint, length); + DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, + x, y, positions, paint, totalAdvance, bounds); addDrawOp(op); return DrawGlInfo::kStatusDone; } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index db08921..85d6107 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -121,7 +121,8 @@ public: virtual status_t drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint); virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, - const float* positions, SkPaint* paint, float length, DrawOpMode drawOpMode); + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds, + DrawOpMode drawOpMode); virtual status_t drawRects(const float* rects, int count, SkPaint* paint); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 038df07..2465b48 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1359,11 +1359,15 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef // 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 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk } 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 @@ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureV 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); @@ -2846,8 +2850,8 @@ mat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const { return fontTransform; } -status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, - float x, float y, const float* positions, SkPaint* paint, float length, +status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) { if (drawOpMode == kDrawOpMode_Immediate && @@ -2855,24 +2859,8 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, return DrawGlInfo::kStatusDone; } - if (length < 0.0f) length = paint->measureText(text, bytesCount); - switch (paint->getTextAlign()) { - case SkPaint::kCenter_Align: - x -= length / 2.0f; - break; - case SkPaint::kRight_Align: - x -= length; - break; - default: - break; - } - - SkPaint::FontMetrics metrics; - paint->getFontMetrics(&metrics, 0.0f); if (drawOpMode == kDrawOpMode_Immediate) { - if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) { - return DrawGlInfo::kStatusDone; - } + if (quickReject(bounds)) return DrawGlInfo::kStatusDone; } else { // merged draw operations don't need scissor, but clip should still be valid mCaches.setScissorEnabled(mScissorOptimizationDisabled); @@ -2923,7 +2911,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, // TODO: Implement better clipping for scaled/rotated text const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect; - Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); + Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); bool status; TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint); @@ -2934,20 +2922,20 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, SkPaint paintCopy(*paint); paintCopy.setTextAlign(SkPaint::kLeft_Align); status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y, - positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish); + positions, hasActiveLayer ? &layerBounds : NULL, &functor, forceFinish); } else { status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, - positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish); + positions, hasActiveLayer ? &layerBounds : NULL, &functor, forceFinish); } if ((status || drawOpMode != kDrawOpMode_Immediate) && hasActiveLayer) { if (!pureTranslate) { - transform.mapRect(bounds); + transform.mapRect(layerBounds); } - dirtyLayerUnchecked(bounds, getRegion()); + dirtyLayerUnchecked(layerBounds, getRegion()); } - drawTextDecorations(text, bytesCount, length, oldX, oldY, paint); + drawTextDecorations(text, bytesCount, totalAdvance, oldX, oldY, paint); return DrawGlInfo::kStatusDrew; } @@ -3231,17 +3219,12 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture, #define kStdUnderline_Offset (1.0f / 9.0f) #define kStdUnderline_Thickness (1.0f / 18.0f) -void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, +void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float underlineWidth, float x, float y, SkPaint* paint) { // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { SkPaint paintCopy(*paint); - float underlineWidth = length; - // If length is > 0.0f, we already measured the text for the text alignment - if (length <= 0.0f) { - underlineWidth = paintCopy.measureText(text, bytesCount); - } if (CC_LIKELY(underlineWidth > 0.0f)) { const float textSize = paintCopy.getTextSize(); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 597e458..d9ba93a 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -87,6 +87,7 @@ struct DeferredDisplayState { // 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; @@ -241,6 +242,9 @@ public: ANDROID_API const Rect& getClipBounds(); ANDROID_API bool quickReject(float left, float top, float right, float bottom); + bool quickReject(const Rect& bounds) { + return quickReject(bounds.left, bounds.top, bounds.right, bounds.bottom); + } bool quickRejectNoScissor(float left, float top, float right, float bottom); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool clipPath(SkPath* path, SkRegion::Op op); @@ -252,7 +256,7 @@ public: 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, @@ -280,7 +284,7 @@ public: virtual status_t drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint); virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, - const float* positions, SkPaint* paint, float length = -1.0f, + const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode = kDrawOpMode_Immediate); virtual status_t drawRects(const float* rects, int count, SkPaint* paint); @@ -824,12 +828,12 @@ private: * * @param text The text to decor * @param bytesCount The number of bytes in the text - * @param length The length in pixels of the text, can be <= 0.0f to force a measurement + * @param totalAdvance The total advance in pixels, defines underline/strikethrough length * @param x The x coordinate where the text will be drawn * @param y The y coordinate where the text will be drawn * @param paint The paint to draw the text with */ - void drawTextDecorations(const char* text, int bytesCount, float length, + void drawTextDecorations(const char* text, int bytesCount, float totalAdvance, float x, float y, SkPaint* paint); /** 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 @@ public: 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); } |
