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