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