1
2#ifdef HAVE_DIX_CONFIG_H
3#include <dix-config.h>
4#endif
5
6#include <string.h>
7
8#include <X11/X.h>
9#include <X11/Xproto.h>
10#include "misc.h"
11#include "os.h"
12#include "dixstruct.h"
13#include "resource.h"
14#include "scrnintstr.h"
15#include "extnsionst.h"
16#include "extinit.h"
17#include "servermd.h"
18#include <X11/Xfuncproto.h>
19#include "xvdix.h"
20#include <X11/extensions/XvMC.h>
21#include <X11/extensions/Xvproto.h>
22#include <X11/extensions/XvMCproto.h>
23#include "xvmcext.h"
24#include "protocol-versions.h"
25
26#ifdef HAS_XVMCSHM
27#include <sys/ipc.h>
28#include <sys/types.h>
29#include <sys/shm.h>
30#endif                          /* HAS_XVMCSHM */
31
32#define DR_CLIENT_DRIVER_NAME_SIZE 48
33#define DR_BUSID_SIZE 48
34
35static DevPrivateKeyRec XvMCScreenKeyRec;
36
37#define XvMCScreenKey (&XvMCScreenKeyRec)
38static Bool XvMCInUse;
39
40int XvMCReqCode;
41int XvMCEventBase;
42
43static RESTYPE XvMCRTContext;
44static RESTYPE XvMCRTSurface;
45static RESTYPE XvMCRTSubpicture;
46
47int (*XvMCScreenInitProc)(ScreenPtr, int, XvMCAdaptorPtr) = NULL;
48
49typedef struct {
50    int num_adaptors;
51    XvMCAdaptorPtr adaptors;
52    CloseScreenProcPtr CloseScreen;
53    char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE];
54    char busID[DR_BUSID_SIZE];
55    int major;
56    int minor;
57    int patchLevel;
58} XvMCScreenRec, *XvMCScreenPtr;
59
60#define XVMC_GET_PRIVATE(pScreen) \
61    (XvMCScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey))
62
63static int
64XvMCDestroyContextRes(void *data, XID id)
65{
66    XvMCContextPtr pContext = (XvMCContextPtr) data;
67
68    pContext->refcnt--;
69
70    if (!pContext->refcnt) {
71        XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
72
73        (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext) (pContext);
74        free(pContext);
75    }
76
77    return Success;
78}
79
80static int
81XvMCDestroySurfaceRes(void *data, XID id)
82{
83    XvMCSurfacePtr pSurface = (XvMCSurfacePtr) data;
84    XvMCContextPtr pContext = pSurface->context;
85    XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
86
87    (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface) (pSurface);
88    free(pSurface);
89
90    XvMCDestroyContextRes((void *) pContext, pContext->context_id);
91
92    return Success;
93}
94
95static int
96XvMCDestroySubpictureRes(void *data, XID id)
97{
98    XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr) data;
99    XvMCContextPtr pContext = pSubpict->context;
100    XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
101
102    (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture) (pSubpict);
103    free(pSubpict);
104
105    XvMCDestroyContextRes((void *) pContext, pContext->context_id);
106
107    return Success;
108}
109
110static int
111ProcXvMCQueryVersion(ClientPtr client)
112{
113    xvmcQueryVersionReply rep = {
114        .type = X_Reply,
115        .sequenceNumber = client->sequence,
116        .length = 0,
117        .major = SERVER_XVMC_MAJOR_VERSION,
118        .minor = SERVER_XVMC_MINOR_VERSION
119    };
120
121    /* REQUEST(xvmcQueryVersionReq); */
122    REQUEST_SIZE_MATCH(xvmcQueryVersionReq);
123
124    WriteToClient(client, sizeof(xvmcQueryVersionReply), &rep);
125    return Success;
126}
127
128static int
129ProcXvMCListSurfaceTypes(ClientPtr client)
130{
131    XvPortPtr pPort;
132    int i;
133    XvMCScreenPtr pScreenPriv;
134    xvmcListSurfaceTypesReply rep;
135    xvmcSurfaceInfo info;
136    XvMCAdaptorPtr adaptor = NULL;
137    XvMCSurfaceInfoPtr surface;
138    int num_surfaces;
139
140    REQUEST(xvmcListSurfaceTypesReq);
141    REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq);
142
143    VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
144
145    if (XvMCInUse) {            /* any adaptors at all */
146        ScreenPtr pScreen = pPort->pAdaptor->pScreen;
147
148        if ((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) {        /* any this screen */
149            for (i = 0; i < pScreenPriv->num_adaptors; i++) {
150                if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
151                    adaptor = &(pScreenPriv->adaptors[i]);
152                    break;
153                }
154            }
155        }
156    }
157
158    num_surfaces = (adaptor) ? adaptor->num_surfaces : 0;
159    rep = (xvmcListSurfaceTypesReply) {
160        .type = X_Reply,
161        .sequenceNumber = client->sequence,
162        .num = num_surfaces,
163        .length = bytes_to_int32(num_surfaces * sizeof(xvmcSurfaceInfo)),
164    };
165
166    WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), &rep);
167
168    for (i = 0; i < num_surfaces; i++) {
169        surface = adaptor->surfaces[i];
170        info.surface_type_id = surface->surface_type_id;
171        info.chroma_format = surface->chroma_format;
172        info.max_width = surface->max_width;
173        info.max_height = surface->max_height;
174        info.subpicture_max_width = surface->subpicture_max_width;
175        info.subpicture_max_height = surface->subpicture_max_height;
176        info.mc_type = surface->mc_type;
177        info.flags = surface->flags;
178        WriteToClient(client, sizeof(xvmcSurfaceInfo), &info);
179    }
180
181    return Success;
182}
183
184static int
185ProcXvMCCreateContext(ClientPtr client)
186{
187    XvPortPtr pPort;
188    CARD32 *data = NULL;
189    int dwords = 0;
190    int i, result, adapt_num = -1;
191    ScreenPtr pScreen;
192    XvMCContextPtr pContext;
193    XvMCScreenPtr pScreenPriv;
194    XvMCAdaptorPtr adaptor = NULL;
195    XvMCSurfaceInfoPtr surface = NULL;
196    xvmcCreateContextReply rep;
197
198    REQUEST(xvmcCreateContextReq);
199    REQUEST_SIZE_MATCH(xvmcCreateContextReq);
200
201    VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
202
203    pScreen = pPort->pAdaptor->pScreen;
204
205    if (!XvMCInUse)             /* no XvMC adaptors */
206        return BadMatch;
207
208    if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))     /* none this screen */
209        return BadMatch;
210
211    for (i = 0; i < pScreenPriv->num_adaptors; i++) {
212        if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
213            adaptor = &(pScreenPriv->adaptors[i]);
214            adapt_num = i;
215            break;
216        }
217    }
218
219    if (adapt_num < 0)          /* none this port */
220        return BadMatch;
221
222    for (i = 0; i < adaptor->num_surfaces; i++) {
223        if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
224            surface = adaptor->surfaces[i];
225            break;
226        }
227    }
228
229    /* adaptor doesn't support this suface_type_id */
230    if (!surface)
231        return BadMatch;
232
233    if ((stuff->width > surface->max_width) ||
234        (stuff->height > surface->max_height))
235        return BadValue;
236
237    if (!(pContext = malloc(sizeof(XvMCContextRec)))) {
238        return BadAlloc;
239    }
240
241    pContext->pScreen = pScreen;
242    pContext->adapt_num = adapt_num;
243    pContext->context_id = stuff->context_id;
244    pContext->surface_type_id = stuff->surface_type_id;
245    pContext->width = stuff->width;
246    pContext->height = stuff->height;
247    pContext->flags = stuff->flags;
248    pContext->refcnt = 1;
249
250    result = (*adaptor->CreateContext) (pPort, pContext, &dwords, &data);
251
252    if (result != Success) {
253        free(pContext);
254        return result;
255    }
256    if (!AddResource(pContext->context_id, XvMCRTContext, pContext)) {
257        free(data);
258        return BadAlloc;
259    }
260
261    rep = (xvmcCreateContextReply) {
262        .type = X_Reply,
263        .sequenceNumber = client->sequence,
264        .length = dwords,
265        .width_actual = pContext->width,
266        .height_actual = pContext->height,
267        .flags_return = pContext->flags
268    };
269
270    WriteToClient(client, sizeof(xvmcCreateContextReply), &rep);
271    if (dwords)
272        WriteToClient(client, dwords << 2, data);
273
274    free(data);
275
276    return Success;
277}
278
279static int
280ProcXvMCDestroyContext(ClientPtr client)
281{
282    void *val;
283    int rc;
284
285    REQUEST(xvmcDestroyContextReq);
286    REQUEST_SIZE_MATCH(xvmcDestroyContextReq);
287
288    rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext,
289                                 client, DixDestroyAccess);
290    if (rc != Success)
291        return rc;
292
293    FreeResource(stuff->context_id, RT_NONE);
294
295    return Success;
296}
297
298static int
299ProcXvMCCreateSurface(ClientPtr client)
300{
301    CARD32 *data = NULL;
302    int dwords = 0;
303    int result;
304    XvMCContextPtr pContext;
305    XvMCSurfacePtr pSurface;
306    XvMCScreenPtr pScreenPriv;
307    xvmcCreateSurfaceReply rep;
308
309    REQUEST(xvmcCreateSurfaceReq);
310    REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq);
311
312    result = dixLookupResourceByType((void **) &pContext, stuff->context_id,
313                                     XvMCRTContext, client, DixUseAccess);
314    if (result != Success)
315        return result;
316
317    pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
318
319    if (!(pSurface = malloc(sizeof(XvMCSurfaceRec))))
320        return BadAlloc;
321
322    pSurface->surface_id = stuff->surface_id;
323    pSurface->surface_type_id = pContext->surface_type_id;
324    pSurface->context = pContext;
325
326    result =
327        (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface) (pSurface,
328                                                                     &dwords,
329                                                                     &data);
330
331    if (result != Success) {
332        free(pSurface);
333        return result;
334    }
335    if (!AddResource(pSurface->surface_id, XvMCRTSurface, pSurface)) {
336        free(data);
337        return BadAlloc;
338    }
339
340    rep = (xvmcCreateSurfaceReply) {
341        .type = X_Reply,
342        .sequenceNumber = client->sequence,
343        .length = dwords
344    };
345
346    WriteToClient(client, sizeof(xvmcCreateSurfaceReply), &rep);
347    if (dwords)
348        WriteToClient(client, dwords << 2, data);
349
350    free(data);
351
352    pContext->refcnt++;
353
354    return Success;
355}
356
357static int
358ProcXvMCDestroySurface(ClientPtr client)
359{
360    void *val;
361    int rc;
362
363    REQUEST(xvmcDestroySurfaceReq);
364    REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq);
365
366    rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface,
367                                 client, DixDestroyAccess);
368    if (rc != Success)
369        return rc;
370
371    FreeResource(stuff->surface_id, RT_NONE);
372
373    return Success;
374}
375
376static int
377ProcXvMCCreateSubpicture(ClientPtr client)
378{
379    Bool image_supported = FALSE;
380    CARD32 *data = NULL;
381    int i, result, dwords = 0;
382    XvMCContextPtr pContext;
383    XvMCSubpicturePtr pSubpicture;
384    XvMCScreenPtr pScreenPriv;
385    xvmcCreateSubpictureReply rep;
386    XvMCAdaptorPtr adaptor;
387    XvMCSurfaceInfoPtr surface = NULL;
388
389    REQUEST(xvmcCreateSubpictureReq);
390    REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq);
391
392    result = dixLookupResourceByType((void **) &pContext, stuff->context_id,
393                                     XvMCRTContext, client, DixUseAccess);
394    if (result != Success)
395        return result;
396
397    pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
398
399    adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]);
400
401    /* find which surface this context supports */
402    for (i = 0; i < adaptor->num_surfaces; i++) {
403        if (adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id) {
404            surface = adaptor->surfaces[i];
405            break;
406        }
407    }
408
409    if (!surface)
410        return BadMatch;
411
412    /* make sure this surface supports that xvimage format */
413    if (!surface->compatible_subpictures)
414        return BadMatch;
415
416    for (i = 0; i < surface->compatible_subpictures->num_xvimages; i++) {
417        if (surface->compatible_subpictures->xvimage_ids[i] ==
418            stuff->xvimage_id) {
419            image_supported = TRUE;
420            break;
421        }
422    }
423
424    if (!image_supported)
425        return BadMatch;
426
427    /* make sure the size is OK */
428    if ((stuff->width > surface->subpicture_max_width) ||
429        (stuff->height > surface->subpicture_max_height))
430        return BadValue;
431
432    if (!(pSubpicture = malloc(sizeof(XvMCSubpictureRec))))
433        return BadAlloc;
434
435    pSubpicture->subpicture_id = stuff->subpicture_id;
436    pSubpicture->xvimage_id = stuff->xvimage_id;
437    pSubpicture->width = stuff->width;
438    pSubpicture->height = stuff->height;
439    pSubpicture->num_palette_entries = 0;       /* overwritten by DDX */
440    pSubpicture->entry_bytes = 0;       /* overwritten by DDX */
441    pSubpicture->component_order[0] = 0;        /* overwritten by DDX */
442    pSubpicture->component_order[1] = 0;
443    pSubpicture->component_order[2] = 0;
444    pSubpicture->component_order[3] = 0;
445    pSubpicture->context = pContext;
446
447    result =
448        (*pScreenPriv->adaptors[pContext->adapt_num].
449         CreateSubpicture) (pSubpicture, &dwords, &data);
450
451    if (result != Success) {
452        free(pSubpicture);
453        return result;
454    }
455    if (!AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture)) {
456        free(data);
457        return BadAlloc;
458    }
459
460    rep = (xvmcCreateSubpictureReply) {
461        .type = X_Reply,
462        .sequenceNumber = client->sequence,
463        .length = dwords,
464        .width_actual = pSubpicture->width,
465        .height_actual = pSubpicture->height,
466        .num_palette_entries = pSubpicture->num_palette_entries,
467        .entry_bytes = pSubpicture->entry_bytes,
468        .component_order[0] = pSubpicture->component_order[0],
469        .component_order[1] = pSubpicture->component_order[1],
470        .component_order[2] = pSubpicture->component_order[2],
471        .component_order[3] = pSubpicture->component_order[3]
472    };
473
474    WriteToClient(client, sizeof(xvmcCreateSubpictureReply), &rep);
475    if (dwords)
476        WriteToClient(client, dwords << 2, data);
477
478    free(data);
479
480    pContext->refcnt++;
481
482    return Success;
483}
484
485static int
486ProcXvMCDestroySubpicture(ClientPtr client)
487{
488    void *val;
489    int rc;
490
491    REQUEST(xvmcDestroySubpictureReq);
492    REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq);
493
494    rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture,
495                                 client, DixDestroyAccess);
496    if (rc != Success)
497        return rc;
498
499    FreeResource(stuff->subpicture_id, RT_NONE);
500
501    return Success;
502}
503
504static int
505ProcXvMCListSubpictureTypes(ClientPtr client)
506{
507    XvPortPtr pPort;
508    xvmcListSubpictureTypesReply rep;
509    XvMCScreenPtr pScreenPriv;
510    ScreenPtr pScreen;
511    XvMCAdaptorPtr adaptor = NULL;
512    XvMCSurfaceInfoPtr surface = NULL;
513    xvImageFormatInfo info;
514    XvImagePtr pImage;
515    int i, j;
516
517    REQUEST(xvmcListSubpictureTypesReq);
518    REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq);
519
520    VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
521
522    pScreen = pPort->pAdaptor->pScreen;
523
524    if (!dixPrivateKeyRegistered(XvMCScreenKey))
525        return BadMatch;        /* No XvMC adaptors */
526
527    if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
528        return BadMatch;        /* None this screen */
529
530    for (i = 0; i < pScreenPriv->num_adaptors; i++) {
531        if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
532            adaptor = &(pScreenPriv->adaptors[i]);
533            break;
534        }
535    }
536
537    if (!adaptor)
538        return BadMatch;
539
540    for (i = 0; i < adaptor->num_surfaces; i++) {
541        if (adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
542            surface = adaptor->surfaces[i];
543            break;
544        }
545    }
546
547    if (!surface)
548        return BadMatch;
549
550    rep = (xvmcListSubpictureTypesReply) {
551        .type = X_Reply,
552        .sequenceNumber = client->sequence,
553        .num = 0
554    };
555    if (surface->compatible_subpictures)
556        rep.num = surface->compatible_subpictures->num_xvimages;
557
558    rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo));
559
560    WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), &rep);
561
562    for (i = 0; i < rep.num; i++) {
563        pImage = NULL;
564        for (j = 0; j < adaptor->num_subpictures; j++) {
565            if (surface->compatible_subpictures->xvimage_ids[i] ==
566                adaptor->subpictures[j]->id) {
567                pImage = adaptor->subpictures[j];
568                break;
569            }
570        }
571        if (!pImage)
572            return BadImplementation;
573
574        info.id = pImage->id;
575        info.type = pImage->type;
576        info.byte_order = pImage->byte_order;
577        memcpy(&info.guid, pImage->guid, 16);
578        info.bpp = pImage->bits_per_pixel;
579        info.num_planes = pImage->num_planes;
580        info.depth = pImage->depth;
581        info.red_mask = pImage->red_mask;
582        info.green_mask = pImage->green_mask;
583        info.blue_mask = pImage->blue_mask;
584        info.format = pImage->format;
585        info.y_sample_bits = pImage->y_sample_bits;
586        info.u_sample_bits = pImage->u_sample_bits;
587        info.v_sample_bits = pImage->v_sample_bits;
588        info.horz_y_period = pImage->horz_y_period;
589        info.horz_u_period = pImage->horz_u_period;
590        info.horz_v_period = pImage->horz_v_period;
591        info.vert_y_period = pImage->vert_y_period;
592        info.vert_u_period = pImage->vert_u_period;
593        info.vert_v_period = pImage->vert_v_period;
594        memcpy(&info.comp_order, pImage->component_order, 32);
595        info.scanline_order = pImage->scanline_order;
596        WriteToClient(client, sizeof(xvImageFormatInfo), &info);
597    }
598
599    return Success;
600}
601
602static int
603ProcXvMCGetDRInfo(ClientPtr client)
604{
605    xvmcGetDRInfoReply rep;
606    XvPortPtr pPort;
607    ScreenPtr pScreen;
608    XvMCScreenPtr pScreenPriv;
609
610#ifdef HAS_XVMCSHM
611    volatile CARD32 *patternP;
612#endif
613
614    REQUEST(xvmcGetDRInfoReq);
615    REQUEST_SIZE_MATCH(xvmcGetDRInfoReq);
616
617    VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
618
619    pScreen = pPort->pAdaptor->pScreen;
620    pScreenPriv = XVMC_GET_PRIVATE(pScreen);
621
622    rep = (xvmcGetDRInfoReply) {
623        .type = X_Reply,
624        .sequenceNumber = client->sequence,
625        .major = pScreenPriv->major,
626        .minor = pScreenPriv->minor,
627        .patchLevel = pScreenPriv->patchLevel,
628        .nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1),
629        .busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1),
630        .isLocal = 1
631    };
632
633    rep.length = rep.nameLen + rep.busIDLen;
634    rep.nameLen <<= 2;
635    rep.busIDLen <<= 2;
636
637    /*
638     * Read back to the client what she has put in the shared memory
639     * segment she prepared for us.
640     */
641
642#ifdef HAS_XVMCSHM
643    patternP = (CARD32 *) shmat(stuff->shmKey, NULL, SHM_RDONLY);
644    if (-1 != (long) patternP) {
645        volatile CARD32 *patternC = patternP;
646        int i;
647        CARD32 magic = stuff->magic;
648
649        rep.isLocal = 1;
650        i = 1024 / sizeof(CARD32);
651
652        while (i--) {
653            if (*patternC++ != magic) {
654                rep.isLocal = 0;
655                break;
656            }
657            magic = ~magic;
658        }
659        shmdt((char *) patternP);
660    }
661#endif                          /* HAS_XVMCSHM */
662
663    WriteToClient(client, sizeof(xvmcGetDRInfoReply), &rep);
664    if (rep.length) {
665        WriteToClient(client, rep.nameLen, pScreenPriv->clientDriverName);
666        WriteToClient(client, rep.busIDLen, pScreenPriv->busID);
667    }
668    return Success;
669}
670
671int (*ProcXvMCVector[xvmcNumRequest]) (ClientPtr) = {
672ProcXvMCQueryVersion,
673        ProcXvMCListSurfaceTypes,
674        ProcXvMCCreateContext,
675        ProcXvMCDestroyContext,
676        ProcXvMCCreateSurface,
677        ProcXvMCDestroySurface,
678        ProcXvMCCreateSubpicture,
679        ProcXvMCDestroySubpicture,
680        ProcXvMCListSubpictureTypes, ProcXvMCGetDRInfo};
681
682static int
683ProcXvMCDispatch(ClientPtr client)
684{
685    REQUEST(xReq);
686
687    if (stuff->data < xvmcNumRequest)
688        return (*ProcXvMCVector[stuff->data]) (client);
689    else
690        return BadRequest;
691}
692
693static int _X_COLD
694SProcXvMCDispatch(ClientPtr client)
695{
696    /* We only support local */
697    return BadImplementation;
698}
699
700void
701XvMCExtensionInit(void)
702{
703    ExtensionEntry *extEntry;
704
705    if (!dixPrivateKeyRegistered(XvMCScreenKey))
706        return;
707
708    if (!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes,
709                                                "XvMCRTContext")))
710        return;
711
712    if (!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes,
713                                                "XvMCRTSurface")))
714        return;
715
716    if (!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes,
717                                                   "XvMCRTSubpicture")))
718        return;
719
720    extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors,
721                            ProcXvMCDispatch, SProcXvMCDispatch,
722                            NULL, StandardMinorOpcode);
723
724    if (!extEntry)
725        return;
726
727    XvMCReqCode = extEntry->base;
728    XvMCEventBase = extEntry->eventBase;
729    SetResourceTypeErrorValue(XvMCRTContext,
730                              extEntry->errorBase + XvMCBadContext);
731    SetResourceTypeErrorValue(XvMCRTSurface,
732                              extEntry->errorBase + XvMCBadSurface);
733    SetResourceTypeErrorValue(XvMCRTSubpicture,
734                              extEntry->errorBase + XvMCBadSubpicture);
735}
736
737static Bool
738XvMCCloseScreen(ScreenPtr pScreen)
739{
740    XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
741
742    pScreen->CloseScreen = pScreenPriv->CloseScreen;
743
744    free(pScreenPriv);
745
746    return (*pScreen->CloseScreen) (pScreen);
747}
748
749int
750XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt)
751{
752    XvMCScreenPtr pScreenPriv;
753
754    if (!dixRegisterPrivateKey(&XvMCScreenKeyRec, PRIVATE_SCREEN, 0))
755        return BadAlloc;
756
757    if (!(pScreenPriv = malloc(sizeof(XvMCScreenRec))))
758        return BadAlloc;
759
760    dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, pScreenPriv);
761
762    pScreenPriv->CloseScreen = pScreen->CloseScreen;
763    pScreen->CloseScreen = XvMCCloseScreen;
764
765    pScreenPriv->num_adaptors = num;
766    pScreenPriv->adaptors = pAdapt;
767    pScreenPriv->clientDriverName[0] = 0;
768    pScreenPriv->busID[0] = 0;
769    pScreenPriv->major = 0;
770    pScreenPriv->minor = 0;
771    pScreenPriv->patchLevel = 0;
772
773    XvMCInUse = TRUE;
774
775    return Success;
776}
777
778XvImagePtr
779XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
780{
781    XvImagePtr pImage = NULL;
782    ScreenPtr pScreen = pPort->pAdaptor->pScreen;
783    XvMCScreenPtr pScreenPriv;
784    XvMCAdaptorPtr adaptor = NULL;
785    int i;
786
787    if (!dixPrivateKeyRegistered(XvMCScreenKey))
788        return NULL;
789
790    if (!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
791        return NULL;
792
793    for (i = 0; i < pScreenPriv->num_adaptors; i++) {
794        if (pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
795            adaptor = &(pScreenPriv->adaptors[i]);
796            break;
797        }
798    }
799
800    if (!adaptor)
801        return NULL;
802
803    for (i = 0; i < adaptor->num_subpictures; i++) {
804        if (adaptor->subpictures[i]->id == id) {
805            pImage = adaptor->subpictures[i];
806            break;
807        }
808    }
809
810    return pImage;
811}
812
813int
814xf86XvMCRegisterDRInfo(ScreenPtr pScreen, const char *name,
815                       const char *busID, int major, int minor, int patchLevel)
816{
817    XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
818
819    strlcpy(pScreenPriv->clientDriverName, name, DR_CLIENT_DRIVER_NAME_SIZE);
820    strlcpy(pScreenPriv->busID, busID, DR_BUSID_SIZE);
821    pScreenPriv->major = major;
822    pScreenPriv->minor = minor;
823    pScreenPriv->patchLevel = patchLevel;
824    return Success;
825}
826