• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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