1f29dbc25Smrg/* Copyright (c) 2007-2008 Advanced Micro Devices, Inc. 2f29dbc25Smrg * 3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to 5f29dbc25Smrg * deal in the Software without restriction, including without limitation the 6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is 8f29dbc25Smrg * furnished to do so, subject to the following conditions: 9f29dbc25Smrg * 10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 11f29dbc25Smrg * all copies or substantial portions of the Software. 12f29dbc25Smrg * 13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19f29dbc25Smrg * IN THE SOFTWARE. 20f29dbc25Smrg * 21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 23f29dbc25Smrg * software without specific prior written permission. 24f29dbc25Smrg */ 25f29dbc25Smrg 26f29dbc25Smrg/* TODO: 27f29dbc25Smrg Add rotation 28f29dbc25Smrg Add back in double buffering? 29f29dbc25Smrg 30f29dbc25Smrg*/ 31f29dbc25Smrg 32f29dbc25Smrg#ifdef HAVE_CONFIG_H 33f29dbc25Smrg#include "config.h" 34f29dbc25Smrg#endif 35f29dbc25Smrg 36f29dbc25Smrg#include <stdlib.h> 37f29dbc25Smrg#include <string.h> 38f29dbc25Smrg 3900be8644Schristos#include "xorg-server.h" 4000be8644Schristos 41f29dbc25Smrg#include "xf86.h" 42f29dbc25Smrg#include "xf86_OSproc.h" 43f29dbc25Smrg#include "compiler.h" 44f29dbc25Smrg#include "xf86PciInfo.h" 45f29dbc25Smrg#include "xf86Pci.h" 46f29dbc25Smrg#include "xf86fbman.h" 47f29dbc25Smrg#include "regionstr.h" 48f29dbc25Smrg#include "dixstruct.h" 49f29dbc25Smrg 50f29dbc25Smrg#include "geode.h" 51f29dbc25Smrg#include "xf86xv.h" 52f29dbc25Smrg#include <X11/extensions/Xv.h> 53f29dbc25Smrg#include "fourcc.h" 54f29dbc25Smrg#include "geode_fourcc.h" 55f29dbc25Smrg#include "cim/cim_defs.h" 56f29dbc25Smrg#include "cim/cim_regs.h" 57f29dbc25Smrg 58f29dbc25Smrg#define OFF_DELAY 200 59f29dbc25Smrg#define FREE_DELAY 60000 60f29dbc25Smrg#define OFF_TIMER 0x01 61f29dbc25Smrg#define FREE_TIMER 0x02 62f29dbc25Smrg#define CLIENT_VIDEO_ON 0x04 63f29dbc25Smrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 64f29dbc25Smrg 65f29dbc25Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 6604007ebaSmrg#ifndef ARRAY_SIZE 67f29dbc25Smrg#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a)))) 6804007ebaSmrg#endif 69f29dbc25Smrg 70f29dbc25Smrg/* Local function prototypes */ 71f29dbc25Smrgstatic void LXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit); 72f29dbc25Smrg 73f29dbc25Smrgstatic void 7404007ebaSmrg 7504007ebaSmrg 76f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 7704007ebaSmrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH); 78f29dbc25Smrg 79f29dbc25Smrgstatic void LXResetVideo(ScrnInfoPtr pScrni); 80f29dbc25Smrg 81f29dbc25Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = { 82f29dbc25Smrg {0, "XV_IMAGE", 1024, 1024, {1, 1}} 83f29dbc25Smrg}; 84f29dbc25Smrg 85f29dbc25Smrgstatic XF86VideoFormatRec Formats[] = { 86f29dbc25Smrg {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 87f29dbc25Smrg}; 88f29dbc25Smrg 89f29dbc25Smrgstatic XF86AttributeRec Attributes[] = { 90f29dbc25Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 91f29dbc25Smrg {XvSettable | XvGettable, 0, 1, "XV_FILTER"}, 92f29dbc25Smrg {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"} 93f29dbc25Smrg}; 94f29dbc25Smrg 95f29dbc25Smrgstatic XF86ImageRec Images[] = { 96f29dbc25Smrg XVIMAGE_UYVY, 97f29dbc25Smrg XVIMAGE_YUY2, 98f29dbc25Smrg XVIMAGE_Y2YU, 99f29dbc25Smrg XVIMAGE_YVYU, 100f29dbc25Smrg XVIMAGE_Y800, 101f29dbc25Smrg XVIMAGE_I420, 102f29dbc25Smrg XVIMAGE_YV12, 103f29dbc25Smrg XVIMAGE_RGB565 104f29dbc25Smrg}; 105f29dbc25Smrg 10604007ebaSmrgtypedef struct { 107170d5fdcSmrg ExaOffscreenArea *vidmem; 108f29dbc25Smrg RegionRec clip; 109f29dbc25Smrg CARD32 filter; 110f29dbc25Smrg CARD32 colorKey; 111f29dbc25Smrg CARD32 colorKeyMode; 112f29dbc25Smrg CARD32 videoStatus; 113f29dbc25Smrg Time offTime; 114f29dbc25Smrg Time freeTime; 115f29dbc25Smrg short pwidth, pheight; 116f29dbc25Smrg} GeodePortPrivRec, *GeodePortPrivPtr; 117f29dbc25Smrg 118f29dbc25Smrg#define GET_PORT_PRIVATE(pScrni) \ 119f29dbc25Smrg (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr) 120f29dbc25Smrg 121f29dbc25Smrgstatic void 122f29dbc25SmrgLXCopyFromSys(GeodeRec * pGeode, unsigned char *src, unsigned int dst, 12304007ebaSmrg int dstPitch, int srcPitch, int h, int w) 124f29dbc25Smrg{ 125f29dbc25Smrg 126f29dbc25Smrg gp_declare_blt(0); 127170d5fdcSmrg gp_set_bpp((srcPitch / w) << 3); 128f29dbc25Smrg 129f29dbc25Smrg gp_set_raster_operation(0xCC); 130f29dbc25Smrg gp_set_strides(dstPitch, srcPitch); 131f29dbc25Smrg gp_set_solid_pattern(0); 132f29dbc25Smrg 133f29dbc25Smrg gp_color_bitmap_to_screen_blt(dst, 0, w, h, src, srcPitch); 134f29dbc25Smrg} 135f29dbc25Smrg 136f29dbc25Smrgstatic void 137f29dbc25SmrgLXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv) 138f29dbc25Smrg{ 139f29dbc25Smrg int red, green, blue; 140f29dbc25Smrg unsigned long key; 141f29dbc25Smrg 142f29dbc25Smrg switch (pScrni->depth) { 143f29dbc25Smrg case 8: 14404007ebaSmrg vg_get_display_palette_entry(pPriv->colorKey & 0xFF, &key); 14504007ebaSmrg red = ((key >> 16) & 0xFF); 14604007ebaSmrg green = ((key >> 8) & 0xFF); 14704007ebaSmrg blue = (key & 0xFF); 14804007ebaSmrg break; 149f29dbc25Smrg case 16: 15004007ebaSmrg red = (pPriv->colorKey & pScrni->mask.red) >> 15104007ebaSmrg pScrni->offset.red << (8 - pScrni->weight.red); 15204007ebaSmrg green = (pPriv->colorKey & pScrni->mask.green) >> 15304007ebaSmrg pScrni->offset.green << (8 - pScrni->weight.green); 15404007ebaSmrg blue = (pPriv->colorKey & pScrni->mask.blue) >> 15504007ebaSmrg pScrni->offset.blue << (8 - pScrni->weight.blue); 15604007ebaSmrg break; 157f29dbc25Smrg default: 15804007ebaSmrg /* for > 16 bpp we send in the mask in xf86SetWeight. This 15904007ebaSmrg * function is providing the offset by 1 more. So we take 16004007ebaSmrg * this as a special case and subtract 1 for > 16 16104007ebaSmrg */ 16204007ebaSmrg 16304007ebaSmrg red = (pPriv->colorKey & pScrni->mask.red) >> 16404007ebaSmrg (pScrni->offset.red - 1) << (8 - pScrni->weight.red); 16504007ebaSmrg green = (pPriv->colorKey & pScrni->mask.green) >> 16604007ebaSmrg (pScrni->offset.green - 1) << (8 - pScrni->weight.green); 16704007ebaSmrg blue = (pPriv->colorKey & pScrni->mask.blue) >> 16804007ebaSmrg (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue); 16904007ebaSmrg break; 170f29dbc25Smrg } 171f29dbc25Smrg 172f29dbc25Smrg df_set_video_color_key((blue | (green << 8) | (red << 16)), 17304007ebaSmrg 0xFFFFFF, (pPriv->colorKeyMode == 0)); 174f29dbc25Smrg 175f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 176f29dbc25Smrg} 177f29dbc25Smrg 178f29dbc25Smrg/* A structure full of the scratch information that originates in the copy routines, 179f29dbc25Smrg but is needed for the video display - maybe we should figure out a way to attach 180f29dbc25Smrg this to structures? I hate to put it in pGeode since it will increase the size of 181f29dbc25Smrg the structure, and possibly cause us cache issues. 182f29dbc25Smrg*/ 183f29dbc25Smrg 18404007ebaSmrgstruct { 185f29dbc25Smrg unsigned int dstOffset; 186f29dbc25Smrg unsigned int dstPitch; 187f29dbc25Smrg unsigned int UVPitch; 188f29dbc25Smrg unsigned int UDstOffset; 189f29dbc25Smrg unsigned int VDstOffset; 190f29dbc25Smrg} videoScratch; 191f29dbc25Smrg 192f29dbc25Smrg/* Copy planar YUV data */ 193f29dbc25Smrg 194f29dbc25Smrgstatic Bool 19504007ebaSmrgLXAllocateVidMem(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv, int size) 196f29dbc25Smrg{ 19704007ebaSmrg if (!pPriv->vidmem || pPriv->vidmem->size < size) { 19804007ebaSmrg if (pPriv->vidmem) { 19904007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 20004007ebaSmrg pPriv->vidmem = NULL; 20104007ebaSmrg } 20204007ebaSmrg 20304007ebaSmrg pPriv->vidmem = exaOffscreenAlloc(pScrni->pScreen, size, 4, 20404007ebaSmrg TRUE, NULL, NULL); 20504007ebaSmrg 20604007ebaSmrg if (pPriv->vidmem == NULL) { 20704007ebaSmrg ErrorF("Could not allocate memory for the video\n"); 20804007ebaSmrg return FALSE; 20904007ebaSmrg } 210f29dbc25Smrg } 211f29dbc25Smrg 212f29dbc25Smrg return TRUE; 21304007ebaSmrg} 214f29dbc25Smrg 215f29dbc25Smrgstatic Bool 216f29dbc25SmrgLXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, 21704007ebaSmrg short x1, short y1, short x2, short y2, 21804007ebaSmrg int width, int height, pointer data) 219f29dbc25Smrg{ 220f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 221f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 222f29dbc25Smrg 223f29dbc25Smrg unsigned int YSrcPitch, YDstPitch; 224f29dbc25Smrg unsigned int UVSrcPitch, UVDstPitch; 225f29dbc25Smrg unsigned int YSrcOffset, YDstOffset; 226f29dbc25Smrg unsigned int USrcOffset, UDstOffset; 227f29dbc25Smrg unsigned int VSrcOffset, VDstOffset; 228f29dbc25Smrg 229f29dbc25Smrg unsigned int size, lines, top, left, pixels; 230f29dbc25Smrg 231f29dbc25Smrg YSrcPitch = (width + 3) & ~3; 232f29dbc25Smrg YDstPitch = (width + 31) & ~31; 233f29dbc25Smrg 234f29dbc25Smrg UVSrcPitch = ((width >> 1) + 3) & ~3; 235f29dbc25Smrg UVDstPitch = ((width >> 1) + 15) & ~15; 236f29dbc25Smrg 237f29dbc25Smrg USrcOffset = YSrcPitch * height; 238f29dbc25Smrg VSrcOffset = USrcOffset + (UVSrcPitch * (height >> 1)); 239f29dbc25Smrg 240f29dbc25Smrg UDstOffset = YDstPitch * height; 241f29dbc25Smrg VDstOffset = UDstOffset + (UVDstPitch * (height >> 1)); 242f29dbc25Smrg 243f29dbc25Smrg size = YDstPitch * height; 244f29dbc25Smrg size += UVDstPitch * height; 245f29dbc25Smrg 246170d5fdcSmrg if (LXAllocateVidMem(pScrni, pPriv, size) == FALSE) { 24704007ebaSmrg ErrorF("Error allocating an offscreen Planar region.\n"); 24804007ebaSmrg return FALSE; 249170d5fdcSmrg } 250f29dbc25Smrg 251f29dbc25Smrg /* The top of the source region we want to copy */ 252f29dbc25Smrg top = y1 & ~1; 253f29dbc25Smrg 254f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 255f29dbc25Smrg left = x1 & ~1; 256f29dbc25Smrg 257f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 258f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 259f29dbc25Smrg 260f29dbc25Smrg /* Calculate the source offset */ 261f29dbc25Smrg YSrcOffset = (top * YSrcPitch) + left; 262f29dbc25Smrg USrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 263f29dbc25Smrg VSrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 264f29dbc25Smrg 265f29dbc25Smrg /* Calculate the destination offset */ 266f29dbc25Smrg YDstOffset = (top * YDstPitch) + left; 267f29dbc25Smrg UDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 268f29dbc25Smrg VDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 269f29dbc25Smrg 270f29dbc25Smrg lines = ((y2 + 1) & ~1) - top; 271f29dbc25Smrg 272f29dbc25Smrg /* Copy Y */ 273f29dbc25Smrg 274f29dbc25Smrg LXCopyFromSys(pGeode, buf + YSrcOffset, 27504007ebaSmrg pPriv->vidmem->offset + YDstOffset, YDstPitch, YSrcPitch, 27604007ebaSmrg lines, pixels); 277f29dbc25Smrg 278f29dbc25Smrg /* Copy U + V at the same time */ 279f29dbc25Smrg 280f29dbc25Smrg LXCopyFromSys(pGeode, buf + USrcOffset, 28104007ebaSmrg pPriv->vidmem->offset + UDstOffset, UVDstPitch, UVSrcPitch, 28204007ebaSmrg lines, pixels >> 1); 283f29dbc25Smrg 284f29dbc25Smrg videoScratch.dstOffset = pPriv->vidmem->offset + YDstOffset; 285f29dbc25Smrg videoScratch.dstPitch = YDstPitch; 286f29dbc25Smrg videoScratch.UVPitch = UVDstPitch; 287f29dbc25Smrg videoScratch.UDstOffset = pPriv->vidmem->offset + UDstOffset; 288f29dbc25Smrg videoScratch.VDstOffset = pPriv->vidmem->offset + VDstOffset; 289f29dbc25Smrg 290f29dbc25Smrg return TRUE; 291f29dbc25Smrg} 292f29dbc25Smrg 293f29dbc25Smrgstatic Bool 294f29dbc25SmrgLXCopyPacked(ScrnInfoPtr pScrni, int id, unsigned char *buf, 29504007ebaSmrg short x1, short y1, short x2, short y2, 29604007ebaSmrg int width, int height, pointer data) 297f29dbc25Smrg{ 298f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 299f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 300f29dbc25Smrg unsigned int dstPitch, srcPitch; 301f29dbc25Smrg unsigned int srcOffset, dstOffset; 302f29dbc25Smrg unsigned int lines, top, left, pixels; 303f29dbc25Smrg 304f29dbc25Smrg dstPitch = ((width << 1) + 3) & ~3; 305f29dbc25Smrg srcPitch = (width << 1); 306f29dbc25Smrg 307f29dbc25Smrg lines = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch; 308f29dbc25Smrg 3097aef237fSmrg if (LXAllocateVidMem(pScrni, pPriv, dstPitch * height) == FALSE) { 31004007ebaSmrg ErrorF("Error allocating an offscreen Packed region.\n"); 31104007ebaSmrg return FALSE; 312170d5fdcSmrg } 313f29dbc25Smrg 314f29dbc25Smrg /* The top of the source region we want to copy */ 315f29dbc25Smrg top = y1; 316f29dbc25Smrg 317f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 318f29dbc25Smrg left = x1 & ~1; 319f29dbc25Smrg 320f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 321f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 322f29dbc25Smrg 323f29dbc25Smrg /* Adjust the incoming buffer */ 324f29dbc25Smrg srcOffset = (top * srcPitch) + left; 325f29dbc25Smrg 326f29dbc25Smrg /* Calculate the destination offset */ 327f29dbc25Smrg dstOffset = pPriv->vidmem->offset + (top * dstPitch) + left; 328f29dbc25Smrg 329f29dbc25Smrg /* Make the copy happen */ 330f29dbc25Smrg 331f29dbc25Smrg if (id == FOURCC_Y800) { 332f29dbc25Smrg 33304007ebaSmrg /* Use the shared (unaccelerated) greyscale copy - you could probably 33404007ebaSmrg * accelerate it using a 2 pass blit and patterns, but it doesn't really 33504007ebaSmrg * seem worth it 33604007ebaSmrg */ 337f29dbc25Smrg 33804007ebaSmrg GeodeCopyGreyscale(buf + srcOffset, pGeode->FBBase + dstOffset, 33904007ebaSmrg srcPitch, dstPitch, height, pixels >> 1); 34004007ebaSmrg } 34104007ebaSmrg else 34204007ebaSmrg /* FIXME: should lines be used here instead of height? */ 34304007ebaSmrg LXCopyFromSys(pGeode, buf + srcOffset, dstOffset, dstPitch, srcPitch, 34404007ebaSmrg height, pixels); 345f29dbc25Smrg 346f29dbc25Smrg videoScratch.dstOffset = dstOffset; 347f29dbc25Smrg videoScratch.dstPitch = dstPitch; 348f29dbc25Smrg 349f29dbc25Smrg return TRUE; 350f29dbc25Smrg} 351f29dbc25Smrg 352f29dbc25Smrgstatic void 353f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 35404007ebaSmrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH) 355f29dbc25Smrg{ 356f29dbc25Smrg long ystart, xend, yend; 357f29dbc25Smrg unsigned long lines = 0; 358f29dbc25Smrg unsigned long yExtra, uvExtra = 0; 359f29dbc25Smrg DF_VIDEO_POSITION vidPos; 360f29dbc25Smrg DF_VIDEO_SOURCE_PARAMS vSrcParams; 361f29dbc25Smrg int err; 362f29dbc25Smrg 363f29dbc25Smrg memset(&vSrcParams, 0, sizeof(vSrcParams)); 364f29dbc25Smrg 365f29dbc25Smrg gp_wait_until_idle(); 366f29dbc25Smrg 367f29dbc25Smrg switch (id) { 368f29dbc25Smrg case FOURCC_UYVY: 36904007ebaSmrg vSrcParams.video_format = DF_VIDFMT_UYVY; 37004007ebaSmrg break; 371f29dbc25Smrg 372f29dbc25Smrg case FOURCC_Y800: 373f29dbc25Smrg case FOURCC_YV12: 374f29dbc25Smrg case FOURCC_I420: 37504007ebaSmrg vSrcParams.video_format = DF_VIDFMT_Y0Y1Y2Y3; 37604007ebaSmrg break; 377f29dbc25Smrg case FOURCC_YUY2: 37804007ebaSmrg vSrcParams.video_format = DF_VIDFMT_YUYV; 37904007ebaSmrg break; 380f29dbc25Smrg case FOURCC_Y2YU: 38104007ebaSmrg vSrcParams.video_format = DF_VIDFMT_Y2YU; 38204007ebaSmrg break; 383f29dbc25Smrg case FOURCC_YVYU: 38404007ebaSmrg vSrcParams.video_format = DF_VIDFMT_YVYU; 38504007ebaSmrg break; 386f29dbc25Smrg case FOURCC_RGB565: 38704007ebaSmrg vSrcParams.video_format = DF_VIDFMT_RGB; 38804007ebaSmrg break; 389f29dbc25Smrg } 390f29dbc25Smrg 391f29dbc25Smrg vSrcParams.width = width; 392f29dbc25Smrg vSrcParams.height = height; 393f29dbc25Smrg vSrcParams.y_pitch = videoScratch.dstPitch; 394f29dbc25Smrg vSrcParams.uv_pitch = videoScratch.UVPitch; 395f29dbc25Smrg 396f29dbc25Smrg /* Set up scaling */ 397f29dbc25Smrg df_set_video_filter_coefficients(NULL, 1); 398f29dbc25Smrg 399f29dbc25Smrg err = df_set_video_scale(width, height, drawW, drawH, 40004007ebaSmrg DF_SCALEFLAG_CHANGEX | DF_SCALEFLAG_CHANGEY); 401f29dbc25Smrg if (err != CIM_STATUS_OK) { 40204007ebaSmrg /* Note the problem, but do nothing for now. */ 40304007ebaSmrg ErrorF("Video scale factor too large: %dx%d -> %dx%d\n", 40404007ebaSmrg width, height, drawW, drawH); 405f29dbc25Smrg } 406f29dbc25Smrg 407f29dbc25Smrg /* Figure out clipping */ 408f29dbc25Smrg 409f29dbc25Smrg xend = dstBox->x2; 410f29dbc25Smrg yend = dstBox->y2; 411f29dbc25Smrg 412f29dbc25Smrg if (dstBox->y1 < 0) { 41304007ebaSmrg if (srcH < drawH) 41404007ebaSmrg lines = ((-dstBox->y1) * srcH) / drawH; 41504007ebaSmrg else 41604007ebaSmrg lines = (-dstBox->y1); 41704007ebaSmrg 41804007ebaSmrg ystart = 0; 41904007ebaSmrg drawH += dstBox->y1; 42004007ebaSmrg } 42104007ebaSmrg else { 42204007ebaSmrg ystart = dstBox->y1; 42304007ebaSmrg lines = 0; 424f29dbc25Smrg } 425f29dbc25Smrg 426f29dbc25Smrg yExtra = lines * videoScratch.dstPitch; 427f29dbc25Smrg uvExtra = (lines >> 1) * videoScratch.UVPitch; 428f29dbc25Smrg 429f29dbc25Smrg memset(&vidPos, 0, sizeof(vidPos)); 430f29dbc25Smrg 431f29dbc25Smrg vidPos.x = dstBox->x1; 432f29dbc25Smrg vidPos.y = ystart; 433f29dbc25Smrg vidPos.width = xend - dstBox->x1; 434f29dbc25Smrg vidPos.height = yend - ystart; 435f29dbc25Smrg 436f29dbc25Smrg df_set_video_position(&vidPos); 437f29dbc25Smrg 438f29dbc25Smrg vSrcParams.y_offset = videoScratch.dstOffset + yExtra; 439f29dbc25Smrg 440f29dbc25Smrg switch (id) { 441f29dbc25Smrg case FOURCC_Y800: 442f29dbc25Smrg case FOURCC_I420: 44304007ebaSmrg vSrcParams.u_offset = videoScratch.UDstOffset + uvExtra; 44404007ebaSmrg vSrcParams.v_offset = videoScratch.VDstOffset + uvExtra; 44504007ebaSmrg break; 446f29dbc25Smrg case FOURCC_YV12: 44704007ebaSmrg vSrcParams.v_offset = videoScratch.UDstOffset + uvExtra; 44804007ebaSmrg vSrcParams.u_offset = videoScratch.VDstOffset + uvExtra; 44904007ebaSmrg break; 450f29dbc25Smrg 451f29dbc25Smrg default: 45204007ebaSmrg vSrcParams.u_offset = vSrcParams.v_offset = 0; 45304007ebaSmrg break; 454f29dbc25Smrg } 455f29dbc25Smrg 456f29dbc25Smrg vSrcParams.flags = DF_SOURCEFLAG_IMPLICITSCALING; 457f29dbc25Smrg df_configure_video_source(&vSrcParams, &vSrcParams); 458f29dbc25Smrg 459f29dbc25Smrg /* Turn on the video palette */ 460f29dbc25Smrg df_set_video_palette(NULL); 461f29dbc25Smrg df_set_video_enable(1, 0); 462f29dbc25Smrg} 463f29dbc25Smrg 464f29dbc25Smrgstatic int 465f29dbc25SmrgLXPutImage(ScrnInfoPtr pScrni, 46604007ebaSmrg short srcX, short srcY, short drawX, short drawY, 46704007ebaSmrg short srcW, short srcH, short drawW, short drawH, 46804007ebaSmrg int id, unsigned char *buf, 46904007ebaSmrg short width, short height, Bool sync, RegionPtr clipBoxes, 47004007ebaSmrg pointer data, DrawablePtr pDraw) 471f29dbc25Smrg{ 472f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 473f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 474f29dbc25Smrg INT32 x1, x2, y1, y2; 475f29dbc25Smrg BoxRec dstBox; 476f29dbc25Smrg Bool ret; 477f29dbc25Smrg 478f29dbc25Smrg if (pGeode->rotation != RR_Rotate_0) 47904007ebaSmrg return Success; 480f29dbc25Smrg 481f29dbc25Smrg if (srcW <= 0 || srcH <= 0) { 48204007ebaSmrg return Success; 483f29dbc25Smrg } 484f29dbc25Smrg 485f29dbc25Smrg if (drawW <= 0 || drawH <= 0) { 48604007ebaSmrg return Success; 487f29dbc25Smrg } 488f29dbc25Smrg 489f29dbc25Smrg if (drawW > 16384) 49004007ebaSmrg drawW = 16384; 491f29dbc25Smrg 492f29dbc25Smrg memset(&videoScratch, 0, sizeof(videoScratch)); 493f29dbc25Smrg 494f29dbc25Smrg x1 = srcX; 495f29dbc25Smrg x2 = srcX + srcW; 496f29dbc25Smrg y1 = srcY; 497f29dbc25Smrg y2 = srcY + srcH; 498f29dbc25Smrg 499f29dbc25Smrg dstBox.x1 = drawX; 500f29dbc25Smrg dstBox.x2 = drawX + drawW; 501f29dbc25Smrg dstBox.y1 = drawY; 502f29dbc25Smrg dstBox.y2 = drawY + drawH; 503f29dbc25Smrg 504f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 505f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 506f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 507f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 508f29dbc25Smrg 509f29dbc25Smrg if (id == FOURCC_YV12 || id == FOURCC_I420) 51004007ebaSmrg ret = LXCopyPlanar(pScrni, id, buf, x1, y1, x2, y2, width, 51104007ebaSmrg height, data); 512f29dbc25Smrg else 51304007ebaSmrg ret = LXCopyPacked(pScrni, id, buf, x1, y1, x2, y2, width, 51404007ebaSmrg height, data); 515f29dbc25Smrg 516f29dbc25Smrg if (ret == FALSE) 51704007ebaSmrg return BadAlloc; 51804007ebaSmrg 519f29dbc25Smrg if (!RegionsEqual(&pPriv->clip, clipBoxes) || 52004007ebaSmrg (drawW != pPriv->pwidth || drawH != pPriv->pheight)) { 52104007ebaSmrg REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes); 522f29dbc25Smrg 52304007ebaSmrg if (pPriv->colorKeyMode == 0) { 52404007ebaSmrg xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes); 52504007ebaSmrg } 526f29dbc25Smrg 52704007ebaSmrg LXDisplayVideo(pScrni, id, width, height, &dstBox, 52804007ebaSmrg srcW, srcH, drawW, drawH); 52904007ebaSmrg pPriv->pwidth = drawW; 53004007ebaSmrg pPriv->pheight = drawH; 531f29dbc25Smrg } 532f29dbc25Smrg 533f29dbc25Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 534f29dbc25Smrg 535f29dbc25Smrg return Success; 536f29dbc25Smrg} 537f29dbc25Smrg 538f29dbc25Smrgstatic void 539f29dbc25SmrgLXQueryBestSize(ScrnInfoPtr pScrni, Bool motion, 54004007ebaSmrg short vidW, short vidH, short drawW, short drawH, 54104007ebaSmrg unsigned int *retW, unsigned int *retH, pointer data) 542f29dbc25Smrg{ 543f29dbc25Smrg *retW = drawW > 16384 ? 16384 : drawW; 544f29dbc25Smrg *retH = drawH; 545f29dbc25Smrg} 546f29dbc25Smrg 547f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter; 548f29dbc25Smrg 549f29dbc25Smrgstatic int 550f29dbc25SmrgLXGetPortAttribute(ScrnInfoPtr pScrni, 55104007ebaSmrg Atom attribute, INT32 *value, pointer data) 552f29dbc25Smrg{ 553f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 554f29dbc25Smrg 555f29dbc25Smrg if (attribute == xvColorKey) 55604007ebaSmrg *value = pPriv->colorKey; 557f29dbc25Smrg else if (attribute == xvColorKeyMode) 55804007ebaSmrg *value = pPriv->colorKeyMode; 559f29dbc25Smrg else if (attribute == xvFilter) 56004007ebaSmrg *value = pPriv->filter; 561f29dbc25Smrg else 56204007ebaSmrg return BadMatch; 563f29dbc25Smrg 564f29dbc25Smrg return Success; 565f29dbc25Smrg} 566f29dbc25Smrg 567f29dbc25Smrgstatic int 568f29dbc25SmrgLXSetPortAttribute(ScrnInfoPtr pScrni, 56904007ebaSmrg Atom attribute, INT32 value, pointer data) 570f29dbc25Smrg{ 571f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 572f29dbc25Smrg 573f29dbc25Smrg gp_wait_until_idle(); 574f29dbc25Smrg 575f29dbc25Smrg if (attribute == xvColorKey) { 57604007ebaSmrg pPriv->colorKey = value; 57704007ebaSmrg LXSetColorkey(pScrni, pPriv); 57804007ebaSmrg } 57904007ebaSmrg else if (attribute == xvColorKeyMode) { 58004007ebaSmrg pPriv->colorKeyMode = value; 58104007ebaSmrg LXSetColorkey(pScrni, pPriv); 58204007ebaSmrg } 58304007ebaSmrg else if (attribute == xvFilter) { 58404007ebaSmrg if ((value < 0) || (value > 1)) 58504007ebaSmrg return BadValue; 58604007ebaSmrg pPriv->filter = value; 58704007ebaSmrg } 58804007ebaSmrg else 58904007ebaSmrg return BadMatch; 590f29dbc25Smrg 591f29dbc25Smrg return Success; 592f29dbc25Smrg} 593f29dbc25Smrg 594f29dbc25Smrgstatic void 595f29dbc25SmrgLXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 596f29dbc25Smrg{ 597f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 598f29dbc25Smrg 599f29dbc25Smrg if (pPriv->videoStatus == 0) 60004007ebaSmrg return; 601f29dbc25Smrg 602f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 603f29dbc25Smrg gp_wait_until_idle(); 604f29dbc25Smrg 605f29dbc25Smrg if (exit) { 60604007ebaSmrg if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 60704007ebaSmrg unsigned int val; 60804007ebaSmrg 60904007ebaSmrg df_set_video_enable(0, 0); 61004007ebaSmrg /* Put the LUT back in bypass */ 61104007ebaSmrg val = READ_VID32(DF_VID_MISC); 61204007ebaSmrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 61304007ebaSmrg } 61404007ebaSmrg 61504007ebaSmrg if (pPriv->vidmem) { 61604007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 61704007ebaSmrg pPriv->vidmem = NULL; 61804007ebaSmrg } 61904007ebaSmrg 62004007ebaSmrg pPriv->videoStatus = 0; 62104007ebaSmrg 62204007ebaSmrg /* Eh? */ 62304007ebaSmrg } 62404007ebaSmrg else if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 62504007ebaSmrg pPriv->videoStatus |= OFF_TIMER; 62604007ebaSmrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 627f29dbc25Smrg } 628f29dbc25Smrg} 629f29dbc25Smrg 630f29dbc25Smrgstatic void 631f29dbc25SmrgLXResetVideo(ScrnInfoPtr pScrni) 632f29dbc25Smrg{ 633f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 634f29dbc25Smrg 635f29dbc25Smrg if (!pGeode->NoAccel) { 63604007ebaSmrg GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr; 637f29dbc25Smrg 63804007ebaSmrg gp_wait_until_idle(); 63904007ebaSmrg df_set_video_palette(NULL); 640f29dbc25Smrg 64104007ebaSmrg LXSetColorkey(pScrni, pPriv); 642f29dbc25Smrg } 643f29dbc25Smrg} 644f29dbc25Smrg 645f29dbc25Smrgstatic void 64604007ebaSmrgLXVidBlockHandler(BLOCKHANDLER_ARGS_DECL) 647f29dbc25Smrg{ 64804007ebaSmrg SCREEN_PTR(arg); 64904007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 650f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 651f29dbc25Smrg GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni); 652f29dbc25Smrg 653f29dbc25Smrg pScrn->BlockHandler = pGeode->BlockHandler; 65404007ebaSmrg (*pScrn->BlockHandler) (BLOCKHANDLER_ARGS); 655f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 656f29dbc25Smrg 657f29dbc25Smrg if (pPriv->videoStatus & TIMER_MASK) { 65804007ebaSmrg Time now = currentTime.milliseconds; 65904007ebaSmrg 66004007ebaSmrg if (pPriv->videoStatus & OFF_TIMER) { 66104007ebaSmrg gp_wait_until_idle(); 66204007ebaSmrg 66304007ebaSmrg if (pPriv->offTime < now) { 66404007ebaSmrg unsigned int val; 66504007ebaSmrg 66604007ebaSmrg df_set_video_enable(0, 0); 66704007ebaSmrg pPriv->videoStatus = FREE_TIMER; 66804007ebaSmrg pPriv->freeTime = now + FREE_DELAY; 66904007ebaSmrg 67004007ebaSmrg /* Turn off the video palette */ 67104007ebaSmrg val = READ_VID32(DF_VID_MISC); 67204007ebaSmrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 67304007ebaSmrg } 67404007ebaSmrg } 67504007ebaSmrg else { 67604007ebaSmrg if (pPriv->freeTime < now) { 67704007ebaSmrg 67804007ebaSmrg if (pPriv->vidmem) { 67904007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 68004007ebaSmrg pPriv->vidmem = NULL; 68104007ebaSmrg } 68204007ebaSmrg 68304007ebaSmrg pPriv->videoStatus = 0; 68404007ebaSmrg } 68504007ebaSmrg } 686f29dbc25Smrg } 687f29dbc25Smrg} 688f29dbc25Smrg 689f29dbc25Smrgstatic XF86VideoAdaptorPtr 690f29dbc25SmrgLXSetupImageVideo(ScreenPtr pScrn) 691f29dbc25Smrg{ 69204007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 693f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 694f29dbc25Smrg XF86VideoAdaptorPtr adapt; 695f29dbc25Smrg GeodePortPrivRec *pPriv; 696f29dbc25Smrg 697170d5fdcSmrg adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 69804007ebaSmrg sizeof(GeodePortPrivRec) + sizeof(DevUnion)); 699f29dbc25Smrg 700f29dbc25Smrg if (adapt == NULL) { 70104007ebaSmrg ErrorF("Couldn't create the rec\n"); 70204007ebaSmrg return NULL; 703f29dbc25Smrg } 704f29dbc25Smrg 705f29dbc25Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 706f29dbc25Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 707f29dbc25Smrg 708f29dbc25Smrg adapt->name = "AMD Geode LX"; 709f29dbc25Smrg adapt->nEncodings = 1; 710f29dbc25Smrg adapt->pEncodings = DummyEncoding; 711f29dbc25Smrg adapt->nFormats = ARRAY_SIZE(Formats); 712f29dbc25Smrg adapt->pFormats = Formats; 713f29dbc25Smrg adapt->nPorts = 1; 714f29dbc25Smrg adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 715f29dbc25Smrg pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]); 716f29dbc25Smrg adapt->pPortPrivates[0].ptr = (pointer) (pPriv); 717f29dbc25Smrg adapt->pAttributes = Attributes; 718f29dbc25Smrg adapt->nImages = ARRAY_SIZE(Images); 719f29dbc25Smrg adapt->nAttributes = ARRAY_SIZE(Attributes); 720f29dbc25Smrg adapt->pImages = Images; 721f29dbc25Smrg adapt->PutVideo = NULL; 722f29dbc25Smrg adapt->PutStill = NULL; 723f29dbc25Smrg adapt->GetVideo = NULL; 724f29dbc25Smrg adapt->GetStill = NULL; 725f29dbc25Smrg adapt->StopVideo = LXStopVideo; 726f29dbc25Smrg adapt->SetPortAttribute = LXSetPortAttribute; 727f29dbc25Smrg adapt->GetPortAttribute = LXGetPortAttribute; 728f29dbc25Smrg adapt->QueryBestSize = LXQueryBestSize; 729f29dbc25Smrg adapt->PutImage = LXPutImage; 730f29dbc25Smrg 731f29dbc25Smrg /* Use the common function */ 732f29dbc25Smrg adapt->QueryImageAttributes = GeodeQueryImageAttributes; 733f29dbc25Smrg 734f29dbc25Smrg pPriv->vidmem = NULL; 735f29dbc25Smrg pPriv->filter = 0; 736f29dbc25Smrg pPriv->colorKey = 0; 737f29dbc25Smrg pPriv->colorKeyMode = 0; 738f29dbc25Smrg pPriv->videoStatus = 0; 739f29dbc25Smrg pPriv->pwidth = 0; 740f29dbc25Smrg pPriv->pheight = 0; 741f29dbc25Smrg 742f29dbc25Smrg REGION_NULL(pScrn, &pPriv->clip); 743f29dbc25Smrg 744f29dbc25Smrg pGeode->adaptor = adapt; 745f29dbc25Smrg 746f29dbc25Smrg pGeode->BlockHandler = pScrn->BlockHandler; 747f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 748f29dbc25Smrg 749f29dbc25Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 750f29dbc25Smrg xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE"); 751f29dbc25Smrg xvFilter = MAKE_ATOM("XV_FILTER"); 752f29dbc25Smrg 753f29dbc25Smrg LXResetVideo(pScrni); 754f29dbc25Smrg 755f29dbc25Smrg return adapt; 756f29dbc25Smrg} 757f29dbc25Smrg 758f29dbc25Smrg/* Offscreen surface allocation */ 759f29dbc25Smrg 76004007ebaSmrgstruct OffscreenPrivRec { 761170d5fdcSmrg ExaOffscreenArea *vidmem; 762f29dbc25Smrg Bool isOn; 763f29dbc25Smrg}; 764f29dbc25Smrg 765f29dbc25Smrgstatic int 766f29dbc25SmrgLXDisplaySurface(XF86SurfacePtr surface, 76704007ebaSmrg short srcX, short srcY, short drawX, short drawY, 76804007ebaSmrg short srcW, short srcH, short drawW, short drawH, 76904007ebaSmrg RegionPtr clipBoxes) 770f29dbc25Smrg{ 771f29dbc25Smrg struct OffscreenPrivRec *pPriv = 77204007ebaSmrg (struct OffscreenPrivRec *) surface->devPrivate.ptr; 773f29dbc25Smrg 774f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 775f29dbc25Smrg GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni); 776f29dbc25Smrg 777f29dbc25Smrg BoxRec dstBox; 778f29dbc25Smrg 779f29dbc25Smrg dstBox.x1 = drawX; 780f29dbc25Smrg dstBox.x2 = drawX + drawW; 781f29dbc25Smrg dstBox.y1 = drawY; 782f29dbc25Smrg dstBox.y2 = drawY + drawH; 783f29dbc25Smrg 784f29dbc25Smrg if ((drawW <= 0) | (drawH <= 0)) 78504007ebaSmrg return Success; 786f29dbc25Smrg 787f29dbc25Smrg /* Is this still valid? */ 788f29dbc25Smrg 789f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 790f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 791f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 792f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 793f29dbc25Smrg 794f29dbc25Smrg xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes); 795f29dbc25Smrg 796f29dbc25Smrg videoScratch.dstOffset = surface->offsets[0]; 797f29dbc25Smrg videoScratch.dstPitch = surface->pitches[0]; 798f29dbc25Smrg 799f29dbc25Smrg LXDisplayVideo(pScrni, surface->id, surface->width, surface->height, 80004007ebaSmrg &dstBox, srcW, srcH, drawW, drawH); 801f29dbc25Smrg 802f29dbc25Smrg pPriv->isOn = TRUE; 803f29dbc25Smrg 804f29dbc25Smrg if (portPriv->videoStatus & CLIENT_VIDEO_ON) { 80504007ebaSmrg REGION_EMPTY(pScrni->pScreen, &portPriv->clip); 80604007ebaSmrg UpdateCurrentTime(); 80704007ebaSmrg portPriv->videoStatus = FREE_TIMER; 80804007ebaSmrg portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 809f29dbc25Smrg } 810f29dbc25Smrg 811f29dbc25Smrg return Success; 812f29dbc25Smrg} 813f29dbc25Smrg 814f29dbc25Smrgstatic int 815f29dbc25SmrgLXAllocateSurface(ScrnInfoPtr pScrni, int id, unsigned short w, 81604007ebaSmrg unsigned short h, XF86SurfacePtr surface) 817f29dbc25Smrg{ 818f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 819f29dbc25Smrg int pitch, lines; 820170d5fdcSmrg ExaOffscreenArea *vidmem; 821f29dbc25Smrg struct OffscreenPrivRec *pPriv; 822f29dbc25Smrg 823f29dbc25Smrg if (w > 1024 || h > 1024) 82404007ebaSmrg return BadAlloc; 825f29dbc25Smrg 826f29dbc25Smrg /* The width needs to be word aligned */ 827f29dbc25Smrg w = (w + 1) & ~1; 828f29dbc25Smrg 829f29dbc25Smrg pitch = ((w << 1) + 15) & ~15; 830f29dbc25Smrg lines = ((pitch * h) + (pGeode->Pitch - 1)) / pGeode->Pitch; 831f29dbc25Smrg 8327aef237fSmrg /* FIXME: is lines the right parameter to use here, 8337aef237fSmrg * or should it be height * pitch? */ 83404007ebaSmrg vidmem = exaOffscreenAlloc(pScrni->pScreen, lines, 4, TRUE, NULL, NULL); 835f29dbc25Smrg 836f29dbc25Smrg if (vidmem == NULL) { 83704007ebaSmrg ErrorF("Error while allocating an offscreen region.\n"); 83804007ebaSmrg return BadAlloc; 839f29dbc25Smrg } 840f29dbc25Smrg 841f29dbc25Smrg surface->width = w; 842f29dbc25Smrg surface->height = h; 843f29dbc25Smrg 844170d5fdcSmrg surface->pitches = malloc(sizeof(int)); 845f29dbc25Smrg 846170d5fdcSmrg surface->offsets = malloc(sizeof(int)); 847f29dbc25Smrg 848170d5fdcSmrg pPriv = malloc(sizeof(struct OffscreenPrivRec)); 849f29dbc25Smrg 850f29dbc25Smrg if (pPriv && surface->pitches && surface->offsets) { 851f29dbc25Smrg 85204007ebaSmrg pPriv->vidmem = vidmem; 853f29dbc25Smrg 85404007ebaSmrg pPriv->isOn = FALSE; 855f29dbc25Smrg 85604007ebaSmrg surface->pScrn = pScrni; 85704007ebaSmrg surface->id = id; 85804007ebaSmrg surface->pitches[0] = pitch; 85904007ebaSmrg surface->offsets[0] = vidmem->offset; 86004007ebaSmrg surface->devPrivate.ptr = (pointer) pPriv; 861f29dbc25Smrg 86204007ebaSmrg return Success; 863f29dbc25Smrg } 864f29dbc25Smrg 865f29dbc25Smrg if (surface->offsets) 86604007ebaSmrg free(surface->offsets); 867f29dbc25Smrg 868f29dbc25Smrg if (surface->pitches) 86904007ebaSmrg free(surface->pitches); 870f29dbc25Smrg 871170d5fdcSmrg if (vidmem) { 87204007ebaSmrg exaOffscreenFree(pScrni->pScreen, vidmem); 87304007ebaSmrg vidmem = NULL; 874170d5fdcSmrg } 875f29dbc25Smrg 876f29dbc25Smrg return BadAlloc; 877f29dbc25Smrg} 878f29dbc25Smrg 879f29dbc25Smrgstatic int 880f29dbc25SmrgLXStopSurface(XF86SurfacePtr surface) 881f29dbc25Smrg{ 882f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 88304007ebaSmrg surface->devPrivate.ptr; 884f29dbc25Smrg 885f29dbc25Smrg pPriv->isOn = FALSE; 886f29dbc25Smrg return Success; 887f29dbc25Smrg} 888f29dbc25Smrg 889f29dbc25Smrgstatic int 890f29dbc25SmrgLXFreeSurface(XF86SurfacePtr surface) 891f29dbc25Smrg{ 892f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 89304007ebaSmrg surface->devPrivate.ptr; 894f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 895f29dbc25Smrg 896f29dbc25Smrg if (pPriv->isOn) 89704007ebaSmrg LXStopSurface(surface); 898f29dbc25Smrg 899f29dbc25Smrg if (pPriv->vidmem) { 90004007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 90104007ebaSmrg pPriv->vidmem = NULL; 902f29dbc25Smrg } 903f29dbc25Smrg 904170d5fdcSmrg free(surface->pitches); 905170d5fdcSmrg free(surface->offsets); 906170d5fdcSmrg free(surface->devPrivate.ptr); 907f29dbc25Smrg 908f29dbc25Smrg return Success; 909f29dbc25Smrg} 910f29dbc25Smrg 911f29dbc25Smrgstatic int 91204007ebaSmrgLXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 *value) 913f29dbc25Smrg{ 914f29dbc25Smrg return LXGetPortAttribute(pScrni, attribute, value, 91504007ebaSmrg (pointer) (GET_PORT_PRIVATE(pScrni))); 916f29dbc25Smrg} 917f29dbc25Smrg 918f29dbc25Smrgstatic int 919f29dbc25SmrgLXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value) 920f29dbc25Smrg{ 921f29dbc25Smrg return LXSetPortAttribute(pScrni, attribute, value, 92204007ebaSmrg (pointer) (GET_PORT_PRIVATE(pScrni))); 923f29dbc25Smrg} 924f29dbc25Smrg 925f29dbc25Smrgstatic void 926f29dbc25SmrgLXInitOffscreenImages(ScreenPtr pScrn) 927f29dbc25Smrg{ 928f29dbc25Smrg XF86OffscreenImagePtr offscreenImages; 929f29dbc25Smrg 930f29dbc25Smrg /* need to free this someplace */ 931170d5fdcSmrg if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 93204007ebaSmrg return; 933f29dbc25Smrg 934f29dbc25Smrg offscreenImages[0].image = &Images[0]; 935f29dbc25Smrg offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 936f29dbc25Smrg offscreenImages[0].alloc_surface = LXAllocateSurface; 937f29dbc25Smrg offscreenImages[0].free_surface = LXFreeSurface; 938f29dbc25Smrg offscreenImages[0].display = LXDisplaySurface; 939f29dbc25Smrg offscreenImages[0].stop = LXStopSurface; 940f29dbc25Smrg offscreenImages[0].setAttribute = LXSetSurfaceAttribute; 941f29dbc25Smrg offscreenImages[0].getAttribute = LXGetSurfaceAttribute; 942f29dbc25Smrg offscreenImages[0].max_width = 1024; 943f29dbc25Smrg offscreenImages[0].max_height = 1024; 944f29dbc25Smrg offscreenImages[0].num_attributes = ARRAY_SIZE(Attributes); 945f29dbc25Smrg offscreenImages[0].attributes = Attributes; 946f29dbc25Smrg 947f29dbc25Smrg xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1); 948f29dbc25Smrg} 949f29dbc25Smrg 950f29dbc25Smrgvoid 951f29dbc25SmrgLXInitVideo(ScreenPtr pScrn) 952f29dbc25Smrg{ 953f29dbc25Smrg GeodeRec *pGeode; 95404007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 955f29dbc25Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 956f29dbc25Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 957f29dbc25Smrg int num_adaptors; 958f29dbc25Smrg 959f29dbc25Smrg pGeode = GEODEPTR(pScrni); 960f29dbc25Smrg 961f29dbc25Smrg if (pGeode->NoAccel) { 96204007ebaSmrg ErrorF("Cannot run Xv without accelerations!\n"); 96304007ebaSmrg return; 964f29dbc25Smrg } 965f29dbc25Smrg 966f29dbc25Smrg if (!(newAdaptor = LXSetupImageVideo(pScrn))) { 96704007ebaSmrg ErrorF("Error while setting up the adaptor.\n"); 96804007ebaSmrg return; 969f29dbc25Smrg } 970f29dbc25Smrg 971f29dbc25Smrg LXInitOffscreenImages(pScrn); 972f29dbc25Smrg 973f29dbc25Smrg num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors); 974f29dbc25Smrg 975f29dbc25Smrg if (!num_adaptors) { 97604007ebaSmrg num_adaptors = 1; 97704007ebaSmrg adaptors = &newAdaptor; 97804007ebaSmrg } 97904007ebaSmrg else { 98004007ebaSmrg newAdaptors = 98104007ebaSmrg malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); 98204007ebaSmrg 98304007ebaSmrg if (newAdaptors) { 98404007ebaSmrg memcpy(newAdaptors, adaptors, num_adaptors * 98504007ebaSmrg sizeof(XF86VideoAdaptorPtr)); 98604007ebaSmrg newAdaptors[num_adaptors] = newAdaptor; 98704007ebaSmrg adaptors = newAdaptors; 98804007ebaSmrg num_adaptors++; 98904007ebaSmrg } 99004007ebaSmrg else 99104007ebaSmrg ErrorF("Memory error while setting up the adaptor\n"); 992f29dbc25Smrg } 993f29dbc25Smrg 994f29dbc25Smrg if (num_adaptors) 99504007ebaSmrg xf86XVScreenInit(pScrn, adaptors, num_adaptors); 996f29dbc25Smrg 997f29dbc25Smrg if (newAdaptors) 99804007ebaSmrg free(newAdaptors); 999f29dbc25Smrg} 1000