1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4     (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
8 Copyright (c) 2000-2014 Torus Knot Software Ltd
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 THE SOFTWARE.
27 -----------------------------------------------------------------------------
28 */
29 
30 #include "OgreException.h"
31 #include "OgreLogManager.h"
32 #include "OgreStringConverter.h"
33 #include "OgreRoot.h"
34 
35 #include "OgreX11EGLSupport.h"
36 #include "OgreX11EGLWindow.h"
37 #include "OgreX11EGLRenderTexture.h"
38 
39 #include "OgreGLUtil.h"
40 
41 #include <X11/extensions/Xrandr.h>
42 
43 namespace Ogre {
getGLSupport(int profile)44     GLNativeSupport* getGLSupport(int profile)
45     {
46         return new X11EGLSupport(profile);
47     }
48 
X11EGLSupport(int profile)49     X11EGLSupport::X11EGLSupport(int profile) : EGLSupport(profile)
50     {
51         // A connection that might be shared with the application for GL rendering:
52         mGLDisplay = getGLDisplay();
53 
54         // A connection that is NOT shared to enable independent event processing:
55         mNativeDisplay = getNativeDisplay();
56 
57         int dummy;
58 
59         if (XQueryExtension(mNativeDisplay, "RANDR", &dummy, &dummy, &dummy))
60         {
61             XRRScreenConfiguration *screenConfig;
62 
63             screenConfig = XRRGetScreenInfo(mNativeDisplay, DefaultRootWindow(mNativeDisplay));
64 
65             if (screenConfig)
66             {
67                 XRRScreenSize *screenSizes;
68                 int nSizes = 0;
69                 Rotation currentRotation;
70                 int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, &currentRotation);
71 
72                 screenSizes = XRRConfigSizes(screenConfig, &nSizes);
73 
74                 mCurrentMode.width = screenSizes[currentSizeID].width;
75                 mCurrentMode.height = screenSizes[currentSizeID].height;
76                 mCurrentMode.refreshRate = XRRConfigCurrentRate(screenConfig);
77 
78                 mOriginalMode = mCurrentMode;
79 
80                 for (int sizeID = 0; sizeID < nSizes; sizeID++)
81                 {
82                     short *rates;
83                     int nRates = 0;
84 
85                     rates = XRRConfigRates(screenConfig, sizeID, &nRates);
86 
87                     for (int rate = 0; rate < nRates; rate++)
88                     {
89                         VideoMode mode;
90 
91                         mode.width = screenSizes[sizeID].width;
92                         mode.height = screenSizes[sizeID].height;
93                         mode.refreshRate = rates[rate];
94 
95                         mVideoModes.push_back(mode);
96                     }
97                 }
98                 XRRFreeScreenConfigInfo(screenConfig);
99             }
100         } else
101         {
102             mCurrentMode.width = DisplayWidth(mNativeDisplay, DefaultScreen(mNativeDisplay));
103             mCurrentMode.height = DisplayHeight(mNativeDisplay, DefaultScreen(mNativeDisplay));
104             mCurrentMode.refreshRate = 0;
105 
106             mOriginalMode = mCurrentMode;
107 
108             mVideoModes.push_back(mCurrentMode);
109         }
110 
111         EGLConfig *glConfigs;
112         int config, nConfigs = 0;
113 
114         glConfigs = chooseGLConfig(NULL, &nConfigs);
115 
116         for (config = 0; config < nConfigs; config++)
117         {
118             int caveat, samples;
119 
120             getGLConfigAttrib(glConfigs[config], EGL_CONFIG_CAVEAT, &caveat);
121 
122             if (caveat != EGL_SLOW_CONFIG)
123             {
124                 getGLConfigAttrib(glConfigs[config], EGL_SAMPLES, &samples);
125                 mFSAALevels.push_back(samples);
126             }
127         }
128 
129         free(glConfigs);
130     }
131 
~X11EGLSupport()132     X11EGLSupport::~X11EGLSupport()
133     {
134         if (mNativeDisplay)
135         {
136             XCloseDisplay((Display*)mNativeDisplay);
137         }
138 
139         if (mGLDisplay)
140         {
141             eglTerminate(mGLDisplay);
142         }
143     }
144 
getNativeDisplay()145     NativeDisplayType X11EGLSupport::getNativeDisplay()
146     {
147         if (!mNativeDisplay)
148         {
149         mNativeDisplay = (NativeDisplayType)XOpenDisplay(NULL);
150 
151             if (!mNativeDisplay)
152             {
153                 OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
154                             "Couldn`t open X display",
155                             "X11EGLSupport::getXDisplay");
156             }
157 
158             mAtomDeleteWindow = XInternAtom((Display*)mNativeDisplay, "WM_DELETE_WINDOW", True);
159             mAtomFullScreen = XInternAtom((Display*)mNativeDisplay, "_NET_WM_STATE_FULLSCREEN", True);
160             mAtomState = XInternAtom((Display*)mNativeDisplay, "_NET_WM_STATE", True);
161         }
162 
163         return mNativeDisplay;
164     }
165 
getDisplayName(void)166     String X11EGLSupport::getDisplayName(void)
167     {
168         return String((const char*)XDisplayName(DisplayString(mNativeDisplay)));
169     }
170 
171 
switchMode(uint & width,uint & height,short & frequency)172     void X11EGLSupport::switchMode(uint& width, uint& height, short& frequency)
173     {
174         int size = 0;
175 
176         EGLVideoModes eglVideoModes(mVideoModes.begin(), mVideoModes.end());
177         EGLVideoModes::iterator mode;
178         EGLVideoModes::iterator end = eglVideoModes.end();
179         EGLVideoMode *newMode = 0;
180 
181         for(mode = eglVideoModes.begin(); mode != end; size++)
182         {
183             if (mode->first.first >= width &&
184                 mode->first.second >= height)
185             {
186                 if (!newMode ||
187                     mode->first.first < newMode->first.first ||
188                     mode->first.second < newMode->first.second)
189                 {
190                     newMode = &(*mode);
191                 }
192             }
193 
194             EGLVideoMode* lastMode = &(*mode);
195 
196             while (++mode != end && mode->first == lastMode->first)
197             {
198                 if (lastMode == newMode && mode->second == frequency)
199                 {
200                     newMode = &(*mode);
201                 }
202             }
203         }
204 
205         if (newMode && *newMode != mCurrentMode)
206         {
207             newMode->first.first = DisplayWidth(mNativeDisplay, 0);
208             newMode->first.second = DisplayHeight(mNativeDisplay, 0);
209             newMode->second = 0; // TODO: Hardcoding refresh rate for LCD's
210             mCurrentMode = {newMode->first.first, newMode->first.second, newMode->second};
211         }
212     }
213 
getVisualFromFBConfig(::EGLConfig glConfig)214     XVisualInfo *X11EGLSupport::getVisualFromFBConfig(::EGLConfig glConfig)
215     {
216         XVisualInfo *vi, tmp;
217         int vid, n;
218         ::EGLDisplay glDisplay;
219 
220         glDisplay = getGLDisplay();
221         mNativeDisplay = getNativeDisplay();
222 
223         if (eglGetConfigAttrib(glDisplay, glConfig, EGL_NATIVE_VISUAL_ID, &vid) == EGL_FALSE)
224         {
225             OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Fail to get VISUAL_ID from glConfig");
226             return 0;
227         }
228         EGL_CHECK_ERROR
229 
230         if (vid == 0)
231         {
232             const int screen_number = DefaultScreen(mNativeDisplay);
233             Visual *v = DefaultVisual((Display*)mNativeDisplay, screen_number);
234             vid = XVisualIDFromVisual(v);
235         }
236 
237         tmp.visualid = vid;
238         vi = 0;
239         vi = XGetVisualInfo((Display*)mNativeDisplay,
240                             VisualIDMask,
241                             &tmp, &n);
242         if (vi == 0)
243         {
244             OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Fail to get X11 VISUAL");
245             return 0;
246         }
247 
248         return vi;
249     }
250 
newWindow(const String & name,unsigned int width,unsigned int height,bool fullScreen,const NameValuePairList * miscParams)251     RenderWindow* X11EGLSupport::newWindow(const String &name,
252                                         unsigned int width, unsigned int height,
253                                         bool fullScreen,
254                                         const NameValuePairList *miscParams)
255     {
256         EGLWindow* window = new X11EGLWindow(this);
257         window->create(name, width, height, fullScreen, miscParams);
258 
259         return window;
260     }
261 
262     //X11EGLSupport::getGLDisplay sets up the native variable
263     //then calls EGLSupport::getGLDisplay
getGLDisplay()264     EGLDisplay X11EGLSupport::getGLDisplay()
265     {
266         if (!mGLDisplay)
267         {
268             if(!mNativeDisplay)
269                 mNativeDisplay = getNativeDisplay();
270             return EGLSupport::getGLDisplay();
271         }
272         return mGLDisplay;
273     }
274 
275 }
276 
277