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(&regs, 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, &regs, 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, &center, &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