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 
35 static DevPrivateKeyRec XvMCScreenKeyRec;
36 
37 #define XvMCScreenKey (&XvMCScreenKeyRec)
38 static Bool XvMCInUse;
39 
40 int XvMCReqCode;
41 int XvMCEventBase;
42 
43 static RESTYPE XvMCRTContext;
44 static RESTYPE XvMCRTSurface;
45 static RESTYPE XvMCRTSubpicture;
46 
47 int (*XvMCScreenInitProc)(ScreenPtr, int, XvMCAdaptorPtr) = NULL;
48 
49 typedef 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 static int
XvMCDestroyContextRes(void * data,XID id)64 XvMCDestroyContextRes(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 
80 static int
XvMCDestroySurfaceRes(void * data,XID id)81 XvMCDestroySurfaceRes(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 
95 static int
XvMCDestroySubpictureRes(void * data,XID id)96 XvMCDestroySubpictureRes(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 
110 static int
ProcXvMCQueryVersion(ClientPtr client)111 ProcXvMCQueryVersion(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 
128 static int
ProcXvMCListSurfaceTypes(ClientPtr client)129 ProcXvMCListSurfaceTypes(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 
184 static int
ProcXvMCCreateContext(ClientPtr client)185 ProcXvMCCreateContext(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 
279 static int
ProcXvMCDestroyContext(ClientPtr client)280 ProcXvMCDestroyContext(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 
298 static int
ProcXvMCCreateSurface(ClientPtr client)299 ProcXvMCCreateSurface(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 
357 static int
ProcXvMCDestroySurface(ClientPtr client)358 ProcXvMCDestroySurface(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 
376 static int
ProcXvMCCreateSubpicture(ClientPtr client)377 ProcXvMCCreateSubpicture(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 
485 static int
ProcXvMCDestroySubpicture(ClientPtr client)486 ProcXvMCDestroySubpicture(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 
504 static int
ProcXvMCListSubpictureTypes(ClientPtr client)505 ProcXvMCListSubpictureTypes(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 
602 static int
ProcXvMCGetDRInfo(ClientPtr client)603 ProcXvMCGetDRInfo(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 
671 int (*ProcXvMCVector[xvmcNumRequest]) (ClientPtr) = {
672 ProcXvMCQueryVersion,
673         ProcXvMCListSurfaceTypes,
674         ProcXvMCCreateContext,
675         ProcXvMCDestroyContext,
676         ProcXvMCCreateSurface,
677         ProcXvMCDestroySurface,
678         ProcXvMCCreateSubpicture,
679         ProcXvMCDestroySubpicture,
680         ProcXvMCListSubpictureTypes, ProcXvMCGetDRInfo};
681 
682 static int
ProcXvMCDispatch(ClientPtr client)683 ProcXvMCDispatch(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 
693 static int _X_COLD
SProcXvMCDispatch(ClientPtr client)694 SProcXvMCDispatch(ClientPtr client)
695 {
696     /* We only support local */
697     return BadImplementation;
698 }
699 
700 void
XvMCExtensionInit(void)701 XvMCExtensionInit(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 
737 static Bool
XvMCCloseScreen(ScreenPtr pScreen)738 XvMCCloseScreen(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 
749 int
XvMCScreenInit(ScreenPtr pScreen,int num,XvMCAdaptorPtr pAdapt)750 XvMCScreenInit(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 
778 XvImagePtr
XvMCFindXvImage(XvPortPtr pPort,CARD32 id)779 XvMCFindXvImage(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 
813 int
xf86XvMCRegisterDRInfo(ScreenPtr pScreen,const char * name,const char * busID,int major,int minor,int patchLevel)814 xf86XvMCRegisterDRInfo(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