summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_out/Makefile.am2
-rw-r--r--src/video_out/video_out_directfb.c306
2 files changed, 207 insertions, 101 deletions
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am
index 2c25e844a..684ecd8ea 100644
--- a/src/video_out/Makefile.am
+++ b/src/video_out/Makefile.am
@@ -148,7 +148,7 @@ xineplug_vo_out_fb_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \
xineplug_vo_out_fb_la_LIBADD = $(MLIB_LIBS) $(XINE_LIB) $(THREAD_LIBS)
xineplug_vo_out_fb_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
-xineplug_vo_out_directfb_la_SOURCES = video_out_directfb.c
+xineplug_vo_out_directfb_la_SOURCES = video_out_directfb.c $(X11OSD)
xineplug_vo_out_directfb_la_LIBADD = $(DIRECTFB_LIBS) $(X_LIBS) $(THREAD_LIBS)
xineplug_vo_out_directfb_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
diff --git a/src/video_out/video_out_directfb.c b/src/video_out/video_out_directfb.c
index db05c1ea7..7d4e10c09 100644
--- a/src/video_out/video_out_directfb.c
+++ b/src/video_out/video_out_directfb.c
@@ -44,6 +44,10 @@
#include "xineutils.h"
#include "vo_scale.h"
+#ifdef HAVE_X11
+#include "x11osd.h"
+#endif
+
#include <directfb.h>
#include <directfb_version.h>
@@ -64,6 +68,7 @@ typedef struct directfb_driver_s {
vo_driver_t vo_driver;
int visual_type;
+ uint32_t capabilities;
xine_t *xine;
@@ -71,6 +76,7 @@ typedef struct directfb_driver_s {
/* DirectFB related stuff */
IDirectFB *dfb;
+ IDirectFBDisplayLayer *primary;
IDirectFBDisplayLayer *layer;
IDirectFBSurface *surface;
DFBDisplayLayerCapabilities caps;
@@ -106,6 +112,8 @@ typedef struct directfb_driver_s {
Drawable drawable;
GC gc;
int depth;
+ x11osd *xoverlay;
+ int ovl_changed;
#endif
/* screen size */
@@ -135,7 +143,8 @@ typedef struct {
/*** driver functions ***/
static uint32_t directfb_get_capabilities (vo_driver_t *this_gen) {
- return VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP;
+ directfb_driver_t *this = (directfb_driver_t *) this_gen;
+ return this->capabilities;
}
static void directfb_frame_field (vo_frame_t *vo_img, int which_field) {
@@ -245,34 +254,35 @@ static void directfb_update_frame_format (vo_driver_t *this_gen,
frame->ratio = ratio;
}
+#ifdef HAVE_X11
+static uint32_t directfb_colorkey_to_pixel (directfb_driver_t *this) {
+ switch (this->depth) {
+ case 8:
+ return ((this->colorkey & 0xe00000) >> 16) |
+ ((this->colorkey & 0x00e000) >> 11) |
+ ((this->colorkey & 0x0000c0) >> 6);
+ case 15:
+ return ((this->colorkey & 0xf80000) >> 9) |
+ ((this->colorkey & 0x00f800) >> 6) |
+ ((this->colorkey & 0x0000f8) >> 3);
+ case 16:
+ return ((this->colorkey & 0xf80000) >> 8) |
+ ((this->colorkey & 0x00fc00) >> 5) |
+ ((this->colorkey & 0x0000f8) >> 3);
+ default:
+ break;
+ }
+
+ return this->colorkey;
+}
+#endif
+
static void directfb_clean_output_area (directfb_driver_t *this) {
if (this->visual_type == XINE_VISUAL_TYPE_X11) {
#ifdef HAVE_X11
if (this->config.options & DLOP_DST_COLORKEY) {
- uint32_t pixel;
- int i;
-
- switch (this->depth) {
- case 8:
- pixel = ((this->colorkey & 0xe00000) >> 16) |
- ((this->colorkey & 0x00e000) >> 11) |
- ((this->colorkey & 0x0000c0) >> 6);
- break;
- case 15:
- pixel = ((this->colorkey & 0xf80000) >> 9) |
- ((this->colorkey & 0x00f800) >> 6) |
- ((this->colorkey & 0x0000f8) >> 3);
- break;
- case 16:
- pixel = ((this->colorkey & 0xf80000) >> 8) |
- ((this->colorkey & 0x00fc00) >> 5) |
- ((this->colorkey & 0x0000f8) >> 3);
- break;
- default:
- pixel = this->colorkey;
- break;
- }
-
+ int i;
+
XLockDisplay (this->display);
XSetForeground (this->display, this->gc, BlackPixel(this->display, this->screen));
@@ -285,10 +295,16 @@ static void directfb_clean_output_area (directfb_driver_t *this) {
}
}
- XSetForeground (this->display, this->gc, pixel);
+ XSetForeground (this->display, this->gc, directfb_colorkey_to_pixel(this));
XFillRectangle (this->display, this->drawable, this->gc,
this->sc.output_xoffset, this->sc.output_yoffset,
this->sc.output_width, this->sc.output_height);
+
+
+ if (this->xoverlay) {
+ x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height);
+ this->ovl_changed = 1;
+ }
XFlush (this->display);
@@ -312,32 +328,75 @@ static void directfb_clean_output_area (directfb_driver_t *this) {
}
}
+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);
+ }
+#endif
+
+ 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_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;
directfb_frame_t *frame = (directfb_frame_t *) frame_gen;
- this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
- this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
-
- if (frame->format == DSPF_YUY2) {
- _x_blend_yuy2 (frame->vo_frame.base[0], overlay,
- frame->width, frame->height,
- frame->vo_frame.pitches[0],
- &this->alphablend_extra_data);
+ if (!overlay->rle)
+ return;
+
+ if (overlay->unscaled) {
+#ifdef HAVE_X11
+ if (this->ovl_changed && this->xoverlay) {
+ XLockDisplay (this->display);
+ x11osd_blend (this->xoverlay, overlay);
+ XUnlockDisplay (this->display);
+ }
+#endif
}
else {
- _x_blend_yuv (frame->vo_frame.base, overlay,
- frame->width, frame->height,
- frame->vo_frame.pitches,
- &this->alphablend_extra_data);
+ if (frame->format == DSPF_YUY2) {
+ _x_blend_yuy2 (frame->vo_frame.base[0], overlay,
+ frame->width, frame->height,
+ frame->vo_frame.pitches[0],
+ &this->alphablend_extra_data);
+ }
+ else {
+ _x_blend_yuv (frame->vo_frame.base, overlay,
+ frame->width, frame->height,
+ frame->vo_frame.pitches,
+ &this->alphablend_extra_data);
+ }
}
}
+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;
+#endif
+}
+
static int directfb_redraw_needed (vo_driver_t *this_gen) {
directfb_driver_t *this = (directfb_driver_t *) this_gen;
directfb_frame_t *frame = this->cur_frame;
-
+
if (!frame)
return 1;
@@ -352,6 +411,7 @@ static int directfb_redraw_needed (vo_driver_t *this_gen) {
_x_vo_scale_compute_ideal_size (&this->sc);
if (_x_vo_scale_redraw_needed (&this->sc)) {
+ lprintf ("redraw needed.\n");
_x_vo_scale_compute_output_size (&this->sc);
if (this->caps & DLCAPS_SCREEN_LOCATION) {
@@ -422,7 +482,7 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen
ret = this->layer->SetConfiguration (this->layer, &this->config);
if (ret != DFB_OK)
- DirectFBError( "IDirectFBDisplayLayer::SetConfiguration()", ret );
+ DirectFBError ("IDirectFBDisplayLayer::SetConfiguration()", ret);
this->layer->GetConfiguration (this->layer, &this->config);
}
@@ -430,7 +490,7 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen
this->sc.delivered_height != frame->height ||
this->sc.delivered_ratio != frame->ratio)
{
- lprintf ("forcing redraw\n");
+ lprintf ("forcing redraw.\n");
this->sc.force_redraw = 1;
}
@@ -532,7 +592,7 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge
this->sc.delivered_height != frame->height ||
this->sc.delivered_ratio != frame->ratio)
{
- lprintf ("forcing redraw\n");
+ lprintf ("forcing redraw.\n");
this->sc.force_redraw = 1;
}
@@ -835,16 +895,37 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen,
switch (data_type) {
case XINE_GUI_SEND_DRAWABLE_CHANGED:
+ lprintf ("drawable changed.\n");
#ifdef HAVE_X11
if (this->visual_type == XINE_VISUAL_TYPE_X11) {
this->drawable = (Drawable) data;
XLockDisplay (this->display);
XFreeGC (this->display, this->gc);
this->gc = XCreateGC (this->display, this->drawable, 0, NULL);
+ if (this->xoverlay) {
+ x11osd_drawable_changed (this->xoverlay, this->drawable);
+ this->ovl_changed = 1;
+ }
XUnlockDisplay (this->display);
+ this->sc.force_redraw = 1;
+ }
+#endif
+ directfb_clean_output_area (this);
+ break;
+
+ case XINE_GUI_SEND_EXPOSE_EVENT:
+ lprintf ("expose event.\n");
+#ifdef HAVE_X11
+ if (this->visual_type == XINE_VISUAL_TYPE_X11) {
+ if (this->xoverlay) {
+ XLockDisplay (this->display);
+ x11osd_expose (this->xoverlay);
+ XUnlockDisplay (this->display);
+ }
}
#endif
- return 0;
+ directfb_clean_output_area (this);
+ break;
case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: {
int x1, y1, x2, y2;
@@ -860,13 +941,13 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen,
rect->y = y1;
rect->w = x2-x1;
rect->h = y2-y1;
- } return 0;
+ } break;
default:
- break;
+ return -1;
}
- return -1;
+ return 0;
}
static void directfb_dispose (vo_driver_t *this_gen) {
@@ -878,6 +959,8 @@ static void directfb_dispose (vo_driver_t *this_gen) {
#ifdef HAVE_X11
if (this->visual_type == XINE_VISUAL_TYPE_X11) {
XLockDisplay (this->display);
+ if (this->xoverlay)
+ x11osd_destroy (this->xoverlay);
XFreeGC (this->display, this->gc);
XUnlockDisplay (this->display);
}
@@ -925,7 +1008,7 @@ static DFBResult probe_device (directfb_driver_t *this, DFBDisplayLayerID id) {
ret = this->dfb->GetDisplayLayer (this->dfb, id, &layer);
if (ret != DFB_OK) {
- DirectFBError( "IDirectFB::GetDisplayLayer()", ret );
+ DirectFBError ("IDirectFB::GetDisplayLayer()", ret);
return ret;
}
@@ -1023,6 +1106,12 @@ static void update_config_cb (void *data, xine_cfg_entry_t *entry) {
this->layer->SetDstColorKey (this->layer, (this->colorkey & 0xff0000) >> 16,
(this->colorkey & 0x00ff00) >> 8,
(this->colorkey & 0x0000ff) >> 0);
+#ifdef HAVE_X11
+ if (this->xoverlay) {
+ x11osd_colorkey (this->xoverlay,
+ directfb_colorkey_to_pixel(this), &this->sc);
+ }
+#endif
directfb_clean_output_area (this);
}
else if (strcmp (entry->key, "video.device.directfb_flicker_filtering") == 0) {
@@ -1121,6 +1210,15 @@ static void init_config (directfb_driver_t *this) {
"the field parity (\"none\"=disabled)."),
10, update_config_cb, (void *)this);
}
+}
+
+static DFBEnumerationResult find_underlay (DFBDisplayLayerID id,
+ DFBDisplayLayerDescription dsc, void *ctx) {
+ DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx;
+
+ *ret_id = id;
+
+ return DFENUM_CANCEL;
}
static DFBResult init_device (directfb_driver_t *this) {
@@ -1209,8 +1307,38 @@ static DFBResult init_device (directfb_driver_t *this) {
this->surface = surface;
- /* check if stretchblit is hardware accelerated */
- if (!(this->caps & DLCAPS_SCREEN_LOCATION)) {
+ if (this->caps & DLCAPS_SCREEN_LOCATION) {
+ IDirectFBScreen *screen = NULL;
+ DFBDisplayLayerID layer_id = -1;
+ int width = 640;
+ int height = 480;
+
+ this->layer->GetScreen (this->layer, &screen);
+ if (screen) {
+ screen->EnumDisplayLayers (screen, find_underlay, (void*)&layer_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->screen_width = width;
+ this->screen_height = height;
+ }
+ else {
+ /* playing to underlay,
+ * check if stretchblit is hardware accelerated. */
IDirectFBSurface *temp;
DFBSurfaceDescription dsc;
DFBAccelerationMask mask = DFXL_NONE;
@@ -1250,52 +1378,17 @@ static DFBResult init_device (directfb_driver_t *this) {
else
temp->Release (temp);
}
- }
-
- return DFB_OK;
-}
-static DFBEnumerationResult find_underlay (DFBDisplayLayerID id,
- DFBDisplayLayerDescription dsc, void *ctx) {
- DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx;
-
- *ret_id = id;
-
- return DFENUM_CANCEL;
-}
-
-static void get_screen_size (directfb_driver_t *this, int *ret_w, int *ret_h) {
- IDirectFBScreen *screen = NULL;
- DFBDisplayLayerID layer_id = -1;
- int width = 640;
- int height = 480;
-
- this->layer->GetScreen (this->layer, &screen);
- if (screen) {
- screen->EnumDisplayLayers (screen, find_underlay, (void*)&layer_id);
- screen->Release (screen);
- }
-
- if (layer_id != -1) {
- IDirectFBDisplayLayer *layer = NULL;
- 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->screen_width = this->config.width;
+ this->screen_height = this->config.height;
}
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"video_out_directfb: screen size is %dx%d.\n",
- width, height);
-
- *ret_w = width; *ret_h = height;
-}
+ this->screen_width, this->screen_height);
+
+ return DFB_OK;
+}
static void directfb_frame_output_cb (void *user_data, int video_width, int video_height,
double video_pixel_aspect, int *dest_x, int *dest_y,
@@ -1391,6 +1484,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
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 */
this->buffermode = 1; // double
this->vsync = 0;
@@ -1409,12 +1503,6 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
free (this);
return NULL;
}
-
- if (!(this->caps & DLCAPS_SCREEN_LOCATION)) {
- this->screen_width = this->config.width;
- this->screen_height = this->config.height;
- } else
- get_screen_size (this, &this->screen_width, &this->screen_height );
_x_alphablend_init (&this->alphablend_extra_data, this->xine);
@@ -1434,9 +1522,9 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void
this->vo_driver.get_capabilities = directfb_get_capabilities;
this->vo_driver.alloc_frame = directfb_alloc_frame;
this->vo_driver.update_frame_format = directfb_update_frame_format;
- this->vo_driver.overlay_begin = NULL; /* not used */
+ this->vo_driver.overlay_begin = directfb_overlay_begin;
this->vo_driver.overlay_blend = directfb_overlay_blend;
- this->vo_driver.overlay_end = NULL; /* not used */
+ this->vo_driver.overlay_end = directfb_overlay_end;
this->vo_driver.display_frame = (this->caps & DLCAPS_SCREEN_LOCATION)
? directfb_display_frame
: directfb_display_frame2;
@@ -1559,6 +1647,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void
return NULL;
}
+ this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP;
/* set default configuration */
this->buffermode = 1; // double
this->vsync = 0;
@@ -1578,6 +1667,8 @@ 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;
@@ -1594,13 +1685,28 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void
this->sc.gui_height = attrs.height;
this->sc.frame_output_cb = visual->frame_output_cb;
this->sc.user_data = visual->user_data;
+
+ if (this->colorkeying) {
+ this->xoverlay = x11osd_create (this->xine, this->display, this->screen,
+ this->drawable, X11OSD_COLORKEY);
+ if (this->xoverlay) {
+ x11osd_colorkey (this->xoverlay,
+ directfb_colorkey_to_pixel(this), &this->sc);
+ }
+ } else {
+ this->xoverlay = x11osd_create (this->xine, this->display, this->screen,
+ this->drawable, X11OSD_SHAPED);
+ }
+
+ if (this->xoverlay)
+ this->capabilities |= VO_CAP_UNSCALED_OVERLAY;
this->vo_driver.get_capabilities = directfb_get_capabilities;
this->vo_driver.alloc_frame = directfb_alloc_frame;
this->vo_driver.update_frame_format = directfb_update_frame_format;
- this->vo_driver.overlay_begin = NULL; /* not used */
+ this->vo_driver.overlay_begin = directfb_overlay_begin;
this->vo_driver.overlay_blend = directfb_overlay_blend;
- this->vo_driver.overlay_end = NULL; /* not used */
+ this->vo_driver.overlay_end = directfb_overlay_end;
this->vo_driver.display_frame = directfb_display_frame;
this->vo_driver.get_property = directfb_get_property;
this->vo_driver.set_property = directfb_set_property;