[ARM] Added neccessary GLES, EGL and other arm related files
[xbmc:xbmc-antiquated.git] / trunk / xbmc / WinSystemEGL.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21 #include "system.h"
22
23 #ifdef HAS_EGL
24
25 #include "WinSystemEGL.h"
26 #include "utils/log.h"
27 #include <SDL/SDL_syswm.h>
28 #include "SpecialProtocol.h"
29 #include "Settings.h"
30 #include "Texture.h"
31 #include "linux/XRandR.h"
32 #include <vector>
33
34 using namespace std;
35
36 // Comment out one of the following defines to select the colourspace to use
37 //#define RGBA8888
38 #define RGB565
39
40 #if defined(RGBA8888)
41 #define RSIZE   8
42 #define GSIZE   8
43 #define BSIZE   8
44 #define ASIZE   8
45 #define DEPTH   8
46 #define BPP             32
47 #elif defined(RGB565)
48 #define RSIZE   5
49 #define GSIZE   6
50 #define BSIZE   5
51 #define ASIZE   0
52 #define DEPTH   16
53 #define BPP             16
54 #endif
55
56 static int configAttributes[] =
57 {
58   EGL_RED_SIZE,                 RSIZE,
59   EGL_GREEN_SIZE,               GSIZE,
60   EGL_BLUE_SIZE,                BSIZE,
61   EGL_ALPHA_SIZE,               ASIZE,
62   EGL_DEPTH_SIZE,               DEPTH,
63   EGL_SAMPLES,                  4,      // 4x AntiAiliasing
64 #if HAS_GLES == 2
65   EGL_RENDERABLE_TYPE,  EGL_OPENGL_ES2_BIT,
66 #endif
67   EGL_NONE
68 };
69
70 static int contextAttributes[] =
71 {
72   EGL_CONTEXT_CLIENT_VERSION,   HAS_GLES,
73   EGL_NONE
74 };
75
76 CWinSystemEGL g_Windowing;
77
78 CWinSystemEGL::CWinSystemEGL() : CWinSystemBase()
79 {
80   m_eWindowSystem = WINDOW_SYSTEM_EGL;
81
82   m_SDLSurface = NULL;
83   m_eglDisplay = NULL;
84   m_eglContext = NULL;
85   m_eglSurface = NULL;
86   m_eglWindow  = NULL;
87   m_dpy        = NULL;
88   
89   m_iVSyncErrors = 0;
90 }
91
92 CWinSystemEGL::~CWinSystemEGL()
93 {
94   DestroyWindowSystem();
95 }
96
97 bool CWinSystemEGL::InitWindowSystem()
98 {
99   EGLBoolean val = false;
100   EGLint maj, min;
101   if ((m_dpy = XOpenDisplay(NULL)) &&
102       (m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_dpy)) &&
103       (val = eglInitialize(m_eglDisplay, &maj, &min)))
104   {
105         SDL_EnableUNICODE(1);
106         // set repeat to 10ms to ensure repeat time < frame time
107         // so that hold times can be reliably detected
108         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 10);
109
110         SDL_GL_SetAttribute(SDL_GL_RED_SIZE,   RSIZE);
111         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, GSIZE);
112         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,  BSIZE);
113         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, ASIZE);
114         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
115
116         return CWinSystemBase::InitWindowSystem();
117   }
118   else
119     CLog::Log(LOGERROR, "EGL Error: No Display found! dpy:%p egl:%p init:%d", m_dpy, m_eglDisplay, val);
120
121   return false;
122 }
123
124 bool CWinSystemEGL::DestroyWindowSystem()
125 {
126   if (m_eglContext)
127     eglDestroyContext(m_eglDisplay, m_eglContext);
128
129   if (m_eglSurface)
130     eglDestroySurface(m_eglDisplay, m_eglSurface);
131
132   // Needed???
133   if (m_eglWindow)
134     XDestroyWindow(m_dpy, m_eglWindow);
135
136   if (m_eglDisplay)
137     eglTerminate(m_eglDisplay);
138
139   if (m_dpy)
140     XCloseDisplay(m_dpy);
141
142   // m_SDLSurface is free()'d by SDL_Quit().
143
144   return true;
145 }
146
147 bool CWinSystemEGL::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction)
148 {
149   if(!SetFullScreen(fullScreen, res, false))
150         return false;
151
152   CTexture iconTexture;
153   iconTexture.LoadFromFile("special://xbmc/media/icon.png");
154
155   SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture.GetPixels(), iconTexture.GetWidth(), iconTexture.GetHeight(), BPP, iconTexture.GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL);
156   SDL_WM_SetCaption("XBMC Media Center", NULL);
157
158   m_bWindowCreated = true;
159
160   m_eglext  = " ";
161   m_eglext += eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
162   m_eglext += " ";
163
164   CLog::Log(LOGDEBUG, "EGL_EXTENSIONS:%s", m_eglext.c_str());
165
166   return true;
167 }
168
169 bool CWinSystemEGL::DestroyWindow()
170 {
171   return true;
172 }
173
174 bool CWinSystemEGL::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
175 {
176   if (m_nWidth != newWidth || m_nHeight != newHeight)
177   {
178     m_nWidth  = newWidth;
179     m_nHeight = newHeight;
180
181     int options = SDL_OPENGL;
182     if (m_bFullScreen)
183       options |= SDL_FULLSCREEN;
184     else
185       options |= SDL_RESIZABLE;
186
187     if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options)))
188     {
189       RefreshEGLContext();
190     }
191   }
192
193   CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight, false, 0);
194
195   return true;
196 }
197
198 bool CWinSystemEGL::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
199 {
200   m_nWidth      = res.iWidth;
201   m_nHeight     = res.iHeight;
202   m_bFullScreen = fullScreen;
203
204 #if defined(HAS_XRANDR)
205
206   if(m_bFullScreen)
207   {
208         XOutput out;
209         XMode mode;
210         out.name = res.strOutput;
211         mode.w   = res.iWidth;
212         mode.h   = res.iHeight;
213         mode.hz  = res.fRefreshRate;
214         mode.id  = res.strId;
215         g_xrandr.SetMode(out, mode);
216   }
217   else
218         g_xrandr.RestoreState();
219
220 #endif
221
222   int options = SDL_OPENGL;
223   if (m_bFullScreen)
224     options |= SDL_FULLSCREEN;
225   else
226     options |= SDL_RESIZABLE;
227
228   if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options)))
229   {
230     RefreshEGLContext();
231   }
232
233   CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate);
234   
235   return true;
236 }
237
238 void CWinSystemEGL::UpdateResolutions()
239 {
240   CWinSystemBase::UpdateResolutions();
241
242 #if defined(HAS_XRANDR)
243   {
244     XOutput out  = g_xrandr.GetCurrentOutput();
245     XMode   mode = g_xrandr.GetCurrentMode(out.name);
246     UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
247     g_settings.m_ResInfo[RES_DESKTOP].strId     = mode.id;
248     g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
249   }
250 #else
251   {
252     int x11screen = DefaultScreen(m_dpy);
253     int w = DisplayWidth(m_dpy, x11screen);
254     int h = DisplayHeight(m_dpy, x11screen);
255     UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0);
256   }
257 #endif
258
259 #if defined(HAS_XRANDR)
260
261   CLog::Log(LOGINFO, "Available videomodes (xrandr):");
262   vector<XOutput>::iterator outiter;
263   vector<XOutput> outs;
264   outs = g_xrandr.GetModes();
265   CLog::Log(LOGINFO, "Number of connected outputs: %"PRIdS"", outs.size());
266   string modename = "";
267
268   for (outiter = outs.begin() ; outiter != outs.end() ; outiter++)
269   {
270     XOutput out = *outiter;
271     vector<XMode>::iterator modeiter;
272     CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out.name.c_str(), out.modes.size());
273
274     for (modeiter = out.modes.begin() ; modeiter!=out.modes.end() ; modeiter++)
275     {
276       XMode mode = *modeiter;
277       CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d",
278                 mode.id.c_str(), mode.name.c_str(), mode.hz, mode.w, mode.h);
279       RESOLUTION_INFO res;
280       res.iWidth  = mode.w;
281       res.iHeight = mode.h;
282       if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0)
283         res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h));
284       else
285         res.fPixelRatio = 1.0f;
286
287       CLog::Log(LOGINFO, "Pixel Ratio: %f", res.fPixelRatio);
288
289       res.strMode.Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz);
290       res.strOutput    = out.name;
291       res.strId        = mode.id;
292       res.iSubtitles   = (int)(0.95*mode.h);
293       res.fRefreshRate = mode.hz;
294
295       if ((float)mode.w / (float)mode.h >= 1.59)
296         res.dwFlags = D3DPRESENTFLAG_WIDESCREEN;
297       else
298         res.dwFlags = 0;
299
300       g_graphicsContext.ResetOverscan(res);
301       g_settings.m_ResInfo.push_back(res);
302     }
303   }
304 #endif
305 }
306
307 bool CWinSystemEGL::IsExtSupported(const char* extension)
308 {
309   if(strncmp(extension, "EGL_", 4) != 0)
310     return CRenderSystemGLES::IsExtSupported(extension);
311
312   CStdString name;
313
314   name  = " ";
315   name += extension;
316   name += " ";
317
318   return m_eglext.find(name) != string::npos;
319 }
320
321 bool CWinSystemEGL::RefreshEGLContext()
322 {
323   SDL_SysWMinfo info;
324   SDL_VERSION(&info.version);
325   if (SDL_GetWMInfo(&info) <= 0)
326   {
327     CLog::Log(LOGERROR, "Failed to get window manager info from SDL");
328     return false;
329   }
330
331   if (!m_eglDisplay)
332   {
333     CLog::Log(LOGERROR, "EGL: No valid display!");
334     return false;
335   }
336
337   if ((m_eglWindow == info.info.x11.window) && m_eglSurface && m_eglContext)
338   {
339     CLog::Log(LOGERROR, "EGL: Same window as before, refreshing context");
340     eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
341     eglMakeCurrent(m_eglDisplay, m_eglSurface,   m_eglSurface,   m_eglContext);
342     return true;
343   }
344
345   m_eglWindow = info.info.x11.window;
346   m_wmWindow  = info.info.x11.wmwindow;
347
348   EGLConfig eglConfig = NULL;
349   EGLint num;
350
351   if (eglChooseConfig(m_eglDisplay, configAttributes, &eglConfig, 1, &num) == EGL_FALSE)
352   {
353     CLog::Log(LOGERROR, "EGL Error: No compatible configs found");
354     return false;
355   }
356
357   if (m_eglContext)
358     eglDestroyContext(m_eglDisplay, m_eglContext);
359
360   if ((m_eglContext = eglCreateContext(m_eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttributes)) == EGL_NO_CONTEXT)
361   {
362     CLog::Log(LOGERROR, "EGL Error: Could not create context");
363     return false;
364   }
365
366   if (m_eglSurface)
367     eglDestroySurface(m_eglDisplay, m_eglSurface);
368
369   if ((m_eglSurface = eglCreateWindowSurface(m_eglDisplay, eglConfig, (EGLNativeWindowType)m_eglWindow, NULL)) == EGL_NO_SURFACE)
370   {
371     CLog::Log(LOGERROR, "EGL Error: Could not create surface");
372     return false;
373   }
374
375   if (eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext) == EGL_FALSE)
376   {
377     CLog::Log(LOGERROR, "EGL Error: Could not make context current");
378     return false;
379   }
380
381   CLog::Log(LOGDEBUG, "RefreshEGLContext Succeeded! Format:A%d|R%d|G%d|B%d|BPP%d", ASIZE, RSIZE, GSIZE, BSIZE, DEPTH);
382   return true;
383 }
384
385 bool CWinSystemEGL::PresentRenderImpl()
386 {
387 //  glFinish(); // Needed???
388   eglSwapBuffers(m_eglDisplay, m_eglSurface);
389
390   return true;
391 }
392
393 void CWinSystemEGL::SetVSyncImpl(bool enable)
394 {
395   // Nothing to do
396 }
397
398 void CWinSystemEGL::ShowOSMouse(bool show)
399 {
400   SDL_ShowCursor(show ? 1 : 0);
401 }
402
403 void CWinSystemEGL::NotifyAppActiveChange(bool bActivated)
404 {
405   if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot())
406     g_graphicsContext.ToggleFullScreenRoot();
407 }
408
409 bool CWinSystemEGL::Minimize()
410 {
411   m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot();
412   if (m_bWasFullScreenBeforeMinimize)
413     g_graphicsContext.ToggleFullScreenRoot();
414
415   SDL_WM_IconifyWindow();
416   return true;
417 }
418
419 bool CWinSystemEGL::Restore()
420 {
421   return false;
422 }
423
424 bool CWinSystemEGL::Hide()
425 {
426 //  XUnmapWindow(m_dpy, m_wmWindow);
427 //  XSync(m_dpy, False);
428 //  return true;
429         return false;
430 }
431
432 bool CWinSystemEGL::Show(bool raise)
433 {
434 //  XMapWindow(m_dpy, m_wmWindow);
435 //  XSync(m_dpy, False);
436 //  return true;
437         return false;
438 }
439
440 #endif