1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Linux/BsLinuxContext.h"
4#include "Private/Linux/BsLinuxPlatform.h"
5#include "Linux/BsLinuxGLSupport.h"
6
7namespace bs { namespace ct
8{
9 typedef int(*ErrorHandlerProc)(::Display*, XErrorEvent*);
10 int contextErrorHandler(::Display* display, XErrorEvent* error)
11 {
12 // Do nothing
13 return 0;
14 }
15
16 LinuxContext::LinuxContext(::Display* display, XVisualInfo& visualInfo)
17 : mDisplay(display)
18 {
19 LinuxPlatform::lockX();
20
21 INT32 dummy;
22 XVisualInfo* windowVisualInfo = XGetVisualInfo(display, VisualIDMask | VisualScreenMask, &visualInfo, &dummy);
23
24 INT32 majorVersion, minorVersion;
25 glXQueryVersion(display, &majorVersion, &minorVersion);
26
27 GLXContext context = 0;
28
29 // createContextAttrib was added in GLX version 1.3
30 bool hasCreateContextAttrib = extGLX_ARB_create_context && (majorVersion > 1 || minorVersion >= 3);
31 if(hasCreateContextAttrib)
32 {
33 // Find the config used to create the window's visual
34 GLXFBConfig* windowConfig = nullptr;
35
36 INT32 numConfigs;
37 GLXFBConfig* configs = glXChooseFBConfig(display, DefaultScreen(display), nullptr, &numConfigs);
38
39 for (INT32 i = 0; i < numConfigs; ++i)
40 {
41 XVisualInfo* configVisualInfo = glXGetVisualFromFBConfig(display, configs[i]);
42
43 if(!configVisualInfo)
44 continue;
45
46 if(windowVisualInfo->visualid == configVisualInfo->visualid)
47 {
48 windowConfig = &configs[i];
49 break;
50 }
51 }
52
53 if(windowConfig)
54 {
55 int32_t attributes[] =
56 {
57 GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
58 GLX_CONTEXT_MINOR_VERSION_ARB, 5,
59 0, 0, // Core profile
60 0, 0, // Debug flags
61 0 // Terminator
62 };
63
64 if(extGLX_ARB_create_context_profile)
65 {
66 attributes[4] = GLX_CONTEXT_PROFILE_MASK_ARB;
67 attributes[5] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
68 }
69
70#if BS_DEBUG_MODE
71 attributes[6] = GLX_CONTEXT_FLAGS_ARB;
72 attributes[7] = GLX_CONTEXT_DEBUG_BIT_ARB;
73#endif
74
75 // Add error handler so the application doesn't crash on error
76 ErrorHandlerProc oldErrorHandler = XSetErrorHandler(&contextErrorHandler);
77 context = glXCreateContextAttribsARB(display, *windowConfig, 0, True, attributes);
78 XSetErrorHandler(oldErrorHandler);
79 }
80
81 XFree(configs);
82 }
83
84 // If createContextAttribs failed or isn't supported, fall back to glXCreateContext
85 if(!context)
86 context = glXCreateContext(display, windowVisualInfo, 0, True);
87
88 XFree(windowVisualInfo);
89
90 mContext = context;
91
92 LinuxPlatform::unlockX();
93 }
94
95 LinuxContext::~LinuxContext()
96 {
97 releaseContext();
98 }
99
100 void LinuxContext::setCurrent(const RenderWindow& window)
101 {
102 window.getCustomAttribute("WINDOW", &mCurrentWindow);
103
104 LinuxPlatform::lockX();
105 glXMakeCurrent(mDisplay, mCurrentWindow, mContext);
106 LinuxPlatform::unlockX();
107 }
108
109 void LinuxContext::endCurrent()
110 {
111 LinuxPlatform::lockX();
112 glXMakeCurrent(mDisplay, 0, 0);
113 LinuxPlatform::unlockX();
114 }
115
116 void LinuxContext::releaseContext()
117 {
118 if (mContext)
119 {
120 LinuxPlatform::lockX();
121
122 glXDestroyContext(mDisplay, mContext);
123 mContext = 0;
124
125 LinuxPlatform::unlockX();
126 }
127 }
128}}