Adding setSurface public API method to SkDeferredCanvas
The purpose of this change is to provide an API that Blink 2D canvas layers can use to install a new render target when recovering from a lost graphics context. Review URL: https://codereview.chromium.org/15896005 git-svn-id: http://skia.googlecode.com/svn/trunk@9276 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
24287c15d6
commit
7070f76b90
@ -53,6 +53,16 @@ public:
|
||||
*/
|
||||
virtual SkDevice* setDevice(SkDevice* device);
|
||||
|
||||
/**
|
||||
* Specify the surface to be used by this canvas. Calling setSurface will
|
||||
* release the previously set surface or device. Takes a reference on the
|
||||
* surface.
|
||||
*
|
||||
* @param surface The surface that the canvas will raw into
|
||||
* @return The surface argument, for convenience.
|
||||
*/
|
||||
SkSurface* setSurface(SkSurface* surface);
|
||||
|
||||
/**
|
||||
* Specify a NotificationClient to be used by this canvas. Calling
|
||||
* setNotificationClient will release the previously set
|
||||
|
@ -148,6 +148,7 @@ public:
|
||||
SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
|
||||
SkDevice* immediateDevice() const {return fImmediateCanvas->getTopDevice();}
|
||||
SkImage* newImageSnapshot();
|
||||
void setSurface(SkSurface* surface);
|
||||
bool isFreshFrame();
|
||||
bool hasPendingCommands();
|
||||
size_t storageAllocatedForRecording() const;
|
||||
@ -261,6 +262,7 @@ DeferredDevice::DeferredDevice(SkDevice* immediateDevice)
|
||||
immediateDevice->getDeviceProperties()) {
|
||||
fSurface = NULL;
|
||||
fImmediateCanvas = SkNEW_ARGS(SkCanvas, (immediateDevice));
|
||||
fPipeController.setPlaybackCanvas(fImmediateCanvas);
|
||||
this->init();
|
||||
}
|
||||
|
||||
@ -272,13 +274,18 @@ DeferredDevice::DeferredDevice(SkSurface* surface)
|
||||
surface->getCanvas()->getDevice()->getDeviceProperties()) {
|
||||
fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
|
||||
fNotificationClient = NULL;
|
||||
fImmediateCanvas = surface->getCanvas();
|
||||
SkSafeRef(fImmediateCanvas);
|
||||
fSurface = surface;
|
||||
SkSafeRef(fSurface);
|
||||
fImmediateCanvas = NULL;
|
||||
fSurface = NULL;
|
||||
this->setSurface(surface);
|
||||
this->init();
|
||||
}
|
||||
|
||||
void DeferredDevice::setSurface(SkSurface* surface) {
|
||||
SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas());
|
||||
SkRefCnt_SafeAssign(fSurface, surface);
|
||||
fPipeController.setPlaybackCanvas(fImmediateCanvas);
|
||||
}
|
||||
|
||||
void DeferredDevice::init() {
|
||||
fRecordingCanvas = NULL;
|
||||
fFreshFrame = true;
|
||||
@ -287,7 +294,6 @@ void DeferredDevice::init() {
|
||||
fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold;
|
||||
fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
|
||||
fNotificationClient = NULL;
|
||||
fPipeController.setPlaybackCanvas(fImmediateCanvas);
|
||||
this->beginRecording();
|
||||
}
|
||||
|
||||
@ -620,6 +626,19 @@ SkDevice* SkDeferredCanvas::setDevice(SkDevice* device) {
|
||||
return device;
|
||||
}
|
||||
|
||||
SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) {
|
||||
DeferredDevice* deferredDevice = this->getDeferredDevice();
|
||||
if (NULL != deferredDevice) {
|
||||
// By swapping the surface into the existing device, we preserve
|
||||
// all pending commands, which can help to seamlessly recover from
|
||||
// a lost accelerated graphics context.
|
||||
deferredDevice->setSurface(surface);
|
||||
} else {
|
||||
this->INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (surface)))->unref();
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
|
||||
NotificationClient* notificationClient) {
|
||||
|
||||
|
@ -548,6 +548,51 @@ static void TestDeferredCanvasSurface(skiatest::Reporter* reporter, GrContextFac
|
||||
REPORTER_ASSERT(reporter, pixels4 == pixels5);
|
||||
}
|
||||
|
||||
static void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContextFactory* factory) {
|
||||
SkImage::Info imageSpec = {
|
||||
10, // width
|
||||
10, // height
|
||||
SkImage::kPMColor_ColorType,
|
||||
SkImage::kPremul_AlphaType
|
||||
};
|
||||
SkSurface* surface;
|
||||
SkSurface* alternateSurface;
|
||||
bool useGpu = NULL != factory;
|
||||
#if SK_SUPPORT_GPU
|
||||
if (useGpu) {
|
||||
GrContext* context = factory->get(GrContextFactory::kNative_GLContextType);
|
||||
surface = SkSurface::NewRenderTarget(context, imageSpec);
|
||||
alternateSurface = SkSurface::NewRenderTarget(context, imageSpec);
|
||||
} else {
|
||||
surface = SkSurface::NewRaster(imageSpec);
|
||||
alternateSurface = SkSurface::NewRaster(imageSpec);
|
||||
}
|
||||
#else
|
||||
SkASSERT(!useGpu);
|
||||
surface = SkSurface::NewRaster(imageSpec);
|
||||
alternateSurface = SkSurface::NewRaster(imageSpec);
|
||||
#endif
|
||||
SkASSERT(NULL != surface);
|
||||
SkASSERT(NULL != alternateSurface);
|
||||
SkAutoTUnref<SkSurface> aur1(surface);
|
||||
SkAutoTUnref<SkSurface> aur2(alternateSurface);
|
||||
PixelPtr pixels1 = getSurfacePixelPtr(surface, useGpu);
|
||||
PixelPtr pixels2 = getSurfacePixelPtr(alternateSurface, useGpu);
|
||||
SkDeferredCanvas canvas(surface);
|
||||
SkAutoTUnref<SkImage> image1(canvas.newImageSnapshot());
|
||||
canvas.setSurface(alternateSurface);
|
||||
SkAutoTUnref<SkImage> image2(canvas.newImageSnapshot());
|
||||
REPORTER_ASSERT(reporter, image1->uniqueID() != image2->uniqueID());
|
||||
// Verify that none of the above operations triggered a surface copy on write.
|
||||
REPORTER_ASSERT(reporter, getSurfacePixelPtr(surface, useGpu) == pixels1);
|
||||
REPORTER_ASSERT(reporter, getSurfacePixelPtr(alternateSurface, useGpu) == pixels2);
|
||||
// Verify that a flushed draw command will trigger a copy on write on alternateSurface.
|
||||
canvas.clear(SK_ColorWHITE);
|
||||
canvas.flush();
|
||||
REPORTER_ASSERT(reporter, getSurfacePixelPtr(surface, useGpu) == pixels1);
|
||||
REPORTER_ASSERT(reporter, getSurfacePixelPtr(alternateSurface, useGpu) != pixels2);
|
||||
}
|
||||
|
||||
static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporter) {
|
||||
SkBitmap store;
|
||||
store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
|
||||
@ -581,8 +626,10 @@ static void TestDeferredCanvas(skiatest::Reporter* reporter, GrContextFactory* f
|
||||
TestDeferredCanvasBitmapSizeThreshold(reporter);
|
||||
TestDeferredCanvasCreateCompatibleDevice(reporter);
|
||||
TestDeferredCanvasSurface(reporter, NULL);
|
||||
TestDeferredCanvasSetSurface(reporter, NULL);
|
||||
if (NULL != factory) {
|
||||
TestDeferredCanvasSurface(reporter, factory);
|
||||
TestDeferredCanvasSetSurface(reporter, factory);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user