aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2010-12-20 18:26:13 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2010-12-20 18:26:13 +0000
commitf2b98d67dcb6fcb3120feede9c72016fc7b3ead8 (patch)
treed78b57945b29865dcdeb1badbb360575289b292d /src/utils
parent29e5054dd07c97c2195c5f64bf67aaa6b5afa204 (diff)
merge with changes for GPU backend
git-svn-id: http://skia.googlecode.com/svn/trunk@637 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/SkProxyCanvas.cpp12
-rw-r--r--src/utils/mac/SkCreateCGImageRef.cpp34
-rw-r--r--src/utils/mac/SkOSWindow_Mac.cpp78
-rw-r--r--src/utils/win/SkOSWindow_Win.cpp782
4 files changed, 675 insertions, 231 deletions
diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp
index c643c8277e..d462d01b12 100644
--- a/src/utils/SkProxyCanvas.cpp
+++ b/src/utils/SkProxyCanvas.cpp
@@ -18,14 +18,6 @@ bool SkProxyCanvas::getViewport(SkIPoint* size) const {
return fProxy->getViewport(size);
}
-bool SkProxyCanvas::setViewport(int x, int y) {
- return fProxy->setViewport(x, y);
-}
-
-SkDevice* SkProxyCanvas::setBitmapDevice(const SkBitmap& bitmap) {
- return fProxy->setBitmapDevice(bitmap);
-}
-
int SkProxyCanvas::save(SaveFlags flags) {
return fProxy->save(flags);
}
@@ -163,8 +155,8 @@ SkDrawFilter* SkProxyCanvas::setDrawFilter(SkDrawFilter* filter) {
return fProxy->setDrawFilter(filter);
}
-SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width,
- int height, bool isOpaque, bool isForLayer) {
+SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, int height,
+ bool isOpaque, bool isForLayer) {
return fProxy->createDevice(config, width, height, isOpaque, isForLayer);
}
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 5c96e21ff6..2169bc09cb 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -26,22 +26,19 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm,
*bitsPerComponent = 8;
#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \
|| defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8)
- *info = kCGBitmapByteOrder32Big |
- kCGImageAlphaPremultipliedLast;
+ *info = kCGBitmapByteOrder32Big;
#elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \
|| defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
// Matches the CGBitmapInfo that Apple recommends for best
// performance, used by google chrome.
- *info = kCGBitmapByteOrder32Host |
- kCGImageAlphaPremultipliedFirst;
+ *info = kCGBitmapByteOrder32Little;
#else
// ...add more formats as required...
#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
This will probably not work.
// Legacy behavior. Perhaps turn this into an error at some
// point.
- *info = kCGBitmapByteOrder32Big |
- kCGImageAlphaPremultipliedLast;
+ *info = kCGBitmapByteOrder32Big;
#endif
break;
#if 0
@@ -59,6 +56,10 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm,
return NULL;
}
+ if (!bm.isOpaque()) {
+ *info |= kCGImageAlphaPremultipliedLast;
+ }
+
SkBitmap* copy;
if (upscaleTo32) {
copy = new SkBitmap;
@@ -93,7 +94,7 @@ CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
SkBitmap_ReleaseInfo);
- CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
bitmap->bytesPerPixel() * 8,
bitmap->rowBytes(), space, info, dataRef,
@@ -103,4 +104,23 @@ CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
return ref;
}
+void SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
+ CGImageRef img = SkCreateCGImageRef(bm);
+
+ if (img) {
+ CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
+
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, x, r.size.height + y);
+ CGContextScaleCTM(cg, 1, -1);
+
+ CGContextDrawImage(cg, r, img);
+
+ CGContextRestoreGState(cg);
+
+ CGImageRelease(img);
+ }
+}
+
+
diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp
index eb07e2aa73..6828a955f0 100644
--- a/src/utils/mac/SkOSWindow_Mac.cpp
+++ b/src/utils/mac/SkOSWindow_Mac.cpp
@@ -2,6 +2,8 @@
#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
+#include <AGL/agl.h>
+
#include <Carbon/Carbon.h>
#include "SkCGUtils.h"
@@ -82,7 +84,7 @@ static void set_axisposition(HIAxisPosition* pos, HIViewRef parent, HIPositionKi
pos->offset = 0;
}
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd)
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), fAGLCtx(NULL)
{
OSStatus result;
WindowRef wr = (WindowRef)hWnd;
@@ -450,5 +452,79 @@ void SkEvent::SignalQueueTimer(SkMSec delay)
}
}
+AGLContext create_gl(WindowRef wref, bool offscreen)
+{
+ GLint major, minor;
+ AGLContext ctx;
+
+ aglGetVersion(&major, &minor);
+ SkDebugf("---- agl version %d %d\n", major, minor);
+
+ const GLint pixelAttrs[] = {
+ AGL_RGBA,
+ AGL_STENCIL_SIZE, 8,
+ AGL_SAMPLE_BUFFERS_ARB, 1,
+ AGL_MULTISAMPLE,
+ AGL_SAMPLES_ARB, 2,
+ (offscreen ? AGL_OFFSCREEN : AGL_ACCELERATED),
+ (offscreen ? AGL_NONE : AGL_DOUBLEBUFFER),
+ AGL_NONE
+ };
+ AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs);
+ //AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
+ SkDebugf("----- agl format %p\n", format);
+ ctx = aglCreateContext(format, NULL);
+ SkDebugf("----- agl context %p\n", ctx);
+ aglDestroyPixelFormat(format);
+
+ static const GLint interval = 1;
+ aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval);
+ aglSetCurrentContext(ctx);
+ return ctx;
+}
+
+bool SkOSWindow::attachGL(const SkBitmap* offscreen)
+{
+ if (NULL == fAGLCtx) {
+ fAGLCtx = create_gl((WindowRef)fHWND, NULL != offscreen);
+ if (NULL == fAGLCtx) {
+ return false;
+ }
+ }
+
+ GLboolean success = true;
+
+ if (offscreen) {
+ success = aglSetOffScreen((AGLContext)fAGLCtx,
+ offscreen->width(),
+ offscreen->height(),
+ offscreen->rowBytes(),
+ offscreen->getPixels());
+ } else {
+ success = aglSetWindowRef((AGLContext)fAGLCtx, (WindowRef)fHWND);
+ }
+
+ GLenum err = aglGetError();
+ if (err) {
+ SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err,
+ aglErrorString(err), offscreen->width(), offscreen->height());
+ }
+
+ if (success) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+ return success;
+}
+
+void SkOSWindow::detachGL() {
+ aglSetWindowRef((AGLContext)fAGLCtx, NULL);
+}
+
+void SkOSWindow::presentGL() {
+ aglSwapBuffers((AGLContext)fAGLCtx);
+ glFlush();
+}
+
#endif
diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp
index 376c3bdfda..26993be661 100644
--- a/src/utils/win/SkOSWindow_Win.cpp
+++ b/src/utils/win/SkOSWindow_Win.cpp
@@ -1,213 +1,569 @@
-#include "SkTypes.h"
-
-#if defined(SK_BUILD_FOR_WIN)
-
-#include "SkWindow.h"
-#include "SkCanvas.h"
-#include "SkOSMenu.h"
-#include "SkTime.h"
-
-#include "SkGraphics.h"
-
-static SkOSWindow* gCurrOSWin;
-
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) {
-}
-
-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(lParam);
- return true;
- 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;
- }
- return false;
-}
-
-void SkOSWindow::doPaint(void* ctx) {
- this->update(NULL);
-
- 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.
- //
- 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;
- rect.left = r.fLeft;
- rect.top = r.fTop;
- rect.right = r.fRight;
- rect.bottom = r.fBottom;
- InvalidateRect((HWND)this->getHWND(), &rect, false);
-}
-
-void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
-{
-}
-
-
-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_skmacevent();
-// SkDebugf("signal nonempty\n");
-}
-
-//static void sk_timer_proc(TMTask* rec)
-//{
-// SkEvent::ServiceQueueTimer();
-// SkDebugf("timer task fired\n");
-//}
-
-void SkEvent::SignalQueueTimer(SkMSec delay)
-{
-#if 0
- if (gTMTaskPtr)
- {
- RemoveTimeTask((QElem*)gTMTaskPtr);
- DisposeTimerUPP(gTMTaskPtr->tmAddr);
- gTMTaskPtr = nil;
- }
- if (delay)
- {
- gTMTaskPtr = &gTMTaskRec;
- memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));
- gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);
- OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);
-// SkDebugf("installtimetask of %d returned %d\n", delay, err);
- PrimeTimeTask((QElem*)gTMTaskPtr, delay);
- }
-#endif
-}
-
-#endif
-
+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_WIN)
+
+#include <GL/glew.h>
+#include <GL/wglew.h>
+#include <GL/gl.h>
+#include <d3d9.h>
+#include <WindowsX.h>
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+#include "SkUtils.h"
+
+#include "SkGraphics.h"
+
+#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),
+ 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);
+ }
+}
+
+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.
+ //
+ 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);
+ }
+}
+
+static HWND create_dummy()
+{
+ HMODULE module = GetModuleHandle(NULL);
+ HWND dummy;
+ RECT windowRect;
+ windowRect.left = 0;
+ windowRect.right = 8;
+ windowRect.top = 0;
+ windowRect.bottom = 8;
+
+ WNDCLASS wc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC) DefWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = module;
+ wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = L"DummyWindow";
+
+ if(!RegisterClass(&wc))
+ {
+ return 0;
+ }
+
+ DWORD style, exStyle;
+ exStyle = WS_EX_CLIENTEDGE;
+ style = WS_SYSMENU;
+
+ AdjustWindowRectEx(&windowRect, style, false, exStyle);
+
+ if(!(dummy = CreateWindowEx(exStyle,
+ L"DummyWindow",
+ L"Dummy Window",
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
+ 0, 0,
+ windowRect.right-windowRect.left,
+ windowRect.bottom-windowRect.top,
+ NULL, NULL,
+ module,
+ NULL)))
+ {
+ UnregisterClass(L"Dummy Window", module);
+ return NULL;
+ }
+ ShowWindow(dummy, SW_HIDE);
+
+ return dummy;
+}
+
+void kill_dummy(HWND dummy) {
+ DestroyWindow(dummy);
+ HMODULE module = GetModuleHandle(NULL);
+ UnregisterClass(L"Dummy Window", module);
+}
+
+HGLRC create_gl(HWND hwnd) {
+ HDC hdc;
+ HDC prevHDC;
+ HGLRC prevGLRC, glrc;
+ PIXELFORMATDESCRIPTOR pfd;
+
+ static bool glewInitialized;
+
+ prevGLRC = wglGetCurrentContext();
+ prevHDC = wglGetCurrentDC();
+
+ int format = 0;
+
+ // glew must be initialized after a context has been created and made current
+ // and we need glew already be initialized to get wglChoosePixelFormatEXT :(
+ // Even worse: SetPixelFormat needs to be called before the context is created
+ // But SetPixelFormat is only allowed to succeed once per-window. So we need to
+ // create a dummy window for glew in order for it to call wglGetProcAddress() to
+ // get wglChoosePixelFormatARB(). This is a Windows problem, not a glew problem.
+ if (!glewInitialized) {
+ ZeroMemory(&pfd, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 32;
+ pfd.cDepthBits = 0;
+ pfd.cStencilBits = 8;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ HWND dummy = create_dummy();
+ SkASSERT(NULL != dummy);
+ hdc = GetDC(dummy);
+ format = ChoosePixelFormat(hdc, &pfd);
+ SetPixelFormat(hdc, format, &pfd);
+ glrc = wglCreateContext(hdc);
+ SkASSERT(glrc);
+ wglMakeCurrent(hdc, glrc);
+
+ GLenum err;
+ err = glewInit();
+ SkASSERT(GLEW_OK == err);
+ SkASSERT(GLEW_EXT_bgra);
+ SkASSERT(GLEW_EXT_framebuffer_object);
+ SkASSERT(WGLEW_ARB_pixel_format);
+ glewInitialized = true;
+ wglMakeCurrent(hdc, NULL);
+ wglDeleteContext(glrc);
+ glrc = 0;
+ kill_dummy(dummy);
+ }
+
+ hdc = GetDC(hwnd);
+ format = 0;
+
+ GLint iattrs[] = {
+ WGL_DRAW_TO_WINDOW_ARB, TRUE,
+ WGL_DOUBLE_BUFFER_ARB, TRUE,
+ WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+ WGL_SUPPORT_OPENGL_ARB, TRUE,
+ WGL_COLOR_BITS_ARB, 24,
+ WGL_STENCIL_BITS_ARB, 8,
+ WGL_SAMPLE_BUFFERS_ARB, TRUE,
+ WGL_SAMPLES_ARB, 0,
+ 0,0
+ };
+ for (int samples = 16; samples > 1; --samples) {
+ iattrs[15] = samples;
+ GLfloat fattrs[] = {0,0};
+ GLuint num;
+ int formats[64];
+ wglChoosePixelFormatARB(hdc, iattrs, fattrs, 64, formats, &num);
+ num = min(num,64);
+ for (GLuint i = 0; i < num; ++i) {
+ DescribePixelFormat(hdc, formats[i], sizeof(pfd), &pfd);
+ if (SetPixelFormat(hdc, formats[i], &pfd)) {
+ format = formats[i];
+ break;
+ }
+ }
+ }
+ if (0 == format) {
+ iattrs[12] = iattrs[13] = 0;
+ GLfloat fattrs[] = {0,0};
+ GLuint num;
+ wglChoosePixelFormatARB(hdc, iattrs, fattrs, 1, &format, &num);
+ DescribePixelFormat(hdc, format, sizeof(pfd), &pfd);
+ BOOL set = SetPixelFormat(hdc, format, &pfd);
+ SkASSERT(TRUE == set);
+ }
+
+ glrc = wglCreateContext(hdc);
+ SkASSERT(glrc);
+
+ wglMakeCurrent(prevHDC, prevGLRC);
+ return glrc;
+}
+
+bool SkOSWindow::attachGL(const SkBitmap* offscreen) {
+ if (offscreen) {
+ printf("windows doesn't support rendering to SkBitmap");
+ }
+ if (NULL == fHGLRC) {
+ fHGLRC = create_gl((HWND)fHWND);
+ if (NULL == fHGLRC) {
+ return false;
+ }
+ }
+ if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ fGLAttached = true;
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachGL() {
+ wglMakeCurrent(GetDC((HWND)fHWND), 0);
+ fGLAttached = false;
+}
+
+void SkOSWindow::presentGL() {
+ glFlush();
+ SwapBuffers(GetDC((HWND)fHWND));
+ glClearColor(0,0,0,0);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+}
+
+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 \ No newline at end of file