xref: /aosp_15_r20/external/deqp/framework/platform/win32/tcuWGL.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief WGL Utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "tcuWGL.hpp"
25 #include "tcuWin32Window.hpp"
26 #include "deDynamicLibrary.hpp"
27 #include "deMemory.h"
28 #include "deStringUtil.hpp"
29 #include "tcuFormatUtil.hpp"
30 #include "gluRenderConfig.hpp"
31 #include "glwEnums.hpp"
32 
33 #include <map>
34 #include <sstream>
35 #include <iterator>
36 #include <set>
37 
38 #include <wingdi.h>
39 
40 // WGL_ARB_pixel_format
41 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
42 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
43 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
44 #define WGL_ACCELERATION_ARB 0x2003
45 #define WGL_NEED_PALETTE_ARB 0x2004
46 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
47 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
48 #define WGL_SWAP_METHOD_ARB 0x2007
49 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
50 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
51 #define WGL_TRANSPARENT_ARB 0x200A
52 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
53 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
54 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
55 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
56 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
57 #define WGL_SHARE_DEPTH_ARB 0x200C
58 #define WGL_SHARE_STENCIL_ARB 0x200D
59 #define WGL_SHARE_ACCUM_ARB 0x200E
60 #define WGL_SUPPORT_GDI_ARB 0x200F
61 #define WGL_SUPPORT_OPENGL_ARB 0x2010
62 #define WGL_DOUBLE_BUFFER_ARB 0x2011
63 #define WGL_STEREO_ARB 0x2012
64 #define WGL_PIXEL_TYPE_ARB 0x2013
65 #define WGL_COLOR_BITS_ARB 0x2014
66 #define WGL_RED_BITS_ARB 0x2015
67 #define WGL_RED_SHIFT_ARB 0x2016
68 #define WGL_GREEN_BITS_ARB 0x2017
69 #define WGL_GREEN_SHIFT_ARB 0x2018
70 #define WGL_BLUE_BITS_ARB 0x2019
71 #define WGL_BLUE_SHIFT_ARB 0x201A
72 #define WGL_ALPHA_BITS_ARB 0x201B
73 #define WGL_ALPHA_SHIFT_ARB 0x201C
74 #define WGL_ACCUM_BITS_ARB 0x201D
75 #define WGL_ACCUM_RED_BITS_ARB 0x201E
76 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
77 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
78 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
79 #define WGL_DEPTH_BITS_ARB 0x2022
80 #define WGL_STENCIL_BITS_ARB 0x2023
81 #define WGL_AUX_BUFFERS_ARB 0x2024
82 
83 #define WGL_NO_ACCELERATION_ARB 0x2025
84 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
85 #define WGL_FULL_ACCELERATION_ARB 0x2027
86 
87 #define WGL_TYPE_RGBA_ARB 0x202B
88 #define WGL_TYPE_COLORINDEX_ARB 0x202C
89 
90 // WGL_ARB_color_buffer_float
91 #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
92 
93 // WGL_EXT_pixel_type_packed_float
94 #define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
95 
96 // WGL_ARB_multisample
97 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
98 #define WGL_SAMPLES_ARB 0x2042
99 
100 // WGL_EXT_colorspace
101 #define WGL_COLORSPACE_EXT 0x309D
102 #define WGL_COLORSPACE_SRGB_EXT 0x3089
103 #define WGL_COLORSPACE_LINEAR_EXT 0x308A
104 
105 // WGL_ARB_create_context
106 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
107 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
108 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
109 #define WGL_CONTEXT_FLAGS_ARB 0x2094
110 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
111 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
112 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
113 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
114 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
115 #define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
116 
117 // WGL_ARB_create_context_robustness
118 #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x0004
119 #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
120 #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
121 #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
122 
123 // WGL ARB_create_context_no_error
124 #define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
125 
126 DE_BEGIN_EXTERN_C
127 
128 // WGL core
129 typedef HGLRC(WINAPI *wglCreateContextFunc)(HDC hdc);
130 typedef BOOL(WINAPI *wglDeleteContextFunc)(HGLRC hglrc);
131 typedef BOOL(WINAPI *wglMakeCurrentFunc)(HDC hdc, HGLRC hglrc);
132 typedef PROC(WINAPI *wglGetProcAddressFunc)(LPCSTR lpszProc);
133 typedef BOOL(WINAPI *wglSwapLayerBuffersFunc)(HDC dhc, UINT fuPlanes);
134 
135 // WGL_ARB_pixel_format
136 typedef BOOL(WINAPI *wglGetPixelFormatAttribivARBFunc)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes,
137                                                        const int *piAttributes, int *piValues);
138 typedef BOOL(WINAPI *wglGetPixelFormatAttribfvARBFunc)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes,
139                                                        const int *piAttributes, FLOAT *pfValues);
140 typedef BOOL(WINAPI *wglChoosePixelFormatARBFunc)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList,
141                                                   UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
142 
143 // WGL_ARB_create_context
144 typedef HGLRC(WINAPI *wglCreateContextAttribsARBFunc)(HDC hdc, HGLRC hshareContext, const int *attribList);
145 typedef const char *(WINAPI *wglGetExtensionsStringARBFunc)(HDC hdc);
146 
147 // WGL_EXT_swap_control
148 typedef BOOL(WINAPI *wglSwapIntervalEXTFunc)(int interval);
149 
150 DE_END_EXTERN_C
151 
152 namespace tcu
153 {
154 namespace wgl
155 {
156 
157 // Functions
158 
159 struct Functions
160 {
161     // Core
162     wglCreateContextFunc createContext;
163     wglDeleteContextFunc deleteContext;
164     wglMakeCurrentFunc makeCurrent;
165     wglGetProcAddressFunc getProcAddress;
166     wglSwapLayerBuffersFunc swapLayerBuffers;
167 
168     // WGL_ARB_pixel_format
169     wglGetPixelFormatAttribivARBFunc getPixelFormatAttribivARB;
170     wglGetPixelFormatAttribfvARBFunc getPixelFormatAttribfvARB;
171     wglChoosePixelFormatARBFunc choosePixelFormatARB;
172 
173     // WGL_ARB_create_context
174     wglCreateContextAttribsARBFunc createContextAttribsARB;
175     wglGetExtensionsStringARBFunc getExtensionsStringARB;
176 
177     // WGL_EXT_swap_control
178     wglSwapIntervalEXTFunc swapIntervalEXT;
179 
Functionstcu::wgl::Functions180     Functions(void)
181         : createContext(DE_NULL)
182         , deleteContext(DE_NULL)
183         , makeCurrent(DE_NULL)
184         , getProcAddress(DE_NULL)
185         , swapLayerBuffers(DE_NULL)
186         , getPixelFormatAttribivARB(DE_NULL)
187         , getPixelFormatAttribfvARB(DE_NULL)
188         , choosePixelFormatARB(DE_NULL)
189         , createContextAttribsARB(DE_NULL)
190         , getExtensionsStringARB(DE_NULL)
191     {
192     }
193 };
194 
195 // Library
196 
197 class Library
198 {
199 public:
200     Library(HINSTANCE instance);
201     ~Library(void);
202 
getFunctions(void) const203     const Functions &getFunctions(void) const
204     {
205         return m_functions;
206     }
getGLLibrary(void) const207     const de::DynamicLibrary &getGLLibrary(void) const
208     {
209         return m_library;
210     }
211     bool isWglExtensionSupported(const char *extName) const;
212 
213 private:
214     de::DynamicLibrary m_library;
215     Functions m_functions;
216     std::set<std::string> m_extensions;
217 };
218 
Library(HINSTANCE instance)219 Library::Library(HINSTANCE instance) : m_library("opengl32.dll")
220 {
221     // Temporary 1x1 window for creating context
222     win32::Window tmpWindow(instance, 1, 1);
223 
224     // Load WGL core.
225     m_functions.createContext    = (wglCreateContextFunc)m_library.getFunction("wglCreateContext");
226     m_functions.deleteContext    = (wglDeleteContextFunc)m_library.getFunction("wglDeleteContext");
227     m_functions.getProcAddress   = (wglGetProcAddressFunc)m_library.getFunction("wglGetProcAddress");
228     m_functions.makeCurrent      = (wglMakeCurrentFunc)m_library.getFunction("wglMakeCurrent");
229     m_functions.swapLayerBuffers = (wglSwapLayerBuffersFunc)m_library.getFunction("wglSwapLayerBuffers");
230 
231     if (!m_functions.createContext || !m_functions.deleteContext || !m_functions.getProcAddress ||
232         !m_functions.makeCurrent || !m_functions.swapLayerBuffers)
233         throw ResourceError("Failed to load core WGL functions");
234 
235     {
236         PIXELFORMATDESCRIPTOR pixelFormatDesc;
237         deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));
238 
239         pixelFormatDesc.nSize      = sizeof(pixelFormatDesc);
240         pixelFormatDesc.nVersion   = 1;
241         pixelFormatDesc.dwFlags    = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
242         pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
243         pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
244 
245         int pixelFormat = ChoosePixelFormat(tmpWindow.getDeviceContext(), &pixelFormatDesc);
246         if (!SetPixelFormat(tmpWindow.getDeviceContext(), pixelFormat, &pixelFormatDesc))
247             throw ResourceError("Failed to set pixel format for temporary context creation");
248     }
249 
250     // Create temporary context for loading extension functions.
251     HGLRC tmpCtx = m_functions.createContext(tmpWindow.getDeviceContext());
252     if (!tmpCtx || !m_functions.makeCurrent(tmpWindow.getDeviceContext(), tmpCtx))
253     {
254         if (tmpCtx)
255             m_functions.deleteContext(tmpCtx);
256         throw ResourceError("Failed to create temporary WGL context");
257     }
258 
259     // WGL_ARB_pixel_format
260     m_functions.getPixelFormatAttribivARB =
261         (wglGetPixelFormatAttribivARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribivARB");
262     m_functions.getPixelFormatAttribfvARB =
263         (wglGetPixelFormatAttribfvARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribfvARB");
264     m_functions.choosePixelFormatARB =
265         (wglChoosePixelFormatARBFunc)m_functions.getProcAddress("wglChoosePixelFormatARB");
266 
267     // WGL_ARB_create_context
268     m_functions.createContextAttribsARB =
269         (wglCreateContextAttribsARBFunc)m_functions.getProcAddress("wglCreateContextAttribsARB");
270     m_functions.getExtensionsStringARB =
271         (wglGetExtensionsStringARBFunc)m_functions.getProcAddress("wglGetExtensionsStringARB");
272 
273     // WGL_EXT_swap_control
274     m_functions.swapIntervalEXT = (wglSwapIntervalEXTFunc)m_functions.getProcAddress("wglSwapIntervalEXT");
275 
276     m_functions.makeCurrent(tmpWindow.getDeviceContext(), NULL);
277     m_functions.deleteContext(tmpCtx);
278 
279     if (!m_functions.getPixelFormatAttribivARB || !m_functions.getPixelFormatAttribfvARB ||
280         !m_functions.choosePixelFormatARB || !m_functions.createContextAttribsARB ||
281         !m_functions.getExtensionsStringARB)
282         throw ResourceError("Failed to load WGL extension functions");
283 
284     const char *extensions = m_functions.getExtensionsStringARB(tmpWindow.getDeviceContext());
285     std::istringstream extStream(extensions);
286     m_extensions =
287         std::set<std::string>(std::istream_iterator<std::string>(extStream), std::istream_iterator<std::string>());
288 }
289 
~Library(void)290 Library::~Library(void)
291 {
292 }
293 
isWglExtensionSupported(const char * extName) const294 bool Library::isWglExtensionSupported(const char *extName) const
295 {
296     return m_extensions.find(extName) != m_extensions.end();
297 }
298 
299 // Core
300 
Core(HINSTANCE instance)301 Core::Core(HINSTANCE instance) : m_library(new Library(instance))
302 {
303 }
304 
~Core(void)305 Core::~Core(void)
306 {
307     delete m_library;
308 }
309 
getPixelFormats(HDC deviceCtx) const310 std::vector<int> Core::getPixelFormats(HDC deviceCtx) const
311 {
312     const Functions &wgl = m_library->getFunctions();
313 
314     int attribs[] = {WGL_NUMBER_PIXEL_FORMATS_ARB};
315     int values[DE_LENGTH_OF_ARRAY(attribs)];
316 
317     if (!wgl.getPixelFormatAttribivARB(deviceCtx, 0, 0, DE_LENGTH_OF_ARRAY(attribs), &attribs[0], &values[0]))
318         TCU_THROW(ResourceError, "Failed to query number of WGL pixel formats");
319 
320     std::vector<int> pixelFormats(values[0]);
321     for (int i = 0; i < values[0]; i++)
322         pixelFormats[i] = i + 1;
323 
324     return pixelFormats;
325 }
326 
translateAcceleration(int accel)327 static PixelFormatInfo::Acceleration translateAcceleration(int accel)
328 {
329     switch (accel)
330     {
331     case WGL_NO_ACCELERATION_ARB:
332         return PixelFormatInfo::ACCELERATION_NONE;
333     case WGL_GENERIC_ACCELERATION_ARB:
334         return PixelFormatInfo::ACCELERATION_GENERIC;
335     case WGL_FULL_ACCELERATION_ARB:
336         return PixelFormatInfo::ACCELERATION_FULL;
337     default:
338         return PixelFormatInfo::ACCELERATION_UNKNOWN;
339     }
340 }
341 
translatePixelType(int type)342 static PixelFormatInfo::PixelType translatePixelType(int type)
343 {
344     switch (type)
345     {
346     case WGL_TYPE_RGBA_ARB:
347         return PixelFormatInfo::PIXELTYPE_RGBA;
348     case WGL_TYPE_RGBA_FLOAT_ARB:
349         return PixelFormatInfo::PIXELTYPE_RGBA_FLOAT;
350     case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
351         return PixelFormatInfo::PIXELTYPE_RGBA_UNSIGNED_FLOAT;
352     case WGL_TYPE_COLORINDEX_ARB:
353         return PixelFormatInfo::PIXELTYPE_COLOR_INDEX;
354     default:
355         return PixelFormatInfo::PIXELTYPE_UNKNOWN;
356     }
357 }
358 
getPixelFormatAttribs(const Functions & wgl,HDC deviceCtx,int pixelFormat,int numAttribs,const int * attribs,std::map<int,int> * dst)359 static void getPixelFormatAttribs(const Functions &wgl, HDC deviceCtx, int pixelFormat, int numAttribs,
360                                   const int *attribs, std::map<int, int> *dst)
361 {
362     std::vector<int> values(numAttribs);
363 
364     if (!wgl.getPixelFormatAttribivARB(deviceCtx, pixelFormat, 0, numAttribs, &attribs[0], &values[0]))
365         TCU_THROW(ResourceError, "Pixel format query failed");
366 
367     for (int ndx = 0; ndx < numAttribs; ++ndx)
368         (*dst)[attribs[ndx]] = values[ndx];
369 }
370 
getPixelFormatInfo(HDC deviceCtx,int pixelFormat) const371 PixelFormatInfo Core::getPixelFormatInfo(HDC deviceCtx, int pixelFormat) const
372 {
373     std::vector<int> s_attribsToQuery{
374         WGL_DRAW_TO_WINDOW_ARB,   WGL_DRAW_TO_BITMAP_ARB,      WGL_ACCELERATION_ARB,
375         WGL_NEED_PALETTE_ARB,     WGL_NEED_SYSTEM_PALETTE_ARB, WGL_NUMBER_OVERLAYS_ARB,
376         WGL_NUMBER_UNDERLAYS_ARB, WGL_SUPPORT_OPENGL_ARB,      WGL_DOUBLE_BUFFER_ARB,
377         WGL_STEREO_ARB,           WGL_PIXEL_TYPE_ARB,          WGL_RED_BITS_ARB,
378         WGL_GREEN_BITS_ARB,       WGL_BLUE_BITS_ARB,           WGL_ALPHA_BITS_ARB,
379         WGL_ACCUM_BITS_ARB,       WGL_DEPTH_BITS_ARB,          WGL_STENCIL_BITS_ARB,
380         WGL_AUX_BUFFERS_ARB,      WGL_SAMPLE_BUFFERS_ARB,      WGL_SAMPLES_ARB,
381     };
382     if (getLibrary()->isWglExtensionSupported("WGL_EXT_colorspace"))
383         s_attribsToQuery.push_back(WGL_COLORSPACE_EXT);
384 
385     const Functions &wgl = m_library->getFunctions();
386     std::map<int, int> values;
387 
388     getPixelFormatAttribs(wgl, deviceCtx, pixelFormat, static_cast<int>(s_attribsToQuery.size()),
389                           s_attribsToQuery.data(), &values);
390 
391     // Translate values.
392     PixelFormatInfo info;
393 
394     info.pixelFormat = pixelFormat;
395     info.surfaceTypes |= (values[WGL_DRAW_TO_WINDOW_ARB] ? PixelFormatInfo::SURFACE_WINDOW : 0);
396     info.surfaceTypes |= (values[WGL_DRAW_TO_BITMAP_ARB] ? PixelFormatInfo::SURFACE_PIXMAP : 0);
397     info.acceleration      = translateAcceleration(values[WGL_ACCELERATION_ARB]);
398     info.needPalette       = values[WGL_NEED_PALETTE_ARB] != 0;
399     info.needSystemPalette = values[WGL_NEED_SYSTEM_PALETTE_ARB] != 0;
400     info.numOverlays       = values[WGL_NUMBER_OVERLAYS_ARB] != 0;
401     info.numUnderlays      = values[WGL_NUMBER_UNDERLAYS_ARB] != 0;
402     info.supportOpenGL     = values[WGL_SUPPORT_OPENGL_ARB] != 0;
403     info.doubleBuffer      = values[WGL_DOUBLE_BUFFER_ARB] != 0;
404     info.stereo            = values[WGL_STEREO_ARB] != 0;
405     info.pixelType         = translatePixelType(values[WGL_PIXEL_TYPE_ARB]);
406     info.redBits           = values[WGL_RED_BITS_ARB];
407     info.greenBits         = values[WGL_GREEN_BITS_ARB];
408     info.blueBits          = values[WGL_BLUE_BITS_ARB];
409     info.alphaBits         = values[WGL_ALPHA_BITS_ARB];
410     info.accumBits         = values[WGL_ACCUM_BITS_ARB];
411     info.depthBits         = values[WGL_DEPTH_BITS_ARB];
412     info.stencilBits       = values[WGL_STENCIL_BITS_ARB];
413     info.numAuxBuffers     = values[WGL_AUX_BUFFERS_ARB];
414     info.sampleBuffers     = values[WGL_SAMPLE_BUFFERS_ARB];
415     info.samples           = values[WGL_SAMPLES_ARB];
416     info.sRGB              = (getLibrary()->isWglExtensionSupported("WGL_EXT_colorspace")) ?
417                                  (values[WGL_COLORSPACE_EXT] == WGL_COLORSPACE_SRGB_EXT) :
418                                  false;
419 
420     return info;
421 }
422 
423 // Context
424 
Context(const Core * core,HDC deviceCtx,const Context * sharedContext,glu::ContextType ctxType,int pixelFormat,glu::ResetNotificationStrategy resetNotificationStrategy)425 Context::Context(const Core *core, HDC deviceCtx, const Context *sharedContext, glu::ContextType ctxType,
426                  int pixelFormat, glu::ResetNotificationStrategy resetNotificationStrategy)
427     : m_core(core)
428     , m_deviceCtx(deviceCtx)
429     , m_context(0)
430 {
431     const Functions &wgl = core->getLibrary()->getFunctions();
432     std::vector<int> attribList;
433 
434     // Context version and profile
435     {
436         int profileBit  = 0;
437         HGLRC sharedCtx = DE_NULL;
438         int minor       = ctxType.getMinorVersion();
439         int major       = ctxType.getMajorVersion();
440 
441         switch (ctxType.getProfile())
442         {
443         case glu::PROFILE_CORE:
444             profileBit = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
445             if (major == 3 && minor < 3)
446                 minor = 3;
447             break;
448 
449         case glu::PROFILE_ES:
450             profileBit = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
451             break;
452 
453         case glu::PROFILE_COMPATIBILITY:
454             profileBit = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
455             break;
456 
457         default:
458             TCU_THROW(NotSupportedError, "Unsupported context type for WGL");
459         }
460 
461         attribList.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
462         attribList.push_back(major);
463         attribList.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
464         attribList.push_back(minor);
465         attribList.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
466         attribList.push_back(profileBit);
467     }
468 
469     // Context flags
470     {
471         int flags = 0;
472 
473         if ((ctxType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
474         {
475             if (glu::isContextTypeES(ctxType))
476                 TCU_THROW(InternalError, "Only OpenGL core contexts can be forward-compatible");
477 
478             flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
479         }
480 
481         if ((ctxType.getFlags() & glu::CONTEXT_DEBUG) != 0)
482             flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
483 
484         if ((ctxType.getFlags() & glu::CONTEXT_ROBUST) != 0)
485             flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
486 
487         if ((ctxType.getFlags() & glu::CONTEXT_NO_ERROR) != 0)
488         {
489             if (core->getLibrary()->isWglExtensionSupported("WGL_ARB_create_context_no_error"))
490             {
491                 attribList.push_back(WGL_CONTEXT_OPENGL_NO_ERROR_ARB);
492                 attribList.push_back(1);
493             }
494             else
495                 TCU_THROW(NotSupportedError,
496                           "WGL_ARB_create_context_no_error is required for creating no-error contexts");
497         }
498 
499         if (flags != 0)
500         {
501             attribList.push_back(WGL_CONTEXT_FLAGS_ARB);
502             attribList.push_back(flags);
503         }
504     }
505 
506     if (resetNotificationStrategy != glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED)
507     {
508         attribList.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
509 
510         if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION)
511             attribList.push_back(WGL_NO_RESET_NOTIFICATION_ARB);
512         else if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET)
513             attribList.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
514         else
515             TCU_THROW(InternalError, "Unknown reset notification strategy");
516     }
517 
518     // Set pixel format
519     {
520         PIXELFORMATDESCRIPTOR pixelFormatDesc;
521         deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));
522 
523         if (!DescribePixelFormat(deviceCtx, pixelFormat, sizeof(pixelFormatDesc), &pixelFormatDesc))
524             throw ResourceError("DescribePixelFormat() failed");
525 
526         if (!SetPixelFormat(deviceCtx, pixelFormat, &pixelFormatDesc))
527             throw ResourceError("Failed to set pixel format");
528     }
529 
530     HGLRC sharedCtx = DE_NULL;
531     if (DE_NULL != sharedContext)
532         sharedCtx = sharedContext->m_context;
533 
534     // Terminate attribList
535     attribList.push_back(0);
536 
537     // Create context
538     m_context = wgl.createContextAttribsARB(deviceCtx, sharedCtx, &attribList[0]);
539 
540     if (!m_context)
541         TCU_THROW(ResourceError, "Failed to create WGL context");
542 
543     if (!wgl.makeCurrent(deviceCtx, m_context))
544     {
545         wgl.deleteContext(m_context);
546         TCU_THROW(ResourceError, "wglMakeCurrent() failed");
547     }
548 
549     if (core->getLibrary()->isWglExtensionSupported("WGL_EXT_swap_control"))
550         core->getLibrary()->getFunctions().swapIntervalEXT(0);
551 }
552 
~Context(void)553 Context::~Context(void)
554 {
555     const Functions &wgl = m_core->getLibrary()->getFunctions();
556 
557     wgl.makeCurrent(m_deviceCtx, NULL);
558     wgl.deleteContext(m_context);
559 }
560 
getGLFunction(const char * name) const561 FunctionPtr Context::getGLFunction(const char *name) const
562 {
563     FunctionPtr ptr = DE_NULL;
564 
565     // Try first with wglGeProcAddress()
566     ptr = (FunctionPtr)m_core->getLibrary()->getFunctions().getProcAddress(name);
567 
568     // Fall-back to dynlib
569     if (!ptr)
570         ptr = (FunctionPtr)m_core->getLibrary()->getGLLibrary().getFunction(name);
571 
572     return ptr;
573 }
574 
makeCurrent(void)575 void Context::makeCurrent(void)
576 {
577     const Functions &wgl = m_core->getLibrary()->getFunctions();
578     if (!wgl.makeCurrent(m_deviceCtx, m_context))
579         TCU_THROW(ResourceError, "wglMakeCurrent() failed");
580 }
581 
swapBuffers(void) const582 void Context::swapBuffers(void) const
583 {
584     const Functions &wgl = m_core->getLibrary()->getFunctions();
585     if (!wgl.swapLayerBuffers(m_deviceCtx, WGL_SWAP_MAIN_PLANE))
586         TCU_THROW(ResourceError, "wglSwapBuffers() failed");
587 }
588 
isSupportedByTests(const PixelFormatInfo & info)589 bool isSupportedByTests(const PixelFormatInfo &info)
590 {
591     if (!info.supportOpenGL)
592         return false;
593 
594     if (info.acceleration != wgl::PixelFormatInfo::ACCELERATION_FULL)
595         return false;
596 
597     if (info.pixelType != wgl::PixelFormatInfo::PIXELTYPE_RGBA)
598         return false;
599 
600     if ((info.surfaceTypes & wgl::PixelFormatInfo::SURFACE_WINDOW) == 0)
601         return false;
602 
603     if (info.needPalette || info.needSystemPalette)
604         return false;
605 
606     if (info.numOverlays != 0 || info.numUnderlays != 0)
607         return false;
608 
609     if (info.stereo)
610         return false;
611 
612     return true;
613 }
614 
choosePixelFormat(const Core & wgl,HDC deviceCtx,const glu::RenderConfig & config)615 int choosePixelFormat(const Core &wgl, HDC deviceCtx, const glu::RenderConfig &config)
616 {
617     std::vector<int> pixelFormats = wgl.getPixelFormats(deviceCtx);
618 
619     for (std::vector<int>::const_iterator fmtIter = pixelFormats.begin(); fmtIter != pixelFormats.end(); ++fmtIter)
620     {
621         const PixelFormatInfo info = wgl.getPixelFormatInfo(deviceCtx, *fmtIter);
622 
623         // Skip formats that are fundamentally not compatible with current tests
624         if (!isSupportedByTests(info))
625             continue;
626 
627         if (config.redBits != glu::RenderConfig::DONT_CARE && config.redBits != info.redBits)
628             continue;
629 
630         if (config.greenBits != glu::RenderConfig::DONT_CARE && config.greenBits != info.greenBits)
631             continue;
632 
633         if (config.blueBits != glu::RenderConfig::DONT_CARE && config.blueBits != info.blueBits)
634             continue;
635 
636         if (config.alphaBits != glu::RenderConfig::DONT_CARE && config.alphaBits != info.alphaBits)
637             continue;
638 
639         if (config.depthBits != glu::RenderConfig::DONT_CARE && config.depthBits != info.depthBits)
640             continue;
641 
642         if (config.stencilBits != glu::RenderConfig::DONT_CARE && config.stencilBits != info.stencilBits)
643             continue;
644 
645         if (config.numSamples != glu::RenderConfig::DONT_CARE && config.numSamples != info.samples)
646             continue;
647 
648         // Passed all tests - select this.
649         return info.pixelFormat;
650     }
651 
652     return -1;
653 }
654 
655 } // namespace wgl
656 } // namespace tcu
657