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