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