diff options
author | cvs2svn <admin@example.com> | 2009-10-21 00:02:02 +0000 |
---|---|---|
committer | cvs2svn <admin@example.com> | 2009-10-21 00:02:02 +0000 |
commit | 97a97ca3358eb48de3eb7a222e487e800566569f (patch) | |
tree | 97c920d0225a1c9773a3bce2207f261d7d230123 /osd.c | |
parent | a61961358c5a2ec92340b3f8e056bab55438f103 (diff) | |
download | xineliboutput-CVS.tar.gz xineliboutput-CVS.tar.bz2 |
This commit was manufactured by cvs2svn to create branch 'CVS'.CVS
Diffstat (limited to 'osd.c')
-rw-r--r-- | osd.c | 633 |
1 files changed, 0 insertions, 633 deletions
@@ -1,633 +0,0 @@ -/* - * osd.c: Xinelib On Screen Display control - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: osd.c,v 1.38 2009-08-19 17:15:37 phintuka Exp $ - * - */ - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/thread.h> - -#include "logdefs.h" -#include "config.h" -#include "device.h" -#include "xine_osd_command.h" -#include "tools/rle.h" - -#include "osd.h" - -//#define LIMIT_OSD_REFRESH_RATE - -#define LOGOSD(x...) - -// -// tools -// - -static inline int saturate(int x, int min, int max) -{ - return x < min ? min : (x > max ? max : x); -} - -static inline void prepare_palette(xine_clut_t *clut, const unsigned int *palette, int colors, bool top, bool rgb) -{ - if (colors) { - int c; - - // Apply alpha layer correction and convert ARGB -> AYCrCb - - for(c=0; c<colors; c++) { - int A = (palette[c] & 0xff000000) >> 24; - int R = (palette[c] & 0x00ff0000) >> 16; - int G = (palette[c] & 0x0000ff00) >> 8; - int B = (palette[c] & 0x000000ff); - A = A + xc.alpha_correction*A/100 + xc.alpha_correction_abs; - if(rgb) { - clut[c].r = R; - clut[c].g = G; - clut[c].b = B; - clut[c].alpha = saturate( A, 0, 255); - } else { - int Y = (( + 66*R + 129*G + 25*B + 0x80) >> 8) + 16; - int CR = (( + 112*R - 94*G - 18*B + 0x80) >> 8) + 128; - int CB = (( - 38*R - 74*G + 112*B + 0x80) >> 8) + 128; - clut[c].y = saturate( Y, 16, 235); - clut[c].cb = saturate(CB, 16, 240); - clut[c].cr = saturate(CR, 16, 240); - clut[c].alpha = saturate( A, 0, 255); - } - } - - // Apply OSD mixer settings - - if(!top) { - if(xc.osd_mixer & OSD_MIXER_ALPHA) - for(c=0; c<colors; c++) - clut[c].alpha >>= 1; /* fade */ - if(xc.osd_mixer & OSD_MIXER_GRAY) - for(c=0; c<colors; c++) { - if(rgb) - clut[c].r = clut[c].g = clut[c].b = (clut[c].r + clut[c].g + clut[c].b)/3; - else - clut[c].cb = clut[c].cr = 0x80; - } - } - } -} - -// -// cXinelibOsd -// - -class cXinelibOsd : public cOsd, public cListObject -{ - private: - cXinelibOsd(); - cXinelibOsd(cXinelibOsd&); // no copy - - cXinelibDevice *m_Device; - - void CloseWindows(void); - void CmdSize(int Width, int Height); - void CmdRle(int Wnd, int X0, int Y0, - int W, int H, unsigned char *Data, - int Colors, unsigned int *Palette, - osd_rect_t *DirtyArea); - void CmdPalette(int Wnd, int Colors, unsigned int *Palette); - void CmdMove(int Wnd, int Width, int Height); - void CmdClose(int Wnd); - void CmdFlush(void); - - /* map single OSD window indexes to unique xine-side window handles */ - static uint64_t m_HandlesBitmap; - int *m_WindowHandles; - int AllocWindowHandles(int NumWindows); - void FreeWindowHandles(void); - - protected: - static cMutex m_Lock; - static cList<cXinelibOsd> m_OsdStack; - - bool m_IsVisible; - bool m_Refresh; - uint m_Layer; - uint16_t m_ExtentWidth; - uint16_t m_ExtentHeight; - - virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); - virtual eOsdError SetAreas(const tArea *Areas, int NumAreas); - virtual void Flush(void); - - // Messages from cXinelibOsdProvider - void Show(void); - void Hide(void); - void Refresh(void); - void Detach(void); - - friend class cXinelibOsdProvider; - - public: - cXinelibOsd(cXinelibDevice *Device, int x, int y, uint Level = 0); - virtual ~cXinelibOsd(); -}; - -cList<cXinelibOsd> cXinelibOsd::m_OsdStack; -cMutex cXinelibOsd::m_Lock; -uint64_t cXinelibOsd::m_HandlesBitmap; - -int cXinelibOsd::AllocWindowHandles(int NumWindows) -{ - uint64_t bit = 1; - int index = 0, wnd = 0; - - FreeWindowHandles(); - m_WindowHandles = new int[NumWindows+1]; - - for (index = 0; index < MAX_OSD_OBJECT; index++) { - if (! (m_HandlesBitmap & bit)) { - m_WindowHandles[wnd++] = index; - m_HandlesBitmap |= bit; - } - if (wnd >= NumWindows) - break; - bit <<= 1; - } - m_WindowHandles[NumWindows] = -1; - - if (wnd < NumWindows) { - LOGMSG("cXinelibOsd::AllocOsdHandles(): Too many open OSD windows !"); - while(wnd < NumWindows) m_WindowHandles[wnd++] = -1; - return 0; - } - - return NumWindows; -} - -void cXinelibOsd::FreeWindowHandles(void) -{ - if (m_WindowHandles) { - int wnd = 0; - while (m_WindowHandles[wnd] >= 0) { - m_HandlesBitmap &= ~( ((uint64_t)1) << m_WindowHandles[wnd]); - wnd++; - } - delete [] m_WindowHandles; - m_WindowHandles = NULL; - } -} - -void cXinelibOsd::CmdSize(int Width, int Height) -{ - TRACEF("cXinelibOsd::CmdSize"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - for (int Wnd = 0; GetBitmap(Wnd); Wnd++) { - osdcmd.cmd = OSD_Size; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.w = Width; - osdcmd.h = Height; - - m_Device->OsdCmd((void*)&osdcmd); - } - } -} - -void cXinelibOsd::CmdMove(int Wnd, int NewX, int NewY) -{ - TRACEF("cXinelibOsd::CmdMove"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Move; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.x = NewX; - osdcmd.y = NewY; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdPalette(int Wnd, int Colors, unsigned int *Palette) -{ - TRACEF("cXinelibOsd::CmdPalette"); - - if (m_Device) { - xine_clut_t clut[Colors]; - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_SetPalette; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.palette = clut; - osdcmd.colors = Colors; - - prepare_palette(&clut[0], Palette, Colors, /*Top*/(Prev() == NULL), true); - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdClose(int Wnd) -{ - TRACEF("cXinelibOsd::CmdClose"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Close; - osdcmd.wnd = m_WindowHandles[Wnd]; - - if (m_Refresh) - osdcmd.flags |= OSDFLAG_REFRESH; - if (Prev() == NULL) - osdcmd.flags |= OSDFLAG_TOP_LAYER; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdFlush(void) -{ - TRACEF("cXinelibOsd::CmdFlush"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Flush; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdRle(int Wnd, int X0, int Y0, - int W, int H, unsigned char *Data, - int Colors, unsigned int *Palette, - osd_rect_t *DirtyArea) -{ - TRACEF("cXinelibOsd::CmdRle"); - - if (m_Device) { - - xine_clut_t clut[Colors]; - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Set_RLE; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.layer = saturate(m_Layer, 0, 0xffff); - osdcmd.x = X0; - osdcmd.y = Y0; - osdcmd.w = W; - osdcmd.h = H; - osdcmd.colors = Colors; - osdcmd.palette = clut; - osdcmd.scaling = xc.osd_scaling; - - if (DirtyArea) - memcpy(&osdcmd.dirty_area, DirtyArea, sizeof(osd_rect_t)); - if (m_Refresh) - osdcmd.flags |= OSDFLAG_REFRESH; - if (xc.osd_blending == OSD_BLENDING_HARDWARE) - osdcmd.flags |= OSDFLAG_UNSCALED; - if (xc.osd_blending_lowresvideo == OSD_BLENDING_HARDWARE) - osdcmd.flags |= OSDFLAG_UNSCALED_LOWRES; - if (Prev() == NULL) - osdcmd.flags |= OSDFLAG_TOP_LAYER; - - prepare_palette(&clut[0], Palette, Colors, /*Top*/(Prev() == NULL), true); - - if (xc.osd_blending_lowresvideo == OSD_BLENDING_HARDWARE) - osdcmd.flags |= OSDFLAG_UNSCALED_LOWRES; - osdcmd.num_rle = rle_compress(&osdcmd.data, Data, W, H); - osdcmd.datalen = 4 * osdcmd.num_rle; - - m_Device->OsdCmd((void*)&osdcmd); - - free(osdcmd.data); - } -} - -cXinelibOsd::cXinelibOsd(cXinelibDevice *Device, int x, int y, uint Level) - : cOsd(x, y, Level) -{ - TRACEF("cXinelibOsd::cXinelibOsd"); - - m_Device = Device; - m_Refresh = false; - m_IsVisible = true; - m_Layer = Level; - m_ExtentWidth = 720; - m_ExtentHeight = 576; - - m_WindowHandles = NULL; -} - -cXinelibOsd::~cXinelibOsd() -{ - TRACEF("cXinelibOsd::~cXinelibOsd"); - - cMutexLock ml(&m_Lock); - - CloseWindows(); - FreeWindowHandles(); - - m_OsdStack.Del(this, false); - - if(m_OsdStack.First()) - m_OsdStack.First()->Show(); -} - -eOsdError cXinelibOsd::SetAreas(const tArea *Areas, int NumAreas) -{ - TRACEF("cXinelibOsd::SetAreas"); - cMutexLock ml(&m_Lock); - - LOGOSD("cXinelibOsd::SetAreas"); - - // Close all existing windows - CloseWindows(); - FreeWindowHandles(); - - eOsdError Result = cOsd::SetAreas(Areas, NumAreas); - - if (Result != oeOk) - return Result; - - // Allocate xine OSD window handles - if (!AllocWindowHandles(NumAreas)) { - FreeWindowHandles(); - return oeTooManyAreas; - } - -#if VDRVERSNUM >= 10708 - - double Aspect; - int W, H; - m_Device->GetOsdSize(W, H, Aspect); - m_ExtentWidth = W; - m_ExtentHeight = H; - -#else - - // Detect full OSD area size - if(Left() + Width() > 720 || Top() + Height() > 576) { - m_ExtentWidth = Setup.OSDWidth + 2 * Setup.OSDLeft; - m_ExtentHeight = Setup.OSDHeight + 2 * Setup.OSDTop; - LOGDBG("Detected HD OSD, size > %dx%d, using setup values %dx%d", - 2*Left() + Width(), 2*Top() + Height(), - m_ExtentWidth, m_ExtentHeight); - } else { - m_ExtentWidth = 720; - m_ExtentHeight = 576; - } - -#endif - - CmdSize(m_ExtentWidth, m_ExtentHeight); - - return Result; -} - -eOsdError cXinelibOsd::CanHandleAreas(const tArea *Areas, int NumAreas) -{ - TRACEF("cXinelibOsd::CanHandleAreas"); - - eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); - - if (Result != oeOk) - return Result; - - if (NumAreas > MAX_OSD_OBJECT) - return oeTooManyAreas; - - for (int i = 0; i < NumAreas; i++) { - if (Areas[i].bpp < 1 || Areas[i].bpp > 8) { - LOGMSG("cXinelibOsd::CanHandleAreas(): invalid bpp (%d)", Areas[i].bpp); - return oeBppNotSupported; - } - } - - // enough free xine OSD windows ? - uint64_t bit = 1; - int windows = NumAreas; - for (int index = 0; index < MAX_OSD_OBJECT && windows > 0; index++) { - if (! (m_HandlesBitmap & bit)) - windows--; - bit <<= 1; - } - if (windows > 0) { - LOGMSG("cXinelibOsd::CanHandleAreas(): not enough free window handles !"); - return oeTooManyAreas; - } - - return oeOk; -} - -void cXinelibOsd::Flush(void) -{ - TRACEF("cXinelibOsd::Flush"); - - cMutexLock ml(&m_Lock); - - cBitmap *Bitmap; - - if(!m_IsVisible) - return; - - int SendDone = 0; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { - int x1 = 0, y1 = 0, x2 = Bitmap->Width()-1, y2 = Bitmap->Height()-1; - if (m_Refresh || Bitmap->Dirty(x1, y1, x2, y2)) { - - /* XXX what if only palette has been changed ? */ - int NumColors; - const tColor *Colors = Bitmap->Colors(NumColors); - if (Colors) { - osd_rect_t DirtyArea = {x1:x1, y1:y1, x2:x2, y2:y2}; - CmdRle(i, - Left() + Bitmap->X0(), Top() + Bitmap->Y0(), - Bitmap->Width(), Bitmap->Height(), - (unsigned char *)Bitmap->Data(0,0), - NumColors, (unsigned int *)Colors, - &DirtyArea); - SendDone++; - } - } - Bitmap->Clean(); - } - -#ifdef LIMIT_OSD_REFRESH_RATE - if(SendDone) { - static int64_t last_refresh = 0LL; - int64_t now = cTimeMs::Now(); - if(now - last_refresh < 100) { - /* too fast refresh rate, delay ... */ - cCondWait::SleepMs(40); /* Can't update faster anyway ... */ -# if 0 - LOGDBG("cXinelibOsd::Flush: OSD refreshing too fast ! (>10Hz) -> Sleeping 50ms"); -# endif - } - last_refresh = now; - } -#endif -} - -void cXinelibOsd::Refresh(void) -{ - TRACEF("cXinelibOsd::Refresh"); - - cMutexLock ml(&m_Lock); - - m_Refresh = true; - CloseWindows(); - CmdSize(m_ExtentWidth, m_ExtentHeight); - Flush(); - m_Refresh = false; -} - -void cXinelibOsd::Show(void) -{ - TRACEF("cXinelibOsd::Show"); - - cMutexLock ml(&m_Lock); - - m_IsVisible = true; - Refresh(); -} - -void cXinelibOsd::CloseWindows(void) -{ - TRACEF("cXinelibOsd::CloseWindows"); - - if(m_IsVisible) { - cBitmap *Bitmap; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { - LOGOSD("Close OSD %d.%d", Index(), i); - if (m_WindowHandles[i] < 0) - LOGMSG("Close unallocated OSD %d.%d @%d", Index(), i, m_WindowHandles[i]); - CmdClose(i); - } - } - - if (!m_Refresh) - CmdFlush(); -} - -void cXinelibOsd::Hide(void) -{ - TRACEF("cXinelibOsd::Hide"); - - cMutexLock ml(&m_Lock); - - CloseWindows(); - m_IsVisible = false; -} - -void cXinelibOsd::Detach(void) -{ - TRACEF("cXinelibOsd::Detach"); - - cMutexLock ml(&m_Lock); - - Hide(); - m_Device = NULL; -} - -// -// cXinelibOsdProvider -// - -cXinelibOsdProvider::cXinelibOsdProvider(cXinelibDevice *Device) -{ - m_Device = Device; -} - -cXinelibOsdProvider::~cXinelibOsdProvider() -{ - LOGMSG("cXinelibOsdProvider: shutting down !"); - - cMutexLock ml(&cXinelibOsd::m_Lock); - - m_Device = NULL; - - if(cXinelibOsd::m_OsdStack.First()) { - LOGMSG("cXinelibOsdProvider: OSD open while OSD provider shutting down !"); - - // Detach all OSD instances from device - cXinelibOsd *osd; - while(NULL != (osd = cXinelibOsd::m_OsdStack.First())) { - osd->Detach(); - cXinelibOsd::m_OsdStack.Del(osd, false); - } - } -} - -cOsd *cXinelibOsdProvider::CreateOsd(int Left, int Top, uint Level) -{ - TRACEF("cXinelibOsdProvider::CreateOsd"); - - cMutexLock ml(&cXinelibOsd::m_Lock); - - cXinelibOsd *m_OsdInstance = new cXinelibOsd(m_Device, Left, Top, Level); - - // sorted insert - cXinelibOsd *it = cXinelibOsd::m_OsdStack.First(); - while(it) { - if(it->m_Layer >= Level) { - cXinelibOsd::m_OsdStack.Ins(m_OsdInstance, it); - break; - } - it = cXinelibOsd::m_OsdStack.Next(it); - } - if(!it) - cXinelibOsd::m_OsdStack.Add(m_OsdInstance); - - LOGOSD("New OSD: index %d, layer %d [now %d OSDs]", - m_OsdInstance->Index(), Level, cXinelibOsd::m_OsdStack.Count()); - - if(xc.osd_mixer == OSD_MIXER_NONE) { - // hide all but top-most OSD - LOGOSD(" OSD mixer off"); - it = cXinelibOsd::m_OsdStack.Last(); - while(cXinelibOsd::m_OsdStack.Prev(it)) { - LOGOSD(" -> hide OSD %d", it->Index()); - it->Hide(); - it = cXinelibOsd::m_OsdStack.Prev(it); - } - - } else /*if(xc.osd_mixer > OSD_MIXER_NONE)*/ { - LOGOSD("OSD mixer on (%d)", xc.osd_mixer); - it = cXinelibOsd::m_OsdStack.Last(); - while (cXinelibOsd::m_OsdStack.Prev(it)) { - LOGOSD(" -> show OSD %d", it->Index()); - it->Show(); - it = cXinelibOsd::m_OsdStack.Prev(it); - } - } - - it->Show(); - - return m_OsdInstance; -} - -void cXinelibOsdProvider::RefreshOsd(void) -{ - TRACEF("cXinelibOsdProvider::RefreshOsd"); - - cMutexLock ml(&cXinelibOsd::m_Lock); - - // bottom --> top (draw lower layer OSDs first) - cXinelibOsd *it = cXinelibOsd::m_OsdStack.Last(); - while(it) { - it->Refresh(); - it = cXinelibOsd::m_OsdStack.Prev(it); - } -} - - - |