diff options
Diffstat (limited to 'vmwgfx/vmwgfx_overlay.c')
-rw-r--r-- | vmwgfx/vmwgfx_overlay.c | 893 |
1 files changed, 893 insertions, 0 deletions
diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c new file mode 100644 index 0000000..6624a10 --- /dev/null +++ b/vmwgfx/vmwgfx_overlay.c | |||
@@ -0,0 +1,893 @@ | |||
1 | /* | ||
2 | * Copyright 2007-2011 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 | /* | ||
30 | * vmwarevideo.c -- | ||
31 | * | ||
32 | * Xv extension support. | ||
33 | * See http://www.xfree86.org/current/DESIGN16.html | ||
34 | * | ||
35 | */ | ||
36 | |||
37 | |||
38 | #include "xf86xv.h" | ||
39 | #include "fourcc.h" | ||
40 | #define debug_printf(...) | ||
41 | |||
42 | /* | ||
43 | * We can't incude svga_types.h due to conflicting types for Bool. | ||
44 | */ | ||
45 | typedef int64_t int64; | ||
46 | typedef uint64_t uint64; | ||
47 | |||
48 | typedef int32_t int32; | ||
49 | typedef uint32_t uint32; | ||
50 | |||
51 | typedef int16_t int16; | ||
52 | typedef uint16_t uint16; | ||
53 | |||
54 | typedef int8_t int8; | ||
55 | typedef uint8_t uint8; | ||
56 | |||
57 | #include "../src/svga_reg.h" | ||
58 | #include "../src/svga_escape.h" | ||
59 | #include "../src/svga_overlay.h" | ||
60 | |||
61 | #include <X11/extensions/Xv.h> | ||
62 | |||
63 | #include "xf86drm.h" | ||
64 | #include "vmwgfx_drm.h" | ||
65 | #include "vmwgfx_drmi.h" | ||
66 | #include "vmwgfx_driver.h" | ||
67 | |||
68 | #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) | ||
69 | |||
70 | /* | ||
71 | * Number of videos that can be played simultaneously | ||
72 | */ | ||
73 | #define VMWARE_VID_NUM_PORTS 1 | ||
74 | |||
75 | /* | ||
76 | * Using a dark shade as the default colorKey | ||
77 | */ | ||
78 | #define VMWARE_VIDEO_COLORKEY 0x100701 | ||
79 | |||
80 | /* | ||
81 | * Maximum dimensions | ||
82 | */ | ||
83 | #define VMWARE_VID_MAX_WIDTH 2048 | ||
84 | #define VMWARE_VID_MAX_HEIGHT 2048 | ||
85 | |||
86 | #define VMWARE_VID_NUM_ENCODINGS 1 | ||
87 | static XF86VideoEncodingRec vmwareVideoEncodings[] = | ||
88 | { | ||
89 | { | ||
90 | 0, | ||
91 | "XV_IMAGE", | ||
92 | VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT, | ||
93 | {1, 1} | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | #define VMWARE_VID_NUM_FORMATS 2 | ||
98 | static XF86VideoFormatRec vmwareVideoFormats[] = | ||
99 | { | ||
100 | { 16, TrueColor}, | ||
101 | { 24, TrueColor} | ||
102 | }; | ||
103 | |||
104 | #define VMWARE_VID_NUM_IMAGES 3 | ||
105 | static XF86ImageRec vmwareVideoImages[] = | ||
106 | { | ||
107 | XVIMAGE_YV12, | ||
108 | XVIMAGE_YUY2, | ||
109 | XVIMAGE_UYVY | ||
110 | }; | ||
111 | |||
112 | #define VMWARE_VID_NUM_ATTRIBUTES 2 | ||
113 | static XF86AttributeRec vmwareVideoAttributes[] = | ||
114 | { | ||
115 | { | ||
116 | XvGettable | XvSettable, | ||
117 | 0x000000, | ||
118 | 0xffffff, | ||
119 | "XV_COLORKEY" | ||
120 | }, | ||
121 | { | ||
122 | XvGettable | XvSettable, | ||
123 | 0, | ||
124 | 1, | ||
125 | "XV_AUTOPAINT_COLORKEY" | ||
126 | } | ||
127 | }; | ||
128 | |||
129 | /* | ||
130 | * Video frames are stored in a circular list of buffers. | ||
131 | * Must be power or two, See vmw_video_port_play. | ||
132 | */ | ||
133 | #define VMWARE_VID_NUM_BUFFERS 1 | ||
134 | |||
135 | /* | ||
136 | * Defines the structure used to hold and pass video data to the host | ||
137 | */ | ||
138 | struct vmw_video_buffer | ||
139 | { | ||
140 | int size; | ||
141 | void *data; | ||
142 | struct vmwgfx_dmabuf *buf; | ||
143 | }; | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Structure representing a single video stream, aka port. | ||
148 | * | ||
149 | * Ports maps one to one to a SVGA stream. Port is just | ||
150 | * what Xv calls a SVGA stream. | ||
151 | */ | ||
152 | struct vmwgfx_overlay_port | ||
153 | { | ||
154 | /* | ||
155 | * Function prototype same as XvPutImage. | ||
156 | * | ||
157 | * This is either set to vmw_video_port_init or vmw_video_port_play. | ||
158 | * At init this function is set to port_init. In port_init we set it | ||
159 | * to port_play and call it, after initializing the struct. | ||
160 | */ | ||
161 | int (*play)(ScrnInfoPtr, struct vmwgfx_overlay_port *, | ||
162 | short, short, short, short, short, | ||
163 | short, short, short, int, unsigned char*, | ||
164 | short, short, RegionPtr); | ||
165 | |||
166 | /* values to go into the SVGAOverlayUnit */ | ||
167 | uint32 streamId; | ||
168 | uint32 colorKey; | ||
169 | uint32 flags; | ||
170 | |||
171 | /* round robin of buffers */ | ||
172 | unsigned currBuf; | ||
173 | struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS]; | ||
174 | |||
175 | /* properties that applies to all buffers */ | ||
176 | int size; | ||
177 | int pitches[3]; | ||
178 | int offsets[3]; | ||
179 | |||
180 | /* things for X */ | ||
181 | RegionRec clipBoxes; | ||
182 | Bool isAutoPaintColorkey; | ||
183 | int drm_fd; | ||
184 | }; | ||
185 | |||
186 | /* | ||
187 | * Callback functions exported to Xv, prefixed with vmw_xv_*. | ||
188 | */ | ||
189 | static int vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, | ||
190 | short drw_x, short drw_y, short src_w, short src_h, | ||
191 | short drw_w, short drw_h, int image, | ||
192 | unsigned char *buf, short width, short height, | ||
193 | Bool sync, RegionPtr clipBoxes, pointer data, | ||
194 | DrawablePtr dst); | ||
195 | static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); | ||
196 | static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, | ||
197 | unsigned short *width, | ||
198 | unsigned short *height, int *pitches, | ||
199 | int *offsets); | ||
200 | static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, | ||
201 | INT32 value, pointer data); | ||
202 | static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, | ||
203 | INT32 *value, pointer data); | ||
204 | static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, | ||
205 | short vid_w, short vid_h, short drw_w, | ||
206 | short drw_h, unsigned int *p_w, | ||
207 | unsigned int *p_h, pointer data); | ||
208 | |||
209 | |||
210 | /* | ||
211 | * Local functions. | ||
212 | */ | ||
213 | static int vmw_video_port_init(ScrnInfoPtr pScrn, | ||
214 | struct vmwgfx_overlay_port *port, | ||
215 | short src_x, short src_y, short drw_x, | ||
216 | short drw_y, short src_w, short src_h, | ||
217 | short drw_w, short drw_h, int format, | ||
218 | unsigned char *buf, short width, | ||
219 | short height, RegionPtr clipBoxes); | ||
220 | static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, | ||
221 | short src_x, short src_y, short drw_x, | ||
222 | short drw_y, short src_w, short src_h, | ||
223 | short drw_w, short drw_h, int format, | ||
224 | unsigned char *buf, short width, | ||
225 | short height, RegionPtr clipBoxes); | ||
226 | static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port); | ||
227 | |||
228 | static int vmw_video_buffer_alloc(int drm_fd, int size, | ||
229 | struct vmw_video_buffer *out); | ||
230 | static int vmw_video_buffer_free(struct vmw_video_buffer *out); | ||
231 | |||
232 | |||
233 | static struct vmwgfx_overlay_port * | ||
234 | vmwgfx_overlay_port_create(int drm_fd, ScreenPtr pScreen) | ||
235 | { | ||
236 | struct vmwgfx_overlay_port *port = calloc(1, sizeof(*port)); | ||
237 | |||
238 | if (!port) | ||
239 | return NULL; | ||
240 | |||
241 | port->drm_fd = drm_fd; | ||
242 | port->play = vmw_video_port_init; | ||
243 | port->flags = SVGA_VIDEO_FLAG_COLORKEY; | ||
244 | port->colorKey = VMWARE_VIDEO_COLORKEY; | ||
245 | port->isAutoPaintColorkey = TRUE; | ||
246 | return port; | ||
247 | } | ||
248 | |||
249 | void | ||
250 | vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) | ||
251 | { | ||
252 | if (free_ports) { | ||
253 | int i; | ||
254 | |||
255 | for(i=0; i<adaptor->nPorts; ++i) { | ||
256 | free(adaptor->pPortPrivates[i].ptr); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | free(adaptor->pPortPrivates); | ||
261 | xf86XVFreeVideoAdaptorRec(adaptor); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | *----------------------------------------------------------------------------- | ||
266 | * | ||
267 | * vmw_video_init_adaptor -- | ||
268 | * | ||
269 | * Initializes a XF86VideoAdaptor structure with the capabilities and | ||
270 | * functions supported by this video driver. | ||
271 | * | ||
272 | * Results: | ||
273 | * On success initialized XF86VideoAdaptor struct or NULL on error | ||
274 | * | ||
275 | * Side effects: | ||
276 | * None. | ||
277 | * | ||
278 | *----------------------------------------------------------------------------- | ||
279 | */ | ||
280 | |||
281 | XF86VideoAdaptorPtr | ||
282 | vmw_video_init_adaptor(ScrnInfoPtr pScrn) | ||
283 | { | ||
284 | XF86VideoAdaptorPtr adaptor; | ||
285 | modesettingPtr ms = modesettingPTR(pScrn); | ||
286 | int i; | ||
287 | DevUnion *dev_unions; | ||
288 | uint32_t ntot, nfree; | ||
289 | |||
290 | if (vmwgfx_num_streams(ms->fd, &ntot, &nfree) != 0) { | ||
291 | debug_printf("No stream ioctl support\n"); | ||
292 | return NULL; | ||
293 | } | ||
294 | if (nfree == 0) { | ||
295 | debug_printf("No free streams\n"); | ||
296 | return NULL; | ||
297 | } | ||
298 | adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); | ||
299 | dev_unions = calloc(VMWARE_VID_NUM_PORTS, sizeof(DevUnion)); | ||
300 | if (adaptor == NULL || dev_unions == NULL) { | ||
301 | xf86XVFreeVideoAdaptorRec(adaptor); | ||
302 | free(dev_unions); | ||
303 | return NULL; | ||
304 | } | ||
305 | |||
306 | adaptor->type = XvInputMask | XvImageMask | XvWindowMask; | ||
307 | |||
308 | /** | ||
309 | * Note: CLIP_TO_VIEWPORT was removed from the flags, since with the | ||
310 | * crtc/output based modesetting, the viewport is not updated on | ||
311 | * RandR modeswitches. Hence the video may incorrectly be clipped away. | ||
312 | * The correct approach, (if needed) would be to clip against the | ||
313 | * scanout area union of all active crtcs. Revisit if needed. | ||
314 | */ | ||
315 | |||
316 | adaptor->flags = VIDEO_OVERLAID_IMAGES; | ||
317 | adaptor->name = "VMware Overlay Video Engine"; | ||
318 | adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS; | ||
319 | adaptor->pEncodings = vmwareVideoEncodings; | ||
320 | adaptor->nFormats = VMWARE_VID_NUM_FORMATS; | ||
321 | adaptor->pFormats = vmwareVideoFormats; | ||
322 | adaptor->nPorts = VMWARE_VID_NUM_PORTS; | ||
323 | adaptor->pPortPrivates = dev_unions; | ||
324 | |||
325 | for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { | ||
326 | struct vmwgfx_overlay_port *priv = | ||
327 | vmwgfx_overlay_port_create(ms->fd, pScrn->pScreen); | ||
328 | |||
329 | adaptor->pPortPrivates[i].ptr = (pointer) priv; | ||
330 | } | ||
331 | |||
332 | adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES; | ||
333 | adaptor->pAttributes = vmwareVideoAttributes; | ||
334 | adaptor->nImages = VMWARE_VID_NUM_IMAGES; | ||
335 | adaptor->pImages = vmwareVideoImages; | ||
336 | |||
337 | adaptor->PutVideo = NULL; | ||
338 | adaptor->PutStill = NULL; | ||
339 | adaptor->GetVideo = NULL; | ||
340 | adaptor->GetStill = NULL; | ||
341 | adaptor->StopVideo = vmw_xv_stop_video; | ||
342 | adaptor->SetPortAttribute = vmw_xv_set_port_attribute; | ||
343 | adaptor->GetPortAttribute = vmw_xv_get_port_attribute; | ||
344 | adaptor->QueryBestSize = vmw_xv_query_best_size; | ||
345 | adaptor->PutImage = vmw_xv_put_image; | ||
346 | adaptor->QueryImageAttributes = vmw_xv_query_image_attributes; | ||
347 | |||
348 | return adaptor; | ||
349 | } | ||
350 | |||
351 | |||
352 | /* | ||
353 | *----------------------------------------------------------------------------- | ||
354 | * | ||
355 | * vmw_video_port_init -- | ||
356 | * | ||
357 | * Initializes a video stream in response to the first PutImage() on a | ||
358 | * video stream. The process goes as follows: | ||
359 | * - Figure out characteristics according to format | ||
360 | * - Allocate offscreen memory | ||
361 | * - Pass on video to Play() functions | ||
362 | * | ||
363 | * Results: | ||
364 | * Success or XvBadAlloc on failure. | ||
365 | * | ||
366 | * Side effects: | ||
367 | * Video stream is initialized and its first frame sent to the host | ||
368 | * (done by VideoPlay() function called at the end) | ||
369 | * | ||
370 | *----------------------------------------------------------------------------- | ||
371 | */ | ||
372 | |||
373 | static int | ||
374 | vmw_video_port_init(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, | ||
375 | short src_x, short src_y, short drw_x, | ||
376 | short drw_y, short src_w, short src_h, | ||
377 | short drw_w, short drw_h, int format, | ||
378 | unsigned char *buf, short width, | ||
379 | short height, RegionPtr clipBoxes) | ||
380 | { | ||
381 | unsigned short w, h; | ||
382 | int i, ret; | ||
383 | |||
384 | debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format); | ||
385 | |||
386 | ret = vmwgfx_claim_stream(port->drm_fd, &port->streamId); | ||
387 | if (ret != 0) | ||
388 | return XvBadAlloc; | ||
389 | |||
390 | w = width; | ||
391 | h = height; | ||
392 | /* init all the format attributes, used for buffers */ | ||
393 | port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, | ||
394 | port->pitches, port->offsets); | ||
395 | |||
396 | if (port->size == -1) { | ||
397 | ret = XvBadAlloc; | ||
398 | goto out_bad_size; | ||
399 | } | ||
400 | |||
401 | for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) { | ||
402 | ret = vmw_video_buffer_alloc(port->drm_fd, port->size, &port->bufs[i]); | ||
403 | if (ret != Success) | ||
404 | goto out_no_buffer; | ||
405 | } | ||
406 | |||
407 | port->currBuf = 0; | ||
408 | REGION_NULL(pScrn->pScreen, &port->clipBoxes); | ||
409 | port->play = vmw_video_port_play; | ||
410 | return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, | ||
411 | drw_w, drw_h, format, buf, width, height, clipBoxes); | ||
412 | |||
413 | out_no_buffer: | ||
414 | while(i-- != 0) { | ||
415 | vmw_video_buffer_free(&port->bufs[i]); | ||
416 | } | ||
417 | out_bad_size: | ||
418 | (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); | ||
419 | |||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | |||
424 | /* | ||
425 | *----------------------------------------------------------------------------- | ||
426 | * | ||
427 | * vmw_video_port_play -- | ||
428 | * | ||
429 | * Sends all the attributes associated with the video frame using the | ||
430 | * FIFO ESCAPE mechanism to the host. | ||
431 | * | ||
432 | * Results: | ||
433 | * Always returns Success. | ||
434 | * | ||
435 | * Side effects: | ||
436 | * None. | ||
437 | * | ||
438 | *----------------------------------------------------------------------------- | ||
439 | */ | ||
440 | |||
441 | static int | ||
442 | vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, | ||
443 | short src_x, short src_y, short drw_x, | ||
444 | short drw_y, short src_w, short src_h, | ||
445 | short drw_w, short drw_h, int format, | ||
446 | unsigned char *buf, short width, | ||
447 | short height, RegionPtr clipBoxes) | ||
448 | { | ||
449 | struct drm_vmw_control_stream_arg arg; | ||
450 | unsigned short w, h; | ||
451 | int size; | ||
452 | int ret; | ||
453 | |||
454 | debug_printf("\t%s: enter\n", __func__); | ||
455 | |||
456 | w = width; | ||
457 | h = height; | ||
458 | |||
459 | /* we don't update the ports size */ | ||
460 | size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, | ||
461 | port->pitches, port->offsets); | ||
462 | |||
463 | if (size != port->size) { | ||
464 | vmw_xv_stop_video(pScrn, port, TRUE); | ||
465 | return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, | ||
466 | src_h, drw_w, drw_h, format, buf, width, height, | ||
467 | clipBoxes); | ||
468 | } | ||
469 | |||
470 | memcpy(port->bufs[port->currBuf].data, buf, port->size); | ||
471 | |||
472 | memset(&arg, 0, sizeof(arg)); | ||
473 | |||
474 | arg.stream_id = port->streamId; | ||
475 | arg.enabled = TRUE; | ||
476 | arg.flags = port->flags; | ||
477 | arg.color_key = port->colorKey; | ||
478 | arg.handle = port->bufs[port->currBuf].buf->handle; | ||
479 | arg.format = format; | ||
480 | arg.size = port->size; | ||
481 | arg.width = w; | ||
482 | arg.height = h; | ||
483 | arg.src.x = src_x; | ||
484 | arg.src.y = src_y; | ||
485 | arg.src.w = src_w; | ||
486 | arg.src.h = src_h; | ||
487 | arg.dst.x = drw_x; | ||
488 | arg.dst.y = drw_y; | ||
489 | arg.dst.w = drw_w; | ||
490 | arg.dst.h = drw_h; | ||
491 | arg.pitch[0] = port->pitches[0]; | ||
492 | arg.pitch[1] = port->pitches[1]; | ||
493 | arg.pitch[2] = port->pitches[2]; | ||
494 | arg.offset = 0; | ||
495 | |||
496 | /* | ||
497 | * Update the clipList and paint the colorkey, if required. | ||
498 | */ | ||
499 | if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) { | ||
500 | REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); | ||
501 | if (port->isAutoPaintColorkey) | ||
502 | xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); | ||
503 | } | ||
504 | |||
505 | xorg_flush(pScrn->pScreen); | ||
506 | ret = drmCommandWrite(port->drm_fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); | ||
507 | if (ret) { | ||
508 | vmw_video_port_cleanup(pScrn, port); | ||
509 | return XvBadAlloc; | ||
510 | } | ||
511 | |||
512 | if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS) | ||
513 | port->currBuf = 0; | ||
514 | |||
515 | return Success; | ||
516 | } | ||
517 | |||
518 | |||
519 | /* | ||
520 | *----------------------------------------------------------------------------- | ||
521 | * | ||
522 | * vmw_video_port_cleanup -- | ||
523 | * | ||
524 | * Frees up all resources (if any) taken by a video stream. | ||
525 | * | ||
526 | * Results: | ||
527 | * None. | ||
528 | * | ||
529 | * Side effects: | ||
530 | * Same as above. | ||
531 | * | ||
532 | *----------------------------------------------------------------------------- | ||
533 | */ | ||
534 | |||
535 | static void | ||
536 | vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port) | ||
537 | { | ||
538 | int i; | ||
539 | |||
540 | debug_printf("\t%s: enter\n", __func__); | ||
541 | |||
542 | if (port->play == vmw_video_port_init) | ||
543 | return; | ||
544 | |||
545 | port->play = vmw_video_port_init; | ||
546 | (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); | ||
547 | |||
548 | for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) { | ||
549 | vmw_video_buffer_free(&port->bufs[i]); | ||
550 | } | ||
551 | |||
552 | REGION_UNINIT(pScreen->pScreen, &port->clipBoxes); | ||
553 | } | ||
554 | |||
555 | |||
556 | /* | ||
557 | *----------------------------------------------------------------------------- | ||
558 | * | ||
559 | * vmw_video_buffer_alloc -- | ||
560 | * | ||
561 | * Allocates and map a kernel buffer to be used as data storage. | ||
562 | * | ||
563 | * Results: | ||
564 | * XvBadAlloc on failure, otherwise Success. | ||
565 | * | ||
566 | * Side effects: | ||
567 | * Calls into the kernel, sets members of out. | ||
568 | * | ||
569 | *----------------------------------------------------------------------------- | ||
570 | */ | ||
571 | |||
572 | static int | ||
573 | vmw_video_buffer_alloc(int drm_fd, int size, | ||
574 | struct vmw_video_buffer *out) | ||
575 | { | ||
576 | out->buf = vmwgfx_dmabuf_alloc(drm_fd, size); | ||
577 | if (!out->buf) | ||
578 | return XvBadAlloc; | ||
579 | |||
580 | out->data = vmwgfx_dmabuf_map(out->buf); | ||
581 | if (!out->data) { | ||
582 | vmwgfx_dmabuf_destroy(out->buf); | ||
583 | out->buf = NULL; | ||
584 | return XvBadAlloc; | ||
585 | } | ||
586 | |||
587 | out->size = size; | ||
588 | debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size); | ||
589 | |||
590 | return Success; | ||
591 | } | ||
592 | |||
593 | |||
594 | /* | ||
595 | *----------------------------------------------------------------------------- | ||
596 | * | ||
597 | * vmw_video_buffer_free -- | ||
598 | * | ||
599 | * Frees and unmaps an allocated kernel buffer. | ||
600 | * | ||
601 | * Results: | ||
602 | * Success. | ||
603 | * | ||
604 | * Side effects: | ||
605 | * Calls into the kernel, sets members of out to 0. | ||
606 | * | ||
607 | *----------------------------------------------------------------------------- | ||
608 | */ | ||
609 | |||
610 | static int | ||
611 | vmw_video_buffer_free(struct vmw_video_buffer *out) | ||
612 | { | ||
613 | if (out->size == 0) | ||
614 | return Success; | ||
615 | |||
616 | vmwgfx_dmabuf_unmap(out->buf); | ||
617 | vmwgfx_dmabuf_destroy(out->buf); | ||
618 | |||
619 | out->buf = NULL; | ||
620 | out->data = NULL; | ||
621 | out->size = 0; | ||
622 | |||
623 | debug_printf("\t\t%s: freed buffer %p\n", __func__, out); | ||
624 | |||
625 | return Success; | ||
626 | } | ||
627 | |||
628 | |||
629 | /* | ||
630 | *----------------------------------------------------------------------------- | ||
631 | * | ||
632 | * vmw_xv_put_image -- | ||
633 | * | ||
634 | * Main video playback function. It copies the passed data which is in | ||
635 | * the specified format (e.g. FOURCC_YV12) into the overlay. | ||
636 | * | ||
637 | * If sync is TRUE the driver should not return from this | ||
638 | * function until it is through reading the data from buf. | ||
639 | * | ||
640 | * Results: | ||
641 | * Success or XvBadAlloc on failure | ||
642 | * | ||
643 | * Side effects: | ||
644 | * Video port will be played(initialized if 1st frame) on success | ||
645 | * or will fail on error. | ||
646 | * | ||
647 | *----------------------------------------------------------------------------- | ||
648 | */ | ||
649 | |||
650 | static int | ||
651 | vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, | ||
652 | short drw_x, short drw_y, short src_w, short src_h, | ||
653 | short drw_w, short drw_h, int format, | ||
654 | unsigned char *buf, short width, short height, | ||
655 | Bool sync, RegionPtr clipBoxes, pointer data, | ||
656 | DrawablePtr dst) | ||
657 | { | ||
658 | struct vmwgfx_overlay_port *port = data; | ||
659 | |||
660 | debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, | ||
661 | src_x, src_y, src_w, src_h, | ||
662 | drw_x, drw_y, drw_w, drw_h, | ||
663 | width, height); | ||
664 | |||
665 | return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, | ||
666 | drw_w, drw_h, format, buf, width, height, clipBoxes); | ||
667 | } | ||
668 | |||
669 | |||
670 | /* | ||
671 | *----------------------------------------------------------------------------- | ||
672 | * | ||
673 | * vmw_xv_stop_video -- | ||
674 | * | ||
675 | * Called when we should stop playing video for a particular stream. If | ||
676 | * Cleanup is FALSE, the "stop" operation is only temporary, and thus we | ||
677 | * don't do anything. If Cleanup is TRUE we kill the video port by | ||
678 | * sending a message to the host and freeing up the stream. | ||
679 | * | ||
680 | * Results: | ||
681 | * None. | ||
682 | * | ||
683 | * Side effects: | ||
684 | * See above. | ||
685 | * | ||
686 | *----------------------------------------------------------------------------- | ||
687 | */ | ||
688 | |||
689 | static void | ||
690 | vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) | ||
691 | { | ||
692 | struct vmwgfx_overlay_port *port = data; | ||
693 | |||
694 | debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE"); | ||
695 | REGION_EMPTY(pScrn->pScreen, &port->clipBoxes); | ||
696 | |||
697 | if (!cleanup) | ||
698 | return; | ||
699 | |||
700 | vmw_video_port_cleanup(pScrn, port); | ||
701 | } | ||
702 | |||
703 | |||
704 | /* | ||
705 | *----------------------------------------------------------------------------- | ||
706 | * | ||
707 | * vmw_xv_query_image_attributes -- | ||
708 | * | ||
709 | * From the spec: This function is called to let the driver specify how data | ||
710 | * for a particular image of size width by height should be stored. | ||
711 | * Sometimes only the size and corrected width and height are needed. In | ||
712 | * that case pitches and offsets are NULL. | ||
713 | * | ||
714 | * Results: | ||
715 | * The size of the memory required for the image, or -1 on error. | ||
716 | * | ||
717 | * Side effects: | ||
718 | * None. | ||
719 | * | ||
720 | *----------------------------------------------------------------------------- | ||
721 | */ | ||
722 | |||
723 | static int | ||
724 | vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, | ||
725 | unsigned short *width, unsigned short *height, | ||
726 | int *pitches, int *offsets) | ||
727 | { | ||
728 | INT32 size, tmp; | ||
729 | |||
730 | if (*width > VMWARE_VID_MAX_WIDTH) { | ||
731 | *width = VMWARE_VID_MAX_WIDTH; | ||
732 | } | ||
733 | if (*height > VMWARE_VID_MAX_HEIGHT) { | ||
734 | *height = VMWARE_VID_MAX_HEIGHT; | ||
735 | } | ||
736 | |||
737 | *width = (*width + 1) & ~1; | ||
738 | if (offsets != NULL) { | ||
739 | offsets[0] = 0; | ||
740 | } | ||
741 | |||
742 | switch (format) { | ||
743 | case FOURCC_YV12: | ||
744 | *height = (*height + 1) & ~1; | ||
745 | size = (*width + 3) & ~3; | ||
746 | if (pitches) { | ||
747 | pitches[0] = size; | ||
748 | } | ||
749 | size *= *height; | ||
750 | if (offsets) { | ||
751 | offsets[1] = size; | ||
752 | } | ||
753 | tmp = ((*width >> 1) + 3) & ~3; | ||
754 | if (pitches) { | ||
755 | pitches[1] = pitches[2] = tmp; | ||
756 | } | ||
757 | tmp *= (*height >> 1); | ||
758 | size += tmp; | ||
759 | if (offsets) { | ||
760 | offsets[2] = size; | ||
761 | } | ||
762 | size += tmp; | ||
763 | break; | ||
764 | case FOURCC_UYVY: | ||
765 | case FOURCC_YUY2: | ||
766 | size = *width * 2; | ||
767 | if (pitches) { | ||
768 | pitches[0] = size; | ||
769 | } | ||
770 | size *= *height; | ||
771 | break; | ||
772 | default: | ||
773 | debug_printf("Query for invalid video format %d\n", format); | ||
774 | return -1; | ||
775 | } | ||
776 | return size; | ||
777 | } | ||
778 | |||
779 | |||
780 | /* | ||
781 | *----------------------------------------------------------------------------- | ||
782 | * | ||
783 | * vmw_xv_set_port_attribute -- | ||
784 | * | ||
785 | * From the spec: A port may have particular attributes such as colorKey, hue, | ||
786 | * saturation, brightness or contrast. Xv clients set these | ||
787 | * attribute values by sending attribute strings (Atoms) to the server. | ||
788 | * | ||
789 | * Results: | ||
790 | * Success if the attribute exists and XvBadAlloc otherwise. | ||
791 | * | ||
792 | * Side effects: | ||
793 | * The respective attribute gets the new value. | ||
794 | * | ||
795 | *----------------------------------------------------------------------------- | ||
796 | */ | ||
797 | |||
798 | static int | ||
799 | vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, | ||
800 | INT32 value, pointer data) | ||
801 | { | ||
802 | struct vmwgfx_overlay_port *port = data; | ||
803 | Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); | ||
804 | Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); | ||
805 | |||
806 | if (attribute == xvColorKey) { | ||
807 | debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value); | ||
808 | port->colorKey = value; | ||
809 | } else if (attribute == xvAutoPaint) { | ||
810 | debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE"); | ||
811 | port->isAutoPaintColorkey = value; | ||
812 | } else { | ||
813 | return XvBadAlloc; | ||
814 | } | ||
815 | |||
816 | return Success; | ||
817 | } | ||
818 | |||
819 | |||
820 | /* | ||
821 | *----------------------------------------------------------------------------- | ||
822 | * | ||
823 | * vmw_xv_get_port_attribute -- | ||
824 | * | ||
825 | * From the spec: A port may have particular attributes such as hue, | ||
826 | * saturation, brightness or contrast. Xv clients get these | ||
827 | * attribute values by sending attribute strings (Atoms) to the server | ||
828 | * | ||
829 | * Results: | ||
830 | * Success if the attribute exists and XvBadAlloc otherwise. | ||
831 | * | ||
832 | * Side effects: | ||
833 | * "value" contains the requested attribute on success. | ||
834 | * | ||
835 | *----------------------------------------------------------------------------- | ||
836 | */ | ||
837 | |||
838 | static int | ||
839 | vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, | ||
840 | INT32 *value, pointer data) | ||
841 | { | ||
842 | struct vmwgfx_overlay_port *port = data; | ||
843 | Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); | ||
844 | Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); | ||
845 | |||
846 | if (attribute == xvColorKey) { | ||
847 | *value = port->colorKey; | ||
848 | } else if (attribute == xvAutoPaint) { | ||
849 | *value = port->isAutoPaintColorkey; | ||
850 | } else { | ||
851 | return XvBadAlloc; | ||
852 | } | ||
853 | |||
854 | return Success; | ||
855 | } | ||
856 | |||
857 | |||
858 | /* | ||
859 | *----------------------------------------------------------------------------- | ||
860 | * | ||
861 | * vmw_xv_query_best_size -- | ||
862 | * | ||
863 | * From the spec: QueryBestSize provides the client with a way to query what | ||
864 | * the destination dimensions would end up being if they were to request | ||
865 | * that an area vid_w by vid_h from the video stream be scaled to rectangle | ||
866 | * of drw_w by drw_h on the screen. Since it is not expected that all | ||
867 | * hardware will be able to get the target dimensions exactly, it is | ||
868 | * important that the driver provide this function. | ||
869 | * | ||
870 | * This function seems to never be called, but to be on the safe side | ||
871 | * we apply the same logic that QueryImageAttributes has for width | ||
872 | * and height. | ||
873 | * | ||
874 | * Results: | ||
875 | * None. | ||
876 | * | ||
877 | * Side effects: | ||
878 | * None. | ||
879 | * | ||
880 | *----------------------------------------------------------------------------- | ||
881 | */ | ||
882 | |||
883 | static void | ||
884 | vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, | ||
885 | short vid_w, short vid_h, short drw_w, | ||
886 | short drw_h, unsigned int *p_w, | ||
887 | unsigned int *p_h, pointer data) | ||
888 | { | ||
889 | *p_w = (drw_w + 1) & ~1; | ||
890 | *p_h = drw_h; | ||
891 | |||
892 | return; | ||
893 | } | ||