summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_out/video_out_directfb.c634
1 files changed, 447 insertions, 187 deletions
diff --git a/src/video_out/video_out_directfb.c b/src/video_out/video_out_directfb.c
index 3d0177f2f..d7aa76d2c 100644
--- a/src/video_out/video_out_directfb.c
+++ b/src/video_out/video_out_directfb.c
@@ -45,12 +45,17 @@
#include "vo_scale.h"
#ifdef HAVE_X11
-#include "x11osd.h"
+# include "x11osd.h"
#endif
#include <directfb.h>
#include <directfb_version.h>
+#define VERSION_CODE( M, m, r ) (((M) * 1000) + ((m) * 100) + (r))
+#define DIRECTFB_VERSION_CODE VERSION_CODE( DIRECTFB_MAJOR_VERSION,\
+ DIRECTFB_MINOR_VERSION,\
+ DIRECTFB_MICRO_VERSION )
+
typedef struct directfb_frame_s {
vo_frame_t vo_frame;
@@ -76,15 +81,23 @@ typedef struct directfb_driver_s {
/* DirectFB related stuff */
IDirectFB *dfb;
- IDirectFBDisplayLayer *primary;
+ IDirectFBDisplayLayer *underlay;
+
+ /* Video Layer */
IDirectFBDisplayLayer *layer;
IDirectFBSurface *surface;
+ DFBDisplayLayerTypeFlags type;
DFBDisplayLayerCapabilities caps;
DFBDisplayLayerConfig config;
- DFBColorAdjustment default_cadj;
DFBColorAdjustment cadj;
+ DFBColorAdjustment default_cadj;
+ int default_level;
int visible;
+ /* Subpicture layer */
+ IDirectFBDisplayLayer *spic_layer;
+ IDirectFBSurface *spic_surface;
+
/* for hardware scaling */
IDirectFBSurface *temp;
int temp_frame_width;
@@ -113,9 +126,9 @@ typedef struct directfb_driver_s {
GC gc;
int depth;
x11osd *xoverlay;
- int ovl_changed;
#endif
-
+ int ovl_changed;
+
/* screen size */
int screen_width;
int screen_height;
@@ -137,9 +150,22 @@ typedef struct {
#ifndef MAX
-# define MAX(a,b) (((a) > (b)) ? (a) : (b))
+# define MAX( a, b ) (((a) > (b)) ? (a) : (b))
#endif
+#define YCBCR_TO_RGB( y, cb, cr, r, g, b ) do {\
+ int _y, _cb, _cr, _r, _g, _b;\
+ _y = ((y) - 16) * 76309;\
+ _cb = (cb) - 128;\
+ _cr = (cr) - 128;\
+ _r = (_y + _cr * 104597 + 0x8000) >> 16;\
+ _g = (_y - _cb * 25675 - _cr * 53279 + 0x8000) >> 16;\
+ _b = (_y + _cb * 132201 + 0x8000) >> 16;\
+ (r) = (_r < 0) ? 0 : ((_r > 255) ? 255 : _r);\
+ (g) = (_g < 0) ? 0 : ((_g > 255) ? 255 : _g);\
+ (b) = (_b < 0) ? 0 : ((_b > 255) ? 255 : _b);\
+} while (0)
+
/*** driver functions ***/
static uint32_t directfb_get_capabilities (vo_driver_t *this_gen) {
@@ -332,20 +358,147 @@ static void directfb_overlay_begin (vo_driver_t *this_gen,
vo_frame_t *frame_gen, int changed) {
directfb_driver_t *this = (directfb_driver_t *) this_gen;
-#ifdef HAVE_X11
this->ovl_changed += changed;
- if (this->ovl_changed && this->xoverlay) {
- XLockDisplay (this->display);
- x11osd_clear (this->xoverlay);
- XUnlockDisplay (this->display);
- }
+ if (this->ovl_changed) {
+#ifdef HAVE_X11
+ if (this->xoverlay) {
+ XLockDisplay (this->display);
+ x11osd_clear (this->xoverlay);
+ XUnlockDisplay (this->display);
+ }
#endif
+ if (this->spic_surface) {
+ lprintf ("clearing subpicture.\n");
+ this->spic_surface->SetClip (this->spic_surface, NULL);
+ this->spic_surface->Clear (this->spic_surface, 0, 0, 0, 0);
+ }
+ }
this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
}
+static void directfb_subpicture_paint (directfb_driver_t *this,
+ vo_overlay_t *overlay) {
+#define MAX_RECTS 100
+ DFBRegion clip;
+ DFBRectangle rects[MAX_RECTS];
+ int n_rects = 0;
+ DFBColor colors[OVL_PALETTE_SIZE*2];
+ int p_index = -1;
+ int xoffset;
+ int yoffset;
+ int x, y, i;
+
+ memset (colors, 0, sizeof(colors));
+
+ xoffset = this->sc.gui_win_x+overlay->x;
+ yoffset = this->sc.gui_win_y+overlay->y;
+
+ clip.x1 = xoffset;
+ clip.y1 = yoffset;
+ clip.x2 = xoffset + overlay->width - 1;
+ clip.y2 = yoffset + overlay->height - 1;
+ this->spic_surface->SetClip (this->spic_surface, &clip);
+
+ for (x = 0, y= 0, i = 0; i < overlay->num_rle; i++) {
+ int idx = overlay->rle[i].color;
+ int len = overlay->rle[i].len;
+
+ while (len > 0) {
+ clut_t color = ((clut_t *)overlay->color)[idx];
+ uint8_t alpha = overlay->trans[idx];
+ int index = idx;
+ int width;
+
+ if ((len+x) > overlay->width) {
+ width = overlay->width - x;
+ len -= width;
+ }
+ else {
+ width = len;
+ len = 0;
+ }
+
+ if ((y >= overlay->hili_top) &&
+ (y <= overlay->hili_bottom) &&
+ (x <= overlay->hili_right))
+ {
+ if ((x < overlay->hili_left) && (x+width-1 >= overlay->hili_left)) {
+ width -= overlay->hili_left - x;
+ len += overlay->hili_left - x;
+ }
+ else if (x > overlay->hili_left) {
+ color = ((clut_t *)overlay->hili_color)[idx];
+ alpha = overlay->hili_trans[idx];
+ index += OVL_PALETTE_SIZE;
+
+ if (x+width-1 > overlay->hili_right) {
+ width -= overlay->hili_right - x;
+ len += overlay->hili_right - x;
+ }
+ }
+ }
+
+ if (alpha) {
+ int flush;
+
+ rects[n_rects].x = x + xoffset;
+ rects[n_rects].y = y + yoffset;
+ rects[n_rects].w = width;
+ rects[n_rects].h = 1;
+ if (n_rects) {
+ if (rects[n_rects-1].x == rects[n_rects].x &&
+ rects[n_rects-1].w == rects[n_rects].w &&
+ rects[n_rects-1].y+rects[n_rects-1].h == rects[n_rects].y) {
+ n_rects--;
+ rects[n_rects].h++;
+ }
+ }
+ n_rects++;
+ flush = (n_rects == MAX_RECTS);
+
+ if (p_index != index) {
+ if (!colors[index].a) {
+ YCBCR_TO_RGB (color.y, color.cb, color.cr,
+ colors[index].r, colors[index].g, colors[index].b);
+ colors[index].a = alpha * 17;
+ }
+
+ lprintf ("color change to %02x%02x%02x%02x.\n",
+ colors[index].a, colors[index].r,
+ colors[index].g, colors[index].b);
+ this->spic_surface->SetColor (this->spic_surface,
+ colors[index].r, colors[index].g,
+ colors[index].b, colors[index].a);
+ if (p_index != -1)
+ flush = 1;
+ p_index = index;
+ }
+
+ if (flush) {
+ lprintf ("flushing %d rect(s).\n", n_rects);
+ this->spic_surface->FillRectangles (this->spic_surface, rects, n_rects);
+ n_rects = 0;
+ }
+ }
+
+ x += width;
+ if (x == overlay->width) {
+ if (++y == overlay->height)
+ break;
+ x = 0;
+ }
+ }
+ }
+
+ if (n_rects) {
+ lprintf ("flushing %d remaining rect(s).\n", n_rects);
+ this->spic_surface->FillRectangles (this->spic_surface, rects, n_rects);
+ }
+}
+
static void directfb_overlay_blend (vo_driver_t *this_gen,
vo_frame_t *frame_gen, vo_overlay_t *overlay) {
directfb_driver_t *this = (directfb_driver_t *) this_gen;
@@ -355,13 +508,19 @@ static void directfb_overlay_blend (vo_driver_t *this_gen,
return;
if (overlay->unscaled) {
+ if (!this->ovl_changed)
+ return;
#ifdef HAVE_X11
- if (this->ovl_changed && this->xoverlay) {
- XLockDisplay (this->display);
- x11osd_blend (this->xoverlay, overlay);
- XUnlockDisplay (this->display);
- }
+ if (this->xoverlay) {
+ XLockDisplay (this->display);
+ x11osd_blend (this->xoverlay, overlay);
+ XUnlockDisplay (this->display);
+ }
#endif
+ if (this->spic_surface) {
+ lprintf ("repainting subpicture.\n");
+ directfb_subpicture_paint (this, overlay);
+ }
}
else {
if (frame->format == DSPF_YUY2) {
@@ -380,17 +539,24 @@ static void directfb_overlay_blend (vo_driver_t *this_gen,
}
static void directfb_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
-#ifdef HAVE_X11
directfb_driver_t *this = (directfb_driver_t *) this_gen;
- if (this->ovl_changed && this->xoverlay) {
- XLockDisplay (this->display);
- x11osd_expose (this->xoverlay);
- XUnlockDisplay (this->display);
- }
-
- this->ovl_changed = 0;
+ if (this->ovl_changed) {
+#ifdef HAVE_X11
+ if (this->xoverlay) {
+ XLockDisplay (this->display);
+ x11osd_expose (this->xoverlay);
+ XUnlockDisplay (this->display);
+ }
#endif
+ if (this->spic_surface) {
+ lprintf ("flipping subpicture.\n");
+ this->spic_surface->SetClip (this->spic_surface, NULL);
+ this->spic_surface->Flip (this->spic_surface, NULL, 0);
+ }
+
+ this->ovl_changed = 0;
+ }
}
static int directfb_redraw_needed (vo_driver_t *this_gen) {
@@ -439,7 +605,6 @@ static int directfb_redraw_needed (vo_driver_t *this_gen) {
static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
directfb_driver_t *this = (directfb_driver_t *) this_gen;
directfb_frame_t *frame = (directfb_frame_t *) frame_gen;
- DFBResult ret;
if (this->cur_frame)
this->cur_frame->vo_frame.free (&this->cur_frame->vo_frame);
@@ -456,10 +621,12 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen
this->config.flags |= DLCONF_HEIGHT;
this->config.height = frame->height;
}
-
- if (frame->format != this->config.pixelformat) {
- this->config.flags |= DLCONF_PIXELFORMAT;
- this->config.pixelformat = frame->format;
+
+ if (this->type & DLTF_VIDEO) {
+ if (frame->format != this->config.pixelformat) {
+ this->config.flags |= DLCONF_PIXELFORMAT;
+ this->config.pixelformat = frame->format;
+ }
}
if (this->caps & DLCAPS_DEINTERLACING) {
@@ -476,14 +643,18 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen
}
if (this->config.flags) {
+ DFBDisplayLayerConfigFlags failed = 0;
+
lprintf ("changing layer configuration to %dx%d %s.\n",
this->config.width, this->config.height,
(this->config.pixelformat == DSPF_YUY2) ? "YUY2" : "YV12");
- ret = this->layer->SetConfiguration (this->layer, &this->config);
- if (ret != DFB_OK)
- DirectFBError ("IDirectFBDisplayLayer::SetConfiguration()", ret);
+ this->layer->TestConfiguration (this->layer, &this->config, &failed);
+ this->config.flags &= ~failed;
+ this->layer->SetConfiguration (this->layer, &this->config);
this->layer->GetConfiguration (this->layer, &this->config);
+
+ lprintf ("failed=0x%08x.\n", failed);
}
if (this->sc.delivered_width != frame->width ||
@@ -545,24 +716,26 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge
/* TODO: try to change video mode when frame size changes */
- if (frame->format != this->config.pixelformat) {
- this->config.flags = DLCONF_PIXELFORMAT;
- this->config.pixelformat = frame->format;
-
- lprintf ("changing layer pixelformat to %s.\n",
- (this->config.pixelformat == DSPF_YUY2) ? "YUY2" : "YV12");
+ if (this->type & DLTF_VIDEO) {
+ if (frame->format != this->config.pixelformat) {
+ this->config.flags = DLCONF_PIXELFORMAT;
+ this->config.pixelformat = frame->format;
- ret = this->layer->SetConfiguration (this->layer, &this->config);
- if (ret != DFB_OK)
- DirectFBError ("IDirectFBDisplayLayer::SetConfiguration()", ret);
- this->layer->GetConfiguration (this->layer, &this->config);
+ lprintf ("changing layer pixelformat to %s.\n",
+ (this->config.pixelformat == DSPF_YUY2) ? "YUY2" : "YV12");
+
+ ret = this->layer->SetConfiguration (this->layer, &this->config);
+ this->layer->GetConfiguration (this->layer, &this->config);
+
+ lprintf ("%s.\n", ret ? "failed" : "ok");
+ }
}
if (this->temp) {
/* try to reduce video memory fragmentation */
if (this->temp_frame_width < frame->width ||
this->temp_frame_height < frame->height ||
- this->temp_frame_format != frame->format)
+ this->temp_frame_format != this->config.pixelformat)
{
DFBSurfaceDescription dsc;
@@ -576,7 +749,7 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge
dsc.caps = DSCAPS_INTERLACED;
dsc.width = frame->width;
dsc.height = frame->height;
- dsc.pixelformat = frame->format;
+ dsc.pixelformat = this->config.pixelformat;
ret = this->dfb->CreateSurface (this->dfb, &dsc, &this->temp);
if (ret != DFB_OK)
@@ -584,7 +757,7 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge
this->temp_frame_width = frame->width;
this->temp_frame_height = frame->height;
- this->temp_frame_format = frame->format;
+ this->temp_frame_format = this->config.pixelformat;
}
}
@@ -701,7 +874,10 @@ static int directfb_get_property (vo_driver_t *this_gen, int property) {
case VO_PROP_WINDOW_HEIGHT:
return this->sc.gui_height;
-
+
+ case VO_PROP_MAX_NUM_FRAMES:
+ return (this->type & DLTF_VIDEO) ? 8 : 15;
+
default:
break;
}
@@ -968,14 +1144,24 @@ static void directfb_dispose (vo_driver_t *this_gen) {
if (this->temp)
this->temp->Release (this->temp);
+
+ if (this->spic_surface)
+ this->spic_surface->Release (this->spic_surface);
+
+ if (this->spic_layer)
+ this->spic_layer->Release (this->spic_layer);
if (this->surface)
this->surface->Release (this->surface);
if (this->layer) {
this->layer->SetColorAdjustment (this->layer, &this->default_cadj);
+ this->layer->SetLevel (this->layer, this->default_level);
this->layer->Release (this->layer);
}
+
+ if (this->underlay)
+ this->underlay->Release (this->underlay);
if (this->dfb)
this->dfb->Release (this->dfb);
@@ -987,71 +1173,6 @@ static void directfb_dispose (vo_driver_t *this_gen) {
/*** misc functions ****/
-static DFBEnumerationResult find_overlay (DFBDisplayLayerID id,
- DFBDisplayLayerDescription dsc, void *ctx) {
- DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx;
-
- if (dsc.caps & DLCAPS_SURFACE &&
- dsc.caps & DLCAPS_SCREEN_LOCATION) {
- *ret_id = id;
- return DFENUM_CANCEL;
- }
-
- return DFENUM_OK;
-}
-
-static DFBResult probe_device (directfb_driver_t *this, DFBDisplayLayerID id) {
- IDirectFBDisplayLayer *layer;
- DFBDisplayLayerDescription dsc;
- DFBDisplayLayerConfig config;
- DFBResult ret;
-
- ret = this->dfb->GetDisplayLayer (this->dfb, id, &layer);
- if (ret != DFB_OK) {
- DirectFBError ("IDirectFB::GetDisplayLayer()", ret);
- return ret;
- }
-
- layer->SetCooperativeLevel (layer, DLSCL_EXCLUSIVE);
-
- /* hide */
- layer->SetOpacity (layer, 0x00);
-
- /* check if YUY2 is supported */
- config.flags = DLCONF_PIXELFORMAT;
- config.pixelformat = DSPF_YUY2;
-
- ret = layer->TestConfiguration (layer, &config, NULL);
- if (ret != DFB_OK) {
- xprintf (this->xine, XINE_VERBOSITY_LOG,
- "video_out_directfb: Display Layer #%d doesn't support YUY2.\n", id);
- layer->Release (layer);
- return DFB_UNSUPPORTED;
- }
-
- /* check if YV12 is supported */
- config.flags = DLCONF_PIXELFORMAT;
- config.pixelformat = DSPF_YV12;
-
- ret = layer->TestConfiguration (layer, &config, NULL);
- if (ret != DFB_OK) {
- xprintf (this->xine, XINE_VERBOSITY_LOG,
- "video_out_directfb: Display Layer #%d doesn't support YV12.\n", id);
- layer->Release (layer);
- return DFB_UNSUPPORTED;
- }
-
- layer->GetDescription (layer, &dsc);
-
- this->layer = layer;
- this->caps = dsc.caps;
-
- xprintf (this->xine, XINE_VERBOSITY_LOG,
- "video_out_directfb: using Display Layer #%d.\n", id);
-
- return DFB_OK;
-}
-
static void update_config_cb (void *data, xine_cfg_entry_t *entry) {
directfb_driver_t *this = (directfb_driver_t *) data;
@@ -1212,29 +1333,128 @@ static void init_config (directfb_driver_t *this) {
}
}
+static DFBEnumerationResult find_overlay (DFBDisplayLayerID id,
+ DFBDisplayLayerDescription dsc, void *ctx) {
+ DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx;
+
+ if (dsc.type & DLTF_VIDEO &&
+ dsc.caps & DLCAPS_SURFACE &&
+ dsc.caps & DLCAPS_SCREEN_LOCATION) {
+ lprintf ("overlay's id = %d.\n", id);
+ *ret_id = id;
+ return DFENUM_CANCEL;
+ }
+
+ return DFENUM_OK;
+}
+
static DFBEnumerationResult find_underlay (DFBDisplayLayerID id,
DFBDisplayLayerDescription dsc, void *ctx) {
DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx;
- *ret_id = id;
+ if (dsc.caps & DLCAPS_SURFACE) {
+ lprintf ("underlay's id = %d.\n", id);
+ *ret_id = id;
+ return DFENUM_CANCEL;
+ }
+
+ return DFENUM_OK;
+}
+
+static void init_subpicture (directfb_driver_t *this) {
+ DFBResult ret;
+
+ /* subpicture layer supported by Unichrome and Radeon */
+ if (this->caps & DLCAPS_LEVELS && this->underlay) {
+ DFBDisplayLayerDescription dsc;
+
+ this->underlay->GetDescription (this->underlay, &dsc);
+ if (dsc.caps & DLCAPS_ALPHACHANNEL) {
+ DFBDisplayLayerConfig config;
+
+ /* put overlay under underlay */
+ this->layer->SetLevel (this->layer, -1);
+
+ /* enable alphachannel on the underlay */
+ config.flags = DLCONF_PIXELFORMAT | DLCONF_OPTIONS;
+ config.pixelformat = DSPF_ARGB;
+ config.options = DLOP_ALPHACHANNEL;
+ ret = this->underlay->SetConfiguration (this->underlay, &config);
+ if (ret == DFB_OK) {
+ this->underlay->AddRef (this->underlay);
+ this->spic_layer = this->underlay;
+ }
+ else {
+ this->layer->SetLevel (this->layer, 1);
+ }
+ }
+ }
- return DFENUM_CANCEL;
-}
+ /* TODO: add support for different types of subpicture layers. */
+
+ if (this->spic_layer) {
+ ret = this->spic_layer->GetSurface (this->spic_layer, &this->spic_surface);
+ if (ret) {
+ DirectFBError ("IDirectFBDisplayLayer::GetSurface()", ret);
+ this->spic_layer->Release (this->spic_layer);
+ this->spic_layer = NULL;
+ return;
+ }
+
+ this->spic_surface->Clear (this->spic_surface, 0, 0, 0, 0);
+ this->spic_surface->Flip (this->spic_surface, NULL, 0);
+
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb: using hardware subpicture acceleration.\n"));
+ }
+}
static DFBResult init_device (directfb_driver_t *this) {
IDirectFBSurface *surface;
DFBDisplayLayerConfig config;
DFBDisplayLayerConfigFlags failed = 0;
DFBResult ret;
-
- /* get current color cadjustment */
- this->layer->GetColorAdjustment (this->layer, &this->default_cadj);
- this->cadj = this->default_cadj;
+
+ config.flags = DLCONF_NONE;
+
+ if (this->type & DLTF_VIDEO) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb: layer supports video output.\n"));
+
+ config.flags |= DLCONF_PIXELFORMAT;
+
+ /* test for YV12 support */
+ config.pixelformat = DSPF_YV12;
+ ret = this->layer->TestConfiguration (this->layer, &config, NULL);
+ if (ret) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb: layer doesn't support YV12!\n"));
+
+ /* test for YUY2 support */
+ config.pixelformat = DSPF_YUY2;
+ ret = this->layer->TestConfiguration (this->layer, &config, NULL);
+ if (ret) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb: layer doesn't support YUY2!\n"));
+ /* layer supports video output but none of the formats we need */
+ this->type &= ~DLTF_VIDEO;
+ config.flags &= ~DLCONF_PIXELFORMAT;
+ }
+ }
+ }
+
+#if DIRECTFB_VERSION_CODE < VERSION_CODE(0,9,25)
+ if (!(this->type & DLTF_VIDEO)) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb:"
+ "need at least DirectFB 0.9.25 to play on this layer!\n"));
+ return DFB_UNSUPPORTED;
+ }
+#endif
/* set layer configuration */
- config.flags = DLCONF_BUFFERMODE | DLCONF_PIXELFORMAT | DLCONF_OPTIONS;
- config.pixelformat = DSPF_YV12;
- config.options = DLOP_NONE;
+ config.flags |= DLCONF_BUFFERMODE | DLCONF_OPTIONS;
+ config.options = DLOP_NONE;
switch (this->buffermode) {
case 0:
@@ -1261,20 +1481,20 @@ static DFBResult init_device (directfb_driver_t *this) {
ret = this->layer->TestConfiguration (this->layer, &config, &failed);
if (failed & DLCONF_BUFFERMODE) {
xprintf (this->xine, XINE_VERBOSITY_LOG,
- "video_out_directfb: layer doesn't support buffermode %d!\n",
+ _("video_out_directfb: layer doesn't support buffermode %d!\n"),
this->buffermode);
config.flags &= ~DLCONF_BUFFERMODE;
}
if (failed & DLCONF_OPTIONS) {
xprintf (this->xine, XINE_VERBOSITY_LOG,
- "video_out_directfb: layer doesn't support options 0x%08x!\n",
+ _("video_out_directfb: layer doesn't support options 0x%08x!\n"),
config.options);
config.flags &= ~DLCONF_OPTIONS;
}
ret = this->layer->SetConfiguration (this->layer, &config);
/* this should never happen */
- if (ret != DFB_OK) {
+ if (ret) {
DirectFBError ("IDirectFBDisplayLayer::SetConfiguration()", ret);
return ret;
}
@@ -1290,6 +1510,13 @@ static DFBResult init_device (directfb_driver_t *this) {
if (this->field_parity)
this->layer->SetFieldParity (this->layer, this->field_parity-1);
+ /* get current color cadjustment */
+ this->layer->GetColorAdjustment (this->layer, &this->default_cadj);
+ this->cadj = this->default_cadj;
+
+ /* get current level */
+ this->layer->GetLevel (this->layer, &this->default_level);
+
/* retrieve layer's surface */
ret = this->layer->GetSurface (this->layer, &surface);
if (ret != DFB_OK) {
@@ -1308,33 +1535,29 @@ static DFBResult init_device (directfb_driver_t *this) {
this->surface = surface;
if (this->caps & DLCAPS_SCREEN_LOCATION) {
- IDirectFBScreen *screen = NULL;
- DFBDisplayLayerID layer_id = -1;
- int width = 640;
- int height = 480;
+ IDirectFBScreen *screen = NULL;
+ DFBDisplayLayerID id = -1;
+
+ this->screen_width = 640;
+ this->screen_height = 480;
this->layer->GetScreen (this->layer, &screen);
if (screen) {
- screen->EnumDisplayLayers (screen, find_underlay, (void*)&layer_id);
+ screen->EnumDisplayLayers (screen, find_underlay, (void*)&id);
screen->Release (screen);
}
- if (layer_id != -1) {
- IDirectFBDisplayLayer *layer;
- DFBDisplayLayerConfig config;
-
- this->dfb->GetDisplayLayer (this->dfb, layer_id, &layer);
- if (layer) {
- layer->GetConfiguration (layer, &config);
- layer->Release (layer);
-
- width = config.width;
- height = config.height;
+ this->dfb->GetDisplayLayer (this->dfb, id, &this->underlay);
+ if (this->underlay) {
+ this->underlay->GetConfiguration (this->underlay, &config);
+ this->screen_width = config.width;
+ this->screen_height = config.height;
+
+ if (this->visual_type == XINE_VISUAL_TYPE_FB) {
+ this->underlay->SetCooperativeLevel (this->underlay, DLSCL_EXCLUSIVE);
+ this->underlay->SetBackgroundMode( this->underlay, DLBM_DONTCARE);
}
- }
-
- this->screen_width = width;
- this->screen_height = height;
+ }
}
else {
/* playing to underlay,
@@ -1343,12 +1566,15 @@ static DFBResult init_device (directfb_driver_t *this) {
DFBSurfaceDescription dsc;
DFBAccelerationMask mask = DFXL_NONE;
+ this->layer->AddRef (this->layer);
+ this->underlay = this->layer;
+
dsc.flags = DSDESC_CAPS | DSDESC_WIDTH |
DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
dsc.caps = DSCAPS_INTERLACED;
dsc.width = 320;
dsc.height = 240;
- dsc.pixelformat = DSPF_YV12;
+ dsc.pixelformat = this->config.pixelformat;
if (this->dfb->CreateSurface (this->dfb, &dsc, &temp) == DFB_OK) {
this->surface->GetAccelerationMask (this->surface, temp, &mask);
@@ -1386,7 +1612,7 @@ static DFBResult init_device (directfb_driver_t *this) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"video_out_directfb: screen size is %dx%d.\n",
this->screen_width, this->screen_height);
-
+
return DFB_OK;
}
@@ -1413,8 +1639,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
directfb_driver_t *this;
fb_visual_t *visual = (fb_visual_t *) visual_gen;
config_values_t *config = class->xine->config;
- IDirectFBScreen *screen;
- DFBDisplayLayerID id = DLID_PRIMARY;
+ DFBDisplayLayerID id;
DFBResult ret;
this = xine_xmalloc (sizeof (directfb_driver_t));
@@ -1432,12 +1657,13 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
return NULL;
}
- DirectFBSetOption ("no-vt", NULL);
DirectFBSetOption ("bg-color", "00000000" );
+ DirectFBSetOption ("no-vt-switch", NULL);
+ DirectFBSetOption ("no-vt-switching", NULL);
DirectFBSetOption ("no-sighandler", NULL );
DirectFBSetOption ("no-deinit-check", NULL );
- /* linux_input blocks input from console, disable it */
DirectFBSetOption ("disable-module", "linux_input");
+ DirectFBSetOption ("disable-module", "keyboard");
/* create the main interface or retrieve an already existing one */
ret = DirectFBCreate (&this->dfb);
@@ -1446,43 +1672,51 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
free (this);
return NULL;
}
-
- /* retrieve an interface to the current screen */
- ret = this->dfb->GetScreen (this->dfb, DSCID_PRIMARY, &screen);
- if (ret != DFB_OK) {
- DirectFBError ("IDirectFB::GetScreen( DSCID_PRIMARY )", ret);
- this->dfb->Release (this->dfb);
- free (this);
- return NULL;
- }
-
- /* find an overlay layer on the current screen */
- ret = screen->EnumDisplayLayers (screen, find_overlay, (void*)&id);
- screen->Release (screen);
- if (ret != DFB_OK) {
- DirectFBError( "IDirectFBScreen::EnumDisplayLayers()", ret);
- this->dfb->Release (this->dfb);
- free (this);
- return NULL;
- }
/* allow user/application to select a different layer */
id = config->register_num (config,
- "video.device.directfb_layer_id", id,
- _("video layer id"),
+ "video.device.directfb_layer_id", -1,
+ _("video layer id (auto: -1)"),
_("Select the video output layer by its id."),
20, NULL, 0);
-
- if (probe_device (this, id) != DFB_OK) {
- xprintf (this->xine, XINE_VERBOSITY_LOG,
- _("video_out_directfb: no usable output layer was found!\n"));
+ if (id == -1) {
+ IDirectFBScreen *screen;
+
+ /* retrieve an interface to the current screen */
+ ret = this->dfb->GetScreen (this->dfb, DSCID_PRIMARY, &screen);
+ if (ret != DFB_OK) {
+ DirectFBError ("IDirectFB::GetScreen( DSCID_PRIMARY )", ret);
+ this->dfb->Release (this->dfb);
+ free (this);
+ return NULL;
+ }
+
+ /* find an overlay layer on the current screen */
+ id = DLID_PRIMARY;
+ screen->EnumDisplayLayers (screen, find_overlay, (void*)&id);
+ screen->Release (screen);
+ }
+
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb: using display layer #%d.\n"), id);
+
+ ret = this->dfb->GetDisplayLayer (this->dfb, id, &this->layer);
+ if (ret == DFB_OK) {
+ DFBDisplayLayerDescription dsc;
+ this->layer->SetCooperativeLevel (this->layer, DLSCL_EXCLUSIVE);
+ this->layer->SetOpacity (this->layer, 0x00);
+ this->layer->GetDescription (this->layer, &dsc);
+ this->type = dsc.type;
+ this->caps = dsc.caps;
+ if (id == DLID_PRIMARY)
+ this->caps &= ~(DLCAPS_SCREEN_LOCATION | DLCAPS_DST_COLORKEY);
+ }
+ else {
+ DirectFBError ("IDirectFB::GetDisplayLayer()", ret);
this->dfb->Release (this->dfb);
free (this);
return NULL;
}
-
- if (id == DLID_PRIMARY)
- this->caps &= ~(DLCAPS_SCREEN_LOCATION | DLCAPS_DST_COLORKEY);
this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP;
/* set default configuration */
@@ -1496,13 +1730,18 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
/* get user configuration */
init_config (this);
- /* set layer configuration */
+ /* initialize video layer */
if (init_device (this) != DFB_OK) {
this->layer->Release (this->layer);
this->dfb->Release (this->dfb);
free (this);
return NULL;
}
+
+ /* initialize subpicture layer (if available) */
+ init_subpicture (this);
+ if (this->spic_layer)
+ this->capabilities |= VO_CAP_UNSCALED_OVERLAY;
_x_alphablend_init (&this->alphablend_extra_data, this->xine);
@@ -1548,14 +1787,13 @@ static char* get_description_fb (video_driver_class_t *this_gen) {
static void dispose_class_fb (video_driver_class_t *this_gen) {
directfb_class_t *this = (directfb_class_t *) this_gen;
-
free (this);
}
static void *init_class_fb (xine_t *xine, void *visual_gen) {
directfb_class_t *this;
const char *error;
-
+
/* check DirectFB version */
error = DirectFBCheckVersion( DIRECTFB_MAJOR_VERSION,
DIRECTFB_MINOR_VERSION,
@@ -1638,15 +1876,39 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void
free (this);
return NULL;
}
-
- if (id == DLID_PRIMARY || probe_device (this, id) != DFB_OK) {
+
+ if (id != DLID_PRIMARY) {
+ DFBDisplayLayerDescription dsc;
+ /* get overlay access */
+ ret = this->dfb->GetDisplayLayer (this->dfb, id, &this->layer);
+ if (ret) {
+ DirectFBError ("IDirectFB::GetDisplayLayer()", ret);
+ this->dfb->Release (this->dfb);
+ free (this);
+ return NULL;
+ }
+ this->layer->SetCooperativeLevel (this->layer, DLSCL_EXCLUSIVE);
+ this->layer->SetOpacity (this->layer, 0x00);
+ this->layer->GetDescription (this->layer, &dsc);
+ this->type = dsc.type;
+ this->caps = dsc.caps;
+ if (!(this->caps & DLCAPS_SCREEN_LOCATION)) {
+ this->layer->Release (this->layer);
+ this->layer = NULL;
+ }
+ }
+
+ if (!this->layer) {
xprintf (this->xine, XINE_VERBOSITY_LOG,
- _("video_out_directfb: no usable overlay layer was found!\n"));
+ _("video_out_directfb: no usable display layer was found!\n"));
this->dfb->Release (this->dfb);
free (this);
return NULL;
}
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ _("video_out_directfb: using display layer #%d.\n"), id);
+
this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP;
/* set default configuration */
this->buffermode = 1; // double
@@ -1667,8 +1929,6 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void
return NULL;
}
-
-
this->display = visual->display;
this->screen = visual->screen;
this->drawable = visual->d;