/* * Copyright (c) 2011 Intel Corporation. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Shengquan Yuan * Zhaohan Ren * */ #include #include "psb_surface.h" #include "psb_output.h" #include "psb_surface_ext.h" #include "psb_x11.h" #include "psb_xrandr.h" #include "psb_drv_debug.h" #include #include #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv) #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw); int (*oldHandler)(Display *, XErrorEvent *) = 0; static int XErrorFlag = 1; static int psb_XErrorHandler(Display *dpy, XErrorEvent *event) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "XErrorEvent caught in psb_XErrorHandler in psb_xvva.c\n"); if (event->type == 0 && event->request_code == 132 && event->error_code == 11 /* BadAlloc */) { XErrorFlag = 1; return 0; } return oldHandler(dpy, event); } static int GetPortId(VADriverContextP ctx, psb_x11_output_p output) { int i, j, k; unsigned int numAdapt; int numImages; XvImageFormatValues *formats; XvAdaptorInfo *info; int ret, grab_ret; Display *dpy = (Display *)ctx->native_dpy; ret = XvQueryAdaptors(dpy, DefaultRootWindow(dpy), &numAdapt, &info); /*Force overlay port num equal to one. OverlayC can't be used independently now.*/ /* check for numAdapt before modifying the info[1]. Without this check * it will cause a memory corruption leading to segfaults */ if (numAdapt > 1) info[1].num_ports = 1; if (Success != ret) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't find Xvideo adaptor\n"); return -1; } grab_ret = XGrabServer(ctx->native_dpy); for (i = 0; i < numAdapt; i++) { if ((info[i].type & XvImageMask) == 0) continue; formats = XvListImageFormats(dpy, info[i].base_id, &numImages); for (j = 0; j < numImages; j++) { if (formats[j].id != FOURCC_XVVA) continue; for (k = 0; k < info[i].num_ports; k++) { int ret = XvGrabPort(dpy, info[i].base_id + k, CurrentTime); if (Success == ret) { /* for textured adaptor 0 */ if (i == 0) output->textured_portID = info[i].base_id + k; /* for overlay adaptor 1 */ if (i == 1) output->overlay_portID = info[i].base_id + k; break; } } } XFree(formats); } if (grab_ret != 0) XUngrabServer(ctx->native_dpy); if ((output->textured_portID == 0) && (output->overlay_portID == 0)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Can't detect any usable Xv XVVA port\n"); return -1; } return 0; } VAStatus psb_init_xvideo(VADriverContextP ctx, psb_x11_output_p output) { #ifdef _FOR_FPGA_ return VA_STATUS_SUCCESS; #endif INIT_DRIVER_DATA; int dummy, ret; output->textured_portID = output->overlay_portID = 0; if (GetPortId(ctx, output)) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab Xvideo port failed, fallback to software vaPutSurface.\n"); return VA_STATUS_ERROR_ALLOCATION_FAILED; } if (output->textured_portID) drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected textured Xvideo port_id = %d.\n", (unsigned int)output->textured_portID); if (output->overlay_portID) drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected overlay Xvideo port_id = %d.\n", (unsigned int)output->overlay_portID); output->sprite_enabled = 0; if (getenv("PSB_SPRITE_ENABLE")) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "use sprite plane to playback rotated protected video\n"); output->sprite_enabled = 1; } output->ignore_dpm = 1; if (getenv("PSB_VIDEO_DPMS_HACK")) { if (DPMSQueryExtension((Display *)ctx->native_dpy, &dummy, &dummy) && DPMSCapable((Display *)ctx->native_dpy)) { BOOL onoff; CARD16 state; DPMSInfo((Display *)ctx->native_dpy, &state, &onoff); drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled", (state == DPMSModeOn) ? "on" : ( (state == DPMSModeOff) ? "off" : ( (state == DPMSModeStandby) ? "standby" : ( (state == DPMSModeSuspend) ? "suspend" : "unknow")))); if (onoff) output->ignore_dpm = 0; } } /* by default, overlay Xv */ if (output->textured_portID) driver_data->output_method = PSB_PUTSURFACE_TEXTURE; if (output->overlay_portID) driver_data->output_method = PSB_PUTSURFACE_OVERLAY; ret = psb_xrandr_init(ctx); if (ret != 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to initialize psb xrandr error # %d\n", __func__, ret); return VA_STATUS_ERROR_UNKNOWN; } return VA_STATUS_SUCCESS; } VAStatus psb_deinit_xvideo(VADriverContextP ctx) { INIT_DRIVER_DATA; INIT_OUTPUT_PRIV; if (output->gc) { XFreeGC((Display *)ctx->native_dpy, output->gc); output->gc = NULL; } if (output->extend_gc) { XFreeGC((Display *)ctx->native_dpy, output->extend_gc); output->extend_gc = NULL; } if (output->textured_xvimage) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for texture Xv\n"); XFree(output->textured_xvimage); output->textured_xvimage = NULL; } if (output->overlay_xvimage) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for overlay Xv\n"); XFree(output->overlay_xvimage); output->textured_xvimage = NULL; } if (output->textured_portID) { if ((output->using_port == USING_TEXTURE_PORT) && output->output_drawable && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop textured Xvideo\n"); XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, output->output_drawable); } drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab textured Xvideo port\n"); XvUngrabPort((Display *)ctx->native_dpy, output->textured_portID, CurrentTime); output->textured_portID = 0; } if (output->overlay_portID) { if ((output->using_port == USING_OVERLAY_PORT) && output->output_drawable && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop overlay Xvideo\n"); XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, output->output_drawable); } drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab overlay Xvideo port\n"); XvUngrabPort((Display *)ctx->native_dpy, output->overlay_portID, CurrentTime); output->overlay_portID = 0; } if (driver_data->use_xrandr_thread && driver_data->xrandr_thread_id) { psb_xrandr_thread_exit(); pthread_join(driver_data->xrandr_thread_id, NULL); driver_data->xrandr_thread_id = 0; } psb_xrandr_deinit(); output->using_port = 0; output->output_drawable = 0; output->extend_drawable = 0; #ifndef _FOR_FPGA_ XSync((Display *)ctx->native_dpy, False); #endif return VA_STATUS_SUCCESS; } static void psb_surface_init( psb_driver_data_p driver_data, PsbVASurfaceRec *srf, int fourcc, int bpp, int w, int h, int stride, int size, unsigned int pre_add, struct _WsbmBufferObject *bo, int flags ) { memset(srf, 0, sizeof(*srf)); srf->fourcc = fourcc; srf->bo = bo; if (bo != NULL) { srf->bufid = wsbmKBufHandle(wsbmKBuf(bo)); srf->pl_flags = wsbmBOPlacementHint(bo); } /* if (srf->pl_flags & DRM_PSB_FLAG_MEM_CI) srf->reserved_phyaddr = driver_data->camera_phyaddr; if (srf->pl_flags & DRM_PSB_FLAG_MEM_RAR) srf->reserved_phyaddr = driver_data->rar_phyaddr; */ srf->bytes_pp = bpp; srf->width = w; srf->pre_add = pre_add; if ((flags == VA_TOP_FIELD) || (flags == VA_BOTTOM_FIELD)) { if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY || driver_data->output_method == PSB_PUTSURFACE_OVERLAY) { srf->height = h; srf->stride = stride; } else { srf->height = h / 2; srf->stride = stride * 2; } if (flags == VA_BOTTOM_FIELD) srf->pre_add += stride; } else { srf->height = h; srf->stride = stride; } srf->size = size; if (flags == VA_CLEAR_DRAWABLE) { srf->clear_color = driver_data->clear_color; /* color */ return; } } #if 0 #define WINDOW 1 #define PIXMAP 0 /* return 0 for no rotation, 1 for rotation occurs */ /* XRRGetScreenInfo has significant performance drop */ static int psb__CheckCurrentRotation(VADriverContextP ctx) { Rotation current_rotation; XRRScreenConfiguration *scrn_cfg; scrn_cfg = XRRGetScreenInfo((Display *)ctx->native_dpy, DefaultRootWindow((Display *)ctx->native_dpy)); XRRConfigCurrentConfiguration(scrn_cfg, ¤t_rotation); XRRFreeScreenConfigInfo(scrn_cfg); return (current_rotation & 0x0f); } /* Check drawable type, 1 for window, 0 for pixmap * Have significant performance drop in XFCE environment */ static void psb__CheckDrawableType(Display *dpy, Window win, Drawable draw, int *type_ret) { unsigned int child_num; Window root_return; Window parent_return; Window *child_return; int i; if (win == draw) { *type_ret = 1; return; } XQueryTree(dpy, win, &root_return, &parent_return, &child_return, &child_num); if (!child_num) return; for (i = 0; i < child_num; i++) psb__CheckDrawableType(dpy, child_return[i], draw, type_ret); } #endif static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw) { INIT_DRIVER_DATA; INIT_OUTPUT_PRIV; Atom xvDrawable = XInternAtom((Display *)ctx->native_dpy, "XV_DRAWABLE", 0); int val = 0; driver_data->drawable_info = 0; if (output->overlay_portID) { XvSetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, draw); XvGetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, &val); } else if (output->textured_portID) { XvSetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, draw); XvGetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, &val); } driver_data->drawable_info = val; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Get xvDrawable = 0x%08x\n", val); if (driver_data->drawable_info == XVDRAWABLE_INVALID_DRAWABLE) return -1; return 0; } static int psb__CheckPutSurfaceXvPort( VADriverContextP ctx, VASurfaceID surface, Drawable draw, /* X Drawable */ short srcx, short srcy, unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, unsigned short desth, VARectangle *cliprects, /* client supplied clip list */ unsigned int number_cliprects, /* number of clip rects in the clip list */ unsigned int flags /* de-interlacing flags */ ) { INIT_DRIVER_DATA; INIT_OUTPUT_PRIV; object_surface_p obj_surface = SURFACE(surface); uint32_t buf_pl; /* silent klockwork */ if (obj_surface && obj_surface->psb_surface) buf_pl = obj_surface->psb_surface->buf.pl_flags; else return -1; if (flags & VA_CLEAR_DRAWABLE) return 0; if (output->overlay_portID == 0) { /* no overlay usable */ driver_data->output_method = PSB_PUTSURFACE_TEXTURE; return 0; } if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Overlay Xvideo for PutSurface\n"); return 0; } if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Textured Xvideo for PutSurface\n"); return 0; } if (((buf_pl & (WSBM_PL_FLAG_TT)) == 0) /* buf not in TT/RAR or CI */ || (obj_surface->width > 1920) /* overlay have isue to support >1920xXXX resolution */ || (obj_surface->subpic_count > 0) /* overlay can't support subpicture */ /* || (flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD))*/ ) { driver_data->output_method = PSB_PUTSURFACE_TEXTURE; return 0; } /* Here should be overlay XV by defaut after overlay is stable */ driver_data->output_method = PSB_PUTSURFACE_OVERLAY; /* driver_data->output_method = PSB_PUTSURFACE_TEXTURE; */ /* *Query Overlay Adaptor by XvDrawable Attribute to know current * Xrandr information:rotation/downscaling * also set target drawable(window vs pixmap) into XvDrawable * to levage Xserver to determiate it is Pixmap or Window */ /* *ROTATE_90: 0x2, ROTATE_180: 0x4, ROTATE_270:0x8 *Overlay adopator can support video rotation, *but its performance is lower than texture video path. *When video protection and rotation are required (use RAR buffer), *only overlay adaptor will be used. *other attribute like down scaling and pixmap, use texture adaptor */ if (driver_data->drawable_info & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) { driver_data->output_method = PSB_PUTSURFACE_TEXTURE; } if (driver_data->drawable_info & (XVDRAWABLE_PIXMAP | XVDRAWABLE_REDIRECT_WINDOW)) driver_data->output_method = PSB_PUTSURFACE_TEXTURE; if (srcw >= destw * 8 || srch >= desth * 8) driver_data->output_method = PSB_PUTSURFACE_TEXTURE; return 0; } static int psb__CheckGCXvImage( VADriverContextP ctx, VASurfaceID surface, Drawable draw, XvImage **xvImage, XvPortID *port_id, unsigned int flags /* de-interlacing flags */ ) { INIT_DRIVER_DATA; INIT_OUTPUT_PRIV; object_surface_p obj_surface = SURFACE(surface); /* surface already checked */ if (output->output_drawable != draw) { if (output->gc) XFreeGC((Display *)ctx->native_dpy, output->gc); output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL); output->output_drawable = draw; } if (flags & VA_CLEAR_DRAWABLE) { if (output->textured_portID && (output->using_port == USING_TEXTURE_PORT)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop textured Xvideo\n"); XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw); } if (output->overlay_portID && (output->using_port == USING_OVERLAY_PORT)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop overlay Xvideo\n"); XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw); } output->using_port = 0; XSetForeground((Display *)ctx->native_dpy, output->gc, driver_data->clear_color); return 0; } if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) || (driver_data->output_method == PSB_PUTSURFACE_OVERLAY)) { /* use OVERLAY XVideo */ if (obj_surface && ((output->output_width != obj_surface->width) || (output->output_height != obj_surface->height) || (!output->overlay_xvimage))) { if (output->overlay_xvimage) XFree(output->overlay_xvimage); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n"); output->overlay_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->overlay_portID, FOURCC_XVVA, 0, obj_surface->width, obj_surface->height); output->overlay_xvimage->data = (char *) & output->imgdata_vasrf; output->output_width = obj_surface->width; output->output_height = obj_surface->height; } *xvImage = output->overlay_xvimage; *port_id = output->overlay_portID; if ((output->textured_portID) && (output->using_port == USING_TEXTURE_PORT)) { /* stop texture port */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using overlay xvideo, stop textured xvideo\n"); XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw); XSync((Display *)ctx->native_dpy, False); } output->using_port = USING_OVERLAY_PORT; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Overlay Xvideo (%d) for PutSurface\n", output->textured_portID); return 0; } if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE) || (driver_data->output_method == PSB_PUTSURFACE_TEXTURE)) { /* use Textured XVideo */ if (obj_surface && ((output->output_width != obj_surface->width) || (output->output_height != obj_surface->height || (!output->textured_xvimage)))) { if (output->textured_xvimage) XFree(output->textured_xvimage); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n"); output->textured_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->textured_portID, FOURCC_XVVA, 0, obj_surface->width, obj_surface->height); output->textured_xvimage->data = (char *) & output->imgdata_vasrf; output->output_width = obj_surface->width; output->output_height = obj_surface->height; } *xvImage = output->textured_xvimage; *port_id = output->textured_portID; if ((output->overlay_portID) && (output->using_port == USING_OVERLAY_PORT)) { /* stop overlay port */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using textured xvideo, stop Overlay xvideo\n"); XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw); XSync((Display *)ctx->native_dpy, False); output->using_port = USING_TEXTURE_PORT; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Texture Xvideo (%d) for PutSurface\n", output->textured_portID); return 0; } return 0; } static int psb_force_dpms_on(VADriverContextP ctx) { BOOL onoff; CARD16 state; DPMSInfo((Display *)ctx->native_dpy, &state, &onoff); drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled", (state == DPMSModeOn) ? "on" : ( (state == DPMSModeOff) ? "off" : ( (state == DPMSModeStandby) ? "standby" : ( (state == DPMSModeSuspend) ? "suspend" : "unknow")))); if (onoff && (state != DPMSModeOn)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is enabled, and monitor isn't DPMSModeOn, force it on\n"); DPMSForceLevel((Display *)ctx->native_dpy, DPMSModeOn); } return 0; } VAStatus psb_check_rotatesurface( VADriverContextP ctx, unsigned short rotate_width, unsigned short rotate_height, unsigned int protected, int fourcc ) { INIT_DRIVER_DATA; INIT_OUTPUT_PRIV; VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_rotate_surface; unsigned int flags = protected? IS_PROTECTED : 0; if (output->rotate_surface) { obj_rotate_surface = SURFACE(output->rotate_surfaceID); if (obj_rotate_surface && ((obj_rotate_surface->width != rotate_width) || (obj_rotate_surface->height != rotate_height))) { psb_surface_destroy(output->rotate_surface); free(output->rotate_surface); object_heap_free(&driver_data->surface_heap, (object_base_p)obj_rotate_surface); output->rotate_surface = NULL; } } if (output->rotate_surface == NULL) { output->rotate_surfaceID = object_heap_allocate(&driver_data->surface_heap); obj_rotate_surface = SURFACE(output->rotate_surfaceID); if (NULL == obj_rotate_surface) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; return VA_STATUS_ERROR_ALLOCATION_FAILED; } obj_rotate_surface->surface_id = output->rotate_surfaceID; obj_rotate_surface->context_id = -1; obj_rotate_surface->width = rotate_width; obj_rotate_surface->height = rotate_height; obj_rotate_surface->subpictures = NULL; obj_rotate_surface->subpic_count = 0; obj_rotate_surface->derived_imgcnt = 0; output->rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); if (NULL == output->rotate_surface) { object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface); obj_rotate_surface->surface_id = VA_INVALID_SURFACE; vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; return VA_STATUS_ERROR_ALLOCATION_FAILED; } flags |= IS_ROTATED; vaStatus = psb_surface_create(driver_data, rotate_width, rotate_height, fourcc, flags, output->rotate_surface); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_rotate_surface->psb_surface); object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface); obj_rotate_surface->surface_id = VA_INVALID_SURFACE; DEBUG_FAILURE; return vaStatus; } obj_rotate_surface->psb_surface = output->rotate_surface; } return vaStatus; } VAStatus psb_putsurface_xvideo( 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, /* client supplied clip list */ unsigned int number_cliprects, /* number of clip rects in the clip list */ unsigned int flags /* de-interlacing flags */ ) { INIT_DRIVER_DATA; INIT_OUTPUT_PRIV; VAStatus vaStatus = VA_STATUS_SUCCESS; PsbVASurfaceRec *subpic_surface; PsbXvVAPutSurfacePtr vaPtr; XvPortID portID = 0; XvImage *xvImage = NULL; object_surface_p obj_surface = SURFACE(surface); psb_surface_p psb_surface; int i = 0, j; if (obj_surface) /* silent klockwork, we already check it */ psb_surface = obj_surface->psb_surface; else return VA_STATUS_ERROR_UNKNOWN; /* Catch X protocol errors with our own error handler */ if (oldHandler == 0) oldHandler = XSetErrorHandler(psb_XErrorHandler); if (XErrorFlag == 1) { if (psb_CheckDrawable(ctx, draw) != 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n"); return VA_STATUS_ERROR_UNKNOWN; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n"); XErrorFlag = 0; } /* check display configuration for every 100 frames */ if ((driver_data->frame_count % 100) == 0) { if (psb_CheckDrawable(ctx, draw) != 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n"); return VA_STATUS_ERROR_UNKNOWN; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n"); } psb__CheckPutSurfaceXvPort(ctx, surface, draw, srcx, srcy, srcw, srch, destx, desty, destw, desth, cliprects, number_cliprects, flags); psb__CheckGCXvImage(ctx, surface, draw, &xvImage, &portID, flags); if (flags & VA_CLEAR_DRAWABLE) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color); XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth); XSync((Display *)ctx->native_dpy, False); XFreeGC((Display *)ctx->native_dpy, output->gc); output->gc = NULL; output->output_drawable = 0; XSync((Display *)ctx->native_dpy, False); driver_data->cur_displaying_surface = VA_INVALID_SURFACE; driver_data->last_displaying_surface = VA_INVALID_SURFACE; obj_surface->display_timestamp = 0; return vaStatus; } vaPtr = (PsbXvVAPutSurfacePtr)xvImage->data; vaPtr->flags = flags; vaPtr->num_subpicture = obj_surface->subpic_count; vaPtr->num_clipbox = number_cliprects; for (j = 0; j < number_cliprects; j++) { vaPtr->clipbox[j].x = cliprects[j].x; vaPtr->clipbox[j].y = cliprects[j].y; vaPtr->clipbox[j].width = cliprects[j].width; vaPtr->clipbox[j].height = cliprects[j].height; } psb_surface_init(driver_data, &vaPtr->src_srf, VA_FOURCC_NV12, 2, obj_surface->width, obj_surface->height, psb_surface->stride, psb_surface->size, psb_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory * all surfaces share one BO but with different offset * pass the offset as the "pre_add" */ psb_surface->buf.drm_buf, flags); if ((driver_data->output_method == PSB_PUTSURFACE_OVERLAY) && (driver_data->drawable_info & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270))) { unsigned int rotate_width, rotate_height; int fourcc; if (output->sprite_enabled) fourcc = VA_FOURCC_RGBA; else fourcc = VA_FOURCC_NV12; if (driver_data->drawable_info & (XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) { rotate_width = obj_surface->height; rotate_height = obj_surface->width; } else { rotate_width = obj_surface->width; rotate_height = obj_surface->height; } unsigned int protected = vaPtr->src_srf.pl_flags & 0; vaStatus = psb_check_rotatesurface(ctx, rotate_width, rotate_height, protected, fourcc); if (VA_STATUS_SUCCESS != vaStatus) return vaStatus; psb_surface_init(driver_data, &vaPtr->dst_srf, fourcc, 4, rotate_width, rotate_height, output->rotate_surface->stride, output->rotate_surface->size, output->rotate_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory * all surfaces share one BO but with different offset * pass the offset as the "pre_add" */ output->rotate_surface->buf.drm_buf, 0); } subpic_surface = obj_surface->subpictures; while (subpic_surface) { PsbVASurfaceRec *tmp = &vaPtr->subpic_srf[i++]; memcpy(tmp, subpic_surface, sizeof(*tmp)); /* reload palette for paletted subpicture * palete_ptr point to image palette */ if (subpic_surface->palette_ptr) memcpy(&tmp->palette[0], subpic_surface->palette_ptr, 16 * sizeof(PsbAYUVSample8)); subpic_surface = subpic_surface->next; } if (output->ignore_dpm == 0) psb_force_dpms_on(ctx); XvPutImage((Display *)ctx->native_dpy, portID, draw, output->gc, xvImage, srcx, srcy, srcw, srch, destx, desty, destw, desth); XFlush((Display *)ctx->native_dpy); //XSync((Display *)ctx->native_dpy, False); if (portID == output->overlay_portID) { if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE) driver_data->last_displaying_surface = driver_data->cur_displaying_surface; obj_surface->display_timestamp = GetTickCount(); driver_data->cur_displaying_surface = surface; } else { driver_data->cur_displaying_surface = VA_INVALID_SURFACE; driver_data->last_displaying_surface = VA_INVALID_SURFACE; obj_surface->display_timestamp = 0; } return vaStatus; }