113496ba1Ssnj/*************************************************************************** 213496ba1Ssnj 313496ba1Ssnj Copyright 2000 Intel Corporation. All Rights Reserved. 413496ba1Ssnj 513496ba1Ssnj Permission is hereby granted, free of charge, to any person obtaining a 613496ba1Ssnj copy of this software and associated documentation files (the 713496ba1Ssnj "Software"), to deal in the Software without restriction, including 813496ba1Ssnj without limitation the rights to use, copy, modify, merge, publish, 913496ba1Ssnj distribute, sub license, and/or sell copies of the Software, and to 1013496ba1Ssnj permit persons to whom the Software is furnished to do so, subject to 1113496ba1Ssnj the following conditions: 1213496ba1Ssnj 1313496ba1Ssnj The above copyright notice and this permission notice (including the 1413496ba1Ssnj next paragraph) shall be included in all copies or substantial portions 1513496ba1Ssnj of the Software. 1613496ba1Ssnj 1713496ba1Ssnj THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1813496ba1Ssnj OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1913496ba1Ssnj MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2013496ba1Ssnj IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2113496ba1Ssnj DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2213496ba1Ssnj OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 2313496ba1Ssnj THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2413496ba1Ssnj 2513496ba1Ssnj **************************************************************************/ 2613496ba1Ssnj 2713496ba1Ssnj/* 2813496ba1Ssnj * i830_video.c: i830/i845 Xv driver. 2913496ba1Ssnj * 3013496ba1Ssnj * Copyright © 2002 by Alan Hourihane and David Dawes 3113496ba1Ssnj * 3213496ba1Ssnj * Authors: 3313496ba1Ssnj * Alan Hourihane <alanh@tungstengraphics.com> 3413496ba1Ssnj * David Dawes <dawes@xfree86.org> 3513496ba1Ssnj * 3613496ba1Ssnj * Derived from i810 Xv driver: 3713496ba1Ssnj * 3813496ba1Ssnj * Authors of i810 code: 3913496ba1Ssnj * Jonathan Bian <jonathan.bian@intel.com> 4013496ba1Ssnj * Offscreen Images: 4113496ba1Ssnj * Matt Sottek <matthew.j.sottek@intel.com> 4213496ba1Ssnj */ 4313496ba1Ssnj 4413496ba1Ssnj/* 4513496ba1Ssnj * XXX Could support more formats. 4613496ba1Ssnj */ 4713496ba1Ssnj 4813496ba1Ssnj#ifdef HAVE_CONFIG_H 4913496ba1Ssnj#include "config.h" 5013496ba1Ssnj#endif 5113496ba1Ssnj 5213496ba1Ssnj#include <inttypes.h> 5313496ba1Ssnj#include <math.h> 5413496ba1Ssnj#include <string.h> 5513496ba1Ssnj#include <assert.h> 5613496ba1Ssnj#include <errno.h> 5713496ba1Ssnj 5813496ba1Ssnj#include "xorg-server.h" 5913496ba1Ssnj#include "xf86.h" 6013496ba1Ssnj#include "xf86_OSproc.h" 6113496ba1Ssnj#include "compiler.h" 6213496ba1Ssnj#include "xf86Pci.h" 6313496ba1Ssnj#include "xf86fbman.h" 6413496ba1Ssnj#include "xf86drm.h" 6513496ba1Ssnj#include "regionstr.h" 6613496ba1Ssnj#include "randrstr.h" 6713496ba1Ssnj#include "windowstr.h" 6813496ba1Ssnj#include "damage.h" 6913496ba1Ssnj#include "intel.h" 7013496ba1Ssnj#include "intel_video.h" 7113496ba1Ssnj#include "i830_reg.h" 7213496ba1Ssnj#include "xf86xv.h" 7313496ba1Ssnj#include <X11/extensions/Xv.h> 7413496ba1Ssnj#include "dixstruct.h" 7513496ba1Ssnj#include "fourcc.h" 7613496ba1Ssnj#include "intel_video_overlay.h" 7713496ba1Ssnj 7813496ba1Ssnj/* overlay debugging printf function */ 7913496ba1Ssnj#if 0 8013496ba1Ssnj#define OVERLAY_DEBUG ErrorF 8113496ba1Ssnj#else 8213496ba1Ssnj#define OVERLAY_DEBUG if (0) ErrorF 8313496ba1Ssnj#endif 8413496ba1Ssnj 8513496ba1Ssnj/* kernel modesetting overlay functions */ 8613496ba1Ssnjstatic Bool intel_has_overlay(intel_screen_private *intel) 8713496ba1Ssnj{ 8813496ba1Ssnj struct drm_i915_getparam gp; 8913496ba1Ssnj int has_overlay = 0; 9013496ba1Ssnj int ret; 9113496ba1Ssnj 9213496ba1Ssnj gp.param = I915_PARAM_HAS_OVERLAY; 9313496ba1Ssnj gp.value = &has_overlay; 9413496ba1Ssnj ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, sizeof(gp)); 9513496ba1Ssnj 9613496ba1Ssnj return ret == 0 && !! has_overlay; 9713496ba1Ssnj} 9813496ba1Ssnj 9913496ba1Ssnjstatic Bool intel_overlay_update_attrs(intel_screen_private *intel) 10013496ba1Ssnj{ 10113496ba1Ssnj intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel); 10213496ba1Ssnj struct drm_intel_overlay_attrs attrs; 10313496ba1Ssnj 10413496ba1Ssnj attrs.flags = I915_OVERLAY_UPDATE_ATTRS; 10513496ba1Ssnj attrs.brightness = adaptor_priv->brightness; 10613496ba1Ssnj attrs.contrast = adaptor_priv->contrast; 10713496ba1Ssnj attrs.saturation = adaptor_priv->saturation; 10813496ba1Ssnj attrs.color_key = adaptor_priv->colorKey; 10913496ba1Ssnj attrs.gamma0 = adaptor_priv->gamma0; 11013496ba1Ssnj attrs.gamma1 = adaptor_priv->gamma1; 11113496ba1Ssnj attrs.gamma2 = adaptor_priv->gamma2; 11213496ba1Ssnj attrs.gamma3 = adaptor_priv->gamma3; 11313496ba1Ssnj attrs.gamma4 = adaptor_priv->gamma4; 11413496ba1Ssnj attrs.gamma5 = adaptor_priv->gamma5; 11513496ba1Ssnj 11613496ba1Ssnj return drmCommandWriteRead(intel->drmSubFD, DRM_I915_OVERLAY_ATTRS, 11713496ba1Ssnj &attrs, sizeof(attrs)) == 0; 11813496ba1Ssnj} 11913496ba1Ssnj 12013496ba1Ssnjvoid intel_video_overlay_off(intel_screen_private *intel) 12113496ba1Ssnj{ 12213496ba1Ssnj struct drm_intel_overlay_put_image request; 12313496ba1Ssnj int ret; 12413496ba1Ssnj 12513496ba1Ssnj request.flags = 0; 12613496ba1Ssnj 12713496ba1Ssnj ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE, 12813496ba1Ssnj &request, sizeof(request)); 12913496ba1Ssnj (void) ret; 13013496ba1Ssnj} 13113496ba1Ssnjstatic int 13213496ba1Ssnjintel_video_overlay_set_port_attribute(ScrnInfoPtr scrn, 13313496ba1Ssnj Atom attribute, INT32 value, pointer data) 13413496ba1Ssnj{ 13513496ba1Ssnj intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 13613496ba1Ssnj intel_screen_private *intel = intel_get_screen_private(scrn); 13713496ba1Ssnj 13813496ba1Ssnj if (attribute == intel_xv_Brightness) { 13913496ba1Ssnj if ((value < -128) || (value > 127)) 14013496ba1Ssnj return BadValue; 14113496ba1Ssnj adaptor_priv->brightness = value; 14213496ba1Ssnj OVERLAY_DEBUG("BRIGHTNESS\n"); 14313496ba1Ssnj } else if (attribute == intel_xv_Contrast) { 14413496ba1Ssnj if ((value < 0) || (value > 255)) 14513496ba1Ssnj return BadValue; 14613496ba1Ssnj adaptor_priv->contrast = value; 14713496ba1Ssnj OVERLAY_DEBUG("CONTRAST\n"); 14813496ba1Ssnj } else if (attribute == intel_xv_Saturation) { 14913496ba1Ssnj if ((value < 0) || (value > 1023)) 15013496ba1Ssnj return BadValue; 15113496ba1Ssnj adaptor_priv->saturation = value; 15213496ba1Ssnj } else if (attribute == intel_xv_Pipe) { 15313496ba1Ssnj xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 15413496ba1Ssnj if ((value < -1) || (value >= xf86_config->num_crtc)) 15513496ba1Ssnj return BadValue; 15613496ba1Ssnj if (value < 0) 15713496ba1Ssnj adaptor_priv->desired_crtc = NULL; 15813496ba1Ssnj else 15913496ba1Ssnj adaptor_priv->desired_crtc = xf86_config->crtc[value]; 16013496ba1Ssnj } else if (attribute == intel_xv_Gamma0 && (INTEL_INFO(intel)->gen >= 030)) { 16113496ba1Ssnj adaptor_priv->gamma0 = value; 16213496ba1Ssnj } else if (attribute == intel_xv_Gamma1 && (INTEL_INFO(intel)->gen >= 030)) { 16313496ba1Ssnj adaptor_priv->gamma1 = value; 16413496ba1Ssnj } else if (attribute == intel_xv_Gamma2 && (INTEL_INFO(intel)->gen >= 030)) { 16513496ba1Ssnj adaptor_priv->gamma2 = value; 16613496ba1Ssnj } else if (attribute == intel_xv_Gamma3 && (INTEL_INFO(intel)->gen >= 030)) { 16713496ba1Ssnj adaptor_priv->gamma3 = value; 16813496ba1Ssnj } else if (attribute == intel_xv_Gamma4 && (INTEL_INFO(intel)->gen >= 030)) { 16913496ba1Ssnj adaptor_priv->gamma4 = value; 17013496ba1Ssnj } else if (attribute == intel_xv_Gamma5 && (INTEL_INFO(intel)->gen >= 030)) { 17113496ba1Ssnj adaptor_priv->gamma5 = value; 17213496ba1Ssnj } else if (attribute == intel_xv_ColorKey) { 17313496ba1Ssnj adaptor_priv->colorKey = value; 17413496ba1Ssnj OVERLAY_DEBUG("COLORKEY\n"); 17513496ba1Ssnj } else 17613496ba1Ssnj return BadMatch; 17713496ba1Ssnj 17813496ba1Ssnj if ((attribute == intel_xv_Gamma0 || 17913496ba1Ssnj attribute == intel_xv_Gamma1 || 18013496ba1Ssnj attribute == intel_xv_Gamma2 || 18113496ba1Ssnj attribute == intel_xv_Gamma3 || 18213496ba1Ssnj attribute == intel_xv_Gamma4 || 18313496ba1Ssnj attribute == intel_xv_Gamma5) && (INTEL_INFO(intel)->gen >= 030)) { 18413496ba1Ssnj OVERLAY_DEBUG("GAMMA\n"); 18513496ba1Ssnj } 18613496ba1Ssnj 18713496ba1Ssnj if (!intel_overlay_update_attrs(intel)) 18813496ba1Ssnj return BadValue; 18913496ba1Ssnj 19013496ba1Ssnj if (attribute == intel_xv_ColorKey) 19113496ba1Ssnj REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip); 19213496ba1Ssnj 19313496ba1Ssnj return Success; 19413496ba1Ssnj} 19513496ba1Ssnj 19613496ba1Ssnjstatic Bool 19713496ba1Ssnjintel_overlay_put_image(intel_screen_private *intel, 19813496ba1Ssnj xf86CrtcPtr crtc, 19913496ba1Ssnj int id, short width, short height, 20013496ba1Ssnj int dstPitch, int dstPitch2, 20113496ba1Ssnj BoxPtr dstBox, short src_w, short src_h, short drw_w, 20213496ba1Ssnj short drw_h) 20313496ba1Ssnj{ 20413496ba1Ssnj intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel); 20513496ba1Ssnj struct drm_intel_overlay_put_image request; 20613496ba1Ssnj int ret; 20713496ba1Ssnj int planar = is_planar_fourcc(id); 20813496ba1Ssnj float scale; 20913496ba1Ssnj dri_bo *tmp; 21013496ba1Ssnj 21113496ba1Ssnj request.flags = I915_OVERLAY_ENABLE; 21213496ba1Ssnj 21313496ba1Ssnj request.bo_handle = adaptor_priv->buf->handle; 21413496ba1Ssnj if (planar) { 21513496ba1Ssnj request.stride_Y = dstPitch2; 21613496ba1Ssnj request.stride_UV = dstPitch; 21713496ba1Ssnj } else { 21813496ba1Ssnj request.stride_Y = dstPitch; 21913496ba1Ssnj request.stride_UV = 0; 22013496ba1Ssnj } 22113496ba1Ssnj request.offset_Y = adaptor_priv->YBufOffset; 22213496ba1Ssnj request.offset_U = adaptor_priv->UBufOffset; 22313496ba1Ssnj request.offset_V = adaptor_priv->VBufOffset; 22413496ba1Ssnj OVERLAY_DEBUG("off_Y: %i, off_U: %i, off_V: %i\n", request.offset_Y, 22513496ba1Ssnj request.offset_U, request.offset_V); 22613496ba1Ssnj 22713496ba1Ssnj request.crtc_id = intel_crtc_id(crtc); 22813496ba1Ssnj request.dst_x = dstBox->x1; 22913496ba1Ssnj request.dst_y = dstBox->y1; 23013496ba1Ssnj request.dst_width = dstBox->x2 - dstBox->x1; 23113496ba1Ssnj request.dst_height = dstBox->y2 - dstBox->y1; 23213496ba1Ssnj 23313496ba1Ssnj request.src_width = width; 23413496ba1Ssnj request.src_height = height; 23513496ba1Ssnj /* adjust src dimensions */ 23613496ba1Ssnj if (request.dst_height > 1) { 23713496ba1Ssnj scale = ((float)request.dst_height - 1) / ((float)drw_h - 1); 23813496ba1Ssnj request.src_scan_height = src_h * scale; 23913496ba1Ssnj } else 24013496ba1Ssnj request.src_scan_height = 1; 24113496ba1Ssnj 24213496ba1Ssnj if (request.dst_width > 1) { 24313496ba1Ssnj scale = ((float)request.dst_width - 1) / ((float)drw_w - 1); 24413496ba1Ssnj request.src_scan_width = src_w * scale; 24513496ba1Ssnj } else 24613496ba1Ssnj request.src_scan_width = 1; 24713496ba1Ssnj 24813496ba1Ssnj if (planar) { 24913496ba1Ssnj request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420; 25013496ba1Ssnj } else { 25113496ba1Ssnj request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422; 25213496ba1Ssnj if (id == FOURCC_UYVY) 25313496ba1Ssnj request.flags |= I915_OVERLAY_Y_SWAP; 25413496ba1Ssnj } 25513496ba1Ssnj 25613496ba1Ssnj ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE, 25713496ba1Ssnj &request, sizeof(request)); 25813496ba1Ssnj if (ret) 25913496ba1Ssnj return FALSE; 26013496ba1Ssnj 26113496ba1Ssnj if (!adaptor_priv->reusable) { 26213496ba1Ssnj drm_intel_bo_unreference(adaptor_priv->buf); 26313496ba1Ssnj adaptor_priv->buf = NULL; 26413496ba1Ssnj adaptor_priv->reusable = TRUE; 26513496ba1Ssnj } 26613496ba1Ssnj 26713496ba1Ssnj tmp = adaptor_priv->old_buf[1]; 26813496ba1Ssnj adaptor_priv->old_buf[1] = adaptor_priv->old_buf[0]; 26913496ba1Ssnj adaptor_priv->old_buf[0] = adaptor_priv->buf; 27013496ba1Ssnj adaptor_priv->buf = tmp; 27113496ba1Ssnj 27213496ba1Ssnj return TRUE; 27313496ba1Ssnj} 27413496ba1Ssnj 27513496ba1Ssnjstatic void 27613496ba1Ssnjintel_update_dst_box_to_crtc_coords(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 27713496ba1Ssnj BoxPtr dstBox) 27813496ba1Ssnj{ 27913496ba1Ssnj int tmp; 28013496ba1Ssnj 28113496ba1Ssnj /* for overlay, we should take it from crtc's screen 28213496ba1Ssnj * coordinate to current crtc's display mode. 28313496ba1Ssnj * yeah, a bit confusing. 28413496ba1Ssnj */ 28513496ba1Ssnj switch (crtc->rotation & 0xf) { 28613496ba1Ssnj case RR_Rotate_0: 28713496ba1Ssnj dstBox->x1 -= crtc->x; 28813496ba1Ssnj dstBox->x2 -= crtc->x; 28913496ba1Ssnj dstBox->y1 -= crtc->y; 29013496ba1Ssnj dstBox->y2 -= crtc->y; 29113496ba1Ssnj break; 29213496ba1Ssnj case RR_Rotate_90: 29313496ba1Ssnj tmp = dstBox->x1; 29413496ba1Ssnj dstBox->x1 = dstBox->y1 - crtc->x; 29513496ba1Ssnj dstBox->y1 = scrn->virtualX - tmp - crtc->y; 29613496ba1Ssnj tmp = dstBox->x2; 29713496ba1Ssnj dstBox->x2 = dstBox->y2 - crtc->x; 29813496ba1Ssnj dstBox->y2 = scrn->virtualX - tmp - crtc->y; 29913496ba1Ssnj tmp = dstBox->y1; 30013496ba1Ssnj dstBox->y1 = dstBox->y2; 30113496ba1Ssnj dstBox->y2 = tmp; 30213496ba1Ssnj break; 30313496ba1Ssnj case RR_Rotate_180: 30413496ba1Ssnj tmp = dstBox->x1; 30513496ba1Ssnj dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x; 30613496ba1Ssnj dstBox->x2 = scrn->virtualX - tmp - crtc->x; 30713496ba1Ssnj tmp = dstBox->y1; 30813496ba1Ssnj dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y; 30913496ba1Ssnj dstBox->y2 = scrn->virtualY - tmp - crtc->y; 31013496ba1Ssnj break; 31113496ba1Ssnj case RR_Rotate_270: 31213496ba1Ssnj tmp = dstBox->x1; 31313496ba1Ssnj dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x; 31413496ba1Ssnj dstBox->y1 = tmp - crtc->y; 31513496ba1Ssnj tmp = dstBox->x2; 31613496ba1Ssnj dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x; 31713496ba1Ssnj dstBox->y2 = tmp - crtc->y; 31813496ba1Ssnj tmp = dstBox->x1; 31913496ba1Ssnj dstBox->x1 = dstBox->x2; 32013496ba1Ssnj dstBox->x2 = tmp; 32113496ba1Ssnj break; 32213496ba1Ssnj } 32313496ba1Ssnj 32413496ba1Ssnj return; 32513496ba1Ssnj} 32613496ba1Ssnj 32713496ba1Ssnjstatic Bool 32813496ba1Ssnjintel_video_overlay_display(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 32913496ba1Ssnj int id, short width, short height, 33013496ba1Ssnj int dstPitch, int dstPitch2, 33113496ba1Ssnj BoxPtr dstBox, short src_w, short src_h, short drw_w, 33213496ba1Ssnj short drw_h) 33313496ba1Ssnj{ 33413496ba1Ssnj intel_screen_private *intel = intel_get_screen_private(scrn); 33513496ba1Ssnj int tmp; 33613496ba1Ssnj 33713496ba1Ssnj OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, 33813496ba1Ssnj dstPitch); 33913496ba1Ssnj 34013496ba1Ssnj /* 34113496ba1Ssnj * If the video isn't visible on any CRTC, turn it off 34213496ba1Ssnj */ 34313496ba1Ssnj if (!crtc) { 34413496ba1Ssnj intel_video_overlay_off(intel); 34513496ba1Ssnj return TRUE; 34613496ba1Ssnj } 34713496ba1Ssnj 34813496ba1Ssnj intel_update_dst_box_to_crtc_coords(scrn, crtc, dstBox); 34913496ba1Ssnj 35013496ba1Ssnj if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 35113496ba1Ssnj tmp = width; 35213496ba1Ssnj width = height; 35313496ba1Ssnj height = tmp; 35413496ba1Ssnj tmp = drw_w; 35513496ba1Ssnj drw_w = drw_h; 35613496ba1Ssnj drw_h = tmp; 35713496ba1Ssnj tmp = src_w; 35813496ba1Ssnj src_w = src_h; 35913496ba1Ssnj src_h = tmp; 36013496ba1Ssnj } 36113496ba1Ssnj 36213496ba1Ssnj return intel_overlay_put_image(intel, crtc, id, 36313496ba1Ssnj width, height, 36413496ba1Ssnj dstPitch, dstPitch2, dstBox, 36513496ba1Ssnj src_w, src_h, drw_w, drw_h); 36613496ba1Ssnj} 36713496ba1Ssnj 36813496ba1Ssnjstatic int 36913496ba1Ssnjintel_video_overlay_put_image(ScrnInfoPtr scrn, 37013496ba1Ssnj short src_x, short src_y, 37113496ba1Ssnj short drw_x, short drw_y, 37213496ba1Ssnj short src_w, short src_h, 37313496ba1Ssnj short drw_w, short drw_h, 37413496ba1Ssnj int id, unsigned char *buf, 37513496ba1Ssnj short width, short height, 37613496ba1Ssnj Bool sync, RegionPtr clipBoxes, pointer data, 37713496ba1Ssnj DrawablePtr drawable) 37813496ba1Ssnj{ 37913496ba1Ssnj intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 38013496ba1Ssnj int dstPitch, dstPitch2; 38113496ba1Ssnj BoxRec dstBox; 38213496ba1Ssnj xf86CrtcPtr crtc; 38313496ba1Ssnj int top, left, npixels, nlines; 38413496ba1Ssnj 38513496ba1Ssnj#if 0 38613496ba1Ssnj ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n" 38713496ba1Ssnj "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, 38813496ba1Ssnj drw_y, drw_w, drw_h, width, height); 38913496ba1Ssnj#endif 39013496ba1Ssnj 39113496ba1Ssnj /* If dst width and height are less than 1/8th the src size, the 39213496ba1Ssnj * src/dst scale factor becomes larger than 8 and doesn't fit in 39313496ba1Ssnj * the scale register. */ 39413496ba1Ssnj if (src_w >= (drw_w * 8)) 39513496ba1Ssnj drw_w = src_w / 7; 39613496ba1Ssnj 39713496ba1Ssnj if (src_h >= (drw_h * 8)) 39813496ba1Ssnj drw_h = src_h / 7; 39913496ba1Ssnj 40013496ba1Ssnj if (!intel_clip_video_helper(scrn, 40113496ba1Ssnj adaptor_priv, 40213496ba1Ssnj &crtc, 40313496ba1Ssnj &dstBox, 40413496ba1Ssnj src_x, src_y, drw_x, drw_y, 40513496ba1Ssnj src_w, src_h, drw_w, drw_h, 40613496ba1Ssnj id, 40713496ba1Ssnj &top, &left, &npixels, &nlines, clipBoxes, 40813496ba1Ssnj width, height)) 40913496ba1Ssnj return Success; 41013496ba1Ssnj 41113496ba1Ssnj /* overlay can't handle rotation natively, store it for the copy func */ 41213496ba1Ssnj if (crtc) 41313496ba1Ssnj adaptor_priv->rotation = crtc->rotation; 41413496ba1Ssnj else { 41513496ba1Ssnj xf86DrvMsg(scrn->scrnIndex, X_WARNING, 41613496ba1Ssnj "Fail to clip video to any crtc!\n"); 41713496ba1Ssnj return Success; 41813496ba1Ssnj } 41913496ba1Ssnj 42013496ba1Ssnj if (!intel_video_copy_data(scrn, adaptor_priv, width, height, 42113496ba1Ssnj &dstPitch, &dstPitch2, 42213496ba1Ssnj top, left, npixels, nlines, id, buf)) 42313496ba1Ssnj return BadAlloc; 42413496ba1Ssnj 42513496ba1Ssnj if (!intel_video_overlay_display 42613496ba1Ssnj (scrn, crtc, id, width, height, dstPitch, dstPitch2, 42713496ba1Ssnj &dstBox, src_w, src_h, drw_w, drw_h)) 42813496ba1Ssnj return BadAlloc; 42913496ba1Ssnj 43013496ba1Ssnj /* update cliplist */ 43113496ba1Ssnj if (!REGION_EQUAL(scrn->pScreen, &adaptor_priv->clip, clipBoxes)) { 43213496ba1Ssnj REGION_COPY(scrn->pScreen, &adaptor_priv->clip, clipBoxes); 43313496ba1Ssnj xf86XVFillKeyHelperDrawable(drawable, 43413496ba1Ssnj adaptor_priv->colorKey, 43513496ba1Ssnj clipBoxes); 43613496ba1Ssnj } 43713496ba1Ssnj 43813496ba1Ssnj adaptor_priv->videoStatus = CLIENT_VIDEO_ON; 43913496ba1Ssnj 44013496ba1Ssnj return Success; 44113496ba1Ssnj} 44213496ba1Ssnj 44313496ba1SsnjXF86VideoAdaptorPtr intel_video_overlay_setup_image(ScreenPtr screen) 44413496ba1Ssnj{ 44513496ba1Ssnj ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 44613496ba1Ssnj intel_screen_private *intel = intel_get_screen_private(scrn); 44713496ba1Ssnj XF86VideoAdaptorPtr adapt; 44813496ba1Ssnj intel_adaptor_private *adaptor_priv; 44913496ba1Ssnj XF86AttributePtr att; 45013496ba1Ssnj 45113496ba1Ssnj /* Set up overlay video if it is available */ 45213496ba1Ssnj intel->use_overlay = intel_has_overlay(intel); 45313496ba1Ssnj if (!intel->use_overlay) 45413496ba1Ssnj return NULL; 45513496ba1Ssnj 45613496ba1Ssnj OVERLAY_DEBUG("intel_video_overlay_setup_image\n"); 45713496ba1Ssnj 45813496ba1Ssnj if (!(adapt = calloc(1, 45913496ba1Ssnj sizeof(XF86VideoAdaptorRec) + 46013496ba1Ssnj sizeof(intel_adaptor_private) + 46113496ba1Ssnj sizeof(DevUnion)))) 46213496ba1Ssnj return NULL; 46313496ba1Ssnj 46413496ba1Ssnj adapt->type = XvWindowMask | XvInputMask | XvImageMask; 46513496ba1Ssnj adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT */ ; 46613496ba1Ssnj adapt->name = "Intel(R) Video Overlay"; 46713496ba1Ssnj adapt->nEncodings = 1; 46813496ba1Ssnj adapt->pEncodings = xnfalloc(sizeof(intel_xv_dummy_encoding)); 46913496ba1Ssnj memcpy(adapt->pEncodings, intel_xv_dummy_encoding, sizeof(intel_xv_dummy_encoding)); 47013496ba1Ssnj if (IS_845G(intel) || IS_I830(intel)) { 47113496ba1Ssnj adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY; 47213496ba1Ssnj adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY; 47313496ba1Ssnj } 47413496ba1Ssnj adapt->nFormats = NUM_FORMATS; 47513496ba1Ssnj adapt->pFormats = intel_xv_formats; 47613496ba1Ssnj adapt->nPorts = 1; 47713496ba1Ssnj adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 47813496ba1Ssnj 47913496ba1Ssnj adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1]; 48013496ba1Ssnj 48113496ba1Ssnj adapt->pPortPrivates[0].ptr = (pointer) (adaptor_priv); 48213496ba1Ssnj adapt->nAttributes = NUM_ATTRIBUTES; 48313496ba1Ssnj if (INTEL_INFO(intel)->gen >= 030) 48413496ba1Ssnj adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */ 48513496ba1Ssnj adapt->pAttributes = 48613496ba1Ssnj xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes); 48713496ba1Ssnj /* Now copy the attributes */ 48813496ba1Ssnj att = adapt->pAttributes; 48913496ba1Ssnj memcpy((char *)att, (char *)intel_xv_attributes, 49013496ba1Ssnj sizeof(XF86AttributeRec) * NUM_ATTRIBUTES); 49113496ba1Ssnj att += NUM_ATTRIBUTES; 49213496ba1Ssnj if (INTEL_INFO(intel)->gen >= 030) { 49313496ba1Ssnj memcpy((char *)att, (char *)intel_xv_gamma_attributes, 49413496ba1Ssnj sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES); 49513496ba1Ssnj } 49613496ba1Ssnj adapt->nImages = NUM_IMAGES - XVMC_IMAGE; 49713496ba1Ssnj 49813496ba1Ssnj adapt->pImages = intel_xv_images; 49913496ba1Ssnj adapt->PutVideo = NULL; 50013496ba1Ssnj adapt->PutStill = NULL; 50113496ba1Ssnj adapt->GetVideo = NULL; 50213496ba1Ssnj adapt->GetStill = NULL; 50313496ba1Ssnj adapt->StopVideo = intel_video_stop_video; 50413496ba1Ssnj adapt->SetPortAttribute = intel_video_overlay_set_port_attribute; 50513496ba1Ssnj adapt->GetPortAttribute = intel_video_get_port_attribute; 50613496ba1Ssnj adapt->QueryBestSize = intel_video_query_best_size; 50713496ba1Ssnj adapt->PutImage = intel_video_overlay_put_image; 50813496ba1Ssnj adapt->QueryImageAttributes = intel_video_query_image_attributes; 50913496ba1Ssnj 51013496ba1Ssnj adaptor_priv->textured = FALSE; 51113496ba1Ssnj adaptor_priv->colorKey = intel->colorKey & ((1 << scrn->depth) - 1); 51213496ba1Ssnj adaptor_priv->videoStatus = 0; 51313496ba1Ssnj adaptor_priv->brightness = -19; /* (255/219) * -16 */ 51413496ba1Ssnj adaptor_priv->contrast = 75; /* 255/219 * 64 */ 51513496ba1Ssnj adaptor_priv->saturation = 146; /* 128/112 * 128 */ 51613496ba1Ssnj adaptor_priv->desired_crtc = NULL; 51713496ba1Ssnj adaptor_priv->buf = NULL; 51813496ba1Ssnj adaptor_priv->old_buf[0] = NULL; 51913496ba1Ssnj adaptor_priv->old_buf[1] = NULL; 52013496ba1Ssnj adaptor_priv->gamma5 = 0xc0c0c0; 52113496ba1Ssnj adaptor_priv->gamma4 = 0x808080; 52213496ba1Ssnj adaptor_priv->gamma3 = 0x404040; 52313496ba1Ssnj adaptor_priv->gamma2 = 0x202020; 52413496ba1Ssnj adaptor_priv->gamma1 = 0x101010; 52513496ba1Ssnj adaptor_priv->gamma0 = 0x080808; 52613496ba1Ssnj 52713496ba1Ssnj adaptor_priv->rotation = RR_Rotate_0; 52813496ba1Ssnj 52913496ba1Ssnj /* gotta uninit this someplace */ 53013496ba1Ssnj REGION_NULL(screen, &adaptor_priv->clip); 53113496ba1Ssnj 53213496ba1Ssnj intel->adaptor = adapt; 53313496ba1Ssnj 53413496ba1Ssnj intel_xv_ColorKey = MAKE_ATOM("XV_COLORKEY"); 53513496ba1Ssnj intel_xv_Brightness = MAKE_ATOM("XV_BRIGHTNESS"); 53613496ba1Ssnj intel_xv_Contrast = MAKE_ATOM("XV_CONTRAST"); 53713496ba1Ssnj intel_xv_Saturation = MAKE_ATOM("XV_SATURATION"); 53813496ba1Ssnj 53913496ba1Ssnj /* Allow the pipe to be switched from pipe A to B when in clone mode */ 54013496ba1Ssnj intel_xv_Pipe = MAKE_ATOM("XV_PIPE"); 54113496ba1Ssnj 54213496ba1Ssnj if (INTEL_INFO(intel)->gen >= 030) { 54313496ba1Ssnj intel_xv_Gamma0 = MAKE_ATOM("XV_GAMMA0"); 54413496ba1Ssnj intel_xv_Gamma1 = MAKE_ATOM("XV_GAMMA1"); 54513496ba1Ssnj intel_xv_Gamma2 = MAKE_ATOM("XV_GAMMA2"); 54613496ba1Ssnj intel_xv_Gamma3 = MAKE_ATOM("XV_GAMMA3"); 54713496ba1Ssnj intel_xv_Gamma4 = MAKE_ATOM("XV_GAMMA4"); 54813496ba1Ssnj intel_xv_Gamma5 = MAKE_ATOM("XV_GAMMA5"); 54913496ba1Ssnj } 55013496ba1Ssnj 55113496ba1Ssnj intel_overlay_update_attrs(intel); 55213496ba1Ssnj 55313496ba1Ssnj return adapt; 55413496ba1Ssnj} 555