From e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0 Mon Sep 17 00:00:00 2001 From: robertphillips Date: Wed, 3 Dec 2014 07:33:57 -0800 Subject: [PATCH] Fuse GrReplacements and GrLayerCache The conversion step from GrCachedLayer to ReplacementInfo isn't necessary. Review URL: https://codereview.chromium.org/769533004 --- src/core/SkLayerInfo.h | 2 +- src/core/SkMultiPictureDraw.cpp | 9 ++-- src/core/SkRecordDraw.cpp | 12 ++--- src/gpu/GrLayerCache.cpp | 17 +++---- src/gpu/GrLayerCache.h | 46 ++++++++--------- src/gpu/GrLayerHoister.cpp | 56 ++------------------- src/gpu/GrLayerHoister.h | 1 - src/gpu/GrRecordReplaceDraw.cpp | 91 ++++++++++++++------------------- src/gpu/GrRecordReplaceDraw.h | 109 +--------------------------------------- src/gpu/SkGpuDevice.cpp | 8 +-- tests/GpuLayerCacheTest.cpp | 31 ++++++------ tests/RecordReplaceDrawTest.cpp | 67 +++++++++++++----------- 12 files changed, 139 insertions(+), 310 deletions(-) diff --git a/src/core/SkLayerInfo.h b/src/core/SkLayerInfo.h index 6ed77c9..add57d7 100644 --- a/src/core/SkLayerInfo.h +++ b/src/core/SkLayerInfo.h @@ -53,7 +53,7 @@ public: // The variable length key for this saveLayer block. It stores the // thread of drawPicture and saveLayer operation indices that lead to this // saveLayer (including its own op index). The BlockInfo owns this memory. - int* fKey; + unsigned* fKey; int fKeySize; // # of ints }; diff --git a/src/core/SkMultiPictureDraw.cpp b/src/core/SkMultiPictureDraw.cpp index bd1e8fe..ed099a0 100644 --- a/src/core/SkMultiPictureDraw.cpp +++ b/src/core/SkMultiPictureDraw.cpp @@ -15,6 +15,7 @@ #include "SkTaskGroup.h" #if SK_SUPPORT_GPU +#include "GrContext.h" #include "GrLayerHoister.h" #include "GrRecordReplaceDraw.h" #include "GrRenderTarget.h" @@ -168,13 +169,9 @@ void SkMultiPictureDraw::draw() { GrLayerHoister::DrawLayers(context, needRendering); - GrReplacements replacements; - - GrLayerHoister::ConvertLayersToReplacements(picture, needRendering, &replacements); - GrLayerHoister::ConvertLayersToReplacements(picture, recycled, &replacements); - // Render the entire picture using new layers - GrRecordReplaceDraw(picture, canvas, &replacements, initialMatrix, NULL); + GrRecordReplaceDraw(picture, canvas, context->getLayerCache(), + initialMatrix, NULL); GrLayerHoister::UnlockLayers(context, needRendering); GrLayerHoister::UnlockLayers(context, recycled); diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 4801f66..47bafe3 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -691,10 +691,10 @@ private: // Store 'saveLayer ops from enclosing picture' + drawPict op + 'ops from sub-picture' dst.fKeySize = fSaveLayerOpStack.count() + src.fKeySize + 1; - dst.fKey = SkNEW_ARRAY(int, dst.fKeySize); - memcpy(dst.fKey, fSaveLayerOpStack.begin(), fSaveLayerOpStack.count() * sizeof(int)); + dst.fKey = SkNEW_ARRAY(unsigned, dst.fKeySize); + memcpy(dst.fKey, fSaveLayerOpStack.begin(), fSaveLayerOpStack.count() * sizeof(unsigned)); dst.fKey[fSaveLayerOpStack.count()] = fFillBounds.currentOp(); - memcpy(&dst.fKey[fSaveLayerOpStack.count()+1], src.fKey, src.fKeySize * sizeof(int)); + memcpy(&dst.fKey[fSaveLayerOpStack.count()+1], src.fKey, src.fKeySize * sizeof(unsigned)); } } @@ -766,8 +766,8 @@ private: block.fIsNested = fSaveLayersInStack > 0; block.fKeySize = fSaveLayerOpStack.count(); - block.fKey = SkNEW_ARRAY(int, block.fKeySize); - memcpy(block.fKey, fSaveLayerOpStack.begin(), block.fKeySize * sizeof(int)); + block.fKey = SkNEW_ARRAY(unsigned, block.fKeySize); + memcpy(block.fKey, fSaveLayerOpStack.begin(), block.fKeySize * sizeof(unsigned)); fSaveLayerOpStack.pop(); } @@ -776,7 +776,7 @@ private: int fSaveLayersInStack; SkTDArray fSaveLayerStack; // The op code indices of all the currently active saveLayers - SkTDArray fSaveLayerOpStack; + SkTDArray fSaveLayerOpStack; SkLayerInfo* fAccelData; const SkPicture::SnapshotArray* fPictList; diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp index c347512..fc5be5f 100644 --- a/src/gpu/GrLayerCache.cpp +++ b/src/gpu/GrLayerCache.cpp @@ -125,7 +125,7 @@ GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, int start, int stop, const SkIRect& bounds, const SkMatrix& initialMat, - const int* key, + const unsigned* key, int keySize, const SkPaint* paint) { SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); @@ -137,7 +137,7 @@ GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID, } GrCachedLayer* GrLayerCache::findLayer(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize) { + const unsigned* key, int keySize) { SkASSERT(pictureID != SK_InvalidGenID); return fLayerHash.find(GrCachedLayer::Key(pictureID, initialMat, key, keySize)); } @@ -146,7 +146,7 @@ GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID, int start, int stop, const SkIRect& bounds, const SkMatrix& initialMat, - const int* key, + const unsigned* key, int keySize, const SkPaint* paint) { SkASSERT(pictureID != SK_InvalidGenID && start >= 0 && stop > 0); @@ -209,9 +209,8 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer, pictInfo->incPlotUsage(plot->id()); #endif // The layer was successfully added to the atlas - GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, - SkToS16(desc.fWidth), - SkToS16(desc.fHeight)); + const SkIRect bounds = SkIRect::MakeXYWH(loc.fX, loc.fY, + desc.fWidth, desc.fHeight); layer->setTexture(fAtlas->getTexture(), bounds); layer->setPlot(plot); layer->setLocked(true); @@ -250,7 +249,7 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* n return false; } - layer->setTexture(tex, GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeight))); + layer->setTexture(tex, SkIRect::MakeWH(desc.fWidth, desc.fHeight)); layer->setLocked(true); *needsRendering = true; return true; @@ -289,11 +288,11 @@ void GrLayerCache::unlock(GrCachedLayer* layer) { } layer->setPlot(NULL); - layer->setTexture(NULL, GrIRect16::MakeEmpty()); + layer->setTexture(NULL, SkIRect::MakeEmpty()); #endif } else { - layer->setTexture(NULL, GrIRect16::MakeEmpty()); + layer->setTexture(NULL, SkIRect::MakeEmpty()); } layer->setLocked(false); diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h index 967503d..b9b59d0 100644 --- a/src/gpu/GrLayerCache.h +++ b/src/gpu/GrLayerCache.h @@ -77,7 +77,7 @@ public: // For SkTDynamicHash struct Key { Key(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize, bool copyKey = false) + const unsigned* key, int keySize, bool copyKey = false) : fKeySize(keySize) , fFreeKey(copyKey) { fIDMatrix.fPictureID = pictureID; @@ -85,8 +85,8 @@ public: fIDMatrix.fInitialMat.getType(); // force initialization of type so hashes match if (copyKey) { - int* tempKey = SkNEW_ARRAY(int, keySize); - memcpy(tempKey, key, keySize*sizeof(int)); + unsigned* tempKey = SkNEW_ARRAY(unsigned, keySize); + memcpy(tempKey, key, keySize*sizeof(unsigned)); fKey = tempKey; } else { fKey = key; @@ -115,7 +115,7 @@ public: uint32_t pictureID() const { return fIDMatrix.fPictureID; } // TODO: remove these when GrCachedLayer & ReplacementInfo fuse - const int* key() const { SkASSERT(fFreeKey); return fKey; } + const unsigned* key() const { SkASSERT(fFreeKey); return fKey; } int keySize() const { SkASSERT(fFreeKey); return fKeySize; } uint32_t hash() const { @@ -133,18 +133,18 @@ public: SkMatrix fInitialMat; } fIDMatrix; - const int* fKey; - const int fKeySize; - bool fFreeKey; + const unsigned* fKey; + const int fKeySize; + bool fFreeKey; }; static const Key& GetKey(const GrCachedLayer& layer) { return layer.fKey; } static uint32_t Hash(const Key& key) { return key.hash(); } // GrCachedLayer proper - GrCachedLayer(uint32_t pictureID, int start, int stop, + GrCachedLayer(uint32_t pictureID, unsigned start, unsigned stop, const SkIRect& bounds, const SkMatrix& ctm, - const int* key, int keySize, + const unsigned* key, int keySize, const SkPaint* paint) : fKey(pictureID, ctm, key, keySize, true) , fStart(start) @@ -152,11 +152,11 @@ public: , fBounds(bounds) , fPaint(paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL) , fTexture(NULL) - , fRect(GrIRect16::MakeEmpty()) + , fRect(SkIRect::MakeEmpty()) , fPlot(NULL) , fUses(0) , fLocked(false) { - SkASSERT(SK_InvalidGenID != pictureID && start >= 0 && stop >= 0); + SkASSERT(SK_InvalidGenID != pictureID); } ~GrCachedLayer() { @@ -166,20 +166,20 @@ public: uint32_t pictureID() const { return fKey.pictureID(); } // TODO: remove these when GrCachedLayer & ReplacementInfo fuse - const int* key() const { return fKey.key(); } + const unsigned* key() const { return fKey.key(); } int keySize() const { return fKey.keySize(); } - int start() const { return fStart; } + unsigned start() const { return fStart; } // TODO: make bound debug only const SkIRect& bound() const { return fBounds; } - int stop() const { return fStop; } - void setTexture(GrTexture* texture, const GrIRect16& rect) { + unsigned stop() const { return fStop; } + void setTexture(GrTexture* texture, const SkIRect& rect) { SkRefCnt_SafeAssign(fTexture, texture); fRect = rect; } GrTexture* texture() { return fTexture; } const SkPaint* paint() const { return fPaint; } - const GrIRect16& rect() const { return fRect; } + const SkIRect& rect() const { return fRect; } void setPlot(GrPlot* plot) { SkASSERT(NULL == plot || NULL == fPlot); @@ -199,9 +199,9 @@ private: const Key fKey; // The "saveLayer" operation index of the cached layer - const int fStart; + const unsigned fStart; // The final "restore" operation index of the cached layer - const int fStop; + const unsigned fStop; const SkIRect fBounds; @@ -216,7 +216,7 @@ private: // For both atlased and non-atlased layers 'fRect' contains the bound of // the layer in whichever texture it resides. It is empty when 'fTexture' // is NULL. - GrIRect16 fRect; + SkIRect fRect; // For atlased layers, fPlot stores the atlas plot in which the layer rests. // It is always NULL for non-atlased layers. @@ -259,11 +259,13 @@ public: // elements by the GrContext void freeAll(); + GrCachedLayer* findLayer(uint32_t pictureID, const SkMatrix& ctm, + const unsigned* key, int keySize); GrCachedLayer* findLayerOrCreate(uint32_t pictureID, int start, int stop, const SkIRect& bounds, const SkMatrix& initialMat, - const int* key, int keySize, + const unsigned* key, int keySize, const SkPaint* paint); // Attempt to place 'layer' in the atlas. Return true on success; false on failure. @@ -346,7 +348,7 @@ private: void initAtlas(); GrCachedLayer* createLayer(uint32_t pictureID, int start, int stop, const SkIRect& bounds, const SkMatrix& initialMat, - const int* key, int keySize, + const unsigned* key, int keySize, const SkPaint* paint); // Remove all the layers (and unlock any resources) associated with 'pictureID' @@ -367,8 +369,6 @@ private: // for testing friend class TestingAccess; int numLayers() const { return fLayerHash.count(); } - GrCachedLayer* findLayer(uint32_t pictureID, const SkMatrix& ctm, - const int* key, int keySize); }; #endif diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp index 4e78368..a17c7dd 100644 --- a/src/gpu/GrLayerHoister.cpp +++ b/src/gpu/GrLayerHoister.cpp @@ -72,7 +72,6 @@ static void prepare_for_hoisting(GrLayerCache* layerCache, layerCache->addUse(layer); hl->fLayer = layer; hl->fPicture = pict; - hl->fOffset = SkIPoint::Make(layerRect.fLeft, layerRect.fTop); hl->fLocalMat = info.fLocalMat; hl->fInitialMat = initialMat; hl->fPreMat = initialMat; @@ -185,46 +184,6 @@ void GrLayerHoister::FindLayersToHoist(GrContext* context, } } -static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) { - SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); - result->setInfo(info); - result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); -} - -void GrLayerHoister::ConvertLayersToReplacements(const SkPicture* topLevelPicture, - const SkTDArray& layers, - GrReplacements* replacements) { - // TODO: just replace GrReplacements::ReplacementInfo with GrCachedLayer? - for (int i = 0; i < layers.count(); ++i) { - GrCachedLayer* layer = layers[i].fLayer; - - GrReplacements::ReplacementInfo* layerInfo = - replacements->newReplacement(topLevelPicture->uniqueID(), - layers[i].fInitialMat, - layer->key(), layer->keySize()); - layerInfo->fStop = layer->stop(); - layerInfo->fPos = layers[i].fOffset; - - SkBitmap bm; - wrap_texture(layers[i].fLayer->texture(), - !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().width() - : layers[i].fLayer->texture()->width(), - !layers[i].fLayer->isAtlased() ? layers[i].fLayer->rect().height() - : layers[i].fLayer->texture()->height(), - &bm); - layerInfo->fImage = SkImage::NewTexture(bm); - - layerInfo->fPaint = layers[i].fLayer->paint() - ? SkNEW_ARGS(SkPaint, (*layers[i].fLayer->paint())) - : NULL; - - layerInfo->fSrcRect = SkIRect::MakeXYWH(layers[i].fLayer->rect().fLeft, - layers[i].fLayer->rect().fTop, - layers[i].fLayer->rect().width(), - layers[i].fLayer->rect().height()); - } -} - void GrLayerHoister::DrawLayersToAtlas(GrContext* context, const SkTDArray& atlased) { if (atlased.count() > 0) { @@ -241,7 +200,7 @@ void GrLayerHoister::DrawLayersToAtlas(GrContext* context, for (int i = 0; i < atlased.count(); ++i) { const GrCachedLayer* layer = atlased[i].fLayer; const SkPicture* pict = atlased[i].fPicture; - const SkIPoint offset = atlased[i].fOffset; + const SkIPoint offset = SkIPoint::Make(layer->bound().fLeft, layer->bound().fTop); SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) SkASSERT(!layerPaint || !layerPaint->getImageFilter()); @@ -250,10 +209,7 @@ void GrLayerHoister::DrawLayersToAtlas(GrContext* context, // Add a rect clip to make sure the rendering doesn't // extend beyond the boundaries of the atlased sub-rect - SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), - SkIntToScalar(layer->rect().fTop), - SkIntToScalar(layer->rect().width()), - SkIntToScalar(layer->rect().height())); + const SkRect bound = SkRect::Make(layer->rect()); atlasCanvas->clipRect(bound); // Since 'clear' doesn't respect the clip we need to draw a rect @@ -285,7 +241,7 @@ void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArraybound().fLeft, layer->bound().fTop); // Each non-atlased layer has its own GrTexture SkAutoTUnref surface(SkSurface::NewRenderTargetDirect( @@ -297,11 +253,7 @@ void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArrayrect().fLeft), - SkIntToScalar(layer->rect().fTop), - SkIntToScalar(layer->rect().width()), - SkIntToScalar(layer->rect().height())); - + const SkRect bound = SkRect::Make(layer->rect()); layerCanvas->clipRect(bound); layerCanvas->clear(SK_ColorTRANSPARENT); diff --git a/src/gpu/GrLayerHoister.h b/src/gpu/GrLayerHoister.h index a28f887..2d68a94 100644 --- a/src/gpu/GrLayerHoister.h +++ b/src/gpu/GrLayerHoister.h @@ -20,7 +20,6 @@ public: const SkPicture* fPicture; // the picture that actually contains the layer // (not necessarily the top-most picture) GrCachedLayer* fLayer; - SkIPoint fOffset; SkMatrix fInitialMat; SkMatrix fPreMat; SkMatrix fLocalMat; diff --git a/src/gpu/GrRecordReplaceDraw.cpp b/src/gpu/GrRecordReplaceDraw.cpp index 3701dda..852c51f 100644 --- a/src/gpu/GrRecordReplaceDraw.cpp +++ b/src/gpu/GrRecordReplaceDraw.cpp @@ -5,50 +5,34 @@ * found in the LICENSE file. */ +#include "GrContext.h" +#include "GrLayerCache.h" #include "GrRecordReplaceDraw.h" #include "SkCanvasPriv.h" +#include "SkGrPixelRef.h" #include "SkImage.h" #include "SkRecordDraw.h" #include "SkRecords.h" -GrReplacements::ReplacementInfo* GrReplacements::newReplacement(uint32_t pictureID, - const SkMatrix& initialMat, - const int* key, int keySize) { - ReplacementInfo* replacement = SkNEW_ARGS(ReplacementInfo, (pictureID, initialMat, - key, keySize)); - fReplacementHash.add(replacement); - return replacement; +static inline void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) { + SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); + result->setInfo(info); + result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); } -void GrReplacements::freeAll() { - SkTDynamicHash::Iter iter(&fReplacementHash); +static inline void draw_replacement_bitmap(GrCachedLayer* layer, SkCanvas* canvas) { + const SkRect src = SkRect::Make(layer->rect()); + const SkRect dst = SkRect::Make(layer->bound()); - for (; !iter.done(); ++iter) { - ReplacementInfo* replacement = &(*iter); - SkDELETE(replacement); - } - - fReplacementHash.reset(); -} - -const GrReplacements::ReplacementInfo* GrReplacements::lookup(uint32_t pictureID, - const SkMatrix& initialMat, - const int* key, - int keySize) const { - return fReplacementHash.find(ReplacementInfo::Key(pictureID, initialMat, key, keySize)); -} - -static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri, - SkCanvas* canvas) { - SkRect src = SkRect::Make(ri->fSrcRect); - SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX), - SkIntToScalar(ri->fPos.fY), - SkIntToScalar(ri->fSrcRect.width()), - SkIntToScalar(ri->fSrcRect.height())); + SkBitmap bm; + wrap_texture(layer->texture(), + !layer->isAtlased() ? layer->rect().width() : layer->texture()->width(), + !layer->isAtlased() ? layer->rect().height() : layer->texture()->height(), + &bm); canvas->save(); canvas->setMatrix(SkMatrix::I()); - canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint); + canvas->drawBitmapRectToRect(bm, &src, dst, layer->paint()); canvas->restore(); } @@ -56,19 +40,18 @@ static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo // also draws them with replaced layers. class ReplaceDraw : public SkRecords::Draw { public: - ReplaceDraw(SkCanvas* canvas, + ReplaceDraw(SkCanvas* canvas, GrLayerCache* layerCache, SkPicture const* const drawablePicts[], int drawableCount, const SkPicture* topLevelPicture, const SkPicture* picture, - const GrReplacements* replacements, const SkMatrix& initialMatrix, SkDrawPictureCallback* callback, - const int* opIndices, int numIndices) + const unsigned* opIndices, int numIndices) : INHERITED(canvas, drawablePicts, NULL, drawableCount) , fCanvas(canvas) + , fLayerCache(layerCache) , fTopLevelPicture(topLevelPicture) , fPicture(picture) - , fReplacements(replacements) , fInitialMatrix(initialMatrix) , fCallback(callback) , fIndex(0) @@ -137,8 +120,9 @@ public: SkAutoCanvasMatrixPaint acmp(fCanvas, &dp.matrix, dp.paint, dp.picture->cullRect()); // Draw sub-pictures with the same replacement list but a different picture - ReplaceDraw draw(fCanvas, this->drawablePicts(), this->drawableCount(), - fTopLevelPicture, dp.picture, fReplacements, fInitialMatrix, fCallback, + ReplaceDraw draw(fCanvas, fLayerCache, + this->drawablePicts(), this->drawableCount(), + fTopLevelPicture, dp.picture, fInitialMatrix, fCallback, fOpIndexStack.begin(), fOpIndexStack.count()); fNumReplaced += draw.draw(); @@ -158,23 +142,23 @@ public: fOpIndexStack.push(startOffset); - const GrReplacements::ReplacementInfo* ri = fReplacements->lookup( - fTopLevelPicture->uniqueID(), - fInitialMatrix, - fOpIndexStack.begin(), - fOpIndexStack.count()); + GrCachedLayer* layer = fLayerCache->findLayer(fTopLevelPicture->uniqueID(), + fInitialMatrix, + fOpIndexStack.begin(), + fOpIndexStack.count()); - if (ri) { + if (layer) { fNumReplaced++; - draw_replacement_bitmap(ri, fCanvas); + + draw_replacement_bitmap(layer, fCanvas); if (fPicture->fBBH.get()) { - while (fOps[fIndex] < ri->fStop) { + while (fOps[fIndex] < layer->stop()) { ++fIndex; } - SkASSERT(fOps[fIndex] == ri->fStop); + SkASSERT(fOps[fIndex] == layer->stop()); } else { - fIndex = ri->fStop; + fIndex = layer->stop(); } fOpIndexStack.pop(); return; @@ -188,9 +172,9 @@ public: private: SkCanvas* fCanvas; + GrLayerCache* fLayerCache; const SkPicture* fTopLevelPicture; const SkPicture* fPicture; - const GrReplacements* fReplacements; const SkMatrix fInitialMatrix; SkDrawPictureCallback* fCallback; @@ -199,22 +183,21 @@ private: int fNumReplaced; // The op code indices of all the enclosing drawPicture and saveLayer calls - SkTDArray fOpIndexStack; + SkTDArray fOpIndexStack; typedef Draw INHERITED; }; int GrRecordReplaceDraw(const SkPicture* picture, SkCanvas* canvas, - const GrReplacements* replacements, + GrLayerCache* layerCache, const SkMatrix& initialMatrix, SkDrawPictureCallback* callback) { SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); // TODO: drawablePicts? - ReplaceDraw draw(canvas, NULL, 0, + ReplaceDraw draw(canvas, layerCache, NULL, 0, picture, picture, - replacements, initialMatrix, callback, NULL, 0); - + initialMatrix, callback, NULL, 0); return draw.draw(); } diff --git a/src/gpu/GrRecordReplaceDraw.h b/src/gpu/GrRecordReplaceDraw.h index 538661a..c0dd0b6 100644 --- a/src/gpu/GrRecordReplaceDraw.h +++ b/src/gpu/GrRecordReplaceDraw.h @@ -8,124 +8,19 @@ #ifndef GrRecordReplaceDraw_DEFINED #define GrRecordReplaceDraw_DEFINED -#include "SkChecksum.h" #include "SkDrawPictureCallback.h" -#include "SkImage.h" -#include "SkRect.h" -#include "SkTDynamicHash.h" -class SkBBoxHierarchy; -class SkBitmap; +class GrLayerCache; class SkCanvas; -class SkImage; class SkMatrix; -class SkPaint; class SkPicture; -class SkRecord; - -// GrReplacements collects op ranges that can be replaced with -// a single drawBitmap call (using a precomputed bitmap). -class GrReplacements { -public: - // All the operations between fStart and fStop (inclusive) will be replaced with - // a single drawBitmap call using fPos, fImage and fPaint. - class ReplacementInfo { - public: - struct Key { - Key(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize, bool copyKey = false) - : fKeySize(keySize) - , fFreeKey(copyKey) { - fIDMatrix.fPictureID = pictureID; - fIDMatrix.fInitialMat = initialMat; - fIDMatrix.fInitialMat.getType(); // force initialization of type so hashes match - - if (copyKey) { - int* tempKey = SkNEW_ARRAY(int, keySize); - memcpy(tempKey, key, keySize * sizeof(int)); - fKey = tempKey; - } else { - fKey = key; - } - - // The pictureID/matrix portion needs to be tightly packed. - GR_STATIC_ASSERT(sizeof(IDMatrix) == sizeof(uint32_t)+ // pictureID - 9 * sizeof(SkScalar)+sizeof(uint32_t)); // matrix - } - - ~Key() { - if (fFreeKey) { - SkDELETE_ARRAY(fKey); - } - } - bool operator==(const Key& other) const { - if (fKeySize != other.fKeySize) { - return false; - } - return fIDMatrix.fPictureID == other.fIDMatrix.fPictureID && - fIDMatrix.fInitialMat.cheapEqualTo(other.fIDMatrix.fInitialMat) && - !memcmp(fKey, other.fKey, fKeySize * sizeof(int)); - } - - uint32_t hash() const { - uint32_t hash = SkChecksum::Murmur3(reinterpret_cast(fKey), - fKeySize * sizeof(int)); - return SkChecksum::Murmur3(reinterpret_cast(&fIDMatrix), - sizeof(IDMatrix), hash); - } - - private: - struct IDMatrix { - uint32_t fPictureID; - SkMatrix fInitialMat; - } fIDMatrix; - - const int* fKey; - const int fKeySize; - const bool fFreeKey; - }; - - static const Key& GetKey(const ReplacementInfo& layer) { return layer.fKey; } - static uint32_t Hash(const Key& key) { return key.hash(); } - - ReplacementInfo(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize) - : fKey(pictureID, initialMat, key, keySize, true) - , fImage(NULL) - , fPaint(NULL) { - } - ~ReplacementInfo() { fImage->unref(); SkDELETE(fPaint); } - - const Key fKey; - unsigned fStop; - SkIPoint fPos; - SkImage* fImage; // Owns a ref - const SkPaint* fPaint; // Owned by this object - - SkIRect fSrcRect; - }; - - ~GrReplacements() { this->freeAll(); } - - // Add a new replacement range. - ReplacementInfo* newReplacement(uint32_t pictureID, const SkMatrix& initialMat, - const int* key, int keySize); - - const ReplacementInfo* lookup(uint32_t pictureID, const SkMatrix& initalMat, - const int* key, int keySize) const; - -private: - SkTDynamicHash fReplacementHash; - - void freeAll(); -}; // Draw an SkPicture into an SkCanvas replacing saveLayer/restore blocks with // drawBitmap calls. A convenience wrapper around SkRecords::Draw. // It returns the number of saveLayer/restore blocks replaced with drawBitmap calls. int GrRecordReplaceDraw(const SkPicture*, SkCanvas*, - const GrReplacements*, + GrLayerCache* layerCache, const SkMatrix& initialMatrix, SkDrawPictureCallback*); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 3f08aa4..407f360 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1863,13 +1863,9 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture GrLayerHoister::DrawLayers(fContext, needRendering); - GrReplacements replacements; - - GrLayerHoister::ConvertLayersToReplacements(mainPicture, needRendering, &replacements); - GrLayerHoister::ConvertLayersToReplacements(mainPicture, recycled, &replacements); - // Render the entire picture using new layers - GrRecordReplaceDraw(mainPicture, mainCanvas, &replacements, initialMatrix, NULL); + GrRecordReplaceDraw(mainPicture, mainCanvas, fContext->getLayerCache(), + initialMatrix, NULL); GrLayerHoister::UnlockLayers(fContext, needRendering); GrLayerHoister::UnlockLayers(fContext, recycled); diff --git a/tests/GpuLayerCacheTest.cpp b/tests/GpuLayerCacheTest.cpp index 43a845b..cba331f 100644 --- a/tests/GpuLayerCacheTest.cpp +++ b/tests/GpuLayerCacheTest.cpp @@ -15,7 +15,7 @@ class TestingAccess { public: - static int NumLayers(GrLayerCache* cache) { + static unsigned NumLayers(GrLayerCache* cache) { return cache->numLayers(); } static void Purge(GrLayerCache* cache, uint32_t pictureID) { @@ -25,7 +25,8 @@ public: return layer->uses(); } static GrCachedLayer* Find(GrLayerCache* cache, uint32_t pictureID, - const SkMatrix& initialMat, const int* key, int keySize) { + const SkMatrix& initialMat, + const unsigned* key, int keySize) { return cache->findLayer(pictureID, initialMat, key, keySize); } }; @@ -34,11 +35,11 @@ public: static void create_layers(skiatest::Reporter* reporter, GrLayerCache* cache, const SkPicture& picture, - int numToAdd, - int idOffset) { + unsigned numToAdd, + unsigned idOffset) { - for (int i = 0; i < numToAdd; ++i) { - int indices[1] = { idOffset+i+1 }; + for (unsigned i = 0; i < numToAdd; ++i) { + unsigned indices[1] = { idOffset+i+1 }; GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(), idOffset+i+1, idOffset+i+2, SkIRect::MakeEmpty(), @@ -116,8 +117,8 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { create_layers(reporter, &cache, *picture, kInitialNumLayers, 0); - for (int i = 0; i < kInitialNumLayers; ++i) { - int indices[1] = { i + 1 }; + for (unsigned i = 0; i < kInitialNumLayers; ++i) { + unsigned indices[1] = { i + 1 }; GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(), indices, 1); REPORTER_ASSERT(reporter, layer); @@ -135,8 +136,8 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { } // Unlock the textures - for (int i = 0; i < kInitialNumLayers; ++i) { - int indices[1] = { i+1 }; + for (unsigned i = 0; i < kInitialNumLayers; ++i) { + unsigned indices[1] = { i+1 }; GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(), indices, 1); @@ -144,8 +145,8 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { cache.removeUse(layer); } - for (int i = 0; i < kInitialNumLayers; ++i) { - int indices[1] = { i+1 }; + for (unsigned i = 0; i < kInitialNumLayers; ++i) { + unsigned indices[1] = { i+1 }; GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(), indices, 1); @@ -172,7 +173,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { } { - int indices[1] = { kInitialNumLayers+1 }; + unsigned indices[1] = { kInitialNumLayers+1 }; // Add an additional layer. Since all the layers are unlocked this // will force out the first atlased layer @@ -185,8 +186,8 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) { cache.removeUse(layer); } - for (int i = 0; i < kInitialNumLayers+1; ++i) { - int indices[1] = { i+1 }; + for (unsigned i = 0; i < kInitialNumLayers+1; ++i) { + unsigned indices[1] = { i+1 }; GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(), indices, 1); diff --git a/tests/RecordReplaceDrawTest.cpp b/tests/RecordReplaceDrawTest.cpp index 8fc824d..edd4766 100644 --- a/tests/RecordReplaceDrawTest.cpp +++ b/tests/RecordReplaceDrawTest.cpp @@ -9,6 +9,8 @@ #include "Test.h" +#include "GrContextFactory.h" +#include "GrLayerCache.h" #include "GrRecordReplaceDraw.h" #include "RecordTestUtils.h" #include "SkBBHFactory.h" @@ -47,9 +49,8 @@ DEF_TEST(RecordReplaceDraw_Abort, r) { SkRecord rerecord; SkRecorder canvas(&rerecord, kWidth, kHeight); - GrReplacements replacements; JustOneDraw callback; - GrRecordReplaceDraw(pic, &canvas, &replacements, SkMatrix::I(), &callback); + GrRecordReplaceDraw(pic, &canvas, NULL, SkMatrix::I(), &callback); REPORTER_ASSERT(r, 3 == rerecord.count()); assert_type(r, rerecord, 0); @@ -74,8 +75,7 @@ DEF_TEST(RecordReplaceDraw_Unbalanced, r) { SkRecord rerecord; SkRecorder canvas(&rerecord, kWidth, kHeight); - GrReplacements replacements; - GrRecordReplaceDraw(pic, &canvas, &replacements, SkMatrix::I(), NULL/*callback*/); + GrRecordReplaceDraw(pic, &canvas, NULL, SkMatrix::I(), NULL/*callback*/); REPORTER_ASSERT(r, 4 == rerecord.count()); assert_type(r, rerecord, 0); @@ -84,20 +84,8 @@ DEF_TEST(RecordReplaceDraw_Unbalanced, r) { assert_type(r, rerecord, 3); } -static SkImage* make_image(SkColor color) { - const SkPMColor pmcolor = SkPreMultiplyColor(color); - const SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); - const size_t rowBytes = info.minRowBytes(); - const size_t size = rowBytes * info.height(); - - SkAutoMalloc addr(size); - sk_memset32((SkPMColor*)addr.get(), pmcolor, SkToInt(size >> 2)); - - return SkImage::NewRasterCopy(info, addr.get(), rowBytes); -} - // Test out the layer replacement functionality with and w/o a BBH -void test_replacements(skiatest::Reporter* r, bool useBBH) { +void test_replacements(skiatest::Reporter* r, GrContext* context, bool useBBH) { SkAutoTUnref pic; { @@ -115,34 +103,53 @@ void test_replacements(skiatest::Reporter* r, bool useBBH) { pic.reset(recorder.endRecording()); } - int key[1] = { 0 }; + unsigned key[1] = { 0 }; - GrReplacements replacements; - GrReplacements::ReplacementInfo* ri = replacements.newReplacement(pic->uniqueID(), - SkMatrix::I(), key, 1); - ri->fStop = 2; - ri->fPos.set(0, 0); - ri->fImage = make_image(SK_ColorRED); - ri->fPaint = SkNEW(SkPaint); - ri->fSrcRect = SkIRect::MakeWH(kWidth, kHeight); + GrLayerCache* layerCache = context->getLayerCache(); + GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2, + SkIRect::MakeWH(kWidth, kHeight), + SkMatrix::I(), key, 1, SkNEW(SkPaint)); + + GrSurfaceDesc desc; + desc.fConfig = kSkia8888_GrPixelConfig; + desc.fFlags = kRenderTarget_GrSurfaceFlag; + desc.fWidth = kWidth; + desc.fHeight = kHeight; + desc.fSampleCnt = 0; + + SkAutoTUnref texture(context->createUncachedTexture(desc, NULL, 0)); + layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight)); SkAutoTUnref bbh; SkRecord rerecord; SkRecorder canvas(&rerecord, kWidth, kHeight); - GrRecordReplaceDraw(pic, &canvas, &replacements, SkMatrix::I(), NULL/*callback*/); + GrRecordReplaceDraw(pic, &canvas, layerCache, SkMatrix::I(), NULL/*callback*/); REPORTER_ASSERT(r, 7 == rerecord.count()); assert_type(r, rerecord, 0); assert_type(r, rerecord, 1); assert_type(r, rerecord, 2); - assert_type(r, rerecord, 3); + assert_type(r, rerecord, 3); assert_type(r, rerecord, 4); assert_type(r, rerecord, 5); assert_type(r, rerecord, 6); } -DEF_TEST(RecordReplaceDraw_Replace, r) { test_replacements(r, false); } -DEF_TEST(RecordReplaceDraw_ReplaceWithBBH, r) { test_replacements(r, true); } +DEF_GPUTEST(RecordReplaceDraw, r, factory) { + for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { + GrContextFactory::GLContextType glType = static_cast(type); + if (!GrContextFactory::IsRenderingGLContext(glType)) { + continue; + } + GrContext* context = factory->get(glType); + if (NULL == context) { + continue; + } + + test_replacements(r, context, true); + test_replacements(r, context, false); + } +} #endif -- 2.7.4