| Index: src/gpu/SkGpuDevice.cpp
|
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
|
| index f2bd025a0f6e5d9bc29777213420914d2549a783..693e16c0e320d13ad9889320f947c7b9f11ed8bf 100644
|
| --- a/src/gpu/SkGpuDevice.cpp
|
| +++ b/src/gpu/SkGpuDevice.cpp
|
| @@ -1876,49 +1876,20 @@ static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* re
|
| result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
|
| }
|
|
|
| -bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture,
|
| - const SkMatrix* matrix, const SkPaint* paint) {
|
| - // todo: should handle these natively
|
| - if (matrix || paint) {
|
| - return false;
|
| - }
|
| -
|
| - fContext->getLayerCache()->processDeletedPictures();
|
| -
|
| - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
| -
|
| - const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| - if (NULL == data) {
|
| - return false;
|
| - }
|
| -
|
| - const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| -
|
| - if (0 == gpuData->numSaveLayers()) {
|
| - return false;
|
| - }
|
| -
|
| - SkAutoTArray<bool> pullForward(gpuData->numSaveLayers());
|
| - for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| - pullForward[i] = false;
|
| - }
|
| -
|
| - SkRect clipBounds;
|
| - if (!mainCanvas->getClipBounds(&clipBounds)) {
|
| - return true;
|
| - }
|
| - SkIRect query;
|
| - clipBounds.roundOut(&query);
|
| -
|
| - SkAutoTDelete<const SkPicture::OperationList> ops(picture->EXPERIMENTAL_getActiveOps(query));
|
| -
|
| - // This code pre-renders the entire layer since it will be cached and potentially
|
| +// Return true if any layers are suitable for hoisting
|
| +bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData,
|
| + const SkPicture::OperationList* ops,
|
| + const SkIRect& query,
|
| + bool* pullForward) {
|
| + bool anyHoisted = false;
|
| +
|
| + // Layer hoisting pre-renders the entire layer since it will be cached and potentially
|
| // reused with different clips (e.g., in different tiles). Because of this the
|
| // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize
|
| // is used to limit which clips are pre-rendered.
|
| static const int kSaveLayerMaxSize = 256;
|
|
|
| - if (NULL != ops.get()) {
|
| + if (NULL != ops) {
|
| // In this case the picture has been generated with a BBH so we use
|
| // the BBH to limit the pre-rendering to just the layers needed to cover
|
| // the region being drawn
|
| @@ -1928,7 +1899,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
| // For now we're saving all the layers in the GrAccelData so they
|
| // can be nested. Additionally, the nested layers appear before
|
| // their parent in the list.
|
| - for (int j = 0 ; j < gpuData->numSaveLayers(); ++j) {
|
| + for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
|
| const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
|
|
|
| if (pullForward[j]) {
|
| @@ -1949,6 +1920,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
| }
|
|
|
| pullForward[j] = true;
|
| + anyHoisted = true;
|
| }
|
| }
|
| } else {
|
| @@ -1976,9 +1948,53 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
| }
|
|
|
| pullForward[j] = true;
|
| + anyHoisted = true;
|
| }
|
| }
|
|
|
| + return anyHoisted;
|
| +}
|
| +
|
| +bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture,
|
| + const SkMatrix* matrix, const SkPaint* paint) {
|
| + // todo: should handle these natively
|
| + if (matrix || paint) {
|
| + return false;
|
| + }
|
| +
|
| + fContext->getLayerCache()->processDeletedPictures();
|
| +
|
| + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
| +
|
| + const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| + if (NULL == data) {
|
| + return false;
|
| + }
|
| +
|
| + const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| +
|
| + if (0 == gpuData->numSaveLayers()) {
|
| + return false;
|
| + }
|
| +
|
| + SkAutoTArray<bool> pullForward(gpuData->numSaveLayers());
|
| + for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| + pullForward[i] = false;
|
| + }
|
| +
|
| + SkRect clipBounds;
|
| + if (!mainCanvas->getClipBounds(&clipBounds)) {
|
| + return true;
|
| + }
|
| + SkIRect query;
|
| + clipBounds.roundOut(&query);
|
| +
|
| + SkAutoTDelete<const SkPicture::OperationList> ops(picture->EXPERIMENTAL_getActiveOps(query));
|
| +
|
| + if (!FindLayersToHoist(gpuData, ops.get(), query, pullForward.get())) {
|
| + return false;
|
| + }
|
| +
|
| SkPictureReplacementPlayback::PlaybackReplacements replacements;
|
|
|
| SkTDArray<GrCachedLayer*> atlased, nonAtlased;
|
| @@ -2037,13 +2053,28 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
| }
|
| }
|
|
|
| + this->drawLayers(picture, atlased, nonAtlased);
|
| +
|
| + // Render the entire picture using new layers
|
| + SkPictureReplacementPlayback playback(picture, &replacements, ops.get());
|
| +
|
| + playback.draw(mainCanvas, NULL);
|
| +
|
| + this->unlockLayers(picture);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void SkGpuDevice::drawLayers(const SkPicture* picture,
|
| + const SkTDArray<GrCachedLayer*>& atlased,
|
| + const SkTDArray<GrCachedLayer*>& nonAtlased) {
|
| // Render the atlased layers that require it
|
| if (atlased.count() > 0) {
|
| // All the atlased layers are rendered into the same GrTexture
|
| SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
|
| - atlased[0]->texture()->asRenderTarget(),
|
| - SkSurface::kStandard_TextRenderMode,
|
| - SkSurface::kDontClear_RenderTargetFlag));
|
| + atlased[0]->texture()->asRenderTarget(),
|
| + SkSurface::kStandard_TextRenderMode,
|
| + SkSurface::kDontClear_RenderTargetFlag));
|
|
|
| SkCanvas* atlasCanvas = surface->getCanvas();
|
|
|
| @@ -2091,9 +2122,9 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
|
|
| // Each non-atlased layer has its own GrTexture
|
| SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
|
| - layer->texture()->asRenderTarget(),
|
| - SkSurface::kStandard_TextRenderMode,
|
| - SkSurface::kDontClear_RenderTargetFlag));
|
| + layer->texture()->asRenderTarget(),
|
| + SkSurface::kStandard_TextRenderMode,
|
| + SkSurface::kDontClear_RenderTargetFlag));
|
|
|
| SkCanvas* layerCanvas = surface->getCanvas();
|
|
|
| @@ -2117,17 +2148,22 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
|
|
| layerCanvas->flush();
|
| }
|
| +}
|
|
|
| - // Render the entire picture using new layers
|
| - SkPictureReplacementPlayback playback(picture, &replacements, ops.get());
|
| +void SkGpuDevice::unlockLayers(const SkPicture* picture) {
|
| + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
|
|
| - playback.draw(mainCanvas, NULL);
|
| + const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
|
| + SkASSERT(NULL != data);
|
| +
|
| + const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
|
| + SkASSERT(0 != gpuData->numSaveLayers());
|
|
|
| // unlock the layers
|
| for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
|
| const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
|
|
|
| - GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(),
|
| + GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(),
|
| info.fSaveLayerOpID,
|
| info.fRestoreOpID,
|
| info.fCTM);
|
| @@ -2142,8 +2178,6 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
|
|
|
| fContext->getLayerCache()->purgeAll();
|
| #endif
|
| -
|
| - return true;
|
| }
|
|
|
| SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() {
|
|
|