Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Unified Diff: src/gpu/SkGpuDevice.cpp

Issue 261663003: First pass at pre-rendering saveLayers for GPU (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Reduce size of PlaybackReplacements in SkPicturePlayback.h Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrPictureUtils.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/SkGpuDevice.cpp
===================================================================
--- src/gpu/SkGpuDevice.cpp (revision 14614)
+++ src/gpu/SkGpuDevice.cpp (working copy)
@@ -28,6 +28,7 @@
#include "SkMaskFilter.h"
#include "SkPathEffect.h"
#include "SkPicture.h"
+#include "SkPicturePlayback.h"
#include "SkRRect.h"
#include "SkStroke.h"
#include "SkSurface.h"
@@ -1920,6 +1921,12 @@
GatherGPUInfo(picture, data);
}
+static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
+ SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
+ result->setConfig(info);
+ result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
+}
+
void SkGpuDevice::EXPERIMENTAL_purge(SkPicture* picture) {
}
@@ -1940,30 +1947,148 @@
pullForward[i] = false;
}
- SkIRect clip;
+ SkRect clipBounds;
+ if (!canvas->getClipBounds(&clipBounds)) {
+ return true;
+ }
+ SkIRect query;
+ clipBounds.roundOut(&query);
- fClipData.getConservativeBounds(this->width(), this->height(), &clip, NULL);
+ const SkPicture::OperationList& ops = picture->EXPERIMENTAL_getActiveOps(query);
- SkMatrix inv;
- if (!fContext->getMatrix().invert(&inv)) {
- return false;
- }
+ // This code 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;
- SkRect r = SkRect::Make(clip);
- inv.mapRect(&r);
- r.roundOut(&clip);
+ if (ops.valid()) {
+ // 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
+ for (int i = 0; i < ops.numOps(); ++i) {
+ uint32_t offset = ops.offset(i);
- const SkPicture::OperationList& ops = picture->EXPERIMENTAL_getActiveOps(clip);
+ // For now we're saving all the layers in the GPUAccelData so they
+ // can be nested. Additionally, the nested layers appear before
+ // their parent in the list.
+ for (int j = 0 ; j < gpuData->numSaveLayers(); ++j) {
+ const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
- for (int i = 0; i < ops.numOps(); ++i) {
+ if (pullForward[j]) {
+ continue; // already pulling forward
+ }
+
+ if (offset < info.fSaveLayerOpID || offset > info.fRestoreOpID) {
+ continue; // the op isn't in this range
+ }
+
+ // 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 ||
+ info.fIsNested) {
+ continue; // this layer is unsuitable
+ }
+
+ pullForward[j] = true;
+ }
+ }
+ } else {
+ // In this case there is no BBH associated with the picture. Pre-render
+ // all the layers
+ // TODO: intersect the bounds of each layer with the clip region to
+ // reduce the number of pre-rendered layers
for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
- if (ops.offset(i) > info.fSaveLayerOpID && ops.offset(i) < info.fRestoreOpID) {
- pullForward[j] = true;
+ // 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 ||
+ info.fIsNested) {
+ continue;
}
+
+ pullForward[j] = true;
}
}
- return false;
+ SkPicturePlayback::PlaybackReplacements replacements;
+
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
+ if (pullForward[i]) {
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
+
+ const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
+
+ if (NULL != picture->fPlayback) {
+ SkPicturePlayback::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 bNeedsRendering = true;
+
+ // This just uses scratch textures and doesn't cache the texture.
+ // This can yield a lot of re-rendering
+ if (NULL == layer->getTexture()) {
+ layer->setTexture(fContext->lockAndRefScratchTexture(desc,
+ GrContext::kApprox_ScratchTexMatch));
+ if (NULL == layer->getTexture()) {
+ continue;
+ }
+ } else {
+ bNeedsRendering = false;
+ }
+
+ layerInfo->fBM = SkNEW(SkBitmap);
+ wrap_texture(layer->getTexture(), desc.fWidth, desc.fHeight, layerInfo->fBM);
+
+ SkASSERT(info.fPaint);
+ layerInfo->fPaint = info.fPaint;
+
+ if (bNeedsRendering) {
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
+ layer->getTexture()->asRenderTarget()));
+
+ SkCanvas* canvas = surface->getCanvas();
+
+ canvas->setMatrix(info.fCTM);
+ canvas->clear(SK_ColorTRANSPARENT);
+
+ picture->fPlayback->setDrawLimits(info.fSaveLayerOpID, info.fRestoreOpID);
+ picture->fPlayback->draw(*canvas, NULL);
+ picture->fPlayback->setDrawLimits(0, 0);
+ canvas->flush();
+ }
+ }
+ }
+ }
+
+ // Playback using new layers
+ picture->fPlayback->setReplacements(&replacements);
+ picture->fPlayback->draw(*canvas, NULL);
+ picture->fPlayback->setReplacements(NULL);
+
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
+
+ if (NULL != layer->getTexture()) {
+ fContext->unlockScratchTexture(layer->getTexture());
+ layer->setTexture(NULL);
+ }
+ }
+
+ return true;
}
« no previous file with comments | « src/gpu/GrPictureUtils.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698