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