Add DeviceManager to SampleWindow
Review URL: http://codereview.appspot.com/4715045/
git-svn-id: http://skia.googlecode.com/svn/trunk@1857 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 258da06..5251604 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -53,6 +53,104 @@
static SampleWindow* gSampleWindow;
///////////////
+class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
+public:
+
+ DefaultDeviceManager() {
+ fGrRenderTarget = NULL;
+ fGrContext = NULL;
+ }
+
+ virtual ~DefaultDeviceManager() {
+ SkSafeUnref(fGrRenderTarget);
+ SkSafeUnref(fGrContext);
+ }
+
+ virtual void init(SampleWindow* win) {
+ win->attachGL();
+ if (NULL == fGrContext) {
+ fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
+ }
+ if (NULL == fGrContext) {
+ SkDebugf("Failed to setup 3D");
+ win->detachGL();
+ }
+ }
+
+ virtual bool supportsDeviceType(SampleWindow::DeviceType dType) {
+ switch (dType) {
+ case kRaster_DeviceType:
+ case kPicture_DeviceType: // fallthru
+ return true;
+ case kGPU_DeviceType:
+ return NULL != fGrContext && NULL != fGrRenderTarget;
+ default:
+ return false;
+ }
+ }
+
+ virtual bool prepareCanvas(SampleWindow::DeviceType dType,
+ SkCanvas* canvas,
+ SampleWindow* win) {
+ if (kGPU_DeviceType == dType) {
+ if (fGrContext) {
+ canvas->setDevice(new SkGpuDevice(fGrContext,
+ fGrRenderTarget))->unref();
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ virtual void publishCanvas(SampleWindow::DeviceType dType,
+ SkCanvas* canvas,
+ SampleWindow* win) {
+ if (fGrContext) {
+ // in case we have queued drawing calls
+ fGrContext->flush();
+ if (dType != kGPU_DeviceType) {
+ // need to send the raster bits to the (gpu) window
+ fGrContext->setRenderTarget(fGrRenderTarget);
+ const SkBitmap& bm = win->getBitmap();
+ fGrContext->writePixels(0, 0, bm.width(), bm.height(),
+ kRGBA_8888_GrPixelConfig, bm.getPixels(),
+ bm.rowBytes());
+ }
+ }
+ win->presentGL();
+ }
+
+ virtual void windowSizeChanged(SampleWindow* win) {
+ if (fGrContext) {
+ win->attachGL();
+
+ GrPlatformSurfaceDesc desc;
+ desc.reset();
+ desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
+ desc.fWidth = SkScalarRound(win->width());
+ desc.fHeight = SkScalarRound(win->height());
+ desc.fConfig = kRGBA_8888_GrPixelConfig;
+ desc.fStencilBits = 8;
+ GrGLint buffer;
+ GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
+ desc.fPlatformRenderTarget = buffer;
+
+ SkSafeUnref(fGrRenderTarget);
+ fGrRenderTarget = static_cast<GrRenderTarget*>(
+ fGrContext->createPlatformSurface(desc));
+ }
+ }
+
+ virtual GrContext* getGrContext() {
+ return fGrContext;
+ }
+private:
+ GrContext* fGrContext;
+ GrRenderTarget* fGrRenderTarget;
+};
+
+///////////////
static const char view_inval_msg[] = "view-inval-msg";
void SampleWindow::postInvalDelay() {
@@ -258,21 +356,6 @@
fZoomCenterY = SkFloatToScalar(y);
}
-bool SampleWindow::setGrContext(GrContext* context)
-{
- if (fGrContext) {
- fGrContext->unref();
- }
- fGrContext = context;
- fGrContext->ref();
- return true;
-}
-
-GrContext* SampleWindow::getGrContext()
-{
- return fGrContext;
-}
-
bool SampleWindow::zoomIn()
{
// Arbitrarily decided
@@ -305,54 +388,16 @@
}
}
-bool SampleWindow::make3DReady() {
-
-#if defined(SK_SUPPORT_GL)
- if (attachGL()) {
- if (NULL != fGrContext) {
- // various gr lifecycle tests
- #if 0
- fGrContext->freeGpuResources();
- #elif 0
- // this will leak resources.
- fGrContext->contextLost();
- #elif 0
- GrAssert(1 == fGrContext->refcnt());
- fGrContext->unref();
- fGrContext = NULL;
- #endif
- }
-
- if (NULL == fGrContext) {
- #if defined(SK_USE_SHADERS)
- fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
- #else
- fGrContext = GrContext::Create(kOpenGL_Fixed_GrEngine, NULL);
- #endif
- SkDebugf("---- constructor\n");
- }
-
- if (NULL != fGrContext) {
- return true;
- } else {
- detachGL();
- }
- }
-#endif
- SkDebugf("Failed to setup 3D");
- return false;
-}
-
-SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
- static const CanvasType gCT[] = {
- kPicture_CanvasType,
- kGPU_CanvasType,
- kRaster_CanvasType
+static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType ct) {
+ static const SampleWindow::DeviceType gCT[] = {
+ SampleWindow::kPicture_DeviceType,
+ SampleWindow::kGPU_DeviceType,
+ SampleWindow::kRaster_DeviceType
};
return gCT[ct];
}
-SampleWindow::SampleWindow(void* hwnd, int argc, char** argv) : INHERITED(hwnd) {
+SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager) : INHERITED(hwnd) {
gSampleWindow = this;
#ifdef PIPE_FILE
@@ -362,14 +407,11 @@
#endif
fPicture = NULL;
-
- fGrContext = NULL;
- fGrRenderTarget = NULL;
-
+
#ifdef DEFAULT_TO_GPU
- fCanvasType = kGPU_CanvasType;
+ fDeviceType = kGPU_DeviceType;
#else
- fCanvasType = kRaster_CanvasType;
+ fDeviceType = kRaster_DeviceType;
#endif
fUseClip = false;
fNClip = false;
@@ -428,7 +470,14 @@
fPDFData = NULL;
- this->make3DReady();
+ if (NULL == devManager) {
+ fDevManager = new DefaultDeviceManager();
+ } else {
+ devManager->ref();
+ fDevManager = devManager;
+ }
+ fDevManager->init(this);
+
// If another constructor set our dimensions, ensure that our
// onSizeChange gets called.
if (this->height() && this->width()) {
@@ -441,8 +490,7 @@
delete fPdfCanvas;
fTypeface->unref();
- SkSafeUnref(fGrRenderTarget);
- SkSafeUnref(fGrContext);
+ SkSafeUnref(fDevManager);
}
static SkBitmap capture_bitmap(SkCanvas* canvas) {
@@ -494,11 +542,10 @@
#define YCLIP_N 8
void SampleWindow::draw(SkCanvas* canvas) {
- if (fGrContext && (kGPU_CanvasType == fCanvasType)) {
- canvas->setDevice(new SkGpuDevice(fGrContext,
- fGrRenderTarget))->unref();
- }
+ if (!fDevManager->prepareCanvas(fDeviceType, canvas, this)) {
+ return;
+ }
// update the animation time
gAnimTimePrev = gAnimTime;
gAnimTime = SkTime::GetMSecs();
@@ -581,29 +628,12 @@
} else {
this->INHERITED::draw(canvas);
}
- if (fShowZoomer && fCanvasType != kGPU_CanvasType && !fSaveToPdf) {
- // In the GPU case, INHERITED::draw calls beforeChildren, which
- // creates an SkGpuCanvas. All further draw calls are directed
- // at that canvas, which is deleted in afterChildren (which is
- // also called by draw), so we cannot show the zoomer here.
- // Instead, we call it inside afterChildren.
+ if (fShowZoomer && !fSaveToPdf) {
showZoomer(canvas);
}
// do this last
- if (fGrContext) {
- // in case we have queued drawing calls
- fGrContext->flush();
- if (fCanvasType != kGPU_CanvasType) {
- // need to send the raster bits to the (gpu) window
- fGrContext->setRenderTarget(fGrRenderTarget);
- const SkBitmap& bm = this->getBitmap();
- fGrContext->writePixels(0, 0, bm.width(), bm.height(),
- kRGBA_8888_GrPixelConfig, bm.getPixels(),
- bm.rowBytes());
- }
- }
- presentGL();
+ fDevManager->publishCanvas(fDeviceType, canvas, this);
}
void SampleWindow::showZoomer(SkCanvas* canvas) {
@@ -731,12 +761,12 @@
pdfDevice->unref();
canvas = fPdfCanvas;
} else {
- switch (fCanvasType) {
- case kRaster_CanvasType:
- case kGPU_CanvasType:
+ switch (fDeviceType) {
+ case kRaster_DeviceType:
+ case kGPU_DeviceType:
canvas = this->INHERITED::beforeChildren(canvas);
break;
- case kPicture_CanvasType:
+ case kPicture_DeviceType:
fPicture = new SkPicture;
canvas = fPicture->beginRecording(9999, 9999);
break;
@@ -811,37 +841,26 @@
}
}
- switch (fCanvasType) {
- case kRaster_CanvasType:
- break;
- case kPicture_CanvasType:
- if (true) {
- SkPicture* pict = new SkPicture(*fPicture);
- fPicture->unref();
- orig->drawPicture(*pict);
- pict->unref();
- } else if (true) {
- SkDynamicMemoryWStream ostream;
- fPicture->serialize(&ostream);
- fPicture->unref();
+ if (kPicture_DeviceType == fDeviceType) {
+ if (true) {
+ SkPicture* pict = new SkPicture(*fPicture);
+ fPicture->unref();
+ orig->drawPicture(*pict);
+ pict->unref();
+ } else if (true) {
+ SkDynamicMemoryWStream ostream;
+ fPicture->serialize(&ostream);
+ fPicture->unref();
- SkAutoDataUnref data(ostream.copyToData());
- SkMemoryStream istream(data.data(), data.size());
- SkPicture pict(&istream);
- orig->drawPicture(pict);
- } else {
- fPicture->draw(orig);
- fPicture->unref();
- }
- fPicture = NULL;
- break;
-#ifdef SK_SUPPORT_GL
- case kGPU_CanvasType:
- if (fShowZoomer) {
- this->showZoomer(orig);
- }
- break;
-#endif
+ SkAutoDataUnref data(ostream.copyToData());
+ SkMemoryStream istream(data.data(), data.size());
+ SkPicture pict(&istream);
+ orig->drawPicture(pict);
+ } else {
+ fPicture->draw(orig);
+ fPicture->unref();
+ }
+ fPicture = NULL;
}
// Do this after presentGL and other finishing, rather than in afterChild
@@ -1165,7 +1184,11 @@
}
void SampleWindow::toggleRendering() {
- fCanvasType = cycle_canvastype(fCanvasType);
+ DeviceType origDevType = fDeviceType;
+ do {
+ fDeviceType = cycle_devicetype(fDeviceType);
+ } while (origDevType != fDeviceType &&
+ !fDevManager->supportsDeviceType(fDeviceType));
this->updateTitle();
this->inval(NULL);
}
@@ -1322,7 +1345,7 @@
return gConfigNames[c];
}
-static const char* gCanvasTypePrefix[] = {
+static const char* gDeviceTypePrefix[] = {
"raster: ",
"picture: ",
"opengl: "
@@ -1351,7 +1374,7 @@
title.set("<unknown>");
}
- title.prepend(gCanvasTypePrefix[fCanvasType]);
+ title.prepend(gDeviceTypePrefix[fDeviceType]);
title.prepend(" ");
title.prepend(configToString(this->getBitmap().config()));
@@ -1394,25 +1417,6 @@
void SampleWindow::onSizeChange() {
this->INHERITED::onSizeChange();
-
- if (fGrContext) {
- this->attachGL();
-
- GrPlatformSurfaceDesc desc;
- desc.reset();
- desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
- desc.fWidth = SkScalarRound(this->width());
- desc.fHeight = SkScalarRound(this->height());
- desc.fConfig = kRGBA_8888_GrPixelConfig;
- desc.fStencilBits = 8;
- GrGLint buffer;
- GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
- desc.fPlatformRenderTarget = buffer;
-
- SkSafeUnref(fGrRenderTarget);
- fGrRenderTarget = static_cast<GrRenderTarget*>(
- fGrContext->createPlatformSurface(desc));
- }
SkView::F2BIter iter(this);
SkView* view = iter.next();
@@ -1449,6 +1453,7 @@
this->postInvalDelay();
#endif
this->updateTitle(); // to refresh our config
+ fDevManager->windowSizeChanged(this);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1692,7 +1697,7 @@
SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
// test();
- return new SampleWindow(hwnd, argc, argv);
+ return new SampleWindow(hwnd, argc, argv, NULL);
}
void get_preferred_size(int* x, int* y, int* width, int* height) {
diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h
index 9b47b8e..770d620 100644
--- a/samplecode/SampleApp.h
+++ b/samplecode/SampleApp.h
@@ -44,7 +44,48 @@
class SampleWindow : public SkOSWindow {
SkTDArray<SkViewFactory> fSamples;
public:
- SampleWindow(void* hwnd, int argc, char** argv);
+ enum DeviceType {
+ kRaster_DeviceType,
+ kPicture_DeviceType,
+ kGPU_DeviceType
+ };
+ /**
+ * SampleApp ports can subclass this manager class if they want to:
+ * * filter the types of devices supported
+ * * customize plugging of SkDevice objects into an SkCanvas
+ * * customize publishing the results of draw to the OS window
+ * * manage GrContext / GrRenderTarget lifetimes
+ */
+ class DeviceManager : public SkRefCnt {
+ public:
+ // called at end of SampleWindow cons
+ virtual void init(SampleWindow* win) = 0;
+
+ // called when selecting a new device type
+ // can disallow a device type by returning false.
+ virtual bool supportsDeviceType(DeviceType dType) = 0;
+
+ // called before drawing. should install correct device
+ // type on the canvas. Will skip drawing if returns false.
+ virtual bool prepareCanvas(DeviceType dType,
+ SkCanvas* canvas,
+ SampleWindow* win) = 0;
+
+ // called after drawing, should get the results onto the
+ // screen.
+ virtual void publishCanvas(DeviceType dType,
+ SkCanvas* canvas,
+ SampleWindow* win) = 0;
+
+ // called when window changes size, guaranteed to be called
+ // at least once before first draw (after init)
+ virtual void windowSizeChanged(SampleWindow* win) = 0;
+
+ // return the GrContext backing gpu devices
+ virtual GrContext* getGrContext() = 0;
+ };
+
+ SampleWindow(void* hwnd, int argc, char** argv, DeviceManager*);
virtual ~SampleWindow();
virtual void draw(SkCanvas* canvas);
@@ -52,9 +93,9 @@
void toggleRendering();
void toggleSlideshow();
void toggleFPS();
- bool drawsToHardware() { return fCanvasType == kGPU_CanvasType; }
- bool setGrContext(GrContext*);
- GrContext* getGrContext();
+
+ GrContext* getGrContext() const { return fDevManager->getGrContext(); }
+
void setZoomCenter(float x, float y);
void changeZoomLevel(float delta);
bool nextSample();
@@ -87,23 +128,19 @@
virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
private:
+ class DefaultDeviceManager;
+
int fCurrIndex;
SkPicture* fPicture;
- GrContext* fGrContext;
- GrRenderTarget* fGrRenderTarget;
SkPath fClipPath;
SkTouchGesture fGesture;
SkScalar fZoomLevel;
SkScalar fZoomScale;
- enum CanvasType {
- kRaster_CanvasType,
- kPicture_CanvasType,
- kGPU_CanvasType
- };
- CanvasType fCanvasType;
+ DeviceType fDeviceType;
+ DeviceManager* fDevManager;
bool fSaveToPdf;
SkCanvas* fPdfCanvas;
@@ -137,8 +174,6 @@
int fScrollTestX, fScrollTestY;
SkScalar fZoomCenterX, fZoomCenterY;
- bool make3DReady();
-
void loadView(SkView*);
void updateTitle();
@@ -150,8 +185,6 @@
void postAnimatingEvent();
- static CanvasType cycle_canvastype(CanvasType);
-
typedef SkOSWindow INHERITED;
};