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