xorg/vmwgfx: Don't use deprecated x*alloc / xfree functions
[mesa.git] / src / gallium / targets / xorg-vmwgfx / vmw_video.c
1 /*
2 * Copyright 2007 by VMware, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28 /*
29 * vmwarevideo.c --
30 *
31 * Xv extension support.
32 * See http://www.xfree86.org/current/DESIGN16.html
33 *
34 */
35
36
37 #include "xf86xv.h"
38 #include "fourcc.h"
39
40 #include "pipe/p_compiler.h"
41 /*
42 * We can't incude svga_types.h due to conflicting types for Bool.
43 */
44 typedef int64_t int64;
45 typedef uint64_t uint64;
46
47 typedef int32_t int32;
48 typedef uint32_t uint32;
49
50 typedef int16_t int16;
51 typedef uint16_t uint16;
52
53 typedef int8_t int8;
54 typedef uint8_t uint8;
55
56 #include "svga/include/svga_reg.h"
57 #include "svga/include/svga_escape.h"
58 #include "svga/include/svga_overlay.h"
59
60 #include "vmw_driver.h"
61
62 #include <X11/extensions/Xv.h>
63
64 #include "xf86drm.h"
65 #include "../../winsys/svga/drm/vmwgfx_drm.h"
66
67 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
68
69 /*
70 * Number of videos that can be played simultaneously
71 */
72 #define VMWARE_VID_NUM_PORTS 1
73
74 /*
75 * Using a dark shade as the default colorKey
76 */
77 #define VMWARE_VIDEO_COLORKEY 0x100701
78
79 /*
80 * Maximum dimensions
81 */
82 #define VMWARE_VID_MAX_WIDTH 2048
83 #define VMWARE_VID_MAX_HEIGHT 2048
84
85 #define VMWARE_VID_NUM_ENCODINGS 1
86 static XF86VideoEncodingRec vmwareVideoEncodings[] =
87 {
88 {
89 0,
90 "XV_IMAGE",
91 VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT,
92 {1, 1}
93 }
94 };
95
96 #define VMWARE_VID_NUM_FORMATS 2
97 static XF86VideoFormatRec vmwareVideoFormats[] =
98 {
99 { 16, TrueColor},
100 { 24, TrueColor}
101 };
102
103 #define VMWARE_VID_NUM_IMAGES 3
104 static XF86ImageRec vmwareVideoImages[] =
105 {
106 XVIMAGE_YV12,
107 XVIMAGE_YUY2,
108 XVIMAGE_UYVY
109 };
110
111 #define VMWARE_VID_NUM_ATTRIBUTES 2
112 static XF86AttributeRec vmwareVideoAttributes[] =
113 {
114 {
115 XvGettable | XvSettable,
116 0x000000,
117 0xffffff,
118 "XV_COLORKEY"
119 },
120 {
121 XvGettable | XvSettable,
122 0,
123 1,
124 "XV_AUTOPAINT_COLORKEY"
125 }
126 };
127
128 /*
129 * Video frames are stored in a circular list of buffers.
130 * Must be power or two, See vmw_video_port_play.
131 */
132 #define VMWARE_VID_NUM_BUFFERS 1
133
134 /*
135 * Defines the structure used to hold and pass video data to the host
136 */
137 struct vmw_video_buffer
138 {
139 unsigned handle;
140 int size;
141 void *data;
142 void *extra_data;
143 struct vmw_dma_buffer *buf;
144 };
145
146
147 /**
148 * Structure representing a single video stream, aka port.
149 *
150 * Ports maps one to one to a SVGA stream. Port is just
151 * what Xv calls a SVGA stream.
152 */
153 struct vmw_video_port
154 {
155 /*
156 * Function prototype same as XvPutImage.
157 *
158 * This is either set to vmw_video_port_init or vmw_video_port_play.
159 * At init this function is set to port_init. In port_init we set it
160 * to port_play and call it, after initializing the struct.
161 */
162 int (*play)(ScrnInfoPtr, struct vmw_video_port *,
163 short, short, short, short, short,
164 short, short, short, int, unsigned char*,
165 short, short, RegionPtr);
166
167 /* values to go into the SVGAOverlayUnit */
168 uint32 streamId;
169 uint32 colorKey;
170 uint32 flags;
171
172 /* round robin of buffers */
173 unsigned currBuf;
174 struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS];
175
176 /* properties that applies to all buffers */
177 int size;
178 int pitches[3];
179 int offsets[3];
180
181 /* things for X */
182 RegionRec clipBoxes;
183 Bool isAutoPaintColorkey;
184 };
185
186
187 /**
188 * Structure holding all the infromation for video.
189 */
190 struct vmw_video_private
191 {
192 int fd;
193
194 /** ports */
195 struct vmw_video_port port[VMWARE_VID_NUM_PORTS];
196
197 /** Used to store port pointers pointers */
198 DevUnion port_ptr[VMWARE_VID_NUM_PORTS];
199 };
200
201
202 /*
203 * Callback functions exported to Xv, prefixed with vmw_xv_*.
204 */
205 static int vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y,
206 short drw_x, short drw_y, short src_w, short src_h,
207 short drw_w, short drw_h, int image,
208 unsigned char *buf, short width, short height,
209 Bool sync, RegionPtr clipBoxes, pointer data,
210 DrawablePtr dst);
211 static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup);
212 static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format,
213 unsigned short *width,
214 unsigned short *height, int *pitches,
215 int *offsets);
216 static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
217 INT32 value, pointer data);
218 static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
219 INT32 *value, pointer data);
220 static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion,
221 short vid_w, short vid_h, short drw_w,
222 short drw_h, unsigned int *p_w,
223 unsigned int *p_h, pointer data);
224
225
226 /*
227 * Local functions.
228 */
229 static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw);
230
231 static int vmw_video_port_init(ScrnInfoPtr pScrn,
232 struct vmw_video_port *port,
233 short src_x, short src_y, short drw_x,
234 short drw_y, short src_w, short src_h,
235 short drw_w, short drw_h, int format,
236 unsigned char *buf, short width,
237 short height, RegionPtr clipBoxes);
238 static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port,
239 short src_x, short src_y, short drw_x,
240 short drw_y, short src_w, short src_h,
241 short drw_w, short drw_h, int format,
242 unsigned char *buf, short width,
243 short height, RegionPtr clipBoxes);
244 static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port);
245
246 static int vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size,
247 struct vmw_video_buffer *out);
248 static int vmw_video_buffer_free(struct vmw_customizer *vmw,
249 struct vmw_video_buffer *out);
250
251
252 /*
253 *-----------------------------------------------------------------------------
254 *
255 * vmw_video_init --
256 *
257 * Initializes Xv support.
258 *
259 * Results:
260 * TRUE on success, FALSE on error.
261 *
262 * Side effects:
263 * Xv support is initialized. Memory is allocated for all supported
264 * video streams.
265 *
266 *-----------------------------------------------------------------------------
267 */
268
269 Bool
270 vmw_video_init(struct vmw_customizer *vmw)
271 {
272 ScrnInfoPtr pScrn = vmw->pScrn;
273 ScreenPtr pScreen = pScrn->pScreen;
274 XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL;
275 XF86VideoAdaptorPtr newAdaptor = NULL;
276 int numAdaptors;
277 unsigned int ntot, nfree;
278
279 debug_printf("%s: enter\n", __func__);
280
281 if (vmw_ioctl_num_streams(vmw, &ntot, &nfree) != 0) {
282 debug_printf("No stream ioctl support\n");
283 return FALSE;
284 }
285
286 if (nfree == 0) {
287 debug_printf("No free streams\n");
288 return FALSE;
289 }
290
291 numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors);
292
293 newAdaptor = vmw_video_init_adaptor(pScrn, vmw);
294 if (!newAdaptor) {
295 debug_printf("Failed to initialize Xv extension\n");
296 return FALSE;
297 }
298
299 if (!numAdaptors) {
300 numAdaptors = 1;
301 overlayAdaptors = &newAdaptor;
302 } else {
303 newAdaptors = malloc((numAdaptors + 1) *
304 sizeof(XF86VideoAdaptorPtr*));
305 if (!newAdaptors) {
306 xf86XVFreeVideoAdaptorRec(newAdaptor);
307 return FALSE;
308 }
309
310 memcpy(newAdaptors, overlayAdaptors,
311 numAdaptors * sizeof(XF86VideoAdaptorPtr));
312 newAdaptors[numAdaptors++] = newAdaptor;
313 overlayAdaptors = newAdaptors;
314 }
315
316 if (!xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors)) {
317 debug_printf("Failed to initialize Xv extension\n");
318 xf86XVFreeVideoAdaptorRec(newAdaptor);
319 return FALSE;
320 }
321
322 if (newAdaptors) {
323 free(newAdaptors);
324 }
325
326 debug_printf("Initialized VMware Xv extension successfully\n");
327
328 return TRUE;
329 }
330
331
332 /*
333 *-----------------------------------------------------------------------------
334 *
335 * vmw_video_close --
336 *
337 * Unitializes video.
338 *
339 * Results:
340 * TRUE.
341 *
342 * Side effects:
343 * vmw->video_priv = NULL
344 *
345 *-----------------------------------------------------------------------------
346 */
347
348 Bool
349 vmw_video_close(struct vmw_customizer *vmw)
350 {
351 ScrnInfoPtr pScrn = vmw->pScrn;
352 struct vmw_video_private *video;
353 int i;
354
355 debug_printf("%s: enter\n", __func__);
356
357 video = vmw->video_priv;
358 if (!video)
359 return TRUE;
360
361 for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
362 /* make sure the port is stoped as well */
363 vmw_xv_stop_video(pScrn, &video->port[i], TRUE);
364 vmw_ioctl_unref_stream(vmw, video->port[i].streamId);
365 }
366
367 /* XXX: I'm sure this function is missing code for turning off Xv */
368
369 free(vmw->video_priv);
370 vmw->video_priv = NULL;
371
372 return TRUE;
373 }
374
375
376 /*
377 *-----------------------------------------------------------------------------
378 *
379 * vmw_video_stop_all --
380 *
381 * Stop all video streams from playing.
382 *
383 * Results:
384 * None.
385 *
386 * Side effects:
387 * All buffers are freed.
388 *
389 *-----------------------------------------------------------------------------
390 */
391
392 void vmw_video_stop_all(struct vmw_customizer *vmw)
393 {
394 ScrnInfoPtr pScrn = vmw->pScrn;
395 struct vmw_video_private *video = vmw->video_priv;
396 int i;
397
398 debug_printf("%s: enter\n", __func__);
399
400 if (!video)
401 return;
402
403 for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
404 vmw_xv_stop_video(pScrn, &video->port[i], TRUE);
405 }
406 }
407
408
409 /*
410 *-----------------------------------------------------------------------------
411 *
412 * vmw_video_init_adaptor --
413 *
414 * Initializes a XF86VideoAdaptor structure with the capabilities and
415 * functions supported by this video driver.
416 *
417 * Results:
418 * On success initialized XF86VideoAdaptor struct or NULL on error
419 *
420 * Side effects:
421 * None.
422 *
423 *-----------------------------------------------------------------------------
424 */
425
426 static XF86VideoAdaptorPtr
427 vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw)
428 {
429 XF86VideoAdaptorPtr adaptor;
430 struct vmw_video_private *video;
431 int i;
432
433 debug_printf("%s: enter \n", __func__);
434
435 adaptor = xf86XVAllocateVideoAdaptorRec(pScrn);
436 if (!adaptor) {
437 debug_printf("Not enough memory\n");
438 return NULL;
439 }
440
441 video = calloc(1, sizeof(*video));
442 if (!video) {
443 debug_printf("Not enough memory.\n");
444 xf86XVFreeVideoAdaptorRec(adaptor);
445 return NULL;
446 }
447
448 vmw->video_priv = video;
449
450 adaptor->type = XvInputMask | XvImageMask | XvWindowMask;
451 adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
452 adaptor->name = "VMware Video Engine";
453 adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS;
454 adaptor->pEncodings = vmwareVideoEncodings;
455 adaptor->nFormats = VMWARE_VID_NUM_FORMATS;
456 adaptor->pFormats = vmwareVideoFormats;
457 adaptor->nPorts = VMWARE_VID_NUM_PORTS;
458 adaptor->pPortPrivates = video->port_ptr;
459
460 for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
461 vmw_ioctl_claim_stream(vmw, &video->port[i].streamId);
462 video->port[i].play = vmw_video_port_init;
463 video->port[i].flags = SVGA_VIDEO_FLAG_COLORKEY;
464 video->port[i].colorKey = VMWARE_VIDEO_COLORKEY;
465 video->port[i].isAutoPaintColorkey = TRUE;
466 adaptor->pPortPrivates[i].ptr = &video->port[i];
467 }
468
469 adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES;
470 adaptor->pAttributes = vmwareVideoAttributes;
471
472 adaptor->nImages = VMWARE_VID_NUM_IMAGES;
473 adaptor->pImages = vmwareVideoImages;
474
475 adaptor->PutVideo = NULL;
476 adaptor->PutStill = NULL;
477 adaptor->GetVideo = NULL;
478 adaptor->GetStill = NULL;
479 adaptor->StopVideo = vmw_xv_stop_video;
480 adaptor->SetPortAttribute = vmw_xv_set_port_attribute;
481 adaptor->GetPortAttribute = vmw_xv_get_port_attribute;
482 adaptor->QueryBestSize = vmw_xv_query_best_size;
483 adaptor->PutImage = vmw_xv_put_image;
484 adaptor->QueryImageAttributes = vmw_xv_query_image_attributes;
485
486 debug_printf("%s: done %p\n", __func__, adaptor);
487
488 return adaptor;
489 }
490
491
492 /*
493 *-----------------------------------------------------------------------------
494 *
495 * vmw_video_port_init --
496 *
497 * Initializes a video stream in response to the first PutImage() on a
498 * video stream. The process goes as follows:
499 * - Figure out characteristics according to format
500 * - Allocate offscreen memory
501 * - Pass on video to Play() functions
502 *
503 * Results:
504 * Success or XvBadAlloc on failure.
505 *
506 * Side effects:
507 * Video stream is initialized and its first frame sent to the host
508 * (done by VideoPlay() function called at the end)
509 *
510 *-----------------------------------------------------------------------------
511 */
512
513 static int
514 vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port,
515 short src_x, short src_y, short drw_x,
516 short drw_y, short src_w, short src_h,
517 short drw_w, short drw_h, int format,
518 unsigned char *buf, short width,
519 short height, RegionPtr clipBoxes)
520 {
521 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
522 unsigned short w, h;
523 int i, ret;
524
525 debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format);
526
527 w = width;
528 h = height;
529 /* init all the format attributes, used for buffers */
530 port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h,
531 port->pitches, port->offsets);
532
533 if (port->size == -1)
534 return XvBadAlloc;
535
536 port->play = vmw_video_port_play;
537
538 for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) {
539 ret = vmw_video_buffer_alloc(vmw, port->size, &port->bufs[i]);
540 if (ret != Success)
541 break;
542 }
543
544 /* Free all allocated buffers on failure */
545 if (ret != Success) {
546 for (--i; i >= 0; --i) {
547 vmw_video_buffer_free(vmw, &port->bufs[i]);
548 }
549 return ret;
550 }
551
552 port->currBuf = 0;
553
554 REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes);
555
556 if (port->isAutoPaintColorkey)
557 xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes);
558
559 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h,
560 drw_w, drw_h, format, buf, width, height, clipBoxes);
561 }
562
563
564 /*
565 *-----------------------------------------------------------------------------
566 *
567 * vmw_video_port_play --
568 *
569 * Sends all the attributes associated with the video frame using the
570 * FIFO ESCAPE mechanism to the host.
571 *
572 * Results:
573 * Always returns Success.
574 *
575 * Side effects:
576 * None.
577 *
578 *-----------------------------------------------------------------------------
579 */
580
581 static int
582 vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port,
583 short src_x, short src_y, short drw_x,
584 short drw_y, short src_w, short src_h,
585 short drw_w, short drw_h, int format,
586 unsigned char *buf, short width,
587 short height, RegionPtr clipBoxes)
588 {
589 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
590 struct drm_vmw_control_stream_arg arg;
591 unsigned short w, h;
592 int size;
593 int ret;
594
595 debug_printf("\t%s: enter\n", __func__);
596
597 w = width;
598 h = height;
599
600 /* we don't update the ports size */
601 size = vmw_xv_query_image_attributes(pScrn, format, &w, &h,
602 port->pitches, port->offsets);
603
604 if (size > port->size) {
605 debug_printf("\t%s: Increase in size of Xv video frame streamId:%d.\n",
606 __func__, port->streamId);
607 vmw_xv_stop_video(pScrn, port, TRUE);
608 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w,
609 src_h, drw_w, drw_h, format, buf, width, height,
610 clipBoxes);
611 }
612
613 memcpy(port->bufs[port->currBuf].data, buf, port->size);
614
615 memset(&arg, 0, sizeof(arg));
616
617 arg.stream_id = port->streamId;
618 arg.enabled = TRUE;
619 arg.flags = port->flags;
620 arg.color_key = port->colorKey;
621 arg.handle = port->bufs[port->currBuf].handle;
622 arg.format = format;
623 arg.size = port->size;
624 arg.width = w;
625 arg.height = h;
626 arg.src.x = src_x;
627 arg.src.y = src_y;
628 arg.src.w = src_w;
629 arg.src.h = src_h;
630 arg.dst.x = drw_x;
631 arg.dst.y = drw_y;
632 arg.dst.w = drw_w;
633 arg.dst.h = drw_h;
634 arg.pitch[0] = port->pitches[0];
635 arg.pitch[1] = port->pitches[1];
636 arg.pitch[2] = port->pitches[2];
637 arg.offset = 0;
638
639 /*
640 * Update the clipList and paint the colorkey, if required.
641 */
642 if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) {
643 REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes);
644 if (port->isAutoPaintColorkey) {
645 xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes);
646 }
647 }
648
649 ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg));
650 if (ret) {
651 vmw_video_port_cleanup(pScrn, port);
652 return XvBadAlloc;
653 }
654
655 if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS)
656 port->currBuf = 0;
657
658 return Success;
659 }
660
661
662 /*
663 *-----------------------------------------------------------------------------
664 *
665 * vmw_video_port_cleanup --
666 *
667 * Frees up all resources (if any) taken by a video stream.
668 *
669 * Results:
670 * None.
671 *
672 * Side effects:
673 * Same as above.
674 *
675 *-----------------------------------------------------------------------------
676 */
677
678 static void
679 vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port)
680 {
681 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
682 uint32 id, colorKey, flags;
683 Bool isAutoPaintColorkey;
684 int i;
685
686 debug_printf("\t%s: enter\n", __func__);
687
688 for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) {
689 vmw_video_buffer_free(vmw, &port->bufs[i]);
690 }
691
692 /*
693 * reset stream for next video
694 */
695 id = port->streamId;
696 colorKey = port->colorKey;
697 flags = port->flags;
698 isAutoPaintColorkey = port->isAutoPaintColorkey;
699
700 memset(port, 0, sizeof(*port));
701
702 port->streamId = id;
703 port->play = vmw_video_port_init;
704 port->colorKey = colorKey;
705 port->flags = flags;
706 port->isAutoPaintColorkey = isAutoPaintColorkey;
707 }
708
709
710 /*
711 *-----------------------------------------------------------------------------
712 *
713 * vmw_video_buffer_alloc --
714 *
715 * Allocates and map a kernel buffer to be used as data storage.
716 *
717 * Results:
718 * XvBadAlloc on failure, otherwise Success.
719 *
720 * Side effects:
721 * Calls into the kernel, sets members of out.
722 *
723 *-----------------------------------------------------------------------------
724 */
725
726 static int
727 vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size,
728 struct vmw_video_buffer *out)
729 {
730 out->buf = vmw_ioctl_buffer_create(vmw, size, &out->handle);
731 if (!out->buf)
732 return XvBadAlloc;
733
734 out->data = vmw_ioctl_buffer_map(vmw, out->buf);
735 if (!out->data) {
736 vmw_ioctl_buffer_destroy(vmw, out->buf);
737
738 out->handle = 0;
739 out->buf = NULL;
740
741 return XvBadAlloc;
742 }
743
744 out->size = size;
745 out->extra_data = calloc(1, size);
746
747 debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size);
748
749 return Success;
750 }
751
752
753 /*
754 *-----------------------------------------------------------------------------
755 *
756 * vmw_video_buffer_free --
757 *
758 * Frees and unmaps an allocated kernel buffer.
759 *
760 * Results:
761 * Success.
762 *
763 * Side effects:
764 * Calls into the kernel, sets members of out to 0.
765 *
766 *-----------------------------------------------------------------------------
767 */
768
769 static int
770 vmw_video_buffer_free(struct vmw_customizer *vmw,
771 struct vmw_video_buffer *out)
772 {
773 if (out->size == 0)
774 return Success;
775
776 free(out->extra_data);
777 vmw_ioctl_buffer_unmap(vmw, out->buf);
778 vmw_ioctl_buffer_destroy(vmw, out->buf);
779
780 out->buf = NULL;
781 out->data = NULL;
782 out->handle = 0;
783 out->size = 0;
784
785 debug_printf("\t\t%s: freed buffer %p\n", __func__, out);
786
787 return Success;
788 }
789
790
791 /*
792 *-----------------------------------------------------------------------------
793 *
794 * vmw_xv_put_image --
795 *
796 * Main video playback function. It copies the passed data which is in
797 * the specified format (e.g. FOURCC_YV12) into the overlay.
798 *
799 * If sync is TRUE the driver should not return from this
800 * function until it is through reading the data from buf.
801 *
802 * Results:
803 * Success or XvBadAlloc on failure
804 *
805 * Side effects:
806 * Video port will be played(initialized if 1st frame) on success
807 * or will fail on error.
808 *
809 *-----------------------------------------------------------------------------
810 */
811
812 static int
813 vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y,
814 short drw_x, short drw_y, short src_w, short src_h,
815 short drw_w, short drw_h, int format,
816 unsigned char *buf, short width, short height,
817 Bool sync, RegionPtr clipBoxes, pointer data,
818 DrawablePtr dst)
819 {
820 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
821 struct vmw_video_port *port = data;
822
823 debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__,
824 src_x, src_y, src_w, src_h,
825 drw_x, drw_y, drw_w, drw_h,
826 width, height);
827
828 if (!vmw->video_priv)
829 return XvBadAlloc;
830
831 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h,
832 drw_w, drw_h, format, buf, width, height, clipBoxes);
833 }
834
835
836 /*
837 *-----------------------------------------------------------------------------
838 *
839 * vmw_xv_stop_video --
840 *
841 * Called when we should stop playing video for a particular stream. If
842 * Cleanup is FALSE, the "stop" operation is only temporary, and thus we
843 * don't do anything. If Cleanup is TRUE we kill the video port by
844 * sending a message to the host and freeing up the stream.
845 *
846 * Results:
847 * None.
848 *
849 * Side effects:
850 * See above.
851 *
852 *-----------------------------------------------------------------------------
853 */
854
855 static void
856 vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
857 {
858 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
859 struct vmw_video_port *port = data;
860 struct drm_vmw_control_stream_arg arg;
861 int ret;
862
863 debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE");
864
865 if (!vmw->video_priv)
866 return;
867
868 if (!cleanup)
869 return;
870
871
872 memset(&arg, 0, sizeof(arg));
873 arg.stream_id = port->streamId;
874 arg.enabled = FALSE;
875
876 ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg));
877 assert(ret == 0);
878
879 vmw_video_port_cleanup(pScrn, port);
880 }
881
882
883 /*
884 *-----------------------------------------------------------------------------
885 *
886 * vmw_xv_query_image_attributes --
887 *
888 * From the spec: This function is called to let the driver specify how data
889 * for a particular image of size width by height should be stored.
890 * Sometimes only the size and corrected width and height are needed. In
891 * that case pitches and offsets are NULL.
892 *
893 * Results:
894 * The size of the memory required for the image, or -1 on error.
895 *
896 * Side effects:
897 * None.
898 *
899 *-----------------------------------------------------------------------------
900 */
901
902 static int
903 vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format,
904 unsigned short *width, unsigned short *height,
905 int *pitches, int *offsets)
906 {
907 INT32 size, tmp;
908
909 if (*width > VMWARE_VID_MAX_WIDTH) {
910 *width = VMWARE_VID_MAX_WIDTH;
911 }
912 if (*height > VMWARE_VID_MAX_HEIGHT) {
913 *height = VMWARE_VID_MAX_HEIGHT;
914 }
915
916 *width = (*width + 1) & ~1;
917 if (offsets != NULL) {
918 offsets[0] = 0;
919 }
920
921 switch (format) {
922 case FOURCC_YV12:
923 *height = (*height + 1) & ~1;
924 size = (*width + 3) & ~3;
925 if (pitches) {
926 pitches[0] = size;
927 }
928 size *= *height;
929 if (offsets) {
930 offsets[1] = size;
931 }
932 tmp = ((*width >> 1) + 3) & ~3;
933 if (pitches) {
934 pitches[1] = pitches[2] = tmp;
935 }
936 tmp *= (*height >> 1);
937 size += tmp;
938 if (offsets) {
939 offsets[2] = size;
940 }
941 size += tmp;
942 break;
943 case FOURCC_UYVY:
944 case FOURCC_YUY2:
945 size = *width * 2;
946 if (pitches) {
947 pitches[0] = size;
948 }
949 size *= *height;
950 break;
951 default:
952 debug_printf("Query for invalid video format %d\n", format);
953 return -1;
954 }
955 return size;
956 }
957
958
959 /*
960 *-----------------------------------------------------------------------------
961 *
962 * vmw_xv_set_port_attribute --
963 *
964 * From the spec: A port may have particular attributes such as colorKey, hue,
965 * saturation, brightness or contrast. Xv clients set these
966 * attribute values by sending attribute strings (Atoms) to the server.
967 *
968 * Results:
969 * Success if the attribute exists and XvBadAlloc otherwise.
970 *
971 * Side effects:
972 * The respective attribute gets the new value.
973 *
974 *-----------------------------------------------------------------------------
975 */
976
977 static int
978 vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
979 INT32 value, pointer data)
980 {
981 struct vmw_video_port *port = data;
982 Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
983 Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
984
985 if (attribute == xvColorKey) {
986 debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value);
987 port->colorKey = value;
988 } else if (attribute == xvAutoPaint) {
989 debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE");
990 port->isAutoPaintColorkey = value;
991 } else {
992 return XvBadAlloc;
993 }
994
995 return Success;
996 }
997
998
999 /*
1000 *-----------------------------------------------------------------------------
1001 *
1002 * vmw_xv_get_port_attribute --
1003 *
1004 * From the spec: A port may have particular attributes such as hue,
1005 * saturation, brightness or contrast. Xv clients get these
1006 * attribute values by sending attribute strings (Atoms) to the server
1007 *
1008 * Results:
1009 * Success if the attribute exists and XvBadAlloc otherwise.
1010 *
1011 * Side effects:
1012 * "value" contains the requested attribute on success.
1013 *
1014 *-----------------------------------------------------------------------------
1015 */
1016
1017 static int
1018 vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
1019 INT32 *value, pointer data)
1020 {
1021 struct vmw_video_port *port = data;
1022 Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
1023 Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1024
1025 if (attribute == xvColorKey) {
1026 *value = port->colorKey;
1027 } else if (attribute == xvAutoPaint) {
1028 *value = port->isAutoPaintColorkey;
1029 } else {
1030 return XvBadAlloc;
1031 }
1032
1033 return Success;
1034 }
1035
1036
1037 /*
1038 *-----------------------------------------------------------------------------
1039 *
1040 * vmw_xv_query_best_size --
1041 *
1042 * From the spec: QueryBestSize provides the client with a way to query what
1043 * the destination dimensions would end up being if they were to request
1044 * that an area vid_w by vid_h from the video stream be scaled to rectangle
1045 * of drw_w by drw_h on the screen. Since it is not expected that all
1046 * hardware will be able to get the target dimensions exactly, it is
1047 * important that the driver provide this function.
1048 *
1049 * This function seems to never be called, but to be on the safe side
1050 * we apply the same logic that QueryImageAttributes has for width
1051 * and height.
1052 *
1053 * Results:
1054 * None.
1055 *
1056 * Side effects:
1057 * None.
1058 *
1059 *-----------------------------------------------------------------------------
1060 */
1061
1062 static void
1063 vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion,
1064 short vid_w, short vid_h, short drw_w,
1065 short drw_h, unsigned int *p_w,
1066 unsigned int *p_h, pointer data)
1067 {
1068 *p_w = (drw_w + 1) & ~1;
1069 *p_h = drw_h;
1070
1071 return;
1072 }