blob: b0bb76ca19cc05071a108a6902cce64b5e4fee2e [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>
djsollen082a4622014-11-14 07:21:29 -080014#include "win/SkWGL.h"
bsalomon@google.com2858b312012-04-02 20:44:38 +000015#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
bsalomon42380172015-02-23 08:57:23 -080024#include "gl/angle/SkANGLEGLContext.h"
bsalomon@google.com2858b312012-04-02 20:44:38 +000025#include "gl/GrGLInterface.h"
bsalomon@google.com2858b312012-04-02 20:44:38 +000026#include "GLES2/gl2.h"
borenet@google.com0dd5ceb2012-08-28 15:15:49 +000027
28#define ANGLE_GL_CALL(IFACE, X) \
29 do { \
commit-bot@chromium.orgc72425a2014-01-21 16:09:18 +000030 (IFACE)->fFunctions.f##X; \
borenet@google.com0dd5ceb2012-08-28 15:15:49 +000031 } while (false)
32
bsalomon@google.com2858b312012-04-02 20:44:38 +000033#endif
34
bsalomon@google.com2858b312012-04-02 20:44:38 +000035#define WM_EVENT_CALLBACK (WM_USER+0)
36
bsalomon1e7951f2015-06-16 07:04:43 -070037void post_skwinevent(HWND hwnd)
bsalomon@google.com2858b312012-04-02 20:44:38 +000038{
bsalomon1e7951f2015-06-16 07:04:43 -070039 PostMessage(hwnd, WM_EVENT_CALLBACK, 0, 0);
bsalomon@google.com2858b312012-04-02 20:44:38 +000040}
41
bsalomon1e7951f2015-06-16 07:04:43 -070042SkTHashMap<void*, SkOSWindow*> SkOSWindow::gHwndToOSWindowMap;
43
44SkOSWindow::SkOSWindow(const void* winInit) {
45 fWinInit = *(const WindowInit*)winInit;
46
47 fHWND = CreateWindow(fWinInit.fClass, NULL, WS_OVERLAPPEDWINDOW,
48 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, fWinInit.fInstance, NULL);
49 gHwndToOSWindowMap.set(fHWND, this);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000050#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +000051#if SK_ANGLE
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000052 fDisplay = EGL_NO_DISPLAY;
53 fContext = EGL_NO_CONTEXT;
54 fSurface = EGL_NO_SURFACE;
bsalomon@google.com2858b312012-04-02 20:44:38 +000055#endif
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000056 fHGLRC = NULL;
57#endif
58 fAttached = kNone_BackEndType;
bsalomon1e7951f2015-06-16 07:04:43 -070059 fFullscreen = false;
bsalomon@google.com2858b312012-04-02 20:44:38 +000060}
61
62SkOSWindow::~SkOSWindow() {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000063#if SK_SUPPORT_GPU
bsalomon49f085d2014-09-05 13:34:00 -070064 if (fHGLRC) {
bsalomon@google.com2858b312012-04-02 20:44:38 +000065 wglDeleteContext((HGLRC)fHGLRC);
66 }
67#if SK_ANGLE
68 if (EGL_NO_CONTEXT != fContext) {
69 eglDestroyContext(fDisplay, fContext);
70 fContext = EGL_NO_CONTEXT;
71 }
72
73 if (EGL_NO_SURFACE != fSurface) {
74 eglDestroySurface(fDisplay, fSurface);
75 fSurface = EGL_NO_SURFACE;
76 }
77
78 if (EGL_NO_DISPLAY != fDisplay) {
79 eglTerminate(fDisplay);
80 fDisplay = EGL_NO_DISPLAY;
81 }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000082#endif // SK_ANGLE
83#endif // SK_SUPPORT_GPU
bsalomon85ab5512015-06-16 12:47:25 -070084 this->closeWindow();
bsalomon@google.com2858b312012-04-02 20:44:38 +000085}
86
87static SkKey winToskKey(WPARAM vk) {
88 static const struct {
89 WPARAM fVK;
90 SkKey fKey;
91 } gPair[] = {
92 { VK_BACK, kBack_SkKey },
93 { VK_CLEAR, kBack_SkKey },
94 { VK_RETURN, kOK_SkKey },
95 { VK_UP, kUp_SkKey },
96 { VK_DOWN, kDown_SkKey },
97 { VK_LEFT, kLeft_SkKey },
98 { VK_RIGHT, kRight_SkKey }
99 };
100 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
101 if (gPair[i].fVK == vk) {
102 return gPair[i].fKey;
103 }
104 }
105 return kNONE_SkKey;
106}
107
reed@google.com4d5c26d2013-01-08 16:17:50 +0000108static unsigned getModifiers(UINT message) {
109 return 0; // TODO
110}
111
bsalomon@google.com2858b312012-04-02 20:44:38 +0000112bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
113 switch (message) {
114 case WM_KEYDOWN: {
115 SkKey key = winToskKey(wParam);
116 if (kNONE_SkKey != key) {
117 this->handleKey(key);
118 return true;
119 }
120 } break;
121 case WM_KEYUP: {
122 SkKey key = winToskKey(wParam);
123 if (kNONE_SkKey != key) {
124 this->handleKeyUp(key);
125 return true;
126 }
127 } break;
128 case WM_UNICHAR:
robertphillips@google.com8b169312013-10-15 17:47:36 +0000129 this->handleChar((SkUnichar) wParam);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000130 return true;
bsalomon@google.com2858b312012-04-02 20:44:38 +0000131 case WM_CHAR: {
132 this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
133 return true;
134 } break;
robertphillips@google.coma4662862013-11-21 14:24:16 +0000135 case WM_SIZE: {
136 INT width = LOWORD(lParam);
137 INT height = HIWORD(lParam);
138 this->resize(width, height);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000139 break;
robertphillips@google.coma4662862013-11-21 14:24:16 +0000140 }
bsalomon@google.com2858b312012-04-02 20:44:38 +0000141 case WM_PAINT: {
142 PAINTSTRUCT ps;
143 HDC hdc = BeginPaint(hWnd, &ps);
144 this->doPaint(hdc);
145 EndPaint(hWnd, &ps);
146 return true;
147 } break;
148
rmistry@google.comd6176b02012-08-23 18:14:13 +0000149 case WM_LBUTTONDOWN:
reed@google.com4d5c26d2013-01-08 16:17:50 +0000150 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
reed@google.com72708fa2013-01-08 16:22:44 +0000151 Click::kDown_State, NULL, getModifiers(message));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000152 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000153
bsalomon@google.com2858b312012-04-02 20:44:38 +0000154 case WM_MOUSEMOVE:
reed@google.com4d5c26d2013-01-08 16:17:50 +0000155 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
reed@google.com72708fa2013-01-08 16:22:44 +0000156 Click::kMoved_State, NULL, getModifiers(message));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000157 return true;
158
159 case WM_LBUTTONUP:
reed@google.com4d5c26d2013-01-08 16:17:50 +0000160 this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
reed@google.com72708fa2013-01-08 16:22:44 +0000161 Click::kUp_State, NULL, getModifiers(message));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000162 return true;
163
164 case WM_EVENT_CALLBACK:
165 if (SkEvent::ProcessEvent()) {
bsalomon1e7951f2015-06-16 07:04:43 -0700166 post_skwinevent(hWnd);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000167 }
168 return true;
169 }
170 return false;
171}
172
173void SkOSWindow::doPaint(void* ctx) {
174 this->update(NULL);
175
176 if (kNone_BackEndType == fAttached)
177 {
178 HDC hdc = (HDC)ctx;
179 const SkBitmap& bitmap = this->getBitmap();
180
181 BITMAPINFO bmi;
182 memset(&bmi, 0, sizeof(bmi));
183 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
184 bmi.bmiHeader.biWidth = bitmap.width();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000185 bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
bsalomon@google.com2858b312012-04-02 20:44:38 +0000186 bmi.bmiHeader.biPlanes = 1;
187 bmi.bmiHeader.biBitCount = 32;
188 bmi.bmiHeader.biCompression = BI_RGB;
189 bmi.bmiHeader.biSizeImage = 0;
190
rmistry@google.comd6176b02012-08-23 18:14:13 +0000191 //
192 // Do the SetDIBitsToDevice.
193 //
bsalomon@google.com2858b312012-04-02 20:44:38 +0000194 // TODO(wjmaclean):
195 // Fix this call to handle SkBitmaps that have rowBytes != width,
196 // i.e. may have padding at the end of lines. The SkASSERT below
197 // may be ignored by builds, and the only obviously safe option
198 // seems to be to copy the bitmap to a temporary (contiguous)
199 // buffer before passing to SetDIBitsToDevice().
200 SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
201 bitmap.lockPixels();
bsalomon@google.comb58a6392013-03-21 20:29:05 +0000202 int ret = SetDIBitsToDevice(hdc,
bsalomon@google.com2858b312012-04-02 20:44:38 +0000203 0, 0,
204 bitmap.width(), bitmap.height(),
205 0, 0,
206 0, bitmap.height(),
207 bitmap.getPixels(),
208 &bmi,
209 DIB_RGB_COLORS);
bsalomon@google.comb58a6392013-03-21 20:29:05 +0000210 (void)ret; // we're ignoring potential failures for now.
bsalomon@google.com2858b312012-04-02 20:44:38 +0000211 bitmap.unlockPixels();
212 }
213}
214
bsalomon@google.com2858b312012-04-02 20:44:38 +0000215void SkOSWindow::updateSize()
216{
217 RECT r;
bsalomon1e7951f2015-06-16 07:04:43 -0700218 GetWindowRect((HWND)fHWND, &r);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000219 this->resize(r.right - r.left, r.bottom - r.top);
220}
bsalomon@google.com2858b312012-04-02 20:44:38 +0000221
222void SkOSWindow::onHandleInval(const SkIRect& r) {
bsalomone0ef4a72015-06-15 12:49:55 -0700223 RECT rect;
224 rect.left = r.fLeft;
225 rect.top = r.fTop;
226 rect.right = r.fRight;
227 rect.bottom = r.fBottom;
228 InvalidateRect((HWND)fHWND, &rect, FALSE);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000229}
230
231void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
232{
233}
234
235void SkOSWindow::onSetTitle(const char title[]){
236 SetWindowTextA((HWND)fHWND, title);
237}
238
239enum {
240 SK_MacReturnKey = 36,
241 SK_MacDeleteKey = 51,
242 SK_MacEndKey = 119,
243 SK_MacLeftKey = 123,
244 SK_MacRightKey = 124,
245 SK_MacDownKey = 125,
246 SK_MacUpKey = 126,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000247
bsalomon@google.com2858b312012-04-02 20:44:38 +0000248 SK_Mac0Key = 0x52,
249 SK_Mac1Key = 0x53,
250 SK_Mac2Key = 0x54,
251 SK_Mac3Key = 0x55,
252 SK_Mac4Key = 0x56,
253 SK_Mac5Key = 0x57,
254 SK_Mac6Key = 0x58,
255 SK_Mac7Key = 0x59,
256 SK_Mac8Key = 0x5b,
257 SK_Mac9Key = 0x5c
258};
rmistry@google.comd6176b02012-08-23 18:14:13 +0000259
bsalomon@google.com2858b312012-04-02 20:44:38 +0000260static SkKey raw2key(uint32_t raw)
261{
262 static const struct {
263 uint32_t fRaw;
264 SkKey fKey;
265 } gKeys[] = {
266 { SK_MacUpKey, kUp_SkKey },
267 { SK_MacDownKey, kDown_SkKey },
268 { SK_MacLeftKey, kLeft_SkKey },
269 { SK_MacRightKey, kRight_SkKey },
270 { SK_MacReturnKey, kOK_SkKey },
271 { SK_MacDeleteKey, kBack_SkKey },
272 { SK_MacEndKey, kEnd_SkKey },
273 { SK_Mac0Key, k0_SkKey },
274 { SK_Mac1Key, k1_SkKey },
275 { SK_Mac2Key, k2_SkKey },
276 { SK_Mac3Key, k3_SkKey },
277 { SK_Mac4Key, k4_SkKey },
278 { SK_Mac5Key, k5_SkKey },
279 { SK_Mac6Key, k6_SkKey },
280 { SK_Mac7Key, k7_SkKey },
281 { SK_Mac8Key, k8_SkKey },
282 { SK_Mac9Key, k9_SkKey }
283 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000284
bsalomon@google.com2858b312012-04-02 20:44:38 +0000285 for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
286 if (gKeys[i].fRaw == raw)
287 return gKeys[i].fKey;
288 return kNONE_SkKey;
289}
290
291///////////////////////////////////////////////////////////////////////////////////////
292
293void SkEvent::SignalNonEmptyQueue()
294{
bsalomon1e7951f2015-06-16 07:04:43 -0700295 SkOSWindow::ForAllWindows([](void* hWND, SkOSWindow**) {
296 post_skwinevent((HWND)hWND);
297 });
bsalomon@google.com2858b312012-04-02 20:44:38 +0000298}
299
300static UINT_PTR gTimer;
301
302VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
303{
304 SkEvent::ServiceQueueTimer();
305 //SkDebugf("timer task fired\n");
306}
307
308void SkEvent::SignalQueueTimer(SkMSec delay)
309{
310 if (gTimer)
311 {
312 KillTimer(NULL, gTimer);
313 gTimer = NULL;
314 }
315 if (delay)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000316 {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000317 gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
318 //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
319 }
320}
321
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000322#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000323
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000324bool SkOSWindow::attachGL(int msaaSampleCount, AttachmentInfo* info) {
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000325 HDC dc = GetDC((HWND)fHWND);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000326 if (NULL == fHGLRC) {
kkinnunen80549fc2014-06-30 06:36:31 -0700327 fHGLRC = SkCreateWGLContext(dc, msaaSampleCount,
328 kGLPreferCompatibilityProfile_SkWGLContextRequest);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000329 if (NULL == fHGLRC) {
330 return false;
331 }
332 glClearStencil(0);
333 glClearColor(0, 0, 0, 0);
334 glStencilMask(0xffffffff);
335 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
336 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000337 if (wglMakeCurrent(dc, (HGLRC)fHGLRC)) {
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000338 // use DescribePixelFormat to get the stencil bit depth.
339 int pixelFormat = GetPixelFormat(dc);
340 PIXELFORMATDESCRIPTOR pfd;
341 DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
342 info->fStencilBits = pfd.cStencilBits;
343
344 // Get sample count if the MSAA WGL extension is present
345 SkWGLExtensions extensions;
346 if (extensions.hasExtension(dc, "WGL_ARB_multisample")) {
347 static const int kSampleCountAttr = SK_WGL_SAMPLES;
348 extensions.getPixelFormatAttribiv(dc,
349 pixelFormat,
350 0,
351 1,
352 &kSampleCountAttr,
353 &info->fSampleCount);
354 } else {
355 info->fSampleCount = 0;
356 }
357
reed@google.come1ca7052013-12-17 19:22:07 +0000358 glViewport(0, 0,
359 SkScalarRoundToInt(this->width()),
360 SkScalarRoundToInt(this->height()));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000361 return true;
362 }
363 return false;
364}
365
366void SkOSWindow::detachGL() {
367 wglMakeCurrent(GetDC((HWND)fHWND), 0);
368 wglDeleteContext((HGLRC)fHGLRC);
369 fHGLRC = NULL;
370}
371
372void SkOSWindow::presentGL() {
bungeman@google.comf44957e2013-03-12 17:27:10 +0000373 HDC dc = GetDC((HWND)fHWND);
374 SwapBuffers(dc);
375 ReleaseDC((HWND)fHWND, dc);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000376}
377
378#if SK_ANGLE
bsalomon42380172015-02-23 08:57:23 -0800379
bsalomon@google.com11959252012-04-06 20:13:38 +0000380bool create_ANGLE(EGLNativeWindowType hWnd,
381 int msaaSampleCount,
382 EGLDisplay* eglDisplay,
383 EGLContext* eglContext,
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000384 EGLSurface* eglSurface,
385 EGLConfig* eglConfig) {
bsalomon@google.com11959252012-04-06 20:13:38 +0000386 static const EGLint contextAttribs[] = {
387 EGL_CONTEXT_CLIENT_VERSION, 2,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000388 EGL_NONE, EGL_NONE
bsalomon@google.com2858b312012-04-02 20:44:38 +0000389 };
bsalomon@google.com11959252012-04-06 20:13:38 +0000390 static const EGLint configAttribList[] = {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000391 EGL_RED_SIZE, 8,
392 EGL_GREEN_SIZE, 8,
393 EGL_BLUE_SIZE, 8,
394 EGL_ALPHA_SIZE, 8,
395 EGL_DEPTH_SIZE, 8,
396 EGL_STENCIL_SIZE, 8,
397 EGL_NONE
398 };
bsalomon@google.com11959252012-04-06 20:13:38 +0000399 static const EGLint surfaceAttribList[] = {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000400 EGL_NONE, EGL_NONE
401 };
402
bsalomon42380172015-02-23 08:57:23 -0800403 EGLDisplay display = SkANGLEGLContext::GetD3DEGLDisplay(GetDC(hWnd));
404
405 if (EGL_NO_DISPLAY == display) {
406 SkDebugf("Could not create ANGLE egl display!\n");
407 return false;
bsalomon@google.com2858b312012-04-02 20:44:38 +0000408 }
409
410 // Initialize EGL
411 EGLint majorVersion, minorVersion;
412 if (!eglInitialize(display, &majorVersion, &minorVersion)) {
413 return false;
414 }
415
416 EGLint numConfigs;
417 if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {
418 return false;
419 }
420
421 // Choose config
bsalomon@google.com11959252012-04-06 20:13:38 +0000422 bool foundConfig = false;
423 if (msaaSampleCount) {
424 static const int kConfigAttribListCnt =
425 SK_ARRAY_COUNT(configAttribList);
426 EGLint msaaConfigAttribList[kConfigAttribListCnt + 4];
427 memcpy(msaaConfigAttribList,
428 configAttribList,
429 sizeof(configAttribList));
430 SkASSERT(EGL_NONE == msaaConfigAttribList[kConfigAttribListCnt - 1]);
431 msaaConfigAttribList[kConfigAttribListCnt - 1] = EGL_SAMPLE_BUFFERS;
432 msaaConfigAttribList[kConfigAttribListCnt + 0] = 1;
433 msaaConfigAttribList[kConfigAttribListCnt + 1] = EGL_SAMPLES;
434 msaaConfigAttribList[kConfigAttribListCnt + 2] = msaaSampleCount;
435 msaaConfigAttribList[kConfigAttribListCnt + 3] = EGL_NONE;
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000436 if (eglChooseConfig(display, configAttribList, eglConfig, 1, &numConfigs)) {
bsalomon@google.com11959252012-04-06 20:13:38 +0000437 SkASSERT(numConfigs > 0);
438 foundConfig = true;
439 }
440 }
441 if (!foundConfig) {
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000442 if (!eglChooseConfig(display, configAttribList, eglConfig, 1, &numConfigs)) {
bsalomon@google.com11959252012-04-06 20:13:38 +0000443 return false;
444 }
bsalomon@google.com2858b312012-04-02 20:44:38 +0000445 }
446
447 // Create a surface
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000448 EGLSurface surface = eglCreateWindowSurface(display, *eglConfig,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000449 (EGLNativeWindowType)hWnd,
bsalomon@google.com2858b312012-04-02 20:44:38 +0000450 surfaceAttribList);
451 if (surface == EGL_NO_SURFACE) {
452 return false;
453 }
454
455 // Create a GL context
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000456 EGLContext context = eglCreateContext(display, *eglConfig,
bsalomon@google.com2858b312012-04-02 20:44:38 +0000457 EGL_NO_CONTEXT,
458 contextAttribs );
459 if (context == EGL_NO_CONTEXT ) {
460 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000461 }
462
bsalomon@google.com2858b312012-04-02 20:44:38 +0000463 // Make the context current
464 if (!eglMakeCurrent(display, surface, surface, context)) {
465 return false;
466 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000467
bsalomon@google.com2858b312012-04-02 20:44:38 +0000468 *eglDisplay = display;
469 *eglContext = context;
470 *eglSurface = surface;
471 return true;
472}
473
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000474bool SkOSWindow::attachANGLE(int msaaSampleCount, AttachmentInfo* info) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000475 if (EGL_NO_DISPLAY == fDisplay) {
bsalomon@google.com11959252012-04-06 20:13:38 +0000476 bool bResult = create_ANGLE((HWND)fHWND,
477 msaaSampleCount,
478 &fDisplay,
479 &fContext,
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000480 &fSurface,
481 &fConfig);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000482 if (false == bResult) {
483 return false;
484 }
bsalomon@google.com82502e22013-01-24 20:47:18 +0000485 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000486
487 if (intf) {
borenet@google.com0dd5ceb2012-08-28 15:15:49 +0000488 ANGLE_GL_CALL(intf, ClearStencil(0));
489 ANGLE_GL_CALL(intf, ClearColor(0, 0, 0, 0));
490 ANGLE_GL_CALL(intf, StencilMask(0xffffffff));
491 ANGLE_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT |GL_COLOR_BUFFER_BIT));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000492 }
493 }
494 if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000495 eglGetConfigAttrib(fDisplay, fConfig, EGL_STENCIL_SIZE, &info->fStencilBits);
496 eglGetConfigAttrib(fDisplay, fConfig, EGL_SAMPLES, &info->fSampleCount);
497
bsalomon@google.com82502e22013-01-24 20:47:18 +0000498 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000499
500 if (intf ) {
reed@google.come1ca7052013-12-17 19:22:07 +0000501 ANGLE_GL_CALL(intf, Viewport(0, 0,
502 SkScalarRoundToInt(this->width()),
503 SkScalarRoundToInt(this->height())));
bsalomon@google.com2858b312012-04-02 20:44:38 +0000504 }
505 return true;
506 }
507 return false;
508}
509
510void SkOSWindow::detachANGLE() {
511 eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
512
513 eglDestroyContext(fDisplay, fContext);
514 fContext = EGL_NO_CONTEXT;
515
516 eglDestroySurface(fDisplay, fSurface);
517 fSurface = EGL_NO_SURFACE;
518
519 eglTerminate(fDisplay);
520 fDisplay = EGL_NO_DISPLAY;
521}
522
523void SkOSWindow::presentANGLE() {
bsalomon@google.com82502e22013-01-24 20:47:18 +0000524 SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000525
526 if (intf) {
borenet@google.com0dd5ceb2012-08-28 15:15:49 +0000527 ANGLE_GL_CALL(intf, Flush());
bsalomon@google.com2858b312012-04-02 20:44:38 +0000528 }
529
530 eglSwapBuffers(fDisplay, fSurface);
531}
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000532#endif // SK_ANGLE
533#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000534
bsalomon@google.com2858b312012-04-02 20:44:38 +0000535// return true on success
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000536bool SkOSWindow::attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo* info) {
bsalomon@google.com2858b312012-04-02 20:44:38 +0000537
538 // attach doubles as "windowResize" so we need to allo
539 // already bound states to pass through again
540 // TODO: split out the resize functionality
541// SkASSERT(kNone_BackEndType == fAttached);
542 bool result = true;
543
544 switch (attachType) {
545 case kNone_BackEndType:
546 // nothing to do
rmistry@google.comd6176b02012-08-23 18:14:13 +0000547 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000548#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000549 case kNativeGL_BackEndType:
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000550 result = attachGL(msaaSampleCount, info);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000551 break;
552#if SK_ANGLE
553 case kANGLE_BackEndType:
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000554 result = attachANGLE(msaaSampleCount, info);
bsalomon@google.com2858b312012-04-02 20:44:38 +0000555 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000556#endif // SK_ANGLE
557#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000558 default:
559 SkASSERT(false);
560 result = false;
561 break;
562 }
563
564 if (result) {
565 fAttached = attachType;
566 }
567
568 return result;
569}
570
571void SkOSWindow::detach() {
572 switch (fAttached) {
573 case kNone_BackEndType:
574 // nothing to do
rmistry@google.comd6176b02012-08-23 18:14:13 +0000575 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000576#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000577 case kNativeGL_BackEndType:
578 detachGL();
579 break;
580#if SK_ANGLE
581 case kANGLE_BackEndType:
582 detachANGLE();
583 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000584#endif // SK_ANGLE
585#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000586 default:
587 SkASSERT(false);
588 break;
589 }
590 fAttached = kNone_BackEndType;
591}
592
593void SkOSWindow::present() {
594 switch (fAttached) {
595 case kNone_BackEndType:
596 // nothing to do
rmistry@google.comd6176b02012-08-23 18:14:13 +0000597 return;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000598#if SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000599 case kNativeGL_BackEndType:
600 presentGL();
601 break;
602#if SK_ANGLE
603 case kANGLE_BackEndType:
604 presentANGLE();
605 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000606#endif // SK_ANGLE
607#endif // SK_SUPPORT_GPU
bsalomon@google.com2858b312012-04-02 20:44:38 +0000608 default:
609 SkASSERT(false);
610 break;
611 }
612}
613
bsalomon85ab5512015-06-16 12:47:25 -0700614bool SkOSWindow::makeFullscreen() {
615 if (fFullscreen) {
616 return true;
bsalomon1e7951f2015-06-16 07:04:43 -0700617 }
618 if (fHGLRC) {
619 this->detachGL();
620 }
621 // This is hacked together from various sources on the web. It can certainly be improved and be
622 // made more robust.
bsalomon1e7951f2015-06-16 07:04:43 -0700623
bsalomon85ab5512015-06-16 12:47:25 -0700624 // Save current window/resolution information. We do this in case we ever implement switching
625 // back to windowed mode.
626 fSavedWindowState.fZoomed = SkToBool(IsZoomed((HWND)fHWND));
627 if (fSavedWindowState.fZoomed) {
628 SendMessage((HWND)fHWND, WM_SYSCOMMAND, SC_RESTORE, 0);
bsalomon1e7951f2015-06-16 07:04:43 -0700629 }
bsalomon85ab5512015-06-16 12:47:25 -0700630 fSavedWindowState.fStyle = GetWindowLong((HWND)fHWND, GWL_STYLE);
631 fSavedWindowState.fExStyle = GetWindowLong((HWND)fHWND, GWL_EXSTYLE);
632 GetWindowRect((HWND)fHWND, &fSavedWindowState.fRect);
633 DEVMODE currScreenSettings;
634 memset(&currScreenSettings,0,sizeof(currScreenSettings));
635 currScreenSettings.dmSize = sizeof(currScreenSettings);
636 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &currScreenSettings);
637 fSavedWindowState.fScreenWidth = currScreenSettings.dmPelsWidth;
638 fSavedWindowState.fScreenHeight = currScreenSettings.dmPelsHeight;
639 fSavedWindowState.fScreenBits = currScreenSettings.dmBitsPerPel;
640 fSavedWindowState.fHWND = fHWND;
641
642 // Try different sizes to find an allowed setting? Use ChangeDisplaySettingsEx?
643 static const int kWidth = 1280;
644 static const int kHeight = 1024;
645 DEVMODE newScreenSettings;
646 memset(&newScreenSettings, 0, sizeof(newScreenSettings));
647 newScreenSettings.dmSize = sizeof(newScreenSettings);
648 newScreenSettings.dmPelsWidth = kWidth;
649 newScreenSettings.dmPelsHeight = kHeight;
650 newScreenSettings.dmBitsPerPel = 32;
651 newScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
652 if (ChangeDisplaySettings(&newScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
653 return false;
654 }
655 RECT WindowRect;
656 WindowRect.left = 0;
657 WindowRect.right = kWidth;
658 WindowRect.top = 0;
659 WindowRect.bottom = kHeight;
660 ShowCursor(FALSE);
661 AdjustWindowRectEx(&WindowRect, WS_POPUP, FALSE, WS_EX_APPWINDOW);
662 HWND fsHWND = CreateWindowEx(
663 WS_EX_APPWINDOW,
664 fWinInit.fClass,
665 NULL,
666 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
667 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top,
668 NULL,
669 NULL,
670 fWinInit.fInstance,
671 NULL
672 );
673 if (!fsHWND) {
674 return false;
675 }
676 // Hide the old window and set the entry in the global mapping for this SkOSWindow to the
677 // new HWND.
678 ShowWindow((HWND)fHWND, SW_HIDE);
679 gHwndToOSWindowMap.remove(fHWND);
680 fHWND = fsHWND;
681 gHwndToOSWindowMap.set(fHWND, this);
682 this->updateSize();
683
684 fFullscreen = true;
685 return true;
bsalomon1e7951f2015-06-16 07:04:43 -0700686}
687
688void SkOSWindow::setVsync(bool enable) {
689 SkWGLExtensions wgl;
690 wgl.swapInterval(enable ? 1 : 0);
691}
692
693void SkOSWindow::closeWindow() {
bsalomon1e7951f2015-06-16 07:04:43 -0700694 DestroyWindow((HWND)fHWND);
bsalomon85ab5512015-06-16 12:47:25 -0700695 if (fFullscreen) {
696 DestroyWindow((HWND)fSavedWindowState.fHWND);
697 }
698 gHwndToOSWindowMap.remove(fHWND);
bsalomon1e7951f2015-06-16 07:04:43 -0700699}
bsalomon@google.com2858b312012-04-02 20:44:38 +0000700#endif