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
32 #include <WinGDI.h>
33
34 // WGL_ARB_pixel_format
35 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
36 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
37 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
38 #define WGL_ACCELERATION_ARB 0x2003
39 #define WGL_NEED_PALETTE_ARB 0x2004
40 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
41 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
42 #define WGL_SWAP_METHOD_ARB 0x2007
43 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
44 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
45 #define WGL_TRANSPARENT_ARB 0x200A
46 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
47 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
48 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
49 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
50 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
51 #define WGL_SHARE_DEPTH_ARB 0x200C
52 #define WGL_SHARE_STENCIL_ARB 0x200D
53 #define WGL_SHARE_ACCUM_ARB 0x200E
54 #define WGL_SUPPORT_GDI_ARB 0x200F
55 #define WGL_SUPPORT_OPENGL_ARB 0x2010
56 #define WGL_DOUBLE_BUFFER_ARB 0x2011
57 #define WGL_STEREO_ARB 0x2012
58 #define WGL_PIXEL_TYPE_ARB 0x2013
59 #define WGL_COLOR_BITS_ARB 0x2014
60 #define WGL_RED_BITS_ARB 0x2015
61 #define WGL_RED_SHIFT_ARB 0x2016
62 #define WGL_GREEN_BITS_ARB 0x2017
63 #define WGL_GREEN_SHIFT_ARB 0x2018
64 #define WGL_BLUE_BITS_ARB 0x2019
65 #define WGL_BLUE_SHIFT_ARB 0x201A
66 #define WGL_ALPHA_BITS_ARB 0x201B
67 #define WGL_ALPHA_SHIFT_ARB 0x201C
68 #define WGL_ACCUM_BITS_ARB 0x201D
69 #define WGL_ACCUM_RED_BITS_ARB 0x201E
70 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
71 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
72 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
73 #define WGL_DEPTH_BITS_ARB 0x2022
74 #define WGL_STENCIL_BITS_ARB 0x2023
75 #define WGL_AUX_BUFFERS_ARB 0x2024
76
77 #define WGL_NO_ACCELERATION_ARB 0x2025
78 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
79 #define WGL_FULL_ACCELERATION_ARB 0x2027
80
81 #define WGL_TYPE_RGBA_ARB 0x202B
82 #define WGL_TYPE_COLORINDEX_ARB 0x202C
83
84 // WGL_ARB_color_buffer_float
85 #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
86
87 // WGL_EXT_pixel_type_packed_float
88 #define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
89
90 // WGL_ARB_multisample
91 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
92 #define WGL_SAMPLES_ARB 0x2042
93
94 // WGL_ARB_create_context
95 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
96 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
97 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
98 #define WGL_CONTEXT_FLAGS_ARB 0x2094
99 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
100 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
101 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
102 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
103 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
104 #define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
105
106 // WGL_ARB_create_context_robustness
107 #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x0004
108 #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
109 #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
110 #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
111
112 DE_BEGIN_EXTERN_C
113
114 // WGL core
115 typedef HGLRC (WINAPI* wglCreateContextFunc) (HDC hdc);
116 typedef BOOL (WINAPI* wglDeleteContextFunc) (HGLRC hglrc);
117 typedef BOOL (WINAPI* wglMakeCurrentFunc) (HDC hdc, HGLRC hglrc);
118 typedef PROC (WINAPI* wglGetProcAddressFunc) (LPCSTR lpszProc);
119 typedef BOOL (WINAPI* wglSwapLayerBuffersFunc) (HDC dhc, UINT fuPlanes);
120
121 // WGL_ARB_pixel_format
122 typedef BOOL (WINAPI* wglGetPixelFormatAttribivARBFunc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
123 typedef BOOL (WINAPI* wglGetPixelFormatAttribfvARBFunc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
124 typedef BOOL (WINAPI* wglChoosePixelFormatARBFunc) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
125
126 // WGL_ARB_create_context
127 typedef HGLRC (WINAPI* wglCreateContextAttribsARBFunc) (HDC hdc, HGLRC hshareContext, const int* attribList);
128
129 DE_END_EXTERN_C
130
131 namespace tcu
132 {
133 namespace wgl
134 {
135
136 // Functions
137
138 struct Functions
139 {
140 // Core
141 wglCreateContextFunc createContext;
142 wglDeleteContextFunc deleteContext;
143 wglMakeCurrentFunc makeCurrent;
144 wglGetProcAddressFunc getProcAddress;
145 wglSwapLayerBuffersFunc swapLayerBuffers;
146
147 // WGL_ARB_pixel_format
148 wglGetPixelFormatAttribivARBFunc getPixelFormatAttribivARB;
149 wglGetPixelFormatAttribfvARBFunc getPixelFormatAttribfvARB;
150 wglChoosePixelFormatARBFunc choosePixelFormatARB;
151
152 // WGL_ARB_create_context
153 wglCreateContextAttribsARBFunc createContextAttribsARB;
154
Functionstcu::wgl::Functions155 Functions (void)
156 : createContext (DE_NULL)
157 , deleteContext (DE_NULL)
158 , makeCurrent (DE_NULL)
159 , getProcAddress (DE_NULL)
160 , swapLayerBuffers (DE_NULL)
161 , getPixelFormatAttribivARB (DE_NULL)
162 , getPixelFormatAttribfvARB (DE_NULL)
163 , choosePixelFormatARB (DE_NULL)
164 , createContextAttribsARB (DE_NULL)
165 {
166 }
167 };
168
169 // Library
170
171 class Library
172 {
173 public:
174 Library (HINSTANCE instance);
175 ~Library (void);
176
getFunctions(void) const177 const Functions& getFunctions (void) const { return m_functions; }
getGLLibrary(void) const178 const de::DynamicLibrary& getGLLibrary (void) const { return m_library; }
179
180 private:
181 de::DynamicLibrary m_library;
182 Functions m_functions;
183 };
184
Library(HINSTANCE instance)185 Library::Library (HINSTANCE instance)
186 : m_library("opengl32.dll")
187 {
188 // Temporary 1x1 window for creating context
189 Win32Window tmpWindow(instance, 1, 1);
190
191 // Load WGL core.
192 m_functions.createContext = (wglCreateContextFunc) m_library.getFunction("wglCreateContext");
193 m_functions.deleteContext = (wglDeleteContextFunc) m_library.getFunction("wglDeleteContext");
194 m_functions.getProcAddress = (wglGetProcAddressFunc) m_library.getFunction("wglGetProcAddress");
195 m_functions.makeCurrent = (wglMakeCurrentFunc) m_library.getFunction("wglMakeCurrent");
196 m_functions.swapLayerBuffers = (wglSwapLayerBuffersFunc) m_library.getFunction("wglSwapLayerBuffers");
197
198 if (!m_functions.createContext ||
199 !m_functions.deleteContext ||
200 !m_functions.getProcAddress ||
201 !m_functions.makeCurrent ||
202 !m_functions.swapLayerBuffers)
203 throw ResourceError("Failed to load core WGL functions");
204
205 {
206 PIXELFORMATDESCRIPTOR pixelFormatDesc;
207 deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));
208
209 pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
210 pixelFormatDesc.nVersion = 1;
211 pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
212 pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
213 pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
214
215 int pixelFormat = ChoosePixelFormat(tmpWindow.getDeviceContext(), &pixelFormatDesc);
216 if (!SetPixelFormat(tmpWindow.getDeviceContext(), pixelFormat, &pixelFormatDesc))
217 throw ResourceError("Failed to set pixel format for temporary context creation");
218 }
219
220 // Create temporary context for loading extension functions.
221 HGLRC tmpCtx = m_functions.createContext(tmpWindow.getDeviceContext());
222 if (!tmpCtx || !m_functions.makeCurrent(tmpWindow.getDeviceContext(), tmpCtx))
223 {
224 if (tmpCtx)
225 m_functions.deleteContext(tmpCtx);
226 throw ResourceError("Failed to create temporary WGL context");
227 }
228
229 // WGL_ARB_pixel_format
230 m_functions.getPixelFormatAttribivARB = (wglGetPixelFormatAttribivARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribivARB");
231 m_functions.getPixelFormatAttribfvARB = (wglGetPixelFormatAttribfvARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribfvARB");
232 m_functions.choosePixelFormatARB = (wglChoosePixelFormatARBFunc)m_functions.getProcAddress("wglChoosePixelFormatARB");
233
234 // WGL_ARB_create_context
235 m_functions.createContextAttribsARB = (wglCreateContextAttribsARBFunc)m_functions.getProcAddress("wglCreateContextAttribsARB");
236
237 m_functions.makeCurrent(tmpWindow.getDeviceContext(), NULL);
238 m_functions.deleteContext(tmpCtx);
239
240 if (!m_functions.getPixelFormatAttribivARB ||
241 !m_functions.getPixelFormatAttribfvARB ||
242 !m_functions.choosePixelFormatARB ||
243 !m_functions.createContextAttribsARB)
244 throw ResourceError("Failed to load WGL extension functions");
245 }
246
~Library(void)247 Library::~Library (void)
248 {
249 }
250
251 // Core
252
Core(HINSTANCE instance)253 Core::Core (HINSTANCE instance)
254 : m_library(new Library(instance))
255 {
256 }
257
~Core(void)258 Core::~Core (void)
259 {
260 delete m_library;
261 }
262
getPixelFormats(HDC deviceCtx) const263 std::vector<int> Core::getPixelFormats (HDC deviceCtx) const
264 {
265 const Functions& wgl = m_library->getFunctions();
266
267 int attribs[] = { WGL_NUMBER_PIXEL_FORMATS_ARB };
268 int values[DE_LENGTH_OF_ARRAY(attribs)];
269
270 if (!wgl.getPixelFormatAttribivARB(deviceCtx, 0, 0, DE_LENGTH_OF_ARRAY(attribs), &attribs[0], &values[0]))
271 throw ResourceError("Failed to query number of WGL pixel formats");
272
273 // \todo [2013-04-14 pyry] Do we need to filter values at all?
274 std::vector<int> pixelFormats(values[0]);
275 for (int i = 0; i < values[0]; i++)
276 pixelFormats[i] = i+1;
277
278 return pixelFormats;
279 }
280
translateAcceleration(int accel)281 static PixelFormatInfo::Acceleration translateAcceleration (int accel)
282 {
283 switch (accel)
284 {
285 case WGL_NO_ACCELERATION_ARB: return PixelFormatInfo::ACCELERATION_NONE;
286 case WGL_GENERIC_ACCELERATION_ARB: return PixelFormatInfo::ACCELERATION_GENERIC;
287 case WGL_FULL_ACCELERATION_ARB: return PixelFormatInfo::ACCELERATION_FULL;
288 default: return PixelFormatInfo::ACCELERATION_UNKNOWN;
289 }
290 }
291
translatePixelType(int type)292 static PixelFormatInfo::PixelType translatePixelType (int type)
293 {
294 switch (type)
295 {
296 case WGL_TYPE_RGBA_ARB: return PixelFormatInfo::PIXELTYPE_RGBA;
297 case WGL_TYPE_RGBA_FLOAT_ARB: return PixelFormatInfo::PIXELTYPE_RGBA_FLOAT;
298 case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: return PixelFormatInfo::PIXELTYPE_RGBA_UNSIGNED_FLOAT;
299 case WGL_TYPE_COLORINDEX_ARB: return PixelFormatInfo::PIXELTYPE_COLOR_INDEX;
300 default: return PixelFormatInfo::PIXELTYPE_UNKNOWN;
301 }
302 }
303
getPixelFormatInfo(HDC deviceCtx,int pixelFormat) const304 PixelFormatInfo Core::getPixelFormatInfo (HDC deviceCtx, int pixelFormat) const
305 {
306 const Functions& wgl = m_library->getFunctions();
307
308 int attribs [14];
309 int values [DE_LENGTH_OF_ARRAY(attribs)];
310 attribs[0] = WGL_DRAW_TO_WINDOW_ARB;
311 attribs[1] = WGL_DRAW_TO_BITMAP_ARB;
312 attribs[2] = WGL_ACCELERATION_ARB;
313 attribs[3] = WGL_SUPPORT_OPENGL_ARB;
314 attribs[4] = WGL_DOUBLE_BUFFER_ARB;
315 attribs[5] = WGL_PIXEL_TYPE_ARB;
316 attribs[6] = WGL_RED_BITS_ARB;
317 attribs[7] = WGL_GREEN_BITS_ARB;
318 attribs[8] = WGL_BLUE_BITS_ARB;
319 attribs[9] = WGL_ALPHA_BITS_ARB;
320 attribs[10] = WGL_DEPTH_BITS_ARB;
321 attribs[11] = WGL_STENCIL_BITS_ARB;
322 attribs[12] = WGL_SAMPLE_BUFFERS_ARB;
323 attribs[13] = WGL_SAMPLES_ARB;
324
325 deMemset(&values[0], 0, sizeof(values));
326 if (!wgl.getPixelFormatAttribivARB(deviceCtx, pixelFormat, 0, DE_LENGTH_OF_ARRAY(attribs), &attribs[0], &values[0]))
327 throw ResourceError("Pixel format query failed");
328
329 // Translate values.
330 PixelFormatInfo info;
331
332 info.pixelFormat = pixelFormat;
333 info.surfaceTypes |= (values[0] ? PixelFormatInfo::SURFACE_WINDOW : 0);
334 info.surfaceTypes |= (values[1] ? PixelFormatInfo::SURFACE_PIXMAP : 0);
335 info.acceleration = translateAcceleration(values[2]);
336 info.supportOpenGL = values[3] != 0;
337 info.doubleBuffer = values[4] != 0;
338 info.pixelType = translatePixelType(values[5]);
339 info.redBits = values[6];
340 info.greenBits = values[7];
341 info.blueBits = values[8];
342 info.alphaBits = values[9];
343 info.depthBits = values[10];
344 info.stencilBits = values[11];
345 info.sampleBuffers = values[12];
346 info.samples = values[13];
347
348 return info;
349 }
350
351 // Context
352
Context(const Core * core,HDC deviceCtx,glu::ContextType ctxType,int pixelFormat)353 Context::Context (const Core* core, HDC deviceCtx, glu::ContextType ctxType, int pixelFormat)
354 : m_core (core)
355 , m_deviceCtx (deviceCtx)
356 , m_context (0)
357 {
358 const Functions& wgl = core->getLibrary()->getFunctions();
359
360 // Map context type & flags.
361 int profileBit = 0;
362 int flags = 0;
363
364 switch (ctxType.getProfile())
365 {
366 case glu::PROFILE_CORE:
367 profileBit = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
368 break;
369
370 case glu::PROFILE_ES:
371 profileBit = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
372 break;
373
374 case glu::PROFILE_COMPATIBILITY:
375 profileBit = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
376 break;
377
378 default:
379 throw NotSupportedError("Unsupported context type for WGL");
380 }
381
382 if ((ctxType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
383 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
384
385 if ((ctxType.getFlags() & glu::CONTEXT_DEBUG) != 0)
386 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
387
388 if ((ctxType.getFlags() & glu::CONTEXT_ROBUST) != 0)
389 flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
390
391 const int attribList[] =
392 {
393 WGL_CONTEXT_MAJOR_VERSION_ARB, ctxType.getMajorVersion(),
394 WGL_CONTEXT_MINOR_VERSION_ARB, ctxType.getMinorVersion(),
395 WGL_CONTEXT_PROFILE_MASK_ARB, profileBit,
396 WGL_CONTEXT_FLAGS_ARB, flags,
397 0
398 };
399
400 // Set pixel format
401 {
402 PIXELFORMATDESCRIPTOR pixelFormatDesc;
403 deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));
404
405 if (!DescribePixelFormat(deviceCtx, pixelFormat, sizeof(pixelFormatDesc), &pixelFormatDesc))
406 throw ResourceError("DescribePixelFormat() failed");
407
408 if (!SetPixelFormat(deviceCtx, pixelFormat, &pixelFormatDesc))
409 throw ResourceError("Failed to set pixel format");
410 }
411
412 // Create context
413 m_context = wgl.createContextAttribsARB(deviceCtx, NULL, attribList);
414
415 if (!m_context)
416 throw ResourceError("Failed to create WGL context");
417
418 if (!wgl.makeCurrent(deviceCtx, m_context))
419 {
420 wgl.deleteContext(m_context);
421 throw ResourceError("wglMakeCurrent() failed");
422 }
423 }
424
~Context(void)425 Context::~Context (void)
426 {
427 const Functions& wgl = m_core->getLibrary()->getFunctions();
428
429 wgl.makeCurrent(m_deviceCtx, NULL);
430 wgl.deleteContext(m_context);
431 }
432
getGLFunction(const char * name) const433 FunctionPtr Context::getGLFunction (const char* name) const
434 {
435 FunctionPtr ptr = DE_NULL;
436
437 // Try first with wglGeProcAddress()
438 ptr = (FunctionPtr)m_core->getLibrary()->getFunctions().getProcAddress(name);
439
440 // Fall-back to dynlib
441 if (!ptr)
442 ptr = (FunctionPtr)m_core->getLibrary()->getGLLibrary().getFunction(name);
443
444 return ptr;
445 }
446
swapBuffers(void) const447 void Context::swapBuffers (void) const
448 {
449 const Functions& wgl = m_core->getLibrary()->getFunctions();
450 if (!wgl.swapLayerBuffers(m_deviceCtx, WGL_SWAP_MAIN_PLANE))
451 throw ResourceError("wglSwapBuffers() failed");
452 }
453
choosePixelFormat(const Core & wgl,HDC deviceCtx,const glu::RenderConfig & config)454 int choosePixelFormat (const Core& wgl, HDC deviceCtx, const glu::RenderConfig& config)
455 {
456 std::vector<int> pixelFormats = wgl.getPixelFormats(deviceCtx);
457
458 for (std::vector<int>::const_iterator fmtIter = pixelFormats.begin(); fmtIter != pixelFormats.end(); ++fmtIter)
459 {
460 PixelFormatInfo info = wgl.getPixelFormatInfo(deviceCtx, *fmtIter);
461
462 // Base rules: Must be OpenGL-compatible, RGBA, double-buffered, and window-renderable
463 if (!info.supportOpenGL ||
464 !(info.pixelType == wgl::PixelFormatInfo::PIXELTYPE_RGBA) ||
465 !info.doubleBuffer ||
466 !(info.surfaceTypes & wgl::PixelFormatInfo::SURFACE_WINDOW))
467 continue;
468
469 if (config.redBits != glu::RenderConfig::DONT_CARE &&
470 config.redBits != info.redBits)
471 continue;
472
473 if (config.greenBits != glu::RenderConfig::DONT_CARE &&
474 config.greenBits != info.greenBits)
475 continue;
476
477 if (config.blueBits != glu::RenderConfig::DONT_CARE &&
478 config.blueBits != info.blueBits)
479 continue;
480
481 if (config.alphaBits != glu::RenderConfig::DONT_CARE &&
482 config.alphaBits != info.alphaBits)
483 continue;
484
485 if (config.depthBits != glu::RenderConfig::DONT_CARE &&
486 config.depthBits != info.depthBits)
487 continue;
488
489 if (config.stencilBits != glu::RenderConfig::DONT_CARE &&
490 config.stencilBits != info.stencilBits)
491 continue;
492
493 if (config.numSamples != glu::RenderConfig::DONT_CARE &&
494 config.numSamples != info.samples)
495 continue;
496
497 // Passed all tests - select this.
498 return info.pixelFormat;
499 }
500
501 return -1;
502 }
503
504 } // wgl
505 } // tcu
506