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