diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 4ed73dfc..879c604a 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3308,6 +3308,8 @@ Thomas Reufer for adding cOsdProvider::OsdSizeChanged() for suggesting to change the German translations if the texts related to "binary skipping" + for suggesting to change the return value of cOsd::RenderPixmaps() from cPixmapMemory + to cPixmap Eike Sauer for reporting a problem with channels that need more than 5 TS packets for detecting diff --git a/HISTORY b/HISTORY index f1af8eff..70acdc73 100644 --- a/HISTORY +++ b/HISTORY @@ -8523,7 +8523,7 @@ Video Disk Recorder Revision History copy process has been successful (problem reported by Christoph Haubrich). - Added the UPDATE-2.2.0 file. -2015-02-10: Version 2.1.10 +2015-02-11: Version 2.1.10 - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - Updated the Macedonian OSD texts (thanks to Dimitar Petrovski). @@ -8551,3 +8551,17 @@ Video Disk Recorder Revision History of using the environment variable VDR_CHARSET_OVERRIDE still works, but is now deprecated and may be removed in a future version. The value given in the --chartab option takes precedence over that in VDR_CHARSET_OVERRIDE. +- cOsd::RenderPixmaps() now returns a pointer to cPixmap instead of cPixmapMemory + (suggested by Thomas Reufer). This is necessary to allow plugins with derived + cPixmap implementations to use this function. Plugins that use this function + with cPixmapMemory now need to add a dynamic cast to the call, as in + + cPixmapMemory *pm = dynamic_cast(RenderPixmaps())); + + They also need to call DestroyPixmap(pm) instead of "delete pm" to properly release + the resulting pixmap after use. + The dvbhddevice plugin has been modified accordingly. +- A cPixmap with a negative layer no longer marks any portion of the OSD's view port + as "dirty" when drawing on it. This may improve performance when drawing on a + hidden pixmap, because it avoids unnecessary refreshes of the OSD. +- Added a missing initialization of "panning" to the constructor of cPixmapMemory. diff --git a/UPDATE-2.2.0 b/UPDATE-2.2.0 index bb3058c8..566da1f5 100644 --- a/UPDATE-2.2.0 +++ b/UPDATE-2.2.0 @@ -127,6 +127,15 @@ Plugins: - Added cOsdProvider::OsdSizeChanged(), which plugins that implement an output device can call to signal a change in the OSD that requires a redraw of the currently displayed object. +- cOsd::RenderPixmaps() now returns a pointer to cPixmap instead of cPixmapMemory + This is necessary to allow plugins with derived cPixmap implementations to use this + function. Plugins that use this function with cPixmapMemory now need to add + a dynamic cast to the call, as in + + cPixmapMemory *pm = dynamic_cast(RenderPixmaps())); + + They also need to call DestroyPixmap(pm) instead of "delete pm" to properly release + the resulting pixmap after use. Skins: @@ -220,6 +229,15 @@ OSD: is unexpected at this point. You can still navigate to the last replayed recording (if any) by pressing Ok repeatedly in the Recordings menu. +- cOsd::RenderPixmaps() now returns a pointer to cPixmap instead of cPixmapMemory + This is necessary to allow plugins with derived cPixmap implementations to use this + function. Plugins that use this function with cPixmapMemory now need to add + a dynamic cast to the call, as in + + cPixmapMemory *pm = dynamic_cast(RenderPixmaps())); + + They also need to call DestroyPixmap(pm) instead of "delete pm" to properly release + the resulting pixmap after use. Channels: diff --git a/osd.c b/osd.c index d31ee8a3..a475488e 100644 --- a/osd.c +++ b/osd.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 3.4 2015/01/15 11:20:56 kls Exp $ + * $Id: osd.c 3.5 2015/02/11 09:48:02 kls Exp $ */ #include "osd.h" @@ -984,12 +984,13 @@ cPixmap::cPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort) void cPixmap::MarkViewPortDirty(const cRect &Rect) { - dirtyViewPort.Combine(Rect.Intersected(viewPort)); + if (layer >= 0) + dirtyViewPort.Combine(Rect.Intersected(viewPort)); } void cPixmap::MarkViewPortDirty(const cPoint &Point) { - if (viewPort.Contains(Point)) + if (layer >= 0 && viewPort.Contains(Point)) dirtyViewPort.Combine(Point); } @@ -1025,11 +1026,18 @@ void cPixmap::SetLayer(int Layer) esyslog("ERROR: pixmap layer %d limited to %d", Layer, MAXPIXMAPLAYERS - 1); Layer = MAXPIXMAPLAYERS - 1; } - if (Layer != layer) { - if (Layer > 0 || layer > 0) - MarkViewPortDirty(viewPort); + // The sequence here is important, because the view port is only marked as dirty + // if the layer is >= 0: + if (layer >= 0) { + MarkViewPortDirty(viewPort); // the pixmap is visible and may or may not become invisible layer = Layer; } + else if (Layer >= 0) { + layer = Layer; + MarkViewPortDirty(viewPort); // the pixmap was invisible and has become visible + } + else + layer = Layer; // the pixmap was invisible and remains so Unlock(); } @@ -1141,6 +1149,7 @@ cPixmapMemory::cPixmapMemory(int Layer, const cRect &ViewPort, const cRect &Draw :cPixmap(Layer, ViewPort, DrawPort) { data = MALLOC(tColor, this->DrawPort().Width() * this->DrawPort().Height()); + panning = false; } cPixmapMemory::~cPixmapMemory() @@ -1714,7 +1723,8 @@ void cOsd::DestroyPixmap(cPixmap *Pixmap) LOCK_PIXMAPS; for (int i = 1; i < pixmaps.Size(); i++) { // begin at 1 - don't let the background pixmap be destroyed! if (pixmaps[i] == Pixmap) { - pixmaps[0]->MarkViewPortDirty(Pixmap->ViewPort()); + if (Pixmap->Layer() >= 0) + pixmaps[0]->MarkViewPortDirty(Pixmap->ViewPort()); delete Pixmap; pixmaps[i] = NULL; return; @@ -1737,9 +1747,9 @@ cPixmap *cOsd::AddPixmap(cPixmap *Pixmap) return Pixmap; } -cPixmapMemory *cOsd::RenderPixmaps(void) +cPixmap *cOsd::RenderPixmaps(void) { - cPixmapMemory *Pixmap = NULL; + cPixmap *Pixmap = NULL; if (isTrueColor) { LOCK_PIXMAPS; // Collect overlapping dirty rectangles: @@ -1762,25 +1772,27 @@ cPixmapMemory *cOsd::RenderPixmaps(void) d.Combine(OldDirty); OldDirty = NewDirty; #endif - Pixmap = new cPixmapMemory(0, d); - Pixmap->Clear(); - // Render the individual pixmaps into the resulting pixmap: - for (int Layer = 0; Layer < MAXPIXMAPLAYERS; Layer++) { - for (int i = 0; i < pixmaps.Size(); i++) { - if (cPixmap *pm = pixmaps[i]) { - if (pm->Layer() == Layer) - Pixmap->DrawPixmap(pm, d); + Pixmap = CreatePixmap(-1, d); + if (Pixmap) { + Pixmap->Clear(); + // Render the individual pixmaps into the resulting pixmap: + for (int Layer = 0; Layer < MAXPIXMAPLAYERS; Layer++) { + for (int i = 0; i < pixmaps.Size(); i++) { + if (cPixmap *pm = pixmaps[i]) { + if (pm->Layer() == Layer) + Pixmap->DrawPixmap(pm, d); + } } - } - } + } #ifdef DebugDirty - cPixmapMemory DirtyIndicator(7, NewDirty); - static tColor DirtyIndicatorColors[] = { 0x7FFFFF00, 0x7F00FFFF }; - static int DirtyIndicatorIndex = 0; - DirtyIndicator.Fill(DirtyIndicatorColors[DirtyIndicatorIndex]); - DirtyIndicatorIndex = 1 - DirtyIndicatorIndex; - Pixmap->Render(&DirtyIndicator, DirtyIndicator.DrawPort(), DirtyIndicator.ViewPort().Point().Shifted(-Pixmap->ViewPort().Point())); + cPixmapMemory DirtyIndicator(7, NewDirty); + static tColor DirtyIndicatorColors[] = { 0x7FFFFF00, 0x7F00FFFF }; + static int DirtyIndicatorIndex = 0; + DirtyIndicator.Fill(DirtyIndicatorColors[DirtyIndicatorIndex]); + DirtyIndicatorIndex = 1 - DirtyIndicatorIndex; + Pixmap->Render(&DirtyIndicator, DirtyIndicator.DrawPort(), DirtyIndicator.ViewPort().Point().Shifted(-Pixmap->ViewPort().Point())); #endif + } } } return Pixmap; diff --git a/osd.h b/osd.h index e5864c4f..9ef32ac7 100644 --- a/osd.h +++ b/osd.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.h 3.5 2015/01/15 11:23:52 kls Exp $ + * $Id: osd.h 3.6 2015/02/11 09:48:02 kls Exp $ */ #ifndef __OSD_H @@ -763,12 +763,13 @@ protected: ///< the pixmap could not be added to the list. ///< A derived class that implements its own cPixmap class must call AddPixmap() ///< in order to add a newly created pixmap to the OSD's list of pixmaps. - cPixmapMemory *RenderPixmaps(void); + cPixmap *RenderPixmaps(void); ///< Renders the dirty part of all pixmaps into a resulting pixmap that ///< shall be displayed on the OSD. The returned pixmap's view port is ///< set to the location of the rectangle on the OSD that needs to be ///< refreshed; its draw port's origin is at (0, 0), and it has the same ///< size as the view port. + ///< Only pixmaps with a non-negative layer value are rendered. ///< If there are several non-overlapping dirty rectangles from different pixmaps, ///< they are returned separately in order to avoid re-rendering large parts ///< of the OSD that haven't changed at all. The caller must therefore call @@ -778,7 +779,7 @@ protected: ///< by putting a LOCK_PIXMAPS into the scope of the operation). ///< If there are no dirty pixmaps, or if this is not a true color OSD, ///< this function returns NULL. - ///< The caller must delete the returned pixmap after use. + ///< The caller must call DestroyPixmap() for the returned pixmap after use. public: virtual ~cOsd(); ///< Shuts down the OSD. @@ -930,13 +931,16 @@ public: ///< pixmaps, the Flush() function should basically do something like this: ///< ///< LOCK_PIXMAPS; - ///< while (cPixmapMemory *pm = RenderPixmaps()) { + ///< while (cPixmapMemory *pm = dynamic_cast(RenderPixmaps())) { ///< int w = pm->ViewPort().Width(); ///< int h = pm->ViewPort().Height(); ///< int d = w * sizeof(tColor); ///< MyOsdDrawPixmap(Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y(), pm->Data(), w, h, h * d); - ///< delete pm; + ///< DestroyPixmap(pm); ///< } + ///< + ///< If a plugin uses a derived cPixmap implementation, it needs to use that + ///< type instead of cPixmapMemory. }; #define MAXOSDIMAGES 64