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 112DE_BEGIN_EXTERN_C 113 114// WGL core 115typedef HGLRC (WINAPI* wglCreateContextFunc) (HDC hdc); 116typedef BOOL (WINAPI* wglDeleteContextFunc) (HGLRC hglrc); 117typedef BOOL (WINAPI* wglMakeCurrentFunc) (HDC hdc, HGLRC hglrc); 118typedef PROC (WINAPI* wglGetProcAddressFunc) (LPCSTR lpszProc); 119typedef BOOL (WINAPI* wglSwapLayerBuffersFunc) (HDC dhc, UINT fuPlanes); 120 121// WGL_ARB_pixel_format 122typedef BOOL (WINAPI* wglGetPixelFormatAttribivARBFunc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); 123typedef BOOL (WINAPI* wglGetPixelFormatAttribfvARBFunc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); 124typedef BOOL (WINAPI* wglChoosePixelFormatARBFunc) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 125 126// WGL_ARB_create_context 127typedef HGLRC (WINAPI* wglCreateContextAttribsARBFunc) (HDC hdc, HGLRC hshareContext, const int* attribList); 128 129DE_END_EXTERN_C 130 131namespace tcu 132{ 133namespace wgl 134{ 135 136// Functions 137 138struct 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 155 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 171class Library 172{ 173public: 174 Library (HINSTANCE instance); 175 ~Library (void); 176 177 const Functions& getFunctions (void) const { return m_functions; } 178 const de::DynamicLibrary& getGLLibrary (void) const { return m_library; } 179 180private: 181 de::DynamicLibrary m_library; 182 Functions m_functions; 183}; 184 185Library::Library (HINSTANCE instance) 186 : m_library("opengl32.dll") 187{ 188 // Temporary 1x1 window for creating context 189 win32::Window 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 247Library::~Library (void) 248{ 249} 250 251// Core 252 253Core::Core (HINSTANCE instance) 254 : m_library(new Library(instance)) 255{ 256} 257 258Core::~Core (void) 259{ 260 delete m_library; 261} 262 263std::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 281static 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 292static 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 304PixelFormatInfo 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 353Context::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 425Context::~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 433FunctionPtr 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 447void 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 454int 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