blob: 4eb41ce1c741673b37784cc0510d64627b28dc2f [file] [log] [blame]
bsalomon@google.com2858b312012-04-02 20:44:38 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SkTypes.h"
9
10#if defined(SK_BUILD_FOR_WIN)
11
12#include <GL/gl.h>
bsalomon@google.com2858b312012-04-02 20:44:38 +000013#include <WindowsX.h>
14#include "SkWGL.h"
15#include "SkWindow.h"
16#include "SkCanvas.h"
17#include "SkOSMenu.h"
18#include "SkTime.h"
19#include "SkUtils.h"
20
21#include "SkGraphics.h"
22
23#if SK_ANGLE
24#include "gl/GrGLInterface.h"
25
26#include "GLES2/gl2.h"
borenet@google.com0dd5ceb2012-08-28 15:15:49 +000027
28#define ANGLE_GL_CALL(IFACE, X) \
29 do { \
30 (IFACE)->f##X; \
31 } while (false)
32
bsalomon@google.com2858b312012-04-02 20:44:38 +000033#endif
34
35#define INVALIDATE_DELAY_MS 200
36
37static SkOSWindow* gCurrOSWin;
38static HWND gEventTarget;
39
40#define WM_EVENT_CALLBACK (WM_USER+0)
41
42void post_skwinevent()
43{
44 PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
45}
46
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000047SkOSWindow::SkOSWindow(void* hWnd) {
48 fHWND = hWnd;
49#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +000050#if SK_ANGLE
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000051 fDisplay = EGL_NO_DISPLAY;
52 fContext = EGL_NO_CONTEXT;
53 fSurface = EGL_NO_SURFACE;
bsalomon@google.com2858b312012-04-02 20:44:38 +000054#endif
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000055 fHGLRC = NULL;
56#endif
57 fAttached = kNone_BackEndType;
bsalomon@google.com2858b312012-04-02 20:44:38 +000058 gEventTarget = (HWND)hWnd;
59}
60
61SkOSWindow::~SkOSWindow() {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000062#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +000063 if (NULL != fHGLRC) {
64 wglDeleteContext((HGLRC)fHGLRC);
65 }
66#if SK_ANGLE
67 if (EGL_NO_CONTEXT != fContext) {
68 eglDestroyContext(fDisplay, fContext);
69 fContext = EGL_NO_CONTEXT;
70 }
71
72 if (EGL_NO_SURFACE != fSurface) {
73 eglDestroySurface(fDisplay, fSurface);
74 fSurface = EGL_NO_SURFACE;
75 }
76
77 if (EGL_NO_DISPLAY != fDisplay) {
78 eglTerminate(fDisplay);
79 fDisplay = EGL_NO_DISPLAY;
80 }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000081#endif // SK_ANGLE
82#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +000083}
84
85static SkKey winToskKey(WPARAM vk) {
86 static const struct {
87 WPARAM fVK;
88 SkKey fKey;
89 } gPair[] = {
90 { VK_BACK, kBack_SkKey },
91 { VK_CLEAR, kBack_SkKey },
92 { VK_RETURN, kOK_SkKey },
93 { VK_UP, kUp_SkKey },
94 { VK_DOWN, kDown_SkKey },
95 { VK_LEFT, kLeft_SkKey },
96 { VK_RIGHT, kRight_SkKey }
97 };
98 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
99 if (gPair[i].fVK == vk) {
100 return gPair[i].fKey;
101 }
102 }
103 return kNONE_SkKey;
104}
105
reed@google.com4d5c26d2013-01-08 16:17:50 +0000106static unsigned getModifiers(UINT message) {
107 return 0; // TODO
108}
109
bsalomon@google.com2858b312012-04-02 20:44:38 +0000110bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
111 switch (message) {
112 case WM_KEYDOWN: {
113 SkKey key = winToskKey(wParam);
114 if (kNONE_SkKey != key) {
115 this->handleKey(key);
116 return true;
117 }
118 } break;
119 case WM_KEYUP: {
120 SkKey key = winToskKey(wParam);
121 if (kNONE_SkKey != key) {
122 this->handleKeyUp(key);
123 return true;
124 }
125 } break;
126 case WM_UNICHAR:
127 this->handleChar(wParam);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000128 return true;
bsalomon@google.com2858b312012-04-02 20:44:38 +0000129 case WM_CHAR: {
130 this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
131 return true;
132 } break;
133 case WM_SIZE:
134 this->resize(lParam & 0xFFFF, lParam >> 16);
135 break;
136 case WM_PAINT: {
137 PAINTSTRUCT ps;
138 HDC hdc = BeginPaint(hWnd, &ps);
139 this->doPaint(hdc);
140 EndPaint(hWnd, &ps);
141 return true;
142 } break;
143
144 case WM_TIMER: {
145 RECT* rect = (RECT*)wParam;
146 InvalidateRect(hWnd, rect, FALSE);
147 KillTimer(hWnd, (UINT_PTR)rect);
148 delete rect;
149 return true;
150 } break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000151
152 case WM_LBUTTONDOWN:
reed@google.com4d5c26d2013-01-08 16:17:50 +0000153 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
reed@google.com72708fa2013-01-08 16:22:44 +0000154 Click::kDown_State, NULL, getModifiers(message));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000155 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000156
bsalomon@google.com2858b312012-04-02 20:44:38 +0000157 case WM_MOUSEMOVE:
reed@google.com4d5c26d2013-01-08 16:17:50 +0000158 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
reed@google.com72708fa2013-01-08 16:22:44 +0000159 Click::kMoved_State, NULL, getModifiers(message));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000160 return true;
161
162 case WM_LBUTTONUP:
reed@google.com4d5c26d2013-01-08 16:17:50 +0000163 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
reed@google.com72708fa2013-01-08 16:22:44 +0000164 Click::kUp_State, NULL, getModifiers(message));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000165 return true;
166
167 case WM_EVENT_CALLBACK:
168 if (SkEvent::ProcessEvent()) {
169 post_skwinevent();
170 }
171 return true;
172 }
173 return false;
174}
175
176void SkOSWindow::doPaint(void* ctx) {
177 this->update(NULL);
178
179 if (kNone_BackEndType == fAttached)
180 {
181 HDC hdc = (HDC)ctx;
182 const SkBitmap& bitmap = this->getBitmap();
183
184 BITMAPINFO bmi;
185 memset(&bmi, 0, sizeof(bmi));
186 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
187 bmi.bmiHeader.biWidth = bitmap.width();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000188 bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
bsalomon@google.com2858b312012-04-02 20:44:38 +0000189 bmi.bmiHeader.biPlanes = 1;
190 bmi.bmiHeader.biBitCount = 32;
191 bmi.bmiHeader.biCompression = BI_RGB;
192 bmi.bmiHeader.biSizeImage = 0;
193
rmistry@google.comd6176b02012-08-23 18:14:13 +0000194 //
195 // Do the SetDIBitsToDevice.
196 //
bsalomon@google.com2858b312012-04-02 20:44:38 +0000197 // TODO(wjmaclean):
198 // Fix this call to handle SkBitmaps that have rowBytes != width,
199 // i.e. may have padding at the end of lines. The SkASSERT below
200 // may be ignored by builds, and the only obviously safe option
201 // seems to be to copy the bitmap to a temporary (contiguous)
202 // buffer before passing to SetDIBitsToDevice().
203 SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
204 bitmap.lockPixels();
205 int iRet = SetDIBitsToDevice(hdc,
206 0, 0,
207 bitmap.width(), bitmap.height(),
208 0, 0,
209 0, bitmap.height(),
210 bitmap.getPixels(),
211 &bmi,
212 DIB_RGB_COLORS);
213 bitmap.unlockPixels();
214 }
215}
216
217#if 0
218void SkOSWindow::updateSize()
219{
220 RECT r;
221 GetWindowRect((HWND)this->getHWND(), &r);
222 this->resize(r.right - r.left, r.bottom - r.top);
223}
224#endif
225
226void SkOSWindow::onHandleInval(const SkIRect& r) {
227 RECT* rect = new RECT;
228 rect->left = r.fLeft;
229 rect->top = r.fTop;
230 rect->right = r.fRight;
231 rect->bottom = r.fBottom;
232 SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
233}
234
235void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
236{
237}
238
239void SkOSWindow::onSetTitle(const char title[]){
240 SetWindowTextA((HWND)fHWND, title);
241}
242
243enum {
244 SK_MacReturnKey = 36,
245 SK_MacDeleteKey = 51,
246 SK_MacEndKey = 119,
247 SK_MacLeftKey = 123,
248 SK_MacRightKey = 124,
249 SK_MacDownKey = 125,
250 SK_MacUpKey = 126,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000251
bsalomon@google.com2858b312012-04-02 20:44:38 +0000252 SK_Mac0Key = 0x52,
253 SK_Mac1Key = 0x53,
254 SK_Mac2Key = 0x54,
255 SK_Mac3Key = 0x55,
256 SK_Mac4Key = 0x56,
257 SK_Mac5Key = 0x57,
258 SK_Mac6Key = 0x58,
259 SK_Mac7Key = 0x59,
260 SK_Mac8Key = 0x5b,
261 SK_Mac9Key = 0x5c
262};
rmistry@google.comd6176b02012-08-23 18:14:13 +0000263
bsalomon@google.com2858b312012-04-02 20:44:38 +0000264static SkKey raw2key(uint32_t raw)
265{
266 static const struct {
267 uint32_t fRaw;
268 SkKey fKey;
269 } gKeys[] = {
270 { SK_MacUpKey, kUp_SkKey },
271 { SK_MacDownKey, kDown_SkKey },
272 { SK_MacLeftKey, kLeft_SkKey },
273 { SK_MacRightKey, kRight_SkKey },
274 { SK_MacReturnKey, kOK_SkKey },
275 { SK_MacDeleteKey, kBack_SkKey },
276 { SK_MacEndKey, kEnd_SkKey },
277 { SK_Mac0Key, k0_SkKey },
278 { SK_Mac1Key, k1_SkKey },
279 { SK_Mac2Key, k2_SkKey },
280 { SK_Mac3Key, k3_SkKey },
281 { SK_Mac4Key, k4_SkKey },
282 { SK_Mac5Key, k5_SkKey },
283 { SK_Mac6Key, k6_SkKey },
284 { SK_Mac7Key, k7_SkKey },
285 { SK_Mac8Key, k8_SkKey },
286 { SK_Mac9Key, k9_SkKey }
287 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000288
bsalomon@google.com2858b312012-04-02 20:44:38 +0000289 for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
290 if (gKeys[i].fRaw == raw)
291 return gKeys[i].fKey;
292 return kNONE_SkKey;
293}
294
295///////////////////////////////////////////////////////////////////////////////////////
296
297void SkEvent::SignalNonEmptyQueue()
298{
299 post_skwinevent();
300 //SkDebugf("signal nonempty\n");
301}
302
303static UINT_PTR gTimer;
304
305VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
306{
307 SkEvent::ServiceQueueTimer();
308 //SkDebugf("timer task fired\n");
309}
310
311void SkEvent::SignalQueueTimer(SkMSec delay)
312{
313 if (gTimer)
314 {
315 KillTimer(NULL, gTimer);
316 gTimer = NULL;
317 }
318 if (delay)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000319 {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000320 gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
321 //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
322 }
323}
324
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000325#if SK_SUPPORT_GPU
bsalomon@google.com11959252012-04-06 20:13:38 +0000326HGLRC create_gl(HWND hwnd, int msaaSampleCount) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000327
328 HDC dc = GetDC(hwnd);
329
330 SkWGLExtensions extensions;
331 if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
332 return NULL;
333 }
334
335 HDC prevDC = wglGetCurrentDC();
336 HGLRC prevGLRC = wglGetCurrentContext();
337 PIXELFORMATDESCRIPTOR pfd;
338
339 int format = 0;
340
bsalomon@google.com11959252012-04-06 20:13:38 +0000341 static const GLint iAttrs[] = {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000342 SK_WGL_DRAW_TO_WINDOW, TRUE,
343 SK_WGL_DOUBLE_BUFFER, TRUE,
344 SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,
345 SK_WGL_SUPPORT_OPENGL, TRUE,
346 SK_WGL_COLOR_BITS, 24,
347 SK_WGL_ALPHA_BITS, 8,
348 SK_WGL_STENCIL_BITS, 8,
bsalomon@google.com11959252012-04-06 20:13:38 +0000349 0, 0
bsalomon@google.com2858b312012-04-02 20:44:38 +0000350 };
351
bsalomon@google.com11959252012-04-06 20:13:38 +0000352 GLfloat fAttrs[] = {0, 0};
353
354 if (msaaSampleCount > 0 &&
355 extensions.hasExtension(dc, "WGL_ARB_multisample")) {
356 static const int kIAttrsCount = SK_ARRAY_COUNT(iAttrs);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000357 GLint msaaIAttrs[kIAttrsCount + 6];
bsalomon@google.com11959252012-04-06 20:13:38 +0000358 memcpy(msaaIAttrs, iAttrs, sizeof(GLint) * kIAttrsCount);
359 SkASSERT(0 == msaaIAttrs[kIAttrsCount - 2] &&
360 0 == msaaIAttrs[kIAttrsCount - 1]);
361 msaaIAttrs[kIAttrsCount - 2] = SK_WGL_SAMPLE_BUFFERS;
362 msaaIAttrs[kIAttrsCount - 1] = TRUE;
363 msaaIAttrs[kIAttrsCount + 0] = SK_WGL_SAMPLES;
364 msaaIAttrs[kIAttrsCount + 1] = msaaSampleCount;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000365 if (extensions.hasExtension(dc, "WGL_NV_multisample_coverage")) {
366 msaaIAttrs[kIAttrsCount + 2] = SK_WGL_COLOR_SAMPLES;
367 // We want the fewest number of color samples possible.
368 // Passing 0 gives only the formats where all samples are color
369 // samples.
370 msaaIAttrs[kIAttrsCount + 3] = 1;
371 msaaIAttrs[kIAttrsCount + 4] = 0;
372 msaaIAttrs[kIAttrsCount + 5] = 0;
373 } else {
374 msaaIAttrs[kIAttrsCount + 2] = 0;
375 msaaIAttrs[kIAttrsCount + 3] = 0;
376 }
bsalomon@google.com11959252012-04-06 20:13:38 +0000377 GLuint num;
378 int formats[64];
379 extensions.choosePixelFormat(dc, msaaIAttrs, fAttrs, 64, formats, &num);
380 num = min(num,64);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000381 int formatToTry = extensions.selectFormat(formats,
382 num,
383 dc,
384 msaaSampleCount);
385 DescribePixelFormat(dc, formatToTry, sizeof(pfd), &pfd);
386 if (SetPixelFormat(dc, formatToTry, &pfd)) {
387 format = formatToTry;
bsalomon@google.com2858b312012-04-02 20:44:38 +0000388 }
389 }
390
391 if (0 == format) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000392 GLuint num;
bsalomon@google.com11959252012-04-06 20:13:38 +0000393 extensions.choosePixelFormat(dc, iAttrs, fAttrs, 1, &format, &num);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000394 DescribePixelFormat(dc, format, sizeof(pfd), &pfd);
395 BOOL set = SetPixelFormat(dc, format, &pfd);
396 SkASSERT(TRUE == set);
397 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000398
bsalomon@google.comb12dc382013-03-04 14:29:01 +0000399 HGLRC glrc = NULL;
400#if 0 // Change to 1 to attempt to create a core profile GL context of version 4.3 or lower
401 if (extensions.hasExtension(dc, "WGL_ARB_create_context")) {
402 static const GLint kCoreGLVersions[] = {
403 4, 3,
404 4, 2,
405 4, 1,
406 4, 0,
407 3, 3,
408 3, 2,
409 };
410 GLint coreProfileAttribs[] = {
411 SK_WGL_CONTEXT_MAJOR_VERSION, -1,
412 SK_WGL_CONTEXT_MINOR_VERSION, -1,
413 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT,
414 0,
415 };
416 for (int v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) {
417 coreProfileAttribs[1] = kCoreGLVersions[2 * v];
418 coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1];
419 glrc = extensions.createContextAttribs(dc, NULL, coreProfileAttribs);
420 if (NULL != glrc) {
421 break;
422 }
423 }
424 }
425#endif
426
427 if (NULL == glrc) {
428 glrc = wglCreateContext(dc);
429 }
bsalomon@google.com2858b312012-04-02 20:44:38 +0000430 SkASSERT(glrc);
431
432 wglMakeCurrent(prevDC, prevGLRC);
433 return glrc;
434}
435
bsalomon@google.com11959252012-04-06 20:13:38 +0000436bool SkOSWindow::attachGL(int msaaSampleCount) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000437 if (NULL == fHGLRC) {
bsalomon@google.com11959252012-04-06 20:13:38 +0000438 fHGLRC = create_gl((HWND)fHWND, msaaSampleCount);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000439 if (NULL == fHGLRC) {
440 return false;
441 }
442 glClearStencil(0);
443 glClearColor(0, 0, 0, 0);
444 glStencilMask(0xffffffff);
445 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
446 }
447 if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
448 glViewport(0, 0, SkScalarRound(this->width()),
449 SkScalarRound(this->height()));
450 return true;
451 }
452 return false;
453}
454
455void SkOSWindow::detachGL() {
456 wglMakeCurrent(GetDC((HWND)fHWND), 0);
457 wglDeleteContext((HGLRC)fHGLRC);
458 fHGLRC = NULL;
459}
460
461void SkOSWindow::presentGL() {
462 glFlush();
463 SwapBuffers(GetDC((HWND)fHWND));
464}
465
466#if SK_ANGLE
bsalomon@google.com11959252012-04-06 20:13:38 +0000467bool create_ANGLE(EGLNativeWindowType hWnd,
468 int msaaSampleCount,
469 EGLDisplay* eglDisplay,
470 EGLContext* eglContext,
471 EGLSurface* eglSurface) {
472 static const EGLint contextAttribs[] = {
473 EGL_CONTEXT_CLIENT_VERSION, 2,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000474 EGL_NONE, EGL_NONE
bsalomon@google.com2858b312012-04-02 20:44:38 +0000475 };
bsalomon@google.com11959252012-04-06 20:13:38 +0000476 static const EGLint configAttribList[] = {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000477 EGL_RED_SIZE, 8,
478 EGL_GREEN_SIZE, 8,
479 EGL_BLUE_SIZE, 8,
480 EGL_ALPHA_SIZE, 8,
481 EGL_DEPTH_SIZE, 8,
482 EGL_STENCIL_SIZE, 8,
483 EGL_NONE
484 };
bsalomon@google.com11959252012-04-06 20:13:38 +0000485 static const EGLint surfaceAttribList[] = {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000486 EGL_NONE, EGL_NONE
487 };
488
489 EGLDisplay display = eglGetDisplay(GetDC(hWnd));
490 if (display == EGL_NO_DISPLAY ) {
491 return false;
492 }
493
494 // Initialize EGL
495 EGLint majorVersion, minorVersion;
496 if (!eglInitialize(display, &majorVersion, &minorVersion)) {
497 return false;
498 }
499
500 EGLint numConfigs;
501 if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {
502 return false;
503 }
504
505 // Choose config
506 EGLConfig config;
bsalomon@google.com11959252012-04-06 20:13:38 +0000507 bool foundConfig = false;
508 if (msaaSampleCount) {
509 static const int kConfigAttribListCnt =
510 SK_ARRAY_COUNT(configAttribList);
511 EGLint msaaConfigAttribList[kConfigAttribListCnt + 4];
512 memcpy(msaaConfigAttribList,
513 configAttribList,
514 sizeof(configAttribList));
515 SkASSERT(EGL_NONE == msaaConfigAttribList[kConfigAttribListCnt - 1]);
516 msaaConfigAttribList[kConfigAttribListCnt - 1] = EGL_SAMPLE_BUFFERS;
517 msaaConfigAttribList[kConfigAttribListCnt + 0] = 1;
518 msaaConfigAttribList[kConfigAttribListCnt + 1] = EGL_SAMPLES;
519 msaaConfigAttribList[kConfigAttribListCnt + 2] = msaaSampleCount;
520 msaaConfigAttribList[kConfigAttribListCnt + 3] = EGL_NONE;
521 if (eglChooseConfig(display, configAttribList,
522 &config, 1, &numConfigs)) {
523 SkASSERT(numConfigs > 0);
524 foundConfig = true;
525 }
526 }
527 if (!foundConfig) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000528 if (!eglChooseConfig(display, configAttribList,
bsalomon@google.com11959252012-04-06 20:13:38 +0000529 &config, 1, &numConfigs)) {
530 return false;
531 }
bsalomon@google.com2858b312012-04-02 20:44:38 +0000532 }
533
534 // Create a surface
rmistry@google.comd6176b02012-08-23 18:14:13 +0000535 EGLSurface surface = eglCreateWindowSurface(display, config,
536 (EGLNativeWindowType)hWnd,
bsalomon@google.com2858b312012-04-02 20:44:38 +0000537 surfaceAttribList);
538 if (surface == EGL_NO_SURFACE) {
539 return false;
540 }
541
542 // Create a GL context
rmistry@google.comd6176b02012-08-23 18:14:13 +0000543 EGLContext context = eglCreateContext(display, config,
bsalomon@google.com2858b312012-04-02 20:44:38 +0000544 EGL_NO_CONTEXT,
545 contextAttribs );
546 if (context == EGL_NO_CONTEXT ) {
547 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000548 }
549
bsalomon@google.com2858b312012-04-02 20:44:38 +0000550 // Make the context current
551 if (!eglMakeCurrent(display, surface, surface, context)) {
552 return false;
553 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000554
bsalomon@google.com2858b312012-04-02 20:44:38 +0000555 *eglDisplay = display;
556 *eglContext = context;
557 *eglSurface = surface;
558 return true;
559}
560
bsalomon@google.com11959252012-04-06 20:13:38 +0000561bool SkOSWindow::attachANGLE(int msaaSampleCount) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000562 if (EGL_NO_DISPLAY == fDisplay) {
bsalomon@google.com11959252012-04-06 20:13:38 +0000563 bool bResult = create_ANGLE((HWND)fHWND,
564 msaaSampleCount,
565 &fDisplay,
566 &fContext,
567 &fSurface);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000568 if (false == bResult) {
569 return false;
570 }
bsalomon@google.com82502e22013-01-24 20:47:18 +0000571 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000572
573 if (intf) {
borenet@google.com0dd5ceb2012-08-28 15:15:49 +0000574 ANGLE_GL_CALL(intf, ClearStencil(0));
575 ANGLE_GL_CALL(intf, ClearColor(0, 0, 0, 0));
576 ANGLE_GL_CALL(intf, StencilMask(0xffffffff));
577 ANGLE_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT |GL_COLOR_BUFFER_BIT));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000578 }
579 }
580 if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
bsalomon@google.com82502e22013-01-24 20:47:18 +0000581 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000582
583 if (intf ) {
borenet@google.com0dd5ceb2012-08-28 15:15:49 +0000584 ANGLE_GL_CALL(intf, Viewport(0, 0, SkScalarRound(this->width()),
bsalomon@google.com2858b312012-04-02 20:44:38 +0000585 SkScalarRound(this->height())));
586 }
587 return true;
588 }
589 return false;
590}
591
592void SkOSWindow::detachANGLE() {
593 eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
594
595 eglDestroyContext(fDisplay, fContext);
596 fContext = EGL_NO_CONTEXT;
597
598 eglDestroySurface(fDisplay, fSurface);
599 fSurface = EGL_NO_SURFACE;
600
601 eglTerminate(fDisplay);
602 fDisplay = EGL_NO_DISPLAY;
603}
604
605void SkOSWindow::presentANGLE() {
bsalomon@google.com82502e22013-01-24 20:47:18 +0000606 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000607
608 if (intf) {
borenet@google.com0dd5ceb2012-08-28 15:15:49 +0000609 ANGLE_GL_CALL(intf, Flush());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000610 }
611
612 eglSwapBuffers(fDisplay, fSurface);
613}
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000614#endif // SK_ANGLE
615#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000616
bsalomon@google.com2858b312012-04-02 20:44:38 +0000617// return true on success
bsalomon@google.com11959252012-04-06 20:13:38 +0000618bool SkOSWindow::attach(SkBackEndTypes attachType, int msaaSampleCount) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000619
620 // attach doubles as "windowResize" so we need to allo
621 // already bound states to pass through again
622 // TODO: split out the resize functionality
623// SkASSERT(kNone_BackEndType == fAttached);
624 bool result = true;
625
626 switch (attachType) {
627 case kNone_BackEndType:
628 // nothing to do
rmistry@google.comd6176b02012-08-23 18:14:13 +0000629 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000630#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000631 case kNativeGL_BackEndType:
bsalomon@google.com11959252012-04-06 20:13:38 +0000632 result = attachGL(msaaSampleCount);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000633 break;
634#if SK_ANGLE
635 case kANGLE_BackEndType:
bsalomon@google.com11959252012-04-06 20:13:38 +0000636 result = attachANGLE(msaaSampleCount);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000637 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000638#endif // SK_ANGLE
639#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000640 default:
641 SkASSERT(false);
642 result = false;
643 break;
644 }
645
646 if (result) {
647 fAttached = attachType;
648 }
649
650 return result;
651}
652
653void SkOSWindow::detach() {
654 switch (fAttached) {
655 case kNone_BackEndType:
656 // nothing to do
rmistry@google.comd6176b02012-08-23 18:14:13 +0000657 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000658#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000659 case kNativeGL_BackEndType:
660 detachGL();
661 break;
662#if SK_ANGLE
663 case kANGLE_BackEndType:
664 detachANGLE();
665 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000666#endif // SK_ANGLE
667#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000668 default:
669 SkASSERT(false);
670 break;
671 }
672 fAttached = kNone_BackEndType;
673}
674
675void SkOSWindow::present() {
676 switch (fAttached) {
677 case kNone_BackEndType:
678 // nothing to do
rmistry@google.comd6176b02012-08-23 18:14:13 +0000679 return;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000680#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000681 case kNativeGL_BackEndType:
682 presentGL();
683 break;
684#if SK_ANGLE
685 case kANGLE_BackEndType:
686 presentANGLE();
687 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000688#endif // SK_ANGLE
689#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000690 default:
691 SkASSERT(false);
692 break;
693 }
694}
695
696#endif