summaryrefslogtreecommitdiff
path: root/src/graphics/BCMDisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/BCMDisplay.cpp')
-rw-r--r--src/graphics/BCMDisplay.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/graphics/BCMDisplay.cpp b/src/graphics/BCMDisplay.cpp
new file mode 100644
index 0000000..917e0e6
--- /dev/null
+++ b/src/graphics/BCMDisplay.cpp
@@ -0,0 +1,142 @@
+//
+// 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 "BCMDisplay.h"
+
+#include "../base/Exception.h"
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_syswm.h>
+
+#include <EGL/eglext_brcm.h>
+
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+IntPoint getX11WindowPosition(const SDL_SysWMinfo* pSDLWMInfo)
+{
+ int x, y;
+ Window dummy;
+ XWindowAttributes wAttribs;
+ pSDLWMInfo->info.x11.lock_func();
+ XGetWindowAttributes(pSDLWMInfo->info.x11.display, pSDLWMInfo->info.x11.window,
+ &wAttribs);
+ XTranslateCoordinates(pSDLWMInfo->info.x11.display, pSDLWMInfo->info.x11.window,
+ wAttribs.root, 0, 0, &x, &y, &dummy);
+ pSDLWMInfo->info.x11.unlock_func();
+ return IntPoint(x, y);
+}
+
+DISPMANX_DISPLAY_HANDLE_T getBCMDisplay(const SDL_SysWMinfo* pSDLWMInfo)
+{
+ bcm_host_init();
+
+ DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(DISPMANX_ID_MAIN_LCD);
+ if (display == DISPMANX_NO_HANDLE) {
+ throw Exception(AVG_ERR_VIDEO_GENERAL, "No BCM display available.");
+ }
+ return display;
+}
+
+EGL_DISPMANX_WINDOW_T* createChildWindow(const SDL_SysWMinfo* pSDLWMInfo,
+ EGLNativeDisplayType bcmDisplay, const IntPoint& windowSize)
+{
+ // Create a child (yet toplevel) window with the required attributes to render into.
+ IntPoint windowPos = getX11WindowPosition(pSDLWMInfo);
+ VC_RECT_T dstRect;
+ dstRect.x = windowPos.x;
+ dstRect.y = windowPos.y;
+ dstRect.width = windowSize.x;
+ dstRect.height = windowSize.y;
+ VC_RECT_T srcRect;
+ srcRect.x = 0;
+ srcRect.y = 0;
+ srcRect.width = windowSize.x << 16;
+ srcRect.height = windowSize.y << 16;
+ // start display update
+ DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
+ if (update == DISPMANX_NO_HANDLE) {
+ throw Exception(AVG_ERR_VIDEO_GENERAL, "Failed to start BCM display update.");
+ }
+ // add element to display
+ DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update,
+ (DISPMANX_DISPLAY_HANDLE_T)bcmDisplay,
+ 0 /* layer */, &dstRect, DISPMANX_NO_HANDLE /* src */, &srcRect,
+ (DISPMANX_PROTECTION_T) DISPMANX_PROTECTION_NONE,
+ 0 /* alpha */, 0 /* clamp */, DISPMANX_NO_ROTATE);
+ if (element == DISPMANX_NO_HANDLE) {
+ throw Exception(AVG_ERR_VIDEO_GENERAL, "Failed to add element to BCM display.");
+ }
+ // finish display update
+ if (vc_dispmanx_update_submit_sync(update)) {
+ throw Exception(AVG_ERR_VIDEO_GENERAL, "Failed to finish BCM display update.");
+ }
+
+ EGL_DISPMANX_WINDOW_T* pWin = new EGL_DISPMANX_WINDOW_T; // XXX: destroy
+ pWin->element = element;
+ pWin->width = windowSize.x;
+ pWin->height = windowSize.y;
+ return pWin;
+}
+
+EGLSurface createBCMPixmapSurface(EGLDisplay display, EGLConfig config)
+{
+ EGLint pixel_format = EGL_PIXEL_FORMAT_ARGB_8888_BRCM;
+ EGLint rt;
+ eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &rt);
+
+ if (rt & EGL_OPENGL_ES_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_GLES_BRCM;
+ pixel_format |= EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM;
+ }
+ if (rt & EGL_OPENGL_ES2_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM;
+ pixel_format |= EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
+ }
+ if (rt & EGL_OPENVG_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_VG_BRCM;
+ pixel_format |= EGL_PIXEL_FORMAT_VG_IMAGE_BRCM;
+ }
+ if (rt & EGL_OPENGL_BIT) {
+ pixel_format |= EGL_PIXEL_FORMAT_RENDER_GL_BRCM;
+ }
+
+ EGLint pixmap[5];
+ pixmap[0] = 0;
+ pixmap[1] = 0;
+ pixmap[2] = 8;
+ pixmap[3] = 8;
+ pixmap[4] = pixel_format;
+
+ eglCreateGlobalImageBRCM(8, 8, pixel_format, 0, 8*4, pixmap);
+
+ EGLSurface surface = eglCreatePixmapSurface(display, config, pixmap, 0);
+ if ( surface == EGL_NO_SURFACE ) {
+ cerr << "Unable to create EGL surface (eglError: " << eglGetError() << ")" << endl;
+ }
+ return surface;
+
+}
+
+}