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

Unified Diff: src/gpu/SkGpuDevice.cpp

Issue 933043006: Implement SkBaseDevice snapshot support Base URL: https://skia.googlesource.com/skia.git@skimage-filters-04-snapshot-devices
Patch Set: Created 5 years, 9 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/SkGpuDevice.h ('k') | src/image/SkSurface.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/SkGpuDevice.cpp
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 808e896ef7da21f053a7c56fd5e4500cdc00b904..6f718e62064e5d5c59a7b00a9d121b1b793be262 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -23,6 +23,7 @@
#include "SkGlyphCache.h"
#include "SkGrTexturePixelRef.h"
#include "SkImageFilter.h"
+#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkLayerInfo.h"
#include "SkMaskFilter.h"
@@ -48,16 +49,17 @@
enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
#if 0
- extern bool (*gShouldDrawProc)();
- #define CHECK_SHOULD_DRAW(draw) \
- do { \
- if (gShouldDrawProc && !gShouldDrawProc()) return; \
- this->prepareDraw(draw); \
- } while (0)
+extern bool (*gShouldDrawProc)();
+#define CHECK_SHOULD_DRAW(draw) \
+ do { \
+ if (gShouldDrawProc && !gShouldDrawProc()) return; \
+ if (!this->prepareDraw(draw)) return; \
+ } while (0)
#else
- #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw)
+#define CHECK_SHOULD_DRAW(draw) if (!this->prepareDraw(draw)) return;
#endif
+
// This constant represents the screen alignment criterion in texels for
// requiring texture domain clamping to prevent color bleeding when drawing
// a sub region of a larger source image.
@@ -166,9 +168,20 @@ static SkSurfaceProps copy_or_default_props(const SkSurfaceProps* props) {
}
}
+namespace {
+
+void wrap_surface(GrSurface* rt, SkBitmap* bm) {
+ bm->setInfo(rt->surfacePriv().info());
+ SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (rt->surfacePriv().info(), rt));
+ bm->setPixelRef(pr)->unref();
+}
+
+};
+
SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags)
: INHERITED(surfaceprops_to_deviceprops(props))
, fSurfaceProps(copy_or_default_props(props))
+ , fSurface(NULL)
{
fDrawProcs = NULL;
@@ -177,11 +190,7 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsign
fRenderTarget = SkRef(rt);
- SkImageInfo info = rt->surfacePriv().info();
- SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt));
- fLegacyBitmap.setInfo(info);
- fLegacyBitmap.setPixelRef(pr)->unref();
-
+ wrap_surface(fRenderTarget, &fLegacyBitmap);
bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLeakyProperties(),
useDFT);
@@ -250,6 +259,13 @@ SkGpuDevice::~SkGpuDevice() {
///////////////////////////////////////////////////////////////////////////////
+void SkGpuDevice::discard() {
+ if (fSurface) {
+ fSurface->notifyContentWillChange();
+ }
+ this->prepareBackendRenderTarget(kDiscard_ModifyMode);
+}
+
bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int x, int y) {
DO_DEFERRED_CLEAR();
@@ -275,6 +291,11 @@ bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, siz
if (kUnknown_GrPixelConfig == config) {
return false;
}
+
+ if (!this->prepareWrite()) {
+ return false;
+ }
+
uint32_t flags = 0;
if (kUnpremul_SkAlphaType == info.alphaType()) {
flags = GrContext::kUnpremul_PixelOpsFlag;
@@ -288,7 +309,9 @@ bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, siz
}
const SkBitmap& SkGpuDevice::onAccessBitmap() {
- DO_DEFERRED_CLEAR();
+ // Must prepare for write because user might obtain the texture from the bitmap and then modify
+ // it.
+ this->prepareWrite();
return fLegacyBitmap;
}
@@ -307,18 +330,38 @@ void SkGpuDevice::onDetachFromCanvas() {
// call this every draw call, to ensure that the context reflects our state,
// and not the state from some other canvas/device
-void SkGpuDevice::prepareDraw(const SkDraw& draw) {
+bool SkGpuDevice::prepareDraw(const SkDraw& draw) {
SkASSERT(fClipStack.get());
SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
fClip.setClipStack(fClipStack, &this->getOrigin());
- DO_DEFERRED_CLEAR();
+ if (!this->prepareBackendRenderTarget(kDrawContent_ModifyMode)) {
+ return false;
+ }
+
+ if (fSurface) {
+ fSurface->notifyContentWillChange();
+ }
+
+ return true;
+}
+
+bool SkGpuDevice::prepareWrite() {
+ if (!this->prepareBackendRenderTarget(kDrawContent_ModifyMode)) {
+ return false;
+ }
+ if (fSurface) {
+ fSurface->notifyContentWillChange();
+ }
+ return true;
}
GrRenderTarget* SkGpuDevice::accessRenderTarget() {
- DO_DEFERRED_CLEAR();
+ // The render target could be read through the ptr, so we must do deferred clear. The render
+ // target could be written to through the ptr, so we must detach the snapshot.
+ this->prepareWrite();
return fRenderTarget;
}
@@ -330,38 +373,81 @@ void SkGpuDevice::clearAll() {
fNeedClear = false;
}
-void SkGpuDevice::replaceRenderTarget(bool shouldRetainContent) {
- // Caller must have accessed the render target, because it knows the rt must be replaced.
- SkASSERT(!fNeedClear);
+bool SkGpuDevice::prepareBackendRenderTarget(ModifyMode writeMode) {
+ // We are preparing for modifying the render target. This will detach the snapshot in all
+ // cases, so do the detach right away.
+ SkAutoTUnref<SkImage> snapshot;
+ snapshot.swap(&fSnapshot);
+
+ bool needNewRenderTarget = false;
+
+ if (NULL != snapshot) {
+ SkASSERT(!fNeedClear);
+ needNewRenderTarget = fRenderTarget->asTexture() == SkTextureImageGetTexture(snapshot) &&
+ !snapshot->unique();
+ }
+
+ if (!needNewRenderTarget) {
+ if (writeMode == kDiscard_ModifyMode) {
+ fRenderTarget->discard();
+ fNeedClear = false;
+ }
+ if (fRenderTarget->wasDestroyed()) {
+ return false;
+ }
+
+ DO_DEFERRED_CLEAR();
+ return true;
+ }
SkSurface::Budgeted budgeted =
fRenderTarget->resourcePriv().isBudgeted() ? SkSurface::kYes_Budgeted
: SkSurface::kNo_Budgeted;
SkAutoTUnref<GrRenderTarget> newRT(CreateRenderTarget(
- fRenderTarget->getContext(), budgeted, this->imageInfo(), fRenderTarget->numSamples()));
+ this->context(), budgeted, this->imageInfo(), fRenderTarget->numSamples()));
if (NULL == newRT) {
- return;
+ return false;
}
- if (shouldRetainContent) {
+ if (writeMode == kDrawContent_ModifyMode) {
if (fRenderTarget->wasDestroyed()) {
- return;
+ return false;
}
- this->context()->copySurface(newRT, fRenderTarget);
+
+ if (fNeedClear) {
+ // Clear the snapshot render target and clear the new render target.
+ this->clearAll();
+ fNeedClear = true; // Clears the new render target.
+ } else {
+ this->context()->copySurface(newRT, fRenderTarget);
+ }
+ } else {
+ fNeedClear = false;
}
SkASSERT(fRenderTarget != newRT);
-
fRenderTarget->unref();
fRenderTarget = newRT.detach();
SkASSERT(fRenderTarget->surfacePriv().info() == fLegacyBitmap.info());
- SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fRenderTarget->surfacePriv().info(), fRenderTarget));
- fLegacyBitmap.setPixelRef(pr)->unref();
+ wrap_surface(fRenderTarget, &fLegacyBitmap);
+
+ SkASSERT(!fRenderTarget->wasDestroyed());
+
+ DO_DEFERRED_CLEAR();
+
+ if (snapshot) {
+ SkTextureImageApplyBudgetedDecision(snapshot);
+ }
+
+ return true;
}
+bool SkGpuDevice::isBackendBudgeted() const {
+ return fRenderTarget->resourcePriv().isBudgeted();
+}
///////////////////////////////////////////////////////////////////////////////
SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
@@ -759,13 +845,6 @@ GrTexture* create_mask_GPU(GrContext* context,
return mask;
}
-SkBitmap wrap_texture(GrTexture* texture) {
- SkBitmap result;
- result.setInfo(texture->surfacePriv().info());
- result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
- return result;
-}
-
};
void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
@@ -1507,7 +1586,9 @@ bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
SkDeviceImageFilterProxy proxy(this, SkSurfaceProps(0, getLeakyProperties().pixelGeometry()));
if (filter->canFilterImageGPU()) {
- return filter->filterImageGPU(&proxy, wrap_texture(texture), ctx, result, offset);
+ SkBitmap filterInput;
+ wrap_surface(texture, &filterInput);
+ return filter->filterImageGPU(&proxy, filterInput, ctx, result, offset);
} else {
return false;
}
@@ -1643,24 +1724,22 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
int x, int y, const SkPaint& paint) {
// clear of the source device must occur before CHECK_SHOULD_DRAW
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext);
- SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
-
// TODO: If the source device covers the whole of this device, we could
// omit fNeedsClear -related flushing.
- // TODO: if source needs clear, we could maybe omit the draw fully.
+ // TODO: if source is a gpu device, we could inspect its fNeedsClear,
+ // and we could maybe omit the draw fully.
- // drawDevice is defined to be in device coords.
- CHECK_SHOULD_DRAW(draw);
-
- GrRenderTarget* devRT = dev->accessRenderTarget();
- GrTexture* devTex;
- if (NULL == (devTex = devRT->asTexture())) {
+ SkAutoTUnref<SkImage> devImage(device->newImageSnapshot());
+ if (NULL == devImage) {
+ return;
+ }
+ GrTexture* devTex = devImage->getTexture();
+ if (NULL == devTex) {
return;
}
- const SkImageInfo ii = dev->imageInfo();
- int w = ii.width();
- int h = ii.height();
+ int w = devImage->width();
+ int h = devImage->height();
SkImageFilter* filter = paint.getImageFilter();
// This bitmap will own the filtered result as a texture.
@@ -1686,6 +1765,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
return;
}
}
+ // drawDevice is defined to be in device coords.
+ CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
grPaint.addColorTextureProcessor(devTex, SkMatrix::I());
@@ -1905,6 +1986,28 @@ void SkGpuDevice::flush() {
fRenderTarget->prepareForExternalRead();
}
+SkImage* SkGpuDevice::newImageSnapshot() {
+ return this->newImageSnapshot(&fSurfaceProps, SkSurface::kYes_Budgeted);
+}
+
+SkImage* SkGpuDevice::newImageSnapshot(const SkSurfaceProps* props, SkSurface::Budgeted budgeted) {
+ if (NULL == fSnapshot) {
+ if (fRenderTarget->wasDestroyed()) {
+ return NULL;
+ }
+ DO_DEFERRED_CLEAR();
+ const int sampleCount = fRenderTarget->numSamples();
+ SkImage* image = SkNewImageFromBitmapTexture(fLegacyBitmap, sampleCount, budgeted);
+ if (!image) {
+ return NULL;
+ }
+ if (props) {
+ as_IB(image)->initWithProps(*props);
+ }
+ fSnapshot.reset(image);
+ }
+ return SkRef(fSnapshot.get());
+}
///////////////////////////////////////////////////////////////////////////////
SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
« no previous file with comments | « src/gpu/SkGpuDevice.h ('k') | src/image/SkSurface.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698