intel_xvmc.c revision 03b705cf
1/*
2 * Copyright © 2007 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Zhenyu Wang <zhenyu.z.wang@intel.com>
25 *
26 */
27#include "intel_xvmc_private.h"
28#include <xcb/xcb.h>
29#include <xcb/xcb_aux.h>
30#include <xcb/dri2.h>
31#include <X11/Xlib-xcb.h>
32#include <X11/extensions/dri2tokens.h>
33
34/* global */
35struct _intel_xvmc_driver *xvmc_driver = NULL;
36
37/* Lookup tables to speed common calculations for coded_block_pattern */
38/* each block is ((8*8) * sizeof(short)) */
39unsigned int mb_bytes_420[] = {
40	0,			/* 0 */
41	128,			/* 1 */
42	128,			/* 10 */
43	256,			/* 11 */
44	128,			/* 100 */
45	256,			/* 101 */
46	256,			/* 110 */
47	384,			/* 111 */
48	128,			/* 1000 */
49	256,			/* 1001 */
50	256,			/* 1010 */
51	384,			/* 1011 */
52	256,			/* 1100 */
53	384,			/* 1101 */
54	384,			/* 1110 */
55	512,			/* 1111 */
56	128,			/* 10000 */
57	256,			/* 10001 */
58	256,			/* 10010 */
59	384,			/* 10011 */
60	256,			/* 10100 */
61	384,			/* 10101 */
62	384,			/* 10110 */
63	512,			/* 10111 */
64	256,			/* 11000 */
65	384,			/* 11001 */
66	384,			/* 11010 */
67	512,			/* 11011 */
68	384,			/* 11100 */
69	512,			/* 11101 */
70	512,			/* 11110 */
71	640,			/* 11111 */
72	128,			/* 100000 */
73	256,			/* 100001 */
74	256,			/* 100010 */
75	384,			/* 100011 */
76	256,			/* 100100 */
77	384,			/* 100101 */
78	384,			/* 100110 */
79	512,			/* 100111 */
80	256,			/* 101000 */
81	384,			/* 101001 */
82	384,			/* 101010 */
83	512,			/* 101011 */
84	384,			/* 101100 */
85	512,			/* 101101 */
86	512,			/* 101110 */
87	640,			/* 101111 */
88	256,			/* 110000 */
89	384,			/* 110001 */
90	384,			/* 110010 */
91	512,			/* 110011 */
92	384,			/* 110100 */
93	512,			/* 110101 */
94	512,			/* 110110 */
95	640,			/* 110111 */
96	384,			/* 111000 */
97	512,			/* 111001 */
98	512,			/* 111010 */
99	640,			/* 111011 */
100	512,			/* 111100 */
101	640,			/* 111101 */
102	640,			/* 111110 */
103	768			/* 111111 */
104};
105
106void LOCK_HARDWARE(drm_context_t ctx)
107{
108	PPTHREAD_MUTEX_LOCK();
109	assert(!xvmc_driver->locked);
110
111	xvmc_driver->locked = 1;
112}
113
114void UNLOCK_HARDWARE(drm_context_t ctx)
115{
116	xvmc_driver->locked = 0;
117
118	PPTHREAD_MUTEX_UNLOCK();
119}
120
121static int
122dri2_connect(Display *display)
123{
124	xcb_dri2_query_version_cookie_t query_version_cookie;
125	xcb_dri2_query_version_reply_t *query_version_reply;
126	xcb_dri2_connect_cookie_t connect_cookie;
127	xcb_dri2_connect_reply_t *connect_reply;
128	xcb_dri2_authenticate_cookie_t auth_cookie;
129	xcb_dri2_authenticate_reply_t *auth_reply;
130	xcb_screen_t *root;
131	xcb_connection_t *c = XGetXCBConnection(display);
132	drm_magic_t magic;
133	const xcb_query_extension_reply_t *dri2_reply;
134	char *device_name;
135	int len;
136
137	root = xcb_aux_get_screen(c, DefaultScreen(display));
138
139	dri2_reply = xcb_get_extension_data(c, &xcb_dri2_id);
140
141	if (!dri2_reply) {
142		XVMC_ERR("DRI2 required");
143		return BadValue;
144	}
145
146	/* Query the extension and make our first use of it at the same time. */
147	query_version_cookie = xcb_dri2_query_version(c, 1, 0);
148	connect_cookie = xcb_dri2_connect(c, root->root, DRI2DriverDRI);
149
150	query_version_reply =
151		xcb_dri2_query_version_reply(c, query_version_cookie, NULL);
152	connect_reply = xcb_dri2_connect_reply(c, connect_cookie, NULL);
153
154	if (!query_version_reply) {
155		XVMC_ERR("DRI2 required");
156		return BadValue;
157	}
158	free(query_version_reply);
159
160	len = xcb_dri2_connect_device_name_length(connect_reply);
161	device_name = malloc(len + 1);
162	if (!device_name) {
163		XVMC_ERR("malloc failure");
164		return BadAlloc;
165	}
166	strncpy(device_name, xcb_dri2_connect_device_name(connect_reply), len);
167	device_name[len] = 0;
168	xvmc_driver->fd = open(device_name, O_RDWR);
169	free(device_name);
170	free(connect_reply);
171	if (xvmc_driver->fd < 0) {
172		XVMC_ERR("Failed to open drm device: %s\n", strerror(errno));
173		return BadValue;
174	}
175
176	if (drmGetMagic(xvmc_driver->fd, &magic)) {
177		XVMC_ERR("Failed to get magic\n");
178		return BadValue;
179	}
180
181	auth_cookie = xcb_dri2_authenticate(c, root->root, magic);
182	auth_reply = xcb_dri2_authenticate_reply(c, auth_cookie, NULL);
183	if (!auth_reply) {
184		XVMC_ERR("Failed to authenticate magic %d\n", magic);
185		return BadValue;
186	}
187	free(auth_reply);
188
189	return Success;
190}
191
192/*
193* Function: XvMCCreateContext
194* Description: Create a XvMC context for the given surface parameters.
195* Arguments:
196*   display - Connection to the X server.
197*   port - XvPortID to use as avertised by the X connection.
198*   surface_type_id - Unique identifier for the Surface type.
199*   width - Width of the surfaces.
200*   height - Height of the surfaces.
201*   flags - one or more of the following
202*      XVMC_DIRECT - A direct rendered context is requested.
203*
204* Notes: surface_type_id and width/height parameters must match those
205*        returned by XvMCListSurfaceTypes.
206* Returns: Status
207*/
208_X_EXPORT Status XvMCCreateContext(Display * display, XvPortID port,
209				   int surface_type_id, int width, int height,
210				   int flags, XvMCContext * context)
211{
212	Status ret;
213	CARD32 *priv_data = NULL;
214	struct intel_xvmc_hw_context *comm;
215	int major, minor;
216	int error_base;
217	int event_base;
218	int priv_count;
219
220	/* Verify Obvious things first */
221	if (!display || !context)
222		return BadValue;
223
224	if (!(flags & XVMC_DIRECT)) {
225		XVMC_ERR("Indirect Rendering not supported! Using Direct.");
226		return BadValue;
227	}
228
229	/*
230	   Width, Height, and flags are checked against surface_type_id
231	   and port for validity inside the X server, no need to check
232	   here.
233	 */
234	context->surface_type_id = surface_type_id;
235	context->width = (unsigned short)((width + 15) & ~15);
236	context->height = (unsigned short)((height + 15) & ~15);
237	context->flags = flags;
238	context->port = port;
239
240	if (!XvMCQueryExtension(display, &event_base, &error_base)) {
241		XVMC_ERR("XvMCExtension is not available!");
242		return BadValue;
243	}
244
245	ret = XvMCQueryVersion(display, &major, &minor);
246	if (ret) {
247		XVMC_ERR
248		    ("XvMCQueryVersion Failed, unable to determine protocol version.");
249		return ret;
250	}
251
252	/* XXX: major and minor could be checked in future for XvMC
253	 * protocol capability (i.e H.264/AVC decode available)
254	 */
255
256	/*
257	   Pass control to the X server to create a drm_context_t for us and
258	   validate the with/height and flags.
259	 */
260	if ((ret =
261	     _xvmc_create_context(display, context, &priv_count, &priv_data))) {
262		XVMC_ERR("Unable to create XvMC Context.");
263		return ret;
264	}
265
266	comm = (struct intel_xvmc_hw_context *)priv_data;
267
268	if (xvmc_driver == NULL || xvmc_driver->type != comm->type) {
269		switch (comm->type) {
270		case XVMC_I915_MPEG2_MC:
271			xvmc_driver = &i915_xvmc_mc_driver;
272			break;
273		case XVMC_I965_MPEG2_MC:
274			xvmc_driver = &i965_xvmc_mc_driver;
275			break;
276		case XVMC_I965_MPEG2_VLD:
277			xvmc_driver = &xvmc_vld_driver;
278			break;
279		case XVMC_I945_MPEG2_VLD:
280		default:
281			XVMC_ERR("unimplemented xvmc type %d", comm->type);
282			XFree(priv_data);
283			priv_data = NULL;
284			return BadValue;
285		}
286	}
287
288	if (xvmc_driver == NULL || xvmc_driver->type != comm->type) {
289		XVMC_ERR("fail to load xvmc driver for type %d\n", comm->type);
290		return BadValue;
291	}
292
293	XVMC_INFO("decoder type is %s", intel_xvmc_decoder_string(comm->type));
294
295	/* check DRI2 */
296	ret = Success;
297	xvmc_driver->fd = -1;
298
299	ret = dri2_connect(display);
300	if (ret != Success) {
301		XFree(priv_data);
302		context->privData = NULL;
303		if (xvmc_driver->fd >= 0)
304			close(xvmc_driver->fd);
305		xvmc_driver = NULL;
306		return ret;
307	}
308
309	if ((xvmc_driver->bufmgr =
310	     intel_bufmgr_gem_init(xvmc_driver->fd, 1024 * 64)) == NULL) {
311		XVMC_ERR("Can't init bufmgr\n");
312		return BadAlloc;
313	}
314	drm_intel_bufmgr_gem_enable_reuse(xvmc_driver->bufmgr);
315
316	/* call driver hook.
317	 * driver hook should free priv_data after return if success.*/
318	ret =
319	    (xvmc_driver->create_context) (display, context, priv_count,
320					   priv_data);
321	if (ret) {
322		XVMC_ERR("driver create context failed\n");
323		XFree(priv_data);
324		context->privData = NULL;
325		xvmc_driver = NULL;
326		return ret;
327	}
328
329	pthread_mutex_init(&xvmc_driver->ctxmutex, NULL);
330	intelInitBatchBuffer();
331	intel_xvmc_dump_open();
332
333	return Success;
334}
335
336/*
337 * Function: XvMCDestroyContext
338 * Description: Destorys the specified context.
339 *
340 * Arguments:
341 *   display - Specifies the connection to the server.
342 *   context - The context to be destroyed.
343 *
344 */
345_X_EXPORT Status XvMCDestroyContext(Display * display, XvMCContext * context)
346{
347	Status ret;
348	int screen;
349
350	if (!display || !context)
351		return XvMCBadContext;
352	screen = DefaultScreen(display);
353	ret = (xvmc_driver->destroy_context) (display, context);
354	if (ret) {
355		XVMC_ERR("destroy context fail\n");
356		return ret;
357	}
358
359	intelFiniBatchBuffer();
360
361	dri_bufmgr_destroy(xvmc_driver->bufmgr);
362
363	ret = _xvmc_destroy_context(display, context);
364	if (ret != Success) {
365		XVMC_ERR("_xvmc_destroy_context fail\n");
366		return ret;
367	}
368
369	if (xvmc_driver->num_ctx == 0) {
370		pthread_mutex_destroy(&xvmc_driver->ctxmutex);
371
372		if (xvmc_driver->fd >= 0)
373			close(xvmc_driver->fd);
374
375		xvmc_driver->fd = -1;
376		intel_xvmc_dump_close();
377	}
378	return Success;
379}
380
381/*
382 * Function: XvMCCreateSurface
383 */
384_X_EXPORT Status XvMCCreateSurface(Display * display, XvMCContext * context,
385				   XvMCSurface * surface)
386{
387	Status ret;
388	int priv_count;
389	CARD32 *priv_data;
390	intel_xvmc_surface_ptr intel_surf = NULL;
391	struct intel_xvmc_context *intel_ctx;
392
393	if (!display || !context)
394		return XvMCBadContext;
395
396	if (!surface)
397		return XvMCBadSurface;
398
399	intel_ctx = context->privData;
400
401	if ((ret = _xvmc_create_surface(display, context, surface,
402					&priv_count, &priv_data))) {
403		XVMC_ERR("Unable to create XvMCSurface.");
404		return ret;
405	}
406
407	XFree(priv_data);
408
409	surface->privData = calloc(1, sizeof(struct intel_xvmc_surface));
410
411	if (!(intel_surf = surface->privData)) {
412		PPTHREAD_MUTEX_UNLOCK();
413		return BadAlloc;
414	}
415
416	intel_surf->bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
417					      "surface",
418					      intel_ctx->surface_bo_size,
419					      GTT_PAGE_SIZE);
420	if (!intel_surf->bo) {
421		free(intel_surf);
422		return BadAlloc;
423	}
424
425	drm_intel_bo_disable_reuse(intel_surf->bo);
426
427	intel_surf = surface->privData;
428	intel_surf->context = context;
429
430	intel_surf->image = XvCreateImage(display, context->port,
431					  FOURCC_XVMC,
432					  (char *) &intel_surf->gem_handle,
433					  surface->width, surface->height);
434	if (!intel_surf->image) {
435		XVMC_ERR("Can't create XvImage for surface\n");
436		free(intel_surf);
437		_xvmc_destroy_surface(display, surface);
438		return BadAlloc;
439	}
440
441	return Success;
442}
443
444/*
445 * Function: XvMCDestroySurface
446 */
447_X_EXPORT Status XvMCDestroySurface(Display * display, XvMCSurface * surface)
448{
449	intel_xvmc_surface_ptr intel_surf;
450
451	if (!display || !surface)
452		return XvMCBadSurface;
453
454	intel_surf = surface->privData;
455	if (!intel_surf)
456		return XvMCBadSurface;
457
458	XFree(intel_surf->image);
459	if (intel_surf->gc_init)
460		XFreeGC(display, intel_surf->gc);
461
462	drm_intel_bo_unreference(intel_surf->bo);
463
464	free(intel_surf);
465
466	_xvmc_destroy_surface(display, surface);
467
468	return Success;
469}
470
471/*
472 * Function: XvMCCreateBlocks
473 */
474_X_EXPORT Status XvMCCreateBlocks(Display * display, XvMCContext * context,
475				  unsigned int num_blocks,
476				  XvMCBlockArray * block)
477{
478	if (!display || !context || !num_blocks || !block)
479		return BadValue;
480
481	memset(block, 0, sizeof(XvMCBlockArray));
482
483	if (!
484	    (block->blocks =
485	     (short *)malloc((num_blocks << 6) * sizeof(short))))
486		return BadAlloc;
487
488	block->num_blocks = num_blocks;
489	block->context_id = context->context_id;
490	block->privData = NULL;
491
492	return Success;
493}
494
495/*
496 * Function: XvMCDestroyBlocks
497 */
498_X_EXPORT Status XvMCDestroyBlocks(Display * display, XvMCBlockArray * block)
499{
500	if (!display || !block)
501		return BadValue;
502
503	if (block->blocks)
504		free(block->blocks);
505
506	block->context_id = 0;
507	block->num_blocks = 0;
508	block->blocks = NULL;
509	block->privData = NULL;
510
511	return Success;
512}
513
514/*
515 * Function: XvMCCreateMacroBlocks
516 */
517_X_EXPORT Status XvMCCreateMacroBlocks(Display * display, XvMCContext * context,
518				       unsigned int num_blocks,
519				       XvMCMacroBlockArray * blocks)
520{
521	if (!display || !context || !blocks || !num_blocks)
522		return BadValue;
523
524	memset(blocks, 0, sizeof(XvMCMacroBlockArray));
525	blocks->macro_blocks =
526	    (XvMCMacroBlock *) malloc(num_blocks * sizeof(XvMCMacroBlock));
527
528	if (!blocks->macro_blocks)
529		return BadAlloc;
530
531	blocks->num_blocks = num_blocks;
532	blocks->context_id = context->context_id;
533	blocks->privData = NULL;
534
535	return Success;
536}
537
538/*
539 * Function: XvMCDestroyMacroBlocks
540 */
541_X_EXPORT Status XvMCDestroyMacroBlocks(Display * display,
542					XvMCMacroBlockArray * block)
543{
544	if (!display || !block)
545		return BadValue;
546	if (block->macro_blocks)
547		free(block->macro_blocks);
548
549	block->context_id = 0;
550	block->num_blocks = 0;
551	block->macro_blocks = NULL;
552	block->privData = NULL;
553
554	return Success;
555}
556
557/*
558 * Function: XvMCRenderSurface
559 *
560 * Description: This function does the actual HWMC. Given a list of
561 *  macroblock structures it dispatched the hardware commands to execute
562 *  them.
563 */
564_X_EXPORT Status XvMCRenderSurface(Display * display, XvMCContext * context,
565				   unsigned int picture_structure,
566				   XvMCSurface * target_surface,
567				   XvMCSurface * past_surface,
568				   XvMCSurface * future_surface,
569				   unsigned int flags,
570				   unsigned int num_macroblocks,
571				   unsigned int first_macroblock,
572				   XvMCMacroBlockArray * macroblock_array,
573				   XvMCBlockArray * blocks)
574{
575	Status ret;
576
577	if (!display || !context) {
578		XVMC_ERR("Invalid Display, Context or Target!");
579		return XvMCBadContext;
580	}
581	if (!target_surface)
582		return XvMCBadSurface;
583
584	intel_xvmc_dump_render(context, picture_structure, target_surface,
585			       past_surface, future_surface, flags,
586			       num_macroblocks, first_macroblock,
587			       macroblock_array, blocks);
588
589	ret =
590	    (xvmc_driver->render_surface) (display, context, picture_structure,
591					   target_surface, past_surface,
592					   future_surface, flags,
593					   num_macroblocks, first_macroblock,
594					   macroblock_array, blocks);
595
596	if (ret) {
597		XVMC_ERR("render surface fail\n");
598		return ret;
599	}
600	return Success;
601}
602
603/*
604 * Function: XvMCPutSurface
605 *
606 * Description:
607 * Arguments:
608 *  display: Connection to X server
609 *  surface: Surface to be displayed
610 *  draw: X Drawable on which to display the surface
611 *  srcx: X coordinate of the top left corner of the region to be
612 *          displayed within the surface.
613 *  srcy: Y coordinate of the top left corner of the region to be
614 *          displayed within the surface.
615 *  srcw: Width of the region to be displayed.
616 *  srch: Height of the region to be displayed.
617 *  destx: X cordinate of the top left corner of the destination region
618 *         in the drawable coordinates.
619 *  desty: Y cordinate of the top left corner of the destination region
620 *         in the drawable coordinates.
621 *  destw: Width of the destination region.
622 *  desth: Height of the destination region.
623 *  flags: One or more of the following.
624 *	XVMC_TOP_FIELD - Display only the Top field of the surface.
625 *	XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface.
626 *	XVMC_FRAME_PICTURE - Display both fields or frame.
627 */
628_X_EXPORT Status XvMCPutSurface(Display * display, XvMCSurface * surface,
629				Drawable draw, short srcx, short srcy,
630				unsigned short srcw, unsigned short srch,
631				short destx, short desty,
632				unsigned short destw, unsigned short desth,
633				int flags)
634{
635	Status ret = Success;
636	XvMCContext *context;
637	intel_xvmc_surface_ptr intel_surf;
638
639	if (!display || !surface)
640		return XvMCBadSurface;
641
642	intel_surf = surface->privData;
643	context = intel_surf->context;
644	if (!context || !intel_surf)
645		return XvMCBadSurface;
646
647	if (intel_surf->gc_init == FALSE) {
648		intel_surf->gc = XCreateGC(display, draw, 0, NULL);
649		intel_surf->gc_init = TRUE;
650	} else if (draw != intel_surf->last_draw) {
651		XFreeGC(display, intel_surf->gc);
652		intel_surf->gc = XCreateGC(display, draw, 0, NULL);
653	}
654	intel_surf->last_draw = draw;
655
656	drm_intel_bo_flink(intel_surf->bo, &intel_surf->gem_handle);
657
658	ret = XvPutImage(display, context->port, draw, intel_surf->gc,
659			 intel_surf->image, srcx, srcy, srcw, srch, destx,
660			 desty, destw, desth);
661	return ret;
662}
663
664/*
665 * Function: XvMCSyncSurface
666 * Arguments:
667 *   display - Connection to the X server
668 *   surface - The surface to synchronize
669 */
670_X_EXPORT Status XvMCSyncSurface(Display * display, XvMCSurface * surface)
671{
672	if (!display || !surface)
673		return XvMCBadSurface;
674
675	return Success;
676}
677
678/*
679 * Function: XvMCFlushSurface
680 * Description:
681 *   This function commits pending rendering requests to ensure that they
682 *   wll be completed in a finite amount of time.
683 * Arguments:
684 *   display - Connection to X server
685 *   surface - Surface to flush
686 * Returns: Status
687 */
688_X_EXPORT Status XvMCFlushSurface(Display * display, XvMCSurface * surface)
689{
690	if (!display || !surface)
691		return XvMCBadSurface;
692
693	return Success;
694}
695
696/*
697 * Function: XvMCGetSurfaceStatus
698 * Description:
699 * Arguments:
700 *  display: connection to X server
701 *  surface: The surface to query
702 *  stat: One of the Following
703 *    XVMC_RENDERING - The last XvMCRenderSurface command has not
704 *                     completed.
705 *    XVMC_DISPLAYING - The surface is currently being displayed or a
706 *                     display is pending.
707 */
708_X_EXPORT Status XvMCGetSurfaceStatus(Display * display, XvMCSurface * surface,
709				      int *stat)
710{
711	if (!display || !surface || !stat)
712		return XvMCBadSurface;
713
714	*stat = 0;
715
716	return Success;
717}
718
719/*
720 * Function: XvMCHideSurface
721 * Description: Stops the display of a surface.
722 * Arguments:
723 *   display - Connection to the X server.
724 *   surface - surface to be hidden.
725 *
726 * Returns: Status
727 */
728_X_EXPORT Status XvMCHideSurface(Display * display, XvMCSurface * surface)
729{
730	if (!display || !surface)
731		return XvMCBadSurface;
732
733	return Success;
734}
735
736/*
737 * Function: XvMCCreateSubpicture
738 * Description: This creates a subpicture by filling out the XvMCSubpicture
739 *              structure passed to it and returning Success.
740 * Arguments:
741 *   display - Connection to the X server.
742 *   context - The context to create the subpicture for.
743 *   subpicture - Pre-allocated XvMCSubpicture structure to be filled in.
744 *   width - of subpicture
745 *   height - of subpicture
746 *   xvimage_id - The id describing the XvImage format.
747 *
748 * Returns: Status
749 */
750_X_EXPORT Status XvMCCreateSubpicture(Display * display, XvMCContext * context,
751				      XvMCSubpicture * subpicture,
752				      unsigned short width,
753				      unsigned short height, int xvimage_id)
754{
755	XVMC_ERR("XvMCCreateSubpicture not implemented!\n");
756	return BadValue;
757}
758
759/*
760 * Function: XvMCClearSubpicture
761 * Description: Clear the area of the given subpicture to "color".
762 *              structure passed to it and returning Success.
763 * Arguments:
764 *   display - Connection to the X server.
765 *   subpicture - Subpicture to clear.
766 *   x, y, width, height - rectangle in the subpicture to clear.
767 *   color - The data to file the rectangle with.
768 *
769 * Returns: Status
770 */
771_X_EXPORT Status XvMCClearSubpicture(Display * display,
772				     XvMCSubpicture * subpicture, short x,
773				     short y, unsigned short width,
774				     unsigned short height, unsigned int color)
775{
776	XVMC_ERR("XvMCClearSubpicture not implemented!");
777	return BadValue;
778}
779
780/*
781 * Function: XvMCCompositeSubpicture
782 * Description: Composite the XvImae on the subpicture. This composit uses
783 *              non-premultiplied alpha. Destination alpha is utilized
784 *              except for with indexed subpictures. Indexed subpictures
785 *              use a simple "replace".
786 * Arguments:
787 *   display - Connection to the X server.
788 *   subpicture - Subpicture to clear.
789 *   image - the XvImage to be used as the source of the composite.
790 *   srcx, srcy, width, height - The rectangle from the image to be used.
791 *   dstx, dsty - location in the subpicture to composite the source.
792 *
793 * Returns: Status
794 */
795_X_EXPORT Status XvMCCompositeSubpicture(Display * display,
796					 XvMCSubpicture * subpicture,
797					 XvImage * image, short srcx,
798					 short srcy, unsigned short width,
799					 unsigned short height, short dstx,
800					 short dsty)
801{
802	XVMC_ERR("XvMCCompositeSubpicture not implemented!");
803	return BadValue;
804}
805
806/*
807 * Function: XvMCDestroySubpicture
808 * Description: Destroys the specified subpicture.
809 * Arguments:
810 *   display - Connection to the X server.
811 *   subpicture - Subpicture to be destroyed.
812 *
813 * Returns: Status
814 */
815_X_EXPORT Status XvMCDestroySubpicture(Display * display,
816				       XvMCSubpicture * subpicture)
817{
818	XVMC_ERR("XvMCDestroySubpicture not implemented!");
819	return BadValue;
820}
821
822/*
823 * Function: XvMCSetSubpicturePalette
824 * Description: Set the subpictures palette
825 * Arguments:
826 *   display - Connection to the X server.
827 *   subpicture - Subpiture to set palette for.
828 *   palette - A pointer to an array holding the palette data. The array
829 *     is num_palette_entries * entry_bytes in size.
830 * Returns: Status
831 */
832_X_EXPORT Status XvMCSetSubpicturePalette(Display * display,
833					  XvMCSubpicture * subpicture,
834					  unsigned char *palette)
835{
836	XVMC_ERR("XvMCSetSubpicturePalette not implemented!");
837	return BadValue;
838}
839
840/*
841 * Function: XvMCBlendSubpicture
842 * Description:
843 *    The behavior of this function is different depending on whether
844 *    or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
845 *    i915 only support frontend behavior.
846 *
847 *    XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
848 *
849 *    XvMCBlendSubpicture is a no-op in this case.
850 *
851 * Arguments:
852 *   display - Connection to the X server.
853 *   subpicture - The subpicture to be blended into the video.
854 *   target_surface - The surface to be displayed with the blended subpic.
855 *   source_surface - Source surface prior to blending.
856 *   subx, suby, subw, subh - The rectangle from the subpicture to use.
857 *   surfx, surfy, surfw, surfh - The rectangle in the surface to blend
858 *      blend the subpicture rectangle into. Scaling can ocure if
859 *      XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
860 *
861 * Returns: Status
862 */
863_X_EXPORT Status XvMCBlendSubpicture(Display * display,
864				     XvMCSurface * target_surface,
865				     XvMCSubpicture * subpicture, short subx,
866				     short suby, unsigned short subw,
867				     unsigned short subh, short surfx,
868				     short surfy, unsigned short surfw,
869				     unsigned short surfh)
870{
871	XVMC_ERR("XvMCBlendSubpicture not implemented!");
872	return BadValue;
873}
874
875/*
876 * Function: XvMCBlendSubpicture2
877 * Description:
878 *    The behavior of this function is different depending on whether
879 *    or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
880 *    i915 only supports frontend blending.
881 *
882 *    XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
883 *
884 *    XvMCBlendSubpicture2 blends the source_surface and subpicture and
885 *    puts it in the target_surface.  This does not effect the status of
886 *    the source surface but will cause the target_surface to query
887 *    XVMC_RENDERING until the blend is completed.
888 *
889 * Arguments:
890 *   display - Connection to the X server.
891 *   subpicture - The subpicture to be blended into the video.
892 *   target_surface - The surface to be displayed with the blended subpic.
893 *   source_surface - Source surface prior to blending.
894 *   subx, suby, subw, subh - The rectangle from the subpicture to use.
895 *   surfx, surfy, surfw, surfh - The rectangle in the surface to blend
896 *      blend the subpicture rectangle into. Scaling can ocure if
897 *      XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
898 *
899 * Returns: Status
900 */
901_X_EXPORT Status XvMCBlendSubpicture2(Display * display,
902				      XvMCSurface * source_surface,
903				      XvMCSurface * target_surface,
904				      XvMCSubpicture * subpicture,
905				      short subx, short suby,
906				      unsigned short subw, unsigned short subh,
907				      short surfx, short surfy,
908				      unsigned short surfw,
909				      unsigned short surfh)
910{
911	XVMC_ERR("XvMCBlendSubpicture2 not implemented!");
912	return BadValue;
913}
914
915/*
916 * Function: XvMCSyncSubpicture
917 * Description: This function blocks until all composite/clear requests on
918 *              the subpicture have been complete.
919 * Arguments:
920 *   display - Connection to the X server.
921 *   subpicture - The subpicture to synchronize
922 *
923 * Returns: Status
924 */
925_X_EXPORT Status XvMCSyncSubpicture(Display * display,
926				    XvMCSubpicture * subpicture)
927{
928	XVMC_ERR("XvMCSyncSubpicture not implemented!");
929	return BadValue;
930}
931
932/*
933 * Function: XvMCFlushSubpicture
934 * Description: This function commits pending composite/clear requests to
935 *              ensure that they will be completed in a finite amount of
936 *              time.
937 * Arguments:
938 *   display - Connection to the X server.
939 *   subpicture - The subpicture whos compsiting should be flushed
940 *
941 * Returns: Status
942 */
943_X_EXPORT Status XvMCFlushSubpicture(Display * display,
944				     XvMCSubpicture * subpicture)
945{
946	XVMC_ERR("XvMCFlushSubpicture not implemented!");
947	return BadValue;
948}
949
950/*
951 * Function: XvMCGetSubpictureStatus
952 * Description: This function gets the current status of a subpicture
953 *
954 * Arguments:
955 *   display - Connection to the X server.
956 *   subpicture - The subpicture whos status is being queried
957 *   stat - The status of the subpicture. It can be any of the following
958 *          OR'd together:
959 *          XVMC_RENDERING  - Last composite or clear request not completed
960 *          XVMC_DISPLAYING - Suppicture currently being displayed.
961 *
962 * Returns: Status
963 */
964_X_EXPORT Status XvMCGetSubpictureStatus(Display * display,
965					 XvMCSubpicture * subpicture, int *stat)
966{
967	XVMC_ERR("XvMCGetSubpictureStatus not implemented!");
968	return BadValue;
969}
970
971/*
972 * Function: XvMCQueryAttributes
973 * Description: An array of XvAttributes of size "number" is returned by
974 *   this function. If there are no attributes, NULL is returned and number
975 *   is set to 0. The array may be freed with free().
976 *
977 * Arguments:
978 *   display - Connection to the X server.
979 *   context - The context whos attributes we are querying.
980 *   number - The returned number of recognized atoms
981 *
982 * Returns:
983 *  An array of XvAttributes.
984 */
985_X_EXPORT XvAttribute *XvMCQueryAttributes(Display * display,
986					   XvMCContext * context, int *number)
987{
988	/* now XvMC has no extra attribs than Xv */
989	*number = 0;
990	return NULL;
991}
992
993/*
994 * Function: XvMCSetAttribute
995 * Description: This function sets a context-specific attribute.
996 *
997 * Arguments:
998 *   display - Connection to the X server.
999 *   context - The context whos attributes we are querying.
1000 *   attribute - The X atom of the attribute to be changed.
1001 *   value - The new value for the attribute.
1002 *
1003 * Returns:
1004 *  Status
1005 */
1006_X_EXPORT Status XvMCSetAttribute(Display * display, XvMCContext * context,
1007				  Atom attribute, int value)
1008{
1009	return Success;
1010}
1011
1012/*
1013 * Function: XvMCGetAttribute
1014 * Description: This function queries a context-specific attribute and
1015 *   returns the value.
1016 *
1017 * Arguments:
1018 *   display - Connection to the X server.
1019 *   context - The context whos attributes we are querying.
1020 *   attribute - The X atom of the attribute to be queried
1021 *   value - The returned attribute value
1022 *
1023 * Returns:
1024 *  Status
1025 */
1026_X_EXPORT Status XvMCGetAttribute(Display * display, XvMCContext * context,
1027				  Atom attribute, int *value)
1028{
1029	return Success;
1030}
1031
1032_X_EXPORT Status XvMCBeginSurface(Display * display, XvMCContext * context,
1033				  XvMCSurface * target,
1034				  XvMCSurface * past,
1035				  XvMCSurface * future,
1036				  const XvMCMpegControl * control)
1037{
1038	if (xvmc_driver->begin_surface(display, context,
1039				       target, past, future, control)) {
1040		XVMC_ERR("BeginSurface fail\n");
1041		return BadValue;
1042	}
1043	return Success;
1044}
1045
1046_X_EXPORT Status XvMCLoadQMatrix(Display * display, XvMCContext * context,
1047				 const XvMCQMatrix * qmx)
1048{
1049	if (xvmc_driver->load_qmatrix(display, context, qmx)) {
1050		XVMC_ERR("LoadQMatrix fail\n");
1051		return BadValue;
1052	}
1053	return Success;
1054}
1055
1056_X_EXPORT Status XvMCPutSlice(Display * display, XvMCContext * context,
1057			      char *slice, int nbytes)
1058{
1059	if (xvmc_driver->put_slice(display, context, (unsigned char *) slice, nbytes)) {
1060		XVMC_ERR("PutSlice fail\n");
1061		return BadValue;
1062	}
1063	return Success;
1064}
1065
1066_X_EXPORT Status XvMCPutSlice2(Display * display, XvMCContext * context,
1067			       char *slice, int nbytes, int slice_code)
1068{
1069	if (xvmc_driver->put_slice2
1070	    (display, context, (unsigned char *) slice, nbytes, slice_code)) {
1071		XVMC_ERR("PutSlice2 fail\n");
1072		return BadValue;
1073	}
1074	return Success;
1075}
1076