summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/xine-engine/osd.c173
-rw-r--r--src/xine-engine/xine_interface.c10
2 files changed, 135 insertions, 48 deletions
diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c
index a789b50d4..1d3754d42 100644
--- a/src/xine-engine/osd.c
+++ b/src/xine-engine/osd.c
@@ -236,15 +236,20 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width
osd->renderer = this;
osd->next = this->osds;
this->osds = osd;
-
+
+ osd->extent_width = 0;
+ osd->extent_height = 0;
osd->width = width;
osd->height = height;
osd->area = calloc(width, height);
+ osd->area_touched = 0;
- osd->x1 = width;
- osd->y1 = height;
- osd->x2 = 0;
- osd->y2 = 0;
+ osd->x1 = osd->argb_layer.x1 = width;
+ osd->y1 = osd->argb_layer.y1 = height;
+ osd->x2 = osd->argb_layer.x2 = 0;
+ osd->y2 = osd->argb_layer.y2 = 0;
+
+ pthread_mutex_init(&osd->argb_layer.mutex, NULL);
memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0]));
memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0]));
@@ -263,6 +268,18 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width
return osd;
}
+/*
+ * osd extent must be set to achive video resolution independent osds
+ * both sizes must be > 0 to take effect. otherwise, video resolution
+ * will still be used. the extent defines the reference coordinate
+ * system which is matched to the video output area.
+ */
+static void osd_set_extent (osd_object_t *osd, int extent_width, int extent_height) {
+
+ osd->extent_width = extent_width;
+ osd->extent_height = extent_height;
+}
+
/*
@@ -322,11 +339,17 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
this->event.object.handle = osd->handle;
memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) );
+
+ this->event.object.overlay->argb_layer = &osd->argb_layer;
+
this->event.object.overlay->unscaled = unscaled;
this->event.object.overlay->x = osd->display_x + osd->x1;
this->event.object.overlay->y = osd->display_y + osd->y1;
this->event.object.overlay->width = osd->x2 - osd->x1;
this->event.object.overlay->height = osd->y2 - osd->y1;
+
+ this->event.object.overlay->extent_width = osd->extent_width;
+ this->event.object.overlay->extent_height = osd->extent_height;
this->event.object.overlay->hili_top = 0;
this->event.object.overlay->hili_bottom = this->event.object.overlay->height;
@@ -335,53 +358,59 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
/* there will be at least that many rle objects (one for each row) */
this->event.object.overlay->num_rle = 0;
- /* We will never need more rle objects than columns in any row
- Rely on lazy page allocation to avoid us actually taking up
- this much RAM */
- this->event.object.overlay->data_size = osd->width * osd->height;
- rle_p = this->event.object.overlay->rle =
- malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) );
+ if (!osd->area_touched) {
+ /* avoid rle encoding when only argb_layer is modified */
+ this->event.object.overlay->data_size = 0;
+ rle_p = this->event.object.overlay->rle = NULL;
+ } else {
+ /* We will never need more rle objects than columns in any row
+ Rely on lazy page allocation to avoid us actually taking up
+ this much RAM */
+ this->event.object.overlay->data_size = osd->width * osd->height;
+ rle_p = this->event.object.overlay->rle =
+ malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) );
- for( y = osd->y1; y < osd->y2; y++ ) {
+ for( y = osd->y1; y < osd->y2; y++ ) {
#ifdef DEBUG_RLE
- lprintf("osd_show %p y = %d: ", osd, y);
+ lprintf("osd_show %p y = %d: ", osd, y);
#endif
- c = osd->area + y * osd->width + osd->x1;
+ c = osd->area + y * osd->width + osd->x1;
- /* initialize a rle object with the first pixel's color */
- rle.len = 1;
- rle.color = *c++;
+ /* initialize a rle object with the first pixel's color */
+ rle.len = 1;
+ rle.color = *c++;
- /* loop over the remaining pixels in the row */
- for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) {
- if( rle.color != *c ) {
+ /* loop over the remaining pixels in the row */
+ for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) {
+ if( rle.color != *c ) {
#ifdef DEBUG_RLE
- lprintf("(%d, %d), ", rle.len, rle.color);
+ lprintf("(%d, %d), ", rle.len, rle.color);
#endif
- *rle_p++ = rle;
- this->event.object.overlay->num_rle++;
+ *rle_p++ = rle;
+ this->event.object.overlay->num_rle++;
- rle.color = *c;
- rle.len = 1;
- } else {
- rle.len++;
- }
- }
+ rle.color = *c;
+ rle.len = 1;
+ } else {
+ rle.len++;
+ }
+ }
#ifdef DEBUG_RLE
- lprintf("(%d, %d)\n", rle.len, rle.color);
+ lprintf("(%d, %d)\n", rle.len, rle.color);
#endif
- *rle_p++ = rle;
- this->event.object.overlay->num_rle++;
- }
+ *rle_p++ = rle;
+ this->event.object.overlay->num_rle++;
+ }
#ifdef DEBUG_RLE
- lprintf("osd_show %p rle ends\n", osd);
+ lprintf("osd_show %p rle ends\n", osd);
#endif
- lprintf("num_rle = %d\n", this->event.object.overlay->num_rle);
+ lprintf("num_rle = %d\n", this->event.object.overlay->num_rle);
- memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color));
- memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans));
- memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color));
- memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans));
+ memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color));
+ memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans));
+ memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color));
+ memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans));
+ }
this->event.event_type = OVERLAY_EVENT_SHOW;
this->event.vpts = vpts;
@@ -465,11 +494,14 @@ static int osd_hide (osd_object_t *osd, int64_t vpts) {
static void osd_clear (osd_object_t *osd) {
lprintf("osd=%p\n",osd);
- memset(osd->area, 0, osd->width * osd->height);
- osd->x1 = osd->width;
- osd->y1 = osd->height;
- osd->x2 = 0;
- osd->y2 = 0;
+ if (osd->area_touched) {
+ osd->area_touched = 0;
+ memset(osd->area, 0, osd->width * osd->height);
+ }
+ osd->x1 = osd->argb_layer.x1 = osd->width;
+ osd->y1 = osd->argb_layer.y1 = osd->height;
+ osd->x2 = osd->argb_layer.x2 = 0;
+ osd->y2 = osd->argb_layer.y2 = 0;
}
/*
@@ -491,6 +523,7 @@ static void osd_point (osd_object_t *osd, int x, int y, int color) {
osd->x2 = MAX(osd->x2, (x + 1));
osd->y1 = MIN(osd->y1, y);
osd->y2 = MAX(osd->y2, (y + 1));
+ osd->area_touched = 1;
c = osd->area + y * osd->width + x;
*c = color;
@@ -550,7 +583,8 @@ static void osd_line (osd_object_t *osd,
osd->x2 = MAX( osd->x2, x2 );
osd->y1 = MIN( osd->y1, y1 );
osd->y2 = MAX( osd->y2, y2 );
-
+ osd->area_touched = 1;
+
dx = x2 - x1;
dy = y2 - y1;
@@ -663,6 +697,7 @@ static void osd_filled_rect (osd_object_t *osd,
osd->x2 = MAX( osd->x2, dx );
osd->y1 = MIN( osd->y1, y );
osd->y2 = MAX( osd->y2, dy );
+ osd->area_touched = 1;
dx -= x;
dy -= y;
@@ -1258,6 +1293,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1,
if( x1 < osd->x1 ) osd->x1 = x1;
if( y1 < osd->y1 ) osd->y1 = y1;
+ osd->area_touched = 1;
inbuf = text;
inbytesleft = strlen(text);
@@ -1606,6 +1642,7 @@ static void osd_free_object (osd_object_t *osd_to_close) {
else
this->osds = osd->next;
+ pthread_mutex_destroy(&osd->argb_layer.mutex);
free( osd );
break;
}
@@ -1651,6 +1688,7 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap,
osd->x2 = MAX( osd->x2, x1+width );
osd->y1 = MIN( osd->y1, y1 );
osd->y2 = MAX( osd->y2, y1+height );
+ osd->area_touched = 1;
for( y=0; y<height; y++ ) {
if ( palette_map ) {
@@ -1669,21 +1707,58 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap,
}
}
+static void osd_set_argb_buffer(osd_object_t *osd, uint32_t *argb_buffer,
+ int dirty_x, int dirty_y, int dirty_width, int dirty_height)
+{
+ if (osd->argb_layer.buffer != argb_buffer) {
+ dirty_x = 0;
+ dirty_y = 0;
+ dirty_width = osd->width;
+ dirty_height = osd->height;
+ }
+
+ /* keep osd_object clipping behavior */
+ osd->x1 = MIN( osd->x1, dirty_x );
+ osd->x2 = MAX( osd->x2, dirty_x + dirty_width );
+ osd->y1 = MIN( osd->y1, dirty_y );
+ osd->y2 = MAX( osd->y2, dirty_y + dirty_height );
+
+ pthread_mutex_lock(&osd->argb_layer.mutex);
+
+ /* argb layer update area accumulation */
+ osd->argb_layer.x1 = MIN( osd->argb_layer.x1, dirty_x );
+ osd->argb_layer.x2 = MAX( osd->argb_layer.x2, dirty_x + dirty_width );
+ osd->argb_layer.y1 = MIN( osd->argb_layer.y1, dirty_y );
+ osd->argb_layer.y2 = MAX( osd->argb_layer.y2, dirty_y + dirty_height );
+
+ osd->argb_layer.buffer = argb_buffer;
+
+ pthread_mutex_unlock(&osd->argb_layer.mutex);
+}
+
static uint32_t osd_get_capabilities (osd_object_t *osd) {
osd_renderer_t *this = osd->renderer;
uint32_t capabilities = 0;
+ uint32_t vo_capabilities;
#ifdef HAVE_FT2
capabilities |= XINE_OSD_CAP_FREETYPE2;
#endif
this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1);
- if( this->stream->video_out->get_capabilities(this->stream->video_out) &
- VO_CAP_UNSCALED_OVERLAY)
- capabilities |= XINE_OSD_CAP_UNSCALED;
+ vo_capabilities = this->stream->video_out->get_capabilities(this->stream->video_out);
this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1);
+
+ if (vo_capabilities & VO_CAP_UNSCALED_OVERLAY)
+ capabilities |= XINE_OSD_CAP_UNSCALED;
+
+ if (vo_capabilities & VO_CAP_CUSTOM_EXTENT_OVERLAY)
+ capabilities |= XINE_OSD_CAP_CUSTOM_EXTENT;
+ if (vo_capabilities & VO_CAP_ARGB_LAYER_OVERLAY)
+ capabilities |= XINE_OSD_CAP_ARGB_LAYER;
+
return capabilities;
}
@@ -1753,8 +1828,10 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) {
this->get_text_size = osd_get_text_size;
this->close = osd_renderer_close;
this->draw_bitmap = osd_draw_bitmap;
+ this->set_argb_buffer = osd_set_argb_buffer;
this->show_unscaled = osd_show_unscaled;
this->get_capabilities = osd_get_capabilities;
+ this->set_extent = osd_set_extent;
return this;
}
diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c
index 217272a97..43a40f51c 100644
--- a/src/xine-engine/xine_interface.c
+++ b/src/xine-engine/xine_interface.c
@@ -846,6 +846,16 @@ void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap,
this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map);
}
+void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer,
+ int dirty_x, int dirty_y, int dirty_width, int dirty_height) {
+ this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, dirty_x, dirty_y, dirty_width, dirty_height);
+}
+
+void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height) {
+ this->osd.renderer->set_extent(&this->osd, extent_width, extent_height);
+}
+
+
const char *const *xine_post_list_inputs(xine_post_t *this_gen) {
post_plugin_t *this = (post_plugin_t *)this_gen;
return this->input_ids;