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 Platform that uses X11 via GLX. 22 *//*--------------------------------------------------------------------*/ 23 24#include "tcuLnxX11GlxPlatform.hpp" 25 26#include "tcuRenderTarget.hpp" 27#include "glwInitFunctions.hpp" 28#include "deUniquePtr.hpp" 29#include "glwEnums.hpp" 30 31#include <sstream> 32#include <iterator> 33#include <set> 34 35#define GLX_GLXEXT_PROTOTYPES 36#include <GL/glx.h> 37 38#ifndef GLX_CONTEXT_OPENGL_NO_ERROR_ARB 39#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 40#endif 41 42namespace tcu 43{ 44namespace lnx 45{ 46namespace x11 47{ 48namespace glx 49{ 50 51using de::UniquePtr; 52using de::MovePtr; 53using glu::ApiType; 54using glu::ContextFactory; 55using glu::ContextType; 56using glu::RenderConfig; 57using glu::RenderContext; 58using tcu::CommandLine; 59using tcu::RenderTarget; 60using std::string; 61using std::set; 62using std::istringstream; 63using std::ostringstream; 64using std::istream_iterator; 65 66typedef RenderConfig::Visibility Visibility; 67 68 69template<typename T> 70static inline T checkGLX(T value, const char* expr, const char* file, int line) 71{ 72 if (!value) 73 throw tcu::TestError("GLX call failed", expr, file, line); 74 return value; 75} 76 77#define TCU_CHECK_GLX(EXPR) checkGLX(EXPR, #EXPR, __FILE__, __LINE__) 78#define TCU_CHECK_GLX_CONFIG(EXPR) checkGLX((EXPR) == Success, #EXPR, __FILE__, __LINE__) 79 80class GlxContextFactory : public glu::ContextFactory 81{ 82public: 83 GlxContextFactory (EventState& eventState); 84 ~GlxContextFactory (void); 85 RenderContext* createContext (const RenderConfig& config, 86 const CommandLine& cmdLine) const; 87 88 EventState& getEventState (void) const { return m_eventState;} 89 90 const PFNGLXCREATECONTEXTATTRIBSARBPROC 91 m_glXCreateContextAttribsARB; 92 93private: 94 EventState& m_eventState; 95}; 96 97class GlxDisplay : public XlibDisplay 98{ 99public: 100 GlxDisplay (EventState& eventState, 101 const char* name); 102 int getGlxMajorVersion (void) const { return m_majorVersion; } 103 int getGlxMinorVersion (void) const { return m_minorVersion; } 104 bool isGlxExtensionSupported (const char* extName) const; 105 106private: 107 int m_errorBase; 108 int m_eventBase; 109 int m_majorVersion; 110 int m_minorVersion; 111 set<string> m_extensions; 112}; 113 114class GlxVisual 115{ 116public: 117 GlxVisual (GlxDisplay& display, GLXFBConfig fbConfig); 118 int getAttrib (int attribute); 119 Visual* getXVisual (void) { return m_visual; } 120 GLXContext createContext (const GlxContextFactory& factory, 121 const ContextType& contextType, 122 glu::ResetNotificationStrategy resetNotificationStrategy); 123 GLXWindow createWindow (::Window xWindow); 124 GlxDisplay& getGlxDisplay (void) { return m_display; } 125 ::Display* getXDisplay (void) { return m_display.getXDisplay(); } 126 127private: 128 GlxDisplay& m_display; 129 ::Visual* m_visual; 130 const GLXFBConfig m_fbConfig; 131}; 132 133class GlxDrawable 134{ 135public: 136 virtual ~GlxDrawable (void) {} 137 138 virtual void processEvents (void) {} 139 virtual void getDimensions (int* width, int* height) = 0; 140 int getWidth (void); 141 int getHeight (void); 142 void swapBuffers (void) { glXSwapBuffers(getXDisplay(), getGLXDrawable()); } 143 144 virtual ::Display* getXDisplay (void) = 0; 145 virtual GLXDrawable getGLXDrawable (void) = 0; 146 147protected: 148 GlxDrawable () {} 149 unsigned int getAttrib (int attribute); 150}; 151 152class GlxWindow : public GlxDrawable 153{ 154public: 155 GlxWindow (GlxVisual& visual, const RenderConfig& cfg); 156 ~GlxWindow (void); 157 void processEvents (void) { m_x11Window.processEvents(); } 158 ::Display* getXDisplay (void) { return m_x11Display.getXDisplay(); } 159 void getDimensions (int* width, int* height); 160 161protected: 162 GLXDrawable getGLXDrawable () { return m_GLXDrawable; } 163 164private: 165 XlibDisplay& m_x11Display; 166 XlibWindow m_x11Window; 167 const GLXDrawable m_GLXDrawable; 168}; 169 170class GlxRenderContext : public RenderContext 171{ 172public: 173 GlxRenderContext (const GlxContextFactory& factory, 174 const RenderConfig& config); 175 ~GlxRenderContext (void); 176 virtual ContextType getType (void) const; 177 virtual void postIterate (void); 178 virtual void makeCurrent (void); 179 void clearCurrent (void); 180 virtual const glw::Functions& getFunctions (void) const; 181 virtual const tcu::RenderTarget& getRenderTarget (void) const; 182 183private: 184 GlxDisplay m_glxDisplay; 185 GlxVisual m_glxVisual; 186 ContextType m_type; 187 GLXContext m_GLXContext; 188 UniquePtr<GlxDrawable> m_glxDrawable; 189 RenderTarget m_renderTarget; 190 glw::Functions m_functions; 191}; 192 193extern "C" 194{ 195 static int tcuLnxX11GlxErrorHandler (::Display* display, XErrorEvent* event) 196 { 197 char buf[80]; 198 XGetErrorText(display, event->error_code, buf, sizeof(buf)); 199 tcu::print("X operation %u:%u failed: %s\n", 200 event->request_code, event->minor_code, buf); 201 return 0; 202 } 203} 204 205GlxContextFactory::GlxContextFactory (EventState& eventState) 206 : glu::ContextFactory ("glx", "X11 GLX OpenGL Context") 207 , m_glXCreateContextAttribsARB ( 208 reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>( 209 TCU_CHECK_GLX( 210 glXGetProcAddress( 211 reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"))))) 212 , m_eventState (eventState) 213{ 214 XSetErrorHandler(tcuLnxX11GlxErrorHandler); 215} 216 217RenderContext* GlxContextFactory::createContext (const RenderConfig& config, 218 const CommandLine& cmdLine) const 219{ 220 DE_UNREF(cmdLine); 221 GlxRenderContext* const renderContext = new GlxRenderContext(*this, config); 222 return renderContext; 223} 224 225GlxContextFactory::~GlxContextFactory (void) 226{ 227} 228 229GlxDisplay::GlxDisplay (EventState& eventState, const char* name) 230 : XlibDisplay (eventState, name) 231{ 232 const Bool supported = glXQueryExtension(m_display, &m_errorBase, &m_eventBase); 233 if (!supported) 234 TCU_THROW(NotSupportedError, "GLX protocol not supported by X server"); 235 236 TCU_CHECK_GLX(glXQueryVersion(m_display, &m_majorVersion, &m_minorVersion)); 237 238 { 239 const int screen = XDefaultScreen(m_display); 240 // nVidia doesn't seem to report client-side extensions correctly, 241 // so only use server side 242 const char* const extensions = 243 TCU_CHECK_GLX(glXQueryServerString(m_display, screen, GLX_EXTENSIONS)); 244 istringstream extStream(extensions); 245 m_extensions = set<string>(istream_iterator<string>(extStream), 246 istream_iterator<string>()); 247 } 248} 249 250 251bool GlxDisplay::isGlxExtensionSupported (const char* extName) const 252{ 253 return m_extensions.find(extName) != m_extensions.end(); 254} 255 256//! Throw `tcu::NotSupportedError` if `dpy` is not compatible with GLX 257//! version `major`.`minor`. 258static void checkGlxVersion (const GlxDisplay& dpy, int major, int minor) 259{ 260 const int dpyMajor = dpy.getGlxMajorVersion(); 261 const int dpyMinor = dpy.getGlxMinorVersion(); 262 if (!(dpyMajor == major && dpyMinor >= minor)) 263 { 264 ostringstream oss; 265 oss << "Server GLX version " 266 << dpyMajor << "." << dpyMinor 267 << " not compatible with required version " 268 << major << "." << minor; 269 TCU_THROW(NotSupportedError, oss.str().c_str()); 270 } 271} 272 273//! Throw `tcu::NotSupportedError` if `dpy` does not support extension `extName`. 274static void checkGlxExtension (const GlxDisplay& dpy, const char* extName) 275{ 276 if (!dpy.isGlxExtensionSupported(extName)) 277 { 278 ostringstream oss; 279 oss << "GLX extension \"" << extName << "\" not supported"; 280 TCU_THROW(NotSupportedError, oss.str().c_str()); 281 } 282} 283 284GlxVisual::GlxVisual (GlxDisplay& display, GLXFBConfig fbConfig) 285 : m_display (display) 286 , m_visual (DE_NULL) 287 , m_fbConfig (fbConfig) 288{ 289 XVisualInfo* visualInfo = glXGetVisualFromFBConfig(getXDisplay(), fbConfig); 290 291 if (!visualInfo) 292 TCU_THROW(ResourceError, "glXGetVisualFromFBConfig() returned NULL"); 293 294 m_visual = visualInfo->visual; 295 XFree(visualInfo); 296} 297 298int GlxVisual::getAttrib (int attribute) 299{ 300 int fbvalue; 301 TCU_CHECK_GLX_CONFIG(glXGetFBConfigAttrib(getXDisplay(), m_fbConfig, attribute, &fbvalue)); 302 return fbvalue; 303} 304 305GLXContext GlxVisual::createContext (const GlxContextFactory& factory, 306 const ContextType& contextType, 307 glu::ResetNotificationStrategy resetNotificationStrategy) 308{ 309 std::vector<int> attribs; 310 311 checkGlxVersion(m_display, 1, 4); 312 checkGlxExtension(m_display, "GLX_ARB_create_context"); 313 checkGlxExtension(m_display, "GLX_ARB_create_context_profile"); 314 315 { 316 const ApiType apiType = contextType.getAPI(); 317 int profileMask = 0; 318 319 switch (apiType.getProfile()) 320 { 321 case glu::PROFILE_ES: 322 checkGlxExtension(m_display, "GLX_EXT_create_context_es2_profile"); 323 profileMask = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; 324 break; 325 case glu::PROFILE_CORE: 326 profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; 327 break; 328 case glu::PROFILE_COMPATIBILITY: 329 profileMask = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; 330 break; 331 default: 332 DE_FATAL("Impossible context profile"); 333 } 334 335 attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); 336 attribs.push_back(apiType.getMajorVersion()); 337 attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); 338 attribs.push_back(apiType.getMinorVersion()); 339 attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); 340 attribs.push_back(profileMask); 341 } 342 343 // Context flags 344 { 345 int flags = 0; 346 347 if ((contextType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0) 348 { 349 if (glu::isContextTypeES(contextType)) 350 TCU_THROW(InternalError, "Only OpenGL core contexts can be forward-compatible"); 351 352 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 353 } 354 355 if ((contextType.getFlags() & glu::CONTEXT_DEBUG) != 0) 356 flags |= GLX_CONTEXT_DEBUG_BIT_ARB; 357 358 if ((contextType.getFlags() & glu::CONTEXT_ROBUST) != 0) 359 flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; 360 361 if ((contextType.getFlags() & glu::CONTEXT_NO_ERROR) != 0) 362 { 363 if (m_display.isGlxExtensionSupported("GLX_ARB_create_context_no_error")) 364 { 365 attribs.push_back(GLX_CONTEXT_OPENGL_NO_ERROR_ARB); 366 attribs.push_back(True); 367 } 368 else 369 TCU_THROW(NotSupportedError, "GLX_ARB_create_context_no_error is required for creating no-error contexts"); 370 } 371 372 if (flags != 0) 373 { 374 attribs.push_back(GLX_CONTEXT_FLAGS_ARB); 375 attribs.push_back(flags); 376 } 377 } 378 379 if (resetNotificationStrategy != glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED) 380 { 381 attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB); 382 383 if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION) 384 attribs.push_back(GLX_NO_RESET_NOTIFICATION_ARB); 385 else if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET) 386 attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB); 387 else 388 TCU_THROW(InternalError, "Unknown reset notification strategy"); 389 } 390 391 // Terminate attrib list 392 attribs.push_back(None); 393 394 return TCU_CHECK_GLX(factory.m_glXCreateContextAttribsARB( 395 getXDisplay(), m_fbConfig, DE_NULL, True, &attribs[0])); 396} 397 398GLXWindow GlxVisual::createWindow (::Window xWindow) 399{ 400 return TCU_CHECK_GLX(glXCreateWindow(getXDisplay(), m_fbConfig, xWindow, NULL)); 401} 402 403unsigned GlxDrawable::getAttrib (int attrib) 404{ 405 unsigned int value = 0; 406 glXQueryDrawable(getXDisplay(), getGLXDrawable(), attrib, &value); 407 return value; 408} 409 410int GlxDrawable::getWidth (void) 411{ 412 int width = 0; 413 getDimensions(&width, DE_NULL); 414 return width; 415} 416 417int GlxDrawable::getHeight (void) 418{ 419 int height = 0; 420 getDimensions(DE_NULL, &height); 421 return height; 422} 423 424GlxWindow::GlxWindow (GlxVisual& visual, const RenderConfig& cfg) 425 : m_x11Display (visual.getGlxDisplay()) 426 , m_x11Window (m_x11Display, cfg.width, cfg.height, 427 visual.getXVisual()) 428 , m_GLXDrawable (visual.createWindow(m_x11Window.getXID())) 429{ 430 m_x11Window.setVisibility(cfg.windowVisibility != RenderConfig::VISIBILITY_HIDDEN); 431} 432 433void GlxWindow::getDimensions (int* width, int* height) 434{ 435 if (width != DE_NULL) 436 *width = getAttrib(GLX_WIDTH); 437 if (height != DE_NULL) 438 *height = getAttrib(GLX_HEIGHT); 439 440 // glXQueryDrawable may be buggy, so fall back to X geometry if needed 441 if ((width != DE_NULL && *width == 0) || (height != DE_NULL && *height == 0)) 442 m_x11Window.getDimensions(width, height); 443} 444 445GlxWindow::~GlxWindow (void) 446{ 447 glXDestroyWindow(m_x11Display.getXDisplay(), m_GLXDrawable); 448} 449 450static const struct Attribute 451{ 452 int glxAttribute; 453 int RenderConfig::* cfgMember; 454} s_attribs[] = 455{ 456 { GLX_RED_SIZE, &RenderConfig::redBits }, 457 { GLX_GREEN_SIZE, &RenderConfig::greenBits }, 458 { GLX_BLUE_SIZE, &RenderConfig::blueBits }, 459 { GLX_ALPHA_SIZE, &RenderConfig::alphaBits }, 460 { GLX_DEPTH_SIZE, &RenderConfig::depthBits }, 461 { GLX_STENCIL_SIZE, &RenderConfig::stencilBits }, 462 { GLX_SAMPLES, &RenderConfig::numSamples }, 463 { GLX_FBCONFIG_ID, &RenderConfig::id }, 464}; 465 466static deUint32 surfaceTypeToDrawableBits (RenderConfig::SurfaceType type) 467{ 468 switch (type) 469 { 470 case RenderConfig::SURFACETYPE_WINDOW: 471 return GLX_WINDOW_BIT; 472 case RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE: 473 return GLX_PIXMAP_BIT; 474 case RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC: 475 return GLX_PBUFFER_BIT; 476 case RenderConfig::SURFACETYPE_DONT_CARE: 477 return GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 478 default: 479 DE_FATAL("Impossible case"); 480 } 481 return 0; 482} 483 484static bool configMatches (GlxVisual& visual, const RenderConfig& renderCfg) 485{ 486 if (renderCfg.id != RenderConfig::DONT_CARE) 487 return visual.getAttrib(GLX_FBCONFIG_ID) == renderCfg.id; 488 489 for (const Attribute* it = DE_ARRAY_BEGIN(s_attribs); it != DE_ARRAY_END(s_attribs); it++) 490 { 491 const int requested = renderCfg.*it->cfgMember; 492 if (requested != RenderConfig::DONT_CARE && 493 requested != visual.getAttrib(it->glxAttribute)) 494 return false; 495 } 496 497 { 498 deUint32 bits = surfaceTypeToDrawableBits(renderCfg.surfaceType); 499 500 if ((visual.getAttrib(GLX_DRAWABLE_TYPE) & bits) == 0) 501 return false; 502 503 // It shouldn't be possible to have GLX_WINDOW_BIT set without a visual, 504 // but let's make sure. 505 if (renderCfg.surfaceType == RenderConfig::SURFACETYPE_WINDOW && 506 visual.getXVisual() == DE_NULL) 507 return false; 508 } 509 510 return true; 511} 512 513class Rank 514{ 515public: 516 Rank (void) : m_value(0), m_bitsLeft(64) {} 517 void add (size_t bits, deUint32 value); 518 void sub (size_t bits, deUint32 value); 519 deUint64 getValue (void) { return m_value; } 520 521private: 522 deUint64 m_value; 523 size_t m_bitsLeft; 524}; 525 526void Rank::add (size_t bits, deUint32 value) 527{ 528 TCU_CHECK_INTERNAL(m_bitsLeft >= bits); 529 m_bitsLeft -= bits; 530 m_value = m_value << bits | de::min((1U << bits) - 1, value); 531} 532 533void Rank::sub (size_t bits, deUint32 value) 534{ 535 TCU_CHECK_INTERNAL(m_bitsLeft >= bits); 536 m_bitsLeft -= bits; 537 m_value = m_value << bits | ((1U << bits) - 1 - de::min((1U << bits) - 1U, value)); 538} 539 540static deUint64 configRank (GlxVisual& visual) 541{ 542 // Sanity checks. 543 if (visual.getAttrib(GLX_DOUBLEBUFFER) == False || 544 (visual.getAttrib(GLX_RENDER_TYPE) & GLX_RGBA_BIT) == 0) 545 return 0; 546 547 Rank rank; 548 int caveat = visual.getAttrib(GLX_CONFIG_CAVEAT); 549 int redSize = visual.getAttrib(GLX_RED_SIZE); 550 int greenSize = visual.getAttrib(GLX_GREEN_SIZE); 551 int blueSize = visual.getAttrib(GLX_BLUE_SIZE); 552 int alphaSize = visual.getAttrib(GLX_ALPHA_SIZE); 553 int depthSize = visual.getAttrib(GLX_DEPTH_SIZE); 554 int stencilSize = visual.getAttrib(GLX_STENCIL_SIZE); 555 int minRGB = de::min(redSize, de::min(greenSize, blueSize)); 556 557 // Prefer conformant configurations. 558 rank.add(1, (caveat != GLX_NON_CONFORMANT_CONFIG)); 559 560 // Prefer non-transparent configurations. 561 rank.add(1, visual.getAttrib(GLX_TRANSPARENT_TYPE) == GLX_NONE); 562 563 // Avoid stereo 564 rank.add(1, visual.getAttrib(GLX_STEREO) == False); 565 566 // Avoid overlays 567 rank.add(1, visual.getAttrib(GLX_LEVEL) == 0); 568 569 // Prefer to have some alpha. 570 rank.add(1, alphaSize > 0); 571 572 // Prefer to have a depth buffer. 573 rank.add(1, depthSize > 0); 574 575 // Prefer to have a stencil buffer. 576 rank.add(1, stencilSize > 0); 577 578 // Avoid slow configurations. 579 rank.add(1, (caveat != GLX_SLOW_CONFIG)); 580 581 // Prefer larger, evenly distributed color depths 582 rank.add(4, de::min(minRGB, alphaSize)); 583 584 // If alpha is low, choose best RGB 585 rank.add(4, minRGB); 586 587 // Prefer larger depth and stencil buffers 588 rank.add(6, deUint32(depthSize + stencilSize)); 589 590 // Avoid excessive sampling 591 rank.sub(5, visual.getAttrib(GLX_SAMPLES)); 592 593 // Prefer True/DirectColor 594 int visualType = visual.getAttrib(GLX_X_VISUAL_TYPE); 595 rank.add(1, visualType == GLX_TRUE_COLOR || visualType == GLX_DIRECT_COLOR); 596 597 return rank.getValue(); 598} 599 600static GlxVisual chooseVisual (GlxDisplay& display, const RenderConfig& cfg) 601{ 602 ::Display* dpy = display.getXDisplay(); 603 deUint64 maxRank = 0; 604 GLXFBConfig maxConfig = DE_NULL; 605 int numElems = 0; 606 607 GLXFBConfig* const fbConfigs = glXGetFBConfigs(dpy, DefaultScreen(dpy), &numElems); 608 TCU_CHECK_MSG(fbConfigs != DE_NULL, "Couldn't query framebuffer configurations"); 609 610 for (int i = 0; i < numElems; i++) 611 { 612 try 613 { 614 GlxVisual visual(display, fbConfigs[i]); 615 616 if (!configMatches(visual, cfg)) 617 continue; 618 619 deUint64 cfgRank = configRank(visual); 620 621 if (cfgRank > maxRank) 622 { 623 maxRank = cfgRank; 624 maxConfig = fbConfigs[i]; 625 } 626 } 627 catch (const tcu::ResourceError&) 628 { 629 // Some drivers report invalid visuals. Ignore them. 630 } 631 } 632 XFree(fbConfigs); 633 634 if (maxRank == 0) 635 TCU_THROW(NotSupportedError, "Requested GLX configuration not found or unusable"); 636 637 return GlxVisual(display, maxConfig); 638} 639 640GlxDrawable* createDrawable (GlxVisual& visual, const RenderConfig& config) 641{ 642 RenderConfig::SurfaceType surfaceType = config.surfaceType; 643 644 if (surfaceType == RenderConfig::SURFACETYPE_DONT_CARE) 645 { 646 if (visual.getXVisual() == DE_NULL) 647 // No visual, cannot create X window 648 surfaceType = RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE; 649 else 650 surfaceType = RenderConfig::SURFACETYPE_WINDOW; 651 } 652 653 switch (surfaceType) 654 { 655 case RenderConfig::SURFACETYPE_DONT_CARE: 656 DE_FATAL("Impossible case"); 657 658 case RenderConfig::SURFACETYPE_WINDOW: 659 return new GlxWindow(visual, config); 660 break; 661 662 case RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE: 663 // \todo [2013-11-28 lauri] Pixmaps 664 665 case RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC: 666 // \todo [2013-11-28 lauri] Pbuffers 667 668 default: 669 TCU_THROW(NotSupportedError, "Unsupported surface type"); 670 } 671 672 return DE_NULL; 673} 674 675struct GlxFunctionLoader : public glw::FunctionLoader 676{ 677 GlxFunctionLoader (void) {} 678 679 glw::GenericFuncType get (const char* name) const 680 { 681 return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name)); 682 } 683}; 684 685GlxRenderContext::GlxRenderContext (const GlxContextFactory& factory, 686 const RenderConfig& config) 687 : m_glxDisplay (factory.getEventState(), DE_NULL) 688 , m_glxVisual (chooseVisual(m_glxDisplay, config)) 689 , m_type (config.type) 690 , m_GLXContext (m_glxVisual.createContext(factory, config.type, config.resetNotificationStrategy)) 691 , m_glxDrawable (createDrawable(m_glxVisual, config)) 692 , m_renderTarget (m_glxDrawable->getWidth(), m_glxDrawable->getHeight(), 693 PixelFormat(m_glxVisual.getAttrib(GLX_RED_SIZE), 694 m_glxVisual.getAttrib(GLX_GREEN_SIZE), 695 m_glxVisual.getAttrib(GLX_BLUE_SIZE), 696 m_glxVisual.getAttrib(GLX_ALPHA_SIZE)), 697 m_glxVisual.getAttrib(GLX_DEPTH_SIZE), 698 m_glxVisual.getAttrib(GLX_STENCIL_SIZE), 699 m_glxVisual.getAttrib(GLX_SAMPLES)) 700{ 701 const GlxFunctionLoader loader; 702 makeCurrent(); 703 glu::initFunctions(&m_functions, &loader, config.type.getAPI()); 704} 705 706GlxRenderContext::~GlxRenderContext (void) 707{ 708 clearCurrent(); 709 if (m_GLXContext != DE_NULL) 710 glXDestroyContext(m_glxDisplay.getXDisplay(), m_GLXContext); 711} 712 713void GlxRenderContext::makeCurrent (void) 714{ 715 const GLXDrawable drawRead = m_glxDrawable->getGLXDrawable(); 716 TCU_CHECK_GLX(glXMakeContextCurrent(m_glxDisplay.getXDisplay(), 717 drawRead, drawRead, m_GLXContext)); 718} 719 720void GlxRenderContext::clearCurrent (void) 721{ 722 TCU_CHECK_GLX(glXMakeContextCurrent(m_glxDisplay.getXDisplay(), 723 None, None, DE_NULL)); 724} 725 726ContextType GlxRenderContext::getType (void) const 727{ 728 return m_type; 729} 730 731void GlxRenderContext::postIterate (void) 732{ 733 m_glxDrawable->swapBuffers(); 734 m_glxDrawable->processEvents(); 735 m_glxDisplay.processEvents(); 736} 737 738const RenderTarget& GlxRenderContext::getRenderTarget (void) const 739{ 740 return m_renderTarget; 741} 742 743const glw::Functions& GlxRenderContext::getFunctions (void) const 744{ 745 return m_functions; 746} 747 748MovePtr<ContextFactory> createContextFactory (EventState& eventState) 749{ 750 return MovePtr<ContextFactory>(new GlxContextFactory(eventState)); 751} 752 753} // glx 754} // x11 755} // lnx 756} // tcu 757