Sophie

Sophie

distrib > Mageia > 1 > i586 > media > tainted-release-src > by-pkgid > f473b7b4d03aac3dab3be9a386f5c81c > files > 3

mplayer-1.0-1.rc4.0.r32713.5.mga1.tainted.src.rpm

--- libvo/vo_xv.c.orig	2007-10-13 12:22:34.000000000 +0100
+++ libvo/vo_xv.c	2007-10-13 12:22:41.000000000 +0100
@@ -93,6 +93,520 @@
 static uint32_t drwX, drwY, drwBorderWidth, drwDepth;
 static uint32_t max_width = 0, max_height = 0; // zero means: not set
 
+#include "libswscale/swscale.h"
+#include <X11/Xatom.h>
+
+#define GRAVITY_WEST  (1 << 0)
+#define GRAVITY_EAST  (1 << 1)
+#define GRAVITY_NORTH (1 << 2)
+#define GRAVITY_SOUTH (1 << 3)
+
+#define COMPIZ_IMAGE_FORMAT_RGB  (1 << 0)
+#define COMPIZ_IMAGE_FORMAT_YV12 (1 << 1)
+
+static Atom vo_supporting_wm_check_atom;
+static Atom vo_compiz_video_atom;
+static Atom vo_compiz_video_supported_atom;
+static Atom vo_compiz_video_image_format_rgb_atom;
+static Atom vo_compiz_video_image_format_yv12_atom;
+static int vo_compiz_formats = 0;
+static int vo_compiz_format = 0;
+static Pixmap vo_pixmap = None;
+static GC vo_pixmap_gc = None;
+static Atom vo_xprop = None;
+static XImage *ximage = NULL;
+static XShmSegmentInfo compizShminfo;
+static int pixmap_width;
+static int pixmap_height;
+static int pixmap_height;
+static int pixmap_depth;
+static int pixmap_offsets[3];
+static int pixmap_pitches[3];
+static struct SwsContext *swsContext = NULL;
+static Window wm_check_window = None;
+
+static int x11_get_property (Atom type, Atom **args, unsigned long *nitems)
+{
+    int format;
+    unsigned long bytesafter;
+
+    return (Success ==
+	    XGetWindowProperty(mDisplay, mRootWin, type, 0, 16384, False,
+			       AnyPropertyType, &type, &format, nitems,
+			       &bytesafter, (unsigned char **) args)
+	    && *nitems > 0);
+}
+
+static int error_handler (Display *dpy, XErrorEvent *e)
+{
+    return 0;
+}
+
+static Bool x11_update_wm_check_window (void)
+{
+    Atom	  actual;
+    int		  result, format;
+    unsigned long n, left;
+    unsigned char *data;
+
+    result = XGetWindowProperty (mDisplay, mRootWin,
+				 vo_supporting_wm_check_atom,
+				 0L, 1L, False, XA_WINDOW, &actual, &format,
+				 &n, &left, &data);
+
+    if (result == Success && n && data)
+    {
+	XErrorHandler old;
+	Window	      win, root;
+	unsigned int  ui;
+	int	     i;
+
+	memcpy (&win, data, sizeof (Window));
+	XFree ((void *) data);
+
+	old = XSetErrorHandler (error_handler);
+
+	XSelectInput (mDisplay, win, StructureNotifyMask);
+
+	if (!XGetGeometry (mDisplay, win, &root, &i, &i, &ui, &ui, &ui, &ui))
+	    win = None;
+
+	XSetErrorHandler (old);
+
+	wm_check_window = win;
+	if (wm_check_window)
+	    return True;
+    }
+
+    return False;
+}
+
+static void vo_compiz_detect (void)
+{
+    unsigned long nitems;
+    Atom *args = NULL;
+    int formats = 0;
+    int i;
+
+    if (!x11_update_wm_check_window ())
+    {
+	vo_compiz_formats = 0;
+	return;
+    }
+
+    if (x11_get_property (vo_compiz_video_supported_atom, &args, &nitems))
+    {
+	mp_msg (MSGT_VO, MSGL_V, "[xv] Detected wm supports compiz video.\n");
+
+	for (i = 0; i < nitems; i++)
+	{
+	    if (args[i] == vo_compiz_video_image_format_rgb_atom)
+		formats |= COMPIZ_IMAGE_FORMAT_RGB;
+	    else if (args[i] == vo_compiz_video_image_format_yv12_atom)
+		formats |= COMPIZ_IMAGE_FORMAT_YV12;
+	}
+
+	XFree (args);
+    }
+
+    vo_compiz_formats = formats;
+}
+
+static void vo_compiz_init (void)
+{
+    vo_supporting_wm_check_atom =
+	XInternAtom (mDisplay, "_NET_SUPPORTING_WM_CHECK", False);
+
+    vo_compiz_video_atom = XInternAtom (mDisplay,
+					"_COMPIZ_VIDEO",
+					False);
+
+    vo_compiz_video_supported_atom = XInternAtom (mDisplay,
+						  "_COMPIZ_VIDEO_SUPPORTED",
+						  False);
+
+    vo_compiz_video_image_format_rgb_atom =
+	XInternAtom (mDisplay,
+		     "_COMPIZ_VIDEO_IMAGE_FORMAT_RGB",
+		     False);
+
+    vo_compiz_video_image_format_yv12_atom =
+	XInternAtom (mDisplay,
+		     "_COMPIZ_VIDEO_IMAGE_FORMAT_YV12",
+		     False);
+
+    XSelectInput (mDisplay, mRootWin, PropertyChangeMask);
+
+    vo_compiz_detect ();
+}
+
+static void allocate_ximage (void)
+{
+#ifdef HAVE_SHM
+    if (Shmem_Flag)
+    {
+	ximage =
+	    XShmCreateImage (mDisplay, NULL, pixmap_depth, ZPixmap, NULL,
+			     &compizShminfo, pixmap_width, pixmap_height);
+	compizShminfo.shmid = shmget (IPC_PRIVATE,
+				      ximage->bytes_per_line *
+				      ximage->height, IPC_CREAT | 0777);
+	compizShminfo.shmaddr = (char *) shmat (compizShminfo.shmid, 0, 0);
+	compizShminfo.readOnly = False;
+
+	ximage->data = compizShminfo.shmaddr;
+	XShmAttach (mDisplay, &compizShminfo);
+	XSync (mDisplay, False);
+	shmctl (compizShminfo.shmid, IPC_RMID, 0);
+    } else
+#endif
+    {
+	ximage =
+	    XShmCreateImage (mDisplay, NULL, pixmap_depth, ZPixmap, NULL,
+			     &compizShminfo, pixmap_width, pixmap_height);
+	ximage->data = malloc (ximage->bytes_per_line *
+			       ximage->height);
+	XSync (mDisplay, False);
+    }
+
+    memset (ximage->data, 128, ximage->bytes_per_line * ximage->height);
+}
+
+static void deallocate_ximage (void)
+{
+#ifdef HAVE_SHM
+    if (Shmem_Flag)
+    {
+	XShmDetach (mDisplay, &compizShminfo);
+	shmdt (compizShminfo.shmaddr);
+    } else
+#endif
+    {
+	free (ximage->data);
+    }
+
+    XFree (ximage);
+    XSync (mDisplay, False);
+}
+
+static void vo_compiz_put_ximage (XImage *myximage)
+{
+
+#ifdef HAVE_SHM
+    if (Shmem_Flag)
+    {
+	XShmPutImage (mDisplay, vo_pixmap, vo_pixmap_gc, myximage,
+		      0, 0,
+		      0, 0,
+		      myximage->width, myximage->height,
+		      True);
+    } else
+#endif
+    {
+	XPutImage (mDisplay, vo_pixmap, vo_pixmap_gc, myximage,
+		   0, 0,
+		   0, 0,
+		   myximage->width, myximage->height);
+    }
+
+    if (!vo_xprop)
+    {
+	long data[11];
+	int  w, h;
+
+	data[0] = vo_pixmap;
+
+	if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
+	    data[1] = vo_compiz_video_image_format_yv12_atom;
+	else
+	    data[1] = vo_compiz_video_image_format_rgb_atom;
+
+	data[2] = image_width;
+	data[3] = image_height;
+
+	aspect (&w, &h, A_NOZOOM);
+
+	data[4] = w;
+	data[5] = h;
+	data[6] = vo_panscan * 65536;
+
+	data[7]  = GRAVITY_NORTH | GRAVITY_WEST;
+	data[8]  = 0;
+	data[9]  = 0;
+	data[10] = GRAVITY_SOUTH | GRAVITY_EAST;
+	data[11] = 0;
+	data[12] = 0;
+
+	XChangeProperty (mDisplay,
+			 vo_window,
+			 vo_compiz_video_atom,
+			 XA_INTEGER,
+			 32, PropModeReplace, (unsigned char *) data,
+			 13);
+
+	vo_xprop = 1;
+    }
+
+    XSync (mDisplay, False);
+}
+
+static void vo_compiz_check_output (void)
+{
+    int format = 0;
+
+    if (vo_compiz_formats)
+    {
+	if (xv_format == IMGFMT_YV12)
+	    format = vo_compiz_formats & COMPIZ_IMAGE_FORMAT_YV12;
+
+	if (!format)
+	    format = vo_compiz_formats & COMPIZ_IMAGE_FORMAT_RGB;
+    }
+
+    if (format != vo_compiz_format)
+    {
+	if (ximage)
+	{
+	    deallocate_ximage ();
+	    ximage = NULL;
+	}
+
+	if (vo_pixmap)
+	{
+	    XFreePixmap (mDisplay, vo_pixmap);
+	    vo_pixmap = None;
+	}
+
+	if (swsContext)
+	{
+	    sws_freeContext (swsContext);
+	    swsContext = NULL;
+	}
+
+	vo_compiz_format = format;
+    }
+
+    if (format)
+    {
+	int width, height;
+
+	if (format == COMPIZ_IMAGE_FORMAT_YV12)
+	{
+	    width  = (image_width  + 7) & ~7;
+	    height = (image_height + 1) & ~1;
+
+	    pixmap_width  = width;
+	    pixmap_height = height + height / 2;
+	    pixmap_depth  = 8;
+
+	    pixmap_offsets[0] = 0;
+	    pixmap_offsets[1] = width * height;
+	    pixmap_offsets[2] = width * height + (width / 2);
+
+	    pixmap_pitches[0] = width;
+	    pixmap_pitches[1] = width;
+	    pixmap_pitches[2] = width;
+
+	    mp_msg (MSGT_VO, MSGL_V,
+		    "[xv] using compiz composited yv12 output\n");
+	}
+	else
+	{
+	    width  = image_width;
+	    height = image_height;
+
+	    pixmap_width  = width;
+	    pixmap_height = height;
+	    pixmap_depth  = 24;
+
+	    swsContext = (struct SwsContext *)
+		sws_getContextFromCmdLine (width, height, image_format,
+					   width, height, IMGFMT_BGR32);
+
+	    mp_msg (MSGT_VO, MSGL_V,
+		    "[xv] using compiz composited rgb output\n");
+	}
+
+	vo_pixmap = XCreatePixmap (mDisplay, mRootWin,
+				   pixmap_width, pixmap_height,
+				   pixmap_depth);
+
+	if (vo_pixmap_gc != None)
+	    XFreeGC (mDisplay, vo_pixmap_gc);
+
+	allocate_ximage ();
+
+	vo_pixmap_gc = XCreateGC (mDisplay, vo_pixmap, 0L, NULL);
+	vo_xprop     = None;
+
+	XSetWindowBackground (mDisplay, vo_window, 0);
+	XClearWindow (mDisplay, vo_window);
+    }
+    else
+    {
+	XDeleteProperty (mDisplay, vo_window, vo_compiz_video_atom);
+
+	mp_msg (MSGT_VO, MSGL_V,
+		"[xv] compiz composited output not available\n");
+    }
+}
+
+static Bool check_compiz_event (Display *display, XEvent *event, XPointer arg)
+{
+    if (event->type == DestroyNotify)
+    {
+	if (event->xdestroywindow.window == wm_check_window)
+	    return True;
+    }
+    else if (event->type == PropertyNotify)
+    {
+	if (event->xproperty.atom == vo_compiz_video_supported_atom)
+	    return True;
+    }
+
+    return False;
+}
+
+static void vo_compiz_check_events (void)
+{
+    XEvent event;
+
+    if (XCheckIfEvent (mDisplay, &event, check_compiz_event, NULL))
+    {
+	vo_compiz_detect ();
+	vo_compiz_check_output ();
+    }
+}
+
+static int vo_compiz_draw_slice (uint8_t * image[], int stride[],
+				 int w, int h, int x, int y)
+{
+    if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
+    {
+	uint8_t *dst;
+
+	dst = ximage->data + pixmap_offsets[0] + pixmap_pitches[0] * y + x;
+	memcpy_pic (dst, image[0], w, h, pixmap_pitches[0], stride[0]);
+
+	x /= 2;
+	y /= 2;
+	w /= 2;
+	h /= 2;
+
+	dst = ximage->data + pixmap_offsets[1] + pixmap_pitches[1] * y + x;
+	memcpy_pic (dst, image[2], w, h, pixmap_pitches[1], stride[2]);
+
+	dst = ximage->data + pixmap_offsets[2] + pixmap_pitches[2] * y + x;
+	memcpy_pic (dst, image[1], w, h, pixmap_pitches[2], stride[1]);
+    }
+    else
+    {
+	uint8_t *dst[3];
+	int	dstStride[3];
+
+	dstStride[1] = dstStride[2] = 0;
+	dst[1] = dst[2] = NULL;
+
+	dst[0] = ximage->data;
+	dstStride[0] = ximage->bytes_per_line;
+
+	sws_scale (swsContext, image, stride, y, h, dst, dstStride);
+    }
+
+    return 0;
+}
+
+static uint32_t vo_compiz_draw_image (mp_image_t *mpi)
+{
+    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+	return VO_TRUE;
+
+    if (mpi->flags & MP_IMGFLAG_PLANAR)
+    {
+	vo_compiz_draw_slice (mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
+	return VO_TRUE;
+    }
+
+    return VO_FALSE;
+}
+
+static uint32_t vo_compiz_get_image (mp_image_t *mpi)
+{
+    if (mpi->imgfmt != image_format)
+	return VO_FALSE;
+
+    if (mpi->height != image_height)
+	return VO_FALSE;
+
+    if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
+    {
+	if (mpi->width * (mpi->bpp / 8) != pixmap_pitches[0])
+	    return VO_FALSE;
+
+	if (!(mpi->flags & MP_IMGFLAG_PLANAR))
+	    return VO_FALSE;
+
+	if (mpi->flags & MP_IMGFLAG_SWAPPED)
+	    return VO_FALSE;
+
+	if (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))
+	{
+	    mpi->planes[0] = ximage->data + pixmap_offsets[0];
+	    mpi->stride[0] = pixmap_pitches[0];
+	    mpi->planes[1] = ximage->data + pixmap_offsets[2];
+	    mpi->stride[1] = pixmap_pitches[2];
+	    mpi->planes[2] = ximage->data + pixmap_offsets[1];
+	    mpi->stride[2] = pixmap_pitches[1];
+
+	    mpi->width = mpi->stride[0] / (mpi->bpp / 8);
+	}
+	else
+	{
+	    return VO_FALSE;
+	}
+    }
+    else
+    {
+	if (mpi->type != MP_IMGTYPE_STATIC)
+	    return VO_FALSE;
+
+	if (mpi->flags & (MP_IMGFLAG_PLANAR | MP_IMGFLAG_YUV))
+	    return VO_FALSE;
+
+	if (mpi->width != image_width)
+	    return VO_FALSE;
+
+	mpi->stride[0] = image_width * 4;
+	mpi->planes[0] = ximage->data;
+    }
+
+    mpi->flags |= MP_IMGFLAG_DIRECT;
+
+    return VO_TRUE;
+}
+
+static void vo_compiz_draw_alpha (int x0, int y0, int w, int h,
+				  unsigned char *src, unsigned char *srca,
+				  int stride)
+{
+    x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
+
+    if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
+    {
+	vo_draw_alpha_yv12 (w, h, src, srca, stride,
+			    ximage->data +
+			    pixmap_offsets[0] +
+			    pixmap_pitches[0] * y0 + x0,
+			    pixmap_pitches[0]);
+    }
+    else
+    {
+	vo_draw_alpha_rgb32 (w, h, src, srca, stride,
+			     ximage->data + 4 * (y0 * image_width + x0),
+			     4 * image_width);
+    }
+}
+
 static void (*draw_alpha_fnc) (int x0, int y0, int w, int h,
                                unsigned char *src, unsigned char *srca,
                                int stride);
@@ -392,6 +906,8 @@
     }
 #endif
 
+    vo_compiz_check_output ();
+
     mp_msg(MSGT_VO, MSGL_V, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX,
            drwY, vo_dwidth, vo_dheight);
 
@@ -487,7 +1003,11 @@
 
 static void check_events(void)
 {
-    int e = vo_x11_check_events(mDisplay);
+    int e;
+
+    vo_compiz_check_events ();
+
+    e = vo_x11_check_events(mDisplay);
 
     if (e & VO_EVENT_RESIZE)
     {
@@ -513,6 +1033,7 @@
         if ( visible_buf != -1 )
         {
           /* redraw the last visible buffer */
+	    if (!vo_pixmap)
           put_xvimage( xvimage[visible_buf] );
         }
     }
@@ -520,13 +1041,24 @@
 
 static void draw_osd(void)
 {
-    vo_draw_text(image_width -
-                 image_width * vo_panscan_x / (vo_dwidth + vo_panscan_x),
-                 image_height, draw_alpha_fnc);
+    if (vo_pixmap)
+	vo_draw_text (image_width -
+		      image_width * vo_panscan_x / (vo_dwidth + vo_panscan_x),
+		      image_height, vo_compiz_draw_alpha);
+    else
+	vo_draw_text (image_width -
+		      image_width * vo_panscan_x / (vo_dwidth + vo_panscan_x),
+		      image_height, draw_alpha_fnc);
 }
 
 static void flip_page(void)
 {
+    if (vo_pixmap)
+    {
+	vo_compiz_put_ximage (ximage);
+	return;
+    }
+
     put_xvimage( xvimage[current_buf] );
 
     /* remember the currently visible buffer */
@@ -547,6 +1079,9 @@
 {
     uint8_t *dst;
 
+    if (vo_pixmap)
+	return vo_compiz_draw_slice (image, stride, w, h, x, y);
+
     dst = xvimage[current_buf]->data + xvimage[current_buf]->offsets[0] +
         xvimage[current_buf]->pitches[0] * y + x;
     memcpy_pic(dst, image[0], w, h, xvimage[current_buf]->pitches[0],
@@ -586,6 +1121,9 @@
 
 static uint32_t draw_image(mp_image_t * mpi)
 {
+    if (vo_pixmap)
+	return vo_compiz_draw_image (mpi);
+
     if (mpi->flags & MP_IMGFLAG_DIRECT)
     {
         // direct rendering:
@@ -615,6 +1153,9 @@
 {
     int buf = current_buf;      // we shouldn't change current_buf unless we do DR!
 
+    if (vo_pixmap)
+	return vo_compiz_get_image (mpi);
+
     if (mpi->type == MP_IMGTYPE_STATIC && num_buffers > 1)
         return VO_FALSE;        // it is not static
     if (mpi->imgfmt != image_format)
@@ -834,6 +1375,7 @@
     vo_xv_get_max_img_dim( &max_width, &max_height );
 
     fo = XvListImageFormats(mDisplay, xv_port, (int *) &formats);
+    vo_compiz_init();
 
     mp_input_add_event_fd(ConnectionNumber(mDisplay), check_events);
     return 0;
@@ -863,7 +1405,12 @@
             vo_x11_fullscreen();
             /* indended, fallthrough to update panscan on fullscreen/windowed switch */
         case VOCTRL_SET_PANSCAN:
-            if ((vo_fs && (vo_panscan != vo_panscan_amount))
+	    if (vo_pixmap)
+	    {
+		panscan_calc ();
+		vo_xprop = None;
+	    }
+	    else if ((vo_fs && (vo_panscan != vo_panscan_amount))
                 || (!vo_fs && vo_panscan_amount))
             {
                 int old_y = vo_panscan_y;