summaryrefslogtreecommitdiff
path: root/src/graphics/EGLContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/EGLContext.cpp')
-rw-r--r--src/graphics/EGLContext.cpp202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/graphics/EGLContext.cpp b/src/graphics/EGLContext.cpp
new file mode 100644
index 0000000..dce62d9
--- /dev/null
+++ b/src/graphics/EGLContext.cpp
@@ -0,0 +1,202 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "EGLContext.h"
+#include "GLContextAttribs.h"
+#ifdef AVG_ENABLE_RPI
+ #include "BCMDisplay.h"
+#else
+ #include "X11Display.h"
+#endif
+
+#include "../base/Exception.h"
+#include "../base/StringHelper.h"
+
+#include <SDL/SDL_syswm.h>
+#include <EGL/egl.h>
+
+#include <iostream>
+
+namespace avg{
+
+using namespace std;
+
+EGLContext::EGLContext(const GLConfig& glConfig, const IntPoint& windowSize,
+ const SDL_SysWMinfo* pSDLWMInfo)
+ : GLContext(windowSize, pSDLWMInfo)
+{
+ createEGLContext(glConfig, windowSize, pSDLWMInfo);
+ init(glConfig, true);
+}
+
+EGLContext::~EGLContext()
+{
+ getVertexBufferCache().deleteBuffers();
+ getIndexBufferCache().deleteBuffers();
+ getPBOCache().deleteBuffers();
+ deleteObjects();
+ eglMakeCurrent(m_Display, EGL_NO_SURFACE, EGL_NO_SURFACE, 0);
+ eglDestroyContext(m_Display, m_Context);
+ eglDestroySurface(m_Display, m_Surface);
+ eglTerminate(m_Display);
+}
+
+void EGLContext::createEGLContext(const GLConfig& glConfig, const IntPoint& windowSize,
+ const SDL_SysWMinfo* pSDLWMInfo)
+{
+ bool bOk;
+
+#ifdef AVG_ENABLE_RPI
+ m_xDisplay = (EGLNativeDisplayType)getBCMDisplay(pSDLWMInfo);
+ m_Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+#else
+ m_xDisplay = (EGLNativeDisplayType)getX11Display(pSDLWMInfo);
+ m_Display = eglGetDisplay(m_xDisplay);
+#endif
+ checkEGLError(m_Display == EGL_NO_DISPLAY, "No EGL display available");
+
+ bOk = eglInitialize(m_Display, NULL, NULL);
+ checkEGLError(!bOk, "eglInitialize failed");
+
+ GLContextAttribs fbAttrs;
+ fbAttrs.append(EGL_RED_SIZE, 1);
+ fbAttrs.append(EGL_GREEN_SIZE, 1);
+ fbAttrs.append(EGL_BLUE_SIZE, 1);
+ fbAttrs.append(EGL_DEPTH_SIZE, 0);
+ fbAttrs.append(EGL_STENCIL_SIZE, 1);
+ int alphaSize = 0;
+#ifdef AVG_ENABLE_RPI
+ if (!pSDLWMInfo) {
+ alphaSize = 1;
+ }
+#endif
+ fbAttrs.append(EGL_ALPHA_SIZE, alphaSize);
+ fbAttrs.append(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
+ EGLint numFBConfig;
+ bOk = eglChooseConfig(m_Display, fbAttrs.get(), &m_Config, 1, &numFBConfig);
+ checkEGLError(!bOk, "Failed to choose EGL config");
+
+ EGLint vid;
+ bOk = eglGetConfigAttrib(m_Display, m_Config, EGL_NATIVE_VISUAL_ID, &vid);
+ AVG_ASSERT(bOk);
+
+#ifndef AVG_ENABLE_RPI
+ XVisualInfo visTemplate;
+ visTemplate.visualid = vid;
+ int num_visuals;
+ XVisualInfo* pVisualInfo = XGetVisualInfo((_XDisplay*)m_xDisplay, VisualIDMask, &visTemplate,
+ &num_visuals);
+ AVG_ASSERT(pVisualInfo);
+#endif
+
+ EGLNativeWindowType xWindow = 0;
+ if (pSDLWMInfo) {
+#ifdef AVG_ENABLE_RPI
+ xWindow = createChildWindow(pSDLWMInfo, m_xDisplay, windowSize);
+#else
+ Colormap colormap;
+ xWindow = (EGLNativeWindowType)createChildWindow(pSDLWMInfo, pVisualInfo, windowSize, colormap);
+#endif
+ }
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ cerr << "Failed to bind GLES API to EGL\n";
+ return;
+ }
+
+ if (numFBConfig != 1) {
+ cerr << "Didn't get exactly one config, but " << numFBConfig << endl;
+ return;
+ }
+ if (xWindow) {
+ m_Surface = eglCreateWindowSurface(m_Display, m_Config, xWindow, NULL);
+ } else {
+#ifdef AVG_ENABLE_RPI
+ m_Surface = createBCMPixmapSurface(m_Display, m_Config);
+#else
+ XVisualInfo visTemplate, *results;
+ visTemplate.screen = 0;
+ int numVisuals;
+ results = XGetVisualInfo((_XDisplay*)m_xDisplay, VisualScreenMask,
+ &visTemplate, & numVisuals);
+
+ Pixmap pmp = XCreatePixmap((_XDisplay*)m_xDisplay,
+ RootWindow((_XDisplay*)m_xDisplay, results[0].screen), 8, 8, results[0].depth);
+ m_Surface = eglCreatePixmapSurface(m_Display, m_Config, (EGLNativePixmapType)pmp, NULL);
+#endif
+ }
+ AVG_ASSERT(m_Surface);
+
+ GLContextAttribs attrs;
+ attrs.append(EGL_CONTEXT_CLIENT_VERSION, 2);
+ m_Context = eglCreateContext(m_Display, m_Config, NULL, attrs.get());
+ checkEGLError(!m_Context, "Unable to create EGL context");
+// dumpEGLConfig();
+}
+
+bool EGLContext::initVBlank(int rate)
+{
+ return false;
+}
+
+void EGLContext::activate()
+{
+ eglMakeCurrent(m_Display, m_Surface, m_Surface, m_Context);
+ setCurrent();
+}
+
+void EGLContext::swapBuffers()
+{
+ eglSwapBuffers(m_Display, m_Surface);
+}
+
+void EGLContext::checkEGLError(bool bError, const std::string& sMsg)
+{
+ if (bError) {
+ throw Exception(AVG_ERR_VIDEO_INIT_FAILED, sMsg + " (EGL error: " +
+ toString(eglGetError()) + ")");
+ }
+}
+
+void EGLContext::dumpEGLConfig() const
+{
+ cout << "EGL configuration:" << endl;
+ dumpEGLConfigAttrib(EGL_RED_SIZE, "RED_SIZE");
+ dumpEGLConfigAttrib(EGL_GREEN_SIZE, "GREEN_SIZE");
+ dumpEGLConfigAttrib(EGL_BLUE_SIZE, "BLUE_SIZE");
+ dumpEGLConfigAttrib(EGL_ALPHA_SIZE, "ALPHA_SIZE");
+ dumpEGLConfigAttrib(EGL_BUFFER_SIZE, "BUFFER_SIZE");
+ dumpEGLConfigAttrib(EGL_DEPTH_SIZE, "DEPTH_SIZE");
+ dumpEGLConfigAttrib(EGL_STENCIL_SIZE, "STENCIL_SIZE");
+}
+
+void EGLContext::dumpEGLConfigAttrib(EGLint attrib, const string& name) const
+{
+ EGLint value;
+ if (eglGetConfigAttrib(m_Display, m_Config, attrib, &value)) {
+ cout << " " << name << ": " << value << endl;
+ }
+ else {
+ cerr << " Failed to get EGL config attribute " << name << endl;
+ }
+}
+
+}