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