diff options
Diffstat (limited to 'src/graphics/EGLContext.cpp')
-rw-r--r-- | src/graphics/EGLContext.cpp | 202 |
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; + } +} + +} |