Refactor X11 and wayland platforms to run alongside each other
[platform/upstream/VK-GL-CTS.git] / framework / platform / lnx / X11 / tcuLnxX11GlxPlatform.cpp
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>
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
83         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);
97         int                                             getGlxMajorVersion              (void) const { return m_majorVersion; }
98         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);
114         Visual*                                 getXVisual                      (void) { return m_visual; }
115         GLXContext                              createContext           (const GlxContextFactory&       factory,
116                                                                                                  const ContextType&                     contextType);
117         GLXWindow                               createWindow            (::Window xWindow);
118         GlxDisplay&                             getGlxDisplay           (void) { return m_display; }
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:
130         virtual                                 ~GlxDrawable            (void) {}
131
132         virtual void                    processEvents           (void) {}
133         virtual void                    getDimensions           (int* width, int* height) = 0;
134         int                                             getWidth                        (void);
135         int                                             getHeight                       (void);
136         void                                    swapBuffers                     (void) { glXSwapBuffers(getXDisplay(), getGLXDrawable()); }
137
138         virtual ::Display*              getXDisplay                     (void) = 0;
139         virtual GLXDrawable             getGLXDrawable          (void) = 0;
140
141 protected:
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);
151         void                                    processEvents           (void) { m_x11Window.processEvents(); }
152         ::Display*                              getXDisplay                     (void) { return m_x11Display.getXDisplay(); }
153         void                                    getDimensions           (int* width, int* height);
154
155 protected:
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 {
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
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
211 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
219 GlxContextFactory::~GlxContextFactory (void)
220 {
221 }
222
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
245 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`.
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`.
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
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
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
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
336 GLXWindow GlxVisual::createWindow (::Window xWindow)
337 {
338         return TCU_CHECK_GLX(glXCreateWindow(getXDisplay(), m_fbConfig, xWindow, NULL));
339 }
340
341 unsigned GlxDrawable::getAttrib (int attrib)
342 {
343         unsigned int value = 0;
344         glXQueryDrawable(getXDisplay(), getGLXDrawable(), attrib, &value);
345         return value;
346 }
347
348 int GlxDrawable::getWidth (void)
349 {
350         int width = 0;
351         getDimensions(&width, DE_NULL);
352         return width;
353 }
354
355 int GlxDrawable::getHeight (void)
356 {
357         int height = 0;
358         getDimensions(DE_NULL, &height);
359         return height;
360 }
361
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
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
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
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
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:
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);
457         deUint64        getValue        (void) { return m_value; }
458
459 private:
460         deUint64        m_value;
461         size_t          m_bitsLeft;
462 };
463
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
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
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
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
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 {
608                                                         GlxFunctionLoader       (void) {}
609
610         glw::GenericFuncType    get                                     (const char* name) const
611         {
612                 return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
613         }
614 };
615
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
637 GlxRenderContext::~GlxRenderContext (void)
638 {
639         clearCurrent();
640         if (m_GLXContext != DE_NULL)
641                 glXDestroyContext(m_glxDisplay.getXDisplay(), m_GLXContext);
642 }
643
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
651 void GlxRenderContext::clearCurrent (void)
652 {
653         TCU_CHECK_GLX(glXMakeContextCurrent(m_glxDisplay.getXDisplay(),
654                                                                                 None, None, DE_NULL));
655 }
656
657 ContextType GlxRenderContext::getType (void) const
658 {
659         return m_type;
660 }
661
662 void GlxRenderContext::postIterate (void)
663 {
664         m_glxDrawable->swapBuffers();
665         m_glxDrawable->processEvents();
666         m_glxDisplay.processEvents();
667 }
668
669 const RenderTarget& GlxRenderContext::getRenderTarget (void) const
670 {
671         return m_renderTarget;
672 }
673
674 const glw::Functions& GlxRenderContext::getFunctions (void) const
675 {
676         return m_functions;
677 }
678
679 MovePtr<ContextFactory> createContextFactory (EventState& eventState)
680 {
681         return MovePtr<ContextFactory>(new GlxContextFactory(eventState));
682 }
683
684 } // glx
685 } // x11
686 } // lnx
687 } // tcu