aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/views/SkOSWindow_Android.h12
-rw-r--r--include/views/SkOSWindow_Mac.h12
-rw-r--r--include/views/SkOSWindow_Unix.h12
-rw-r--r--include/views/SkOSWindow_Win.h38
-rwxr-xr-xinclude/views/SkOSWindow_iOS.h12
-rw-r--r--samplecode/SampleApp.cpp319
-rw-r--r--samplecode/SampleApp.h16
-rw-r--r--src/views/mac/SkOSWindow_Mac.cpp6
-rw-r--r--src/views/unix/SkOSWindow_Unix.cpp6
-rw-r--r--src/views/win/SkOSWindow_win.cpp1346
10 files changed, 963 insertions, 816 deletions
diff --git a/include/views/SkOSWindow_Android.h b/include/views/SkOSWindow_Android.h
index bdce5d0d4f..5818a0af69 100644
--- a/include/views/SkOSWindow_Android.h
+++ b/include/views/SkOSWindow_Android.h
@@ -18,9 +18,15 @@ class SkOSWindow : public SkWindow {
public:
SkOSWindow(void*) {}
~SkOSWindow() {}
- bool attachGL() { return true; }
- void detachGL() {}
- void presentGL() {}
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ bool attach(SkBackEndTypes /* attachType */) { return true; }
+ void detach() {}
+ void present() {}
virtual void onPDFSaved(const char title[], const char desc[],
const char path[]);
diff --git a/include/views/SkOSWindow_Mac.h b/include/views/SkOSWindow_Mac.h
index b09f1dd5e4..01fa29f334 100644
--- a/include/views/SkOSWindow_Mac.h
+++ b/include/views/SkOSWindow_Mac.h
@@ -19,9 +19,15 @@ public:
virtual bool onDispatchClick(int x, int y, Click::State state,
void* owner);
- void detachGL();
- bool attachGL();
- void presentGL();
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ void detach();
+ bool attach(SkBackEndTypes attachType);
+ void present();
protected:
// overrides from SkEventSink
diff --git a/include/views/SkOSWindow_Unix.h b/include/views/SkOSWindow_Unix.h
index 3b71af8330..40059bf8d4 100644
--- a/include/views/SkOSWindow_Unix.h
+++ b/include/views/SkOSWindow_Unix.h
@@ -34,9 +34,15 @@ public:
void* getUnixWindow() const { return (void*)&fUnixWindow; }
void loop();
void post_linuxevent();
- bool attachGL();
- void detachGL();
- void presentGL();
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ bool attach(SkBackEndTypes attachType);
+ void detach();
+ void present();
//static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h
index c857e7a6cd..2663c8c75d 100644
--- a/include/views/SkOSWindow_Win.h
+++ b/include/views/SkOSWindow_Win.h
@@ -26,20 +26,19 @@ public:
void updateSize();
static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
-
- bool attachGL();
- void detachGL();
- void presentGL();
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
#if SK_ANGLE
- bool attachANGLE();
- void detachANGLE();
- void presentANGLE();
+ kANGLE_BackEndType,
#endif
+ kD3D9_BackEndType
+ };
- bool attachD3D9();
- void detachD3D9();
- void presentD3D9();
+ bool attach(SkBackEndTypes attachType);
+ void detach();
+ void present();
void* d3d9Device() { return fD3D9Device; }
@@ -73,13 +72,26 @@ private:
EGLSurface fSurface;
#endif
- bool fGLAttached;
-
void* fD3D9Device;
- bool fD3D9Attached;
HMENU fMBar;
+ SkBackEndTypes fAttached;
+
+ bool attachGL();
+ void detachGL();
+ void presentGL();
+
+#if SK_ANGLE
+ bool attachANGLE();
+ void detachANGLE();
+ void presentANGLE();
+#endif
+
+ bool attachD3D9();
+ void detachD3D9();
+ void presentD3D9();
+
typedef SkWindow INHERITED;
};
diff --git a/include/views/SkOSWindow_iOS.h b/include/views/SkOSWindow_iOS.h
index ff284843bb..34ce421778 100755
--- a/include/views/SkOSWindow_iOS.h
+++ b/include/views/SkOSWindow_iOS.h
@@ -18,9 +18,15 @@ public:
virtual bool onDispatchClick(int x, int y, Click::State state,
void* owner);
- void detachGL();
- bool attachGL();
- void presentGL();
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ void detach();
+ bool attach(SkBackEndTypes attachType);
+ void present();
protected:
// overrides from SkEventSink
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index dc522b603a..92c9e6c984 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -53,7 +53,12 @@ SkTDArray<char> gTempDataStore;
#endif
#define USE_ARROWS_FOR_ZOOM true
-//#define DEFAULT_TO_GPU
+
+#if SK_ANGLE
+//#define DEFAULT_TO_ANGLE 1
+#else
+//#define DEFAULT_TO_GPU 1
+#endif
extern SkView* create_overview(int, const SkViewFactory*[]);
extern bool is_overview(SkView* view);
@@ -131,113 +136,129 @@ class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
public:
DefaultDeviceManager()
-#if SK_ANGLE
- : fUseAltContext(false)
-#endif
- {
- fGrRenderTarget = NULL;
- fGrContext = NULL;
- fGL = NULL;
- fNullGrContext = NULL;
- fNullGrRenderTarget = NULL;
+ : fCurContext(NULL)
+ , fCurIntf(NULL)
+ , fCurRenderTarget(NULL)
+ , fBackend(kNone_BackEndType) {
}
virtual ~DefaultDeviceManager() {
- SkSafeUnref(fGrRenderTarget);
- SkSafeUnref(fGrContext);
- SkSafeUnref(fGL);
- SkSafeUnref(fNullGrContext);
- SkSafeUnref(fNullGrRenderTarget);
+ SkSafeUnref(fCurContext);
+ SkSafeUnref(fCurIntf);
+ SkSafeUnref(fCurRenderTarget);
}
- virtual void init(SampleWindow* win, bool useAltContext) {
-#if SK_ANGLE
- fUseAltContext = useAltContext;
-#endif
- bool result;
+ virtual void setUpBackend(SampleWindow* win) {
+ SkASSERT(kNone_BackEndType == fBackend);
+
+ fBackend = kNone_BackEndType;
+ switch (win->getDeviceType()) {
+ case kRaster_DeviceType:
+ // fallthrough
+ case kPicture_DeviceType:
+ // fallthrough
+ case kGPU_DeviceType:
+ // fallthrough
+ case kNullGPU_DeviceType:
+ // all these guys use the native backend
+ fBackend = kNativeGL_BackEndType;
+ break;
#if SK_ANGLE
- if (useAltContext) {
- result = win->attachANGLE();
- } else
+ case kANGLE_DeviceType:
+ // ANGLE is really the only odd man out
+ fBackend = kANGLE_BackEndType;
+ break;
#endif
- {
- result = win->attachGL();
+ default:
+ SkASSERT(false);
+ break;
}
+
+ bool result = win->attach(fBackend);
if (!result) {
SkDebugf("Failed to initialize GL");
+ return;
}
- if (NULL == fGL) {
+
+ SkASSERT(NULL == fCurIntf);
+ switch (win->getDeviceType()) {
+ case kRaster_DeviceType:
+ // fallthrough
+ case kPicture_DeviceType:
+ // fallthrough
+ case kGPU_DeviceType:
+ // all these guys use the native interface
+ fCurIntf = GrGLCreateNativeInterface();
+ break;
#if SK_ANGLE
- if (useAltContext) {
- fGL = GrGLCreateANGLEInterface();
- } else
+ case kANGLE_DeviceType:
+ fCurIntf = GrGLCreateANGLEInterface();
+ break;
#endif
- {
- fGL = GrGLCreateNativeInterface();
- }
- GrAssert(NULL == fGrContext);
- fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
- (GrPlatform3DContext) fGL);
+ case kNullGPU_DeviceType:
+ fCurIntf = GrGLCreateNullInterface();
+ break;
+ default:
+ SkASSERT(false);
+ break;
}
- if (NULL == fGrContext || NULL == fGL) {
- SkSafeUnref(fGrContext);
- SkSafeUnref(fGL);
+
+ SkASSERT(NULL == fCurContext);
+ fCurContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
+ (GrPlatform3DContext) fCurIntf);
+
+ if (NULL == fCurContext || NULL == fCurIntf) {
+ // We need some context and interface to see results
+ SkSafeUnref(fCurContext);
+ SkSafeUnref(fCurIntf);
SkDebugf("Failed to setup 3D");
-#if SK_ANGLE
- if (useAltContext) {
- win->detachANGLE();
- } else
-#endif
- {
- win->detachGL();
- }
- }
- if (NULL == fNullGrContext) {
- const GrGLInterface* nullGL = GrGLCreateNullInterface();
- fNullGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
- (GrPlatform3DContext) nullGL);
- nullGL->unref();
+
+ win->detach();
}
+
+ // call windowSizeChanged to create the render target
+ windowSizeChanged(win);
}
- 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;
- case kNullGPU_DeviceType:
- return NULL != fNullGrContext && NULL != fNullGrRenderTarget;
- default:
- return false;
- }
+ virtual void tearDownBackend(SampleWindow *win) {
+ win->detach();
+ fBackend = kNone_BackEndType;
+
+ SkSafeUnref(fCurContext);
+ fCurContext = NULL;
+
+ SkSafeUnref(fCurIntf);
+ fCurIntf = NULL;
+
+ SkSafeUnref(fCurRenderTarget);
+ fCurRenderTarget = NULL;
}
virtual bool prepareCanvas(SampleWindow::DeviceType dType,
SkCanvas* canvas,
SampleWindow* win) {
switch (dType) {
- case kGPU_DeviceType:
- if (fGrContext) {
- canvas->setDevice(new SkGpuDevice(fGrContext,
- fGrRenderTarget))->unref();
- } else {
- return false;
- }
+ case kRaster_DeviceType:
+ // fallthrough
+ case kPicture_DeviceType:
+ // fallthrough
+#if SK_ANGLE
+ case kANGLE_DeviceType:
+#endif
break;
+ case kGPU_DeviceType:
case kNullGPU_DeviceType:
- if (fNullGrContext) {
- canvas->setDevice(new SkGpuDevice(fNullGrContext,
- fNullGrRenderTarget))->unref();
+ if (fCurContext) {
+ canvas->setDevice(new SkGpuDevice(fCurContext,
+ fCurRenderTarget))->unref();
} else {
return false;
}
break;
- case kRaster_DeviceType:
- case kPicture_DeviceType:
- break;
+ default:
+ SkASSERT(false);
+ return false;
}
return true;
}
@@ -245,85 +266,55 @@ public:
virtual void publishCanvas(SampleWindow::DeviceType dType,
SkCanvas* canvas,
SampleWindow* win) {
- if (fGrContext) {
+ if (fCurContext) {
// in case we have queued drawing calls
- fGrContext->flush();
- if (NULL != fNullGrContext) {
- fNullGrContext->flush();
- }
- if (dType != kGPU_DeviceType &&
- dType != kNullGPU_DeviceType) {
+ fCurContext->flush();
+
+ if (kGPU_DeviceType != dType && kNullGPU_DeviceType != dType) {
// need to send the raster bits to the (gpu) window
- fGrContext->setRenderTarget(fGrRenderTarget);
+ fCurContext->setRenderTarget(fCurRenderTarget);
const SkBitmap& bm = win->getBitmap();
- fGrRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
+ fCurRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
kSkia8888_PM_GrPixelConfig,
bm.getPixels(),
bm.rowBytes());
}
}
-#if SK_ANGLE
- if (fUseAltContext) {
- win->presentANGLE();
- } else
-#endif
- {
- win->presentGL();
- }
+
+ win->present();
}
virtual void windowSizeChanged(SampleWindow* win) {
- if (fGrContext) {
-#if SK_ANGLE
- if (fUseAltContext) {
- win->attachANGLE();
- } else
-#endif
- {
- win->attachGL();
- }
+
+ if (fCurContext) {
+ win->attach(fBackend);
GrPlatformRenderTargetDesc desc;
desc.fWidth = SkScalarRound(win->width());
desc.fHeight = SkScalarRound(win->height());
desc.fConfig = kSkia8888_PM_GrPixelConfig;
- GR_GL_GetIntegerv(fGL, GR_GL_SAMPLES, &desc.fSampleCnt);
- GR_GL_GetIntegerv(fGL, GR_GL_STENCIL_BITS, &desc.fStencilBits);
+ GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt);
+ GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits);
GrGLint buffer;
- GR_GL_GetIntegerv(fGL, GR_GL_FRAMEBUFFER_BINDING, &buffer);
+ GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer);
desc.fRenderTargetHandle = buffer;
- SkSafeUnref(fGrRenderTarget);
- fGrRenderTarget = fGrContext->createPlatformRenderTarget(desc);
- }
- if (NULL != fNullGrContext) {
- GrPlatformRenderTargetDesc desc;
- desc.fWidth = SkScalarRound(win->width());
- desc.fHeight = SkScalarRound(win->height());
- desc.fConfig = kSkia8888_PM_GrPixelConfig;
- desc.fStencilBits = 8;
- desc.fSampleCnt = 0;
- desc.fRenderTargetHandle = 0;
- fNullGrRenderTarget = fNullGrContext->createPlatformRenderTarget(desc);
+ SkSafeUnref(fCurRenderTarget);
+ fCurRenderTarget = fCurContext->createPlatformRenderTarget(desc);
}
}
- virtual GrContext* getGrContext(SampleWindow::DeviceType dType) {
- if (kNullGPU_DeviceType == dType) {
- return fNullGrContext;
- } else {
- return fGrContext;
- }
+ virtual GrContext* getGrContext() {
+ return fCurContext;
}
private:
-#if SK_ANGLE
- bool fUseAltContext;
-#endif
- GrContext* fGrContext;
- const GrGLInterface* fGL;
- GrRenderTarget* fGrRenderTarget;
- GrContext* fNullGrContext;
- GrRenderTarget* fNullGrRenderTarget;
+ GrContext* fCurContext;
+ const GrGLInterface* fCurIntf;
+ GrRenderTarget* fCurRenderTarget;
+
+ SkOSWindow::SkBackEndTypes fBackend;
+
+ typedef SampleWindow::DeviceManager INHERITED;
};
///////////////
@@ -644,6 +635,9 @@ static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType
static const SampleWindow::DeviceType gCT[] = {
SampleWindow::kPicture_DeviceType,
SampleWindow::kGPU_DeviceType,
+#if SK_ANGLE
+ SampleWindow::kANGLE_DeviceType,
+#endif
SampleWindow::kRaster_DeviceType, // skip the null gpu device in normal cycling
SampleWindow::kRaster_DeviceType
};
@@ -669,7 +663,6 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
const char* resourcePath = NULL;
fCurrIndex = -1;
- bool useAltContext = false;
const char* const commandName = argv[0];
char* const* stop = argv + argc;
@@ -688,12 +681,6 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
}
}
}
-#if SK_ANGLE
- else if (strcmp(*argv, "--angle") == 0) {
- argv++;
- useAltContext = true;
- }
-#endif
else {
usage(commandName);
}
@@ -720,11 +707,15 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
fPicture = NULL;
-#ifdef DEFAULT_TO_GPU
- fDeviceType = kGPU_DeviceType;
-#else
fDeviceType = kRaster_DeviceType;
+
+#if DEFAULT_TO_GPU
+ fDeviceType = kGPU_DeviceType;
+#endif
+#if SK_ANGLE && DEFAULT_TO_ANGLE
+ fDeviceType = kANGLE_DeviceType;
#endif
+
fUseClip = false;
fNClip = false;
fAnimating = false;
@@ -764,7 +755,11 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
int itemID;
itemID =fAppMenu.appendList("Device Type", "Device Type", sinkID, 0,
- "Raster", "Picture", "OpenGL", NULL);
+ "Raster", "Picture", "OpenGL",
+#if SK_ANGLE
+ "ANGLE",
+#endif
+ NULL);
fAppMenu.assignKeyEquivalentToItem(itemID, 'd');
itemID = fAppMenu.appendTriState("AA", "AA", sinkID, fAAState);
fAppMenu.assignKeyEquivalentToItem(itemID, 'b');
@@ -825,7 +820,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
devManager->ref();
fDevManager = devManager;
}
- fDevManager->init(this, useAltContext);
+ fDevManager->setUpBackend(this);
// If another constructor set our dimensions, ensure that our
// onSizeChange gets called.
@@ -1133,7 +1128,12 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
} else {
switch (fDeviceType) {
case kRaster_DeviceType:
+ // fallthrough
case kGPU_DeviceType:
+ // fallthrough
+#if SK_ANGLE
+ case kANGLE_DeviceType:
+#endif
canvas = this->INHERITED::beforeChildren(canvas);
break;
case kPicture_DeviceType:
@@ -1142,6 +1142,9 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
break;
case kNullGPU_DeviceType:
break;
+ default:
+ SkASSERT(false);
+ break;
}
}
@@ -1628,11 +1631,9 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
this->updateTitle();
return true;
case '\\':
- if (fDevManager->supportsDeviceType(kNullGPU_DeviceType)) {
- fDeviceType= kNullGPU_DeviceType;
- this->inval(NULL);
- this->updateTitle();
- }
+ this->setDeviceType(kNullGPU_DeviceType);
+ this->inval(NULL);
+ this->updateTitle();
return true;
case 'p':
{
@@ -1663,8 +1664,15 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
}
void SampleWindow::setDeviceType(DeviceType type) {
- if (type != fDeviceType && fDevManager->supportsDeviceType(fDeviceType))
- fDeviceType = type;
+ if (type == fDeviceType)
+ return;
+
+ fDevManager->tearDownBackend(this);
+
+ fDeviceType = type;
+
+ fDevManager->setUpBackend(this);
+
this->updateTitle();
this->inval(NULL);
}
@@ -1676,11 +1684,7 @@ void SampleWindow::toggleSlideshow() {
}
void SampleWindow::toggleRendering() {
- DeviceType origDevType = fDeviceType;
- do {
- fDeviceType = cycle_devicetype(fDeviceType);
- } while (origDevType != fDeviceType &&
- !fDevManager->supportsDeviceType(fDeviceType));
+ this->setDeviceType(cycle_devicetype(fDeviceType));
this->updateTitle();
this->inval(NULL);
}
@@ -1857,6 +1861,9 @@ static const char* gDeviceTypePrefix[] = {
"raster: ",
"picture: ",
"opengl: ",
+#if SK_ANGLE
+ "angle: ",
+#endif
"null-gl: "
};
diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h
index 94f663feb0..ba404da515 100644
--- a/samplecode/SampleApp.h
+++ b/samplecode/SampleApp.h
@@ -36,6 +36,9 @@ public:
kRaster_DeviceType,
kPicture_DeviceType,
kGPU_DeviceType,
+#if SK_ANGLE
+ kANGLE_DeviceType,
+#endif
kNullGPU_DeviceType
};
/**
@@ -47,12 +50,9 @@ public:
*/
class DeviceManager : public SkRefCnt {
public:
- // called at end of SampleWindow cons
- virtual void init(SampleWindow* win, bool useAltContext) = 0;
+ virtual void setUpBackend(SampleWindow* win) = 0;
- // called when selecting a new device type
- // can disallow a device type by returning false.
- virtual bool supportsDeviceType(DeviceType dType) = 0;
+ virtual void tearDownBackend(SampleWindow* win) = 0;
// called before drawing. should install correct device
// type on the canvas. Will skip drawing if returns false.
@@ -71,7 +71,7 @@ public:
virtual void windowSizeChanged(SampleWindow* win) = 0;
// return the GrContext backing gpu devices
- virtual GrContext* getGrContext(DeviceType dType) = 0;
+ virtual GrContext* getGrContext() = 0;
};
SampleWindow(void* hwnd, int argc, char** argv, DeviceManager*);
@@ -85,7 +85,7 @@ public:
void toggleFPS();
void showOverview();
- GrContext* getGrContext() const { return fDevManager->getGrContext(fDeviceType); }
+ GrContext* getGrContext() const { return fDevManager->getGrContext(); }
void setZoomCenter(float x, float y);
void changeZoomLevel(float delta);
@@ -100,6 +100,8 @@ public:
SkData* getPDFData() { return fPDFData; }
void postInvalDelay();
+ DeviceType getDeviceType() const { return fDeviceType; }
+
protected:
virtual void onDraw(SkCanvas* canvas);
virtual bool onHandleKey(SkKey key);
diff --git a/src/views/mac/SkOSWindow_Mac.cpp b/src/views/mac/SkOSWindow_Mac.cpp
index d41c9a75de..63106f088d 100644
--- a/src/views/mac/SkOSWindow_Mac.cpp
+++ b/src/views/mac/SkOSWindow_Mac.cpp
@@ -500,7 +500,7 @@ AGLContext create_gl(WindowRef wref)
return ctx;
}
-bool SkOSWindow::attachGL()
+bool SkOSWindow::attach(SkBackEndTypes /* attachType */)
{
if (NULL == fAGLCtx) {
fAGLCtx = create_gl((WindowRef)fHWND);
@@ -532,11 +532,11 @@ bool SkOSWindow::attachGL()
return success;
}
-void SkOSWindow::detachGL() {
+void SkOSWindow::detach() {
aglSetWindowRef((AGLContext)fAGLCtx, NULL);
}
-void SkOSWindow::presentGL() {
+void SkOSWindow::present() {
aglSwapBuffers((AGLContext)fAGLCtx);
}
diff --git a/src/views/unix/SkOSWindow_Unix.cpp b/src/views/unix/SkOSWindow_Unix.cpp
index b4b0f17cd6..01bc21c89e 100644
--- a/src/views/unix/SkOSWindow_Unix.cpp
+++ b/src/views/unix/SkOSWindow_Unix.cpp
@@ -170,7 +170,7 @@ void SkOSWindow::mapWindowAndWait()
}
-bool SkOSWindow::attachGL()
+bool SkOSWindow::attach(SkBackEndTypes /* attachType */)
{
if (fGLAttached) return true;
Display* dsp = fUnixWindow.fDisplay;
@@ -194,7 +194,7 @@ bool SkOSWindow::attachGL()
return true;
}
-void SkOSWindow::detachGL()
+void SkOSWindow::detach()
{
if (!fUnixWindow.fDisplay || !fGLAttached) return;
fGLAttached = false;
@@ -204,7 +204,7 @@ void SkOSWindow::detachGL()
this->inval(NULL);
}
-void SkOSWindow::presentGL()
+void SkOSWindow::present()
{
if (fUnixWindow.fDisplay && fGLAttached) {
glXSwapBuffers(fUnixWindow.fDisplay, fUnixWindow.fWin);
diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp
index 75f6de65c7..d3e49c9171 100644
--- a/src/views/win/SkOSWindow_win.cpp
+++ b/src/views/win/SkOSWindow_win.cpp
@@ -1,622 +1,724 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkTypes.h"
-
-#if defined(SK_BUILD_FOR_WIN)
-
-#include <GL/gl.h>
-#include <d3d9.h>
-#include <WindowsX.h>
-#include "SkWGL.h"
-#include "SkWindow.h"
-#include "SkCanvas.h"
-#include "SkOSMenu.h"
-#include "SkTime.h"
-#include "SkUtils.h"
-
-#include "SkGraphics.h"
-
-#if SK_ANGLE
-#include "gl/GrGLInterface.h"
-
-#include "GLES2/gl2.h"
-#endif
-
-#define INVALIDATE_DELAY_MS 200
-
-static SkOSWindow* gCurrOSWin;
-static HWND gEventTarget;
-
-#define WM_EVENT_CALLBACK (WM_USER+0)
-
-void post_skwinevent()
-{
- PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
-}
-
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd)
-#if SK_ANGLE
- , fDisplay(EGL_NO_DISPLAY)
- , fContext(EGL_NO_CONTEXT)
- , fSurface(EGL_NO_SURFACE)
-#endif
- , fHGLRC(NULL),
- fGLAttached(false),
- fD3D9Device(NULL),
- fD3D9Attached(FALSE) {
- gEventTarget = (HWND)hWnd;
-}
-
-SkOSWindow::~SkOSWindow() {
- if (NULL != fD3D9Device) {
- ((IDirect3DDevice9*)fD3D9Device)->Release();
- }
- if (NULL != fHGLRC) {
- wglDeleteContext((HGLRC)fHGLRC);
- }
-#if SK_ANGLE
- if (EGL_NO_DISPLAY != fDisplay) {
- eglDestroyContext(fDisplay, fContext);
- }
-#endif
-}
-
-static SkKey winToskKey(WPARAM vk) {
- static const struct {
- WPARAM fVK;
- SkKey fKey;
- } gPair[] = {
- { VK_BACK, kBack_SkKey },
- { VK_CLEAR, kBack_SkKey },
- { VK_RETURN, kOK_SkKey },
- { VK_UP, kUp_SkKey },
- { VK_DOWN, kDown_SkKey },
- { VK_LEFT, kLeft_SkKey },
- { VK_RIGHT, kRight_SkKey }
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fVK == vk) {
- return gPair[i].fKey;
- }
- }
- return kNONE_SkKey;
-}
-
-bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
- switch (message) {
- case WM_KEYDOWN: {
- SkKey key = winToskKey(wParam);
- if (kNONE_SkKey != key) {
- this->handleKey(key);
- return true;
- }
- } break;
- case WM_KEYUP: {
- SkKey key = winToskKey(wParam);
- if (kNONE_SkKey != key) {
- this->handleKeyUp(key);
- return true;
- }
- } break;
- case WM_UNICHAR:
- this->handleChar(wParam);
- return true;
- case WM_CHAR: {
- this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
- return true;
- } break;
- case WM_SIZE:
- this->resize(lParam & 0xFFFF, lParam >> 16);
- break;
- case WM_PAINT: {
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(hWnd, &ps);
- this->doPaint(hdc);
- EndPaint(hWnd, &ps);
- return true;
- } break;
-
- case WM_TIMER: {
- RECT* rect = (RECT*)wParam;
- InvalidateRect(hWnd, rect, FALSE);
- KillTimer(hWnd, (UINT_PTR)rect);
- delete rect;
- return true;
- } break;
-
- case WM_LBUTTONDOWN:
- this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
- return true;
-
- case WM_MOUSEMOVE:
- this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
- return true;
-
- case WM_LBUTTONUP:
- this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
- return true;
-
- case WM_EVENT_CALLBACK:
- if (SkEvent::ProcessEvent()) {
- post_skwinevent();
- }
- return true;
- }
- return false;
-}
-
-void SkOSWindow::doPaint(void* ctx) {
- this->update(NULL);
-
- if (!fGLAttached && !fD3D9Attached)
- {
- HDC hdc = (HDC)ctx;
- const SkBitmap& bitmap = this->getBitmap();
-
- BITMAPINFO bmi;
- memset(&bmi, 0, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = bitmap.width();
- bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = 0;
-
- //
- // Do the SetDIBitsToDevice.
- //
- // TODO(wjmaclean):
- // Fix this call to handle SkBitmaps that have rowBytes != width,
- // i.e. may have padding at the end of lines. The SkASSERT below
- // may be ignored by builds, and the only obviously safe option
- // seems to be to copy the bitmap to a temporary (contiguous)
- // buffer before passing to SetDIBitsToDevice().
- SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
- bitmap.lockPixels();
- int iRet = SetDIBitsToDevice(hdc,
- 0, 0,
- bitmap.width(), bitmap.height(),
- 0, 0,
- 0, bitmap.height(),
- bitmap.getPixels(),
- &bmi,
- DIB_RGB_COLORS);
- bitmap.unlockPixels();
- }
-}
-
-#if 0
-void SkOSWindow::updateSize()
-{
- RECT r;
- GetWindowRect((HWND)this->getHWND(), &r);
- this->resize(r.right - r.left, r.bottom - r.top);
-}
-#endif
-
-void SkOSWindow::onHandleInval(const SkIRect& r) {
- RECT* rect = new RECT;
- rect->left = r.fLeft;
- rect->top = r.fTop;
- rect->right = r.fRight;
- rect->bottom = r.fBottom;
- SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
-}
-
-void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
-{
-}
-
-void SkOSWindow::onSetTitle(const char title[]){
- SetWindowTextA((HWND)fHWND, title);
-}
-
-enum {
- SK_MacReturnKey = 36,
- SK_MacDeleteKey = 51,
- SK_MacEndKey = 119,
- SK_MacLeftKey = 123,
- SK_MacRightKey = 124,
- SK_MacDownKey = 125,
- SK_MacUpKey = 126,
-
- SK_Mac0Key = 0x52,
- SK_Mac1Key = 0x53,
- SK_Mac2Key = 0x54,
- SK_Mac3Key = 0x55,
- SK_Mac4Key = 0x56,
- SK_Mac5Key = 0x57,
- SK_Mac6Key = 0x58,
- SK_Mac7Key = 0x59,
- SK_Mac8Key = 0x5b,
- SK_Mac9Key = 0x5c
-};
-
-static SkKey raw2key(uint32_t raw)
-{
- static const struct {
- uint32_t fRaw;
- SkKey fKey;
- } gKeys[] = {
- { SK_MacUpKey, kUp_SkKey },
- { SK_MacDownKey, kDown_SkKey },
- { SK_MacLeftKey, kLeft_SkKey },
- { SK_MacRightKey, kRight_SkKey },
- { SK_MacReturnKey, kOK_SkKey },
- { SK_MacDeleteKey, kBack_SkKey },
- { SK_MacEndKey, kEnd_SkKey },
- { SK_Mac0Key, k0_SkKey },
- { SK_Mac1Key, k1_SkKey },
- { SK_Mac2Key, k2_SkKey },
- { SK_Mac3Key, k3_SkKey },
- { SK_Mac4Key, k4_SkKey },
- { SK_Mac5Key, k5_SkKey },
- { SK_Mac6Key, k6_SkKey },
- { SK_Mac7Key, k7_SkKey },
- { SK_Mac8Key, k8_SkKey },
- { SK_Mac9Key, k9_SkKey }
- };
-
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
- if (gKeys[i].fRaw == raw)
- return gKeys[i].fKey;
- return kNONE_SkKey;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void SkEvent::SignalNonEmptyQueue()
-{
- post_skwinevent();
- //SkDebugf("signal nonempty\n");
-}
-
-static UINT_PTR gTimer;
-
-VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
-{
- SkEvent::ServiceQueueTimer();
- //SkDebugf("timer task fired\n");
-}
-
-void SkEvent::SignalQueueTimer(SkMSec delay)
-{
- if (gTimer)
- {
- KillTimer(NULL, gTimer);
- gTimer = NULL;
- }
- if (delay)
- {
- gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
- //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
- }
-}
-
-
-#define USE_MSAA 0
-
-HGLRC create_gl(HWND hwnd) {
- HDC dc = GetDC(hwnd);
- SkWGLExtensions extensions;
- if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
- return NULL;
- }
-
- HDC prevDC = wglGetCurrentDC();
- HGLRC prevGLRC = wglGetCurrentContext();
- PIXELFORMATDESCRIPTOR pfd;
-
- int format = 0;
-
- GLint iattrs[] = {
- SK_WGL_DRAW_TO_WINDOW, TRUE,
- SK_WGL_DOUBLE_BUFFER, TRUE,
- SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,
- SK_WGL_SUPPORT_OPENGL, TRUE,
- SK_WGL_COLOR_BITS, 24,
- SK_WGL_ALPHA_BITS, 8,
- SK_WGL_STENCIL_BITS, 8,
-
- // these must be kept last
- SK_WGL_SAMPLE_BUFFERS, TRUE,
- SK_WGL_SAMPLES, 0,
- 0,0
- };
- static const int kSampleBuffersValueIdx = SK_ARRAY_COUNT(iattrs) - 5;
- static const int kSamplesValueIdx = SK_ARRAY_COUNT(iattrs) - 3;
- if (USE_MSAA && extensions.hasExtension(dc, "WGL_ARB_multisample")) {
- for (int samples = 16; samples > 1; --samples) {
-
- iattrs[kSamplesValueIdx] = samples;
- GLfloat fattrs[] = {0,0};
- GLuint num;
- int formats[64];
- extensions.choosePixelFormat(dc, iattrs, fattrs, 64, formats, &num);
- num = min(num,64);
- for (GLuint i = 0; i < num; ++i) {
- DescribePixelFormat(dc, formats[i], sizeof(pfd), &pfd);
- if (SetPixelFormat(dc, formats[i], &pfd)) {
- format = formats[i];
- break;
- }
- }
- }
- }
- if (0 == format) {
- iattrs[kSampleBuffersValueIdx-1] = iattrs[kSampleBuffersValueIdx] = 0;
- iattrs[kSamplesValueIdx-1] = iattrs[kSamplesValueIdx] = 0;
- GLfloat fattrs[] = {0,0};
- GLuint num;
- extensions.choosePixelFormat(dc, iattrs, fattrs, 1, &format, &num);
- DescribePixelFormat(dc, format, sizeof(pfd), &pfd);
- BOOL set = SetPixelFormat(dc, format, &pfd);
- SkASSERT(TRUE == set);
- }
-
- HGLRC glrc = wglCreateContext(dc);
- SkASSERT(glrc);
-
- wglMakeCurrent(prevDC, prevGLRC);
- return glrc;
-}
-
-bool SkOSWindow::attachGL() {
- if (NULL == fHGLRC) {
- fHGLRC = create_gl((HWND)fHWND);
- if (NULL == fHGLRC) {
- return false;
- }
- glClearStencil(0);
- glClearColor(0, 0, 0, 0);
- glStencilMask(0xffffffff);
- glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
- }
- if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
- glViewport(0, 0, SkScalarRound(this->width()),
- SkScalarRound(this->height()));
- fGLAttached = true;
- return true;
- }
- return false;
-}
-
-void SkOSWindow::detachGL() {
- wglMakeCurrent(GetDC((HWND)fHWND), 0);
- fGLAttached = false;
-}
-
-void SkOSWindow::presentGL() {
- glFlush();
- SwapBuffers(GetDC((HWND)fHWND));
-}
-
-#if SK_ANGLE
-bool create_ANGLE(EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
- EGLContext* eglContext, EGLSurface* eglSurface) {
- EGLint contextAttribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE, EGL_NONE
- };
- EGLint configAttribList[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 8,
- EGL_STENCIL_SIZE, 8,
- EGL_NONE
- };
- EGLint surfaceAttribList[] = {
- EGL_NONE, EGL_NONE
- };
-
- EGLDisplay display = eglGetDisplay(GetDC(hWnd));
- if (display == EGL_NO_DISPLAY ) {
- return false;
- }
-
- // Initialize EGL
- EGLint majorVersion, minorVersion;
- if (!eglInitialize(display, &majorVersion, &minorVersion)) {
- return false;
- }
-
- EGLint numConfigs;
- if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {
- return false;
- }
-
- // Choose config
- EGLConfig config;
- if (!eglChooseConfig(display, configAttribList,
- &config, 1, &numConfigs)) {
- return false;
- }
-
- // Create a surface
- EGLSurface surface = eglCreateWindowSurface(display, config,
- (EGLNativeWindowType)hWnd,
- surfaceAttribList);
- if (surface == EGL_NO_SURFACE) {
- return false;
- }
-
- // Create a GL context
- EGLContext context = eglCreateContext(display, config,
- EGL_NO_CONTEXT,
- contextAttribs );
- if (context == EGL_NO_CONTEXT ) {
- return false;
- }
-
- // Make the context current
- if (!eglMakeCurrent(display, surface, surface, context)) {
- return false;
- }
-
- *eglDisplay = display;
- *eglContext = context;
- *eglSurface = surface;
- return true;
-}
-
-bool SkOSWindow::attachANGLE() {
- if (EGL_NO_DISPLAY == fDisplay) {
- bool bResult = create_ANGLE((HWND)fHWND, &fDisplay, &fContext, &fSurface);
- if (false == bResult) {
- return false;
- }
- const GrGLInterface* intf = GrGLCreateANGLEInterface();
-
- if (intf) {
- GR_GL_CALL(intf, ClearStencil(0));
- GR_GL_CALL(intf, ClearColor(0, 0, 0, 0));
- GR_GL_CALL(intf, StencilMask(0xffffffff));
- GR_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
- }
- }
- if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
- const GrGLInterface* intf = GrGLCreateANGLEInterface();
-
- if (intf ) {
- GR_GL_CALL(intf, Viewport(0, 0, SkScalarRound(this->width()),
- SkScalarRound(this->height())));
- }
- fGLAttached = true;
- return true;
- }
- return false;
-}
-
-void SkOSWindow::detachANGLE() {
- eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
- fGLAttached = false;
-}
-
-void SkOSWindow::presentANGLE() {
- const GrGLInterface* intf = GrGLCreateANGLEInterface();
-
- if (intf) {
- GR_GL_CALL(intf, Flush());
- }
- eglSwapBuffers(fDisplay, fSurface);
-}
-#endif
-
-IDirect3DDevice9* create_d3d9_device(HWND hwnd) {
- HRESULT hr;
-
- IDirect3D9* d3d9;
- d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
- if (NULL == d3d9) {
- return NULL;
- }
- D3DDEVTYPE devType = D3DDEVTYPE_HAL;
- //D3DDEVTYPE devType = D3DDEVTYPE_REF;
- DWORD qLevels;
- DWORD qLevelsDepth;
- D3DMULTISAMPLE_TYPE type;
- for (type = D3DMULTISAMPLE_16_SAMPLES;
- type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {
- hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
- devType, D3DFMT_D24S8, TRUE,
- type, &qLevels);
- qLevels = (hr == D3D_OK) ? qLevels : 0;
- hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
- devType, D3DFMT_A8R8G8B8, TRUE,
- type, &qLevelsDepth);
- qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;
- qLevels = min(qLevels,qLevelsDepth);
- if (qLevels > 0) {
- break;
- }
- }
- qLevels = 0;
- IDirect3DDevice9* d3d9Device;
- D3DPRESENT_PARAMETERS pres;
- memset(&pres, 0, sizeof(pres));
- pres.EnableAutoDepthStencil = TRUE;
- pres.AutoDepthStencilFormat = D3DFMT_D24S8;
- pres.BackBufferCount = 2;
- pres.BackBufferFormat = D3DFMT_A8R8G8B8;
- pres.BackBufferHeight = 0;
- pres.BackBufferWidth = 0;
- if (qLevels > 0) {
- pres.MultiSampleType = type;
- pres.MultiSampleQuality = qLevels-1;
- } else {
- pres.MultiSampleType = D3DMULTISAMPLE_NONE;
- pres.MultiSampleQuality = 0;
- }
- pres.SwapEffect = D3DSWAPEFFECT_DISCARD;
- pres.Windowed = TRUE;
- pres.hDeviceWindow = hwnd;
- pres.PresentationInterval = 1;
- pres.Flags = 0;
- hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,
- devType,
- hwnd,
- D3DCREATE_HARDWARE_VERTEXPROCESSING,
- &pres,
- &d3d9Device);
- D3DERR_INVALIDCALL;
- if (SUCCEEDED(hr)) {
- d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);
- return d3d9Device;
- }
- return NULL;
-}
-
-// This needs some improvement. D3D doesn't have the same notion of attach/detach
-// as GL. However, just allowing GDI to write to the window after creating the
-// D3D device seems to work.
-// We need to handle resizing. On XP and earlier Reset() will trash all our textures
-// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we
-// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing
-// everything. Currently we do nothing and the D3D9 image gets stretched/compressed
-// when resized.
-
-bool SkOSWindow::attachD3D9() {
- if (NULL == fD3D9Device) {
- fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);
- }
- if (NULL != fD3D9Device) {
- ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
- fD3D9Attached = true;
- }
- return fD3D9Attached;
-}
-
-void SkOSWindow::detachD3D9() {
- if (NULL != fD3D9Device) {
- ((IDirect3DDevice9*)fD3D9Device)->EndScene();
- }
- fD3D9Attached = false;
-}
-
-void SkOSWindow::presentD3D9() {
- if (NULL != fD3D9Device) {
- HRESULT hr;
- hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();
- SkASSERT(SUCCEEDED(hr));
- hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);
- SkASSERT(SUCCEEDED(hr));
- hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET |
- D3DCLEAR_STENCIL, 0x0, 0,
- 0);
- SkASSERT(SUCCEEDED(hr));
- hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
- SkASSERT(SUCCEEDED(hr));
- }
-}
-
-
-#endif
-
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_WIN)
+
+#include <GL/gl.h>
+#include <d3d9.h>
+#include <WindowsX.h>
+#include "SkWGL.h"
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+#include "SkUtils.h"
+
+#include "SkGraphics.h"
+
+#if SK_ANGLE
+#include "gl/GrGLInterface.h"
+
+#include "GLES2/gl2.h"
+#endif
+
+#define INVALIDATE_DELAY_MS 200
+
+static SkOSWindow* gCurrOSWin;
+static HWND gEventTarget;
+
+#define WM_EVENT_CALLBACK (WM_USER+0)
+
+void post_skwinevent()
+{
+ PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
+}
+
+SkOSWindow::SkOSWindow(void* hWnd)
+ : fHWND(hWnd)
+#if SK_ANGLE
+ , fDisplay(EGL_NO_DISPLAY)
+ , fContext(EGL_NO_CONTEXT)
+ , fSurface(EGL_NO_SURFACE)
+#endif
+ , fHGLRC(NULL)
+ , fD3D9Device(NULL)
+ , fAttached(kNone_BackEndType) {
+ gEventTarget = (HWND)hWnd;
+}
+
+SkOSWindow::~SkOSWindow() {
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->Release();
+ }
+ if (NULL != fHGLRC) {
+ wglDeleteContext((HGLRC)fHGLRC);
+ }
+#if SK_ANGLE
+ if (EGL_NO_CONTEXT != fContext) {
+ eglDestroyContext(fDisplay, fContext);
+ fContext = EGL_NO_CONTEXT;
+ }
+
+ if (EGL_NO_SURFACE != fSurface) {
+ eglDestroySurface(fDisplay, fSurface);
+ fSurface = EGL_NO_SURFACE;
+ }
+
+ if (EGL_NO_DISPLAY != fDisplay) {
+ eglTerminate(fDisplay);
+ fDisplay = EGL_NO_DISPLAY;
+ }
+#endif
+}
+
+static SkKey winToskKey(WPARAM vk) {
+ static const struct {
+ WPARAM fVK;
+ SkKey fKey;
+ } gPair[] = {
+ { VK_BACK, kBack_SkKey },
+ { VK_CLEAR, kBack_SkKey },
+ { VK_RETURN, kOK_SkKey },
+ { VK_UP, kUp_SkKey },
+ { VK_DOWN, kDown_SkKey },
+ { VK_LEFT, kLeft_SkKey },
+ { VK_RIGHT, kRight_SkKey }
+ };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
+ if (gPair[i].fVK == vk) {
+ return gPair[i].fKey;
+ }
+ }
+ return kNONE_SkKey;
+}
+
+bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_KEYDOWN: {
+ SkKey key = winToskKey(wParam);
+ if (kNONE_SkKey != key) {
+ this->handleKey(key);
+ return true;
+ }
+ } break;
+ case WM_KEYUP: {
+ SkKey key = winToskKey(wParam);
+ if (kNONE_SkKey != key) {
+ this->handleKeyUp(key);
+ return true;
+ }
+ } break;
+ case WM_UNICHAR:
+ this->handleChar(wParam);
+ return true;
+ case WM_CHAR: {
+ this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
+ return true;
+ } break;
+ case WM_SIZE:
+ this->resize(lParam & 0xFFFF, lParam >> 16);
+ break;
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hWnd, &ps);
+ this->doPaint(hdc);
+ EndPaint(hWnd, &ps);
+ return true;
+ } break;
+
+ case WM_TIMER: {
+ RECT* rect = (RECT*)wParam;
+ InvalidateRect(hWnd, rect, FALSE);
+ KillTimer(hWnd, (UINT_PTR)rect);
+ delete rect;
+ return true;
+ } break;
+
+ case WM_LBUTTONDOWN:
+ this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
+ return true;
+
+ case WM_MOUSEMOVE:
+ this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
+ return true;
+
+ case WM_LBUTTONUP:
+ this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
+ return true;
+
+ case WM_EVENT_CALLBACK:
+ if (SkEvent::ProcessEvent()) {
+ post_skwinevent();
+ }
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::doPaint(void* ctx) {
+ this->update(NULL);
+
+ if (kNone_BackEndType == fAttached)
+ {
+ HDC hdc = (HDC)ctx;
+ const SkBitmap& bitmap = this->getBitmap();
+
+ BITMAPINFO bmi;
+ memset(&bmi, 0, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = bitmap.width();
+ bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = 0;
+
+ //
+ // Do the SetDIBitsToDevice.
+ //
+ // TODO(wjmaclean):
+ // Fix this call to handle SkBitmaps that have rowBytes != width,
+ // i.e. may have padding at the end of lines. The SkASSERT below
+ // may be ignored by builds, and the only obviously safe option
+ // seems to be to copy the bitmap to a temporary (contiguous)
+ // buffer before passing to SetDIBitsToDevice().
+ SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
+ bitmap.lockPixels();
+ int iRet = SetDIBitsToDevice(hdc,
+ 0, 0,
+ bitmap.width(), bitmap.height(),
+ 0, 0,
+ 0, bitmap.height(),
+ bitmap.getPixels(),
+ &bmi,
+ DIB_RGB_COLORS);
+ bitmap.unlockPixels();
+ }
+}
+
+#if 0
+void SkOSWindow::updateSize()
+{
+ RECT r;
+ GetWindowRect((HWND)this->getHWND(), &r);
+ this->resize(r.right - r.left, r.bottom - r.top);
+}
+#endif
+
+void SkOSWindow::onHandleInval(const SkIRect& r) {
+ RECT* rect = new RECT;
+ rect->left = r.fLeft;
+ rect->top = r.fTop;
+ rect->right = r.fRight;
+ rect->bottom = r.fBottom;
+ SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
+}
+
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
+{
+}
+
+void SkOSWindow::onSetTitle(const char title[]){
+ SetWindowTextA((HWND)fHWND, title);
+}
+
+enum {
+ SK_MacReturnKey = 36,
+ SK_MacDeleteKey = 51,
+ SK_MacEndKey = 119,
+ SK_MacLeftKey = 123,
+ SK_MacRightKey = 124,
+ SK_MacDownKey = 125,
+ SK_MacUpKey = 126,
+
+ SK_Mac0Key = 0x52,
+ SK_Mac1Key = 0x53,
+ SK_Mac2Key = 0x54,
+ SK_Mac3Key = 0x55,
+ SK_Mac4Key = 0x56,
+ SK_Mac5Key = 0x57,
+ SK_Mac6Key = 0x58,
+ SK_Mac7Key = 0x59,
+ SK_Mac8Key = 0x5b,
+ SK_Mac9Key = 0x5c
+};
+
+static SkKey raw2key(uint32_t raw)
+{
+ static const struct {
+ uint32_t fRaw;
+ SkKey fKey;
+ } gKeys[] = {
+ { SK_MacUpKey, kUp_SkKey },
+ { SK_MacDownKey, kDown_SkKey },
+ { SK_MacLeftKey, kLeft_SkKey },
+ { SK_MacRightKey, kRight_SkKey },
+ { SK_MacReturnKey, kOK_SkKey },
+ { SK_MacDeleteKey, kBack_SkKey },
+ { SK_MacEndKey, kEnd_SkKey },
+ { SK_Mac0Key, k0_SkKey },
+ { SK_Mac1Key, k1_SkKey },
+ { SK_Mac2Key, k2_SkKey },
+ { SK_Mac3Key, k3_SkKey },
+ { SK_Mac4Key, k4_SkKey },
+ { SK_Mac5Key, k5_SkKey },
+ { SK_Mac6Key, k6_SkKey },
+ { SK_Mac7Key, k7_SkKey },
+ { SK_Mac8Key, k8_SkKey },
+ { SK_Mac9Key, k9_SkKey }
+ };
+
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
+ if (gKeys[i].fRaw == raw)
+ return gKeys[i].fKey;
+ return kNONE_SkKey;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void SkEvent::SignalNonEmptyQueue()
+{
+ post_skwinevent();
+ //SkDebugf("signal nonempty\n");
+}
+
+static UINT_PTR gTimer;
+
+VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ SkEvent::ServiceQueueTimer();
+ //SkDebugf("timer task fired\n");
+}
+
+void SkEvent::SignalQueueTimer(SkMSec delay)
+{
+ if (gTimer)
+ {
+ KillTimer(NULL, gTimer);
+ gTimer = NULL;
+ }
+ if (delay)
+ {
+ gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
+ //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
+ }
+}
+
+
+#define USE_MSAA 0
+
+HGLRC create_gl(HWND hwnd) {
+
+ HDC dc = GetDC(hwnd);
+
+ SkWGLExtensions extensions;
+ if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
+ return NULL;
+ }
+
+ HDC prevDC = wglGetCurrentDC();
+ HGLRC prevGLRC = wglGetCurrentContext();
+ PIXELFORMATDESCRIPTOR pfd;
+
+ int format = 0;
+
+ GLint iattrs[] = {
+ SK_WGL_DRAW_TO_WINDOW, TRUE,
+ SK_WGL_DOUBLE_BUFFER, TRUE,
+ SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,
+ SK_WGL_SUPPORT_OPENGL, TRUE,
+ SK_WGL_COLOR_BITS, 24,
+ SK_WGL_ALPHA_BITS, 8,
+ SK_WGL_STENCIL_BITS, 8,
+
+ // these must be kept last
+ SK_WGL_SAMPLE_BUFFERS, TRUE,
+ SK_WGL_SAMPLES, 0,
+ 0,0
+ };
+
+ static const int kSampleBuffersValueIdx = SK_ARRAY_COUNT(iattrs) - 5;
+ static const int kSamplesValueIdx = SK_ARRAY_COUNT(iattrs) - 3;
+ if (USE_MSAA && extensions.hasExtension(dc, "WGL_ARB_multisample")) {
+ for (int samples = 16; samples > 1; --samples) {
+
+ iattrs[kSamplesValueIdx] = samples;
+ GLfloat fattrs[] = {0,0};
+ GLuint num;
+ int formats[64];
+ extensions.choosePixelFormat(dc, iattrs, fattrs, 64, formats, &num);
+ num = min(num,64);
+ for (GLuint i = 0; i < num; ++i) {
+ DescribePixelFormat(dc, formats[i], sizeof(pfd), &pfd);
+ if (SetPixelFormat(dc, formats[i], &pfd)) {
+ format = formats[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (0 == format) {
+ iattrs[kSampleBuffersValueIdx-1] = iattrs[kSampleBuffersValueIdx] = 0;
+ iattrs[kSamplesValueIdx-1] = iattrs[kSamplesValueIdx] = 0;
+ GLfloat fattrs[] = {0,0};
+ GLuint num;
+ extensions.choosePixelFormat(dc, iattrs, fattrs, 1, &format, &num);
+ DescribePixelFormat(dc, format, sizeof(pfd), &pfd);
+ BOOL set = SetPixelFormat(dc, format, &pfd);
+ SkASSERT(TRUE == set);
+ }
+
+ HGLRC glrc = wglCreateContext(dc);
+ SkASSERT(glrc);
+
+ wglMakeCurrent(prevDC, prevGLRC);
+ return glrc;
+}
+
+bool SkOSWindow::attachGL() {
+ if (NULL == fHGLRC) {
+ fHGLRC = create_gl((HWND)fHWND);
+ if (NULL == fHGLRC) {
+ return false;
+ }
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 0);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ }
+ if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
+ glViewport(0, 0, SkScalarRound(this->width()),
+ SkScalarRound(this->height()));
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachGL() {
+ wglMakeCurrent(GetDC((HWND)fHWND), 0);
+ wglDeleteContext((HGLRC)fHGLRC);
+ fHGLRC = NULL;
+}
+
+void SkOSWindow::presentGL() {
+ glFlush();
+ SwapBuffers(GetDC((HWND)fHWND));
+}
+
+#if SK_ANGLE
+bool create_ANGLE(EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
+ EGLContext* eglContext, EGLSurface* eglSurface) {
+ EGLint contextAttribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE, EGL_NONE
+ };
+ EGLint configAttribList[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 8,
+ EGL_STENCIL_SIZE, 8,
+ EGL_NONE
+ };
+ EGLint surfaceAttribList[] = {
+ EGL_NONE, EGL_NONE
+ };
+
+ EGLDisplay display = eglGetDisplay(GetDC(hWnd));
+ if (display == EGL_NO_DISPLAY ) {
+ return false;
+ }
+
+ // Initialize EGL
+ EGLint majorVersion, minorVersion;
+ if (!eglInitialize(display, &majorVersion, &minorVersion)) {
+ return false;
+ }
+
+ EGLint numConfigs;
+ if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {
+ return false;
+ }
+
+ // Choose config
+ EGLConfig config;
+ if (!eglChooseConfig(display, configAttribList,
+ &config, 1, &numConfigs)) {
+ return false;
+ }
+
+ // Create a surface
+ EGLSurface surface = eglCreateWindowSurface(display, config,
+ (EGLNativeWindowType)hWnd,
+ surfaceAttribList);
+ if (surface == EGL_NO_SURFACE) {
+ return false;
+ }
+
+ // Create a GL context
+ EGLContext context = eglCreateContext(display, config,
+ EGL_NO_CONTEXT,
+ contextAttribs );
+ if (context == EGL_NO_CONTEXT ) {
+ return false;
+ }
+
+ // Make the context current
+ if (!eglMakeCurrent(display, surface, surface, context)) {
+ return false;
+ }
+
+ *eglDisplay = display;
+ *eglContext = context;
+ *eglSurface = surface;
+ return true;
+}
+
+bool SkOSWindow::attachANGLE() {
+ if (EGL_NO_DISPLAY == fDisplay) {
+ bool bResult = create_ANGLE((HWND)fHWND, &fDisplay, &fContext, &fSurface);
+ if (false == bResult) {
+ return false;
+ }
+ const GrGLInterface* intf = GrGLCreateANGLEInterface();
+
+ if (intf) {
+ GR_GL_CALL(intf, ClearStencil(0));
+ GR_GL_CALL(intf, ClearColor(0, 0, 0, 0));
+ GR_GL_CALL(intf, StencilMask(0xffffffff));
+ GR_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
+ }
+ }
+ if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+ const GrGLInterface* intf = GrGLCreateANGLEInterface();
+
+ if (intf ) {
+ GR_GL_CALL(intf, Viewport(0, 0, SkScalarRound(this->width()),
+ SkScalarRound(this->height())));
+ }
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachANGLE() {
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
+
+ eglDestroyContext(fDisplay, fContext);
+ fContext = EGL_NO_CONTEXT;
+
+ eglDestroySurface(fDisplay, fSurface);
+ fSurface = EGL_NO_SURFACE;
+
+ eglTerminate(fDisplay);
+ fDisplay = EGL_NO_DISPLAY;
+}
+
+void SkOSWindow::presentANGLE() {
+ const GrGLInterface* intf = GrGLCreateANGLEInterface();
+
+ if (intf) {
+ GR_GL_CALL(intf, Flush());
+ }
+
+ eglSwapBuffers(fDisplay, fSurface);
+}
+#endif
+
+IDirect3DDevice9* create_d3d9_device(HWND hwnd) {
+ HRESULT hr;
+
+ IDirect3D9* d3d9;
+ d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ if (NULL == d3d9) {
+ return NULL;
+ }
+ D3DDEVTYPE devType = D3DDEVTYPE_HAL;
+ //D3DDEVTYPE devType = D3DDEVTYPE_REF;
+ DWORD qLevels;
+ DWORD qLevelsDepth;
+ D3DMULTISAMPLE_TYPE type;
+ for (type = D3DMULTISAMPLE_16_SAMPLES;
+ type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {
+ hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
+ devType, D3DFMT_D24S8, TRUE,
+ type, &qLevels);
+ qLevels = (hr == D3D_OK) ? qLevels : 0;
+ hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
+ devType, D3DFMT_A8R8G8B8, TRUE,
+ type, &qLevelsDepth);
+ qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;
+ qLevels = min(qLevels,qLevelsDepth);
+ if (qLevels > 0) {
+ break;
+ }
+ }
+ qLevels = 0;
+ IDirect3DDevice9* d3d9Device;
+ D3DPRESENT_PARAMETERS pres;
+ memset(&pres, 0, sizeof(pres));
+ pres.EnableAutoDepthStencil = TRUE;
+ pres.AutoDepthStencilFormat = D3DFMT_D24S8;
+ pres.BackBufferCount = 2;
+ pres.BackBufferFormat = D3DFMT_A8R8G8B8;
+ pres.BackBufferHeight = 0;
+ pres.BackBufferWidth = 0;
+ if (qLevels > 0) {
+ pres.MultiSampleType = type;
+ pres.MultiSampleQuality = qLevels-1;
+ } else {
+ pres.MultiSampleType = D3DMULTISAMPLE_NONE;
+ pres.MultiSampleQuality = 0;
+ }
+ pres.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ pres.Windowed = TRUE;
+ pres.hDeviceWindow = hwnd;
+ pres.PresentationInterval = 1;
+ pres.Flags = 0;
+ hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,
+ devType,
+ hwnd,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING,
+ &pres,
+ &d3d9Device);
+ D3DERR_INVALIDCALL;
+ if (SUCCEEDED(hr)) {
+ d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);
+ return d3d9Device;
+ }
+ return NULL;
+}
+
+// This needs some improvement. D3D doesn't have the same notion of attach/detach
+// as GL. However, just allowing GDI to write to the window after creating the
+// D3D device seems to work.
+// We need to handle resizing. On XP and earlier Reset() will trash all our textures
+// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we
+// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing
+// everything. Currently we do nothing and the D3D9 image gets stretched/compressed
+// when resized.
+
+bool SkOSWindow::attachD3D9() {
+ if (NULL == fD3D9Device) {
+ fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);
+ }
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachD3D9() {
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+ }
+}
+
+void SkOSWindow::presentD3D9() {
+ if (NULL != fD3D9Device) {
+ HRESULT hr;
+ hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+ SkASSERT(SUCCEEDED(hr));
+ hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);
+ SkASSERT(SUCCEEDED(hr));
+ hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET |
+ D3DCLEAR_STENCIL, 0x0, 0,
+ 0);
+ SkASSERT(SUCCEEDED(hr));
+ hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
+ SkASSERT(SUCCEEDED(hr));
+ }
+}
+
+// return true on success
+bool SkOSWindow::attach(SkBackEndTypes attachType) {
+
+ // attach doubles as "windowResize" so we need to allo
+ // already bound states to pass through again
+ // TODO: split out the resize functionality
+// SkASSERT(kNone_BackEndType == fAttached);
+ bool result = true;
+
+ switch (attachType) {
+ case kNone_BackEndType:
+ // nothing to do
+ break;
+ case kNativeGL_BackEndType:
+ result = attachGL();
+ break;
+#if SK_ANGLE
+ case kANGLE_BackEndType:
+ result = attachANGLE();
+ break;
+#endif
+ case kD3D9_BackEndType:
+ result = attachD3D9();
+ break;
+ default:
+ SkASSERT(false);
+ result = false;
+ break;
+ }
+
+ if (result) {
+ fAttached = attachType;
+ }
+
+ return result;
+}
+
+void SkOSWindow::detach() {
+ switch (fAttached) {
+ case kNone_BackEndType:
+ // nothing to do
+ break;
+ case kNativeGL_BackEndType:
+ detachGL();
+ break;
+#if SK_ANGLE
+ case kANGLE_BackEndType:
+ detachANGLE();
+ break;
+#endif
+ case kD3D9_BackEndType:
+ detachD3D9();
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
+ fAttached = kNone_BackEndType;
+}
+
+void SkOSWindow::present() {
+ switch (fAttached) {
+ case kNone_BackEndType:
+ // nothing to do
+ return;
+ case kNativeGL_BackEndType:
+ presentGL();
+ break;
+#if SK_ANGLE
+ case kANGLE_BackEndType:
+ presentANGLE();
+ break;
+#endif
+ case kD3D9_BackEndType:
+ presentD3D9();
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
+}
+
+#endif