1428d7b3dSmrg/*************************************************************************** 2428d7b3dSmrg 3428d7b3dSmrg Copyright 2000 Intel Corporation. All Rights Reserved. 4428d7b3dSmrg 5428d7b3dSmrg Permission is hereby granted, free of charge, to any person obtaining a 6428d7b3dSmrg copy of this software and associated documentation files (the 7428d7b3dSmrg "Software"), to deal in the Software without restriction, including 8428d7b3dSmrg without limitation the rights to use, copy, modify, merge, publish, 9428d7b3dSmrg distribute, sub license, and/or sell copies of the Software, and to 10428d7b3dSmrg permit persons to whom the Software is furnished to do so, subject to 11428d7b3dSmrg the following conditions: 12428d7b3dSmrg 13428d7b3dSmrg The above copyright notice and this permission notice (including the 14428d7b3dSmrg next paragraph) shall be included in all copies or substantial portions 15428d7b3dSmrg of the Software. 16428d7b3dSmrg 17428d7b3dSmrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18428d7b3dSmrg OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19428d7b3dSmrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20428d7b3dSmrg IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21428d7b3dSmrg DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22428d7b3dSmrg OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 23428d7b3dSmrg THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24428d7b3dSmrg 25428d7b3dSmrg **************************************************************************/ 26428d7b3dSmrg 27428d7b3dSmrg/* 28428d7b3dSmrg * i830_video.c: i830/i845 Xv driver. 29428d7b3dSmrg * 30428d7b3dSmrg * Copyright © 2002 by Alan Hourihane and David Dawes 31428d7b3dSmrg * 32428d7b3dSmrg * Authors: 33428d7b3dSmrg * Alan Hourihane <alanh@tungstengraphics.com> 34428d7b3dSmrg * David Dawes <dawes@xfree86.org> 35428d7b3dSmrg * 36428d7b3dSmrg * Derived from i810 Xv driver: 37428d7b3dSmrg * 38428d7b3dSmrg * Authors of i810 code: 39428d7b3dSmrg * Jonathan Bian <jonathan.bian@intel.com> 40428d7b3dSmrg * Offscreen Images: 41428d7b3dSmrg * Matt Sottek <matthew.j.sottek@intel.com> 42428d7b3dSmrg */ 43428d7b3dSmrg 44428d7b3dSmrg/* 45428d7b3dSmrg * XXX Could support more formats. 46428d7b3dSmrg */ 47428d7b3dSmrg 48428d7b3dSmrg#ifdef HAVE_CONFIG_H 49428d7b3dSmrg#include "config.h" 50428d7b3dSmrg#endif 51428d7b3dSmrg 52428d7b3dSmrg#include <inttypes.h> 53428d7b3dSmrg#include <math.h> 54428d7b3dSmrg#include <string.h> 55428d7b3dSmrg#include <assert.h> 56428d7b3dSmrg#include <errno.h> 57428d7b3dSmrg 58428d7b3dSmrg#include "xorg-server.h" 59428d7b3dSmrg#include "xf86.h" 60428d7b3dSmrg#include "xf86_OSproc.h" 61428d7b3dSmrg#include "compiler.h" 62428d7b3dSmrg#include "xf86Pci.h" 63428d7b3dSmrg#include "xf86fbman.h" 64428d7b3dSmrg#include "xf86drm.h" 65428d7b3dSmrg#include "regionstr.h" 66428d7b3dSmrg#include "randrstr.h" 67428d7b3dSmrg#include "windowstr.h" 68428d7b3dSmrg#include "damage.h" 69428d7b3dSmrg#include "intel.h" 70428d7b3dSmrg#include "intel_video.h" 71428d7b3dSmrg#include "i830_reg.h" 72428d7b3dSmrg#include "xf86xv.h" 73428d7b3dSmrg#include <X11/extensions/Xv.h> 74428d7b3dSmrg#include "dixstruct.h" 75428d7b3dSmrg#include "fourcc.h" 76428d7b3dSmrg 77428d7b3dSmrg#ifdef INTEL_XVMC 78428d7b3dSmrg#define _INTEL_XVMC_SERVER_ 79428d7b3dSmrg#include "intel_xvmc.h" 80428d7b3dSmrg#endif 81428d7b3dSmrg#include "intel_uxa.h" 82428d7b3dSmrg#include "intel_video_overlay.h" 83428d7b3dSmrg 84428d7b3dSmrgAtom intel_xv_Brightness, intel_xv_Contrast, intel_xv_Saturation, intel_xv_ColorKey, intel_xv_Pipe; 85428d7b3dSmrgAtom intel_xv_Gamma0, intel_xv_Gamma1, intel_xv_Gamma2, intel_xv_Gamma3, intel_xv_Gamma4, intel_xv_Gamma5; 86428d7b3dSmrgAtom intel_xv_SyncToVblank; 87428d7b3dSmrg 88428d7b3dSmrg/* client libraries expect an encoding */ 89428d7b3dSmrgconst XF86VideoEncodingRec intel_xv_dummy_encoding[1] = { 90428d7b3dSmrg { 91428d7b3dSmrg 0, 92428d7b3dSmrg "XV_IMAGE", 93428d7b3dSmrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 94428d7b3dSmrg {1, 1} 95428d7b3dSmrg } 96428d7b3dSmrg}; 97428d7b3dSmrg 98428d7b3dSmrgXF86VideoFormatRec intel_xv_formats[NUM_FORMATS] = { 99428d7b3dSmrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 100428d7b3dSmrg}; 101428d7b3dSmrg 102428d7b3dSmrgXF86AttributeRec intel_xv_attributes[NUM_ATTRIBUTES] = { 103428d7b3dSmrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 104428d7b3dSmrg {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 105428d7b3dSmrg {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, 106428d7b3dSmrg {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"}, 107428d7b3dSmrg {XvSettable | XvGettable, -1, 1, "XV_PIPE"} 108428d7b3dSmrg}; 109428d7b3dSmrg 110428d7b3dSmrg#define GAMMA_ATTRIBUTES 6 111428d7b3dSmrgXF86AttributeRec intel_xv_gamma_attributes[GAMMA_ATTRIBUTES] = { 112428d7b3dSmrg {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"}, 113428d7b3dSmrg {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"}, 114428d7b3dSmrg {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"}, 115428d7b3dSmrg {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"}, 116428d7b3dSmrg {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"}, 117428d7b3dSmrg {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"} 118428d7b3dSmrg}; 119428d7b3dSmrg 120428d7b3dSmrg#ifdef INTEL_XVMC 121428d7b3dSmrg#define NUM_IMAGES 5 122428d7b3dSmrg#define XVMC_IMAGE 1 123428d7b3dSmrg#else 124428d7b3dSmrg#define NUM_IMAGES 4 125428d7b3dSmrg#define XVMC_IMAGE 0 126428d7b3dSmrg#endif 127428d7b3dSmrg 128428d7b3dSmrgXF86ImageRec intel_xv_images[NUM_IMAGES] = { 129428d7b3dSmrg XVIMAGE_YUY2, 130428d7b3dSmrg XVIMAGE_YV12, 131428d7b3dSmrg XVIMAGE_I420, 132428d7b3dSmrg XVIMAGE_UYVY, 133428d7b3dSmrg#ifdef INTEL_XVMC 134428d7b3dSmrg { 135428d7b3dSmrg /* 136428d7b3dSmrg * Below, a dummy picture type that is used in XvPutImage only to do 137428d7b3dSmrg * an overlay update. Introduced for the XvMC client lib. 138428d7b3dSmrg * Defined to have a zero data size. 139428d7b3dSmrg */ 140428d7b3dSmrg FOURCC_XVMC, 141428d7b3dSmrg XvYUV, 142428d7b3dSmrg LSBFirst, 143428d7b3dSmrg {'X', 'V', 'M', 'C', 144428d7b3dSmrg 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 145428d7b3dSmrg 0x38, 0x9B, 0x71}, 146428d7b3dSmrg 12, 147428d7b3dSmrg XvPlanar, 148428d7b3dSmrg 3, 149428d7b3dSmrg 0, 0, 0, 0, 150428d7b3dSmrg 8, 8, 8, 151428d7b3dSmrg 1, 2, 2, 152428d7b3dSmrg 1, 2, 2, 153428d7b3dSmrg {'Y', 'V', 'U', 154428d7b3dSmrg 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155428d7b3dSmrg 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156428d7b3dSmrg XvTopToBottom}, 157428d7b3dSmrg#endif 158428d7b3dSmrg}; 159428d7b3dSmrg 160428d7b3dSmrgvoid intel_video_init(ScreenPtr screen) 161428d7b3dSmrg{ 162428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 163428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 164428d7b3dSmrg XF86VideoAdaptorPtr *adaptors = NULL, *newAdaptors = NULL; 165428d7b3dSmrg XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; 166428d7b3dSmrg int num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors); 167428d7b3dSmrg 168428d7b3dSmrg /* Give our adaptor list enough space for the overlay and/or texture video 169428d7b3dSmrg * adaptors. 170428d7b3dSmrg */ 171428d7b3dSmrg newAdaptors = realloc(adaptors, 172428d7b3dSmrg (num_adaptors + 3) * sizeof(XF86VideoAdaptorPtr)); 173428d7b3dSmrg 174428d7b3dSmrg if (newAdaptors == NULL) { 175428d7b3dSmrg free(adaptors); 176428d7b3dSmrg return; 177428d7b3dSmrg } 178428d7b3dSmrg adaptors = newAdaptors; 179428d7b3dSmrg 180428d7b3dSmrg /* Add the adaptors supported by our hardware. First, set up the atoms 181428d7b3dSmrg * that will be used by both output adaptors. 182428d7b3dSmrg */ 183428d7b3dSmrg intel_xv_Brightness = MAKE_ATOM("XV_BRIGHTNESS"); 184428d7b3dSmrg intel_xv_Contrast = MAKE_ATOM("XV_CONTRAST"); 185428d7b3dSmrg 186428d7b3dSmrg /* Set up textured video if we can do it at this depth and we are on 187428d7b3dSmrg * supported hardware. 188428d7b3dSmrg */ 189428d7b3dSmrg if (!intel->force_fallback && 190428d7b3dSmrg scrn->bitsPerPixel >= 16 && 191428d7b3dSmrg INTEL_INFO(intel)->gen >= 030 && 192428d7b3dSmrg INTEL_INFO(intel)->gen < 0100) { 193428d7b3dSmrg texturedAdaptor = intel_uxa_video_setup_image_textured(screen); 194428d7b3dSmrg if (texturedAdaptor != NULL) { 195428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 196428d7b3dSmrg "Set up textured video\n"); 197428d7b3dSmrg } else { 198428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 199428d7b3dSmrg "Failed to set up textured video\n"); 200428d7b3dSmrg } 201428d7b3dSmrg } 202428d7b3dSmrg 203428d7b3dSmrg overlayAdaptor = intel_video_overlay_setup_image(screen); 204428d7b3dSmrg 205428d7b3dSmrg if (intel->use_overlay) { 206428d7b3dSmrg if (overlayAdaptor != NULL) { 207428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 208428d7b3dSmrg "Set up overlay video\n"); 209428d7b3dSmrg } else { 210428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 211428d7b3dSmrg "Failed to set up overlay video\n"); 212428d7b3dSmrg } 213428d7b3dSmrg } 214428d7b3dSmrg 215428d7b3dSmrg if (overlayAdaptor && intel->XvPreferOverlay) 216428d7b3dSmrg adaptors[num_adaptors++] = overlayAdaptor; 217428d7b3dSmrg 218428d7b3dSmrg if (texturedAdaptor) 219428d7b3dSmrg adaptors[num_adaptors++] = texturedAdaptor; 220428d7b3dSmrg 221428d7b3dSmrg if (overlayAdaptor && !intel->XvPreferOverlay) 222428d7b3dSmrg adaptors[num_adaptors++] = overlayAdaptor; 223428d7b3dSmrg 224428d7b3dSmrg if (num_adaptors) { 225428d7b3dSmrg xf86XVScreenInit(screen, adaptors, num_adaptors); 226428d7b3dSmrg } else { 227428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 228428d7b3dSmrg "Disabling Xv because no adaptors could be initialized.\n"); 229428d7b3dSmrg intel->XvEnabled = FALSE; 230428d7b3dSmrg } 231428d7b3dSmrg 232428d7b3dSmrg#ifdef INTEL_XVMC 233428d7b3dSmrg if (texturedAdaptor) 234428d7b3dSmrg intel_xvmc_adaptor_init(screen); 235428d7b3dSmrg#endif 236428d7b3dSmrg 237428d7b3dSmrg free(adaptors); 238428d7b3dSmrg} 239428d7b3dSmrg 240428d7b3dSmrgvoid intel_free_video_buffers(intel_adaptor_private *adaptor_priv) 241428d7b3dSmrg{ 242428d7b3dSmrg int i; 243428d7b3dSmrg 244428d7b3dSmrg for (i = 0; i < 2; i++) { 245428d7b3dSmrg if (adaptor_priv->old_buf[i]) { 246428d7b3dSmrg drm_intel_bo_disable_reuse(adaptor_priv->old_buf[i]); 247428d7b3dSmrg drm_intel_bo_unreference(adaptor_priv->old_buf[i]); 248428d7b3dSmrg adaptor_priv->old_buf[i] = NULL; 249428d7b3dSmrg } 250428d7b3dSmrg } 251428d7b3dSmrg 252428d7b3dSmrg if (adaptor_priv->buf) { 253428d7b3dSmrg drm_intel_bo_unreference(adaptor_priv->buf); 254428d7b3dSmrg adaptor_priv->buf = NULL; 255428d7b3dSmrg } 256428d7b3dSmrg} 257428d7b3dSmrg 258428d7b3dSmrgint 259428d7b3dSmrgintel_video_get_port_attribute(ScrnInfoPtr scrn, 260428d7b3dSmrg Atom attribute, INT32 * value, pointer data) 261428d7b3dSmrg{ 262428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 263428d7b3dSmrg intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 264428d7b3dSmrg 265428d7b3dSmrg if (attribute == intel_xv_Brightness) { 266428d7b3dSmrg *value = adaptor_priv->brightness; 267428d7b3dSmrg } else if (attribute == intel_xv_Contrast) { 268428d7b3dSmrg *value = adaptor_priv->contrast; 269428d7b3dSmrg } else if (attribute == intel_xv_Saturation) { 270428d7b3dSmrg *value = adaptor_priv->saturation; 271428d7b3dSmrg } else if (attribute == intel_xv_Pipe) { 272428d7b3dSmrg int c; 273428d7b3dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 274428d7b3dSmrg for (c = 0; c < xf86_config->num_crtc; c++) 275428d7b3dSmrg if (xf86_config->crtc[c] == adaptor_priv->desired_crtc) 276428d7b3dSmrg break; 277428d7b3dSmrg if (c == xf86_config->num_crtc) 278428d7b3dSmrg c = -1; 279428d7b3dSmrg *value = c; 280428d7b3dSmrg } else if (attribute == intel_xv_Gamma0 && (INTEL_INFO(intel)->gen >= 030)) { 281428d7b3dSmrg *value = adaptor_priv->gamma0; 282428d7b3dSmrg } else if (attribute == intel_xv_Gamma1 && (INTEL_INFO(intel)->gen >= 030)) { 283428d7b3dSmrg *value = adaptor_priv->gamma1; 284428d7b3dSmrg } else if (attribute == intel_xv_Gamma2 && (INTEL_INFO(intel)->gen >= 030)) { 285428d7b3dSmrg *value = adaptor_priv->gamma2; 286428d7b3dSmrg } else if (attribute == intel_xv_Gamma3 && (INTEL_INFO(intel)->gen >= 030)) { 287428d7b3dSmrg *value = adaptor_priv->gamma3; 288428d7b3dSmrg } else if (attribute == intel_xv_Gamma4 && (INTEL_INFO(intel)->gen >= 030)) { 289428d7b3dSmrg *value = adaptor_priv->gamma4; 290428d7b3dSmrg } else if (attribute == intel_xv_Gamma5 && (INTEL_INFO(intel)->gen >= 030)) { 291428d7b3dSmrg *value = adaptor_priv->gamma5; 292428d7b3dSmrg } else if (attribute == intel_xv_ColorKey) { 293428d7b3dSmrg *value = adaptor_priv->colorKey; 294428d7b3dSmrg } else if (attribute == intel_xv_SyncToVblank) { 295428d7b3dSmrg *value = adaptor_priv->SyncToVblank; 296428d7b3dSmrg } else 297428d7b3dSmrg return BadMatch; 298428d7b3dSmrg 299428d7b3dSmrg return Success; 300428d7b3dSmrg} 301428d7b3dSmrg 302428d7b3dSmrgvoid 303428d7b3dSmrgintel_video_query_best_size(ScrnInfoPtr scrn, 304428d7b3dSmrg Bool motion, 305428d7b3dSmrg short vid_w, short vid_h, 306428d7b3dSmrg short drw_w, short drw_h, 307428d7b3dSmrg unsigned int *p_w, unsigned int *p_h, pointer data) 308428d7b3dSmrg{ 309428d7b3dSmrg if (vid_w > (drw_w << 1)) 310428d7b3dSmrg drw_w = vid_w >> 1; 311428d7b3dSmrg if (vid_h > (drw_h << 1)) 312428d7b3dSmrg drw_h = vid_h >> 1; 313428d7b3dSmrg 314428d7b3dSmrg *p_w = drw_w; 315428d7b3dSmrg *p_h = drw_h; 316428d7b3dSmrg} 317428d7b3dSmrg 318428d7b3dSmrgstatic Bool 319428d7b3dSmrgintel_video_copy_packed_data(intel_adaptor_private *adaptor_priv, 320428d7b3dSmrg unsigned char *buf, 321428d7b3dSmrg int srcPitch, int dstPitch, int top, int left, int h, int w) 322428d7b3dSmrg{ 323428d7b3dSmrg unsigned char *src, *dst, *dst_base; 324428d7b3dSmrg int i, j; 325428d7b3dSmrg unsigned char *s; 326428d7b3dSmrg 327428d7b3dSmrg#if 0 328428d7b3dSmrg ErrorF("intel_video_copy_packed_data: (%d,%d) (%d,%d)\n" 329428d7b3dSmrg "srcPitch: %d, dstPitch: %d\n", top, left, h, w, 330428d7b3dSmrg srcPitch, dstPitch); 331428d7b3dSmrg#endif 332428d7b3dSmrg 333428d7b3dSmrg src = buf + (top * srcPitch) + (left << 1); 334428d7b3dSmrg 335428d7b3dSmrg if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf)) 336428d7b3dSmrg return FALSE; 337428d7b3dSmrg 338428d7b3dSmrg dst_base = adaptor_priv->buf->virtual; 339428d7b3dSmrg 340428d7b3dSmrg dst = dst_base + adaptor_priv->YBufOffset; 341428d7b3dSmrg 342428d7b3dSmrg switch (adaptor_priv->rotation) { 343428d7b3dSmrg case RR_Rotate_0: 344428d7b3dSmrg w <<= 1; 345428d7b3dSmrg for (i = 0; i < h; i++) { 346428d7b3dSmrg memcpy(dst, src, w); 347428d7b3dSmrg src += srcPitch; 348428d7b3dSmrg dst += dstPitch; 349428d7b3dSmrg } 350428d7b3dSmrg break; 351428d7b3dSmrg case RR_Rotate_90: 352428d7b3dSmrg h <<= 1; 353428d7b3dSmrg for (i = 0; i < h; i += 2) { 354428d7b3dSmrg s = src; 355428d7b3dSmrg for (j = 0; j < w; j++) { 356428d7b3dSmrg /* Copy Y */ 357428d7b3dSmrg dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; 358428d7b3dSmrg (void)*s++; 359428d7b3dSmrg } 360428d7b3dSmrg src += srcPitch; 361428d7b3dSmrg } 362428d7b3dSmrg h >>= 1; 363428d7b3dSmrg src = buf + (top * srcPitch) + (left << 1); 364428d7b3dSmrg for (i = 0; i < h; i += 2) { 365428d7b3dSmrg for (j = 0; j < w; j += 2) { 366428d7b3dSmrg /* Copy U */ 367428d7b3dSmrg dst[((i * 2) + 1) + ((w - j - 1) * dstPitch)] = 368428d7b3dSmrg src[(j * 2) + 1 + (i * srcPitch)]; 369428d7b3dSmrg dst[((i * 2) + 1) + ((w - j - 2) * dstPitch)] = 370428d7b3dSmrg src[(j * 2) + 1 + ((i + 1) * srcPitch)]; 371428d7b3dSmrg /* Copy V */ 372428d7b3dSmrg dst[((i * 2) + 3) + ((w - j - 1) * dstPitch)] = 373428d7b3dSmrg src[(j * 2) + 3 + (i * srcPitch)]; 374428d7b3dSmrg dst[((i * 2) + 3) + ((w - j - 2) * dstPitch)] = 375428d7b3dSmrg src[(j * 2) + 3 + ((i + 1) * srcPitch)]; 376428d7b3dSmrg } 377428d7b3dSmrg } 378428d7b3dSmrg break; 379428d7b3dSmrg case RR_Rotate_180: 380428d7b3dSmrg w <<= 1; 381428d7b3dSmrg for (i = 0; i < h; i++) { 382428d7b3dSmrg s = src; 383428d7b3dSmrg for (j = 0; j < w; j += 4) { 384428d7b3dSmrg dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = 385428d7b3dSmrg *s++; 386428d7b3dSmrg dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = 387428d7b3dSmrg *s++; 388428d7b3dSmrg dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = 389428d7b3dSmrg *s++; 390428d7b3dSmrg dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = 391428d7b3dSmrg *s++; 392428d7b3dSmrg } 393428d7b3dSmrg src += srcPitch; 394428d7b3dSmrg } 395428d7b3dSmrg break; 396428d7b3dSmrg case RR_Rotate_270: 397428d7b3dSmrg h <<= 1; 398428d7b3dSmrg for (i = 0; i < h; i += 2) { 399428d7b3dSmrg s = src; 400428d7b3dSmrg for (j = 0; j < w; j++) { 401428d7b3dSmrg /* Copy Y */ 402428d7b3dSmrg dst[(h - i - 2) + (j * dstPitch)] = *s++; 403428d7b3dSmrg (void)*s++; 404428d7b3dSmrg } 405428d7b3dSmrg src += srcPitch; 406428d7b3dSmrg } 407428d7b3dSmrg h >>= 1; 408428d7b3dSmrg src = buf + (top * srcPitch) + (left << 1); 409428d7b3dSmrg for (i = 0; i < h; i += 2) { 410428d7b3dSmrg for (j = 0; j < w; j += 2) { 411428d7b3dSmrg /* Copy U */ 412428d7b3dSmrg dst[(((h - i) * 2) - 3) + (j * dstPitch)] = 413428d7b3dSmrg src[(j * 2) + 1 + (i * srcPitch)]; 414428d7b3dSmrg dst[(((h - i) * 2) - 3) + 415428d7b3dSmrg ((j + 1) * dstPitch)] = 416428d7b3dSmrg src[(j * 2) + 1 + ((i + 1) * srcPitch)]; 417428d7b3dSmrg /* Copy V */ 418428d7b3dSmrg dst[(((h - i) * 2) - 1) + (j * dstPitch)] = 419428d7b3dSmrg src[(j * 2) + 3 + (i * srcPitch)]; 420428d7b3dSmrg dst[(((h - i) * 2) - 1) + 421428d7b3dSmrg ((j + 1) * dstPitch)] = 422428d7b3dSmrg src[(j * 2) + 3 + ((i + 1) * srcPitch)]; 423428d7b3dSmrg } 424428d7b3dSmrg } 425428d7b3dSmrg break; 426428d7b3dSmrg } 427428d7b3dSmrg 428428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf); 429428d7b3dSmrg return TRUE; 430428d7b3dSmrg} 431428d7b3dSmrg 432428d7b3dSmrgstatic void intel_memcpy_plane(unsigned char *dst, unsigned char *src, 433428d7b3dSmrg int height, int width, 434428d7b3dSmrg int dstPitch, int srcPitch, Rotation rotation) 435428d7b3dSmrg{ 436428d7b3dSmrg int i, j = 0; 437428d7b3dSmrg unsigned char *s; 438428d7b3dSmrg 439428d7b3dSmrg switch (rotation) { 440428d7b3dSmrg case RR_Rotate_0: 441428d7b3dSmrg /* optimise for the case of no clipping */ 442428d7b3dSmrg if (srcPitch == dstPitch && srcPitch == width) 443428d7b3dSmrg memcpy(dst, src, srcPitch * height); 444428d7b3dSmrg else 445428d7b3dSmrg for (i = 0; i < height; i++) { 446428d7b3dSmrg memcpy(dst, src, width); 447428d7b3dSmrg src += srcPitch; 448428d7b3dSmrg dst += dstPitch; 449428d7b3dSmrg } 450428d7b3dSmrg break; 451428d7b3dSmrg case RR_Rotate_90: 452428d7b3dSmrg for (i = 0; i < height; i++) { 453428d7b3dSmrg s = src; 454428d7b3dSmrg for (j = 0; j < width; j++) { 455428d7b3dSmrg dst[(i) + ((width - j - 1) * dstPitch)] = *s++; 456428d7b3dSmrg } 457428d7b3dSmrg src += srcPitch; 458428d7b3dSmrg } 459428d7b3dSmrg break; 460428d7b3dSmrg case RR_Rotate_180: 461428d7b3dSmrg for (i = 0; i < height; i++) { 462428d7b3dSmrg s = src; 463428d7b3dSmrg for (j = 0; j < width; j++) { 464428d7b3dSmrg dst[(width - j - 1) + 465428d7b3dSmrg ((height - i - 1) * dstPitch)] = *s++; 466428d7b3dSmrg } 467428d7b3dSmrg src += srcPitch; 468428d7b3dSmrg } 469428d7b3dSmrg break; 470428d7b3dSmrg case RR_Rotate_270: 471428d7b3dSmrg for (i = 0; i < height; i++) { 472428d7b3dSmrg s = src; 473428d7b3dSmrg for (j = 0; j < width; j++) { 474428d7b3dSmrg dst[(height - i - 1) + (j * dstPitch)] = *s++; 475428d7b3dSmrg } 476428d7b3dSmrg src += srcPitch; 477428d7b3dSmrg } 478428d7b3dSmrg break; 479428d7b3dSmrg } 480428d7b3dSmrg} 481428d7b3dSmrg 482428d7b3dSmrgstatic Bool 483428d7b3dSmrgintel_video_copy_planar_data(intel_adaptor_private *adaptor_priv, 484428d7b3dSmrg unsigned char *buf, int srcPitch, int srcPitch2, 485428d7b3dSmrg int dstPitch, int dstPitch2, 486428d7b3dSmrg int srcH, int top, int left, 487428d7b3dSmrg int h, int w, int id) 488428d7b3dSmrg{ 489428d7b3dSmrg unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3; 490428d7b3dSmrg 491428d7b3dSmrg#if 0 492428d7b3dSmrg ErrorF("intel_video_copy_planar_data: srcPitch %d, srcPitch %d, dstPitch %d\n" 493428d7b3dSmrg "nlines %d, npixels %d, top %d, left %d\n", 494428d7b3dSmrg srcPitch, srcPitch2, dstPitch, h, w, top, left); 495428d7b3dSmrg#endif 496428d7b3dSmrg 497428d7b3dSmrg /* Copy Y data */ 498428d7b3dSmrg src1 = buf + (top * srcPitch) + left; 499428d7b3dSmrg#if 0 500428d7b3dSmrg ErrorF("src1 is %p, offset is %ld\n", src1, 501428d7b3dSmrg (unsigned long)src1 - (unsigned long)buf); 502428d7b3dSmrg#endif 503428d7b3dSmrg 504428d7b3dSmrg if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf)) 505428d7b3dSmrg return FALSE; 506428d7b3dSmrg 507428d7b3dSmrg dst_base = adaptor_priv->buf->virtual; 508428d7b3dSmrg 509428d7b3dSmrg dst1 = dst_base + adaptor_priv->YBufOffset; 510428d7b3dSmrg 511428d7b3dSmrg intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch, 512428d7b3dSmrg adaptor_priv->rotation); 513428d7b3dSmrg 514428d7b3dSmrg /* Copy V data for YV12, or U data for I420 */ 515428d7b3dSmrg src2 = buf + /* start of YUV data */ 516428d7b3dSmrg (srcH * srcPitch) + /* move over Luma plane */ 517428d7b3dSmrg ((top >> 1) * srcPitch2) + /* move down from by top lines */ 518428d7b3dSmrg (left >> 1); /* move left by left pixels */ 519428d7b3dSmrg 520428d7b3dSmrg#if 0 521428d7b3dSmrg ErrorF("src2 is %p, offset is %ld\n", src2, 522428d7b3dSmrg (unsigned long)src2 - (unsigned long)buf); 523428d7b3dSmrg#endif 524428d7b3dSmrg if (id == FOURCC_I420) 525428d7b3dSmrg dst2 = dst_base + adaptor_priv->UBufOffset; 526428d7b3dSmrg else 527428d7b3dSmrg dst2 = dst_base + adaptor_priv->VBufOffset; 528428d7b3dSmrg 529428d7b3dSmrg intel_memcpy_plane(dst2, src2, h / 2, w / 2, 530428d7b3dSmrg dstPitch, srcPitch2, adaptor_priv->rotation); 531428d7b3dSmrg 532428d7b3dSmrg /* Copy U data for YV12, or V data for I420 */ 533428d7b3dSmrg src3 = buf + /* start of YUV data */ 534428d7b3dSmrg (srcH * srcPitch) + /* move over Luma plane */ 535428d7b3dSmrg ((srcH >> 1) * srcPitch2) + /* move over Chroma plane */ 536428d7b3dSmrg ((top >> 1) * srcPitch2) + /* move down from by top lines */ 537428d7b3dSmrg (left >> 1); /* move left by left pixels */ 538428d7b3dSmrg#if 0 539428d7b3dSmrg ErrorF("src3 is %p, offset is %ld\n", src3, 540428d7b3dSmrg (unsigned long)src3 - (unsigned long)buf); 541428d7b3dSmrg#endif 542428d7b3dSmrg if (id == FOURCC_I420) 543428d7b3dSmrg dst3 = dst_base + adaptor_priv->VBufOffset; 544428d7b3dSmrg else 545428d7b3dSmrg dst3 = dst_base + adaptor_priv->UBufOffset; 546428d7b3dSmrg 547428d7b3dSmrg intel_memcpy_plane(dst3, src3, h / 2, w / 2, 548428d7b3dSmrg dstPitch, srcPitch2, adaptor_priv->rotation); 549428d7b3dSmrg 550428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf); 551428d7b3dSmrg return TRUE; 552428d7b3dSmrg} 553428d7b3dSmrg 554428d7b3dSmrgvoid 555428d7b3dSmrgintel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width, 556428d7b3dSmrg short height, int *dstPitch, int *dstPitch2, int *size, 557428d7b3dSmrg int id) 558428d7b3dSmrg{ 559428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 560428d7b3dSmrg int pitchAlign; 561428d7b3dSmrg 562428d7b3dSmrg /* Only needs to be DWORD-aligned for textured on i915, but overlay has 563428d7b3dSmrg * stricter requirements. 564428d7b3dSmrg */ 565428d7b3dSmrg if (adaptor_priv->textured) { 566428d7b3dSmrg pitchAlign = 4; 567428d7b3dSmrg } else { 568428d7b3dSmrg if (INTEL_INFO(intel)->gen >= 040) 569428d7b3dSmrg /* Actually the alignment is 64 bytes, too. But the 570428d7b3dSmrg * stride must be at least 512 bytes. Take the easy fix 571428d7b3dSmrg * and align on 512 bytes unconditionally. */ 572428d7b3dSmrg pitchAlign = 512; 573428d7b3dSmrg else if (IS_I830(intel) || IS_845G(intel)) 574428d7b3dSmrg /* Harsh, errata on these chipsets limit the stride to be 575428d7b3dSmrg * a multiple of 256 bytes. 576428d7b3dSmrg */ 577428d7b3dSmrg pitchAlign = 256; 578428d7b3dSmrg else 579428d7b3dSmrg pitchAlign = 64; 580428d7b3dSmrg } 581428d7b3dSmrg 582428d7b3dSmrg#if INTEL_XVMC 583428d7b3dSmrg /* for i915 xvmc, hw requires 1kb aligned surfaces */ 584428d7b3dSmrg if ((id == FOURCC_XVMC) && IS_GEN3(intel)) 585428d7b3dSmrg pitchAlign = 1024; 586428d7b3dSmrg#endif 587428d7b3dSmrg 588428d7b3dSmrg /* Determine the desired destination pitch (representing the chroma's pitch, 589428d7b3dSmrg * in the planar case. 590428d7b3dSmrg */ 591428d7b3dSmrg if (is_planar_fourcc(id)) { 592428d7b3dSmrg if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 593428d7b3dSmrg *dstPitch = ALIGN((height / 2), pitchAlign); 594428d7b3dSmrg *dstPitch2 = ALIGN(height, pitchAlign); 595428d7b3dSmrg *size = *dstPitch * width * 3; 596428d7b3dSmrg } else { 597428d7b3dSmrg *dstPitch = ALIGN((width / 2), pitchAlign); 598428d7b3dSmrg *dstPitch2 = ALIGN(width, pitchAlign); 599428d7b3dSmrg *size = *dstPitch * height * 3; 600428d7b3dSmrg } 601428d7b3dSmrg } else { 602428d7b3dSmrg if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 603428d7b3dSmrg *dstPitch = ALIGN((height << 1), pitchAlign); 604428d7b3dSmrg *size = *dstPitch * width; 605428d7b3dSmrg } else { 606428d7b3dSmrg *dstPitch = ALIGN((width << 1), pitchAlign); 607428d7b3dSmrg *size = *dstPitch * height; 608428d7b3dSmrg } 609428d7b3dSmrg *dstPitch2 = 0; 610428d7b3dSmrg } 611428d7b3dSmrg#if 0 612428d7b3dSmrg ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch, 613428d7b3dSmrg size); 614428d7b3dSmrg#endif 615428d7b3dSmrg 616428d7b3dSmrg adaptor_priv->YBufOffset = 0; 617428d7b3dSmrg 618428d7b3dSmrg if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 619428d7b3dSmrg adaptor_priv->UBufOffset = 620428d7b3dSmrg adaptor_priv->YBufOffset + (*dstPitch2 * width); 621428d7b3dSmrg adaptor_priv->VBufOffset = 622428d7b3dSmrg adaptor_priv->UBufOffset + (*dstPitch * width / 2); 623428d7b3dSmrg } else { 624428d7b3dSmrg adaptor_priv->UBufOffset = 625428d7b3dSmrg adaptor_priv->YBufOffset + (*dstPitch2 * height); 626428d7b3dSmrg adaptor_priv->VBufOffset = 627428d7b3dSmrg adaptor_priv->UBufOffset + (*dstPitch * height / 2); 628428d7b3dSmrg } 629428d7b3dSmrg} 630428d7b3dSmrg 631428d7b3dSmrgstatic Bool 632428d7b3dSmrgintel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, 633428d7b3dSmrg int alloc_size, int id, unsigned char *buf) 634428d7b3dSmrg{ 635428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 636428d7b3dSmrg 637428d7b3dSmrg /* Free the current buffer if we're going to have to reallocate */ 638428d7b3dSmrg if (adaptor_priv->buf && adaptor_priv->buf->size < alloc_size) 639428d7b3dSmrg intel_free_video_buffers(adaptor_priv); 640428d7b3dSmrg 641428d7b3dSmrg if (adaptor_priv->buf == NULL) { 642428d7b3dSmrg adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer", 643428d7b3dSmrg alloc_size, 4096); 644428d7b3dSmrg if (adaptor_priv->buf == NULL) 645428d7b3dSmrg return FALSE; 646428d7b3dSmrg 647428d7b3dSmrg adaptor_priv->reusable = TRUE; 648428d7b3dSmrg } 649428d7b3dSmrg 650428d7b3dSmrg return TRUE; 651428d7b3dSmrg} 652428d7b3dSmrg 653428d7b3dSmrgBool 654428d7b3dSmrgintel_video_copy_data(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, 655428d7b3dSmrg short width, short height, int *dstPitch, int *dstPitch2, 656428d7b3dSmrg int top, int left, int npixels, int nlines, 657428d7b3dSmrg int id, unsigned char *buf) 658428d7b3dSmrg{ 659428d7b3dSmrg int srcPitch = 0, srcPitch2 = 0; 660428d7b3dSmrg int size; 661428d7b3dSmrg 662428d7b3dSmrg if (is_planar_fourcc(id)) { 663428d7b3dSmrg srcPitch = ALIGN(width, 0x4); 664428d7b3dSmrg srcPitch2 = ALIGN((width >> 1), 0x4); 665428d7b3dSmrg } else { 666428d7b3dSmrg srcPitch = width << 1; 667428d7b3dSmrg } 668428d7b3dSmrg 669428d7b3dSmrg intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch, 670428d7b3dSmrg dstPitch2, &size, id); 671428d7b3dSmrg 672428d7b3dSmrg if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf)) 673428d7b3dSmrg return FALSE; 674428d7b3dSmrg 675428d7b3dSmrg /* copy data */ 676428d7b3dSmrg if (is_planar_fourcc(id)) { 677428d7b3dSmrg return intel_video_copy_planar_data(adaptor_priv, buf, srcPitch, srcPitch2, 678428d7b3dSmrg *dstPitch, *dstPitch2, 679428d7b3dSmrg height, top, left, nlines, 680428d7b3dSmrg npixels, id); 681428d7b3dSmrg } else { 682428d7b3dSmrg return intel_video_copy_packed_data(adaptor_priv, buf, srcPitch, *dstPitch, top, left, 683428d7b3dSmrg nlines, npixels); 684428d7b3dSmrg } 685428d7b3dSmrg} 686428d7b3dSmrg 687428d7b3dSmrgint is_planar_fourcc(int id) 688428d7b3dSmrg{ 689428d7b3dSmrg switch (id) { 690428d7b3dSmrg case FOURCC_YV12: 691428d7b3dSmrg case FOURCC_I420: 692428d7b3dSmrg#ifdef INTEL_XVMC 693428d7b3dSmrg case FOURCC_XVMC: 694428d7b3dSmrg#endif 695428d7b3dSmrg return 1; 696428d7b3dSmrg case FOURCC_UYVY: 697428d7b3dSmrg case FOURCC_YUY2: 698428d7b3dSmrg return 0; 699428d7b3dSmrg default: 700428d7b3dSmrg ErrorF("Unknown format 0x%x\n", id); 701428d7b3dSmrg return 0; 702428d7b3dSmrg } 703428d7b3dSmrg} 704428d7b3dSmrg 705428d7b3dSmrgBool 706428d7b3dSmrgintel_clip_video_helper(ScrnInfoPtr scrn, 707428d7b3dSmrg intel_adaptor_private *adaptor_priv, 708428d7b3dSmrg xf86CrtcPtr * crtc_ret, 709428d7b3dSmrg BoxPtr dst, 710428d7b3dSmrg short src_x, short src_y, 711428d7b3dSmrg short drw_x, short drw_y, 712428d7b3dSmrg short src_w, short src_h, 713428d7b3dSmrg short drw_w, short drw_h, 714428d7b3dSmrg int id, 715428d7b3dSmrg int *top, int* left, int* npixels, int *nlines, 716428d7b3dSmrg RegionPtr reg, INT32 width, INT32 height) 717428d7b3dSmrg{ 718428d7b3dSmrg Bool ret; 719428d7b3dSmrg RegionRec crtc_region_local; 720428d7b3dSmrg RegionPtr crtc_region = reg; 721428d7b3dSmrg BoxRec crtc_box; 722428d7b3dSmrg INT32 x1, x2, y1, y2; 723428d7b3dSmrg xf86CrtcPtr crtc; 724428d7b3dSmrg 725428d7b3dSmrg x1 = src_x; 726428d7b3dSmrg x2 = src_x + src_w; 727428d7b3dSmrg y1 = src_y; 728428d7b3dSmrg y2 = src_y + src_h; 729428d7b3dSmrg 730428d7b3dSmrg dst->x1 = drw_x; 731428d7b3dSmrg dst->x2 = drw_x + drw_w; 732428d7b3dSmrg dst->y1 = drw_y; 733428d7b3dSmrg dst->y2 = drw_y + drw_h; 734428d7b3dSmrg 735428d7b3dSmrg /* 736428d7b3dSmrg * For overlay video, compute the relevant CRTC and 737428d7b3dSmrg * clip video to that 738428d7b3dSmrg */ 739428d7b3dSmrg crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc, 740428d7b3dSmrg &crtc_box); 741428d7b3dSmrg 742428d7b3dSmrg /* For textured video, we don't actually want to clip at all. */ 743428d7b3dSmrg if (crtc && !adaptor_priv->textured) { 744428d7b3dSmrg REGION_INIT(screen, &crtc_region_local, &crtc_box, 1); 745428d7b3dSmrg crtc_region = &crtc_region_local; 746428d7b3dSmrg REGION_INTERSECT(screen, crtc_region, crtc_region, 747428d7b3dSmrg reg); 748428d7b3dSmrg } 749428d7b3dSmrg *crtc_ret = crtc; 750428d7b3dSmrg 751428d7b3dSmrg ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2, 752428d7b3dSmrg crtc_region, width, height); 753428d7b3dSmrg if (crtc_region != reg) 754428d7b3dSmrg REGION_UNINIT(screen, &crtc_region_local); 755428d7b3dSmrg 756428d7b3dSmrg *top = y1 >> 16; 757428d7b3dSmrg *left = (x1 >> 16) & ~1; 758428d7b3dSmrg *npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left; 759428d7b3dSmrg if (is_planar_fourcc(id)) { 760428d7b3dSmrg *top &= ~1; 761428d7b3dSmrg *nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top; 762428d7b3dSmrg } else 763428d7b3dSmrg *nlines = ((y2 + 0xffff) >> 16) - *top; 764428d7b3dSmrg 765428d7b3dSmrg return ret; 766428d7b3dSmrg} 767428d7b3dSmrg 768428d7b3dSmrgint 769428d7b3dSmrgintel_video_query_image_attributes(ScrnInfoPtr scrn, 770428d7b3dSmrg int id, 771428d7b3dSmrg unsigned short *w, unsigned short *h, 772428d7b3dSmrg int *pitches, int *offsets) 773428d7b3dSmrg{ 774428d7b3dSmrg intel_screen_private *intel = intel_get_screen_private(scrn); 775428d7b3dSmrg int size, tmp; 776428d7b3dSmrg 777428d7b3dSmrg#if 0 778428d7b3dSmrg ErrorF("intel_video_query_image_attributes: w is %d, h is %d\n", *w, *h); 779428d7b3dSmrg#endif 780428d7b3dSmrg 781428d7b3dSmrg if (IS_845G(intel) || IS_I830(intel)) { 782428d7b3dSmrg if (*w > IMAGE_MAX_WIDTH_LEGACY) 783428d7b3dSmrg *w = IMAGE_MAX_WIDTH_LEGACY; 784428d7b3dSmrg if (*h > IMAGE_MAX_HEIGHT_LEGACY) 785428d7b3dSmrg *h = IMAGE_MAX_HEIGHT_LEGACY; 786428d7b3dSmrg } else { 787428d7b3dSmrg if (*w > IMAGE_MAX_WIDTH) 788428d7b3dSmrg *w = IMAGE_MAX_WIDTH; 789428d7b3dSmrg if (*h > IMAGE_MAX_HEIGHT) 790428d7b3dSmrg *h = IMAGE_MAX_HEIGHT; 791428d7b3dSmrg } 792428d7b3dSmrg 793428d7b3dSmrg *w = (*w + 1) & ~1; 794428d7b3dSmrg if (offsets) 795428d7b3dSmrg offsets[0] = 0; 796428d7b3dSmrg 797428d7b3dSmrg switch (id) { 798428d7b3dSmrg /* IA44 is for XvMC only */ 799428d7b3dSmrg case FOURCC_IA44: 800428d7b3dSmrg case FOURCC_AI44: 801428d7b3dSmrg if (pitches) 802428d7b3dSmrg pitches[0] = *w; 803428d7b3dSmrg size = *w * *h; 804428d7b3dSmrg break; 805428d7b3dSmrg case FOURCC_YV12: 806428d7b3dSmrg case FOURCC_I420: 807428d7b3dSmrg *h = (*h + 1) & ~1; 808428d7b3dSmrg size = (*w + 3) & ~3; 809428d7b3dSmrg if (pitches) 810428d7b3dSmrg pitches[0] = size; 811428d7b3dSmrg size *= *h; 812428d7b3dSmrg if (offsets) 813428d7b3dSmrg offsets[1] = size; 814428d7b3dSmrg tmp = ((*w >> 1) + 3) & ~3; 815428d7b3dSmrg if (pitches) 816428d7b3dSmrg pitches[1] = pitches[2] = tmp; 817428d7b3dSmrg tmp *= (*h >> 1); 818428d7b3dSmrg size += tmp; 819428d7b3dSmrg if (offsets) 820428d7b3dSmrg offsets[2] = size; 821428d7b3dSmrg size += tmp; 822428d7b3dSmrg#if 0 823428d7b3dSmrg if (pitches) 824428d7b3dSmrg ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", 825428d7b3dSmrg pitches[0], pitches[1], pitches[2]); 826428d7b3dSmrg if (offsets) 827428d7b3dSmrg ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], 828428d7b3dSmrg offsets[2]); 829428d7b3dSmrg if (offsets) 830428d7b3dSmrg ErrorF("size is %d\n", size); 831428d7b3dSmrg#endif 832428d7b3dSmrg break; 833428d7b3dSmrg#ifdef INTEL_XVMC 834428d7b3dSmrg case FOURCC_XVMC: 835428d7b3dSmrg *h = (*h + 1) & ~1; 836428d7b3dSmrg size = sizeof(struct intel_xvmc_command); 837428d7b3dSmrg if (pitches) 838428d7b3dSmrg pitches[0] = size; 839428d7b3dSmrg break; 840428d7b3dSmrg#endif 841428d7b3dSmrg case FOURCC_UYVY: 842428d7b3dSmrg case FOURCC_YUY2: 843428d7b3dSmrg default: 844428d7b3dSmrg size = *w << 1; 845428d7b3dSmrg if (pitches) 846428d7b3dSmrg pitches[0] = size; 847428d7b3dSmrg size *= *h; 848428d7b3dSmrg break; 849428d7b3dSmrg } 850428d7b3dSmrg 851428d7b3dSmrg return size; 852428d7b3dSmrg} 853428d7b3dSmrg 854428d7b3dSmrgvoid intel_video_stop_video(ScrnInfoPtr scrn, pointer data, Bool shutdown) 855428d7b3dSmrg{ 856428d7b3dSmrg intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 857428d7b3dSmrg 858428d7b3dSmrg if (adaptor_priv->textured) 859428d7b3dSmrg return; 860428d7b3dSmrg 861428d7b3dSmrg REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip); 862428d7b3dSmrg 863428d7b3dSmrg if (shutdown) { 864428d7b3dSmrg if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) 865428d7b3dSmrg intel_video_overlay_off(intel_get_screen_private(scrn)); 866428d7b3dSmrg 867428d7b3dSmrg intel_free_video_buffers(adaptor_priv); 868428d7b3dSmrg adaptor_priv->videoStatus = 0; 869428d7b3dSmrg } else { 870428d7b3dSmrg if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) { 871428d7b3dSmrg adaptor_priv->videoStatus |= OFF_TIMER; 872428d7b3dSmrg adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY; 873428d7b3dSmrg } 874428d7b3dSmrg } 875428d7b3dSmrg 876428d7b3dSmrg} 877428d7b3dSmrg 878428d7b3dSmrgvoid 879428d7b3dSmrgintel_video_block_handler(intel_screen_private *intel) 880428d7b3dSmrg{ 881428d7b3dSmrg intel_adaptor_private *adaptor_priv; 882428d7b3dSmrg 883428d7b3dSmrg /* no overlay */ 884428d7b3dSmrg if (intel->adaptor == NULL) 885428d7b3dSmrg return; 886428d7b3dSmrg 887428d7b3dSmrg adaptor_priv = intel_get_adaptor_private(intel); 888428d7b3dSmrg if (adaptor_priv->videoStatus & OFF_TIMER) { 889428d7b3dSmrg Time now = currentTime.milliseconds; 890428d7b3dSmrg if (adaptor_priv->offTime < now) { 891428d7b3dSmrg /* Turn off the overlay */ 892428d7b3dSmrg intel_video_overlay_off(intel); 893428d7b3dSmrg intel_free_video_buffers(adaptor_priv); 894428d7b3dSmrg adaptor_priv->videoStatus = 0; 895428d7b3dSmrg } 896428d7b3dSmrg } 897428d7b3dSmrg} 898