Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 258657 | Differences between
and this patch

Collapse All | Expand All

(-)libvo/vo_xv.c (-5 / +553 lines)
Lines 92-97 Link Here
92
static uint32_t dwidth, dheight;
92
static uint32_t dwidth, dheight;
93
static uint32_t max_width = 0, max_height = 0; // zero means: not set
93
static uint32_t max_width = 0, max_height = 0; // zero means: not set
94
94
95
#include "libswscale/swscale.h"
96
#include <X11/Xatom.h>
97
98
#define GRAVITY_WEST  (1 << 0)
99
#define GRAVITY_EAST  (1 << 1)
100
#define GRAVITY_NORTH (1 << 2)
101
#define GRAVITY_SOUTH (1 << 3)
102
103
#define COMPIZ_IMAGE_FORMAT_RGB  (1 << 0)
104
#define COMPIZ_IMAGE_FORMAT_YV12 (1 << 1)
105
106
static Atom vo_supporting_wm_check_atom;
107
static Atom vo_compiz_video_atom;
108
static Atom vo_compiz_video_supported_atom;
109
static Atom vo_compiz_video_image_format_rgb_atom;
110
static Atom vo_compiz_video_image_format_yv12_atom;
111
static int vo_compiz_formats = 0;
112
static int vo_compiz_format = 0;
113
static Pixmap vo_pixmap = None;
114
static GC vo_pixmap_gc = None;
115
static Atom vo_xprop = None;
116
static XImage *ximage = NULL;
117
static XShmSegmentInfo compizShminfo;
118
static int pixmap_width;
119
static int pixmap_height;
120
static int pixmap_height;
121
static int pixmap_depth;
122
static int pixmap_offsets[3];
123
static int pixmap_pitches[3];
124
static struct SwsContext *swsContext = NULL;
125
static Window wm_check_window = None;
126
127
static int x11_get_property (Atom type, Atom **args, unsigned long *nitems)
128
{
129
    int format;
130
    unsigned long bytesafter;
131
132
    return (Success ==
133
	    XGetWindowProperty(mDisplay, mRootWin, type, 0, 16384, False,
134
			       AnyPropertyType, &type, &format, nitems,
135
			       &bytesafter, (unsigned char **) args)
136
	    && *nitems > 0);
137
}
138
139
static int error_handler (Display *dpy, XErrorEvent *e)
140
{
141
    return 0;
142
}
143
144
static Bool x11_update_wm_check_window (void)
145
{
146
    Atom	  actual;
147
    int		  result, format;
148
    unsigned long n, left;
149
    unsigned char *data;
150
151
    result = XGetWindowProperty (mDisplay, mRootWin,
152
				 vo_supporting_wm_check_atom,
153
				 0L, 1L, False, XA_WINDOW, &actual, &format,
154
				 &n, &left, &data);
155
156
    if (result == Success && n && data)
157
    {
158
	XErrorHandler old;
159
	Window	      win, root;
160
	unsigned int  ui;
161
	int	     i;
162
163
	memcpy (&win, data, sizeof (Window));
164
	XFree ((void *) data);
165
166
	old = XSetErrorHandler (error_handler);
167
168
	XSelectInput (mDisplay, win, StructureNotifyMask);
169
170
	if (!XGetGeometry (mDisplay, win, &root, &i, &i, &ui, &ui, &ui, &ui))
171
	    win = None;
172
173
	XSetErrorHandler (old);
174
175
	wm_check_window = win;
176
	if (wm_check_window)
177
	    return True;
178
    }
179
180
    return False;
181
}
182
183
static void vo_compiz_detect (void)
184
{
185
    unsigned long nitems;
186
    Atom *args = NULL;
187
    int formats = 0;
188
    int i;
189
190
    if (!x11_update_wm_check_window ())
191
    {
192
	vo_compiz_formats = 0;
193
	return;
194
    }
195
196
    if (x11_get_property (vo_compiz_video_supported_atom, &args, &nitems))
197
    {
198
	mp_msg (MSGT_VO, MSGL_V, "[xv] Detected wm supports compiz video.\n");
199
200
	for (i = 0; i < nitems; i++)
201
	{
202
	    if (args[i] == vo_compiz_video_image_format_rgb_atom)
203
		formats |= COMPIZ_IMAGE_FORMAT_RGB;
204
	    else if (args[i] == vo_compiz_video_image_format_yv12_atom)
205
		formats |= COMPIZ_IMAGE_FORMAT_YV12;
206
	}
207
208
	XFree (args);
209
    }
210
211
    vo_compiz_formats = formats;
212
}
213
214
static void vo_compiz_init (void)
215
{
216
    vo_supporting_wm_check_atom =
217
	XInternAtom (mDisplay, "_NET_SUPPORTING_WM_CHECK", False);
218
219
    vo_compiz_video_atom = XInternAtom (mDisplay,
220
					"_COMPIZ_VIDEO",
221
					False);
222
223
    vo_compiz_video_supported_atom = XInternAtom (mDisplay,
224
						  "_COMPIZ_VIDEO_SUPPORTED",
225
						  False);
226
227
    vo_compiz_video_image_format_rgb_atom =
228
	XInternAtom (mDisplay,
229
		     "_COMPIZ_VIDEO_IMAGE_FORMAT_RGB",
230
		     False);
231
232
    vo_compiz_video_image_format_yv12_atom =
233
	XInternAtom (mDisplay,
234
		     "_COMPIZ_VIDEO_IMAGE_FORMAT_YV12",
235
		     False);
236
237
    XSelectInput (mDisplay, mRootWin, PropertyChangeMask);
238
239
    vo_compiz_detect ();
240
}
241
242
static void allocate_ximage (void)
243
{
244
#ifdef HAVE_SHM
245
    if (Shmem_Flag)
246
    {
247
	ximage =
248
	    XShmCreateImage (mDisplay, NULL, pixmap_depth, ZPixmap, NULL,
249
			     &compizShminfo, pixmap_width, pixmap_height);
250
	compizShminfo.shmid = shmget (IPC_PRIVATE,
251
				      ximage->bytes_per_line *
252
				      ximage->height, IPC_CREAT | 0777);
253
	compizShminfo.shmaddr = (char *) shmat (compizShminfo.shmid, 0, 0);
254
	compizShminfo.readOnly = False;
255
256
	ximage->data = compizShminfo.shmaddr;
257
	XShmAttach (mDisplay, &compizShminfo);
258
	XSync (mDisplay, False);
259
	shmctl (compizShminfo.shmid, IPC_RMID, 0);
260
    } else
261
#endif
262
    {
263
	ximage =
264
	    XShmCreateImage (mDisplay, NULL, pixmap_depth, ZPixmap, NULL,
265
			     &compizShminfo, pixmap_width, pixmap_height);
266
	ximage->data = malloc (ximage->bytes_per_line *
267
			       ximage->height);
268
	XSync (mDisplay, False);
269
    }
270
271
    memset (ximage->data, 128, ximage->bytes_per_line * ximage->height);
272
}
273
274
static void deallocate_ximage (void)
275
{
276
#ifdef HAVE_SHM
277
    if (Shmem_Flag)
278
    {
279
	XShmDetach (mDisplay, &compizShminfo);
280
	shmdt (compizShminfo.shmaddr);
281
    } else
282
#endif
283
    {
284
	free (ximage->data);
285
    }
286
287
    XFree (ximage);
288
    XSync (mDisplay, False);
289
}
290
291
static void vo_compiz_put_ximage (XImage *myximage)
292
{
293
294
#ifdef HAVE_SHM
295
    if (Shmem_Flag)
296
    {
297
	XShmPutImage (mDisplay, vo_pixmap, vo_pixmap_gc, myximage,
298
		      0, 0,
299
		      0, 0,
300
		      myximage->width, myximage->height,
301
		      True);
302
    } else
303
#endif
304
    {
305
	XPutImage (mDisplay, vo_pixmap, vo_pixmap_gc, myximage,
306
		   0, 0,
307
		   0, 0,
308
		   myximage->width, myximage->height);
309
    }
310
311
    if (!vo_xprop)
312
    {
313
	long data[11];
314
	int  w, h;
315
316
	data[0] = vo_pixmap;
317
318
	if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
319
	    data[1] = vo_compiz_video_image_format_yv12_atom;
320
	else
321
	    data[1] = vo_compiz_video_image_format_rgb_atom;
322
323
	data[2] = image_width;
324
	data[3] = image_height;
325
326
	aspect (&w, &h, A_NOZOOM);
327
328
	data[4] = w;
329
	data[5] = h;
330
	data[6] = vo_panscan * 65536;
331
332
	data[7]  = GRAVITY_NORTH | GRAVITY_WEST;
333
	data[8]  = 0;
334
	data[9]  = 0;
335
	data[10] = GRAVITY_SOUTH | GRAVITY_EAST;
336
	data[11] = 0;
337
	data[12] = 0;
338
339
	XChangeProperty (mDisplay,
340
			 vo_window,
341
			 vo_compiz_video_atom,
342
			 XA_INTEGER,
343
			 32, PropModeReplace, (unsigned char *) data,
344
			 13);
345
346
	vo_xprop = 1;
347
    }
348
349
    XSync (mDisplay, False);
350
}
351
352
static void vo_compiz_check_output (void)
353
{
354
    int format = 0;
355
356
    if (vo_compiz_formats)
357
    {
358
	if (xv_format == IMGFMT_YV12)
359
	    format = vo_compiz_formats & COMPIZ_IMAGE_FORMAT_YV12;
360
361
	if (!format)
362
	    format = vo_compiz_formats & COMPIZ_IMAGE_FORMAT_RGB;
363
    }
364
365
    if (format != vo_compiz_format)
366
    {
367
	if (ximage)
368
	{
369
	    deallocate_ximage ();
370
	    ximage = NULL;
371
	}
372
373
	if (vo_pixmap)
374
	{
375
	    XFreePixmap (mDisplay, vo_pixmap);
376
	    vo_pixmap = None;
377
	}
378
379
	if (swsContext)
380
	{
381
	    sws_freeContext (swsContext);
382
	    swsContext = NULL;
383
	}
384
385
	vo_compiz_format = format;
386
    }
387
388
    if (format)
389
    {
390
	int width, height;
391
392
	if (format == COMPIZ_IMAGE_FORMAT_YV12)
393
	{
394
	    width  = (image_width  + 7) & ~7;
395
	    height = (image_height + 1) & ~1;
396
397
	    pixmap_width  = width;
398
	    pixmap_height = height + height / 2;
399
	    pixmap_depth  = 8;
400
401
	    pixmap_offsets[0] = 0;
402
	    pixmap_offsets[1] = width * height;
403
	    pixmap_offsets[2] = width * height + (width / 2);
404
405
	    pixmap_pitches[0] = width;
406
	    pixmap_pitches[1] = width;
407
	    pixmap_pitches[2] = width;
408
409
	    mp_msg (MSGT_VO, MSGL_V,
410
		    "[xv] using compiz composited yv12 output\n");
411
	}
412
	else
413
	{
414
	    width  = image_width;
415
	    height = image_height;
416
417
	    pixmap_width  = width;
418
	    pixmap_height = height;
419
	    pixmap_depth  = 24;
420
421
	    swsContext = (struct SwsContext *)
422
		sws_getContextFromCmdLine (width, height, image_format,
423
					   width, height, IMGFMT_BGR32);
424
425
	    mp_msg (MSGT_VO, MSGL_V,
426
		    "[xv] using compiz composited rgb output\n");
427
	}
428
429
	vo_pixmap = XCreatePixmap (mDisplay, mRootWin,
430
				   pixmap_width, pixmap_height,
431
				   pixmap_depth);
432
433
	if (vo_pixmap_gc != None)
434
	    XFreeGC (mDisplay, vo_pixmap_gc);
435
436
	allocate_ximage ();
437
438
	vo_pixmap_gc = XCreateGC (mDisplay, vo_pixmap, 0L, NULL);
439
	vo_xprop     = None;
440
441
	XSetWindowBackground (mDisplay, vo_window, 0);
442
	XClearWindow (mDisplay, vo_window);
443
    }
444
    else
445
    {
446
	XDeleteProperty (mDisplay, vo_window, vo_compiz_video_atom);
447
448
	mp_msg (MSGT_VO, MSGL_V,
449
		"[xv] compiz composited output not available\n");
450
    }
451
}
452
453
static Bool check_compiz_event (Display *display, XEvent *event, XPointer arg)
454
{
455
    if (event->type == DestroyNotify)
456
    {
457
	if (event->xdestroywindow.window == wm_check_window)
458
	    return True;
459
    }
460
    else if (event->type == PropertyNotify)
461
    {
462
	if (event->xproperty.atom == vo_compiz_video_supported_atom)
463
	    return True;
464
    }
465
466
    return False;
467
}
468
469
static void vo_compiz_check_events (void)
470
{
471
    XEvent event;
472
473
    if (XCheckIfEvent (mDisplay, &event, check_compiz_event, NULL))
474
    {
475
	vo_compiz_detect ();
476
	vo_compiz_check_output ();
477
    }
478
}
479
480
static int vo_compiz_draw_slice (uint8_t * image[], int stride[],
481
				 int w, int h, int x, int y)
482
{
483
    if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
484
    {
485
	uint8_t *dst;
486
487
	dst = ximage->data + pixmap_offsets[0] + pixmap_pitches[0] * y + x;
488
	memcpy_pic (dst, image[0], w, h, pixmap_pitches[0], stride[0]);
489
490
	x /= 2;
491
	y /= 2;
492
	w /= 2;
493
	h /= 2;
494
495
	dst = ximage->data + pixmap_offsets[1] + pixmap_pitches[1] * y + x;
496
	memcpy_pic (dst, image[2], w, h, pixmap_pitches[1], stride[2]);
497
498
	dst = ximage->data + pixmap_offsets[2] + pixmap_pitches[2] * y + x;
499
	memcpy_pic (dst, image[1], w, h, pixmap_pitches[2], stride[1]);
500
    }
501
    else
502
    {
503
	uint8_t *dst[3];
504
	int	dstStride[3];
505
506
	dstStride[1] = dstStride[2] = 0;
507
	dst[1] = dst[2] = NULL;
508
509
	dst[0] = ximage->data;
510
	dstStride[0] = ximage->bytes_per_line;
511
512
	sws_scale (swsContext, image, stride, y, h, dst, dstStride);
513
    }
514
515
    return 0;
516
}
517
518
static uint32_t vo_compiz_draw_image (mp_image_t *mpi)
519
{
520
    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
521
	return VO_TRUE;
522
523
    if (mpi->flags & MP_IMGFLAG_PLANAR)
524
    {
525
	vo_compiz_draw_slice (mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
526
	return VO_TRUE;
527
    }
528
529
    return VO_FALSE;
530
}
531
532
static uint32_t vo_compiz_get_image (mp_image_t *mpi)
533
{
534
    if (mpi->imgfmt != image_format)
535
	return VO_FALSE;
536
537
    if (mpi->height != image_height)
538
	return VO_FALSE;
539
540
    if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
541
    {
542
	if (mpi->width * (mpi->bpp / 8) != pixmap_pitches[0])
543
	    return VO_FALSE;
544
545
	if (!(mpi->flags & MP_IMGFLAG_PLANAR))
546
	    return VO_FALSE;
547
548
	if (mpi->flags & MP_IMGFLAG_SWAPPED)
549
	    return VO_FALSE;
550
551
	if (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))
552
	{
553
	    mpi->planes[0] = ximage->data + pixmap_offsets[0];
554
	    mpi->stride[0] = pixmap_pitches[0];
555
	    mpi->planes[1] = ximage->data + pixmap_offsets[2];
556
	    mpi->stride[1] = pixmap_pitches[2];
557
	    mpi->planes[2] = ximage->data + pixmap_offsets[1];
558
	    mpi->stride[2] = pixmap_pitches[1];
559
560
	    mpi->width = mpi->stride[0] / (mpi->bpp / 8);
561
	}
562
	else
563
	{
564
	    return VO_FALSE;
565
	}
566
    }
567
    else
568
    {
569
	if (mpi->type != MP_IMGTYPE_STATIC)
570
	    return VO_FALSE;
571
572
	if (mpi->flags & (MP_IMGFLAG_PLANAR | MP_IMGFLAG_YUV))
573
	    return VO_FALSE;
574
575
	if (mpi->width != image_width)
576
	    return VO_FALSE;
577
578
	mpi->stride[0] = image_width * 4;
579
	mpi->planes[0] = ximage->data;
580
    }
581
582
    mpi->flags |= MP_IMGFLAG_DIRECT;
583
584
    return VO_TRUE;
585
}
586
587
static void vo_compiz_draw_alpha (int x0, int y0, int w, int h,
588
				  unsigned char *src, unsigned char *srca,
589
				  int stride)
590
{
591
    x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
592
593
    if (vo_compiz_format == COMPIZ_IMAGE_FORMAT_YV12)
594
    {
595
	vo_draw_alpha_yv12 (w, h, src, srca, stride,
596
			    ximage->data +
597
			    pixmap_offsets[0] +
598
			    pixmap_pitches[0] * y0 + x0,
599
			    pixmap_pitches[0]);
600
    }
601
    else
602
    {
603
	vo_draw_alpha_rgb32 (w, h, src, srca, stride,
604
			     ximage->data + 4 * (y0 * image_width + x0),
605
			     4 * image_width);
606
    }
607
}
608
95
static void (*draw_alpha_fnc) (int x0, int y0, int w, int h,
609
static void (*draw_alpha_fnc) (int x0, int y0, int w, int h,
96
                               unsigned char *src, unsigned char *srca,
610
                               unsigned char *src, unsigned char *srca,
97
                               int stride);
611
                               int stride);
Lines 452-457 Link Here
452
    }
966
    }
453
#endif
967
#endif
454
968
969
    vo_compiz_check_output ();
970
455
    mp_msg(MSGT_VO, MSGL_V, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX,
971
    mp_msg(MSGT_VO, MSGL_V, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX,
456
           drwY, vo_dwidth, vo_dheight);
972
           drwY, vo_dwidth, vo_dheight);
457
973
Lines 547-554 Link Here
547
1063
548
static void check_events(void)
1064
static void check_events(void)
549
{
1065
{
550
    int e = vo_x11_check_events(mDisplay);
1066
    int e;
551
1067
1068
    vo_compiz_check_events ();
1069
1070
    e = vo_x11_check_events(mDisplay);
1071
552
    if (e & VO_EVENT_RESIZE)
1072
    if (e & VO_EVENT_RESIZE)
553
    {
1073
    {
554
        XGetGeometry(mDisplay, vo_window, &mRoot, &drwX, &drwY, &vo_dwidth,
1074
        XGetGeometry(mDisplay, vo_window, &mRoot, &drwX, &drwY, &vo_dwidth,
Lines 592-597 Link Here
592
        if ( visible_buf != -1 )
1112
        if ( visible_buf != -1 )
593
        {
1113
        {
594
          /* redraw the last visible buffer */
1114
          /* redraw the last visible buffer */
1115
	    if (!vo_pixmap)
595
          put_xvimage( xvimage[visible_buf] );
1116
          put_xvimage( xvimage[visible_buf] );
596
        }
1117
        }
597
    }
1118
    }
Lines 599-611 Link Here
599
1120
600
static void draw_osd(void)
1121
static void draw_osd(void)
601
{
1122
{
602
    vo_draw_text(image_width -
1123
    if (vo_pixmap)
603
                 image_width * vo_panscan_x / (vo_dwidth + vo_panscan_x),
1124
	vo_draw_text (image_width -
604
                 image_height, draw_alpha_fnc);
1125
		      image_width * vo_panscan_x / (vo_dwidth + vo_panscan_x),
1126
		      image_height, vo_compiz_draw_alpha);
1127
    else
1128
	vo_draw_text (image_width -
1129
		      image_width * vo_panscan_x / (vo_dwidth + vo_panscan_x),
1130
		      image_height, draw_alpha_fnc);
605
}
1131
}
606
1132
607
static void flip_page(void)
1133
static void flip_page(void)
608
{
1134
{
1135
    if (vo_pixmap)
1136
    {
1137
	vo_compiz_put_ximage (ximage);
1138
	return;
1139
    }
1140
609
    put_xvimage( xvimage[current_buf] );
1141
    put_xvimage( xvimage[current_buf] );
610
1142
611
    /* remember the currently visible buffer */
1143
    /* remember the currently visible buffer */
Lines 626-631 Link Here
626
{
1158
{
627
    uint8_t *dst;
1159
    uint8_t *dst;
628
1160
1161
    if (vo_pixmap)
1162
	return vo_compiz_draw_slice (image, stride, w, h, x, y);
1163
629
    dst = xvimage[current_buf]->data + xvimage[current_buf]->offsets[0] +
1164
    dst = xvimage[current_buf]->data + xvimage[current_buf]->offsets[0] +
630
        xvimage[current_buf]->pitches[0] * y + x;
1165
        xvimage[current_buf]->pitches[0] * y + x;
631
    memcpy_pic(dst, image[0], w, h, xvimage[current_buf]->pitches[0],
1166
    memcpy_pic(dst, image[0], w, h, xvimage[current_buf]->pitches[0],
Lines 665-670 Link Here
665
1200
666
static uint32_t draw_image(mp_image_t * mpi)
1201
static uint32_t draw_image(mp_image_t * mpi)
667
{
1202
{
1203
    if (vo_pixmap)
1204
	return vo_compiz_draw_image (mpi);
1205
668
    if (mpi->flags & MP_IMGFLAG_DIRECT)
1206
    if (mpi->flags & MP_IMGFLAG_DIRECT)
669
    {
1207
    {
670
        // direct rendering:
1208
        // direct rendering:
Lines 694-699 Link Here
694
{
1232
{
695
    int buf = current_buf;      // we shouldn't change current_buf unless we do DR!
1233
    int buf = current_buf;      // we shouldn't change current_buf unless we do DR!
696
1234
1235
    if (vo_pixmap)
1236
	return vo_compiz_get_image (mpi);
1237
697
    if (mpi->type == MP_IMGTYPE_STATIC && num_buffers > 1)
1238
    if (mpi->type == MP_IMGTYPE_STATIC && num_buffers > 1)
698
        return VO_FALSE;        // it is not static
1239
        return VO_FALSE;        // it is not static
699
    if (mpi->imgfmt != image_format)
1240
    if (mpi->imgfmt != image_format)
Lines 913-918 Link Here
913
1454
914
    fo = XvListImageFormats(mDisplay, xv_port, (int *) &formats);
1455
    fo = XvListImageFormats(mDisplay, xv_port, (int *) &formats);
915
1456
1457
    vo_compiz_init ();
1458
916
    mp_input_add_event_fd(ConnectionNumber(mDisplay), check_events);
1459
    mp_input_add_event_fd(ConnectionNumber(mDisplay), check_events);
917
    return 0;
1460
    return 0;
918
} 
1461
} 
Lines 940-946 Link Here
940
            vo_x11_fullscreen();
1483
            vo_x11_fullscreen();
941
            /* indended, fallthrough to update panscan on fullscreen/windowed switch */
1484
            /* indended, fallthrough to update panscan on fullscreen/windowed switch */
942
        case VOCTRL_SET_PANSCAN:
1485
        case VOCTRL_SET_PANSCAN:
943
            if ((vo_fs && (vo_panscan != vo_panscan_amount))
1486
	    if (vo_pixmap)
1487
	    {
1488
		panscan_calc ();
1489
		vo_xprop = None;
1490
	    }
1491
	    else if ((vo_fs && (vo_panscan != vo_panscan_amount))
944
                || (!vo_fs && vo_panscan_amount))
1492
                || (!vo_fs && vo_panscan_amount))
945
            {
1493
            {
946
                int old_y = vo_panscan_y;
1494
                int old_y = vo_panscan_y;

Return to bug 258657