1 /*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Jason Hu <jason.hu@intel.com>
26 * Zhaohan Ren <zhaohan.ren@intel.com>
27 * Shengquan Yuan <shengquan.yuan@intel.com>
28 *
29 */
30
31 #include <X11/Xutil.h>
32 #include <X11/extensions/Xrandr.h>
33 #include <va/va_backend.h>
34 #include "psb_output.h"
35 #include "psb_surface.h"
36 #include "psb_buffer.h"
37 #include "psb_x11.h"
38 #include "psb_drv_debug.h"
39
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdarg.h>
43 #include "psb_surface_ext.h"
44 #include <wsbm/wsbm_manager.h>
45 #include "psb_drv_video.h"
46 #include "psb_xrandr.h"
47 #include <sys/types.h>
48
49 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
50 #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
51 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
52
53 static int
psb_x11_getWindowCoordinate(Display * display,Window x11_window_id,psb_x11_win_t * psX11Window,int * pbIsVisible)54 psb_x11_getWindowCoordinate(Display * display,
55 Window x11_window_id,
56 psb_x11_win_t * psX11Window,
57 int * pbIsVisible)
58 {
59 Window DummyWindow;
60 Status status;
61 XWindowAttributes sXWinAttrib;
62
63 if ((status = XGetWindowAttributes(display,
64 x11_window_id,
65 &sXWinAttrib)) == 0) {
66 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates - error %lu\n", __func__, (unsigned long)status);
67 return -1;
68 }
69
70 psX11Window->i32Left = sXWinAttrib.x;
71 psX11Window->i32Top = sXWinAttrib.y;
72 psX11Window->ui32Width = sXWinAttrib.width;
73 psX11Window->ui32Height = sXWinAttrib.height;
74 *pbIsVisible = (sXWinAttrib.map_state == IsViewable);
75
76 if (!*pbIsVisible)
77 return 0;
78
79 if (XTranslateCoordinates(display,
80 x11_window_id,
81 DefaultRootWindow(display),
82 0,
83 0,
84 &psX11Window->i32Left,
85 &psX11Window->i32Top,
86 &DummyWindow) == 0) {
87 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to tranlate X coordinates - error %lu\n", __func__, (unsigned long)status);
88 return -1;
89 }
90
91 psX11Window->i32Right = psX11Window->i32Left + psX11Window->ui32Width - 1;
92 psX11Window->i32Bottom = psX11Window->i32Top + psX11Window->ui32Height - 1;
93
94 return 0;
95 }
96 static psb_x11_clip_list_t *
psb_x11_createClipBoxNode(psb_x11_win_t * pRect,psb_x11_clip_list_t * pClipNext)97 psb_x11_createClipBoxNode(psb_x11_win_t * pRect,
98 psb_x11_clip_list_t * pClipNext)
99 {
100 psb_x11_clip_list_t * pCurrent = NULL;
101
102 pCurrent = (psb_x11_clip_list_t *)calloc(1, sizeof(psb_x11_clip_list_t));
103 if (pCurrent) {
104 pCurrent->rect = *pRect;
105 pCurrent->next = pClipNext;
106
107 return pCurrent;
108 } else
109 return pClipNext;
110 }
111
112 void
psb_x11_freeWindowClipBoxList(psb_x11_clip_list_t * pHead)113 psb_x11_freeWindowClipBoxList(psb_x11_clip_list_t * pHead)
114 {
115 psb_x11_clip_list_t * pNext = NULL;
116
117 while (pHead) {
118 pNext = pHead->next;
119 free(pHead);
120 pHead = pNext;
121 }
122 }
123
124 #define IS_BETWEEN_RANGE(a,b,c) ((a<=b)&&(b<=c))
125
126 static psb_x11_clip_list_t *
psb_x11_substractRects(Display * display,psb_x11_clip_list_t * psRegion,psb_x11_win_t * psRect)127 psb_x11_substractRects(Display * display,
128 psb_x11_clip_list_t * psRegion,
129 psb_x11_win_t * psRect)
130 {
131 psb_x11_clip_list_t * psCur, * psPrev, * psFirst, * psNext;
132 psb_x11_win_t sCreateRect;
133 int display_width = (int)(DisplayWidth(display, DefaultScreen(display))) - 1;
134 int display_height = (int)(DisplayHeight(display, DefaultScreen(display))) - 1;
135
136 psFirst = psb_x11_createClipBoxNode(psRect, NULL);
137
138 if (psFirst->rect.i32Left < 0)
139 psFirst->rect.i32Left = 0;
140 else if (psFirst->rect.i32Left > display_width)
141 psFirst->rect.i32Left = display_width;
142
143 if (psFirst->rect.i32Right < 0)
144 psFirst->rect.i32Right = 0;
145 else if (psFirst->rect.i32Right > display_width)
146 psFirst->rect.i32Right = display_width;
147
148 if (psFirst->rect.i32Top < 0)
149 psFirst->rect.i32Top = 0;
150 else if (psFirst->rect.i32Top > display_height)
151 psFirst->rect.i32Top = display_height;
152
153 if (psFirst->rect.i32Bottom < 0)
154 psFirst->rect.i32Bottom = 0;
155 else if (psFirst->rect.i32Bottom > display_height)
156 psFirst->rect.i32Bottom = display_height;
157
158 while (psRegion) {
159 psCur = psFirst;
160 psPrev = NULL;
161
162 while (psCur) {
163 psNext = psCur->next;
164
165 if ((psRegion->rect.i32Left > psCur->rect.i32Left) &&
166 (psRegion->rect.i32Left <= psCur->rect.i32Right)) {
167 sCreateRect.i32Right = psRegion->rect.i32Left - 1;
168
169 sCreateRect.i32Left = psCur->rect.i32Left;
170 sCreateRect.i32Top = psCur->rect.i32Top;
171 sCreateRect.i32Bottom = psCur->rect.i32Bottom;
172
173 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
174
175 if (!psPrev)
176 psPrev = psFirst;
177
178 psCur->rect.i32Left = psRegion->rect.i32Left;
179 }
180
181 if ((psRegion->rect.i32Right >= psCur->rect.i32Left) &&
182 (psRegion->rect.i32Right < psCur->rect.i32Right))
183
184 {
185 sCreateRect.i32Left = psRegion->rect.i32Right + 1;
186
187 sCreateRect.i32Right = psCur->rect.i32Right;
188 sCreateRect.i32Top = psCur->rect.i32Top;
189 sCreateRect.i32Bottom = psCur->rect.i32Bottom;
190
191 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
192
193 if (!psPrev)
194 psPrev = psFirst;
195
196 psCur->rect.i32Right = psRegion->rect.i32Right;
197 }
198
199 if ((psRegion->rect.i32Top > psCur->rect.i32Top) &&
200 (psRegion->rect.i32Top <= psCur->rect.i32Bottom)) {
201 sCreateRect.i32Bottom = psRegion->rect.i32Top - 1;
202
203 sCreateRect.i32Left = psCur->rect.i32Left;
204 sCreateRect.i32Right = psCur->rect.i32Right;
205 sCreateRect.i32Top = psCur->rect.i32Top;
206
207 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
208
209 if (!psPrev)
210 psPrev = psFirst;
211
212 psCur->rect.i32Top = psRegion->rect.i32Top;
213 }
214
215 if ((psRegion->rect.i32Bottom >= psCur->rect.i32Top) &&
216 (psRegion->rect.i32Bottom < psCur->rect.i32Bottom)) {
217 sCreateRect.i32Top = psRegion->rect.i32Bottom + 1;
218 sCreateRect.i32Left = psCur->rect.i32Left;
219 sCreateRect.i32Right = psCur->rect.i32Right;
220 sCreateRect.i32Bottom = psCur->rect.i32Bottom;
221
222 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
223
224 if (!psPrev)
225 psPrev = psFirst;
226
227 psCur->rect.i32Bottom = psRegion->rect.i32Bottom;
228 }
229
230 if ((IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Left, psRegion->rect.i32Right)) &&
231 (IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Right, psRegion->rect.i32Right)) &&
232 (IS_BETWEEN_RANGE(psRegion->rect.i32Top, psCur->rect.i32Top, psRegion->rect.i32Bottom)) &&
233 (IS_BETWEEN_RANGE(psRegion->rect.i32Top, psCur->rect.i32Bottom, psRegion->rect.i32Bottom))) {
234 if (psPrev) {
235 psPrev->next = psCur->next;
236 free(psCur);
237 psCur = psPrev;
238 } else {
239 free(psCur);
240 psCur = NULL;
241 psFirst = psNext;
242 }
243 }
244 psPrev = psCur;
245 psCur = psNext;
246 }//while(psCur)
247 psRegion = psRegion->next;
248 }//while(psRegion)
249
250 return psFirst;
251 }
252
253 static int
psb_x11_createWindowClipBoxList(Display * display,Window x11_window_id,psb_x11_clip_list_t ** ppWindowClipBoxList,unsigned int * pui32NumClipBoxList)254 psb_x11_createWindowClipBoxList(Display * display,
255 Window x11_window_id,
256 psb_x11_clip_list_t ** ppWindowClipBoxList,
257 unsigned int * pui32NumClipBoxList)
258 {
259 Window CurrentWindow = x11_window_id;
260 Window RootWindow, ParentWindow, ChildWindow;
261 Window * pChildWindow;
262 Status XResult;
263 unsigned int i32NumChildren, i;
264 int bIsVisible;
265 unsigned int ui32NumRects = 0;
266 psb_x11_clip_list_t *psRegions = NULL;
267 psb_x11_win_t sRect;
268
269 if (!display || (!ppWindowClipBoxList) || (!pui32NumClipBoxList))
270 return -1;
271
272 XResult = XQueryTree(display,
273 CurrentWindow,
274 &RootWindow,
275 &ParentWindow,
276 &pChildWindow,
277 &i32NumChildren);
278 if (XResult == 0)
279 return -2;
280
281 if (i32NumChildren) {
282 for (i = 0; i < i32NumChildren; i++) {
283
284 psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible);
285 if (bIsVisible) {
286 psRegions = psb_x11_createClipBoxNode(&sRect, psRegions);
287 ui32NumRects++;
288 }
289 }
290 XFree(pChildWindow);
291 i32NumChildren = 0;
292 }
293
294 while (CurrentWindow != RootWindow) {
295 ChildWindow = CurrentWindow;
296 CurrentWindow = ParentWindow;
297
298 XResult = XQueryTree(display,
299 CurrentWindow,
300 &RootWindow,
301 &ParentWindow,
302 &pChildWindow,
303 &i32NumChildren);
304 if (XResult == 0) {
305 if (i32NumChildren)
306 XFree(pChildWindow);
307
308 psb_x11_freeWindowClipBoxList(psRegions);
309 return -3;
310 }
311
312 if (i32NumChildren) {
313 unsigned int iStartWindow = 0;
314
315 for (i = 0; i < i32NumChildren; i++) {
316 if (pChildWindow[i] == ChildWindow) {
317 iStartWindow = i;
318 break;
319 }
320 }
321
322 if (i == i32NumChildren) {
323 XFree(pChildWindow);
324 psb_x11_freeWindowClipBoxList(psRegions);
325 return -4;
326 }
327
328 for (i = iStartWindow + 1; i < i32NumChildren; i++) {
329 psb_x11_getWindowCoordinate(display, pChildWindow[i], &sRect, &bIsVisible);
330 if (bIsVisible) {
331 psRegions = psb_x11_createClipBoxNode(&sRect, psRegions);
332 ui32NumRects++;
333 }
334 }
335
336 XFree(pChildWindow);
337 }
338 }
339
340 ui32NumRects = 0;
341
342 if (psRegions) {
343 psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible);
344 *ppWindowClipBoxList = psb_x11_substractRects(display, psRegions, &sRect);
345 psb_x11_freeWindowClipBoxList(psRegions);
346
347 psRegions = *ppWindowClipBoxList;
348
349 while (psRegions) {
350 ui32NumRects++;
351 psRegions = psRegions->next;
352 }
353 } else {
354 *ppWindowClipBoxList = psb_x11_substractRects(display, NULL, &sRect);
355 ui32NumRects = 1;
356 }
357
358 *pui32NumClipBoxList = ui32NumRects;
359
360 return 0;
361 }
362
psb_cleardrawable_stopoverlay(VADriverContextP ctx,Drawable draw,short destx,short desty,unsigned short destw,unsigned short desth)363 static int psb_cleardrawable_stopoverlay(
364 VADriverContextP ctx,
365 Drawable draw, /* X Drawable */
366 short destx,
367 short desty,
368 unsigned short destw,
369 unsigned short desth
370 )
371 {
372 INIT_DRIVER_DATA;
373 INIT_OUTPUT_PRIV;
374
375 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth);
376 XSync((Display *)ctx->native_dpy, False);
377
378 driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
379 driver_data->last_displaying_surface = VA_INVALID_SURFACE;
380
381 return 0;
382 }
383
psb_DisplayRGBASubpicture(PsbVASurfaceRec * subpicture,VADriverContextP ctx,int win_width,int win_height,int surface_x,int surface_y,int surface_w,int surface_h,psb_extvideo_subtitle subtitle)384 static VAStatus psb_DisplayRGBASubpicture(
385 PsbVASurfaceRec *subpicture,
386 VADriverContextP ctx,
387 int win_width,
388 int win_height,
389 int surface_x,
390 int surface_y,
391 int surface_w,
392 int surface_h,
393 psb_extvideo_subtitle subtitle
394 )
395 {
396 INIT_DRIVER_DATA;
397 INIT_OUTPUT_PRIV;
398 XImage *ximg = NULL;
399 Visual *visual;
400 PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
401 struct _WsbmBufferObject *bo = subpicture->bo;
402 int image_width, image_height, width, height, size;
403 int srcx, srcy, srcw, srch;
404 int destx, desty, destw, desth;
405 int depth, i;
406
407 if (subpicture->fourcc != VA_FOURCC_RGBA) {
408 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid image format, ONLY support RGBA subpicture now.\n", __func__);
409 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
410 }
411
412 for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) {
413 srcx = subpicture->subpic_srcx;
414 srcy = subpicture->subpic_srcy;
415 srcw = subpicture->subpic_srcw;
416 srch = subpicture->subpic_srch;
417
418 destx = subpicture->subpic_dstx + surface_x;
419 desty = subpicture->subpic_dsty + surface_y;
420 destw = subpicture->subpic_dstw;
421 desth = subpicture->subpic_dsth;
422
423 image_width = subpicture->width;
424 image_height = subpicture->height;
425 size = subpicture->size;
426
427 //clip in image region
428 if (srcx < 0) {
429 srcw += srcx;
430 srcx = 0;
431 }
432
433 if (srcy < 0) {
434 srch += srcy;
435 srcy = 0;
436 }
437
438 if ((srcx + srcw) > image_width)
439 srcw = image_width - srcx;
440 if ((srcy + srch) > image_height)
441 srch = image_height - srcy;
442
443 //clip in drawable region
444 if (destx < 0) {
445 destw += destx;
446 destx = 0;
447 }
448
449 if (desty < 0) {
450 desth += desty;
451 desty = 0;
452 }
453
454 if ((destx + destw) > surface_w)
455 destw = surface_w - destx;
456 if ((desty + desth) > surface_h)
457 desth = surface_h - desty;
458
459 if (srcw <= destw)
460 width = srcw;
461 else
462 width = destw;
463
464 if (srch <= desth)
465 height = srch;
466 else
467 height = desth;
468
469 visual = DefaultVisual(ctx->native_dpy, 0);
470 depth = DefaultDepth(ctx->native_dpy, 0);
471
472 ximg = XCreateImage(ctx->native_dpy, visual, depth, ZPixmap, 0, NULL, image_width, image_height, 32, 0);
473
474 if (NULL == ximg) {
475 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: XCreateImage failed! at L%d\n", __func__, __LINE__);
476 return VA_STATUS_ERROR_UNKNOWN;
477 }
478
479 ximg->data = wsbmBOMap(bo, WSBM_ACCESS_READ);
480 if (NULL == ximg->data) {
481 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to map to ximg->data.\n", __func__);
482 return VA_STATUS_ERROR_ALLOCATION_FAILED;
483 }
484
485 pPriv->clear_key[i].subpic_dstx = destx;
486 pPriv->clear_key[i].subpic_dsty = desty;
487 pPriv->clear_key[i].subpic_dstw = destw;
488 pPriv->clear_key[i].subpic_dsth = desth;
489 if (psb_xrandr_extvideo_mode()) {
490 /*It is a HACK: Adjust subtitle to proper position.*/
491 float xScale, yScale;
492
493 xScale = win_width * 1.0 / surface_w;
494 yScale = win_height * 1.0 / surface_h;
495 destx = subpicture->subpic_dstx * xScale;
496 desty = subpicture->subpic_dsty * yScale;
497 }
498 XPutImage(ctx->native_dpy, output->output_drawable, output->gc, ximg, srcx, srcy, destx, desty, width, height);
499 XSync((Display *)ctx->native_dpy, False);
500
501 if (psb_xrandr_extvideo_mode() &&
502 (subtitle == ONLY_HDMI || subtitle == BOTH)) {
503 float xScale, yScale;
504
505 xScale = pPriv->extend_display_width * 1.0 / surface_w;
506 yScale = pPriv->extend_display_height * 1.0 / surface_h;
507
508 destx = subpicture->subpic_dstx * xScale;
509 desty = subpicture->subpic_dsty * yScale;
510
511 XPutImage(ctx->native_dpy, output->extend_drawable, output->extend_gc, ximg,
512 srcx, srcy, destx, desty, destw, desth);
513 XSync((Display *)ctx->native_dpy, False);
514 }
515
516 pPriv->subpic_clear_flag = 0;
517 ximg->data = NULL;
518 wsbmBOUnmap(bo);
519 if (NULL != ximg)
520 XDestroyImage(ximg);
521 }
522 return VA_STATUS_SUCCESS;
523 }
524
psb_repaint_colorkey(VADriverContextP ctx,Drawable draw,VASurfaceID surface,int x11_window_width,int x11_window_height)525 static VAStatus psb_repaint_colorkey(
526 VADriverContextP ctx,
527 Drawable draw, /* X Drawable */
528 VASurfaceID surface,
529 int x11_window_width,
530 int x11_window_height
531 )
532 {
533 INIT_DRIVER_DATA;
534 INIT_OUTPUT_PRIV;
535 int i, ret;
536 psb_x11_clip_list_t *pClipNext = NULL;
537 VARectangle *pVaWindowClipRects = NULL;
538 object_surface_p obj_surface = SURFACE(surface);
539 PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
540
541 if (output->frame_count % 500 == 0 || driver_data->xrandr_update) {
542 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Repaint color key.\n");
543 if (output->pClipBoxList)
544 psb_x11_freeWindowClipBoxList(output->pClipBoxList);
545 /* get window clipbox */
546 ret = psb_x11_createWindowClipBoxList(ctx->native_dpy, draw, &output->pClipBoxList, &output->ui32NumClipBoxList);
547 if (ret != 0) {
548 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: get window clip boxes error # %d\n", __func__, ret);
549 return VA_STATUS_ERROR_UNKNOWN;
550 }
551 if (output->frame_count == 500)
552 output->frame_count = 0;
553
554 driver_data->xrandr_update = 0;
555 }
556
557 pVaWindowClipRects = (VARectangle *)calloc(1, sizeof(VARectangle) * output->ui32NumClipBoxList);
558 if (!pVaWindowClipRects) {
559 psb_x11_freeWindowClipBoxList(output->pClipBoxList);
560 return VA_STATUS_ERROR_ALLOCATION_FAILED;
561 }
562
563 memset(pVaWindowClipRects, 0, sizeof(VARectangle)*output->ui32NumClipBoxList);
564 pClipNext = output->pClipBoxList;
565 #ifdef CLIP_DEBUG
566 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Total %d clip boxes\n", __func__, output->ui32NumClipBoxList);
567 #endif
568 for (i = 0; i < output->ui32NumClipBoxList; i++) {
569 pVaWindowClipRects[i].x = pClipNext->rect.i32Left;
570 pVaWindowClipRects[i].y = pClipNext->rect.i32Top;
571 pVaWindowClipRects[i].width = pClipNext->rect.i32Right - pClipNext->rect.i32Left;
572 pVaWindowClipRects[i].height = pClipNext->rect.i32Bottom - pClipNext->rect.i32Top;
573 #ifdef CLIP_DEBUG
574 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: clip boxes Left Top (%d, %d) Right Bottom (%d, %d) width %d height %d\n", __func__,
575 pClipNext->rect.i32Left, pClipNext->rect.i32Top,
576 pClipNext->rect.i32Right, pClipNext->rect.i32Bottom,
577 pVaWindowClipRects[i].width, pVaWindowClipRects[i].height);
578 #endif
579 pClipNext = pClipNext->next;
580 }
581
582 /* repaint the color key when window size changed*/
583 if (!obj_surface->subpictures &&
584 ((pPriv->x11_window_width != x11_window_width) ||
585 (pPriv->x11_window_height != x11_window_height))) {
586 pPriv->x11_window_width = x11_window_width;
587 pPriv->x11_window_height = x11_window_height;
588 XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
589 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
590 XSync((Display *)ctx->native_dpy, False);
591 }
592
593
594 if ((!obj_surface->subpictures) &&
595 ((output->ui32NumClipBoxList != pPriv->last_num_clipbox) ||
596 (memcmp(&pVaWindowClipRects[0], &(pPriv->last_clipbox[0]), (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle)) != 0))) {
597 pPriv->last_num_clipbox = output->ui32NumClipBoxList;
598 memcpy(&pPriv->last_clipbox[0], &pVaWindowClipRects[0], (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle));
599 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
600 XSync((Display *)ctx->native_dpy, False);
601 }
602
603 free(pVaWindowClipRects);
604
605 return VA_STATUS_SUCCESS;
606 }
607
psb_extendMode_getCoordinate(PsbPortPrivPtr pPriv,psb_xrandr_location extend_location,short destx,short desty,short srcx,short srcy,float xScaleFactor,float yScaleFactor,int * x11_window_width,int * x11_window_height,psb_overlay_rect_p local_rect,psb_overlay_rect_p extend_rect,enum overlay_id_t * extend_overlay)608 static VAStatus psb_extendMode_getCoordinate(
609 PsbPortPrivPtr pPriv,
610 psb_xrandr_location extend_location,
611 short destx,
612 short desty,
613 short srcx,
614 short srcy,
615 float xScaleFactor,
616 float yScaleFactor,
617 int *x11_window_width,
618 int *x11_window_height,
619 psb_overlay_rect_p local_rect,
620 psb_overlay_rect_p extend_rect,
621 enum overlay_id_t *extend_overlay
622 )
623 {
624 switch (extend_location) {
625 case LEFT_OF:
626 if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) {
627 *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx;
628 }
629 if (((desty + *x11_window_height) < pPriv->display_height) &&
630 ((desty + *x11_window_height) < pPriv->extend_display_height))
631 local_rect->dHeight = extend_rect->dHeight = *x11_window_height;
632 else if (pPriv->display_height < pPriv->extend_display_height) {
633 local_rect->dHeight = pPriv->display_height - desty;
634 if ((desty + *x11_window_height) > pPriv->extend_display_height)
635 extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty;
636 else
637 extend_rect->dHeight = *x11_window_height;
638 } else {
639 extend_rect->dHeight = pPriv->extend_display_height - desty;
640 if ((desty + *x11_window_height) > pPriv->display_height)
641 local_rect->dHeight = *x11_window_height = pPriv->display_height - desty;
642 else
643 local_rect->dHeight = *x11_window_height;
644 }
645
646 if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) < pPriv->extend_display_width)) {
647 local_rect->dWidth = 0;
648 extend_rect->dWidth = *x11_window_width;
649 *extend_overlay = OVERLAY_A;
650 local_rect->destx = 0;
651 } else if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) >= pPriv->extend_display_width)) {
652 extend_rect->dWidth = pPriv->extend_display_width - destx;
653 local_rect->dWidth = *x11_window_width - extend_rect->dWidth;
654 local_rect->destx = 0;
655 } else {
656 local_rect->dWidth = *x11_window_width;
657 extend_rect->dWidth = 0;
658 local_rect->destx = destx - pPriv->extend_display_width;
659 }
660 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
661 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
662 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
663 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
664
665 local_rect->srcx = srcx + extend_rect->sWidth;
666 extend_rect->srcx = srcx;
667 local_rect->srcy = extend_rect->srcy = srcy;
668
669 extend_rect->destx = destx;
670 local_rect->desty = extend_rect->desty = desty;
671 break;
672 case RIGHT_OF:
673 if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) {
674 *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx;
675 }
676 if (((desty + *x11_window_height) < pPriv->display_height) &&
677 ((desty + *x11_window_height) < pPriv->extend_display_height))
678 local_rect->dHeight = extend_rect->dHeight = *x11_window_height;
679 else if (pPriv->display_height < pPriv->extend_display_height) {
680 local_rect->dHeight = pPriv->display_height - desty;
681 if ((desty + *x11_window_height) > pPriv->extend_display_height)
682 extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty;
683 else
684 extend_rect->dHeight = *x11_window_height;
685 } else {
686 extend_rect->dHeight = pPriv->extend_display_height - desty;
687 if ((desty + *x11_window_height) > pPriv->display_height)
688 local_rect->dHeight = *x11_window_height = pPriv->display_height - desty;
689 else
690 local_rect->dHeight = *x11_window_height;
691 }
692
693 if ((destx < pPriv->display_width) && ((destx + *x11_window_width) < pPriv->display_width)) {
694 local_rect->dWidth = *x11_window_width;
695 extend_rect->dWidth = 0;
696 extend_rect->destx = 0;
697 } else if ((destx < pPriv->display_width) && ((destx + *x11_window_width) >= pPriv->display_width)) {
698 local_rect->dWidth = pPriv->display_width - destx;
699 extend_rect->dWidth = *x11_window_width - local_rect->dWidth;
700 extend_rect->destx = 0;
701 } else {
702 local_rect->dWidth = 0;
703 extend_rect->dWidth = *x11_window_width;
704 *extend_overlay = OVERLAY_A;
705 extend_rect->destx = destx - pPriv->display_width;
706 }
707 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
708 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
709 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
710 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
711
712 local_rect->srcx = srcx;
713 extend_rect->srcx = srcx + local_rect->sWidth;
714 local_rect->srcy = extend_rect->srcy = srcy;
715
716 local_rect->destx = destx;
717 local_rect->desty = extend_rect->desty = desty;
718 break;
719 case ABOVE:
720 if (((destx + *x11_window_width) < pPriv->display_width) &&
721 ((destx + *x11_window_width) < pPriv->extend_display_width))
722 local_rect->dWidth = extend_rect->dWidth = *x11_window_width;
723 else if (pPriv->display_width < pPriv->extend_display_width) {
724 local_rect->dWidth = pPriv->display_width - destx;
725 if ((destx + *x11_window_width) > pPriv->extend_display_width)
726 extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx;
727 else
728 extend_rect->dWidth = *x11_window_width;
729 } else {
730 extend_rect->dWidth = pPriv->extend_display_width - destx;
731 if ((destx + *x11_window_width) > pPriv->display_width)
732 local_rect->dWidth = *x11_window_width = pPriv->display_width - destx;
733 else
734 local_rect->dWidth = *x11_window_width;
735 }
736
737 if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) {
738 *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty;
739 }
740
741 if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) < pPriv->extend_display_height)) {
742 local_rect->dHeight = 0;
743 extend_rect->dHeight = *x11_window_height;
744 *extend_overlay = OVERLAY_A;
745 local_rect->desty = 0;
746 } else if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) >= pPriv->extend_display_height)) {
747 extend_rect->dHeight = pPriv->extend_display_height - desty;
748 local_rect->dHeight = *x11_window_height - extend_rect->dHeight;
749 local_rect->desty = 0;
750 } else {
751 local_rect->dHeight = *x11_window_height;
752 extend_rect->dHeight = 0;
753 local_rect->desty = desty - pPriv->extend_display_height;
754 }
755 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
756 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
757 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
758 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
759
760 local_rect->srcy = srcy + extend_rect->sHeight;
761 extend_rect->srcy = srcy;
762 local_rect->srcx = extend_rect->srcx = srcx;
763
764 extend_rect->desty = desty;
765 local_rect->destx = extend_rect->destx = destx;
766 break;
767 case BELOW:
768 if (((destx + *x11_window_width) < pPriv->display_width) &&
769 ((destx + *x11_window_width) < pPriv->extend_display_width))
770 local_rect->dWidth = extend_rect->dWidth = *x11_window_width;
771 else if (pPriv->display_width < pPriv->extend_display_width) {
772 local_rect->dWidth = pPriv->display_width - destx;
773 if ((destx + *x11_window_width) > pPriv->extend_display_width)
774 extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx;
775 else
776 extend_rect->dWidth = *x11_window_width;
777 } else {
778 extend_rect->dWidth = pPriv->extend_display_width - destx;
779 if ((destx + *x11_window_width) > pPriv->display_width)
780 local_rect->dWidth = *x11_window_width = pPriv->display_width - destx;
781 else
782 local_rect->dWidth = *x11_window_width;
783 }
784
785 if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) {
786 *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty;
787 }
788
789 if ((desty < pPriv->display_height) && ((desty + *x11_window_height) < pPriv->display_height)) {
790 local_rect->dHeight = *x11_window_height;
791 extend_rect->dHeight = 0;
792 extend_rect->desty = 0;
793 } else if ((desty < pPriv->display_height) && ((desty + *x11_window_height) >= pPriv->display_height)) {
794 local_rect->dHeight = pPriv->display_height - desty;
795 extend_rect->dHeight = *x11_window_height - local_rect->dHeight;
796 extend_rect->desty = 0;
797 } else {
798 local_rect->dHeight = 0;
799 extend_rect->dHeight = *x11_window_height;
800 *extend_overlay = OVERLAY_A;
801 extend_rect->desty = desty - pPriv->display_height;
802 }
803 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
804 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
805 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
806 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
807
808 local_rect->srcy = srcy;
809 extend_rect->srcy = srcy + local_rect->sHeight;
810 local_rect->srcx = extend_rect->srcx = srcx;
811
812 local_rect->desty = desty;
813 local_rect->destx = extend_rect->destx = destx;
814 break;
815 case NORMAL:
816 default:
817 break;
818 }
819 return VA_STATUS_SUCCESS;
820 }
821
psb_init_subpicture(VADriverContextP ctx,PsbPortPrivPtr pPriv)822 static void psb_init_subpicture(VADriverContextP ctx, PsbPortPrivPtr pPriv)
823 {
824 INIT_DRIVER_DATA;
825 struct drm_psb_register_rw_arg regs;
826 unsigned int subpicture_enable_mask = REGRWBITS_DSPACNTR;
827
828 if (!pPriv->subpicture_enabled) {
829 if (psb_xrandr_hdmi_enabled())
830 subpicture_enable_mask |= REGRWBITS_DSPBCNTR;
831 if (psb_xrandr_mipi1_enabled())
832 subpicture_enable_mask |= REGRWBITS_DSPCCNTR;
833
834 memset(®s, 0, sizeof(regs));
835 regs.subpicture_enable_mask = subpicture_enable_mask;
836 pPriv->subpicture_enable_mask = subpicture_enable_mask;
837 pPriv->subpicture_enabled = 1;
838 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
839 }
840 }
841
psb_clear_subpictures(VADriverContextP ctx,PsbPortPrivPtr pPriv,int win_width,int win_height,object_surface_p obj_surface)842 static void psb_clear_subpictures(
843 VADriverContextP ctx,
844 PsbPortPrivPtr pPriv,
845 int win_width,
846 int win_height,
847 object_surface_p obj_surface
848 )
849 {
850 INIT_OUTPUT_PRIV;
851 PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures;
852 int i;
853
854 if (subpicture == NULL) {
855 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Surface has no subpicture to render.\n");
856 return;
857 }
858
859 for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) {
860 if ((subpicture->subpic_dstx != pPriv->clear_key[i].subpic_dstx) ||
861 (subpicture->subpic_dsty != pPriv->clear_key[i].subpic_dsty) ||
862 (subpicture->subpic_dstw != pPriv->clear_key[i].subpic_dstw) ||
863 (subpicture->subpic_dsth != pPriv->clear_key[i].subpic_dsth)) {
864 XSetForeground((Display *)ctx->native_dpy, output->gc, 0);
865 XFillRectangle((Display *)ctx->native_dpy, output->output_drawable, output->gc, 0, 0, win_width, win_height);
866 XSync((Display *)ctx->native_dpy, False);
867 if (psb_xrandr_extvideo_mode()) {
868 XSetForeground((Display *)ctx->native_dpy, output->extend_gc, 0);
869 XFillRectangle((Display *)ctx->native_dpy, output->extend_drawable, output->extend_gc,
870 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
871 XSync((Display *)ctx->native_dpy, False);
872 }
873 pPriv->subpic_clear_flag = 1;
874 }
875 }
876 return;
877 }
878
psb_putsurface_coverlay(VADriverContextP ctx,VASurfaceID surface,Drawable draw,short srcx,short srcy,unsigned short srcw,unsigned short srch,short destx,short desty,unsigned short destw,unsigned short desth,VARectangle * cliprects,unsigned int number_cliprects,unsigned int flags)879 VAStatus psb_putsurface_coverlay(
880 VADriverContextP ctx,
881 VASurfaceID surface,
882 Drawable draw, /* X Drawable */
883 short srcx,
884 short srcy,
885 unsigned short srcw,
886 unsigned short srch,
887 short destx,
888 short desty,
889 unsigned short destw,
890 unsigned short desth,
891 VARectangle *cliprects, /* client supplied clip list */
892 unsigned int number_cliprects, /* number of clip rects in the clip list */
893 unsigned int flags /* de-interlacing flags */
894 )
895 {
896 INIT_DRIVER_DATA;
897 INIT_OUTPUT_PRIV;
898 int ret;
899 int x11_window_width = destw, x11_window_height = desth;
900 psb_xrandr_location extend_location;
901 object_surface_p obj_surface = SURFACE(surface);
902 PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
903 int primary_crtc_x, primary_crtc_y, extend_crtc_x, extend_crtc_y;
904 enum pipe_id_t local_pipe = PIPEA, extend_pipe = PIPEB;
905 int surfacex = destx, surfacey = desty;
906 float xScaleFactor, yScaleFactor;
907 Rotation rotation = RR_Rotate_0;
908 psb_output_device local_device, extend_device;
909 psb_extvideo_subtitle subtitle;
910
911 if (flags & VA_CLEAR_DRAWABLE) {
912 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color);
913 psb_cleardrawable_stopoverlay(ctx, draw, destx, desty, destw, desth);
914
915 return VA_STATUS_SUCCESS;
916 }
917
918 if (output->frame_count % 500 == 0 || driver_data->xrandr_update) {
919 /* get window screen coordination */
920 ret = psb_x11_getWindowCoordinate(ctx->native_dpy, draw, &output->winRect, &output->bIsVisible);
921 if (ret != 0) {
922 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates error # %d\n", __func__, ret);
923 return VA_STATUS_ERROR_UNKNOWN;
924 }
925 }
926
927 if (!output->bIsVisible) {
928 return VA_STATUS_SUCCESS;
929 }
930
931 if (NULL == obj_surface) {
932 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid surface id 0x%08x.\n", __func__, surface);
933 return VA_STATUS_ERROR_INVALID_SURFACE;
934 }
935
936 if (output->output_drawable != draw) {
937 output->output_drawable = draw;
938 }
939
940 if (!output->gc) {
941 output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL);
942 /* paint the color key */
943 if (!obj_surface->subpictures && !driver_data->overlay_auto_paint_color_key) {
944 XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
945 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
946 XSync((Display *)ctx->native_dpy, False);
947 }
948 }
949
950 if (driver_data->use_xrandr_thread && !driver_data->xrandr_thread_id) {
951 ret = psb_xrandr_thread_create(ctx);
952 if (ret != 0) {
953 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to create psb xrandr thread error # %d\n", __func__, ret);
954 return VA_STATUS_ERROR_UNKNOWN;
955 }
956 }
957
958 ret = psb_xrandr_local_crtc_coordinate(&local_device, &primary_crtc_x, &primary_crtc_y, &pPriv->display_width, &pPriv->display_height, &rotation);
959 if (ret != VA_STATUS_SUCCESS) {
960 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get primary crtc coordinates error # %d\n", __func__, ret);
961 return VA_STATUS_ERROR_UNKNOWN;
962 }
963 switch (local_device) {
964 case LVDS0:
965 case MIPI0:
966 local_pipe = PIPEA;
967 break;
968 /* single HDMI */
969 case HDMI:
970 local_pipe = PIPEB;
971 break;
972 case MIPI1:
973 local_pipe = PIPEC;
974 break;
975 }
976
977 if (!psb_xrandr_single_mode()) {
978
979 ret = psb_xrandr_extend_crtc_coordinate(&extend_device, &extend_crtc_x, &extend_crtc_y,
980 &pPriv->extend_display_width, &pPriv->extend_display_height, &extend_location, &rotation);
981 if (ret != VA_STATUS_SUCCESS) {
982 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend crtc coordinates error # %d\n", __func__, ret);
983 return VA_STATUS_ERROR_UNKNOWN;
984 }
985
986 switch (extend_device) {
987 case HDMI:
988 extend_pipe = PIPEB;
989 break;
990 case MIPI1:
991 extend_pipe = PIPEC;
992 break;
993 default:
994 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend pipe\n", __func__);
995 break;
996 }
997 }
998
999 /*clip in the window area*/
1000 if (destx < 0) {
1001 x11_window_width += destx;
1002 destx = 0;
1003 }
1004
1005 if (desty < 0) {
1006 x11_window_height += desty;
1007 desty = 0;
1008 }
1009
1010 if (srcx < 0) {
1011 srcw += srcx;
1012 srcx = 0;
1013 }
1014
1015 if (srcy < 0) {
1016 srch += srcy;
1017 srcy = 0;
1018 }
1019
1020 if ((destx + x11_window_width) > output->winRect.ui32Width)
1021 x11_window_width = output->winRect.ui32Width - destx;
1022
1023 if ((desty + x11_window_height) > output->winRect.ui32Height)
1024 x11_window_height = output->winRect.ui32Height - desty;
1025
1026 /*translate destx, desty into screen coordinate*/
1027 destx += output->winRect.i32Left;
1028 desty += output->winRect.i32Top;
1029
1030 /*clip in the screen area*/
1031 xScaleFactor = srcw * 1.0 / x11_window_width;
1032 yScaleFactor = srch * 1.0 / x11_window_height;
1033
1034 if (destx < 0) {
1035 x11_window_width += destx;
1036 srcx = (short)((-destx) * xScaleFactor);
1037 destx = 0;
1038 }
1039
1040 if (desty < 0) {
1041 x11_window_height += desty;
1042 srcy = (short)((-desty) * yScaleFactor);
1043 desty = 0;
1044 }
1045
1046 /* display by overlay */
1047 if (psb_xrandr_single_mode() || IS_MRST(driver_data)) {
1048 if ((destx + x11_window_width) > pPriv->display_width) {
1049 x11_window_width = pPriv->display_width - destx;
1050 srcw = (unsigned short)(x11_window_width * xScaleFactor);
1051 }
1052
1053 if ((desty + x11_window_height) > pPriv->display_height) {
1054 x11_window_height = pPriv->display_height - desty;
1055 srch = (unsigned short)(x11_window_height * yScaleFactor);
1056 }
1057
1058 if (!driver_data->overlay_auto_paint_color_key) {
1059 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1060 if (ret != 0) {
1061 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1062 return VA_STATUS_ERROR_UNKNOWN;
1063 }
1064 }
1065
1066 psb_putsurface_overlay(
1067 ctx, surface, srcx, srcy, srcw, srch,
1068 /* screen coordinate */
1069 destx, desty, x11_window_width, x11_window_height,
1070 flags, OVERLAY_A, local_pipe);
1071 } else if (psb_xrandr_clone_mode()) {
1072 psb_overlay_rect_t local_rect, extend_rect;
1073
1074 if (output->extend_drawable) {
1075 XDestroyWindow(ctx->native_dpy, output->extend_drawable);
1076 output->extend_drawable = 0;
1077 XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
1078 output->extend_gc = 0;
1079 }
1080
1081 if (((destx + x11_window_width) < pPriv->display_width) &&
1082 ((destx + x11_window_width) < pPriv->extend_display_width))
1083 local_rect.dWidth = extend_rect.dWidth = x11_window_width;
1084 else if (pPriv->display_width < pPriv->extend_display_width) {
1085 local_rect.dWidth = pPriv->display_width - destx;
1086 if ((destx + x11_window_width) > pPriv->extend_display_width)
1087 extend_rect.dWidth = x11_window_width = pPriv->extend_display_width - destx;
1088 else
1089 extend_rect.dWidth = x11_window_width;
1090 } else {
1091 extend_rect.dWidth = pPriv->extend_display_width - destx;
1092 if ((destx + x11_window_width) > pPriv->display_width)
1093 local_rect.dWidth = x11_window_width = pPriv->display_width - destx;
1094 else
1095 local_rect.dWidth = x11_window_width;
1096 }
1097
1098 if (((desty + x11_window_height) < pPriv->display_height) &&
1099 ((desty + x11_window_height) < pPriv->extend_display_height))
1100 local_rect.dHeight = extend_rect.dHeight = x11_window_height;
1101 else if (pPriv->display_height < pPriv->extend_display_height) {
1102 local_rect.dHeight = pPriv->display_height - desty;
1103 if ((desty + x11_window_height) > pPriv->extend_display_height)
1104 extend_rect.dHeight = x11_window_height = pPriv->extend_display_height - desty;
1105 else
1106 extend_rect.dHeight = x11_window_height;
1107 } else {
1108 extend_rect.dHeight = pPriv->extend_display_height - desty;
1109 if ((desty + x11_window_height) > pPriv->display_height)
1110 local_rect.dHeight = x11_window_height = pPriv->display_height - desty;
1111 else
1112 local_rect.dHeight = x11_window_height;
1113 }
1114 if ((driver_data->mipi0_rotation != VA_ROTATION_NONE) ||
1115 (driver_data->hdmi_rotation != VA_ROTATION_NONE)) {
1116 local_rect.sWidth = srcw;
1117 local_rect.sHeight = srch;
1118 extend_rect.sWidth = srcw;
1119 extend_rect.sHeight = srch;
1120 } else {
1121 local_rect.sWidth = (unsigned short)(local_rect.dWidth * xScaleFactor);
1122 local_rect.sHeight = (unsigned short)(local_rect.dHeight * yScaleFactor);
1123 extend_rect.sWidth = (unsigned short)(extend_rect.dWidth * xScaleFactor);
1124 extend_rect.sHeight = (unsigned short)(extend_rect.dHeight * yScaleFactor);
1125 }
1126 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1127 if (ret != 0) {
1128 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1129 return VA_STATUS_ERROR_UNKNOWN;
1130 }
1131 psb_putsurface_overlay(
1132 ctx, surface, srcx, srcy, extend_rect.sWidth, extend_rect.sHeight,
1133 /* screen coordinate */
1134 destx, desty, extend_rect.dWidth, extend_rect.dHeight,
1135 flags, OVERLAY_C, extend_pipe);
1136 psb_putsurface_overlay(
1137 ctx, surface, srcx, srcy, local_rect.sWidth, local_rect.sHeight,
1138 /* screen coordinate */
1139 destx, desty, local_rect.dWidth, local_rect.dHeight,
1140 flags, OVERLAY_A, local_pipe);
1141 } else if (psb_xrandr_extend_mode()) {
1142 if (driver_data->extend_fullscreen) {
1143 switch (extend_location) {
1144 case RIGHT_OF:
1145 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, pPriv->display_width, 0, pPriv->extend_display_width, pPriv->extend_display_height);
1146 break;
1147 case BELOW:
1148 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, pPriv->display_height, pPriv->extend_display_width, pPriv->extend_display_height);
1149 break;
1150 case LEFT_OF:
1151 case ABOVE:
1152 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
1153 break;
1154 default:
1155 break;
1156
1157 }
1158 XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
1159 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
1160 XFlush(ctx->native_dpy);
1161
1162 psb_putsurface_overlay(
1163 ctx, surface, srcx, srcy, srcw, srch,
1164 /* screen coordinate */
1165 0, 0, pPriv->extend_display_width, pPriv->extend_display_height,
1166 flags, OVERLAY_A, PIPEB);
1167 } else {
1168 psb_overlay_rect_t local_rect, extend_rect;
1169 enum overlay_id_t extend_overlay = OVERLAY_C;
1170
1171 if (output->extend_drawable) {
1172 XDestroyWindow(ctx->native_dpy, output->extend_drawable);
1173 output->extend_drawable = 0;
1174 XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
1175 output->extend_gc = 0;
1176 }
1177 memset(&local_rect, 0, sizeof(psb_overlay_rect_t));
1178 memset(&extend_rect, 0, sizeof(psb_overlay_rect_t));
1179 psb_extendMode_getCoordinate(pPriv, extend_location, destx, desty, srcx, srcy,
1180 xScaleFactor, yScaleFactor, &x11_window_width, &x11_window_height,
1181 &local_rect, &extend_rect, &extend_overlay);
1182
1183 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1184 if (ret != 0) {
1185 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1186 return VA_STATUS_ERROR_UNKNOWN;
1187 }
1188
1189 if ((extend_rect.dWidth > 0) && (extend_rect.dHeight > 0)) {
1190 psb_putsurface_overlay(
1191 ctx, surface,
1192 extend_rect.srcx, extend_rect.srcy, extend_rect.sWidth, extend_rect.sHeight,
1193 extend_rect.destx, extend_rect.desty, extend_rect.dWidth, extend_rect.dHeight,
1194 flags, extend_overlay, extend_pipe);
1195 }
1196 if ((local_rect.dWidth > 0) && (local_rect.dHeight > 0)) {
1197 psb_putsurface_overlay(
1198 ctx, surface,
1199 local_rect.srcx, local_rect.srcy, local_rect.sWidth, local_rect.sHeight,
1200 local_rect.destx, local_rect.desty, local_rect.dWidth, local_rect.dHeight,
1201 flags, OVERLAY_A, local_pipe);
1202 }
1203 }
1204 } else if (psb_xrandr_extvideo_mode()) {
1205 unsigned int xres, yres, xoffset, yoffset, overscanmode, pannelfitting, x, y;
1206 psb_extvideo_center center;
1207
1208 psb_xrandr_extvideo_prop(&xres, &yres, &xoffset, &yoffset, ¢er, &subtitle, &overscanmode, &pannelfitting);
1209 x = xoffset;
1210 y = yoffset;
1211
1212 switch (extend_location) {
1213 case RIGHT_OF:
1214 x += pPriv->display_width;
1215 break;
1216 case BELOW:
1217 y += pPriv->display_height;
1218 break;
1219 case NORMAL:
1220 break;
1221 case LEFT_OF:
1222 if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
1223 destx += pPriv->extend_display_width;
1224 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height);
1225 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
1226 XFlush(ctx->native_dpy);
1227 }
1228 destx = destx - pPriv->extend_display_width;
1229 break;
1230 case ABOVE:
1231 if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
1232 desty += pPriv->extend_display_height;
1233 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height);
1234 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
1235 XFlush(ctx->native_dpy);
1236 }
1237 desty = desty - pPriv->extend_display_height;
1238 break;
1239 }
1240 if ((destx + x11_window_width) > pPriv->display_width)
1241 x11_window_width = pPriv->display_width - destx;
1242 if ((desty + x11_window_height) > pPriv->display_height)
1243 x11_window_height = pPriv->display_height - desty;
1244
1245 if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
1246 Window extend_win;
1247 extend_win = psb_xrandr_create_full_screen_window(x, y, xres, yres);
1248 if (output->extend_drawable != extend_win) {
1249 output->extend_drawable = extend_win;
1250 if (output->extend_gc)
1251 XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
1252 output->extend_gc = XCreateGC((Display *)ctx->native_dpy, extend_win, 0, NULL);
1253
1254 /* paint the color key */
1255 if (!obj_surface->subpictures) {
1256 XSetForeground((Display *)ctx->native_dpy, output->extend_gc, pPriv->colorKey);
1257 XFillRectangle((Display *)ctx->native_dpy, extend_win, output->extend_gc, 0, 0, xres, yres);
1258 XSync((Display *)ctx->native_dpy, False);
1259 }
1260 }
1261 driver_data->xrandr_dirty &= ~PSB_NEW_EXTVIDEO;
1262 }
1263
1264 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1265 if (ret != 0) {
1266 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1267 return VA_STATUS_ERROR_UNKNOWN;
1268 }
1269
1270 psb_putsurface_overlay(
1271 ctx, surface, srcx, srcy, srcw, srch,
1272 /* screen coordinate */
1273 xoffset, yoffset, xres, yres,
1274 flags, OVERLAY_C, PIPEB);
1275 psb_putsurface_overlay(
1276 ctx, surface, srcx, srcy, srcw, srch,
1277 /* screen coordinate */
1278 destx, desty,
1279 x11_window_width, x11_window_height,
1280 flags, OVERLAY_A, local_pipe);
1281 }
1282
1283 /*Init Overlay subpicuture blending and make proper clear.*/
1284 if (pPriv->is_mfld && obj_surface->subpictures) {
1285 PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures;
1286
1287 psb_init_subpicture(ctx, pPriv);
1288 /*clear changed subpicture zones in drawable.*/
1289 psb_clear_subpictures(ctx, pPriv, x11_window_width, x11_window_height, obj_surface);
1290 if (pPriv->subpic_clear_flag) {
1291 psb_DisplayRGBASubpicture(subpicture, ctx, x11_window_width, x11_window_height,
1292 surfacex, surfacey, obj_surface->width, obj_surface->height, subtitle);
1293 }
1294 }
1295
1296 output->frame_count++;
1297
1298 return VA_STATUS_SUCCESS;
1299 }
1300