psb_coverlay.c revision c60d5b7bdb5616ca37e0b912c10725bec4320f33
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following conditions:
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice (including the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the Software.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Authors:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    Jason Hu  <jason.hu@intel.com>
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    Zhaohan Ren  <zhaohan.ren@intel.com>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    Shengquan Yuan  <shengquan.yuan@intel.com>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xutil.h>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xrandr.h>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <va/va_backend.h>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_output.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_surface.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_buffer.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_x11.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_surface_ext.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wsbm/wsbm_manager.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_drv_video.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "psb_xrandr.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INIT_OUTPUT_PRIV    psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SURFACE(id)     ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)psb_x11_getWindowCoordinate(Display * display,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            Window x11_window_id,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            psb_x11_win_t * psX11Window,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            int * pbIsVisible)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Window DummyWindow;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status status;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWindowAttributes sXWinAttrib;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((status = XGetWindowAttributes(display,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       x11_window_id,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &sXWinAttrib)) == 0) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates - error %lu\n", __func__, (unsigned long)status);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return -1;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psX11Window->i32Left = sXWinAttrib.x;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psX11Window->i32Top = sXWinAttrib.y;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psX11Window->ui32Width = sXWinAttrib.width;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psX11Window->ui32Height = sXWinAttrib.height;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pbIsVisible = (sXWinAttrib.map_state == IsViewable);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!*pbIsVisible)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (XTranslateCoordinates(display,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              x11_window_id,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              DefaultRootWindow(display),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &psX11Window->i32Left,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &psX11Window->i32Top,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &DummyWindow) == 0) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to tranlate X coordinates - error %lu\n", __func__, (unsigned long)status);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return -1;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psX11Window->i32Right  = psX11Window->i32Left + psX11Window->ui32Width - 1;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psX11Window->i32Bottom = psX11Window->i32Top + psX11Window->ui32Height - 1;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static psb_x11_clip_list_t *
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)psb_x11_createClipBoxNode(psb_x11_win_t *       pRect,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          psb_x11_clip_list_t * pClipNext)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    psb_x11_clip_list_t * pCurrent = NULL;
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCurrent = (psb_x11_clip_list_t *)calloc(1, sizeof(psb_x11_clip_list_t));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pCurrent) {
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        pCurrent->rect = *pRect;
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        pCurrent->next = pClipNext;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return pCurrent;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return pClipNext;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)psb_x11_freeWindowClipBoxList(psb_x11_clip_list_t * pHead)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psb_x11_clip_list_t * pNext = NULL;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (pHead) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNext = pHead->next;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        free(pHead);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pHead = pNext;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define IS_BETWEEN_RANGE(a,b,c) ((a<=b)&&(b<=c))
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static psb_x11_clip_list_t *
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)psb_x11_substractRects(Display *             display,
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       psb_x11_clip_list_t * psRegion,
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       psb_x11_win_t *       psRect)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    psb_x11_clip_list_t * psCur, * psPrev, * psFirst, * psNext;
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    psb_x11_win_t sCreateRect;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int display_width  = (int)(DisplayWidth(display, DefaultScreen(display))) - 1;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int display_height = (int)(DisplayHeight(display, DefaultScreen(display))) - 1;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    psFirst = psb_x11_createClipBoxNode(psRect, NULL);
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (psFirst->rect.i32Left < 0)
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        psFirst->rect.i32Left = 0;
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    else if (psFirst->rect.i32Left > display_width)
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        psFirst->rect.i32Left = display_width;
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (psFirst->rect.i32Right < 0)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psFirst->rect.i32Right = 0;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else if (psFirst->rect.i32Right > display_width)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psFirst->rect.i32Right = display_width;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (psFirst->rect.i32Top < 0)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psFirst->rect.i32Top = 0;
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else if (psFirst->rect.i32Top > display_height)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psFirst->rect.i32Top = display_height;
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (psFirst->rect.i32Bottom < 0)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psFirst->rect.i32Bottom = 0;
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else if (psFirst->rect.i32Bottom > display_height)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psFirst->rect.i32Bottom = display_height;
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (psRegion) {
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psCur  = psFirst;
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        psPrev = NULL;
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        while (psCur) {
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            psNext = psCur->next;
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if ((psRegion->rect.i32Left > psCur->rect.i32Left) &&
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                (psRegion->rect.i32Left <= psCur->rect.i32Right)) {
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sCreateRect.i32Right = psRegion->rect.i32Left - 1;
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                sCreateRect.i32Left = psCur->rect.i32Left;
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                sCreateRect.i32Top = psCur->rect.i32Top;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Bottom = psCur->rect.i32Bottom;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                if (!psPrev)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    psPrev = psFirst;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                psCur->rect.i32Left = psRegion->rect.i32Left;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((psRegion->rect.i32Right >= psCur->rect.i32Left) &&
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (psRegion->rect.i32Right < psCur->rect.i32Right))
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Left = psRegion->rect.i32Right + 1;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Right = psCur->rect.i32Right;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Top = psCur->rect.i32Top;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Bottom = psCur->rect.i32Bottom;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (!psPrev)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    psPrev = psFirst;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                psCur->rect.i32Right = psRegion->rect.i32Right;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((psRegion->rect.i32Top > psCur->rect.i32Top) &&
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (psRegion->rect.i32Top <= psCur->rect.i32Bottom)) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Bottom = psRegion->rect.i32Top - 1;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Left   = psCur->rect.i32Left;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Right  = psCur->rect.i32Right;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Top    = psCur->rect.i32Top;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (!psPrev)
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    psPrev = psFirst;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                psCur->rect.i32Top = psRegion->rect.i32Top;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((psRegion->rect.i32Bottom >= psCur->rect.i32Top) &&
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (psRegion->rect.i32Bottom <  psCur->rect.i32Bottom)) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Top    = psRegion->rect.i32Bottom + 1;
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                sCreateRect.i32Left   = psCur->rect.i32Left;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Right  = psCur->rect.i32Right;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sCreateRect.i32Bottom = psCur->rect.i32Bottom;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                if (!psPrev)
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    psPrev = psFirst;
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                psCur->rect.i32Bottom = psRegion->rect.i32Bottom;
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            }
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if ((IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Left,   psRegion->rect.i32Right)) &&
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Right,  psRegion->rect.i32Right)) &&
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (IS_BETWEEN_RANGE(psRegion->rect.i32Top,  psCur->rect.i32Top,    psRegion->rect.i32Bottom)) &&
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (IS_BETWEEN_RANGE(psRegion->rect.i32Top,  psCur->rect.i32Bottom, psRegion->rect.i32Bottom))) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (psPrev) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    psPrev->next = psCur->next;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    free(psCur);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    psCur = psPrev;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                } else {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    free(psCur);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    psCur = NULL;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    psFirst = psNext;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            psPrev = psCur;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            psCur  = psNext;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }//while(psCur)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        psRegion = psRegion->next;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }//while(psRegion)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return psFirst;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)psb_x11_createWindowClipBoxList(Display *              display,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Window                 x11_window_id,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                psb_x11_clip_list_t ** ppWindowClipBoxList,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                unsigned int *         pui32NumClipBoxList)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Window CurrentWindow = x11_window_id;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Window RootWindow, ParentWindow, ChildWindow;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Window * pChildWindow;
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Status XResult;
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    unsigned int i32NumChildren, i;
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int bIsVisible;
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    unsigned int ui32NumRects = 0;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psb_x11_clip_list_t *psRegions = NULL;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psb_x11_win_t sRect;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!display || (!ppWindowClipBoxList) || (!pui32NumClipBoxList))
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return -1;
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    XResult = XQueryTree(display,
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         CurrentWindow,
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         &RootWindow,
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         &ParentWindow,
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         &pChildWindow,
2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         &i32NumChildren);
2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (XResult == 0)
2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return -2;
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (i32NumChildren) {
2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        for (i = 0; i < i32NumChildren; i++) {
2826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible);
2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (bIsVisible) {
2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                psRegions = psb_x11_createClipBoxNode(&sRect, psRegions);
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                ui32NumRects++;
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        XFree(pChildWindow);
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        i32NumChildren = 0;
2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    while (CurrentWindow != RootWindow) {
2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        ChildWindow   = CurrentWindow;
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        CurrentWindow = ParentWindow;
2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        XResult = XQueryTree(display,
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             CurrentWindow,
2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             &RootWindow,
3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             &ParentWindow,
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             &pChildWindow,
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             &i32NumChildren);
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (XResult == 0) {
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (i32NumChildren)
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                XFree(pChildWindow);
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            psb_x11_freeWindowClipBoxList(psRegions);
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            return -3;
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (i32NumChildren) {
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            unsigned int iStartWindow = 0;
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            for (i = 0; i < i32NumChildren; i++) {
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                if (pChildWindow[i] == ChildWindow) {
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    iStartWindow = i;
3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    break;
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                }
3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (i == i32NumChildren) {
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                XFree(pChildWindow);
3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                psb_x11_freeWindowClipBoxList(psRegions);
3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                return -4;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = iStartWindow + 1; i < i32NumChildren; i++) {
328                psb_x11_getWindowCoordinate(display, pChildWindow[i], &sRect, &bIsVisible);
329                if (bIsVisible) {
330                    psRegions = psb_x11_createClipBoxNode(&sRect, psRegions);
331                    ui32NumRects++;
332                }
333            }
334
335            XFree(pChildWindow);
336        }
337    }
338
339    ui32NumRects = 0;
340
341    if (psRegions) {
342        psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible);
343        *ppWindowClipBoxList = psb_x11_substractRects(display, psRegions, &sRect);
344        psb_x11_freeWindowClipBoxList(psRegions);
345
346        psRegions = *ppWindowClipBoxList;
347
348        while (psRegions) {
349            ui32NumRects++;
350            psRegions = psRegions->next;
351        }
352    } else {
353        *ppWindowClipBoxList = psb_x11_substractRects(display, NULL, &sRect);
354        ui32NumRects = 1;
355    }
356
357    *pui32NumClipBoxList = ui32NumRects;
358
359    return 0;
360}
361
362static int psb_cleardrawable_stopoverlay(
363    VADriverContextP ctx,
364    Drawable draw, /* X Drawable */
365    short destx,
366    short desty,
367    unsigned short destw,
368    unsigned short desth
369)
370{
371    INIT_DRIVER_DATA;
372    INIT_OUTPUT_PRIV;
373
374    XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth);
375    XSync((Display *)ctx->native_dpy, False);
376
377    driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
378    driver_data->last_displaying_surface = VA_INVALID_SURFACE;
379
380    return 0;
381}
382
383static VAStatus psb_DisplayRGBASubpicture(
384    PsbVASurfaceRec *subpicture,
385    VADriverContextP ctx,
386    int win_width,
387    int win_height,
388    int surface_x,
389    int surface_y,
390    int surface_w,
391    int surface_h,
392    psb_extvideo_subtitle subtitle
393)
394{
395    INIT_DRIVER_DATA;
396    INIT_OUTPUT_PRIV;
397    XImage *ximg = NULL;
398    Visual *visual;
399    PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
400    struct _WsbmBufferObject *bo = subpicture->bo;
401    int image_width, image_height, width, height, size;
402    int srcx, srcy, srcw, srch;
403    int destx, desty, destw, desth;
404    int depth, i;
405
406    if (subpicture->fourcc != VA_FOURCC_RGBA) {
407        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid image format, ONLY support RGBA subpicture now.\n", __func__);
408        return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
409    }
410
411    for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) {
412        srcx = subpicture->subpic_srcx;
413        srcy = subpicture->subpic_srcy;
414        srcw = subpicture->subpic_srcw;
415        srch = subpicture->subpic_srch;
416
417        destx = subpicture->subpic_dstx + surface_x;
418        desty = subpicture->subpic_dsty + surface_y;
419        destw = subpicture->subpic_dstw;
420        desth = subpicture->subpic_dsth;
421
422        image_width = subpicture->width;
423        image_height = subpicture->height;
424        size = subpicture->size;
425
426        //clip in image region
427        if (srcx < 0) {
428            srcw += srcx;
429            srcx = 0;
430        }
431
432        if (srcy < 0) {
433            srch += srcy;
434            srcy = 0;
435        }
436
437        if ((srcx + srcw) > image_width)
438            srcw = image_width - srcx;
439        if ((srcy + srch) > image_height)
440            srch = image_height - srcy;
441
442        //clip in drawable region
443        if (destx < 0) {
444            destw += destx;
445            destx = 0;
446        }
447
448        if (desty < 0) {
449            desth += desty;
450            desty = 0;
451        }
452
453        if ((destx + destw) > surface_w)
454            destw = surface_w - destx;
455        if ((desty + desth) > surface_h)
456            desth = surface_h - desty;
457
458        if (srcw <= destw)
459            width = srcw;
460        else
461            width = destw;
462
463        if (srch <= desth)
464            height = srch;
465        else
466            height = desth;
467
468        visual = DefaultVisual(ctx->native_dpy, 0);
469        depth = DefaultDepth(ctx->native_dpy, 0);
470
471        ximg = XCreateImage(ctx->native_dpy, visual, depth, ZPixmap, 0, NULL, image_width, image_height, 32, 0);
472
473        if (NULL == ximg) {
474            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: XCreateImage failed! at L%d\n", __func__, __LINE__);
475            return VA_STATUS_ERROR_UNKNOWN;
476        }
477
478        ximg->data = wsbmBOMap(bo, WSBM_ACCESS_READ);
479        if (NULL == ximg->data) {
480            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to map to ximg->data.\n", __func__);
481            return VA_STATUS_ERROR_ALLOCATION_FAILED;
482        }
483
484        pPriv->clear_key[i].subpic_dstx = destx;
485        pPriv->clear_key[i].subpic_dsty = desty;
486        pPriv->clear_key[i].subpic_dstw = destw;
487        pPriv->clear_key[i].subpic_dsth = desth;
488        if (psb_xrandr_extvideo_mode()) {
489            /*It is a HACK: Adjust subtitle to proper position.*/
490            float xScale, yScale;
491
492            xScale = win_width * 1.0 / surface_w;
493            yScale = win_height * 1.0 / surface_h;
494            destx = subpicture->subpic_dstx * xScale;
495            desty = subpicture->subpic_dsty * yScale;
496        }
497        XPutImage(ctx->native_dpy, output->output_drawable, output->gc, ximg, srcx, srcy, destx, desty, width, height);
498        XSync((Display *)ctx->native_dpy, False);
499
500        if (psb_xrandr_extvideo_mode() &&
501            (subtitle == ONLY_HDMI || subtitle == BOTH)) {
502            float xScale, yScale;
503
504            xScale = pPriv->extend_display_width * 1.0 / surface_w;
505            yScale = pPriv->extend_display_height * 1.0 / surface_h;
506
507            destx = subpicture->subpic_dstx * xScale;
508            desty = subpicture->subpic_dsty * yScale;
509
510            XPutImage(ctx->native_dpy, output->extend_drawable, output->extend_gc, ximg,
511                      srcx, srcy, destx, desty, destw, desth);
512            XSync((Display *)ctx->native_dpy, False);
513        }
514
515        pPriv->subpic_clear_flag = 0;
516        ximg->data = NULL;
517        wsbmBOUnmap(bo);
518        if (NULL != ximg)
519            XDestroyImage(ximg);
520    }
521    return VA_STATUS_SUCCESS;
522}
523
524static VAStatus psb_repaint_colorkey(
525    VADriverContextP ctx,
526    Drawable draw, /* X Drawable */
527    VASurfaceID surface,
528    int x11_window_width,
529    int x11_window_height
530)
531{
532    INIT_DRIVER_DATA;
533    INIT_OUTPUT_PRIV;
534    int i, ret;
535    psb_x11_clip_list_t *pClipNext = NULL;
536    VARectangle *pVaWindowClipRects = NULL;
537    object_surface_p obj_surface = SURFACE(surface);
538    PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
539
540    if (output->frame_count % 500 == 0 || driver_data->xrandr_update) {
541        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Repaint color key.\n");
542        if (output->pClipBoxList)
543            psb_x11_freeWindowClipBoxList(output->pClipBoxList);
544        /* get window clipbox */
545        ret = psb_x11_createWindowClipBoxList(ctx->native_dpy, draw, &output->pClipBoxList, &output->ui32NumClipBoxList);
546        if (ret != 0) {
547            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: get window clip boxes error # %d\n", __func__, ret);
548            return VA_STATUS_ERROR_UNKNOWN;
549        }
550        if (output->frame_count == 500)
551            output->frame_count = 0;
552
553        driver_data->xrandr_update = 0;
554    }
555
556    pVaWindowClipRects = (VARectangle *)calloc(1, sizeof(VARectangle) * output->ui32NumClipBoxList);
557    if (!pVaWindowClipRects) {
558        psb_x11_freeWindowClipBoxList(output->pClipBoxList);
559        return VA_STATUS_ERROR_ALLOCATION_FAILED;
560    }
561
562    memset(pVaWindowClipRects, 0, sizeof(VARectangle)*output->ui32NumClipBoxList);
563    pClipNext = output->pClipBoxList;
564#ifdef CLIP_DEBUG
565    drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Total %d clip boxes\n", __func__, output->ui32NumClipBoxList);
566#endif
567    for (i = 0; i < output->ui32NumClipBoxList; i++) {
568        pVaWindowClipRects[i].x      = pClipNext->rect.i32Left;
569        pVaWindowClipRects[i].y      = pClipNext->rect.i32Top;
570        pVaWindowClipRects[i].width  = pClipNext->rect.i32Right - pClipNext->rect.i32Left;
571        pVaWindowClipRects[i].height = pClipNext->rect.i32Bottom - pClipNext->rect.i32Top;
572#ifdef CLIP_DEBUG
573        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: clip boxes Left Top (%d, %d) Right Bottom (%d, %d) width %d height %d\n", __func__,
574                           pClipNext->rect.i32Left, pClipNext->rect.i32Top,
575                           pClipNext->rect.i32Right, pClipNext->rect.i32Bottom,
576                           pVaWindowClipRects[i].width, pVaWindowClipRects[i].height);
577#endif
578        pClipNext = pClipNext->next;
579    }
580
581    /* repaint the color key when window size changed*/
582    if (!obj_surface->subpictures &&
583        ((pPriv->x11_window_width != x11_window_width) ||
584         (pPriv->x11_window_height != x11_window_height))) {
585        pPriv->x11_window_width = x11_window_width;
586        pPriv->x11_window_height = x11_window_height;
587        XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
588        XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
589        XSync((Display *)ctx->native_dpy, False);
590    }
591
592
593    if ((!obj_surface->subpictures) &&
594        ((output->ui32NumClipBoxList != pPriv->last_num_clipbox) ||
595         (memcmp(&pVaWindowClipRects[0], &(pPriv->last_clipbox[0]), (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle)) != 0))) {
596        pPriv->last_num_clipbox = output->ui32NumClipBoxList;
597        memcpy(&pPriv->last_clipbox[0], &pVaWindowClipRects[0], (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle));
598        XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
599        XSync((Display *)ctx->native_dpy, False);
600    }
601
602    free(pVaWindowClipRects);
603
604    return VA_STATUS_SUCCESS;
605}
606
607static VAStatus psb_extendMode_getCoordinate(
608    PsbPortPrivPtr pPriv,
609    psb_xrandr_location extend_location,
610    short destx,
611    short desty,
612    short srcx,
613    short srcy,
614    float xScaleFactor,
615    float yScaleFactor,
616    int *x11_window_width,
617    int *x11_window_height,
618    psb_overlay_rect_p local_rect,
619    psb_overlay_rect_p extend_rect,
620    enum overlay_id_t *extend_overlay
621)
622{
623    switch (extend_location) {
624    case LEFT_OF:
625        if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) {
626            *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx;
627        }
628        if (((desty + *x11_window_height) < pPriv->display_height) &&
629            ((desty + *x11_window_height) < pPriv->extend_display_height))
630            local_rect->dHeight = extend_rect->dHeight = *x11_window_height;
631        else if (pPriv->display_height < pPriv->extend_display_height) {
632            local_rect->dHeight = pPriv->display_height - desty;
633            if ((desty + *x11_window_height) > pPriv->extend_display_height)
634                extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty;
635            else
636                extend_rect->dHeight = *x11_window_height;
637        } else {
638            extend_rect->dHeight = pPriv->extend_display_height - desty;
639            if ((desty + *x11_window_height) > pPriv->display_height)
640                local_rect->dHeight = *x11_window_height = pPriv->display_height - desty;
641            else
642                local_rect->dHeight = *x11_window_height;
643        }
644
645        if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) < pPriv->extend_display_width)) {
646            local_rect->dWidth = 0;
647            extend_rect->dWidth = *x11_window_width;
648            *extend_overlay = OVERLAY_A;
649            local_rect->destx = 0;
650        } else if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) >= pPriv->extend_display_width)) {
651            extend_rect->dWidth = pPriv->extend_display_width - destx;
652            local_rect->dWidth = *x11_window_width - extend_rect->dWidth;
653            local_rect->destx = 0;
654        } else {
655            local_rect->dWidth = *x11_window_width;
656            extend_rect->dWidth = 0;
657            local_rect->destx = destx - pPriv->extend_display_width;
658        }
659        local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
660        local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
661        extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
662        extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
663
664        local_rect->srcx = srcx + extend_rect->sWidth;
665        extend_rect->srcx = srcx;
666        local_rect->srcy = extend_rect->srcy = srcy;
667
668        extend_rect->destx = destx;
669        local_rect->desty = extend_rect->desty = desty;
670        break;
671    case RIGHT_OF:
672        if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) {
673            *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx;
674        }
675        if (((desty + *x11_window_height) < pPriv->display_height) &&
676            ((desty + *x11_window_height) < pPriv->extend_display_height))
677            local_rect->dHeight = extend_rect->dHeight = *x11_window_height;
678        else if (pPriv->display_height < pPriv->extend_display_height) {
679            local_rect->dHeight = pPriv->display_height - desty;
680            if ((desty + *x11_window_height) > pPriv->extend_display_height)
681                extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty;
682            else
683                extend_rect->dHeight = *x11_window_height;
684        } else {
685            extend_rect->dHeight = pPriv->extend_display_height - desty;
686            if ((desty + *x11_window_height) > pPriv->display_height)
687                local_rect->dHeight = *x11_window_height = pPriv->display_height - desty;
688            else
689                local_rect->dHeight = *x11_window_height;
690        }
691
692        if ((destx < pPriv->display_width) && ((destx + *x11_window_width) < pPriv->display_width)) {
693            local_rect->dWidth = *x11_window_width;
694            extend_rect->dWidth = 0;
695            extend_rect->destx = 0;
696        } else if ((destx < pPriv->display_width) && ((destx + *x11_window_width) >= pPriv->display_width)) {
697            local_rect->dWidth = pPriv->display_width - destx;
698            extend_rect->dWidth = *x11_window_width - local_rect->dWidth;
699            extend_rect->destx = 0;
700        } else {
701            local_rect->dWidth = 0;
702            extend_rect->dWidth = *x11_window_width;
703            *extend_overlay = OVERLAY_A;
704            extend_rect->destx = destx - pPriv->display_width;
705        }
706        local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
707        local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
708        extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
709        extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
710
711        local_rect->srcx = srcx;
712        extend_rect->srcx = srcx + local_rect->sWidth;
713        local_rect->srcy = extend_rect->srcy = srcy;
714
715        local_rect->destx = destx;
716        local_rect->desty = extend_rect->desty = desty;
717        break;
718    case ABOVE:
719        if (((destx + *x11_window_width) < pPriv->display_width) &&
720            ((destx + *x11_window_width) < pPriv->extend_display_width))
721            local_rect->dWidth = extend_rect->dWidth = *x11_window_width;
722        else if (pPriv->display_width < pPriv->extend_display_width) {
723            local_rect->dWidth = pPriv->display_width - destx;
724            if ((destx + *x11_window_width) > pPriv->extend_display_width)
725                extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx;
726            else
727                extend_rect->dWidth = *x11_window_width;
728        } else {
729            extend_rect->dWidth = pPriv->extend_display_width - destx;
730            if ((destx + *x11_window_width) > pPriv->display_width)
731                local_rect->dWidth = *x11_window_width = pPriv->display_width - destx;
732            else
733                local_rect->dWidth = *x11_window_width;
734        }
735
736        if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) {
737            *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty;
738        }
739
740        if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) < pPriv->extend_display_height)) {
741            local_rect->dHeight = 0;
742            extend_rect->dHeight = *x11_window_height;
743            *extend_overlay = OVERLAY_A;
744            local_rect->desty = 0;
745        } else if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) >= pPriv->extend_display_height)) {
746            extend_rect->dHeight = pPriv->extend_display_height - desty;
747            local_rect->dHeight = *x11_window_height - extend_rect->dHeight;
748            local_rect->desty = 0;
749        } else {
750            local_rect->dHeight = *x11_window_height;
751            extend_rect->dHeight = 0;
752            local_rect->desty = desty - pPriv->extend_display_height;
753        }
754        local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
755        local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
756        extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
757        extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
758
759        local_rect->srcy = srcy + extend_rect->sHeight;
760        extend_rect->srcy = srcy;
761        local_rect->srcx = extend_rect->srcx = srcx;
762
763        extend_rect->desty = desty;
764        local_rect->destx = extend_rect->destx = destx;
765        break;
766    case BELOW:
767        if (((destx + *x11_window_width) < pPriv->display_width) &&
768            ((destx + *x11_window_width) < pPriv->extend_display_width))
769            local_rect->dWidth = extend_rect->dWidth = *x11_window_width;
770        else if (pPriv->display_width < pPriv->extend_display_width) {
771            local_rect->dWidth = pPriv->display_width - destx;
772            if ((destx + *x11_window_width) > pPriv->extend_display_width)
773                extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx;
774            else
775                extend_rect->dWidth = *x11_window_width;
776        } else {
777            extend_rect->dWidth = pPriv->extend_display_width - destx;
778            if ((destx + *x11_window_width) > pPriv->display_width)
779                local_rect->dWidth = *x11_window_width = pPriv->display_width - destx;
780            else
781                local_rect->dWidth = *x11_window_width;
782        }
783
784        if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) {
785            *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty;
786        }
787
788        if ((desty < pPriv->display_height) && ((desty + *x11_window_height) < pPriv->display_height)) {
789            local_rect->dHeight = *x11_window_height;
790            extend_rect->dHeight = 0;
791            extend_rect->desty = 0;
792        } else if ((desty < pPriv->display_height) && ((desty + *x11_window_height) >= pPriv->display_height)) {
793            local_rect->dHeight = pPriv->display_height - desty;
794            extend_rect->dHeight = *x11_window_height - local_rect->dHeight;
795            extend_rect->desty = 0;
796        } else {
797            local_rect->dHeight = 0;
798            extend_rect->dHeight = *x11_window_height;
799            *extend_overlay = OVERLAY_A;
800            extend_rect->desty = desty - pPriv->display_height;
801        }
802        local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
803        local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
804        extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
805        extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
806
807        local_rect->srcy = srcy;
808        extend_rect->srcy = srcy + local_rect->sHeight;
809        local_rect->srcx = extend_rect->srcx = srcx;
810
811        local_rect->desty = desty;
812        local_rect->destx = extend_rect->destx = destx;
813        break;
814    case NORMAL:
815    default:
816        break;
817    }
818    return VA_STATUS_SUCCESS;
819}
820
821static void psb_init_subpicture(VADriverContextP ctx, PsbPortPrivPtr pPriv)
822{
823    INIT_DRIVER_DATA;
824    struct drm_psb_register_rw_arg regs;
825    unsigned int subpicture_enable_mask = REGRWBITS_DSPACNTR;
826
827    if (!pPriv->subpicture_enabled) {
828        if (psb_xrandr_hdmi_enabled())
829            subpicture_enable_mask |= REGRWBITS_DSPBCNTR;
830        if (psb_xrandr_mipi1_enabled())
831            subpicture_enable_mask |= REGRWBITS_DSPCCNTR;
832
833        memset(&regs, 0, sizeof(regs));
834        regs.subpicture_enable_mask = subpicture_enable_mask;
835        pPriv->subpicture_enable_mask = subpicture_enable_mask;
836        pPriv->subpicture_enabled = 1;
837        drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
838    }
839}
840
841static void psb_clear_subpictures(
842    VADriverContextP ctx,
843    PsbPortPrivPtr pPriv,
844    int win_width,
845    int win_height,
846    object_surface_p obj_surface
847)
848{
849    INIT_OUTPUT_PRIV;
850    PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures;
851    int i;
852
853    if (subpicture == NULL) {
854        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Surface has no subpicture to render.\n");
855        return;
856    }
857
858    for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) {
859        if ((subpicture->subpic_dstx != pPriv->clear_key[i].subpic_dstx) ||
860            (subpicture->subpic_dsty != pPriv->clear_key[i].subpic_dsty) ||
861            (subpicture->subpic_dstw != pPriv->clear_key[i].subpic_dstw) ||
862            (subpicture->subpic_dsth != pPriv->clear_key[i].subpic_dsth)) {
863            XSetForeground((Display *)ctx->native_dpy, output->gc, 0);
864            XFillRectangle((Display *)ctx->native_dpy, output->output_drawable, output->gc, 0, 0, win_width, win_height);
865            XSync((Display *)ctx->native_dpy, False);
866            if (psb_xrandr_extvideo_mode()) {
867                XSetForeground((Display *)ctx->native_dpy, output->extend_gc, 0);
868                XFillRectangle((Display *)ctx->native_dpy, output->extend_drawable, output->extend_gc,
869                               0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
870                XSync((Display *)ctx->native_dpy, False);
871            }
872            pPriv->subpic_clear_flag = 1;
873        }
874    }
875    return;
876}
877
878VAStatus psb_putsurface_coverlay(
879    VADriverContextP ctx,
880    VASurfaceID surface,
881    Drawable draw, /* X Drawable */
882    short srcx,
883    short srcy,
884    unsigned short srcw,
885    unsigned short srch,
886    short destx,
887    short desty,
888    unsigned short destw,
889    unsigned short desth,
890    VARectangle *cliprects, /* client supplied clip list */
891    unsigned int number_cliprects, /* number of clip rects in the clip list */
892    unsigned int flags /* de-interlacing flags */
893)
894{
895    INIT_DRIVER_DATA;
896    INIT_OUTPUT_PRIV;
897    int ret;
898    int x11_window_width = destw, x11_window_height = desth;
899    psb_xrandr_location extend_location;
900    object_surface_p obj_surface = SURFACE(surface);
901    PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
902    int primary_crtc_x, primary_crtc_y, extend_crtc_x, extend_crtc_y;
903    enum pipe_id_t local_pipe = PIPEA, extend_pipe = PIPEB;
904    int surfacex = destx, surfacey = desty;
905    float xScaleFactor, yScaleFactor;
906    Rotation rotation = RR_Rotate_0;
907    psb_output_device local_device, extend_device;
908    psb_extvideo_subtitle subtitle;
909
910    if (flags & VA_CLEAR_DRAWABLE) {
911        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color);
912        psb_cleardrawable_stopoverlay(ctx, draw, destx, desty, destw, desth);
913
914        return VA_STATUS_SUCCESS;
915    }
916
917    if (output->frame_count % 500 == 0 || driver_data->xrandr_update) {
918        /* get window screen coordination */
919        ret = psb_x11_getWindowCoordinate(ctx->native_dpy, draw, &output->winRect, &output->bIsVisible);
920        if (ret != 0) {
921            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates error # %d\n", __func__, ret);
922            return VA_STATUS_ERROR_UNKNOWN;
923        }
924    }
925
926    if (!output->bIsVisible) {
927        return VA_STATUS_SUCCESS;
928    }
929
930    if (NULL == obj_surface) {
931        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid surface id 0x%08x.\n", __func__, surface);
932        return VA_STATUS_ERROR_INVALID_SURFACE;
933    }
934
935    if (output->output_drawable != draw) {
936        output->output_drawable = draw;
937    }
938
939    if (!output->gc) {
940        output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL);
941        /* paint the color key */
942        if (!obj_surface->subpictures && !driver_data->overlay_auto_paint_color_key) {
943            XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
944            XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
945            XSync((Display *)ctx->native_dpy, False);
946        }
947    }
948
949    if (driver_data->use_xrandr_thread && !driver_data->xrandr_thread_id) {
950        ret = psb_xrandr_thread_create(ctx);
951        if (ret != 0) {
952            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to create psb xrandr thread error # %d\n", __func__, ret);
953            return VA_STATUS_ERROR_UNKNOWN;
954        }
955    }
956
957    ret = psb_xrandr_local_crtc_coordinate(&local_device, &primary_crtc_x, &primary_crtc_y, &pPriv->display_width, &pPriv->display_height, &rotation);
958    if (ret != VA_STATUS_SUCCESS) {
959        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get primary crtc coordinates error # %d\n", __func__, ret);
960        return VA_STATUS_ERROR_UNKNOWN;
961    }
962    switch (local_device) {
963    case LVDS0:
964    case MIPI0:
965        local_pipe = PIPEA;
966        break;
967        /* single HDMI */
968    case HDMI:
969        local_pipe = PIPEB;
970        break;
971    case MIPI1:
972        local_pipe = PIPEC;
973        break;
974    }
975
976    if (!psb_xrandr_single_mode()) {
977
978        ret = psb_xrandr_extend_crtc_coordinate(&extend_device, &extend_crtc_x, &extend_crtc_y,
979                                                &pPriv->extend_display_width, &pPriv->extend_display_height, &extend_location, &rotation);
980        if (ret != VA_STATUS_SUCCESS) {
981            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend crtc coordinates error # %d\n", __func__, ret);
982            return VA_STATUS_ERROR_UNKNOWN;
983        }
984
985        switch (extend_device) {
986        case HDMI:
987            extend_pipe = PIPEB;
988            break;
989        case MIPI1:
990            extend_pipe = PIPEC;
991            break;
992        default:
993            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend pipe\n", __func__);
994            break;
995        }
996    }
997
998    /*clip in the window area*/
999    if (destx < 0) {
1000        x11_window_width += destx;
1001        destx = 0;
1002    }
1003
1004    if (desty < 0) {
1005        x11_window_height += desty;
1006        desty = 0;
1007    }
1008
1009    if (srcx < 0) {
1010        srcw += srcx;
1011        srcx = 0;
1012    }
1013
1014    if (srcy < 0) {
1015        srch += srcy;
1016        srcy = 0;
1017    }
1018
1019    if ((destx + x11_window_width) > output->winRect.ui32Width)
1020        x11_window_width = output->winRect.ui32Width - destx;
1021
1022    if ((desty + x11_window_height) > output->winRect.ui32Height)
1023        x11_window_height = output->winRect.ui32Height - desty;
1024
1025    /*translate destx, desty into screen coordinate*/
1026    destx += output->winRect.i32Left;
1027    desty += output->winRect.i32Top;
1028
1029    /*clip in the screen area*/
1030    xScaleFactor = srcw * 1.0 / x11_window_width;
1031    yScaleFactor = srch * 1.0 / x11_window_height;
1032
1033    if (destx < 0) {
1034        x11_window_width += destx;
1035        srcx = (short)((-destx) * xScaleFactor);
1036        destx = 0;
1037    }
1038
1039    if (desty < 0) {
1040        x11_window_height += desty;
1041        srcy = (short)((-desty) * yScaleFactor);
1042        desty = 0;
1043    }
1044
1045    /* display by overlay */
1046    if (psb_xrandr_single_mode() || IS_MRST(driver_data)) {
1047        if ((destx + x11_window_width) > pPriv->display_width) {
1048            x11_window_width = pPriv->display_width - destx;
1049            srcw = (unsigned short)(x11_window_width * xScaleFactor);
1050        }
1051
1052        if ((desty + x11_window_height) > pPriv->display_height) {
1053            x11_window_height = pPriv->display_height - desty;
1054            srch = (unsigned short)(x11_window_height * yScaleFactor);
1055        }
1056
1057        if (!driver_data->overlay_auto_paint_color_key) {
1058            ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1059            if (ret != 0) {
1060                drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1061                return VA_STATUS_ERROR_UNKNOWN;
1062            }
1063        }
1064
1065        psb_putsurface_overlay(
1066            ctx, surface, srcx, srcy, srcw, srch,
1067            /* screen coordinate */
1068            destx, desty, x11_window_width, x11_window_height,
1069            flags, OVERLAY_A, local_pipe);
1070    } else if (psb_xrandr_clone_mode()) {
1071        psb_overlay_rect_t local_rect, extend_rect;
1072
1073        if (output->extend_drawable) {
1074            XDestroyWindow(ctx->native_dpy, output->extend_drawable);
1075            output->extend_drawable = 0;
1076            XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
1077            output->extend_gc = 0;
1078        }
1079
1080        if (((destx + x11_window_width) < pPriv->display_width) &&
1081            ((destx + x11_window_width) < pPriv->extend_display_width))
1082            local_rect.dWidth = extend_rect.dWidth = x11_window_width;
1083        else if (pPriv->display_width < pPriv->extend_display_width) {
1084            local_rect.dWidth = pPriv->display_width - destx;
1085            if ((destx + x11_window_width) > pPriv->extend_display_width)
1086                extend_rect.dWidth = x11_window_width = pPriv->extend_display_width - destx;
1087            else
1088                extend_rect.dWidth = x11_window_width;
1089        } else {
1090            extend_rect.dWidth = pPriv->extend_display_width - destx;
1091            if ((destx + x11_window_width) > pPriv->display_width)
1092                local_rect.dWidth = x11_window_width = pPriv->display_width - destx;
1093            else
1094                local_rect.dWidth = x11_window_width;
1095        }
1096
1097        if (((desty + x11_window_height) < pPriv->display_height) &&
1098            ((desty + x11_window_height) < pPriv->extend_display_height))
1099            local_rect.dHeight = extend_rect.dHeight = x11_window_height;
1100        else if (pPriv->display_height < pPriv->extend_display_height) {
1101            local_rect.dHeight = pPriv->display_height - desty;
1102            if ((desty + x11_window_height) > pPriv->extend_display_height)
1103                extend_rect.dHeight = x11_window_height = pPriv->extend_display_height - desty;
1104            else
1105                extend_rect.dHeight = x11_window_height;
1106        } else {
1107            extend_rect.dHeight = pPriv->extend_display_height - desty;
1108            if ((desty + x11_window_height) > pPriv->display_height)
1109                local_rect.dHeight = x11_window_height = pPriv->display_height - desty;
1110            else
1111                local_rect.dHeight = x11_window_height;
1112        }
1113        if ((driver_data->mipi0_rotation != VA_ROTATION_NONE) ||
1114            (driver_data->hdmi_rotation != VA_ROTATION_NONE)) {
1115            local_rect.sWidth = srcw;
1116            local_rect.sHeight = srch;
1117            extend_rect.sWidth = srcw;
1118            extend_rect.sHeight = srch;
1119        } else {
1120            local_rect.sWidth = (unsigned short)(local_rect.dWidth * xScaleFactor);
1121            local_rect.sHeight = (unsigned short)(local_rect.dHeight * yScaleFactor);
1122            extend_rect.sWidth = (unsigned short)(extend_rect.dWidth * xScaleFactor);
1123            extend_rect.sHeight = (unsigned short)(extend_rect.dHeight * yScaleFactor);
1124        }
1125        ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1126        if (ret != 0) {
1127            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1128            return VA_STATUS_ERROR_UNKNOWN;
1129        }
1130        psb_putsurface_overlay(
1131            ctx, surface, srcx, srcy, extend_rect.sWidth, extend_rect.sHeight,
1132            /* screen coordinate */
1133            destx, desty, extend_rect.dWidth, extend_rect.dHeight,
1134            flags, OVERLAY_C, extend_pipe);
1135        psb_putsurface_overlay(
1136            ctx, surface,  srcx, srcy, local_rect.sWidth, local_rect.sHeight,
1137            /* screen coordinate */
1138            destx, desty, local_rect.dWidth, local_rect.dHeight,
1139            flags, OVERLAY_A, local_pipe);
1140    } else if (psb_xrandr_extend_mode()) {
1141        if (driver_data->extend_fullscreen) {
1142            switch (extend_location) {
1143            case RIGHT_OF:
1144                XMoveResizeWindow(ctx->native_dpy, output->output_drawable, pPriv->display_width, 0, pPriv->extend_display_width, pPriv->extend_display_height);
1145                break;
1146            case BELOW:
1147                XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, pPriv->display_height, pPriv->extend_display_width, pPriv->extend_display_height);
1148                break;
1149            case LEFT_OF:
1150            case ABOVE:
1151                XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
1152                break;
1153            default:
1154                break;
1155
1156            }
1157            XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
1158            XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
1159            XFlush(ctx->native_dpy);
1160
1161            psb_putsurface_overlay(
1162                ctx, surface, srcx, srcy, srcw, srch,
1163                /* screen coordinate */
1164                0, 0, pPriv->extend_display_width, pPriv->extend_display_height,
1165                flags, OVERLAY_A, PIPEB);
1166        } else {
1167            psb_overlay_rect_t local_rect, extend_rect;
1168            enum overlay_id_t extend_overlay = OVERLAY_C;
1169
1170            if (output->extend_drawable) {
1171                XDestroyWindow(ctx->native_dpy, output->extend_drawable);
1172                output->extend_drawable = 0;
1173                XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
1174                output->extend_gc = 0;
1175            }
1176            memset(&local_rect, 0, sizeof(psb_overlay_rect_t));
1177            memset(&extend_rect, 0, sizeof(psb_overlay_rect_t));
1178            psb_extendMode_getCoordinate(pPriv, extend_location, destx, desty, srcx, srcy,
1179                                         xScaleFactor, yScaleFactor, &x11_window_width, &x11_window_height,
1180                                         &local_rect, &extend_rect, &extend_overlay);
1181
1182            ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1183            if (ret != 0) {
1184                drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1185                return VA_STATUS_ERROR_UNKNOWN;
1186            }
1187
1188            if ((extend_rect.dWidth > 0) && (extend_rect.dHeight > 0)) {
1189                psb_putsurface_overlay(
1190                    ctx, surface,
1191                    extend_rect.srcx, extend_rect.srcy, extend_rect.sWidth, extend_rect.sHeight,
1192                    extend_rect.destx, extend_rect.desty, extend_rect.dWidth, extend_rect.dHeight,
1193                    flags, extend_overlay, extend_pipe);
1194            }
1195            if ((local_rect.dWidth > 0) && (local_rect.dHeight > 0)) {
1196                psb_putsurface_overlay(
1197                    ctx, surface,
1198                    local_rect.srcx, local_rect.srcy, local_rect.sWidth, local_rect.sHeight,
1199                    local_rect.destx, local_rect.desty, local_rect.dWidth, local_rect.dHeight,
1200                    flags, OVERLAY_A, local_pipe);
1201            }
1202        }
1203    } else if (psb_xrandr_extvideo_mode()) {
1204        unsigned int xres, yres, xoffset, yoffset, overscanmode, pannelfitting, x, y;
1205        psb_extvideo_center center;
1206
1207        psb_xrandr_extvideo_prop(&xres, &yres, &xoffset, &yoffset, &center, &subtitle, &overscanmode, &pannelfitting);
1208        x = xoffset;
1209        y = yoffset;
1210
1211        switch (extend_location) {
1212        case RIGHT_OF:
1213            x += pPriv->display_width;
1214            break;
1215        case BELOW:
1216            y += pPriv->display_height;
1217            break;
1218        case NORMAL:
1219            break;
1220        case LEFT_OF:
1221            if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
1222                destx += pPriv->extend_display_width;
1223                XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height);
1224                XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
1225                XFlush(ctx->native_dpy);
1226            }
1227            destx = destx - pPriv->extend_display_width;
1228            break;
1229        case ABOVE:
1230            if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
1231                desty += pPriv->extend_display_height;
1232                XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height);
1233                XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
1234                XFlush(ctx->native_dpy);
1235            }
1236            desty = desty - pPriv->extend_display_height;
1237            break;
1238        }
1239        if ((destx + x11_window_width) > pPriv->display_width)
1240            x11_window_width = pPriv->display_width - destx;
1241        if ((desty + x11_window_height) > pPriv->display_height)
1242            x11_window_height = pPriv->display_height - desty;
1243
1244        if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
1245            Window extend_win;
1246            extend_win = psb_xrandr_create_full_screen_window(x, y, xres, yres);
1247            if (output->extend_drawable != extend_win) {
1248                output->extend_drawable = extend_win;
1249                if (output->extend_gc)
1250                    XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
1251                output->extend_gc = XCreateGC((Display *)ctx->native_dpy, extend_win, 0, NULL);
1252
1253                /* paint the color key */
1254                if (!obj_surface->subpictures) {
1255                    XSetForeground((Display *)ctx->native_dpy, output->extend_gc, pPriv->colorKey);
1256                    XFillRectangle((Display *)ctx->native_dpy, extend_win, output->extend_gc, 0, 0, xres, yres);
1257                    XSync((Display *)ctx->native_dpy, False);
1258                }
1259            }
1260            driver_data->xrandr_dirty &= ~PSB_NEW_EXTVIDEO;
1261        }
1262
1263        ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
1264        if (ret != 0) {
1265            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
1266            return VA_STATUS_ERROR_UNKNOWN;
1267        }
1268
1269        psb_putsurface_overlay(
1270            ctx, surface, srcx, srcy, srcw, srch,
1271            /* screen coordinate */
1272            xoffset, yoffset, xres, yres,
1273            flags, OVERLAY_C, PIPEB);
1274        psb_putsurface_overlay(
1275            ctx, surface, srcx, srcy, srcw, srch,
1276            /* screen coordinate */
1277            destx, desty,
1278            x11_window_width, x11_window_height,
1279            flags, OVERLAY_A, local_pipe);
1280    }
1281
1282    /*Init Overlay subpicuture blending and make proper clear.*/
1283    if (pPriv->is_mfld && obj_surface->subpictures) {
1284        PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures;
1285
1286        psb_init_subpicture(ctx, pPriv);
1287        /*clear changed subpicture zones in drawable.*/
1288        psb_clear_subpictures(ctx, pPriv, x11_window_width, x11_window_height, obj_surface);
1289        if (pPriv->subpic_clear_flag) {
1290            psb_DisplayRGBASubpicture(subpicture, ctx, x11_window_width, x11_window_height,
1291                                      surfacex, surfacey, obj_surface->width, obj_surface->height, subtitle);
1292        }
1293    }
1294
1295    output->frame_count++;
1296
1297    return VA_STATUS_SUCCESS;
1298}
1299