diff options
author | Romain Guy <romainguy@google.com> | 2010-09-29 13:37:37 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-09-29 13:37:37 -0700 |
commit | e17c054d34676c25f03b4eb0d8daebe41b84bf6e (patch) | |
tree | cf64a233b113e99723d72ffb5da35952933742da /libs | |
parent | 4715bd91f5949a1919156a5a5cb50f0cccda645e (diff) | |
parent | b051e895ccb696604349c6c5efe7c4747e1d1ab6 (diff) | |
download | frameworks_base-e17c054d34676c25f03b4eb0d8daebe41b84bf6e.zip frameworks_base-e17c054d34676c25f03b4eb0d8daebe41b84bf6e.tar.gz frameworks_base-e17c054d34676c25f03b4eb0d8daebe41b84bf6e.tar.bz2 |
Merge "Add display lists caching."
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 300 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 144 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 6 |
3 files changed, 404 insertions, 46 deletions
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 16b6b56..ee90702 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -22,6 +22,229 @@ namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// +// Display list +/////////////////////////////////////////////////////////////////////////////// + +DisplayList::DisplayList(const DisplayListRenderer& recorder) { + const SkWriter32& writer = recorder.writeStream(); + init(); + + if (writer.size() == 0) { + return; + } + + size_t size = writer.size(); + void* buffer = sk_malloc_throw(size); + writer.flatten(buffer); + mReader.setMemory(buffer, size); + + mRCPlayback.reset(&recorder.mRCRecorder); + mRCPlayback.setupBuffer(mReader); + + mTFPlayback.reset(&recorder.mTFRecorder); + mTFPlayback.setupBuffer(mReader); + + const SkTDArray<const SkFlatBitmap*>& bitmaps = recorder.getBitmaps(); + mBitmapCount = bitmaps.count(); + if (mBitmapCount > 0) { + mBitmaps = new SkBitmap[mBitmapCount]; + for (const SkFlatBitmap** flatBitmapPtr = bitmaps.begin(); + flatBitmapPtr != bitmaps.end(); flatBitmapPtr++) { + const SkFlatBitmap* flatBitmap = *flatBitmapPtr; + int index = flatBitmap->index() - 1; + flatBitmap->unflatten(&mBitmaps[index], &mRCPlayback); + } + } + + const SkTDArray<const SkFlatMatrix*>& matrices = recorder.getMatrices(); + mMatrixCount = matrices.count(); + if (mMatrixCount > 0) { + mMatrices = new SkMatrix[mMatrixCount]; + for (const SkFlatMatrix** matrixPtr = matrices.begin(); + matrixPtr != matrices.end(); matrixPtr++) { + const SkFlatMatrix* flatMatrix = *matrixPtr; + flatMatrix->unflatten(&mMatrices[flatMatrix->index() - 1]); + } + } + + const SkTDArray<const SkFlatPaint*>& paints = recorder.getPaints(); + mPaintCount = paints.count(); + if (mPaintCount > 0) { + mPaints = new SkPaint[mPaintCount]; + for (const SkFlatPaint** flatPaintPtr = paints.begin(); + flatPaintPtr != paints.end(); flatPaintPtr++) { + const SkFlatPaint* flatPaint = *flatPaintPtr; + int index = flatPaint->index() - 1; + flatPaint->unflatten(&mPaints[index], &mRCPlayback, &mTFPlayback); + } + } + + mPathHeap = recorder.mPathHeap; + mPathHeap->safeRef(); +} + +DisplayList::~DisplayList() { + sk_free((void*) mReader.base()); + + Caches& caches = Caches::getInstance(); + for (int i = 0; i < mBitmapCount; i++) { + caches.textureCache.remove(&mBitmaps[i]); + } + + delete[] mBitmaps; + delete[] mMatrices; + delete[] mPaints; + + mPathHeap->safeUnref(); +} + +void DisplayList::init() { + mBitmaps = NULL; + mMatrices = NULL; + mPaints = NULL; + mPathHeap = NULL; + mBitmapCount = mMatrixCount = mPaintCount = 0; +} + +void DisplayList::replay(OpenGLRenderer& renderer) { + TextContainer text; + mReader.rewind(); + + int saveCount = renderer.getSaveCount() - 1; + + while (!mReader.eof()) { + switch (mReader.readInt()) { + case AcquireContext: { + renderer.acquireContext(); + } + break; + case ReleaseContext: { + renderer.releaseContext(); + } + break; + case Save: { + renderer.save(getInt()); + } + break; + case Restore: { + renderer.restore(); + } + break; + case RestoreToCount: { + renderer.restoreToCount(saveCount + getInt()); + } + break; + case SaveLayer: { + renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(), + getPaint(), getInt()); + } + break; + case Translate: { + renderer.translate(getFloat(), getFloat()); + } + break; + case Rotate: { + renderer.rotate(getFloat()); + } + break; + case Scale: { + renderer.scale(getFloat(), getFloat()); + } + break; + case SetMatrix: { + renderer.setMatrix(getMatrix()); + } + break; + case ConcatMatrix: { + renderer.concatMatrix(getMatrix()); + } + break; + case ClipRect: { + renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(), + (SkRegion::Op) getInt()); + } + break; + case DrawBitmap: { + renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint()); + } + break; + case DrawBitmapMatrix: { + renderer.drawBitmap(getBitmap(), getMatrix(), getPaint()); + } + break; + case DrawBitmapRect: { + renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(), + getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); + } + break; + case DrawPatch: { + int32_t* xDivs = NULL; + int32_t* yDivs = NULL; + uint32_t xDivsCount = 0; + uint32_t yDivsCount = 0; + + SkBitmap* bitmap = getBitmap(); + + xDivs = getInts(xDivsCount); + yDivs = getInts(yDivsCount); + + renderer.drawPatch(bitmap, xDivs, yDivs, xDivsCount, yDivsCount, + getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); + } + break; + case DrawColor: { + renderer.drawColor(getInt(), (SkXfermode::Mode) getInt()); + } + break; + case DrawRect: { + renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint()); + } + break; + case DrawPath: { + renderer.drawPath(getPath(), getPaint()); + } + break; + case DrawLines: { + int count = 0; + float* points = getFloats(count); + renderer.drawLines(points, count, getPaint()); + } + break; + case DrawText: { + getText(&text); + renderer.drawText(text.text(), text.length(), getInt(), + getFloat(), getFloat(), getPaint()); + } + break; + case ResetShader: { + renderer.resetShader(); + } + break; + case SetupShader: { + // TODO: Implement + } + break; + case ResetColorFilter: { + renderer.resetColorFilter(); + } + break; + case SetupColorFilter: { + // TODO: Implement + } + break; + case ResetShadow: { + renderer.resetShadow(); + } + break; + case SetupShadow: { + renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt()); + } + break; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// // Base structure /////////////////////////////////////////////////////////////////////////////// @@ -56,75 +279,89 @@ void DisplayListRenderer::reset() { // Operations /////////////////////////////////////////////////////////////////////////////// +void DisplayListRenderer::setViewport(int width, int height) { + mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); + + mWidth = width; + mHeight = height; +} + +void DisplayListRenderer::prepare() { + mSnapshot = new Snapshot(mFirstSnapshot, + SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); + mSaveCount = 1; + mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); +} + void DisplayListRenderer::acquireContext() { - addOp(AcquireContext); + addOp(DisplayList::AcquireContext); OpenGLRenderer::acquireContext(); } void DisplayListRenderer::releaseContext() { - addOp(ReleaseContext); + addOp(DisplayList::ReleaseContext); OpenGLRenderer::releaseContext(); } int DisplayListRenderer::save(int flags) { - addOp(Save); + addOp(DisplayList::Save); addInt(flags); return OpenGLRenderer::save(flags); } void DisplayListRenderer::restore() { - addOp(Restore); + addOp(DisplayList::Restore); OpenGLRenderer::restore(); } void DisplayListRenderer::restoreToCount(int saveCount) { - addOp(RestoreToCount); + addOp(DisplayList::RestoreToCount); addInt(saveCount); OpenGLRenderer::restoreToCount(saveCount); } int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom, const SkPaint* p, int flags) { - addOp(SaveLayer); + addOp(DisplayList::SaveLayer); addBounds(left, top, right, bottom); addPaint(p); addInt(flags); - return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags); + return OpenGLRenderer::save(flags); } void DisplayListRenderer::translate(float dx, float dy) { - addOp(Translate); + addOp(DisplayList::Translate); addPoint(dx, dy); OpenGLRenderer::translate(dx, dy); } void DisplayListRenderer::rotate(float degrees) { - addOp(Rotate); + addOp(DisplayList::Rotate); addFloat(degrees); OpenGLRenderer::rotate(degrees); } void DisplayListRenderer::scale(float sx, float sy) { - addOp(Scale); + addOp(DisplayList::Scale); addPoint(sx, sy); OpenGLRenderer::scale(sx, sy); } void DisplayListRenderer::setMatrix(SkMatrix* matrix) { - addOp(SetMatrix); + addOp(DisplayList::SetMatrix); addMatrix(matrix); OpenGLRenderer::setMatrix(matrix); } void DisplayListRenderer::concatMatrix(SkMatrix* matrix) { - addOp(ConcatMatrix); + addOp(DisplayList::ConcatMatrix); addMatrix(matrix); OpenGLRenderer::concatMatrix(matrix); } bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { - addOp(ClipRect); + addOp(DisplayList::ClipRect); addBounds(left, top, right, bottom); addInt(op); return OpenGLRenderer::clipRect(left, top, right, bottom, op); @@ -132,88 +369,77 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) { - addOp(DrawBitmap); + addOp(DisplayList::DrawBitmap); addBitmap(bitmap); addPoint(left, top); addPaint(paint); - OpenGLRenderer::drawBitmap(bitmap, left, top, paint); } void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) { - addOp(DrawBitmapMatrix); + addOp(DisplayList::DrawBitmapMatrix); addBitmap(bitmap); addMatrix(matrix); addPaint(paint); - OpenGLRenderer::drawBitmap(bitmap, matrix, paint); } void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { - addOp(DrawBitmapRect); + addOp(DisplayList::DrawBitmapRect); addBitmap(bitmap); addBounds(srcLeft, srcTop, srcRight, srcBottom); addBounds(dstLeft, dstTop, dstRight, dstBottom); addPaint(paint); - OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, - dstLeft, dstTop, dstRight, dstBottom, paint); } void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, uint32_t width, uint32_t height, float left, float top, float right, float bottom, const SkPaint* paint) { - addOp(DrawPatch); + addOp(DisplayList::DrawPatch); addBitmap(bitmap); addInts(xDivs, width); addInts(yDivs, height); addBounds(left, top, right, bottom); addPaint(paint); - OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, width, height, - left, top, right, bottom, paint); } void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) { - addOp(DrawColor); + addOp(DisplayList::DrawColor); addInt(color); addInt(mode); - OpenGLRenderer::drawColor(color, mode); } void DisplayListRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* paint) { - addOp(DrawRect); + addOp(DisplayList::DrawRect); addBounds(left, top, right, bottom); addPaint(paint); - OpenGLRenderer::drawRect(left, top, right, bottom, paint); } void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) { - addOp(DrawPath); + addOp(DisplayList::DrawPath); addPath(path); addPaint(paint); - OpenGLRenderer::drawPath(path, paint); } void DisplayListRenderer::drawLines(float* points, int count, const SkPaint* paint) { - addOp(DrawLines); + addOp(DisplayList::DrawLines); addFloats(points, count); addPaint(paint); - OpenGLRenderer::drawLines(points, count, paint); } void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint) { - addOp(DrawText); + addOp(DisplayList::DrawText); addText(text, bytesCount); addInt(count); addPoint(x, y); addPaint(paint); - OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint); } void DisplayListRenderer::resetShader() { - addOp(ResetShader); + addOp(DisplayList::ResetShader); OpenGLRenderer::resetShader(); } @@ -223,7 +449,7 @@ void DisplayListRenderer::setupShader(SkiaShader* shader) { } void DisplayListRenderer::resetColorFilter() { - addOp(ResetColorFilter); + addOp(DisplayList::ResetColorFilter); OpenGLRenderer::resetColorFilter(); } @@ -233,12 +459,12 @@ void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) { } void DisplayListRenderer::resetShadow() { - addOp(ResetShadow); + addOp(DisplayList::ResetShadow); OpenGLRenderer::resetShadow(); } void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) { - addOp(SetupShadow); + addOp(DisplayList::SetupShadow); addFloat(radius); addPoint(dx, dy); addInt(color); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 7a20b59..735f0e7 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -81,7 +81,7 @@ public: int count() const { return mPaths.count(); } - const SkPath& operator[](int index) const { + SkPath& operator[](int index) const { return *mPaths[index]; } @@ -103,16 +103,18 @@ private: }; /////////////////////////////////////////////////////////////////////////////// -// Renderer +// Display list /////////////////////////////////////////////////////////////////////////////// +class DisplayListRenderer; + /** - * Records drawing commands in a display list for latter playback. + * Replays recorded drawing commands. */ -class DisplayListRenderer: public OpenGLRenderer { +class DisplayList { public: - DisplayListRenderer(); - ~DisplayListRenderer(); + DisplayList(const DisplayListRenderer& recorder); + ~DisplayList(); enum Op { AcquireContext, @@ -121,7 +123,6 @@ public: Restore, RestoreToCount, SaveLayer, - SaveLayerAlpha, Translate, Rotate, Scale, @@ -145,6 +146,109 @@ public: SetupShadow }; + void replay(OpenGLRenderer& renderer); + +private: + void init(); + + class TextContainer { + public: + size_t length() const { + return mByteLength; + } + + const char* text() const { + return (const char*) mText; + } + + size_t mByteLength; + const char* mText; + }; + + SkBitmap* getBitmap() { + int index = getInt(); + return &mBitmaps[index - 1]; + } + + inline int getIndex() { + return mReader.readInt(); + } + + inline int getInt() { + return mReader.readInt(); + } + + SkMatrix* getMatrix() { + int index = getInt(); + if (index == 0) { + return NULL; + } + return &mMatrices[index - 1]; + } + + SkPath* getPath() { + return &(*mPathHeap)[getInt() - 1]; + } + + SkPaint* getPaint() { + int index = getInt(); + if (index == 0) { + return NULL; + } + return &mPaints[index - 1]; + } + + inline float getFloat() { + return mReader.readScalar(); + } + + int32_t* getInts(uint32_t& count) { + count = getInt(); + return (int32_t*) mReader.skip(count * sizeof(int32_t)); + } + + float* getFloats(int& count) { + count = getInt(); + return (float*) mReader.skip(count * sizeof(float)); + } + + void getText(TextContainer* text) { + size_t length = text->mByteLength = getInt(); + text->mText = (const char*) mReader.skip(length); + } + + PathHeap* mPathHeap; + + SkBitmap* mBitmaps; + int mBitmapCount; + + SkMatrix* mMatrices; + int mMatrixCount; + + SkPaint* mPaints; + int mPaintCount; + + mutable SkFlattenableReadBuffer mReader; + + SkRefCntPlayback mRCPlayback; + SkTypefacePlayback mTFPlayback; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Renderer +/////////////////////////////////////////////////////////////////////////////// + +/** + * Records drawing commands in a display list for latter playback. + */ +class DisplayListRenderer: public OpenGLRenderer { +public: + DisplayListRenderer(); + ~DisplayListRenderer(); + + void setViewport(int width, int height); + void prepare(); + void acquireContext(); void releaseContext(); @@ -189,8 +293,28 @@ public: void reset(); + DisplayList* getDisplayList() const { + return new DisplayList(*this); + } + + const SkWriter32& writeStream() const { + return mWriter; + } + + const SkTDArray<const SkFlatBitmap*>& getBitmaps() const { + return mBitmaps; + } + + const SkTDArray<const SkFlatMatrix*>& getMatrices() const { + return mMatrices; + } + + const SkTDArray<const SkFlatPaint*>& getPaints() const { + return mPaints; + } + private: - inline void addOp(Op drawOp) { + inline void addOp(DisplayList::Op drawOp) { mWriter.writeInt(drawOp); } @@ -199,6 +323,7 @@ private: } void addInts(const int32_t* values, uint32_t count) { + mWriter.writeInt(count); for (uint32_t i = 0; i < count; i++) { mWriter.writeInt(values[i]); } @@ -209,6 +334,7 @@ private: } void addFloats(const float* values, int count) { + mWriter.writeInt(count); for (int i = 0; i < count; i++) { mWriter.writeScalar(values[i]); } @@ -273,6 +399,8 @@ private: SkRefCntRecorder mRCRecorder; SkRefCntRecorder mTFRecorder; + friend class DisplayList; + }; // class DisplayListRenderer }; // namespace uirenderer diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index d505d80..1974cf0 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -54,6 +54,8 @@ namespace uirenderer { // Renderer /////////////////////////////////////////////////////////////////////////////// +class DisplayListRenderer; + /** * OpenGL renderer used to draw accelerated 2D graphics. The API is a * simplified version of Skia's Canvas API. @@ -63,7 +65,7 @@ public: OpenGLRenderer(); virtual ~OpenGLRenderer(); - void setViewport(int width, int height); + virtual void setViewport(int width, int height); virtual void prepare(); virtual void finish(); @@ -428,6 +430,8 @@ private: // Misc GLint mMaxTextureSize; + friend class DisplayListRenderer; + }; // class OpenGLRenderer }; // namespace uirenderer |