Index: src/gpu/SkGpuDevice.cpp |
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp |
index 693e16c0e320d13ad9889320f947c7b9f11ed8bf..3b2e5b17d78407bc55eeddde4070c72c8eb79f48 100644 |
--- a/src/gpu/SkGpuDevice.cpp |
+++ b/src/gpu/SkGpuDevice.cpp |
@@ -1887,7 +1887,7 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData, |
// 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; |
+ static const int kSaveLayerMaxSize1 = 512; |
if (NULL != ops) { |
// In this case the picture has been generated with a BBH so we use |
@@ -1913,8 +1913,9 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData, |
// TODO: once this code is more stable unsuitable layers can |
// just be omitted during the optimization stage |
if (!info.fValid || |
- kSaveLayerMaxSize < info.fSize.fWidth || |
- kSaveLayerMaxSize < info.fSize.fHeight || |
+ kSaveLayerMaxSize1 < info.fSize.fWidth || |
+ kSaveLayerMaxSize1 < info.fSize.fHeight || |
+ info.fSize.fWidth * info.fSize.fHeight > 256 * 256 || |
info.fIsNested) { |
continue; // this layer is unsuitable |
} |
@@ -1941,8 +1942,9 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData, |
// TODO: once this code is more stable unsuitable layers can |
// just be omitted during the optimization stage |
if (!info.fValid || |
- kSaveLayerMaxSize < info.fSize.fWidth || |
- kSaveLayerMaxSize < info.fSize.fHeight || |
+ kSaveLayerMaxSize1 < info.fSize.fWidth || |
+ kSaveLayerMaxSize1 < info.fSize.fHeight || |
+ info.fSize.fWidth * info.fSize.fHeight > 256 * 256 || |
info.fIsNested) { |
continue; |
} |
@@ -1957,8 +1959,7 @@ bool SkGpuDevice::FindLayersToHoist(const GrAccelData *gpuData, |
bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture, |
const SkMatrix* matrix, const SkPaint* paint) { |
- // todo: should handle these natively |
- if (matrix || paint) { |
+ if (NULL != matrix || NULL != paint) { |
return false; |
} |
@@ -1996,62 +1997,97 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture |
} |
SkPictureReplacementPlayback::PlaybackReplacements replacements; |
+} |
+ |
+void SkGpuDevice::EXPERIMENTAL_preDrawPicture(const SkPicture* picture, |
+ const SkMatrix* matrix, const SkPaint* paint, |
+ const SkIRect* target) { |
+ if (NULL != matrix || NULL != paint) { |
+ return; |
+ } |
- SkTDArray<GrCachedLayer*> atlased, nonAtlased; |
- atlased.setReserve(gpuData->numSaveLayers()); |
+ fContext->getLayerCache()->processDeletedPictures(); |
- // Generate the layer and/or ensure it is locked |
+ SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); |
+ |
+ const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key); |
+ if (NULL == data) { |
+ return; |
+ } |
+ |
+ const GrAccelData *gpuData = static_cast<const GrAccelData*>(data); |
+ |
+ if (0 == gpuData->numSaveLayers()) { |
+ return; |
+ } |
+ |
+ SkAutoTArray<bool> pullForward(gpuData->numSaveLayers()); |
for (int i = 0; i < gpuData->numSaveLayers(); ++i) { |
- if (pullForward[i]) { |
- const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); |
+ pullForward[i] = false; |
+ } |
- GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(), |
- info.fSaveLayerOpID, |
- info.fRestoreOpID, |
- info.fCTM); |
- |
- SkPictureReplacementPlayback::PlaybackReplacements::ReplacementInfo* layerInfo = |
- replacements.push(); |
- layerInfo->fStart = info.fSaveLayerOpID; |
- layerInfo->fStop = info.fRestoreOpID; |
- layerInfo->fPos = info.fOffset; |
- |
- GrTextureDesc desc; |
- desc.fFlags = kRenderTarget_GrTextureFlagBit; |
- desc.fWidth = info.fSize.fWidth; |
- desc.fHeight = info.fSize.fHeight; |
- desc.fConfig = kSkia8888_GrPixelConfig; |
- // TODO: need to deal with sample count |
- |
- bool needsRendering = fContext->getLayerCache()->lock(layer, desc, |
- info.fHasNestedLayers || info.fIsNested); |
- if (NULL == layer->texture()) { |
- continue; |
- } |
+ SkAutoTDelete<const SkPicture::OperationList> ops; |
+ SkIRect query; |
+ |
+ if (NULL != target) { |
+ // TODO: this is suboptimal since it will be repeated in EXPERIMENTAL_drawPicture! |
+ // TODO: just always use 'target' to determine hoisting (rather than active ops)? |
+ ops.reset(picture->EXPERIMENTAL_getActiveOps(*target)); |
+ query = *target; |
+ } else { |
+ query = SkIRect::MakeWH(picture->width(), picture->height()); |
+ } |
- layerInfo->fBM = SkNEW(SkBitmap); // fBM is allocated so ReplacementInfo can be POD |
- wrap_texture(layer->texture(), |
- !layer->isAtlased() ? desc.fWidth : layer->texture()->width(), |
- !layer->isAtlased() ? desc.fHeight : layer->texture()->height(), |
- layerInfo->fBM); |
+ if (!FindLayersToHoist(gpuData, ops.get(), query, pullForward.get())) { |
+ return; |
+ } |
- SkASSERT(info.fPaint); |
- layerInfo->fPaint = info.fPaint; |
+ *fPreprocessed.append() = SkRef(picture); |
- layerInfo->fSrcRect = SkIRect::MakeXYWH(layer->rect().fLeft, |
- layer->rect().fTop, |
- layer->rect().width(), |
- layer->rect().height()); |
+ fDeferredAtlasDraws.setReserve(fDeferredAtlasDraws.count() + gpuData->numSaveLayers()); |
- if (needsRendering) { |
- if (layer->isAtlased()) { |
- *atlased.append() = layer; |
- } else { |
- *nonAtlased.append() = layer; |
- } |
+ // Lock the memory required for all the hoisted layers and add them |
+ // to the deferred drawing lists |
+ // TODO: this may be a bit more VRAM intensive then necessary |
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) { |
+ if (!pullForward[i]) { |
+ continue; |
+ } |
+ |
+ const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); |
+ |
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(), |
+ info.fSaveLayerOpID, |
+ info.fRestoreOpID, |
+ info.fCTM); |
+ |
+ GrTextureDesc desc; |
+ desc.fFlags = kRenderTarget_GrTextureFlagBit; |
+ desc.fWidth = info.fSize.fWidth; |
+ desc.fHeight = info.fSize.fHeight; |
+ desc.fConfig = kSkia8888_GrPixelConfig; |
+ // TODO: need to deal with sample count |
+ |
+ bool needsRendering = fContext->getLayerCache()->lock(layer, desc, |
+ info.fHasNestedLayers || info.fIsNested); |
+ if (NULL == layer->texture()) { |
+ continue; |
+ } |
+ |
+ if (needsRendering) { |
+ DeferredDraw* draw; |
+ |
+ if (layer->isAtlased()) { |
+ draw = fDeferredAtlasDraws.append(); |
+ } else { |
+ draw = fDeferredNonAtlasDraws.append(); |
} |
+ |
+ draw->layer = layer; |
+ draw->picture1 = picture; |
} |
} |
+} |
this->drawLayers(picture, atlased, nonAtlased); |
@@ -2150,6 +2186,7 @@ void SkGpuDevice::drawLayers(const SkPicture* picture, |
} |
} |
+<<<<<<< HEAD |
void SkGpuDevice::unlockLayers(const SkPicture* picture) { |
SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); |
@@ -2158,26 +2195,147 @@ void SkGpuDevice::unlockLayers(const SkPicture* picture) { |
const GrAccelData *gpuData = static_cast<const GrAccelData*>(data); |
SkASSERT(0 != gpuData->numSaveLayers()); |
+======= |
+ fDeferredAtlasDraws.rewind(); |
+ fDeferredNonAtlasDraws.rewind(); |
+} |
+ |
+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(); |
- // unlock the layers |
+ 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)); |
+>>>>>>> Reapply patch |
+ |
+ if (!FindLayersToHoist(gpuData, ops.get(), query, pullForward.get())) { |
+ return false; |
+ } |
+ |
+ this->flushDeferredDraws(); |
+ |
+ SkPictureReplacementPlayback::PlaybackReplacements replacements; |
+ |
+ // Assemble the information needed to render the original picture with the |
+ // hoisted layers |
for (int i = 0; i < gpuData->numSaveLayers(); ++i) { |
+ if (!pullForward[i]) { |
+ continue; |
+ } |
+ |
const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); |
+<<<<<<< HEAD |
GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(), |
info.fSaveLayerOpID, |
info.fRestoreOpID, |
info.fCTM); |
fContext->getLayerCache()->unlock(layer); |
+======= |
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(), |
+ info.fSaveLayerOpID, |
+ info.fRestoreOpID, |
+ info.fCTM); |
+ SkASSERT(layer->locked()); |
+ |
+ SkPictureReplacementPlayback::PlaybackReplacements::ReplacementInfo* layerInfo = |
+ replacements.push(); |
+ layerInfo->fStart = info.fSaveLayerOpID; |
+ layerInfo->fStop = info.fRestoreOpID; |
+ layerInfo->fPos = info.fOffset; |
+ |
+ layerInfo->fBM = SkNEW(SkBitmap); // fBM is allocated so ReplacementInfo can be POD |
+ wrap_texture(layer->texture(), |
+ layer->isAtlased() ? layer->texture()->width() : info.fSize.fWidth, |
+ layer->isAtlased() ? layer->texture()->height() : info.fSize.fHeight, |
+ layerInfo->fBM); |
+ |
+ SkASSERT(info.fPaint); |
+ layerInfo->fPaint = info.fPaint; |
+ |
+ layerInfo->fSrcRect = SkIRect::MakeXYWH(layer->rect().fLeft, |
+ layer->rect().fTop, |
+ layer->rect().width(), |
+ layer->rect().height()); |
+>>>>>>> Reapply patch |
+ } |
+ |
+ // Render the entire picture using new layers |
+ SkPictureReplacementPlayback playback(picture, &replacements, ops.get()); |
+ |
+ playback.draw(mainCanvas, NULL); |
+ |
+ return true; |
+} |
+ |
+void SkGpuDevice::EXPERIMENTAL_postDrawPicture() { |
+ SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); |
+ |
+ for (int i = 0; i < fPreprocessed.count(); ++i) { |
+ const SkPicture* picture = fPreprocessed[i]; |
+ |
+ 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 associated with the current picture |
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) { |
+ const GrAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); |
+ |
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(), |
+ info.fSaveLayerOpID, |
+ info.fRestoreOpID, |
+ info.fCTM); |
+ fContext->getLayerCache()->unlock(layer); |
+ } |
+ |
+#if DISABLE_CACHING |
+ // TODO: for debugging only |
+ fContext->getLayerCache()->purge(picture->uniqueID()); |
+#endif |
+ |
+ picture->unref(); |
} |
#if DISABLE_CACHING |
// This code completely clears out the atlas. It is required when |
// caching is disabled so the atlas doesn't fill up and force more |
// free floating layers |
- fContext->getLayerCache()->purge(picture->uniqueID()); |
- |
fContext->getLayerCache()->purgeAll(); |
#endif |
+ |
+ fPreprocessed.rewind(); |
} |
SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { |