1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "EglOsApi.h"
17
18 #include "aemu/base/synchronization/Lock.h"
19 #include "aemu/base/SharedLibrary.h"
20
21 #include "CoreProfileConfigs.h"
22 #include "host-common/logging.h"
23 #include "GLcommon/GLLibrary.h"
24
25 #include <windows.h>
26 #include <wingdi.h>
27
28 #include <GLES/glplatform.h>
29 #include <GL/gl.h>
30 #include <GL/wglext.h>
31
32 #include <EGL/eglext.h>
33
34 #include <algorithm>
35 #include <memory>
36 #include <unordered_map>
37 #include <unordered_set>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41
42 #define IS_TRUE(a) \
43 do { if (!(a)) return NULL; } while (0)
44
45 #define EXIT_IF_FALSE(a) \
46 do { if (!(a)) return; } while (0)
47
48 #define DEBUG 0
49 #if DEBUG
50 #define D(...) fprintf(stderr, __VA_ARGS__)
51 #else
52 #define D(...) ((void)0)
53 #endif
54
55 #define WGL_ERR(...) do { \
56 fprintf(stderr, __VA_ARGS__); \
57 GL_LOG(__VA_ARGS__); \
58 } while(0) \
59
60 // TODO: Replace with latency tracker.
61 #define PROFILE_SLOW(tag)
62
63 namespace {
64
65 using android::base::SharedLibrary;
66 typedef GlLibrary::GlFunctionPointer GlFunctionPointer;
67
68 // Returns true if an extension is include in a given extension list.
69 // |extension| is an GL extension name.
70 // |extensionList| is a space-separated list of supported extension.
71 // Returns true if the extension is supported, false otherwise.
supportsExtension(const char * extension,const char * extensionList)72 bool supportsExtension(const char* extension, const char* extensionList) {
73 size_t extensionLen = ::strlen(extension);
74 const char* list = extensionList;
75 for (;;) {
76 const char* p = const_cast<const char*>(::strstr(list, extension));
77 if (!p) {
78 return false;
79 }
80 // Check that the extension appears as a single word in the list
81 // i.e. that it is wrapped by either spaces or the start/end of
82 // the list.
83 if ((p == extensionList || p[-1] == ' ') &&
84 (p[extensionLen] == '\0' || p[extensionLen] == ' ')) {
85 return true;
86 }
87 // otherwise, skip over the current position to find something else.
88 p += extensionLen;
89 }
90 }
91
92 /////
93 ///// W G L D I S P A T C H T A B L E S
94 /////
95
96 // A technical note to explain what is going here, trust me, it's important.
97 //
98 // I. Library-dependent symbol resolution:
99 // ---------------------------------------
100 //
101 // The code here can deal with two kinds of OpenGL Windows libraries: the
102 // system-provided opengl32.dll, or alternate software renderers like Mesa
103 // (e.g. mesa_opengl32.dll).
104 //
105 // When using the system library, pixel-format related functions, like
106 // SetPixelFormat(), are provided by gdi32.dll, and _not_ opengl32.dll
107 // (even though they are documented as part of the Windows GL API).
108 //
109 // These functions must _not_ be used when using alternative renderers.
110 // Instead, these provide _undocumented_ alternatives with the 'wgl' prefix,
111 // as in wglSetPixelFormat(), wglDescribePixelFormat(), etc... which
112 // implement the same calling conventions.
113 //
114 // For more details about this, see 5.190 of the Windows OpenGL FAQ at:
115 // https://www.opengl.org/archives/resources/faq/technical/mswindows.htm
116 //
117 // Another good source of information on this topic:
118 // http://stackoverflow.com/questions/20645706/why-are-functions-duplicated-between-opengl32-dll-and-gdi32-dll
119 //
120 // In practice, it means that the code here should resolve 'naked' symbols
121 // (e.g. 'GetPixelFormat()) when using the system library, and 'prefixed' ones
122 // (e.g. 'wglGetPixelFormat()) otherwise.
123 //
124
125 // List of WGL functions of interest to probe with GetProcAddress()
126 #define LIST_WGL_FUNCTIONS(X) \
127 X(HGLRC, wglCreateContext, (HDC hdc)) \
128 X(BOOL, wglDeleteContext, (HGLRC hglrc)) \
129 X(BOOL, wglMakeCurrent, (HDC hdc, HGLRC hglrc)) \
130 X(BOOL, wglShareLists, (HGLRC hglrc1, HGLRC hglrc2)) \
131 X(HGLRC, wglGetCurrentContext, (void)) \
132 X(HDC, wglGetCurrentDC, (void)) \
133 X(GlFunctionPointer, wglGetProcAddress, (const char* functionName)) \
134
135 // List of WGL functions exported by GDI32 that must be used when using
136 // the system's opengl32.dll only, i.e. not with a software renderer like
137 // Mesa. For more information, see 5.190 at:
138 // And also:
139 #define LIST_GDI32_FUNCTIONS(X) \
140 X(int, ChoosePixelFormat, (HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)) \
141 X(BOOL, SetPixelFormat, (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR* pfd)) \
142 X(int, GetPixelFormat, (HDC hdc)) \
143 X(int, DescribePixelFormat, (HDC hdc, int iPixelFormat, UINT nbytes, LPPIXELFORMATDESCRIPTOR ppfd)) \
144 X(BOOL, SwapBuffers, (HDC hdc)) \
145
146 // Declare a structure containing pointers to all functions listed above,
147 // and a way to initialize them.
148 struct WglBaseDispatch {
149 // declare all function pointers, followed by a dummy member used
150 // to terminate the constructor's initialization list properly.
151 #define DECLARE_WGL_POINTER(return_type, function_name, signature) \
152 return_type (GL_APIENTRY* function_name) signature;
153 LIST_WGL_FUNCTIONS(DECLARE_WGL_POINTER)
154 LIST_GDI32_FUNCTIONS(DECLARE_WGL_POINTER)
155 SharedLibrary* mLib = nullptr;
156 bool mIsSystemLib = false;
157
158 // Default Constructor
WglBaseDispatch__anon7bb9b2c40111::WglBaseDispatch159 WglBaseDispatch() :
160 #define INIT_WGL_POINTER(return_type, function_name, signature) \
161 function_name(),
162 LIST_WGL_FUNCTIONS(INIT_WGL_POINTER)
163 LIST_GDI32_FUNCTIONS(INIT_WGL_POINTER)
164 mIsSystemLib(false) {}
165
166 // Copy constructor
WglBaseDispatch__anon7bb9b2c40111::WglBaseDispatch167 WglBaseDispatch(const WglBaseDispatch& other) :
168 #define COPY_WGL_POINTER(return_type, function_name, signature) \
169 function_name(other.function_name),
170 LIST_WGL_FUNCTIONS(COPY_WGL_POINTER)
171 LIST_GDI32_FUNCTIONS(COPY_WGL_POINTER)
172 mLib(other.mLib),
173 mIsSystemLib(other.mIsSystemLib) {}
174
175 // Initialize the dispatch table from shared library |glLib|, which
176 // must point to either the system or non-system opengl32.dll
177 // implementation. If |systemLib| is true, this considers the library
178 // to be the system one, and will try to find the GDI32 functions
179 // like GetPixelFormat() directly. If |systemLib| is false, this will
180 // try to load the wglXXX variants (e.g. for Mesa). See technical note
181 // above for details.
182 // Returns true on success, false otherwise (i.e. if one of the
183 // required symbols could not be loaded).
init__anon7bb9b2c40111::WglBaseDispatch184 bool init(SharedLibrary* glLib, bool systemLib) {
185 bool result = true;
186
187 mLib = glLib;
188 mIsSystemLib = systemLib;
189
190 #define LOAD_WGL_POINTER(return_type, function_name, signature) \
191 this->function_name = reinterpret_cast< \
192 return_type (GL_APIENTRY*) signature>( \
193 glLib->findSymbol(#function_name)); \
194 if (!this->function_name) { \
195 WGL_ERR("%s: Could not find %s in GL library\n", __FUNCTION__, \
196 #function_name); \
197 result = false; \
198 }
199
200 #define LOAD_WGL_GDI32_POINTER(return_type, function_name, signature) \
201 this->function_name = reinterpret_cast< \
202 return_type (GL_APIENTRY*) signature>( \
203 GetProcAddress(gdi32, #function_name)); \
204 if (!this->function_name) { \
205 WGL_ERR("%s: Could not find %s in GDI32 library\n", __FUNCTION__, \
206 #function_name); \
207 result = false; \
208 }
209
210 #define LOAD_WGL_INNER_POINTER(return_type, function_name, signature) \
211 this->function_name = reinterpret_cast< \
212 return_type (GL_APIENTRY*) signature>( \
213 glLib->findSymbol("wgl" #function_name)); \
214 if (!this->function_name) { \
215 WGL_ERR("%s: Could not find %s in GL library\n", __FUNCTION__, \
216 "wgl" #function_name); \
217 result = false; \
218 }
219
220 LIST_WGL_FUNCTIONS(LOAD_WGL_POINTER)
221 if (systemLib) {
222 HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
223 LIST_GDI32_FUNCTIONS(LOAD_WGL_GDI32_POINTER)
224 } else {
225 LIST_GDI32_FUNCTIONS(LOAD_WGL_INNER_POINTER)
226 }
227 return result;
228 }
229
230 // Find a function, using wglGetProcAddress() first, and if that doesn't
231 // work, SharedLibrary::findSymbol().
232 // |functionName| is the function name.
233 // |glLib| is the GL library to probe with findSymbol() is needed.
findFunction__anon7bb9b2c40111::WglBaseDispatch234 GlFunctionPointer findFunction(const char* functionName) const {
235 GlFunctionPointer result = this->wglGetProcAddress(functionName);
236 if (!result && mLib) {
237 result = mLib->findSymbol(functionName);
238 }
239 return result;
240 }
241 };
242
243 // Used internally by createDummyWindow().
dummyWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)244 LRESULT CALLBACK dummyWndProc(HWND hwnd,
245 UINT uMsg,
246 WPARAM wParam,
247 LPARAM lParam) {
248 return DefWindowProcA(hwnd, uMsg, wParam, lParam);
249 }
250
251 // Create a new dummy window, and return its handle.
252 // Note that the window is 1x1 pixels and not visible, but
253 // it can be used to create a device context and associated
254 // OpenGL rendering context. Return NULL on failure.
createDummyWindow()255 HWND createDummyWindow() {
256 WNDCLASSA wcx;
257 // wcx.cbSize = sizeof(wcx); // size of structure
258 wcx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; // redraw if size changes
259 wcx.lpfnWndProc = dummyWndProc; // points to window procedure
260 wcx.cbClsExtra = 0; // no extra class memory
261 wcx.cbWndExtra = sizeof(void*); // save extra window memory, to store VasWindow instance
262 wcx.hInstance = NULL; // handle to instance
263 wcx.hIcon = NULL; // predefined app. icon
264 wcx.hCursor = NULL;
265 wcx.hbrBackground = NULL; // no background brush
266 wcx.lpszMenuName = NULL; // name of menu resource
267 wcx.lpszClassName = "DummyWin"; // name of window class
268
269 RegisterClassA(&wcx);
270
271 HWND hwnd = CreateWindowExA(WS_EX_CLIENTEDGE,
272 "DummyWin",
273 "Dummy",
274 WS_POPUP,
275 0,
276 0,
277 1,
278 1,
279 NULL,
280 NULL,
281 0,0);
282 return hwnd;
283 }
284
285 // List of functions defined by the WGL_ARB_extensions_string extension.
286 #define LIST_extensions_string_FUNCTIONS(X) \
287 X(const char*, wglGetExtensionsString, (HDC hdc))
288
289 // List of functions defined by the WGL_ARB_pixel_format extension.
290 #define LIST_pixel_format_FUNCTIONS(X) \
291 X(BOOL, wglGetPixelFormatAttribiv, (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int* piValues)) \
292 X(BOOL, wglGetPixelFormatAttribfv, (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT* pfValues)) \
293 X(BOOL, wglChoosePixelFormat, (HDC, const int* piAttribList, const FLOAT* pfAttribList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats)) \
294
295 // List of functions defined by the WGL_ARB_make_current_read extension.
296 #define LIST_make_current_read_FUNCTIONS(X) \
297 X(BOOL, wglMakeContextCurrent, (HDC hDrawDC, HDC hReadDC, HGLRC hglrc)) \
298 X(HDC, wglGetCurrentReadDC, (void)) \
299
300 // List of functions defined by the WGL_ARB_pbuffer extension.
301 #define LIST_pbuffer_FUNCTIONS(X) \
302 X(HPBUFFERARB, wglCreatePbuffer, (HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList)) \
303 X(HDC, wglGetPbufferDC, (HPBUFFERARB hPbuffer)) \
304 X(int, wglReleasePbufferDC, (HPBUFFERARB hPbuffer, HDC hdc)) \
305 X(BOOL, wglDestroyPbuffer, (HPBUFFERARB hPbuffer)) \
306
307 // List of functions defined by WGL_ARB_create_context
308 #define LIST_create_context_FUNCTIONS(X) \
309 X(HGLRC, wglCreateContextAttribs, (HDC hDC, HGLRC hshareContext, const int *attribList)) \
310
311 // List of functions define by WGL_EXT_swap_control
312 #define LIST_swap_control_FUNCTIONS(X) \
313 X(void, wglSwapInterval, (int)) \
314 X(int, wglGetSwapInterval, (void)) \
315
316 #define LIST_WGL_EXTENSIONS_FUNCTIONS(X) \
317 LIST_pixel_format_FUNCTIONS(X) \
318 LIST_make_current_read_FUNCTIONS(X) \
319 LIST_pbuffer_FUNCTIONS(X) \
320 LIST_create_context_FUNCTIONS(X) \
321 LIST_swap_control_FUNCTIONS(X) \
322
323 // A structure used to hold pointers to WGL extension functions.
324 struct WglExtensionsDispatch : public WglBaseDispatch {
325 public:
326 LIST_WGL_EXTENSIONS_FUNCTIONS(DECLARE_WGL_POINTER)
327 int dummy;
328
329 // Default constructor
WglExtensionsDispatch__anon7bb9b2c40111::WglExtensionsDispatch330 explicit WglExtensionsDispatch(const WglBaseDispatch& baseDispatch) :
331 WglBaseDispatch(baseDispatch),
332 LIST_WGL_EXTENSIONS_FUNCTIONS(INIT_WGL_POINTER)
333 dummy(0) {}
334
335 // Initialization
init__anon7bb9b2c40111::WglExtensionsDispatch336 bool init(HDC hdc) {
337 // Base initialization happens first.
338 bool result = WglBaseDispatch::init(mLib, mIsSystemLib);
339 if (!result) {
340 return false;
341 }
342
343 // Find the list of extensions.
344 typedef const char* (GL_APIENTRY* GetExtensionsStringFunc)(HDC hdc);
345
346 const char* extensionList = nullptr;
347 GetExtensionsStringFunc wglGetExtensionsString =
348 reinterpret_cast<GetExtensionsStringFunc>(
349 this->findFunction("wglGetExtensionsStringARB"));
350
351 bool foundArb = wglGetExtensionsString != nullptr;
352
353 if (wglGetExtensionsString) {
354 extensionList = wglGetExtensionsString(hdc);
355 }
356
357 bool extensionListArbNull = extensionList == nullptr;
358 bool extensionListArbEmpty = !extensionListArbNull && !strcmp(extensionList, "");
359
360 bool foundExt = false;
361 bool extensionListExtNull = false;
362 bool extensionListExtEmpty = false;
363
364 // wglGetExtensionsStringARB failed, try wglGetExtensionsStringEXT.
365 if (!extensionList || !strcmp(extensionList, "")) {
366 wglGetExtensionsString =
367 reinterpret_cast<GetExtensionsStringFunc>(
368 this->findFunction("wglGetExtensionsStringEXT"));
369
370 foundExt = wglGetExtensionsString != nullptr;
371
372 if (wglGetExtensionsString) {
373 extensionList = wglGetExtensionsString(hdc);
374 }
375 }
376
377 extensionListExtNull = extensionList == nullptr;
378 extensionListExtEmpty = !extensionListExtNull && !strcmp(extensionList, "");
379
380 // Both failed, suicide.
381 if (!extensionList || !strcmp(extensionList, "")) {
382 bool isRemoteSession = GetSystemMetrics(SM_REMOTESESSION);
383
384 WGL_ERR(
385 "%s: Could not find wglGetExtensionsString! "
386 "arbFound %d listarbNull/empty %d %d "
387 "extFound %d extNull/empty %d %d remote %d\n",
388 __FUNCTION__,
389 foundArb,
390 extensionListArbNull,
391 extensionListArbEmpty,
392 foundExt,
393 extensionListExtNull,
394 extensionListExtEmpty,
395 isRemoteSession);
396
397 return false;
398 }
399
400 // Load each extension individually.
401 #define LOAD_WGL_EXTENSION_FUNCTION(return_type, function_name, signature) \
402 this->function_name = reinterpret_cast< \
403 return_type (GL_APIENTRY*) signature>( \
404 this->findFunction(#function_name "ARB")); \
405 if (!this->function_name) { \
406 this->function_name = reinterpret_cast< \
407 return_type (GL_APIENTRY*) signature>( \
408 this->findFunction(#function_name "EXT")); \
409 } \
410 if (!this->function_name) { \
411 WGL_ERR("ERROR: %s: Missing extension function %s\n", __FUNCTION__, \
412 #function_name); \
413 result = false; \
414 }
415
416 #define LOAD_WGL_EXTENSION(extension) \
417 if (supportsExtension("WGL_ARB_" #extension, extensionList) || \
418 supportsExtension("WGL_EXT_" #extension, extensionList)) { \
419 LIST_##extension##_FUNCTIONS(LOAD_WGL_EXTENSION_FUNCTION) \
420 } else { \
421 WGL_ERR("WARNING: %s: Missing WGL extension %s\n", __FUNCTION__, #extension); \
422 }
423
424 LOAD_WGL_EXTENSION(pixel_format)
425 LOAD_WGL_EXTENSION(make_current_read)
426 LOAD_WGL_EXTENSION(pbuffer)
427 LOAD_WGL_EXTENSION(create_context)
428 LOAD_WGL_EXTENSION(swap_control)
429
430 // Done.
431 return result;
432 }
433
434 private:
435 WglExtensionsDispatch(); // no default constructor.
436 };
437
initExtensionsDispatch(const WglBaseDispatch * dispatch)438 const WglExtensionsDispatch* initExtensionsDispatch(
439 const WglBaseDispatch* dispatch) {
440 HWND hwnd = createDummyWindow();
441 HDC hdc = GetDC(hwnd);
442 if (!hwnd || !hdc){
443 int err = GetLastError();
444 WGL_ERR("error while getting DC: 0x%x\n", err);
445 return NULL;
446 }
447 PIXELFORMATDESCRIPTOR pfd = {
448 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
449 1, // version number
450 PFD_DRAW_TO_WINDOW | // support window
451 PFD_SUPPORT_OPENGL | // support OpenGL
452 PFD_DOUBLEBUFFER, // double buffered
453 PFD_TYPE_RGBA, // RGBA type
454 32, // 32-bit color depth
455 0, 0, 0, 0, 0, 0, // color bits ignored
456 0, // no alpha buffer
457 0, // shift bit ignored
458 0, // no accumulation buffer
459 0, 0, 0, 0, // accum bits ignored
460 24, // 24-bit z-buffer
461 0, // no stencil buffer
462 0, // no auxiliary buffer
463 PFD_MAIN_PLANE, // main layer
464 0, // reserved
465 0, 0, 0 // layer masks ignored
466 };
467
468 int iPixelFormat = dispatch->ChoosePixelFormat(hdc, &pfd);
469 if (iPixelFormat <= 0) {
470 int err = GetLastError();
471 WGL_ERR("error while choosing pixel format 0x%x\n", err);
472 return NULL;
473 }
474 if (!dispatch->SetPixelFormat(hdc, iPixelFormat, &pfd)) {
475 int err = GetLastError();
476 WGL_ERR("error while setting pixel format 0x%x\n", err);
477 return NULL;
478 }
479
480 int err;
481 HGLRC ctx = dispatch->wglCreateContext(hdc);
482 if (!ctx) {
483 err = GetLastError();
484 WGL_ERR("error while creating dummy context: 0x%x\n", err);
485 }
486 if (!dispatch->wglMakeCurrent(hdc, ctx)) {
487 err = GetLastError();
488 WGL_ERR("error while making dummy context current: 0x%x\n", err);
489 }
490
491 WglExtensionsDispatch* result = new WglExtensionsDispatch(*dispatch);
492 result->init(hdc);
493
494 dispatch->wglMakeCurrent(hdc, NULL);
495 dispatch->wglDeleteContext(ctx);
496 ReleaseDC(hwnd, hdc);
497 DestroyWindow(hwnd);
498
499 return result;
500 }
501
502 class WinPixelFormat : public EglOS::PixelFormat {
503 public:
WinPixelFormat(const PIXELFORMATDESCRIPTOR * desc,int configId)504 WinPixelFormat(const PIXELFORMATDESCRIPTOR* desc, int configId)
505 : mDesc(*desc), mConfigId(configId) {}
506
clone()507 EglOS::PixelFormat* clone() {
508 return new WinPixelFormat(&mDesc, mConfigId);
509 }
510
desc() const511 const PIXELFORMATDESCRIPTOR* desc() const { return &mDesc; }
configId() const512 const int configId() const { return mConfigId; }
513
from(const EglOS::PixelFormat * f)514 static const WinPixelFormat* from(const EglOS::PixelFormat* f) {
515 return static_cast<const WinPixelFormat*>(f);
516 }
517
518 private:
519 WinPixelFormat(const WinPixelFormat& other) = delete;
520
521 PIXELFORMATDESCRIPTOR mDesc = {};
522 int mConfigId = 0;
523 };
524
525 class WinSurface : public EglOS::Surface {
526 public:
WinSurface(HWND wnd,const WglExtensionsDispatch * dispatch)527 explicit WinSurface(HWND wnd, const WglExtensionsDispatch* dispatch) :
528 Surface(WINDOW),
529 m_hwnd(wnd),
530 m_hdc(GetDC(wnd)),
531 m_dispatch(dispatch) {}
532
WinSurface(HPBUFFERARB pb,const EglOS::PixelFormat * pixelFormat,const WglExtensionsDispatch * dispatch)533 explicit WinSurface(HPBUFFERARB pb, const EglOS::PixelFormat* pixelFormat, const WglExtensionsDispatch* dispatch) :
534 Surface(PBUFFER),
535 m_pb(pb),
536 m_pixelFormat(pixelFormat),
537 m_dispatch(dispatch) {
538 refreshDC();
539 }
540
releaseDC()541 bool releaseDC() {
542 if (m_dcReleased) return true;
543
544 bool res = false;
545 if (m_dispatch->wglReleasePbufferDC) {
546 res = m_dispatch->wglReleasePbufferDC(m_pb, m_hdc);
547 m_hdc = 0;
548 m_dcReleased = true;
549 }
550 return res;
551 }
552
refreshDC()553 bool refreshDC() {
554 if (!m_dcReleased) releaseDC();
555 if (m_dispatch->wglGetPbufferDC) {
556 m_hdc = m_dispatch->wglGetPbufferDC(m_pb);
557 }
558
559 if (!m_hdc) return false;
560
561 m_dcReleased = false;
562
563 return true;
564 }
565
~WinSurface()566 ~WinSurface() {
567 if (type() == WINDOW) {
568 ReleaseDC(m_hwnd, m_hdc);
569 }
570 }
571
onMakeCurrent()572 void onMakeCurrent() {
573 if (m_everMadeCurrent) return;
574 if (m_dispatch->wglSwapInterval) {
575 m_dispatch->wglSwapInterval(0);
576 }
577 m_everMadeCurrent = true;
578 }
579
getHwnd() const580 HWND getHwnd() const { return m_hwnd; }
getDC() const581 HDC getDC() const { return m_hdc; }
getPbuffer() const582 HPBUFFERARB getPbuffer() const { return m_pb; }
getPixelFormat() const583 const EglOS::PixelFormat* getPixelFormat() const { return m_pixelFormat; }
584
from(EglOS::Surface * s)585 static WinSurface* from(EglOS::Surface* s) {
586 return static_cast<WinSurface*>(s);
587 }
588
589 private:
590 bool m_everMadeCurrent = false;
591 bool m_dcReleased = true;
592 HWND m_hwnd = nullptr;
593 HPBUFFERARB m_pb = nullptr;
594 HDC m_hdc = nullptr;
595 const EglOS::PixelFormat* m_pixelFormat = nullptr;
596 const WglExtensionsDispatch* m_dispatch = nullptr;
597 };
598
599 static android::base::StaticLock sGlobalLock;
600
601 class WinContext : public EglOS::Context {
602 public:
WinContext(const WglExtensionsDispatch * dispatch,HGLRC ctx)603 explicit WinContext(const WglExtensionsDispatch* dispatch, HGLRC ctx) :
604 mDispatch(dispatch), mCtx(ctx) {}
605
~WinContext()606 virtual ~WinContext() {
607 android::base::AutoLock lock(sGlobalLock);
608 if (!mDispatch->wglDeleteContext(mCtx)) {
609 WGL_ERR("error deleting WGL context! error 0x%x\n",
610 (unsigned)GetLastError());
611 }
612 }
613
context() const614 HGLRC context() const { return mCtx; }
615
from(const EglOS::Context * c)616 static HGLRC from(const EglOS::Context* c) {
617 if (!c) return nullptr;
618 return static_cast<const WinContext*>(c)->context();
619 }
620
621 private:
622 const WglExtensionsDispatch* mDispatch = nullptr;
623 HGLRC mCtx = nullptr;
624 };
625
626 // A helper class used to deal with a vexing limitation of the WGL API.
627 // The documentation for SetPixelFormat() states the following:
628 //
629 // -- If hdc references a window, calling the SetPixelFormat function also
630 // -- changes the pixel format of the window. Setting the pixel format of a
631 // -- window more than once [...] is not allowed. An application can only set
632 // -- the pixel format of a window one time. Once a window's pixel format is
633 // -- set, it cannot be changed.
634 // --
635 // -- You should select a pixel format in the device context before calling
636 // -- the wglCreateContext function. The wglCreateContext function creates a
637 // -- rendering context for drawing on the device in the selected pixel format
638 // -- of the device context.
639 //
640 // In other words, creating a GL context requires having a unique window and
641 // device context for the corresponding EGLConfig.
642 //
643 // This code deals with this by implementing the followin scheme:
644 //
645 // - For each unique PixelFormat ID (a.k.a. EGLConfig number), provide a way
646 // to create a new hidden 1x1 window, and corresponding HDC.
647 //
648 // - Implement a simple thread-local mapping from PixelFormat IDs to
649 // (HWND, HDC) pairs that are created on demand.
650 //
651 // WinGlobals is the class used to implement this scheme. Usage is the
652 // following:
653 //
654 // - Create a single global instance, passing a WglBaseDispatch pointer
655 // which is required to call its SetPixelFormat() method.
656 //
657 // - Call getDefaultDummyDC() to retrieve a thread-local device context that
658 // can be used to query / probe the list of available pixel formats for the
659 // host window, but not perform rendering.
660 //
661 // - Call getDummyDC() to retrieve a thread-local device context that can be
662 // used to create WGL context objects to render into a specific pixel
663 // format.
664 //
665 // - These devic contexts are thread-local, i.e. they are automatically
666 // reclaimed on thread exit. This also means that the caller should not
667 // call either ReleaseDC() or DeleteDC() on them.
668 //
669 class WinGlobals {
670 public:
671 // Constructor. |dispatch| will be used to call the right version of
672 // ::SetPixelFormat() depending on GPU emulation configuration. See
673 // technical notes above for details.
WinGlobals(const WglBaseDispatch * dispatch)674 explicit WinGlobals(const WglBaseDispatch* dispatch)
675 : mDispatch(dispatch) {}
676
677 // Return a thread-local device context that can be used to list
678 // available pixel formats for the host window. The caller cannot use
679 // this context for drawing though. The context is owned
680 // by this instance and will be automatically reclaimed on thread exit.
getDefaultDummyDC()681 HDC getDefaultDummyDC() {
682 return getInternalDC(nullptr);
683 }
684
getDefaultNontrivialDC()685 HDC getDefaultNontrivialDC() {
686 return mNontrivialDC;
687 }
setNontrivialDC(const WinPixelFormat * format)688 void setNontrivialDC(const WinPixelFormat* format) {
689 mNontrivialDC = getInternalDC(format);
690 }
691
692 // Return a thread-local device context associated with a specific
693 // pixel format. The result is owned by this instance, and is automatically
694 // reclaimed on thread exit. Don't try to call ReleaseDC() on it.
getDummyDC(const WinPixelFormat * format)695 HDC getDummyDC(const WinPixelFormat* format) {
696 return getInternalDC(format);
697 }
698
699 private:
700 // ConfigDC holds a (HWND,HDC) pair to be associated with a given
701 // pixel format ID. This serves as the value type for ConfigMap
702 // declared below. Implemented as a movable type without copy-operations.
703 class ConfigDC {
704 public:
705 // Constructor. This creates a new dummy 1x1 invisible window and
706 // an associated device context. If |format| is not nullptr, then
707 // calls |dispatch->SetPixelFormat()| on the resulting context to
708 // set the window's pixel format.
ConfigDC(const WinPixelFormat * format,const WglBaseDispatch * dispatch)709 ConfigDC(const WinPixelFormat* format,
710 const WglBaseDispatch* dispatch) {
711 mWindow = createDummyWindow();
712 if (mWindow) {
713 mDeviceContext = GetDC(mWindow);
714 if (format) {
715 dispatch->SetPixelFormat(mDeviceContext,
716 format->configId(),
717 format->desc());
718 }
719 }
720 }
721
722 // Destructor.
~ConfigDC()723 ~ConfigDC() {
724 if (mWindow) {
725 ReleaseDC(mWindow, mDeviceContext);
726 DestroyWindow(mWindow);
727 mWindow = nullptr;
728 }
729 }
730
731 // Supports moves - this disables auto-generated copy-constructors.
ConfigDC(ConfigDC && other)732 ConfigDC(ConfigDC&& other)
733 : mWindow(other.mWindow),
734 mDeviceContext(other.mDeviceContext) {
735 other.mWindow = nullptr;
736 }
737
operator =(ConfigDC && other)738 ConfigDC& operator=(ConfigDC&& other) {
739 mWindow = other.mWindow;
740 mDeviceContext = other.mDeviceContext;
741 other.mWindow = nullptr;
742 return *this;
743 }
744
745 // Return device context for this instance.
dc() const746 HDC dc() const { return mDeviceContext; }
747
748 private:
749 HWND mWindow = nullptr;
750 HDC mDeviceContext = nullptr;
751 };
752
753 // Convenience type alias for mapping pixel format IDs, a.k.a. EGLConfig
754 // IDs, to ConfigDC instances.
755 using ConfigMap = std::unordered_map<int, ConfigDC>;
756
757 // Called when a thread terminates to delete the thread-local map
758 // that associates pixel format IDs with ConfigDC instances.
onThreadTermination(void * opaque)759 static void onThreadTermination(void* opaque) {
760 auto map = reinterpret_cast<ConfigMap*>(opaque);
761 delete map;
762 }
763
764 // Helper function used by getDefaultDummyDC() and getDummyDC().
765 //
766 // If |format| is nullptr, return a thread-local device context that can
767 // be used to list all available pixel formats for the host window.
768 //
769 // If |format| is not nullptr, then return a thread-local device context
770 // associated with the corresponding pixel format.
771 //
772 // Both cases will lazily create a 1x1 invisible dummy window which
773 // the device is connected to. All objects are automatically destroyed
774 // on thread exit. Return nullptr on failure.
getInternalDC(const WinPixelFormat * format)775 HDC getInternalDC(const WinPixelFormat* format) {
776 int formatId = format ? format->configId() : 0;
777 static thread_local ConfigMap configMap;
778
779 auto it = configMap.find(formatId);
780 if (it != configMap.end()) {
781 return it->second.dc();
782 }
783
784 ConfigDC newValue(format, mDispatch);
785 HDC result = newValue.dc();
786 configMap.emplace(formatId, std::move(newValue));
787 return result;
788 }
789
790 const WglBaseDispatch* mDispatch = nullptr;
791 HDC mNontrivialDC = nullptr;
792 };
793
initPixelFormat(HDC dc,const WglExtensionsDispatch * dispatch)794 bool initPixelFormat(HDC dc, const WglExtensionsDispatch* dispatch) {
795 if (dispatch->wglChoosePixelFormat) {
796 unsigned int numpf;
797 int iPixelFormat;
798 int i0 = 0;
799 float f0 = 0.0f;
800 return dispatch->wglChoosePixelFormat(
801 dc, &i0, &f0, 1, &iPixelFormat, &numpf);
802 } else {
803 PIXELFORMATDESCRIPTOR pfd = {
804 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
805 1, // version number
806 PFD_DRAW_TO_WINDOW | // support window
807 PFD_SUPPORT_OPENGL | // support OpenGL
808 PFD_DOUBLEBUFFER, // double buffered
809 PFD_TYPE_RGBA, // RGBA type
810 32, // 32-bit color depth
811 0, 0, 0, 0, 0, 0, // color bits ignored
812 0, // no alpha buffer
813 0, // shift bit ignored
814 0, // no accumulation buffer
815 0, 0, 0, 0, // accum bits ignored
816 24, // 24-bit z-buffer
817 0, // no stencil buffer
818 0, // no auxiliary buffer
819 PFD_MAIN_PLANE, // main layer
820 0, // reserved
821 0, 0, 0 // layer masks ignored
822 };
823 return dispatch->ChoosePixelFormat(dc, &pfd);
824 }
825 }
826
pixelFormatToConfig(WinGlobals * globals,const WglExtensionsDispatch * dispatch,int renderableType,const PIXELFORMATDESCRIPTOR * frmt,int index,EglOS::AddConfigCallback * addConfigFunc,void * addConfigOpaque)827 void pixelFormatToConfig(WinGlobals* globals,
828 const WglExtensionsDispatch* dispatch,
829 int renderableType,
830 const PIXELFORMATDESCRIPTOR* frmt,
831 int index,
832 EglOS::AddConfigCallback* addConfigFunc,
833 void* addConfigOpaque) {
834 EglOS::ConfigInfo info;
835 memset(&info, 0, sizeof(info));
836
837 if (frmt->iPixelType != PFD_TYPE_RGBA) {
838 D("%s: Not an RGBA type!\n", __FUNCTION__);
839 return; // other formats are not supported yet
840 }
841 if (!(frmt->dwFlags & PFD_SUPPORT_OPENGL)) {
842 D("%s: No OpenGL support\n", __FUNCTION__);
843 return;
844 }
845 // NOTE: Software renderers don't always support double-buffering.
846 if (dispatch->mIsSystemLib && !(frmt->dwFlags & PFD_DOUBLEBUFFER)) {
847 D("%s: No double-buffer support\n", __FUNCTION__);
848 return;
849 }
850 if ((frmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_NEED_PALETTE)) != 0) {
851 //discard generic pixel formats as well as pallete pixel formats
852 D("%s: Generic format or needs palette\n", __FUNCTION__);
853 return;
854 }
855
856 if (!dispatch->wglGetPixelFormatAttribiv) {
857 D("%s: Missing wglGetPixelFormatAttribiv\n", __FUNCTION__);
858 return;
859 }
860
861 GLint window = 0, pbuffer = 0;
862 HDC dpy = globals->getDefaultDummyDC();
863
864 if (dispatch->mIsSystemLib) {
865 int windowAttrib = WGL_DRAW_TO_WINDOW_ARB;
866 EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribiv(
867 dpy, index, 0, 1, &windowAttrib, &window));
868 }
869 int pbufferAttrib = WGL_DRAW_TO_PBUFFER_ARB;
870 EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribiv(
871 dpy, index, 0, 1, &pbufferAttrib, &pbuffer));
872
873 info.surface_type = 0;
874 if (window) {
875 info.surface_type |= EGL_WINDOW_BIT;
876 }
877 if (pbuffer) {
878 info.surface_type |= EGL_PBUFFER_BIT;
879 }
880 if (!info.surface_type) {
881 D("%s: Missing surface type\n", __FUNCTION__);
882 return;
883 }
884
885 //default values
886 info.native_visual_id = 0;
887 info.native_visual_type = EGL_NONE;
888 info.caveat = EGL_NONE;
889 info.native_renderable = EGL_FALSE;
890 info.renderable_type = renderableType;
891 info.max_pbuffer_width = PBUFFER_MAX_WIDTH;
892 info.max_pbuffer_height = PBUFFER_MAX_HEIGHT;
893 info.max_pbuffer_size = PBUFFER_MAX_PIXELS;
894 info.samples_per_pixel = 0;
895 info.frame_buffer_level = 0;
896
897 GLint transparent;
898 int transparentAttrib = WGL_TRANSPARENT_ARB;
899 EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribiv(
900 dpy, index, 0, 1, &transparentAttrib, &transparent));
901 if (transparent) {
902 info.transparent_type = EGL_TRANSPARENT_RGB;
903 int transparentRedAttrib = WGL_TRANSPARENT_RED_VALUE_ARB;
904 EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribiv(
905 dpy, index, 0, 1, &transparentRedAttrib, &info.trans_red_val));
906 int transparentGreenAttrib = WGL_TRANSPARENT_GREEN_VALUE_ARB;
907 EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribiv(
908 dpy, index, 0, 1, &transparentGreenAttrib,
909 &info.trans_green_val));
910 int transparentBlueAttrib = WGL_TRANSPARENT_RED_VALUE_ARB;
911 EXIT_IF_FALSE(dispatch->wglGetPixelFormatAttribiv(
912 dpy,index, 0, 1, &transparentBlueAttrib, &info.trans_blue_val));
913 } else {
914 info.transparent_type = EGL_NONE;
915 }
916
917 info.red_size = frmt->cRedBits;
918 info.green_size = frmt->cGreenBits;
919 info.blue_size = frmt->cBlueBits;
920 info.alpha_size = frmt->cAlphaBits;
921 info.depth_size = frmt->cDepthBits;
922 info.stencil_size = frmt->cStencilBits;
923
924 info.frmt = new WinPixelFormat(frmt, index);
925
926 if (!globals->getDefaultNontrivialDC() &&
927 info.red_size >= 8) {
928 globals->setNontrivialDC(WinPixelFormat::from(info.frmt));
929 }
930
931 (*addConfigFunc)(addConfigOpaque, &info);
932 }
933
934 class WglDisplay : public EglOS::Display {
935 public:
WglDisplay(const WglExtensionsDispatch * dispatch,WinGlobals * globals)936 WglDisplay(const WglExtensionsDispatch* dispatch,
937 WinGlobals* globals)
938 : mDispatch(dispatch), mGlobals(globals) {}
939
getMaxGlesVersion()940 virtual EglOS::GlesVersion getMaxGlesVersion() {
941 if (!mCoreProfileSupported) {
942 return EglOS::GlesVersion::ES2;
943 }
944
945 return EglOS::calcMaxESVersionFromCoreVersion(
946 mCoreMajorVersion, mCoreMinorVersion);
947 }
948
queryConfigs(int renderableType,EglOS::AddConfigCallback addConfigFunc,void * addConfigOpaque)949 virtual void queryConfigs(int renderableType,
950 EglOS::AddConfigCallback addConfigFunc,
951 void* addConfigOpaque) {
952 HDC dpy = mGlobals->getDefaultDummyDC();
953
954 // wglChoosePixelFormat() needs to be called at least once,
955 // i.e. it seems that the driver needs to initialize itself.
956 // Do it here during initialization.
957 initPixelFormat(dpy, mDispatch);
958
959 // Quering number of formats
960 PIXELFORMATDESCRIPTOR pfd;
961 int maxFormat = mDispatch->DescribePixelFormat(
962 dpy, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
963
964 if (0 == maxFormat) {
965 WGL_ERR("No pixel formats found from wglDescribePixelFormat! "
966 "error: 0x%x\n", static_cast<unsigned int>(GetLastError()));
967 }
968
969 // Inserting rest of formats. Try to map each one to an EGL Config.
970 for (int configId = 1; configId <= maxFormat; configId++) {
971 mDispatch->DescribePixelFormat(
972 dpy, configId, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
973 pixelFormatToConfig(
974 mGlobals,
975 mDispatch,
976 renderableType,
977 &pfd,
978 configId,
979 addConfigFunc,
980 addConfigOpaque);
981 }
982
983 queryCoreProfileSupport();
984
985 if (mDispatch->wglSwapInterval) {
986 mDispatch->wglSwapInterval(0); // use guest SF / HWC instead
987 }
988 }
989
isValidNativeWin(EglOS::Surface * win)990 virtual bool isValidNativeWin(EglOS::Surface* win) {
991 if (!win) {
992 return false;
993 } else {
994 return isValidNativeWin(WinSurface::from(win)->getHwnd());
995 }
996 }
997
isValidNativeWin(EGLNativeWindowType win)998 virtual bool isValidNativeWin(EGLNativeWindowType win) {
999 return IsWindow(win);
1000 }
1001
checkWindowPixelFormatMatch(EGLNativeWindowType win,const EglOS::PixelFormat * pixelFormat,unsigned int * width,unsigned int * height)1002 virtual bool checkWindowPixelFormatMatch(
1003 EGLNativeWindowType win,
1004 const EglOS::PixelFormat* pixelFormat,
1005 unsigned int* width,
1006 unsigned int* height) {
1007 RECT r;
1008 if (!GetClientRect(win, &r)) {
1009 return false;
1010 }
1011 *width = r.right - r.left;
1012 *height = r.bottom - r.top;
1013 HDC dc = GetDC(win);
1014 const WinPixelFormat* format = WinPixelFormat::from(pixelFormat);
1015 bool ret = mDispatch->SetPixelFormat(dc,
1016 format->configId(),
1017 format->desc());
1018 ReleaseDC(win, dc);
1019 return ret;
1020 }
1021
createContext(EGLint profileMask,const EglOS::PixelFormat * pixelFormat,EglOS::Context * sharedContext)1022 virtual std::shared_ptr<EglOS::Context> createContext(
1023 EGLint profileMask,
1024 const EglOS::PixelFormat* pixelFormat,
1025 EglOS::Context* sharedContext) {
1026
1027 android::base::AutoLock lock(sGlobalLock);
1028
1029 const WinPixelFormat* format = WinPixelFormat::from(pixelFormat);
1030 HDC dpy = mGlobals->getDummyDC(format);
1031 if (!dpy) {
1032 return nullptr;
1033 }
1034
1035 bool useCoreProfile =
1036 mCoreProfileSupported &&
1037 (profileMask & EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
1038
1039 HGLRC ctx;
1040 if (useCoreProfile) {
1041 ctx = mDispatch->wglCreateContextAttribs(
1042 dpy, WinContext::from(sharedContext),
1043 mCoreProfileCtxAttribs);
1044 } else {
1045 ctx = mDispatch->wglCreateContext(dpy);
1046 if (ctx && sharedContext) {
1047 if (!mDispatch->wglShareLists(WinContext::from(sharedContext), ctx)) {
1048 mDispatch->wglDeleteContext(ctx);
1049 return NULL;
1050 }
1051 }
1052 }
1053
1054 return std::make_shared<WinContext>(mDispatch, ctx);
1055 }
1056
createPbufferSurface(const EglOS::PixelFormat * pixelFormat,const EglOS::PbufferInfo * info)1057 virtual EglOS::Surface* createPbufferSurface(
1058 const EglOS::PixelFormat* pixelFormat,
1059 const EglOS::PbufferInfo* info) {
1060 android::base::AutoLock lock(sGlobalLock);
1061 (void)info;
1062
1063 bool needPrime = false;
1064
1065 auto& freeElts = mFreePbufs[pixelFormat];
1066
1067 if (freeElts.empty()) {
1068 needPrime = true;
1069 }
1070
1071 if (needPrime) {
1072 // Policy here is based on the behavior of Android UI when opening
1073 // and closing lots of apps, and to avoid frequent pauses to create
1074 // pbuffers. We start by priming with 8 pbuffers, and then double
1075 // the current set of live pbuffers each time. This will then
1076 // require only a few primings (up to ~32 pbuffers) to make it
1077 // unnecessary to create or delete a pbuffer ever again after that.
1078 // Creating many pbuffers in a batch is faster than interrupting
1079 // the process at various times to create them one at a time.
1080 PROFILE_SLOW("createPbufferSurface (slow path)");
1081 int toCreate = std::max((int)mLivePbufs[pixelFormat].size(), kPbufPrimingCount);
1082 for (int i = 0; i < toCreate; i++) {
1083 freeElts.push_back(createPbufferSurfaceImpl(pixelFormat));
1084 }
1085 }
1086
1087 PROFILE_SLOW("createPbufferSurface (fast path)");
1088 EglOS::Surface* surf = freeElts.back();
1089 WinSurface* winSurface = WinSurface::from(surf);
1090 if (!winSurface->refreshDC()) {
1091 // TODO: Figure out why some Intel GPUs can hang flakily if
1092 // we just destroy the pbuffer here.
1093 mDeletePbufs.push_back(surf);
1094 surf = createPbufferSurfaceImpl(pixelFormat);
1095 }
1096 freeElts.pop_back();
1097
1098 mLivePbufs[pixelFormat].insert(surf);
1099
1100 return surf;
1101 }
1102
releasePbuffer(EglOS::Surface * pb)1103 virtual bool releasePbuffer(EglOS::Surface* pb) {
1104 android::base::AutoLock lock(sGlobalLock);
1105 if (!pb) return false;
1106
1107 WinSurface* winpb = WinSurface::from(pb);
1108
1109 if (!winpb->releaseDC()) return false;
1110
1111 const EglOS::PixelFormat* pixelFormat =
1112 winpb->getPixelFormat();
1113
1114 auto& frees = mFreePbufs[pixelFormat];
1115 frees.push_back(pb);
1116
1117 mLivePbufs[pixelFormat].erase(pb);
1118
1119 for (auto surf : mDeletePbufs) {
1120 WinSurface* winSurface = WinSurface::from(surf);
1121 mDispatch->wglDestroyPbuffer(winSurface->getPbuffer());
1122 delete winSurface;
1123 }
1124
1125 mDeletePbufs.clear();
1126
1127 return true;
1128 }
1129
makeCurrent(EglOS::Surface * read,EglOS::Surface * draw,EglOS::Context * context)1130 virtual bool makeCurrent(EglOS::Surface* read,
1131 EglOS::Surface* draw,
1132 EglOS::Context* context) {
1133 android::base::AutoLock lock(sGlobalLock);
1134 WinSurface* readWinSurface = WinSurface::from(read);
1135 WinSurface* drawWinSurface = WinSurface::from(draw);
1136 HDC hdcRead = read ? readWinSurface->getDC() : NULL;
1137 HDC hdcDraw = draw ? drawWinSurface->getDC() : NULL;
1138 HGLRC hdcContext = context ? WinContext::from(context) : 0;
1139
1140 const WglExtensionsDispatch* dispatch = mDispatch;
1141
1142 bool ret = false;
1143 if (hdcRead == hdcDraw){
1144 // The following loop is a work-around for a problem when
1145 // occasionally the rendering is incorrect after hibernating and
1146 // waking up windows.
1147 // wglMakeCurrent will sometimes fail for a short period of time
1148 // in such situation.
1149 //
1150 // For a stricter test, in addition to checking the return value, we
1151 // might also want to check its error code. On my computer in such
1152 // situation GetLastError() returns 0 (which is documented as
1153 // success code). This is not a documented behaviour and is
1154 // unreliable. But in case one needs to use it, here is the code:
1155 //
1156 // while (!(isSuccess = dispatch->wglMakeCurrent(hdcDraw, hdcContext))
1157 // && GetLastError()==0) Sleep(16);
1158 //
1159
1160 int count = 100;
1161 while (!dispatch->wglMakeCurrent(hdcDraw, hdcContext)
1162 && --count > 0
1163 && !GetLastError()) {
1164 Sleep(16);
1165 }
1166 if (count <= 0) {
1167 D("Error: wglMakeCurrent() failed, error %d\n", (int)GetLastError());
1168 return false;
1169 }
1170 ret = true;
1171 } else if (!dispatch->wglMakeContextCurrent) {
1172 return false;
1173 } else {
1174 ret = dispatch->wglMakeContextCurrent(
1175 hdcDraw, hdcRead, hdcContext);
1176 }
1177
1178 if (ret) {
1179 if (readWinSurface) readWinSurface->onMakeCurrent();
1180 if (drawWinSurface) drawWinSurface->onMakeCurrent();
1181 }
1182 return ret;
1183 }
1184
swapBuffers(EglOS::Surface * srfc)1185 virtual void swapBuffers(EglOS::Surface* srfc) {
1186 android::base::AutoLock lock(sGlobalLock);
1187 if (srfc && !mDispatch->SwapBuffers(WinSurface::from(srfc)->getDC())) {
1188 GetLastError();
1189 }
1190 }
1191
1192 private:
1193 // Returns the highest level of OpenGL core profile support in
1194 // this WGL implementation.
queryCoreProfileSupport()1195 void queryCoreProfileSupport() {
1196 mCoreProfileSupported = false;
1197
1198 if (!mDispatch->wglCreateContextAttribs) {
1199 WGL_ERR("OpenGL Core Profile not supported.\n");
1200 // Not supported, don't even try.
1201 return;
1202 }
1203
1204 // Ascending index order of context attribs :
1205 // decreasing GL major/minor version
1206 HGLRC testContext = nullptr;
1207 HDC dpy = mGlobals->getDefaultNontrivialDC();
1208
1209 for (int i = 0; i < getNumCoreProfileCtxAttribs(); i++) {
1210 const int* attribs = getCoreProfileCtxAttribs(i);
1211 testContext =
1212 mDispatch->wglCreateContextAttribs(
1213 dpy, nullptr /* no shared context */,
1214 attribs);
1215
1216 if (testContext) {
1217 mCoreProfileSupported = true;
1218 mCoreProfileCtxAttribs = attribs;
1219 getCoreProfileCtxAttribsVersion(
1220 attribs, &mCoreMajorVersion, &mCoreMinorVersion);
1221 mDispatch->wglDeleteContext(testContext);
1222 return;
1223 }
1224 }
1225 }
1226
createPbufferSurfaceImpl(const EglOS::PixelFormat * pixelFormat)1227 EglOS::Surface* createPbufferSurfaceImpl(const EglOS::PixelFormat* pixelFormat) {
1228 // we never care about width or height, since we just use
1229 // opengl fbos anyway.
1230 const WinPixelFormat* format = WinPixelFormat::from(pixelFormat);
1231 HDC dpy = mGlobals->getDummyDC(format);
1232
1233 const WglExtensionsDispatch* dispatch = mDispatch;
1234 if (!dispatch->wglCreatePbuffer) {
1235 return NULL;
1236 }
1237 HPBUFFERARB pb = dispatch->wglCreatePbuffer(dpy, format->configId(), 1, 1, nullptr);
1238 if (!pb) {
1239 GetLastError();
1240 return NULL;
1241 }
1242 return new WinSurface(pb, pixelFormat, dispatch);
1243 }
1244
1245 bool mCoreProfileSupported = false;
1246 int mCoreMajorVersion = 4;
1247 int mCoreMinorVersion = 5;
1248 const int* mCoreProfileCtxAttribs = nullptr;
1249
1250 const WglExtensionsDispatch* mDispatch = nullptr;
1251 WinGlobals* mGlobals = nullptr;
1252
1253 std::unordered_map<const EglOS::PixelFormat*, std::vector<EglOS::Surface* > > mFreePbufs;
1254 std::unordered_map<const EglOS::PixelFormat*, std::unordered_set<EglOS::Surface* > > mLivePbufs;
1255 std::vector<EglOS::Surface*> mDeletePbufs;
1256 static constexpr int kPbufPrimingCount = 8;
1257 };
1258
1259 constexpr int WglDisplay::kPbufPrimingCount;
1260
1261 class WglLibrary : public GlLibrary {
1262 public:
WglLibrary(const WglBaseDispatch * dispatch)1263 WglLibrary(const WglBaseDispatch* dispatch) : mDispatch(dispatch) {}
1264
findSymbol(const char * name)1265 virtual GlFunctionPointer findSymbol(const char* name) {
1266 return mDispatch->findFunction(name);
1267 }
1268
1269 private:
1270 const WglBaseDispatch* mDispatch = nullptr;
1271 };
1272
1273 class WinEngine : public EglOS::Engine {
1274 public:
1275 WinEngine();
1276
~WinEngine()1277 ~WinEngine() {
1278 delete mDispatch;
1279 }
1280
getDefaultDisplay()1281 virtual EglOS::Display* getDefaultDisplay() {
1282 return new WglDisplay(mDispatch, &mGlobals);
1283 }
1284
getGlLibrary()1285 virtual GlLibrary* getGlLibrary() {
1286 return &mGlLib;
1287 }
1288
eglGetProcAddress(const char *)1289 virtual void* eglGetProcAddress(const char*) {
1290 return 0;
1291 }
1292
createWindowSurface(EglOS::PixelFormat * cfg,EGLNativeWindowType wnd)1293 virtual EglOS::Surface* createWindowSurface(EglOS::PixelFormat* cfg,
1294 EGLNativeWindowType wnd) {
1295 (void)cfg;
1296 return new WinSurface(wnd, mDispatch);
1297 }
1298
1299 private:
1300 SharedLibrary* mLib = nullptr;
1301 const WglExtensionsDispatch* mDispatch = nullptr;
1302 WglBaseDispatch mBaseDispatch = {};
1303 WglLibrary mGlLib;
1304 WinGlobals mGlobals;
1305 };
1306
WinEngine()1307 WinEngine::WinEngine() :
1308 mGlLib(&mBaseDispatch),
1309 mGlobals(&mBaseDispatch) {
1310 const char* kLibName = "opengl32.dll";
1311 bool isSystemLib = true;
1312 const char* env = ::getenv("ANDROID_GL_LIB");
1313 if (env && !strcmp(env, "mesa")) {
1314 kLibName = "mesa_opengl32.dll";
1315 isSystemLib = false;
1316 }
1317 char error[256];
1318 GL_LOG("%s: Trying to load %s\n", __FUNCTION__, kLibName);
1319 mLib = SharedLibrary::open(kLibName, error, sizeof(error));
1320 if (!mLib) {
1321 WGL_ERR("ERROR: %s: Could not open %s: %s\n", __FUNCTION__,
1322 kLibName, error);
1323 exit(1);
1324 }
1325
1326 GL_LOG("%s: Library loaded at %p\n", __FUNCTION__, mLib);
1327 mBaseDispatch.init(mLib, isSystemLib);
1328 mDispatch = initExtensionsDispatch(&mBaseDispatch);
1329 GL_LOG("%s: Dispatch initialized\n", __FUNCTION__);
1330 }
1331
sHostEngine()1332 static WinEngine* sHostEngine() {
1333 static WinEngine* e = new WinEngine;
1334 return e;
1335 }
1336
1337 } // namespace
1338
1339 // static
getHostInstance()1340 EglOS::Engine* EglOS::Engine::getHostInstance() {
1341 return sHostEngine();
1342 }
1343