103b705cfSriastradh/*************************************************************************** 203b705cfSriastradh 303b705cfSriastradh Copyright 2000 Intel Corporation. All Rights Reserved. 403b705cfSriastradh 503b705cfSriastradh Permission is hereby granted, free of charge, to any person obtaining a 603b705cfSriastradh copy of this software and associated documentation files (the 703b705cfSriastradh "Software"), to deal in the Software without restriction, including 803b705cfSriastradh without limitation the rights to use, copy, modify, merge, publish, 903b705cfSriastradh distribute, sub license, and/or sell copies of the Software, and to 1003b705cfSriastradh permit persons to whom the Software is furnished to do so, subject to 1103b705cfSriastradh the following conditions: 1203b705cfSriastradh 1303b705cfSriastradh The above copyright notice and this permission notice (including the 1403b705cfSriastradh next paragraph) shall be included in all copies or substantial portions 1503b705cfSriastradh of the Software. 1603b705cfSriastradh 1703b705cfSriastradh THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1803b705cfSriastradh OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1903b705cfSriastradh MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2003b705cfSriastradh IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2103b705cfSriastradh DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2203b705cfSriastradh OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 2303b705cfSriastradh THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2403b705cfSriastradh 2503b705cfSriastradh **************************************************************************/ 2603b705cfSriastradh 2703b705cfSriastradh/* 2803b705cfSriastradh * i830_video.c: i830/i845 Xv driver. 2903b705cfSriastradh * 3003b705cfSriastradh * Copyright © 2002 by Alan Hourihane and David Dawes 3103b705cfSriastradh * 3203b705cfSriastradh * Authors: 3303b705cfSriastradh * Alan Hourihane <alanh@tungstengraphics.com> 3403b705cfSriastradh * David Dawes <dawes@xfree86.org> 3503b705cfSriastradh * 3603b705cfSriastradh * Derived from i810 Xv driver: 3703b705cfSriastradh * 3803b705cfSriastradh * Authors of i810 code: 3903b705cfSriastradh * Jonathan Bian <jonathan.bian@intel.com> 4003b705cfSriastradh * Offscreen Images: 4103b705cfSriastradh * Matt Sottek <matthew.j.sottek@intel.com> 4203b705cfSriastradh */ 4303b705cfSriastradh 4403b705cfSriastradh#ifdef HAVE_CONFIG_H 4503b705cfSriastradh#include "config.h" 4603b705cfSriastradh#endif 4703b705cfSriastradh 4803b705cfSriastradh#include <inttypes.h> 4903b705cfSriastradh#include <math.h> 5003b705cfSriastradh#include <string.h> 5103b705cfSriastradh#include <errno.h> 5203b705cfSriastradh 5303b705cfSriastradh#include <sys/mman.h> 5403b705cfSriastradh 5503b705cfSriastradh#include "sna.h" 5603b705cfSriastradh#include "sna_reg.h" 5703b705cfSriastradh#include "sna_video.h" 5803b705cfSriastradh 5903b705cfSriastradh#include "intel_options.h" 6003b705cfSriastradh 6103b705cfSriastradh#include <xf86xv.h> 62fe8aea9eSmrg#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) 63fe8aea9eSmrg#include <sys/types.h> 64fe8aea9eSmrg#include <sys/endian.h> 65fe8aea9eSmrg#ifdef __OpenBSD__ 66fe8aea9eSmrg#define bswap_32 swap32 67fe8aea9eSmrg#else 68fe8aea9eSmrg#define bswap_32 bswap32 69fe8aea9eSmrg#endif 70fe8aea9eSmrg#else 71fe8aea9eSmrg#include <byteswap.h> 72fe8aea9eSmrg#endif 7303b705cfSriastradh 7403b705cfSriastradh#ifdef SNA_XVMC 7503b705cfSriastradh#define _SNA_XVMC_SERVER_ 7603b705cfSriastradh#include "sna_video_hwmc.h" 7703b705cfSriastradh#else 7803b705cfSriastradhstatic inline void sna_video_xvmc_setup(struct sna *sna, ScreenPtr ptr) 7903b705cfSriastradh{ 8042542f5fSchristos DBG(("%s: XvMC not compiled in\n", __FUNCTION__)); 8103b705cfSriastradh} 8203b705cfSriastradh#endif 8303b705cfSriastradh 8403b705cfSriastradhvoid sna_video_free_buffers(struct sna_video *video) 8503b705cfSriastradh{ 8603b705cfSriastradh unsigned int i; 8703b705cfSriastradh 8803b705cfSriastradh for (i = 0; i < ARRAY_SIZE(video->old_buf); i++) { 8903b705cfSriastradh if (video->old_buf[i]) { 9003b705cfSriastradh kgem_bo_destroy(&video->sna->kgem, video->old_buf[i]); 9103b705cfSriastradh video->old_buf[i] = NULL; 9203b705cfSriastradh } 9303b705cfSriastradh } 9403b705cfSriastradh 9503b705cfSriastradh if (video->buf) { 9603b705cfSriastradh kgem_bo_destroy(&video->sna->kgem, video->buf); 9703b705cfSriastradh video->buf = NULL; 9803b705cfSriastradh } 9903b705cfSriastradh} 10003b705cfSriastradh 10103b705cfSriastradhstruct kgem_bo * 10203b705cfSriastradhsna_video_buffer(struct sna_video *video, 10303b705cfSriastradh struct sna_video_frame *frame) 10403b705cfSriastradh{ 10503b705cfSriastradh /* Free the current buffer if we're going to have to reallocate */ 10603b705cfSriastradh if (video->buf && __kgem_bo_size(video->buf) < frame->size) 10703b705cfSriastradh sna_video_free_buffers(video); 10803b705cfSriastradh 10942542f5fSchristos if (video->buf && video->buf->scanout) { 11042542f5fSchristos if (frame->width != video->width || 11142542f5fSchristos frame->height != video->height || 11242542f5fSchristos frame->id != video->format) 11342542f5fSchristos sna_video_free_buffers(video); 11442542f5fSchristos } 11542542f5fSchristos 11603b705cfSriastradh if (video->buf == NULL) { 11703b705cfSriastradh if (video->tiled) { 11803b705cfSriastradh video->buf = kgem_create_2d(&video->sna->kgem, 11903b705cfSriastradh frame->width, frame->height, 32, 12003b705cfSriastradh I915_TILING_X, CREATE_EXACT); 12103b705cfSriastradh } else { 12203b705cfSriastradh video->buf = kgem_create_linear(&video->sna->kgem, frame->size, 12303b705cfSriastradh CREATE_GTT_MAP); 12403b705cfSriastradh } 12503b705cfSriastradh } 12603b705cfSriastradh 12742542f5fSchristos video->width = frame->width; 12842542f5fSchristos video->height = frame->height; 12942542f5fSchristos video->format = frame->id; 13042542f5fSchristos 13103b705cfSriastradh return video->buf; 13203b705cfSriastradh} 13303b705cfSriastradh 13403b705cfSriastradhvoid sna_video_buffer_fini(struct sna_video *video) 13503b705cfSriastradh{ 13603b705cfSriastradh struct kgem_bo *bo; 13703b705cfSriastradh 13803b705cfSriastradh bo = video->old_buf[1]; 13903b705cfSriastradh video->old_buf[1] = video->old_buf[0]; 14003b705cfSriastradh video->old_buf[0] = video->buf; 14103b705cfSriastradh video->buf = bo; 14203b705cfSriastradh} 14303b705cfSriastradh 14403b705cfSriastradhbool 14542542f5fSchristossna_video_clip_helper(struct sna_video *video, 14603b705cfSriastradh struct sna_video_frame *frame, 14742542f5fSchristos xf86CrtcPtr *crtc_ret, 14803b705cfSriastradh BoxPtr dst, 14903b705cfSriastradh short src_x, short src_y, 15003b705cfSriastradh short drw_x, short drw_y, 15103b705cfSriastradh short src_w, short src_h, 15203b705cfSriastradh short drw_w, short drw_h, 15303b705cfSriastradh RegionPtr reg) 15403b705cfSriastradh{ 15503b705cfSriastradh bool ret; 15603b705cfSriastradh RegionRec crtc_region_local; 15703b705cfSriastradh RegionPtr crtc_region = reg; 15803b705cfSriastradh INT32 x1, x2, y1, y2; 15903b705cfSriastradh xf86CrtcPtr crtc; 16003b705cfSriastradh 16103b705cfSriastradh x1 = src_x; 16203b705cfSriastradh x2 = src_x + src_w; 16303b705cfSriastradh y1 = src_y; 16403b705cfSriastradh y2 = src_y + src_h; 16503b705cfSriastradh 16603b705cfSriastradh dst->x1 = drw_x; 16703b705cfSriastradh dst->x2 = drw_x + drw_w; 16803b705cfSriastradh dst->y1 = drw_y; 16903b705cfSriastradh dst->y2 = drw_y + drw_h; 17003b705cfSriastradh 17103b705cfSriastradh /* 17203b705cfSriastradh * For overlay video, compute the relevant CRTC and 17303b705cfSriastradh * clip video to that 17403b705cfSriastradh */ 17542542f5fSchristos crtc = sna_covering_crtc(video->sna, dst, video->desired_crtc); 17603b705cfSriastradh 17703b705cfSriastradh /* For textured video, we don't actually want to clip at all. */ 17803b705cfSriastradh if (crtc && !video->textured) { 17903b705cfSriastradh crtc_region_local.extents = crtc->bounds; 18003b705cfSriastradh crtc_region_local.data = NULL; 18103b705cfSriastradh crtc_region = &crtc_region_local; 18203b705cfSriastradh RegionIntersect(crtc_region, crtc_region, reg); 18303b705cfSriastradh } 18403b705cfSriastradh *crtc_ret = crtc; 18503b705cfSriastradh 18603b705cfSriastradh ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2, 18703b705cfSriastradh crtc_region, frame->width, frame->height); 18803b705cfSriastradh if (crtc_region != reg) 18903b705cfSriastradh RegionUninit(crtc_region); 19003b705cfSriastradh 19103b705cfSriastradh frame->src.x1 = x1 >> 16; 19203b705cfSriastradh frame->src.y1 = y1 >> 16; 19303b705cfSriastradh frame->src.x2 = (x2 + 0xffff) >> 16; 19403b705cfSriastradh frame->src.y2 = (y2 + 0xffff) >> 16; 19503b705cfSriastradh 19603b705cfSriastradh frame->image.x1 = frame->src.x1 & ~1; 19703b705cfSriastradh frame->image.x2 = ALIGN(frame->src.x2, 2); 19803b705cfSriastradh if (is_planar_fourcc(frame->id)) { 19903b705cfSriastradh frame->image.y1 = frame->src.y1 & ~1; 20003b705cfSriastradh frame->image.y2 = ALIGN(frame->src.y2, 2); 20103b705cfSriastradh } else { 20203b705cfSriastradh frame->image.y1 = frame->src.y1; 20303b705cfSriastradh frame->image.y2 = frame->src.y2; 20403b705cfSriastradh } 20503b705cfSriastradh 20603b705cfSriastradh return ret; 20703b705cfSriastradh} 20803b705cfSriastradh 20903b705cfSriastradhvoid 21003b705cfSriastradhsna_video_frame_init(struct sna_video *video, 21103b705cfSriastradh int id, short width, short height, 21203b705cfSriastradh struct sna_video_frame *frame) 21303b705cfSriastradh{ 21403b705cfSriastradh DBG(("%s: id=%d [planar? %d], width=%d, height=%d, align=%d\n", 21503b705cfSriastradh __FUNCTION__, id, is_planar_fourcc(id), width, height, video->alignment)); 21603b705cfSriastradh assert(width && height); 21703b705cfSriastradh 21803b705cfSriastradh frame->bo = NULL; 21903b705cfSriastradh frame->id = id; 22003b705cfSriastradh frame->width = width; 22103b705cfSriastradh frame->height = height; 22242542f5fSchristos frame->rotation = 0; 22342542f5fSchristos} 22442542f5fSchristos 22542542f5fSchristosvoid 22642542f5fSchristossna_video_frame_set_rotation(struct sna_video *video, 22742542f5fSchristos struct sna_video_frame *frame, 22842542f5fSchristos Rotation rotation) 22942542f5fSchristos{ 23042542f5fSchristos unsigned width = frame->width; 23142542f5fSchristos unsigned height = frame->height; 23242542f5fSchristos unsigned align; 23342542f5fSchristos 23442542f5fSchristos DBG(("%s: rotation=%d\n", __FUNCTION__, rotation)); 23542542f5fSchristos frame->rotation = rotation; 23603b705cfSriastradh 23703b705cfSriastradh align = video->alignment; 23803b705cfSriastradh#if SNA_XVMC 23903b705cfSriastradh /* for i915 xvmc, hw requires 1kb aligned surfaces */ 24042542f5fSchristos if (frame->id == FOURCC_XVMC && video->sna->kgem.gen < 040 && align < 1024) 24103b705cfSriastradh align = 1024; 24203b705cfSriastradh#endif 24303b705cfSriastradh 24403b705cfSriastradh /* Determine the desired destination pitch (representing the 24503b705cfSriastradh * chroma's pitch in the planar case). 24603b705cfSriastradh */ 247fe8aea9eSmrg if (is_nv12_fourcc(frame->id)) { 248fe8aea9eSmrg assert((width & 1) == 0); 249fe8aea9eSmrg assert((height & 1) == 0); 250fe8aea9eSmrg if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 251fe8aea9eSmrg frame->pitch[0] = ALIGN(height, align); 252fe8aea9eSmrg frame->pitch[1] = ALIGN(height, align); 253fe8aea9eSmrg frame->size = width * frame->pitch[1] + 254fe8aea9eSmrg width / 2 * frame->pitch[0]; 255fe8aea9eSmrg } else { 256fe8aea9eSmrg frame->pitch[0] = ALIGN(width, align); 257fe8aea9eSmrg frame->pitch[1] = ALIGN(width, align); 258fe8aea9eSmrg frame->size = height * frame->pitch[1] + 259fe8aea9eSmrg height / 2 * frame->pitch[0]; 260fe8aea9eSmrg } 261fe8aea9eSmrg 262fe8aea9eSmrg if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 263fe8aea9eSmrg frame->UBufOffset = (int)frame->pitch[1] * width; 264fe8aea9eSmrg frame->VBufOffset = frame->UBufOffset; 265fe8aea9eSmrg } else { 266fe8aea9eSmrg frame->UBufOffset = (int)frame->pitch[1] * height; 267fe8aea9eSmrg frame->VBufOffset = frame->UBufOffset; 268fe8aea9eSmrg } 269fe8aea9eSmrg } else if (is_planar_fourcc(frame->id)) { 27003b705cfSriastradh assert((width & 1) == 0); 27103b705cfSriastradh assert((height & 1) == 0); 27242542f5fSchristos if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 27303b705cfSriastradh frame->pitch[0] = ALIGN((height / 2), align); 27403b705cfSriastradh frame->pitch[1] = ALIGN(height, align); 27503b705cfSriastradh frame->size = width; 27603b705cfSriastradh } else { 27703b705cfSriastradh frame->pitch[0] = ALIGN((width / 2), align); 27803b705cfSriastradh frame->pitch[1] = ALIGN(width, align); 27903b705cfSriastradh frame->size = height; 28003b705cfSriastradh } 28103b705cfSriastradh frame->size *= frame->pitch[0] + frame->pitch[1]; 28203b705cfSriastradh 28342542f5fSchristos if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 28403b705cfSriastradh frame->UBufOffset = (int)frame->pitch[1] * width; 28503b705cfSriastradh frame->VBufOffset = 28603b705cfSriastradh frame->UBufOffset + (int)frame->pitch[0] * width / 2; 28703b705cfSriastradh } else { 28803b705cfSriastradh frame->UBufOffset = (int)frame->pitch[1] * height; 28903b705cfSriastradh frame->VBufOffset = 29003b705cfSriastradh frame->UBufOffset + (int)frame->pitch[0] * height / 2; 29103b705cfSriastradh } 29203b705cfSriastradh } else { 29303b705cfSriastradh switch (frame->id) { 29403b705cfSriastradh case FOURCC_RGB888: 295fe8aea9eSmrg case FOURCC_AYUV: 29642542f5fSchristos if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 29703b705cfSriastradh frame->pitch[0] = ALIGN((height << 2), align); 29803b705cfSriastradh frame->size = (int)frame->pitch[0] * width; 29903b705cfSriastradh } else { 30003b705cfSriastradh frame->pitch[0] = ALIGN((width << 2), align); 30103b705cfSriastradh frame->size = (int)frame->pitch[0] * height; 30203b705cfSriastradh } 30303b705cfSriastradh frame->UBufOffset = frame->VBufOffset = 0; 30403b705cfSriastradh break; 30503b705cfSriastradh case FOURCC_RGB565: 30642542f5fSchristos if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 30703b705cfSriastradh frame->pitch[0] = ALIGN((height << 1), align); 30803b705cfSriastradh frame->size = (int)frame->pitch[0] * width; 30903b705cfSriastradh } else { 31003b705cfSriastradh frame->pitch[0] = ALIGN((width << 1), align); 31103b705cfSriastradh frame->size = (int)frame->pitch[0] * height; 31203b705cfSriastradh } 31303b705cfSriastradh frame->UBufOffset = frame->VBufOffset = 0; 31403b705cfSriastradh break; 31503b705cfSriastradh 31603b705cfSriastradh default: 31742542f5fSchristos if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 31803b705cfSriastradh frame->pitch[0] = ALIGN((height << 1), align); 31903b705cfSriastradh frame->size = (int)frame->pitch[0] * width; 32003b705cfSriastradh } else { 32103b705cfSriastradh frame->pitch[0] = ALIGN((width << 1), align); 32203b705cfSriastradh frame->size = (int)frame->pitch[0] * height; 32303b705cfSriastradh } 32403b705cfSriastradh break; 32503b705cfSriastradh } 32603b705cfSriastradh frame->pitch[1] = 0; 32703b705cfSriastradh frame->UBufOffset = 0; 32803b705cfSriastradh frame->VBufOffset = 0; 32903b705cfSriastradh } 33003b705cfSriastradh 33103b705cfSriastradh assert(frame->size); 33203b705cfSriastradh} 33303b705cfSriastradh 334fe8aea9eSmrgstatic void plane_dims(const struct sna_video_frame *frame, int sub, 335fe8aea9eSmrg int *x, int *y, int *w, int *h) 336fe8aea9eSmrg{ 337fe8aea9eSmrg *x = frame->image.x1; 338fe8aea9eSmrg *y = frame->image.y1; 339fe8aea9eSmrg *w = frame->image.x2 - frame->image.x1; 340fe8aea9eSmrg *h = frame->image.y2 - frame->image.y1; 341fe8aea9eSmrg 342fe8aea9eSmrg if (sub) { 343fe8aea9eSmrg *x >>= 1; *w >>= 1; 344fe8aea9eSmrg *y >>= 1; *h >>= 1; 345fe8aea9eSmrg } 346fe8aea9eSmrg} 347fe8aea9eSmrg 348fe8aea9eSmrgstatic void sna_memcpy_cbcr_plane(struct sna_video *video, 349fe8aea9eSmrg uint16_t *dst, const uint16_t *src, 350fe8aea9eSmrg const struct sna_video_frame *frame) 351fe8aea9eSmrg{ 352fe8aea9eSmrg int dstPitch = frame->pitch[0] >> 1, srcPitch; 353fe8aea9eSmrg const uint16_t *s; 354fe8aea9eSmrg int i, j = 0; 355fe8aea9eSmrg int x, y, w, h; 356fe8aea9eSmrg 357fe8aea9eSmrg plane_dims(frame, 1, &x, &y, &w, &h); 358fe8aea9eSmrg 359fe8aea9eSmrg srcPitch = ALIGN((frame->width >> 1), 2); 360fe8aea9eSmrg 361fe8aea9eSmrg src += y * srcPitch + x; 362fe8aea9eSmrg if (!video->textured) 363fe8aea9eSmrg x = y = 0; 364fe8aea9eSmrg 365fe8aea9eSmrg switch (frame->rotation) { 366fe8aea9eSmrg case RR_Rotate_0: 367fe8aea9eSmrg dst += y * dstPitch + x; 368fe8aea9eSmrg if (srcPitch == dstPitch && srcPitch == w) 369fe8aea9eSmrg memcpy(dst, src, (srcPitch * h) << 1); 370fe8aea9eSmrg else while (h--) { 371fe8aea9eSmrg memcpy(dst, src, w << 1); 372fe8aea9eSmrg src += srcPitch; 373fe8aea9eSmrg dst += dstPitch; 374fe8aea9eSmrg } 375fe8aea9eSmrg break; 376fe8aea9eSmrg case RR_Rotate_90: 377fe8aea9eSmrg for (i = 0; i < h; i++) { 378fe8aea9eSmrg s = src; 379fe8aea9eSmrg for (j = 0; j < w; j++) 380fe8aea9eSmrg dst[i + ((x + w - j - 1) * dstPitch)] = *s++; 381fe8aea9eSmrg src += srcPitch; 382fe8aea9eSmrg } 383fe8aea9eSmrg break; 384fe8aea9eSmrg case RR_Rotate_180: 385fe8aea9eSmrg for (i = 0; i < h; i++) { 386fe8aea9eSmrg s = src; 387fe8aea9eSmrg for (j = 0; j < w; j++) { 388fe8aea9eSmrg dst[(x + w - j - 1) + 389fe8aea9eSmrg ((h - i - 1) * dstPitch)] = *s++; 390fe8aea9eSmrg } 391fe8aea9eSmrg src += srcPitch; 392fe8aea9eSmrg } 393fe8aea9eSmrg break; 394fe8aea9eSmrg case RR_Rotate_270: 395fe8aea9eSmrg for (i = 0; i < h; i++) { 396fe8aea9eSmrg s = src; 397fe8aea9eSmrg for (j = 0; j < w; j++) { 398fe8aea9eSmrg dst[(h - i - 1) + (x + j * dstPitch)] = *s++; 399fe8aea9eSmrg } 400fe8aea9eSmrg src += srcPitch; 401fe8aea9eSmrg } 402fe8aea9eSmrg break; 403fe8aea9eSmrg } 404fe8aea9eSmrg} 405fe8aea9eSmrg 40603b705cfSriastradhstatic void sna_memcpy_plane(struct sna_video *video, 40703b705cfSriastradh uint8_t *dst, const uint8_t *src, 40803b705cfSriastradh const struct sna_video_frame *frame, int sub) 40903b705cfSriastradh{ 41003b705cfSriastradh int dstPitch = frame->pitch[!sub], srcPitch; 41103b705cfSriastradh const uint8_t *s; 41203b705cfSriastradh int i, j = 0; 41303b705cfSriastradh int x, y, w, h; 41403b705cfSriastradh 415fe8aea9eSmrg plane_dims(frame, sub, &x, &y, &w, &h); 416fe8aea9eSmrg 417fe8aea9eSmrg if (sub) 41803b705cfSriastradh srcPitch = ALIGN((frame->width >> 1), 4); 419fe8aea9eSmrg else 42003b705cfSriastradh srcPitch = ALIGN(frame->width, 4); 42103b705cfSriastradh 42203b705cfSriastradh src += y * srcPitch + x; 42303b705cfSriastradh if (!video->textured) 42403b705cfSriastradh x = y = 0; 42503b705cfSriastradh 42642542f5fSchristos switch (frame->rotation) { 42703b705cfSriastradh case RR_Rotate_0: 42803b705cfSriastradh dst += y * dstPitch + x; 42903b705cfSriastradh if (srcPitch == dstPitch && srcPitch == w) 43003b705cfSriastradh memcpy(dst, src, srcPitch * h); 43103b705cfSriastradh else while (h--) { 43203b705cfSriastradh memcpy(dst, src, w); 43303b705cfSriastradh src += srcPitch; 43403b705cfSriastradh dst += dstPitch; 43503b705cfSriastradh } 43603b705cfSriastradh break; 43703b705cfSriastradh case RR_Rotate_90: 43803b705cfSriastradh for (i = 0; i < h; i++) { 43903b705cfSriastradh s = src; 44003b705cfSriastradh for (j = 0; j < w; j++) 44103b705cfSriastradh dst[i + ((x + w - j - 1) * dstPitch)] = *s++; 44203b705cfSriastradh src += srcPitch; 44303b705cfSriastradh } 44403b705cfSriastradh break; 44503b705cfSriastradh case RR_Rotate_180: 44603b705cfSriastradh for (i = 0; i < h; i++) { 44703b705cfSriastradh s = src; 44803b705cfSriastradh for (j = 0; j < w; j++) { 44903b705cfSriastradh dst[(x + w - j - 1) + 45003b705cfSriastradh ((h - i - 1) * dstPitch)] = *s++; 45103b705cfSriastradh } 45203b705cfSriastradh src += srcPitch; 45303b705cfSriastradh } 45403b705cfSriastradh break; 45503b705cfSriastradh case RR_Rotate_270: 45603b705cfSriastradh for (i = 0; i < h; i++) { 45703b705cfSriastradh s = src; 45803b705cfSriastradh for (j = 0; j < w; j++) { 45903b705cfSriastradh dst[(h - i - 1) + (x + j * dstPitch)] = *s++; 46003b705cfSriastradh } 46103b705cfSriastradh src += srcPitch; 46203b705cfSriastradh } 46303b705cfSriastradh break; 46403b705cfSriastradh } 46503b705cfSriastradh} 46603b705cfSriastradh 467fe8aea9eSmrgstatic void 468fe8aea9eSmrgsna_copy_nv12_data(struct sna_video *video, 469fe8aea9eSmrg const struct sna_video_frame *frame, 470fe8aea9eSmrg const uint8_t *src, uint8_t *dst) 471fe8aea9eSmrg{ 472fe8aea9eSmrg sna_memcpy_plane(video, dst, src, frame, 0); 473fe8aea9eSmrg src += frame->height * ALIGN(frame->width, 4); 474fe8aea9eSmrg dst += frame->UBufOffset; 475fe8aea9eSmrg sna_memcpy_cbcr_plane(video, (void*)dst, (void*)src, frame); 476fe8aea9eSmrg} 477fe8aea9eSmrg 47803b705cfSriastradhstatic void 47903b705cfSriastradhsna_copy_planar_data(struct sna_video *video, 48003b705cfSriastradh const struct sna_video_frame *frame, 48103b705cfSriastradh const uint8_t *src, uint8_t *dst) 48203b705cfSriastradh{ 48303b705cfSriastradh uint8_t *d; 48403b705cfSriastradh 48503b705cfSriastradh sna_memcpy_plane(video, dst, src, frame, 0); 48603b705cfSriastradh src += frame->height * ALIGN(frame->width, 4); 48703b705cfSriastradh 48803b705cfSriastradh if (frame->id == FOURCC_I420) 48903b705cfSriastradh d = dst + frame->UBufOffset; 49003b705cfSriastradh else 49103b705cfSriastradh d = dst + frame->VBufOffset; 49203b705cfSriastradh sna_memcpy_plane(video, d, src, frame, 1); 49303b705cfSriastradh src += (frame->height >> 1) * ALIGN(frame->width >> 1, 4); 49403b705cfSriastradh 49503b705cfSriastradh if (frame->id == FOURCC_I420) 49603b705cfSriastradh d = dst + frame->VBufOffset; 49703b705cfSriastradh else 49803b705cfSriastradh d = dst + frame->UBufOffset; 49903b705cfSriastradh sna_memcpy_plane(video, d, src, frame, 1); 50003b705cfSriastradh} 50103b705cfSriastradh 50203b705cfSriastradhstatic void 50303b705cfSriastradhsna_copy_packed_data(struct sna_video *video, 50403b705cfSriastradh const struct sna_video_frame *frame, 50503b705cfSriastradh const uint8_t *buf, 50603b705cfSriastradh uint8_t *dst) 50703b705cfSriastradh{ 50803b705cfSriastradh int pitch = frame->width << 1; 50903b705cfSriastradh const uint8_t *src, *s; 51003b705cfSriastradh int x, y, w, h; 51103b705cfSriastradh int i, j; 51203b705cfSriastradh 51303b705cfSriastradh if (video->textured) { 51403b705cfSriastradh /* XXX support copying cropped extents */ 51503b705cfSriastradh x = y = 0; 51603b705cfSriastradh w = frame->width; 51703b705cfSriastradh h = frame->height; 51803b705cfSriastradh } else { 51903b705cfSriastradh x = frame->image.x1; 52003b705cfSriastradh y = frame->image.y1; 52103b705cfSriastradh w = frame->image.x2 - frame->image.x1; 52203b705cfSriastradh h = frame->image.y2 - frame->image.y1; 52303b705cfSriastradh } 52403b705cfSriastradh 52503b705cfSriastradh src = buf + (y * pitch) + (x << 1); 52603b705cfSriastradh 52742542f5fSchristos switch (frame->rotation) { 52803b705cfSriastradh case RR_Rotate_0: 52903b705cfSriastradh w <<= 1; 53003b705cfSriastradh for (i = 0; i < h; i++) { 53103b705cfSriastradh memcpy(dst, src, w); 53203b705cfSriastradh src += pitch; 53303b705cfSriastradh dst += frame->pitch[0]; 53403b705cfSriastradh } 53503b705cfSriastradh break; 53603b705cfSriastradh case RR_Rotate_90: 53703b705cfSriastradh h <<= 1; 53803b705cfSriastradh for (i = 0; i < h; i += 2) { 53903b705cfSriastradh s = src; 54003b705cfSriastradh for (j = 0; j < w; j++) { 54103b705cfSriastradh /* Copy Y */ 54203b705cfSriastradh dst[(i + 0) + ((w - j - 1) * frame->pitch[0])] = *s; 54303b705cfSriastradh s += 2; 54403b705cfSriastradh } 54503b705cfSriastradh src += pitch; 54603b705cfSriastradh } 54703b705cfSriastradh h >>= 1; 54803b705cfSriastradh src = buf + (y * pitch) + (x << 1); 54903b705cfSriastradh for (i = 0; i < h; i += 2) { 55003b705cfSriastradh for (j = 0; j < w; j += 2) { 55103b705cfSriastradh /* Copy U */ 55203b705cfSriastradh dst[((i * 2) + 1) + ((w - j - 1) * frame->pitch[0])] = src[(j * 2) + 1 + (i * pitch)]; 55303b705cfSriastradh dst[((i * 2) + 1) + ((w - j - 2) * frame->pitch[0])] = src[(j * 2) + 1 + ((i + 1) * pitch)]; 55403b705cfSriastradh /* Copy V */ dst[((i * 2) + 3) + ((w - j - 1) * frame->pitch[0])] = src[(j * 2) + 3 + (i * pitch)]; 55503b705cfSriastradh dst[((i * 2) + 3) + ((w - j - 2) * frame->pitch[0])] = src[(j * 2) + 3 + ((i + 1) * pitch)]; 55603b705cfSriastradh } 55703b705cfSriastradh } 55803b705cfSriastradh break; 55903b705cfSriastradh case RR_Rotate_180: 56003b705cfSriastradh w <<= 1; 56103b705cfSriastradh for (i = 0; i < h; i++) { 56203b705cfSriastradh s = src; 56303b705cfSriastradh for (j = 0; j < w; j += 4) { 56403b705cfSriastradh dst[(w - j - 4) + ((h - i - 1) * frame->pitch[0])] = *s++; 56503b705cfSriastradh dst[(w - j - 3) + ((h - i - 1) * frame->pitch[0])] = *s++; 56603b705cfSriastradh dst[(w - j - 2) + ((h - i - 1) * frame->pitch[0])] = *s++; 56703b705cfSriastradh dst[(w - j - 1) + ((h - i - 1) * frame->pitch[0])] = *s++; 56803b705cfSriastradh } 56903b705cfSriastradh src += pitch; 57003b705cfSriastradh } 57103b705cfSriastradh break; 57203b705cfSriastradh case RR_Rotate_270: 57303b705cfSriastradh h <<= 1; 57403b705cfSriastradh for (i = 0; i < h; i += 2) { 57503b705cfSriastradh s = src; 57603b705cfSriastradh for (j = 0; j < w; j++) { 57703b705cfSriastradh /* Copy Y */ 57803b705cfSriastradh dst[(h - i - 2) + (j * frame->pitch[0])] = *s; 57903b705cfSriastradh s += 2; 58003b705cfSriastradh } 58103b705cfSriastradh src += pitch; 58203b705cfSriastradh } 58303b705cfSriastradh h >>= 1; 58403b705cfSriastradh src = buf + (y * pitch) + (x << 1); 58503b705cfSriastradh for (i = 0; i < h; i += 2) { 58603b705cfSriastradh for (j = 0; j < w; j += 2) { 58703b705cfSriastradh /* Copy U */ 58803b705cfSriastradh dst[(((h - i) * 2) - 3) + (j * frame->pitch[0])] = src[(j * 2) + 1 + (i * pitch)]; 58903b705cfSriastradh dst[(((h - i) * 2) - 3) + ((j + 1) * frame->pitch[0])] = src[(j * 2) + 1 + ((i + 1) * pitch)]; 59003b705cfSriastradh /* Copy V */ 59103b705cfSriastradh dst[(((h - i) * 2) - 1) + (j * frame->pitch[0])] = src[(j * 2) + 3 + (i * pitch)]; 59203b705cfSriastradh dst[(((h - i) * 2) - 1) + ((j + 1) * frame->pitch[0])] = src[(j * 2) + 3 + ((i + 1) * pitch)]; 59303b705cfSriastradh } 59403b705cfSriastradh } 59503b705cfSriastradh break; 59603b705cfSriastradh } 59703b705cfSriastradh} 59803b705cfSriastradh 599fe8aea9eSmrgstatic void 600fe8aea9eSmrgsna_copy_ayuv_data(struct sna_video *video, 601fe8aea9eSmrg const struct sna_video_frame *frame, 602fe8aea9eSmrg const uint8_t *buf, 603fe8aea9eSmrg uint8_t *dst) 604fe8aea9eSmrg{ 605fe8aea9eSmrg int pitch = frame->width << 2; 606fe8aea9eSmrg const uint32_t *src_dw; 607fe8aea9eSmrg const uint8_t *src; 608fe8aea9eSmrg uint32_t *dst_dw = (uint32_t *)dst; 609fe8aea9eSmrg int x, y, w, h; 610fe8aea9eSmrg int i, j; 611fe8aea9eSmrg 612fe8aea9eSmrg if (video->textured) { 613fe8aea9eSmrg /* XXX support copying cropped extents */ 614fe8aea9eSmrg x = y = 0; 615fe8aea9eSmrg w = frame->width; 616fe8aea9eSmrg h = frame->height; 617fe8aea9eSmrg } else { 618fe8aea9eSmrg x = frame->image.x1; 619fe8aea9eSmrg y = frame->image.y1; 620fe8aea9eSmrg w = frame->image.x2 - frame->image.x1; 621fe8aea9eSmrg h = frame->image.y2 - frame->image.y1; 622fe8aea9eSmrg } 623fe8aea9eSmrg 624fe8aea9eSmrg src = buf + (y * pitch) + (x << 2); 625fe8aea9eSmrg src_dw = (uint32_t *)src; 626fe8aea9eSmrg 627fe8aea9eSmrg switch (frame->rotation) { 628fe8aea9eSmrg case RR_Rotate_0: 629fe8aea9eSmrg for (i = 0; i < h; i++) { 630fe8aea9eSmrg for (j = 0; j < w; j++) { 631fe8aea9eSmrg /* 632fe8aea9eSmrg * Have to reverse bytes order, because the only 633fe8aea9eSmrg * player which supports AYUV format currently is 634fe8aea9eSmrg * Gstreamer and it supports in bad way, even though 635fe8aea9eSmrg * spec says MSB:AYUV, we get the bytes opposite way. 636fe8aea9eSmrg */ 637fe8aea9eSmrg dst_dw[i * w + j] = bswap_32(src_dw[i * w + j]); 638fe8aea9eSmrg } 639fe8aea9eSmrg } 640fe8aea9eSmrg break; 641fe8aea9eSmrg case RR_Rotate_90: 642fe8aea9eSmrg for (i = 0; i < h; i++) { 643fe8aea9eSmrg for (j = 0; j < w; j++) { 644fe8aea9eSmrg dst_dw[(w - j - 1) * h + i] = bswap_32(src_dw[i * w + j]); 645fe8aea9eSmrg } 646fe8aea9eSmrg } 647fe8aea9eSmrg break; 648fe8aea9eSmrg case RR_Rotate_180: 649fe8aea9eSmrg for (i = 0; i < h; i++) { 650fe8aea9eSmrg for (j = 0; j < w; j++) { 651fe8aea9eSmrg dst_dw[(h - i - 1) * w + w - j - 1] = bswap_32(src_dw[i * w + j]); 652fe8aea9eSmrg } 653fe8aea9eSmrg } 654fe8aea9eSmrg break; 655fe8aea9eSmrg case RR_Rotate_270: 656fe8aea9eSmrg for (i = 0; i < h; i++) { 657fe8aea9eSmrg for (j = 0; j < w; j++) { 658fe8aea9eSmrg dst_dw[(w - j - 1) * h + i] = bswap_32(src_dw[i * w + j]); 659fe8aea9eSmrg } 660fe8aea9eSmrg } 661fe8aea9eSmrg break; 662fe8aea9eSmrg } 663fe8aea9eSmrg} 664fe8aea9eSmrg 66503b705cfSriastradhbool 66603b705cfSriastradhsna_video_copy_data(struct sna_video *video, 66703b705cfSriastradh struct sna_video_frame *frame, 66803b705cfSriastradh const uint8_t *buf) 66903b705cfSriastradh{ 67003b705cfSriastradh uint8_t *dst; 67103b705cfSriastradh 67203b705cfSriastradh DBG(("%s: handle=%d, size=%dx%d [%d], pitch=[%d,%d] rotation=%d, is-texture=%d\n", 67303b705cfSriastradh __FUNCTION__, frame->bo ? frame->bo->handle : 0, 67403b705cfSriastradh frame->width, frame->height, frame->size, frame->pitch[0], frame->pitch[1], 67542542f5fSchristos frame->rotation, video->textured)); 67603b705cfSriastradh DBG(("%s: image=(%d, %d), (%d, %d), source=(%d, %d), (%d, %d)\n", 67703b705cfSriastradh __FUNCTION__, 67803b705cfSriastradh frame->image.x1, frame->image.y1, frame->image.x2, frame->image.y2, 67903b705cfSriastradh frame->src.x1, frame->src.y1, frame->src.x2, frame->src.y2)); 68003b705cfSriastradh assert(frame->width && frame->height); 68142542f5fSchristos assert(frame->rotation); 68203b705cfSriastradh assert(frame->size); 68303b705cfSriastradh 68403b705cfSriastradh /* In the common case, we can simply the upload in a single pwrite */ 685fe8aea9eSmrg if (frame->rotation == RR_Rotate_0 && !video->tiled && !is_ayuv_fourcc(frame->id)) { 68603b705cfSriastradh DBG(("%s: unrotated, untiled fast paths: is-planar?=%d\n", 68703b705cfSriastradh __FUNCTION__, is_planar_fourcc(frame->id))); 688fe8aea9eSmrg if (is_nv12_fourcc(frame->id)) { 689fe8aea9eSmrg int w = frame->image.x2 - frame->image.x1; 690fe8aea9eSmrg int h = frame->image.y2 - frame->image.y1; 691fe8aea9eSmrg if (ALIGN(h, 2) == frame->height && 692fe8aea9eSmrg ALIGN(w, 4) == frame->pitch[0] && 693fe8aea9eSmrg ALIGN(w, 4) == frame->pitch[1]) { 694fe8aea9eSmrg if (frame->bo) { 695fe8aea9eSmrg if (!kgem_bo_write(&video->sna->kgem, frame->bo, 696fe8aea9eSmrg buf, frame->size)) 697fe8aea9eSmrg goto use_gtt; 698fe8aea9eSmrg } else { 699fe8aea9eSmrg frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 700fe8aea9eSmrg KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 701fe8aea9eSmrg (void **)&dst); 702fe8aea9eSmrg if (frame->bo == NULL) 703fe8aea9eSmrg return false; 704fe8aea9eSmrg 705fe8aea9eSmrg memcpy(dst, buf, frame->size); 706fe8aea9eSmrg } 707fe8aea9eSmrg return true; 708fe8aea9eSmrg } 709fe8aea9eSmrg } else if (is_planar_fourcc(frame->id)) { 71003b705cfSriastradh int w = frame->image.x2 - frame->image.x1; 71103b705cfSriastradh int h = frame->image.y2 - frame->image.y1; 71203b705cfSriastradh if (ALIGN(h, 2) == frame->height && 71303b705cfSriastradh ALIGN(w >> 1, 4) == frame->pitch[0] && 71403b705cfSriastradh ALIGN(w, 4) == frame->pitch[1]) { 71503b705cfSriastradh if (frame->bo) { 71642542f5fSchristos if (!kgem_bo_write(&video->sna->kgem, frame->bo, 71742542f5fSchristos buf, frame->size)) 71842542f5fSchristos goto use_gtt; 71903b705cfSriastradh } else { 72003b705cfSriastradh frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 72103b705cfSriastradh KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 72203b705cfSriastradh (void **)&dst); 72303b705cfSriastradh if (frame->bo == NULL) 72403b705cfSriastradh return false; 72503b705cfSriastradh 72603b705cfSriastradh memcpy(dst, buf, frame->size); 72703b705cfSriastradh } 72803b705cfSriastradh if (frame->id != FOURCC_I420) { 72903b705cfSriastradh uint32_t tmp; 73003b705cfSriastradh tmp = frame->VBufOffset; 73103b705cfSriastradh frame->VBufOffset = frame->UBufOffset; 73203b705cfSriastradh frame->UBufOffset = tmp; 73303b705cfSriastradh } 73403b705cfSriastradh return true; 73503b705cfSriastradh } 73603b705cfSriastradh } else { 73742542f5fSchristos int x, y, w, h; 73842542f5fSchristos 73942542f5fSchristos if (video->textured) { 74042542f5fSchristos /* XXX support copying cropped extents */ 74142542f5fSchristos x = y = 0; 74242542f5fSchristos w = frame->width; 74342542f5fSchristos h = frame->height; 74442542f5fSchristos } else { 74542542f5fSchristos x = frame->image.x1; 74642542f5fSchristos y = frame->image.y1; 74742542f5fSchristos w = frame->image.x2 - frame->image.x1; 74842542f5fSchristos h = frame->image.y2 - frame->image.y1; 74942542f5fSchristos } 75042542f5fSchristos 75142542f5fSchristos if (w*2 == frame->pitch[0]) { 75242542f5fSchristos buf += (2U*y * frame->width) + (x << 1); 75303b705cfSriastradh if (frame->bo) { 75442542f5fSchristos if (!kgem_bo_write(&video->sna->kgem, frame->bo, 75542542f5fSchristos buf, 2U*h*frame->width)) 75642542f5fSchristos goto use_gtt; 75703b705cfSriastradh } else { 75803b705cfSriastradh frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 75903b705cfSriastradh KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 76003b705cfSriastradh (void **)&dst); 76103b705cfSriastradh if (frame->bo == NULL) 76203b705cfSriastradh return false; 76303b705cfSriastradh 76442542f5fSchristos memcpy(dst, buf, 2U*h*frame->width); 76503b705cfSriastradh } 76603b705cfSriastradh return true; 76703b705cfSriastradh } 76803b705cfSriastradh } 76903b705cfSriastradh 77003b705cfSriastradh DBG(("%s: source cropped, fallback\n", __FUNCTION__)); 77103b705cfSriastradh } 77203b705cfSriastradh 77342542f5fSchristosuse_gtt: /* copy data, must use GTT so that we keep the overlay uncached */ 77403b705cfSriastradh if (frame->bo) { 77503b705cfSriastradh dst = kgem_bo_map__gtt(&video->sna->kgem, frame->bo); 77603b705cfSriastradh if (dst == NULL) 77703b705cfSriastradh return false; 77803b705cfSriastradh } else { 77903b705cfSriastradh frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 78003b705cfSriastradh KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 78103b705cfSriastradh (void **)&dst); 78203b705cfSriastradh if (frame->bo == NULL) 78303b705cfSriastradh return false; 78403b705cfSriastradh } 78503b705cfSriastradh 786fe8aea9eSmrg if (is_nv12_fourcc(frame->id)) 787fe8aea9eSmrg sna_copy_nv12_data(video, frame, buf, dst); 788fe8aea9eSmrg else if (is_planar_fourcc(frame->id)) 78903b705cfSriastradh sna_copy_planar_data(video, frame, buf, dst); 790fe8aea9eSmrg else if (is_ayuv_fourcc(frame->id)) 791fe8aea9eSmrg sna_copy_ayuv_data(video, frame, buf, dst); 79203b705cfSriastradh else 79303b705cfSriastradh sna_copy_packed_data(video, frame, buf, dst); 79403b705cfSriastradh 79503b705cfSriastradh return true; 79603b705cfSriastradh} 79703b705cfSriastradh 798fe8aea9eSmrgvoid sna_video_fill_colorkey(struct sna_video *video, 799fe8aea9eSmrg const RegionRec *clip) 800fe8aea9eSmrg{ 801fe8aea9eSmrg struct sna *sna = video->sna; 802fe8aea9eSmrg PixmapPtr front = sna->front; 803fe8aea9eSmrg struct kgem_bo *bo = __sna_pixmap_get_bo(front); 804fe8aea9eSmrg uint8_t *dst, *tmp; 805fe8aea9eSmrg int w, width; 806fe8aea9eSmrg 807fe8aea9eSmrg if (video->AlwaysOnTop || RegionEqual(&video->clip, (RegionPtr)clip)) 808fe8aea9eSmrg return; 809fe8aea9eSmrg 810fe8aea9eSmrg assert(bo); 811fe8aea9eSmrg if (!wedged(sna) && 812fe8aea9eSmrg sna_blt_fill_boxes(sna, GXcopy, bo, 813fe8aea9eSmrg front->drawable.bitsPerPixel, 814fe8aea9eSmrg video->color_key, 815fe8aea9eSmrg region_rects(clip), 816fe8aea9eSmrg region_num_rects(clip))) { 817fe8aea9eSmrg RegionCopy(&video->clip, (RegionPtr)clip); 818fe8aea9eSmrg return; 819fe8aea9eSmrg } 820fe8aea9eSmrg 821fe8aea9eSmrg dst = kgem_bo_map__gtt(&sna->kgem, bo); 822fe8aea9eSmrg if (dst == NULL) 823fe8aea9eSmrg return; 824fe8aea9eSmrg 825fe8aea9eSmrg w = front->drawable.bitsPerPixel/8; 826fe8aea9eSmrg width = (clip->extents.x2 - clip->extents.x1) * w; 827fe8aea9eSmrg tmp = malloc(width); 828fe8aea9eSmrg if (tmp == NULL) 829fe8aea9eSmrg return; 830fe8aea9eSmrg 831fe8aea9eSmrg memcpy(tmp, &video->color_key, w); 832fe8aea9eSmrg while (2 * w < width) { 833fe8aea9eSmrg memcpy(tmp + w, tmp, w); 834fe8aea9eSmrg w *= 2; 835fe8aea9eSmrg } 836fe8aea9eSmrg if (w < width) 837fe8aea9eSmrg memcpy(tmp + w, tmp, width - w); 838fe8aea9eSmrg 839fe8aea9eSmrg if (sigtrap_get() == 0) { 840fe8aea9eSmrg const BoxRec *box = region_rects(clip); 841fe8aea9eSmrg int n = region_num_rects(clip); 842fe8aea9eSmrg 843fe8aea9eSmrg w = front->drawable.bitsPerPixel/8; 844fe8aea9eSmrg do { 845fe8aea9eSmrg int y = box->y1; 846fe8aea9eSmrg uint8_t *row = dst + y*bo->pitch + w*box->x1; 847fe8aea9eSmrg 848fe8aea9eSmrg width = (box->x2 - box->x1) * w; 849fe8aea9eSmrg while (y < box->y2) { 850fe8aea9eSmrg memcpy(row, tmp, width); 851fe8aea9eSmrg row += bo->pitch; 852fe8aea9eSmrg y++; 853fe8aea9eSmrg } 854fe8aea9eSmrg box++; 855fe8aea9eSmrg } while (--n); 856fe8aea9eSmrg sigtrap_put(); 857fe8aea9eSmrg 858fe8aea9eSmrg RegionCopy(&video->clip, (RegionPtr)clip); 859fe8aea9eSmrg } 860fe8aea9eSmrg 861fe8aea9eSmrg free(tmp); 862fe8aea9eSmrg} 863fe8aea9eSmrg 86403b705cfSriastradhXvAdaptorPtr sna_xv_adaptor_alloc(struct sna *sna) 86503b705cfSriastradh{ 86603b705cfSriastradh XvAdaptorPtr new_adaptors; 86703b705cfSriastradh 86803b705cfSriastradh new_adaptors = realloc(sna->xv.adaptors, 86903b705cfSriastradh (sna->xv.num_adaptors+1)*sizeof(XvAdaptorRec)); 87003b705cfSriastradh if (new_adaptors == NULL) 87103b705cfSriastradh return NULL; 87203b705cfSriastradh 87303b705cfSriastradh if (sna->xv.num_adaptors && new_adaptors != sna->xv.adaptors) { 87403b705cfSriastradh XvAdaptorPtr adaptor = new_adaptors; 87503b705cfSriastradh int i = sna->xv.num_adaptors, j; 87603b705cfSriastradh while (i--) { 87703b705cfSriastradh for (j = 0; j < adaptor->nPorts; j++) 87803b705cfSriastradh adaptor->pPorts[j].pAdaptor = adaptor; 87903b705cfSriastradh adaptor++; 88003b705cfSriastradh } 88103b705cfSriastradh } 88203b705cfSriastradh 88303b705cfSriastradh sna->xv.adaptors = new_adaptors; 88403b705cfSriastradh return &sna->xv.adaptors[sna->xv.num_adaptors++]; 88503b705cfSriastradh} 88603b705cfSriastradh 88703b705cfSriastradhint 88803b705cfSriastradhsna_xv_alloc_port(unsigned long port, XvPortPtr in, XvPortPtr *out) 88903b705cfSriastradh{ 89003b705cfSriastradh *out = in; 89103b705cfSriastradh return Success; 89203b705cfSriastradh} 89303b705cfSriastradh 89403b705cfSriastradhint 89503b705cfSriastradhsna_xv_free_port(XvPortPtr port) 89603b705cfSriastradh{ 89703b705cfSriastradh return Success; 89803b705cfSriastradh} 89903b705cfSriastradh 90003b705cfSriastradhint 90103b705cfSriastradhsna_xv_fixup_formats(ScreenPtr screen, XvFormatPtr formats, int num_formats) 90203b705cfSriastradh{ 90303b705cfSriastradh XvFormatPtr out = formats; 90403b705cfSriastradh int count = 0; 90503b705cfSriastradh 90603b705cfSriastradh while (num_formats--) { 90703b705cfSriastradh int num_visuals = screen->numVisuals; 90803b705cfSriastradh VisualPtr v = screen->visuals; 90903b705cfSriastradh 91003b705cfSriastradh while (num_visuals--) { 91103b705cfSriastradh if (v->class == TrueColor && 91203b705cfSriastradh v->nplanes == formats->depth) { 91303b705cfSriastradh int tmp = out[count].depth; 91403b705cfSriastradh out[count].depth = formats->depth; 91503b705cfSriastradh out[count].visual = v->vid; 91603b705cfSriastradh formats->depth = tmp; 91703b705cfSriastradh count++; 91803b705cfSriastradh break; 91903b705cfSriastradh } 92003b705cfSriastradh v++; 92103b705cfSriastradh } 92203b705cfSriastradh 92303b705cfSriastradh formats++; 92403b705cfSriastradh } 92503b705cfSriastradh 92603b705cfSriastradh return count; 92703b705cfSriastradh} 92803b705cfSriastradh 92942542f5fSchristos#if XORG_XV_VERSION < 2 93003b705cfSriastradhstatic int 93103b705cfSriastradhsna_xv_query_adaptors(ScreenPtr screen, 93203b705cfSriastradh XvAdaptorPtr *adaptors, 93303b705cfSriastradh int *num_adaptors) 93403b705cfSriastradh{ 93503b705cfSriastradh struct sna *sna = to_sna_from_screen(screen); 93603b705cfSriastradh 93703b705cfSriastradh *num_adaptors = sna->xv.num_adaptors; 93803b705cfSriastradh *adaptors = sna->xv.adaptors; 93903b705cfSriastradh return Success; 94003b705cfSriastradh} 94103b705cfSriastradh 94203b705cfSriastradhstatic Bool 94303b705cfSriastradhsna_xv_close_screen(CLOSE_SCREEN_ARGS_DECL) 94403b705cfSriastradh{ 94503b705cfSriastradh struct sna *sna = to_sna_from_screen(screen); 94642542f5fSchristos sna_video_close(sna); 94703b705cfSriastradh return TRUE; 94803b705cfSriastradh} 94942542f5fSchristos#endif 95003b705cfSriastradh 95103b705cfSriastradhvoid sna_video_init(struct sna *sna, ScreenPtr screen) 95203b705cfSriastradh{ 95303b705cfSriastradh XvScreenPtr xv; 95403b705cfSriastradh 95503b705cfSriastradh if (noXvExtension) 95603b705cfSriastradh return; 95703b705cfSriastradh 95803b705cfSriastradh if (xf86LoaderCheckSymbol("xf86XVListGenericAdaptors")) { 95903b705cfSriastradh XF86VideoAdaptorPtr *adaptors = NULL; 96003b705cfSriastradh int num_adaptors = xf86XVListGenericAdaptors(sna->scrn, &adaptors); 96103b705cfSriastradh if (num_adaptors) 96203b705cfSriastradh xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR, 96303b705cfSriastradh "Ignoring generic xf86XV adaptors"); 96403b705cfSriastradh free(adaptors); 96503b705cfSriastradh } 96603b705cfSriastradh 96703b705cfSriastradh if (XvScreenInit(screen) != Success) 96803b705cfSriastradh return; 96903b705cfSriastradh 97003b705cfSriastradh xv = to_xv(screen); 97142542f5fSchristos#if XORG_XV_VERSION < 2 97203b705cfSriastradh xv->ddCloseScreen = sna_xv_close_screen; 97303b705cfSriastradh xv->ddQueryAdaptors = sna_xv_query_adaptors; 97442542f5fSchristos#endif 97503b705cfSriastradh 97603b705cfSriastradh sna_video_textured_setup(sna, screen); 97703b705cfSriastradh sna_video_sprite_setup(sna, screen); 97803b705cfSriastradh sna_video_overlay_setup(sna, screen); 97903b705cfSriastradh 98003b705cfSriastradh if (sna->xv.num_adaptors >= 2 && 98103b705cfSriastradh xf86ReturnOptValBool(sna->Options, OPTION_PREFER_OVERLAY, false)) { 98203b705cfSriastradh XvAdaptorRec tmp; 98303b705cfSriastradh 98403b705cfSriastradh tmp = sna->xv.adaptors[0]; 98503b705cfSriastradh sna->xv.adaptors[0] = sna->xv.adaptors[1]; 98603b705cfSriastradh sna->xv.adaptors[1] = tmp; 98703b705cfSriastradh } 98803b705cfSriastradh 98903b705cfSriastradh xv->nAdaptors = sna->xv.num_adaptors; 99003b705cfSriastradh xv->pAdaptors = sna->xv.adaptors; 99103b705cfSriastradh 99203b705cfSriastradh sna_video_xvmc_setup(sna, screen); 99303b705cfSriastradh} 99403b705cfSriastradh 99503b705cfSriastradhvoid sna_video_destroy_window(WindowPtr win) 99603b705cfSriastradh{ 99703b705cfSriastradh XvPortPtr port; 99803b705cfSriastradh 99903b705cfSriastradh port = sna_window_get_port(win); 100042542f5fSchristos if (port) { 100142542f5fSchristos#if XORG_XV_VERSION < 2 100203b705cfSriastradh port->pAdaptor->ddStopVideo(NULL, port, &win->drawable); 100342542f5fSchristos#else 100442542f5fSchristos port->pAdaptor->ddStopVideo(port, &win->drawable); 100542542f5fSchristos#endif 100642542f5fSchristos } 100703b705cfSriastradh assert(sna_window_get_port(win) == NULL); 100803b705cfSriastradh} 100942542f5fSchristos 101042542f5fSchristosvoid sna_video_close(struct sna *sna) 101142542f5fSchristos{ 101242542f5fSchristos int i; 101342542f5fSchristos 101442542f5fSchristos for (i = 0; i < sna->xv.num_adaptors; i++) { 101542542f5fSchristos free(sna->xv.adaptors[i].pPorts->devPriv.ptr); 101642542f5fSchristos free(sna->xv.adaptors[i].pPorts); 101742542f5fSchristos free(sna->xv.adaptors[i].pEncodings); 101842542f5fSchristos } 101942542f5fSchristos free(sna->xv.adaptors); 102042542f5fSchristos 102142542f5fSchristos sna->xv.adaptors = NULL; 102242542f5fSchristos sna->xv.num_adaptors = 0; 102342542f5fSchristos} 1024