diff options
-rw-r--r-- | xbmc/windowing/egl/WinEGLPlatformRaspberryPI.cpp | 694 | ||||
-rw-r--r-- | xbmc/windowing/egl/WinEGLPlatformRaspberryPI.h | 98 |
2 files changed, 792 insertions, 0 deletions
diff --git a/xbmc/windowing/egl/WinEGLPlatformRaspberryPI.cpp b/xbmc/windowing/egl/WinEGLPlatformRaspberryPI.cpp new file mode 100644 index 0000000000..4279963553 --- /dev/null +++ b/xbmc/windowing/egl/WinEGLPlatformRaspberryPI.cpp @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" + +#if defined(TARGET_RASPBERRY_PI) + +#include "system_gl.h" + +#ifdef HAS_EGL + +#include "WinEGLPlatformRaspberryPI.h" +#include "utils/log.h" +#include "guilib/gui3d.h" +#include "xbmc/cores/VideoRenderers/RenderManager.h" +#include "settings/Settings.h" + +#include <string> + +#ifndef __VIDEOCORE4__ +#define __VIDEOCORE4__ +#endif + +#define __VCCOREVER__ 0x04000000 + +#define IS_WIDESCREEN(m) (m==3||m==7||m==9||m==11||m==13||m==15||m==18||m==22||m==24||m==26||m==28||m==30||m==36||m==38||m==43||m==45||m==49||m==51||m==53||m==55||m==57||m==59) + +#define MAKEFLAGS(group, mode, interlace, mode3d) (((mode)<<24)|((group)<<16)|((interlace)!=0?D3DPRESENTFLAG_INTERLACED:D3DPRESENTFLAG_PROGRESSIVE)| \ + (((group)==HDMI_RES_GROUP_CEA && IS_WIDESCREEN(mode))?D3DPRESENTFLAG_WIDESCREEN:0)|((mode3d)!=0?D3DPRESENTFLAG_MODE3DSBS:0)) +#define GETFLAGS_INTERLACE(f) (((f)&D3DPRESENTFLAG_INTERLACED)!=0) +#define GETFLAGS_WIDESCREEN(f) (((f)&D3DPRESENTFLAG_WIDESCREEN)!=0) +#define GETFLAGS_GROUP(f) ((HDMI_RES_GROUP_T)(((f)>>16)&0xff)) +#define GETFLAGS_MODE(f) (((f)>>24)&0xff) +#define GETFLAGS_MODE3D(f) (((f)&D3DPRESENTFLAG_MODE3DSBS)!=0) + +CWinEGLPlatformRaspberryPI::CWinEGLPlatformRaspberryPI() +{ + m_surface = EGL_NO_SURFACE; + m_context = EGL_NO_CONTEXT; + m_display = EGL_NO_DISPLAY; + + m_nativeWindow = NULL; + + m_desktopRes.iScreen = 0; + m_desktopRes.iWidth = 1280; + m_desktopRes.iHeight = 720; + //m_desktopRes.iScreenWidth = 1280; + //m_desktopRes.iScreenHeight = 720; + m_desktopRes.fRefreshRate = 60.0f; + m_desktopRes.bFullScreen = true; + m_desktopRes.iSubtitles = (int)(0.965 * 720); + m_desktopRes.dwFlags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN; + m_desktopRes.fPixelRatio = 1.0f; + m_desktopRes.strMode = "720p 16:9"; + m_sdMode = false; +} + +CWinEGLPlatformRaspberryPI::~CWinEGLPlatformRaspberryPI() +{ + DestroyWindow(); +} + +EGLNativeWindowType CWinEGLPlatformRaspberryPI::InitWindowSystem(EGLNativeDisplayType nativeDisplay, int width, int height, int bpp) +{ + m_nativeDisplay = nativeDisplay; + m_width = width; + m_height = height; + + m_dispman_element = DISPMANX_NO_HANDLE; + m_dispman_element2 = DISPMANX_NO_HANDLE; + m_dispman_display = DISPMANX_NO_HANDLE; + + if (!m_DllBcmHost.Load()) + return NULL; + + memset(&m_tv_state, 0, sizeof(TV_GET_STATE_RESP_T)); + m_DllBcmHost.vc_tv_get_state(&m_tv_state); + + m_nativeWindow = (EGL_DISPMANX_WINDOW_T*)calloc(1, sizeof(EGL_DISPMANX_WINDOW_T)); + + return (EGLNativeWindowType)m_nativeWindow; +} + +bool CWinEGLPlatformRaspberryPI::SetDisplayResolution(RESOLUTION_INFO& res) +{ + EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow; + + DestroyWindow(); + + bool bFound = false; + + RESOLUTION_INFO resSearch; + + int best_score = 0; + + for (size_t i = 0; i < m_res.size(); i++) + { + if(m_res[i].iWidth == res.iWidth && m_res[i].iHeight == res.iHeight && m_res[i].fRefreshRate == res.fRefreshRate) + { + int score = 0; + + /* prefere progressive over interlaced */ + if(!GETFLAGS_INTERLACE(m_res[i].dwFlags)) + score = 1; + + if(score >= best_score) + { + resSearch = m_res[i]; + bFound = true; + } + } + } + + if(bFound && !m_sdMode) + { + sem_init(&m_tv_synced, 0, 0); + m_DllBcmHost.vc_tv_register_callback(CallbackTvServiceCallback, this); + + int success = m_DllBcmHost.vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), GETFLAGS_MODE(resSearch.dwFlags)); + + if (success == 0) + { + CLog::Log(LOGNOTICE, "CWinEGLPlatformRaspberryPI::SetDisplayResolution set HDMI mode (%d,%d,%d)=%d\n", + GETFLAGS_MODE3D(resSearch.dwFlags) ? HDMI_MODE_3D:HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), + GETFLAGS_MODE(resSearch.dwFlags), success); + sem_wait(&m_tv_synced); + } + else + { + CLog::Log(LOGERROR, "CWinEGLPlatformRaspberryPI::SetDisplayResolution failed to set HDMI mode (%d,%d,%d)=%d\n", + GETFLAGS_MODE3D(resSearch.dwFlags) ? HDMI_MODE_3D:HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), + GETFLAGS_MODE(resSearch.dwFlags), success); + } + m_DllBcmHost.vc_tv_unregister_callback(CallbackTvServiceCallback); + sem_destroy(&m_tv_synced); + } + + m_dispman_display = m_DllBcmHost.vc_dispmanx_display_open(0); + + m_width = res.iWidth; + m_height = res.iHeight; + //m_bFullScreen = fullScreen; + m_fb_width = res.iWidth; + m_fb_height = res.iHeight; + + m_fb_bpp = 8; + + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = res.iWidth; + dst_rect.height = res.iHeight; + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = m_fb_width << 16; + src_rect.height = m_fb_height << 16; + + VC_DISPMANX_ALPHA_T alpha; + memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T)); + alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE; + + DISPMANX_CLAMP_T clamp; + memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T)); + + DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE; + DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost.vc_dispmanx_update_start(0); + CLog::Log(LOGDEBUG, "CWinEGLPlatformRaspberryPI::SetDisplayResolution %dx%d->%dx%d\n", m_fb_width, m_fb_height, dst_rect.width, dst_rect.height); + + // width < height => half SBS + if (src_rect.width < src_rect.height) + { + // right side + /* + dst_rect.x = m_width; + dst_rect.width = m_width; + */ + dst_rect.x = res.iWidth; + dst_rect.width >>= dst_rect.width - dst_rect.x; + m_dispman_element2 = m_DllBcmHost.vc_dispmanx_element_add(dispman_update, + m_dispman_display, + 1, // layer + &dst_rect, + (DISPMANX_RESOURCE_HANDLE_T)0, // src + &src_rect, + DISPMANX_PROTECTION_NONE, + //(VC_DISPMANX_ALPHA_T*)0, // alpha + &alpha, + //(DISPMANX_CLAMP_T*)0, // clamp + &clamp, + //(DISPMANX_TRANSFORM_T)0); // transform + transform); // transform + assert(m_dispman_element2 != DISPMANX_NO_HANDLE); + assert(m_dispman_element2 != (unsigned)DISPMANX_INVALID); + // left side - fall through + /* + dst_rect.x = 0; + dst_rect.width = m_width; + */ + dst_rect.x = 0; + dst_rect.width = res.iWidth - dst_rect.x; + } + m_dispman_element = m_DllBcmHost.vc_dispmanx_element_add(dispman_update, + m_dispman_display, + 1, // layer + &dst_rect, + (DISPMANX_RESOURCE_HANDLE_T)0, // src + &src_rect, + DISPMANX_PROTECTION_NONE, + //(VC_DISPMANX_ALPHA_T*)0, // alpha + &alpha, + //(DISPMANX_CLAMP_T*)0, // clamp + &clamp, + //(DISPMANX_TRANSFORM_T)0); // transform + transform); // transform + assert(m_dispman_element != DISPMANX_NO_HANDLE); + assert(m_dispman_element != (unsigned)DISPMANX_INVALID); + + memset(nativeWindow, 0, sizeof(EGL_DISPMANX_WINDOW_T)); + nativeWindow->element = m_dispman_element; + nativeWindow->width = m_fb_width; + nativeWindow->height = m_fb_height; + m_DllBcmHost.vc_dispmanx_display_set_background(dispman_update, m_dispman_display, 0x00, 0x00, 0x00); + m_DllBcmHost.vc_dispmanx_update_submit_sync(dispman_update); + + CLog::Log(LOGDEBUG, "CWinEGLPlatformRaspberryPI::SetDisplayResolution(%dx%d) (%dx%d)\n", nativeWindow->width, nativeWindow->height, m_width, m_height); + + if (!setConfiguration()) + { + free(m_nativeWindow); + m_nativeWindow = NULL; + return false; + } + + return true; +} + +bool CWinEGLPlatformRaspberryPI::ClampToGUIDisplayLimits(int &width, int &height) +{ + /* + width = m_tv_state.width; + height = m_tv_state.height; + */ + return true; +} + +bool CWinEGLPlatformRaspberryPI::ProbeDisplayResolutions(std::vector<RESOLUTION_INFO> &resolutions) +{ + resolutions.clear(); + + GetSupportedModes(HDMI_RES_GROUP_CEA, resolutions); + GetSupportedModes(HDMI_RES_GROUP_DMT, resolutions); + GetSupportedModes(HDMI_RES_GROUP_CEA_3D, resolutions); + + if(resolutions.size() == 0) + { + m_sdMode = true; + + TV_GET_STATE_RESP_T tv; + m_DllBcmHost.vc_tv_get_state(&tv); + + RESOLUTION_INFO res; + CLog::Log(LOGNOTICE, "%dx%d@%d %s:%x\n", tv.width, tv.height, tv.frame_rate, tv.scan_mode?"I":""); + + res.iScreen = 0; + res.bFullScreen = true; + res.iSubtitles = (int)(0.965 * tv.height); + res.dwFlags = tv.scan_mode ? D3DPRESENTFLAG_INTERLACED : D3DPRESENTFLAG_PROGRESSIVE; + res.fRefreshRate = (float)tv.frame_rate; + res.fPixelRatio = 1.0f; + res.iWidth = tv.width; + res.iHeight = tv.height; + //res.iScreenWidth = tv.width; + //res.iScreenHeight = tv.height; + res.strMode.Format("%dx%d", tv.width, tv.height); + if ((float)tv.frame_rate > 1) + res.strMode.Format("%s @ %.2f%s - Full Screen", res.strMode, (float)tv.frame_rate, res.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); + + CStdString resolution; + resolutions.push_back(res); + m_desktopRes = res; + m_res.push_back(res); + } + + return true; +} + +void CWinEGLPlatformRaspberryPI::DestroyWindowSystem(EGLNativeWindowType native_window) +{ + DestroyWindow(); + + EGLBoolean eglStatus; + if (m_context != EGL_NO_CONTEXT) + { + eglStatus = eglDestroyContext(m_display, m_context); + if (!eglStatus) + CLog::Log(LOGERROR, "Error destroying EGL context"); + m_context = EGL_NO_CONTEXT; + } + + if (m_surface != EGL_NO_SURFACE) + { + eglStatus = eglDestroySurface(m_display, m_surface); + if (!eglStatus) + CLog::Log(LOGERROR, "Error destroying EGL surface"); + m_surface = EGL_NO_SURFACE; + } + + if (m_display != EGL_NO_DISPLAY) + { + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + eglStatus = eglTerminate(m_display); + if (!eglStatus) + CLog::Log(LOGERROR, "Error terminating EGL"); + m_display = EGL_NO_DISPLAY; + } + + free(m_nativeWindow); + m_nativeWindow = NULL; + + if(m_DllBcmHost.IsLoaded()) + m_DllBcmHost.Unload(); +} + +bool CWinEGLPlatformRaspberryPI::setConfiguration() +{ + EGLBoolean eglStatus; + EGLint configCount; + EGLConfig* configList = NULL; + + m_display = eglGetDisplay(m_nativeDisplay); + if (m_display == EGL_NO_DISPLAY) + { + CLog::Log(LOGERROR, "EGL failed to obtain display"); + return false; + } + + if (!eglInitialize(m_display, 0, 0)) + { + CLog::Log(LOGERROR, "EGL failed to initialize"); + return false; + } + + EGLint configAttrs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_DEPTH_SIZE, 16, + EGL_SAMPLE_BUFFERS, 1, + EGL_NONE + }; + + // Find out how many configurations suit our needs + eglStatus = eglChooseConfig(m_display, configAttrs, NULL, 0, &configCount); + if (!eglStatus || !configCount) + { + CLog::Log(LOGERROR, "EGL failed to return any matching configurations: %d", eglStatus); + return false; + } + + // Allocate room for the list of matching configurations + configList = (EGLConfig*)malloc(configCount * sizeof(EGLConfig)); + if (!configList) + { + CLog::Log(LOGERROR, "kdMalloc failure obtaining configuration list"); + return false; + } + + // Obtain the configuration list from EGL + eglStatus = eglChooseConfig(m_display, configAttrs, + configList, configCount, &configCount); + if (!eglStatus || !configCount) + { + CLog::Log(LOGERROR, "EGL failed to populate configuration list: %d", eglStatus); + return false; + } + + // Select an EGL configuration that matches the native window + m_config = configList[0]; + + if (m_surface != EGL_NO_SURFACE) + { + ReleaseSurface(); + } + + m_surface = eglCreateWindowSurface(m_display, m_config, m_nativeWindow, NULL); + if (!m_surface) + { + CLog::Log(LOGERROR, "EGL couldn't create window surface"); + return false; + } + + // Let's get the current width and height + EGLint width, height; + if (!eglQuerySurface(m_display, m_surface, EGL_WIDTH, &width) || !eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &height) || + width <= 0 || height <= 0) + { + CLog::Log(LOGERROR, "EGL couldn't provide the surface's width and/or height"); + return false; + } + + m_width = width; + m_height = height; + + free(configList); + + return true; +} + +bool CWinEGLPlatformRaspberryPI::BindSurface() +{ + EGLBoolean eglStatus; + + if (m_display == EGL_NO_DISPLAY || m_surface == EGL_NO_SURFACE || m_config == NULL) + { + CLog::Log(LOGNOTICE, "EGL not configured correctly. Let's try to do that now..."); + if (!setConfiguration()) + { + CLog::Log(LOGERROR, "EGL not configured correctly to create a surface"); + return false; + } + } + + eglStatus = eglBindAPI(EGL_OPENGL_ES_API); + if (!eglStatus) + { + CLog::Log(LOGERROR, "EGL failed to bind API: %d", eglStatus); + return false; + } + + EGLint contextAttrs[] = + { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + // Create an EGL context + if (m_context == EGL_NO_CONTEXT) + { + m_context = eglCreateContext(m_display, m_config, NULL, contextAttrs); + if (!m_context) + { + CLog::Log(LOGERROR, "EGL couldn't create context"); + return false; + } + } + + // Make the context and surface current to this thread for rendering + eglStatus = eglMakeCurrent(m_display, m_surface, m_surface, m_context); + if (!eglStatus) + { + CLog::Log(LOGERROR, "EGL couldn't make context/surface current: %d", eglStatus); + return false; + } + + eglSwapInterval(m_display, 0); + + // For EGL backend, it needs to clear all the back buffers of the window + // surface before drawing anything, otherwise the image will be blinking + // heavily. The default eglWindowSurface has 3 gdl surfaces as the back + // buffer, that's why glClear should be called 3 times. + glClearColor (0.0f, 0.0f, 0.0f, 0.0f); + glClear (GL_COLOR_BUFFER_BIT); + eglSwapBuffers(m_display, m_surface); + + glClear (GL_COLOR_BUFFER_BIT); + eglSwapBuffers(m_display, m_surface); + + glClear (GL_COLOR_BUFFER_BIT); + eglSwapBuffers(m_display, m_surface); + + m_eglext = " "; + m_eglext += eglQueryString(m_display, EGL_EXTENSIONS); + m_eglext += " "; + CLog::Log(LOGDEBUG, "EGL extensions:%s", m_eglext.c_str()); + + // setup for vsync disabled + eglSwapInterval(m_display, 0); + + CLog::Log(LOGNOTICE, "EGL window and context creation complete"); + + return true; +} + +bool CWinEGLPlatformRaspberryPI::DestroyWindow() +{ + CLog::Log(LOGDEBUG, "CWinEGLPlatformRaspberryPI::DestroyWindow()\n"); + + DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost.vc_dispmanx_update_start(0); + + if (m_dispman_element != DISPMANX_NO_HANDLE) + { + m_DllBcmHost.vc_dispmanx_element_remove(dispman_update, m_dispman_element); + m_dispman_element = DISPMANX_NO_HANDLE; + } + if (m_dispman_element2 != DISPMANX_NO_HANDLE) + { + m_DllBcmHost.vc_dispmanx_element_remove(dispman_update, m_dispman_element2); + m_dispman_element2 = DISPMANX_NO_HANDLE; + } + m_DllBcmHost.vc_dispmanx_update_submit_sync(dispman_update); + + if (m_dispman_display != DISPMANX_NO_HANDLE) + { + m_DllBcmHost.vc_dispmanx_display_close(m_dispman_display); + m_dispman_display = DISPMANX_NO_HANDLE; + } + + return true; +} + +bool CWinEGLPlatformRaspberryPI::ShowWindow(bool show) +{ + return true; +} + +bool CWinEGLPlatformRaspberryPI::ReleaseSurface() +{ + EGLBoolean eglStatus; + + if (m_surface == EGL_NO_SURFACE) + { + return true; + } + + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + eglStatus = eglDestroySurface(m_display, m_surface); + if (!eglStatus) + { + CLog::Log(LOGERROR, "Error destroying EGL surface"); + return false; + } + + m_surface = EGL_NO_SURFACE; + + return true; +} + +void CWinEGLPlatformRaspberryPI::SwapBuffers() +{ + eglSwapBuffers(m_display, m_surface); +} + +bool CWinEGLPlatformRaspberryPI::SetVSync(bool enable) +{ + // depending how buffers are setup, eglSwapInterval + // might fail so let caller decide if this is an error. + return eglSwapInterval(m_display, enable ? 1 : 0); +} + +bool CWinEGLPlatformRaspberryPI::IsExtSupported(const char* extension) +{ + CStdString name; + + name = " "; + name += extension; + name += " "; + + return m_eglext.find(name) != std::string::npos; +} + +EGLDisplay CWinEGLPlatformRaspberryPI::GetEGLDisplay() +{ + return m_display; +} + +EGLSurface CWinEGLPlatformRaspberryPI::GetEGLSurface() +{ + return m_surface; +} + +EGLContext CWinEGLPlatformRaspberryPI::GetEGLContext() +{ + return m_context; +} + +void CWinEGLPlatformRaspberryPI::TvServiceCallback(uint32_t reason, uint32_t param1, uint32_t param2) +{ + CLog::Log(LOGDEBUG, "tvservice_callback(%d,%d,%d)\n", reason, param1, param2); + switch(reason) + { + case VC_HDMI_UNPLUGGED: + break; + case VC_HDMI_STANDBY: + break; + case VC_SDTV_NTSC: + case VC_SDTV_PAL: + case VC_HDMI_HDMI: + case VC_HDMI_DVI: + //Signal we are ready now + sem_post(&m_tv_synced); + break; + default: + break; + } +} + +void CWinEGLPlatformRaspberryPI::CallbackTvServiceCallback(void *userdata, uint32_t reason, uint32_t param1, uint32_t param2) +{ + CWinEGLPlatformRaspberryPI *omx = static_cast<CWinEGLPlatformRaspberryPI*>(userdata); + omx->TvServiceCallback(reason, param1, param2); +} + +void CWinEGLPlatformRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::vector<RESOLUTION_INFO> &resolutions) +{ + //Supported HDMI CEA/DMT resolutions, first one will be preferred resolution + #define TV_MAX_SUPPORTED_MODES 60 + TV_SUPPORTED_MODE_T supported_modes[TV_MAX_SUPPORTED_MODES]; + int32_t num_modes; + HDMI_RES_GROUP_T prefer_group; + uint32_t prefer_mode; + int i; + + num_modes = m_DllBcmHost.vc_tv_hdmi_get_supported_modes(group, + supported_modes, + TV_MAX_SUPPORTED_MODES, + &prefer_group, + &prefer_mode); + CLog::Log(LOGNOTICE, "CWinEGLPlatformRaspberryPI::GetSupportedModes (%d) = %d, prefer_group=%x, prefer_mode=%x\n", group, num_modes, prefer_group, prefer_mode); + + if (num_modes > 0 && prefer_group != HDMI_RES_GROUP_INVALID) + { + TV_SUPPORTED_MODE_T *tv = supported_modes; + for (i=0; i < num_modes; i++, tv++) + { + /* filter out interlaced modes */ + /* + if(tv->scan_mode && group != HDMI_RES_GROUP_CEA_3D) + continue; + */ + + // treat 3D modes as half-width SBS + unsigned int width = group==HDMI_RES_GROUP_CEA_3D ? tv->width>>1:tv->width; + RESOLUTION_INFO res; + CLog::Log(LOGNOTICE, "%d: %dx%d@%d %s%s:%x\n", i, width, tv->height, tv->frame_rate, tv->native?"N":"", tv->scan_mode?"I":"", tv->code); + + res.iScreen = 0; + res.bFullScreen = true; + res.iSubtitles = (int)(0.965 * tv->height); + res.dwFlags = MAKEFLAGS(group, tv->code, tv->scan_mode, group==HDMI_RES_GROUP_CEA_3D); + res.fRefreshRate = (float)tv->frame_rate; + res.fPixelRatio = 1.0f; + res.iWidth = width; + res.iHeight = tv->height; + //res.iScreenWidth = width; + //res.iScreenHeight = tv->height; + res.strMode.Format("%dx%d", width, tv->height); + if ((float)tv->frame_rate > 1) + res.strMode.Format("%s @ %.2f%s - Full Screen", res.strMode, (float)tv->frame_rate, res.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); + + CStdString resolution; + + //resolution.Format("%dx%d%s%dHz", width, tv->height, tv->scan_mode ? "i" :"p", tv->frame_rate); + //resolutions.push_back(resolution); + + resolutions.push_back(res); + + if(m_tv_state.width == width && m_tv_state.height == tv->height && + m_tv_state.scan_mode == tv->scan_mode && m_tv_state.frame_rate == tv->frame_rate) + m_desktopRes = res; + + m_res.push_back(res); + } + } +} + +#endif + +#endif diff --git a/xbmc/windowing/egl/WinEGLPlatformRaspberryPI.h b/xbmc/windowing/egl/WinEGLPlatformRaspberryPI.h new file mode 100644 index 0000000000..b3970008f7 --- /dev/null +++ b/xbmc/windowing/egl/WinEGLPlatformRaspberryPI.h @@ -0,0 +1,98 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#if defined(TARGET_RASPBERRY_PI) + +#include "WinEGLPlatformGeneric.h" +#include "utils/StringUtils.h" +#include "guilib/Resolution.h" + +#include <semaphore.h> + +#include "linux/DllBCM.h" + +class CWinEGLPlatformRaspberryPI +{ +public: + CWinEGLPlatformRaspberryPI(); + virtual ~CWinEGLPlatformRaspberryPI(); + + virtual EGLNativeWindowType InitWindowSystem(EGLNativeDisplayType nativeDisplay, int width, int height, int bpp); + virtual void DestroyWindowSystem(EGLNativeWindowType native_window); + virtual bool SetDisplayResolution(RESOLUTION_INFO &res); + virtual bool ClampToGUIDisplayLimits(int &width, int &height); + virtual bool ProbeDisplayResolutions(std::vector<RESOLUTION_INFO> &resolutions); + + virtual bool InitializeDisplay() { return true; }; + virtual bool BindSurface(); + virtual bool CreateWindow() { return true; }; + virtual bool DestroyWindow(); + virtual bool ShowWindow(bool show); + virtual bool ReleaseSurface(); + + virtual void SwapBuffers(); + virtual bool SetVSync(bool enable); + virtual bool IsExtSupported(const char* extension); + + virtual EGLDisplay GetEGLDisplay(); + virtual EGLSurface GetEGLSurface(); + virtual EGLContext GetEGLContext(); + virtual bool FixedDesktop() { return true; } + virtual RESOLUTION_INFO GetDesktopRes() { return m_desktopRes; } + +protected: + virtual bool setConfiguration(); + + EGL_DISPMANX_WINDOW_T *m_nativeWindow; + EGLNativeDisplayType m_nativeDisplay; + EGLDisplay m_display; + EGLSurface m_surface; + EGLConfig m_config; + EGLContext m_context; + CStdString m_eglext; + int m_width; + int m_height; + + int m_fb_width; + int m_fb_height; + int m_fb_bpp; + DllBcmHost m_DllBcmHost; + + DISPMANX_ELEMENT_HANDLE_T m_dispman_element; + DISPMANX_ELEMENT_HANDLE_T m_dispman_element2; + DISPMANX_DISPLAY_HANDLE_T m_dispman_display; + sem_t m_tv_synced; + + void GetSupportedModes(HDMI_RES_GROUP_T group, std::vector<RESOLUTION_INFO> &resolutions); + void TvServiceCallback(uint32_t reason, uint32_t param1, uint32_t param2); + static void CallbackTvServiceCallback(void *userdata, uint32_t reason, uint32_t param1, uint32_t param2); + + std::vector<RESOLUTION_INFO> m_res; + + RESOLUTION_INFO m_desktopRes; + + TV_GET_STATE_RESP_T m_tv_state; + + bool m_sdMode; +}; + +#endif |