lx_video.c revision 04007eba
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 39f29dbc25Smrg#include "xf86.h" 40f29dbc25Smrg#include "xf86_OSproc.h" 41f29dbc25Smrg#include "compiler.h" 42f29dbc25Smrg#include "xf86PciInfo.h" 43f29dbc25Smrg#include "xf86Pci.h" 44f29dbc25Smrg#include "xf86fbman.h" 45f29dbc25Smrg#include "regionstr.h" 46f29dbc25Smrg#include "dixstruct.h" 47f29dbc25Smrg 48f29dbc25Smrg#include "geode.h" 49f29dbc25Smrg#include "xf86xv.h" 50f29dbc25Smrg#include <X11/extensions/Xv.h> 51f29dbc25Smrg#include "fourcc.h" 52f29dbc25Smrg#include "geode_fourcc.h" 53f29dbc25Smrg#include "cim/cim_defs.h" 54f29dbc25Smrg#include "cim/cim_regs.h" 55f29dbc25Smrg 56f29dbc25Smrg#define OFF_DELAY 200 57f29dbc25Smrg#define FREE_DELAY 60000 58f29dbc25Smrg#define OFF_TIMER 0x01 59f29dbc25Smrg#define FREE_TIMER 0x02 60f29dbc25Smrg#define CLIENT_VIDEO_ON 0x04 61f29dbc25Smrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 62f29dbc25Smrg 63f29dbc25Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 6404007ebaSmrg#ifndef ARRAY_SIZE 65f29dbc25Smrg#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a)))) 6604007ebaSmrg#endif 67f29dbc25Smrg 68f29dbc25Smrg/* Local function prototypes */ 69f29dbc25Smrgstatic void LXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit); 70f29dbc25Smrg 71f29dbc25Smrgstatic void 7204007ebaSmrg 7304007ebaSmrg 74f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 7504007ebaSmrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH); 76f29dbc25Smrg 77f29dbc25Smrgstatic void LXResetVideo(ScrnInfoPtr pScrni); 78f29dbc25Smrg 79f29dbc25Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = { 80f29dbc25Smrg {0, "XV_IMAGE", 1024, 1024, {1, 1}} 81f29dbc25Smrg}; 82f29dbc25Smrg 83f29dbc25Smrgstatic XF86VideoFormatRec Formats[] = { 84f29dbc25Smrg {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 85f29dbc25Smrg}; 86f29dbc25Smrg 87f29dbc25Smrgstatic XF86AttributeRec Attributes[] = { 88f29dbc25Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 89f29dbc25Smrg {XvSettable | XvGettable, 0, 1, "XV_FILTER"}, 90f29dbc25Smrg {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"} 91f29dbc25Smrg}; 92f29dbc25Smrg 93f29dbc25Smrgstatic XF86ImageRec Images[] = { 94f29dbc25Smrg XVIMAGE_UYVY, 95f29dbc25Smrg XVIMAGE_YUY2, 96f29dbc25Smrg XVIMAGE_Y2YU, 97f29dbc25Smrg XVIMAGE_YVYU, 98f29dbc25Smrg XVIMAGE_Y800, 99f29dbc25Smrg XVIMAGE_I420, 100f29dbc25Smrg XVIMAGE_YV12, 101f29dbc25Smrg XVIMAGE_RGB565 102f29dbc25Smrg}; 103f29dbc25Smrg 10404007ebaSmrgtypedef struct { 105170d5fdcSmrg ExaOffscreenArea *vidmem; 106f29dbc25Smrg RegionRec clip; 107f29dbc25Smrg CARD32 filter; 108f29dbc25Smrg CARD32 colorKey; 109f29dbc25Smrg CARD32 colorKeyMode; 110f29dbc25Smrg CARD32 videoStatus; 111f29dbc25Smrg Time offTime; 112f29dbc25Smrg Time freeTime; 113f29dbc25Smrg short pwidth, pheight; 114f29dbc25Smrg} GeodePortPrivRec, *GeodePortPrivPtr; 115f29dbc25Smrg 116f29dbc25Smrg#define GET_PORT_PRIVATE(pScrni) \ 117f29dbc25Smrg (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr) 118f29dbc25Smrg 119f29dbc25Smrgstatic void 120f29dbc25SmrgLXCopyFromSys(GeodeRec * pGeode, unsigned char *src, unsigned int dst, 12104007ebaSmrg int dstPitch, int srcPitch, int h, int w) 122f29dbc25Smrg{ 123f29dbc25Smrg 124f29dbc25Smrg gp_declare_blt(0); 125170d5fdcSmrg gp_set_bpp((srcPitch / w) << 3); 126f29dbc25Smrg 127f29dbc25Smrg gp_set_raster_operation(0xCC); 128f29dbc25Smrg gp_set_strides(dstPitch, srcPitch); 129f29dbc25Smrg gp_set_solid_pattern(0); 130f29dbc25Smrg 131f29dbc25Smrg gp_color_bitmap_to_screen_blt(dst, 0, w, h, src, srcPitch); 132f29dbc25Smrg} 133f29dbc25Smrg 134f29dbc25Smrgstatic void 135f29dbc25SmrgLXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv) 136f29dbc25Smrg{ 137f29dbc25Smrg int red, green, blue; 138f29dbc25Smrg unsigned long key; 139f29dbc25Smrg 140f29dbc25Smrg switch (pScrni->depth) { 141f29dbc25Smrg case 8: 14204007ebaSmrg vg_get_display_palette_entry(pPriv->colorKey & 0xFF, &key); 14304007ebaSmrg red = ((key >> 16) & 0xFF); 14404007ebaSmrg green = ((key >> 8) & 0xFF); 14504007ebaSmrg blue = (key & 0xFF); 14604007ebaSmrg break; 147f29dbc25Smrg case 16: 14804007ebaSmrg red = (pPriv->colorKey & pScrni->mask.red) >> 14904007ebaSmrg pScrni->offset.red << (8 - pScrni->weight.red); 15004007ebaSmrg green = (pPriv->colorKey & pScrni->mask.green) >> 15104007ebaSmrg pScrni->offset.green << (8 - pScrni->weight.green); 15204007ebaSmrg blue = (pPriv->colorKey & pScrni->mask.blue) >> 15304007ebaSmrg pScrni->offset.blue << (8 - pScrni->weight.blue); 15404007ebaSmrg break; 155f29dbc25Smrg default: 15604007ebaSmrg /* for > 16 bpp we send in the mask in xf86SetWeight. This 15704007ebaSmrg * function is providing the offset by 1 more. So we take 15804007ebaSmrg * this as a special case and subtract 1 for > 16 15904007ebaSmrg */ 16004007ebaSmrg 16104007ebaSmrg red = (pPriv->colorKey & pScrni->mask.red) >> 16204007ebaSmrg (pScrni->offset.red - 1) << (8 - pScrni->weight.red); 16304007ebaSmrg green = (pPriv->colorKey & pScrni->mask.green) >> 16404007ebaSmrg (pScrni->offset.green - 1) << (8 - pScrni->weight.green); 16504007ebaSmrg blue = (pPriv->colorKey & pScrni->mask.blue) >> 16604007ebaSmrg (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue); 16704007ebaSmrg break; 168f29dbc25Smrg } 169f29dbc25Smrg 170f29dbc25Smrg df_set_video_color_key((blue | (green << 8) | (red << 16)), 17104007ebaSmrg 0xFFFFFF, (pPriv->colorKeyMode == 0)); 172f29dbc25Smrg 173f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 174f29dbc25Smrg} 175f29dbc25Smrg 176f29dbc25Smrg/* A structure full of the scratch information that originates in the copy routines, 177f29dbc25Smrg but is needed for the video display - maybe we should figure out a way to attach 178f29dbc25Smrg this to structures? I hate to put it in pGeode since it will increase the size of 179f29dbc25Smrg the structure, and possibly cause us cache issues. 180f29dbc25Smrg*/ 181f29dbc25Smrg 18204007ebaSmrgstruct { 183f29dbc25Smrg unsigned int dstOffset; 184f29dbc25Smrg unsigned int dstPitch; 185f29dbc25Smrg unsigned int UVPitch; 186f29dbc25Smrg unsigned int UDstOffset; 187f29dbc25Smrg unsigned int VDstOffset; 188f29dbc25Smrg} videoScratch; 189f29dbc25Smrg 190f29dbc25Smrg/* Copy planar YUV data */ 191f29dbc25Smrg 192f29dbc25Smrgstatic Bool 19304007ebaSmrgLXAllocateVidMem(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv, int size) 194f29dbc25Smrg{ 19504007ebaSmrg if (!pPriv->vidmem || pPriv->vidmem->size < size) { 19604007ebaSmrg if (pPriv->vidmem) { 19704007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 19804007ebaSmrg pPriv->vidmem = NULL; 19904007ebaSmrg } 20004007ebaSmrg 20104007ebaSmrg pPriv->vidmem = exaOffscreenAlloc(pScrni->pScreen, size, 4, 20204007ebaSmrg TRUE, NULL, NULL); 20304007ebaSmrg 20404007ebaSmrg if (pPriv->vidmem == NULL) { 20504007ebaSmrg ErrorF("Could not allocate memory for the video\n"); 20604007ebaSmrg return FALSE; 20704007ebaSmrg } 208f29dbc25Smrg } 209f29dbc25Smrg 210f29dbc25Smrg return TRUE; 21104007ebaSmrg} 212f29dbc25Smrg 213f29dbc25Smrgstatic Bool 214f29dbc25SmrgLXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, 21504007ebaSmrg short x1, short y1, short x2, short y2, 21604007ebaSmrg int width, int height, pointer data) 217f29dbc25Smrg{ 218f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 219f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 220f29dbc25Smrg 221f29dbc25Smrg unsigned int YSrcPitch, YDstPitch; 222f29dbc25Smrg unsigned int UVSrcPitch, UVDstPitch; 223f29dbc25Smrg unsigned int YSrcOffset, YDstOffset; 224f29dbc25Smrg unsigned int USrcOffset, UDstOffset; 225f29dbc25Smrg unsigned int VSrcOffset, VDstOffset; 226f29dbc25Smrg 227f29dbc25Smrg unsigned int size, lines, top, left, pixels; 228f29dbc25Smrg 229f29dbc25Smrg YSrcPitch = (width + 3) & ~3; 230f29dbc25Smrg YDstPitch = (width + 31) & ~31; 231f29dbc25Smrg 232f29dbc25Smrg UVSrcPitch = ((width >> 1) + 3) & ~3; 233f29dbc25Smrg UVDstPitch = ((width >> 1) + 15) & ~15; 234f29dbc25Smrg 235f29dbc25Smrg USrcOffset = YSrcPitch * height; 236f29dbc25Smrg VSrcOffset = USrcOffset + (UVSrcPitch * (height >> 1)); 237f29dbc25Smrg 238f29dbc25Smrg UDstOffset = YDstPitch * height; 239f29dbc25Smrg VDstOffset = UDstOffset + (UVDstPitch * (height >> 1)); 240f29dbc25Smrg 241f29dbc25Smrg size = YDstPitch * height; 242f29dbc25Smrg size += UVDstPitch * height; 243f29dbc25Smrg 244170d5fdcSmrg if (LXAllocateVidMem(pScrni, pPriv, size) == FALSE) { 24504007ebaSmrg ErrorF("Error allocating an offscreen Planar region.\n"); 24604007ebaSmrg return FALSE; 247170d5fdcSmrg } 248f29dbc25Smrg 249f29dbc25Smrg /* The top of the source region we want to copy */ 250f29dbc25Smrg top = y1 & ~1; 251f29dbc25Smrg 252f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 253f29dbc25Smrg left = x1 & ~1; 254f29dbc25Smrg 255f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 256f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 257f29dbc25Smrg 258f29dbc25Smrg /* Calculate the source offset */ 259f29dbc25Smrg YSrcOffset = (top * YSrcPitch) + left; 260f29dbc25Smrg USrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 261f29dbc25Smrg VSrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 262f29dbc25Smrg 263f29dbc25Smrg /* Calculate the destination offset */ 264f29dbc25Smrg YDstOffset = (top * YDstPitch) + left; 265f29dbc25Smrg UDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 266f29dbc25Smrg VDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 267f29dbc25Smrg 268f29dbc25Smrg lines = ((y2 + 1) & ~1) - top; 269f29dbc25Smrg 270f29dbc25Smrg /* Copy Y */ 271f29dbc25Smrg 272f29dbc25Smrg LXCopyFromSys(pGeode, buf + YSrcOffset, 27304007ebaSmrg pPriv->vidmem->offset + YDstOffset, YDstPitch, YSrcPitch, 27404007ebaSmrg lines, pixels); 275f29dbc25Smrg 276f29dbc25Smrg /* Copy U + V at the same time */ 277f29dbc25Smrg 278f29dbc25Smrg LXCopyFromSys(pGeode, buf + USrcOffset, 27904007ebaSmrg pPriv->vidmem->offset + UDstOffset, UVDstPitch, UVSrcPitch, 28004007ebaSmrg lines, pixels >> 1); 281f29dbc25Smrg 282f29dbc25Smrg videoScratch.dstOffset = pPriv->vidmem->offset + YDstOffset; 283f29dbc25Smrg videoScratch.dstPitch = YDstPitch; 284f29dbc25Smrg videoScratch.UVPitch = UVDstPitch; 285f29dbc25Smrg videoScratch.UDstOffset = pPriv->vidmem->offset + UDstOffset; 286f29dbc25Smrg videoScratch.VDstOffset = pPriv->vidmem->offset + VDstOffset; 287f29dbc25Smrg 288f29dbc25Smrg return TRUE; 289f29dbc25Smrg} 290f29dbc25Smrg 291f29dbc25Smrgstatic Bool 292f29dbc25SmrgLXCopyPacked(ScrnInfoPtr pScrni, int id, unsigned char *buf, 29304007ebaSmrg short x1, short y1, short x2, short y2, 29404007ebaSmrg int width, int height, pointer data) 295f29dbc25Smrg{ 296f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 297f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 298f29dbc25Smrg unsigned int dstPitch, srcPitch; 299f29dbc25Smrg unsigned int srcOffset, dstOffset; 300f29dbc25Smrg unsigned int lines, top, left, pixels; 301f29dbc25Smrg 302f29dbc25Smrg dstPitch = ((width << 1) + 3) & ~3; 303f29dbc25Smrg srcPitch = (width << 1); 304f29dbc25Smrg 305f29dbc25Smrg lines = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch; 306f29dbc25Smrg 3077aef237fSmrg if (LXAllocateVidMem(pScrni, pPriv, dstPitch * height) == FALSE) { 30804007ebaSmrg ErrorF("Error allocating an offscreen Packed region.\n"); 30904007ebaSmrg return FALSE; 310170d5fdcSmrg } 311f29dbc25Smrg 312f29dbc25Smrg /* The top of the source region we want to copy */ 313f29dbc25Smrg top = y1; 314f29dbc25Smrg 315f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 316f29dbc25Smrg left = x1 & ~1; 317f29dbc25Smrg 318f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 319f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 320f29dbc25Smrg 321f29dbc25Smrg /* Adjust the incoming buffer */ 322f29dbc25Smrg srcOffset = (top * srcPitch) + left; 323f29dbc25Smrg 324f29dbc25Smrg /* Calculate the destination offset */ 325f29dbc25Smrg dstOffset = pPriv->vidmem->offset + (top * dstPitch) + left; 326f29dbc25Smrg 327f29dbc25Smrg /* Make the copy happen */ 328f29dbc25Smrg 329f29dbc25Smrg if (id == FOURCC_Y800) { 330f29dbc25Smrg 33104007ebaSmrg /* Use the shared (unaccelerated) greyscale copy - you could probably 33204007ebaSmrg * accelerate it using a 2 pass blit and patterns, but it doesn't really 33304007ebaSmrg * seem worth it 33404007ebaSmrg */ 335f29dbc25Smrg 33604007ebaSmrg GeodeCopyGreyscale(buf + srcOffset, pGeode->FBBase + dstOffset, 33704007ebaSmrg srcPitch, dstPitch, height, pixels >> 1); 33804007ebaSmrg } 33904007ebaSmrg else 34004007ebaSmrg /* FIXME: should lines be used here instead of height? */ 34104007ebaSmrg LXCopyFromSys(pGeode, buf + srcOffset, dstOffset, dstPitch, srcPitch, 34204007ebaSmrg height, pixels); 343f29dbc25Smrg 344f29dbc25Smrg videoScratch.dstOffset = dstOffset; 345f29dbc25Smrg videoScratch.dstPitch = dstPitch; 346f29dbc25Smrg 347f29dbc25Smrg return TRUE; 348f29dbc25Smrg} 349f29dbc25Smrg 350f29dbc25Smrgstatic void 351f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 35204007ebaSmrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH) 353f29dbc25Smrg{ 354f29dbc25Smrg long ystart, xend, yend; 355f29dbc25Smrg unsigned long lines = 0; 356f29dbc25Smrg unsigned long yExtra, uvExtra = 0; 357f29dbc25Smrg DF_VIDEO_POSITION vidPos; 358f29dbc25Smrg DF_VIDEO_SOURCE_PARAMS vSrcParams; 359f29dbc25Smrg int err; 360f29dbc25Smrg 361f29dbc25Smrg memset(&vSrcParams, 0, sizeof(vSrcParams)); 362f29dbc25Smrg 363f29dbc25Smrg gp_wait_until_idle(); 364f29dbc25Smrg 365f29dbc25Smrg switch (id) { 366f29dbc25Smrg case FOURCC_UYVY: 36704007ebaSmrg vSrcParams.video_format = DF_VIDFMT_UYVY; 36804007ebaSmrg break; 369f29dbc25Smrg 370f29dbc25Smrg case FOURCC_Y800: 371f29dbc25Smrg case FOURCC_YV12: 372f29dbc25Smrg case FOURCC_I420: 37304007ebaSmrg vSrcParams.video_format = DF_VIDFMT_Y0Y1Y2Y3; 37404007ebaSmrg break; 375f29dbc25Smrg case FOURCC_YUY2: 37604007ebaSmrg vSrcParams.video_format = DF_VIDFMT_YUYV; 37704007ebaSmrg break; 378f29dbc25Smrg case FOURCC_Y2YU: 37904007ebaSmrg vSrcParams.video_format = DF_VIDFMT_Y2YU; 38004007ebaSmrg break; 381f29dbc25Smrg case FOURCC_YVYU: 38204007ebaSmrg vSrcParams.video_format = DF_VIDFMT_YVYU; 38304007ebaSmrg break; 384f29dbc25Smrg case FOURCC_RGB565: 38504007ebaSmrg vSrcParams.video_format = DF_VIDFMT_RGB; 38604007ebaSmrg break; 387f29dbc25Smrg } 388f29dbc25Smrg 389f29dbc25Smrg vSrcParams.width = width; 390f29dbc25Smrg vSrcParams.height = height; 391f29dbc25Smrg vSrcParams.y_pitch = videoScratch.dstPitch; 392f29dbc25Smrg vSrcParams.uv_pitch = videoScratch.UVPitch; 393f29dbc25Smrg 394f29dbc25Smrg /* Set up scaling */ 395f29dbc25Smrg df_set_video_filter_coefficients(NULL, 1); 396f29dbc25Smrg 397f29dbc25Smrg err = df_set_video_scale(width, height, drawW, drawH, 39804007ebaSmrg DF_SCALEFLAG_CHANGEX | DF_SCALEFLAG_CHANGEY); 399f29dbc25Smrg if (err != CIM_STATUS_OK) { 40004007ebaSmrg /* Note the problem, but do nothing for now. */ 40104007ebaSmrg ErrorF("Video scale factor too large: %dx%d -> %dx%d\n", 40204007ebaSmrg width, height, drawW, drawH); 403f29dbc25Smrg } 404f29dbc25Smrg 405f29dbc25Smrg /* Figure out clipping */ 406f29dbc25Smrg 407f29dbc25Smrg xend = dstBox->x2; 408f29dbc25Smrg yend = dstBox->y2; 409f29dbc25Smrg 410f29dbc25Smrg if (dstBox->y1 < 0) { 41104007ebaSmrg if (srcH < drawH) 41204007ebaSmrg lines = ((-dstBox->y1) * srcH) / drawH; 41304007ebaSmrg else 41404007ebaSmrg lines = (-dstBox->y1); 41504007ebaSmrg 41604007ebaSmrg ystart = 0; 41704007ebaSmrg drawH += dstBox->y1; 41804007ebaSmrg } 41904007ebaSmrg else { 42004007ebaSmrg ystart = dstBox->y1; 42104007ebaSmrg lines = 0; 422f29dbc25Smrg } 423f29dbc25Smrg 424f29dbc25Smrg yExtra = lines * videoScratch.dstPitch; 425f29dbc25Smrg uvExtra = (lines >> 1) * videoScratch.UVPitch; 426f29dbc25Smrg 427f29dbc25Smrg memset(&vidPos, 0, sizeof(vidPos)); 428f29dbc25Smrg 429f29dbc25Smrg vidPos.x = dstBox->x1; 430f29dbc25Smrg vidPos.y = ystart; 431f29dbc25Smrg vidPos.width = xend - dstBox->x1; 432f29dbc25Smrg vidPos.height = yend - ystart; 433f29dbc25Smrg 434f29dbc25Smrg df_set_video_position(&vidPos); 435f29dbc25Smrg 436f29dbc25Smrg vSrcParams.y_offset = videoScratch.dstOffset + yExtra; 437f29dbc25Smrg 438f29dbc25Smrg switch (id) { 439f29dbc25Smrg case FOURCC_Y800: 440f29dbc25Smrg case FOURCC_I420: 44104007ebaSmrg vSrcParams.u_offset = videoScratch.UDstOffset + uvExtra; 44204007ebaSmrg vSrcParams.v_offset = videoScratch.VDstOffset + uvExtra; 44304007ebaSmrg break; 444f29dbc25Smrg case FOURCC_YV12: 44504007ebaSmrg vSrcParams.v_offset = videoScratch.UDstOffset + uvExtra; 44604007ebaSmrg vSrcParams.u_offset = videoScratch.VDstOffset + uvExtra; 44704007ebaSmrg break; 448f29dbc25Smrg 449f29dbc25Smrg default: 45004007ebaSmrg vSrcParams.u_offset = vSrcParams.v_offset = 0; 45104007ebaSmrg break; 452f29dbc25Smrg } 453f29dbc25Smrg 454f29dbc25Smrg vSrcParams.flags = DF_SOURCEFLAG_IMPLICITSCALING; 455f29dbc25Smrg df_configure_video_source(&vSrcParams, &vSrcParams); 456f29dbc25Smrg 457f29dbc25Smrg /* Turn on the video palette */ 458f29dbc25Smrg df_set_video_palette(NULL); 459f29dbc25Smrg df_set_video_enable(1, 0); 460f29dbc25Smrg} 461f29dbc25Smrg 462f29dbc25Smrgstatic int 463f29dbc25SmrgLXPutImage(ScrnInfoPtr pScrni, 46404007ebaSmrg short srcX, short srcY, short drawX, short drawY, 46504007ebaSmrg short srcW, short srcH, short drawW, short drawH, 46604007ebaSmrg int id, unsigned char *buf, 46704007ebaSmrg short width, short height, Bool sync, RegionPtr clipBoxes, 46804007ebaSmrg pointer data, DrawablePtr pDraw) 469f29dbc25Smrg{ 470f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 471f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 472f29dbc25Smrg INT32 x1, x2, y1, y2; 473f29dbc25Smrg BoxRec dstBox; 474f29dbc25Smrg Bool ret; 475f29dbc25Smrg 476f29dbc25Smrg if (pGeode->rotation != RR_Rotate_0) 47704007ebaSmrg return Success; 478f29dbc25Smrg 479f29dbc25Smrg if (srcW <= 0 || srcH <= 0) { 48004007ebaSmrg return Success; 481f29dbc25Smrg } 482f29dbc25Smrg 483f29dbc25Smrg if (drawW <= 0 || drawH <= 0) { 48404007ebaSmrg return Success; 485f29dbc25Smrg } 486f29dbc25Smrg 487f29dbc25Smrg if (drawW > 16384) 48804007ebaSmrg drawW = 16384; 489f29dbc25Smrg 490f29dbc25Smrg memset(&videoScratch, 0, sizeof(videoScratch)); 491f29dbc25Smrg 492f29dbc25Smrg x1 = srcX; 493f29dbc25Smrg x2 = srcX + srcW; 494f29dbc25Smrg y1 = srcY; 495f29dbc25Smrg y2 = srcY + srcH; 496f29dbc25Smrg 497f29dbc25Smrg dstBox.x1 = drawX; 498f29dbc25Smrg dstBox.x2 = drawX + drawW; 499f29dbc25Smrg dstBox.y1 = drawY; 500f29dbc25Smrg dstBox.y2 = drawY + drawH; 501f29dbc25Smrg 502f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 503f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 504f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 505f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 506f29dbc25Smrg 507f29dbc25Smrg if (id == FOURCC_YV12 || id == FOURCC_I420) 50804007ebaSmrg ret = LXCopyPlanar(pScrni, id, buf, x1, y1, x2, y2, width, 50904007ebaSmrg height, data); 510f29dbc25Smrg else 51104007ebaSmrg ret = LXCopyPacked(pScrni, id, buf, x1, y1, x2, y2, width, 51204007ebaSmrg height, data); 513f29dbc25Smrg 514f29dbc25Smrg if (ret == FALSE) 51504007ebaSmrg return BadAlloc; 51604007ebaSmrg 517f29dbc25Smrg if (!RegionsEqual(&pPriv->clip, clipBoxes) || 51804007ebaSmrg (drawW != pPriv->pwidth || drawH != pPriv->pheight)) { 51904007ebaSmrg REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes); 520f29dbc25Smrg 52104007ebaSmrg if (pPriv->colorKeyMode == 0) { 52204007ebaSmrg xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes); 52304007ebaSmrg } 524f29dbc25Smrg 52504007ebaSmrg LXDisplayVideo(pScrni, id, width, height, &dstBox, 52604007ebaSmrg srcW, srcH, drawW, drawH); 52704007ebaSmrg pPriv->pwidth = drawW; 52804007ebaSmrg pPriv->pheight = drawH; 529f29dbc25Smrg } 530f29dbc25Smrg 531f29dbc25Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 532f29dbc25Smrg 533f29dbc25Smrg return Success; 534f29dbc25Smrg} 535f29dbc25Smrg 536f29dbc25Smrgstatic void 537f29dbc25SmrgLXQueryBestSize(ScrnInfoPtr pScrni, Bool motion, 53804007ebaSmrg short vidW, short vidH, short drawW, short drawH, 53904007ebaSmrg unsigned int *retW, unsigned int *retH, pointer data) 540f29dbc25Smrg{ 541f29dbc25Smrg *retW = drawW > 16384 ? 16384 : drawW; 542f29dbc25Smrg *retH = drawH; 543f29dbc25Smrg} 544f29dbc25Smrg 545f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter; 546f29dbc25Smrg 547f29dbc25Smrgstatic int 548f29dbc25SmrgLXGetPortAttribute(ScrnInfoPtr pScrni, 54904007ebaSmrg Atom attribute, INT32 *value, pointer data) 550f29dbc25Smrg{ 551f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 552f29dbc25Smrg 553f29dbc25Smrg if (attribute == xvColorKey) 55404007ebaSmrg *value = pPriv->colorKey; 555f29dbc25Smrg else if (attribute == xvColorKeyMode) 55604007ebaSmrg *value = pPriv->colorKeyMode; 557f29dbc25Smrg else if (attribute == xvFilter) 55804007ebaSmrg *value = pPriv->filter; 559f29dbc25Smrg else 56004007ebaSmrg return BadMatch; 561f29dbc25Smrg 562f29dbc25Smrg return Success; 563f29dbc25Smrg} 564f29dbc25Smrg 565f29dbc25Smrgstatic int 566f29dbc25SmrgLXSetPortAttribute(ScrnInfoPtr pScrni, 56704007ebaSmrg Atom attribute, INT32 value, pointer data) 568f29dbc25Smrg{ 569f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 570f29dbc25Smrg 571f29dbc25Smrg gp_wait_until_idle(); 572f29dbc25Smrg 573f29dbc25Smrg if (attribute == xvColorKey) { 57404007ebaSmrg pPriv->colorKey = value; 57504007ebaSmrg LXSetColorkey(pScrni, pPriv); 57604007ebaSmrg } 57704007ebaSmrg else if (attribute == xvColorKeyMode) { 57804007ebaSmrg pPriv->colorKeyMode = value; 57904007ebaSmrg LXSetColorkey(pScrni, pPriv); 58004007ebaSmrg } 58104007ebaSmrg else if (attribute == xvFilter) { 58204007ebaSmrg if ((value < 0) || (value > 1)) 58304007ebaSmrg return BadValue; 58404007ebaSmrg pPriv->filter = value; 58504007ebaSmrg } 58604007ebaSmrg else 58704007ebaSmrg return BadMatch; 588f29dbc25Smrg 589f29dbc25Smrg return Success; 590f29dbc25Smrg} 591f29dbc25Smrg 592f29dbc25Smrgstatic void 593f29dbc25SmrgLXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 594f29dbc25Smrg{ 595f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 596f29dbc25Smrg 597f29dbc25Smrg if (pPriv->videoStatus == 0) 59804007ebaSmrg return; 599f29dbc25Smrg 600f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 601f29dbc25Smrg gp_wait_until_idle(); 602f29dbc25Smrg 603f29dbc25Smrg if (exit) { 60404007ebaSmrg if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 60504007ebaSmrg unsigned int val; 60604007ebaSmrg 60704007ebaSmrg df_set_video_enable(0, 0); 60804007ebaSmrg /* Put the LUT back in bypass */ 60904007ebaSmrg val = READ_VID32(DF_VID_MISC); 61004007ebaSmrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 61104007ebaSmrg } 61204007ebaSmrg 61304007ebaSmrg if (pPriv->vidmem) { 61404007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 61504007ebaSmrg pPriv->vidmem = NULL; 61604007ebaSmrg } 61704007ebaSmrg 61804007ebaSmrg pPriv->videoStatus = 0; 61904007ebaSmrg 62004007ebaSmrg /* Eh? */ 62104007ebaSmrg } 62204007ebaSmrg else if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 62304007ebaSmrg pPriv->videoStatus |= OFF_TIMER; 62404007ebaSmrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 625f29dbc25Smrg } 626f29dbc25Smrg} 627f29dbc25Smrg 628f29dbc25Smrgstatic void 629f29dbc25SmrgLXResetVideo(ScrnInfoPtr pScrni) 630f29dbc25Smrg{ 631f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 632f29dbc25Smrg 633f29dbc25Smrg if (!pGeode->NoAccel) { 63404007ebaSmrg GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr; 635f29dbc25Smrg 63604007ebaSmrg gp_wait_until_idle(); 63704007ebaSmrg df_set_video_palette(NULL); 638f29dbc25Smrg 63904007ebaSmrg LXSetColorkey(pScrni, pPriv); 640f29dbc25Smrg } 641f29dbc25Smrg} 642f29dbc25Smrg 643f29dbc25Smrgstatic void 64404007ebaSmrgLXVidBlockHandler(BLOCKHANDLER_ARGS_DECL) 645f29dbc25Smrg{ 64604007ebaSmrg SCREEN_PTR(arg); 64704007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 648f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 649f29dbc25Smrg GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni); 650f29dbc25Smrg 651f29dbc25Smrg pScrn->BlockHandler = pGeode->BlockHandler; 65204007ebaSmrg (*pScrn->BlockHandler) (BLOCKHANDLER_ARGS); 653f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 654f29dbc25Smrg 655f29dbc25Smrg if (pPriv->videoStatus & TIMER_MASK) { 65604007ebaSmrg Time now = currentTime.milliseconds; 65704007ebaSmrg 65804007ebaSmrg if (pPriv->videoStatus & OFF_TIMER) { 65904007ebaSmrg gp_wait_until_idle(); 66004007ebaSmrg 66104007ebaSmrg if (pPriv->offTime < now) { 66204007ebaSmrg unsigned int val; 66304007ebaSmrg 66404007ebaSmrg df_set_video_enable(0, 0); 66504007ebaSmrg pPriv->videoStatus = FREE_TIMER; 66604007ebaSmrg pPriv->freeTime = now + FREE_DELAY; 66704007ebaSmrg 66804007ebaSmrg /* Turn off the video palette */ 66904007ebaSmrg val = READ_VID32(DF_VID_MISC); 67004007ebaSmrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 67104007ebaSmrg } 67204007ebaSmrg } 67304007ebaSmrg else { 67404007ebaSmrg if (pPriv->freeTime < now) { 67504007ebaSmrg 67604007ebaSmrg if (pPriv->vidmem) { 67704007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 67804007ebaSmrg pPriv->vidmem = NULL; 67904007ebaSmrg } 68004007ebaSmrg 68104007ebaSmrg pPriv->videoStatus = 0; 68204007ebaSmrg } 68304007ebaSmrg } 684f29dbc25Smrg } 685f29dbc25Smrg} 686f29dbc25Smrg 687f29dbc25Smrgstatic XF86VideoAdaptorPtr 688f29dbc25SmrgLXSetupImageVideo(ScreenPtr pScrn) 689f29dbc25Smrg{ 69004007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 691f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 692f29dbc25Smrg XF86VideoAdaptorPtr adapt; 693f29dbc25Smrg GeodePortPrivRec *pPriv; 694f29dbc25Smrg 695170d5fdcSmrg adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 69604007ebaSmrg sizeof(GeodePortPrivRec) + sizeof(DevUnion)); 697f29dbc25Smrg 698f29dbc25Smrg if (adapt == NULL) { 69904007ebaSmrg ErrorF("Couldn't create the rec\n"); 70004007ebaSmrg return NULL; 701f29dbc25Smrg } 702f29dbc25Smrg 703f29dbc25Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 704f29dbc25Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 705f29dbc25Smrg 706f29dbc25Smrg adapt->name = "AMD Geode LX"; 707f29dbc25Smrg adapt->nEncodings = 1; 708f29dbc25Smrg adapt->pEncodings = DummyEncoding; 709f29dbc25Smrg adapt->nFormats = ARRAY_SIZE(Formats); 710f29dbc25Smrg adapt->pFormats = Formats; 711f29dbc25Smrg adapt->nPorts = 1; 712f29dbc25Smrg adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 713f29dbc25Smrg pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]); 714f29dbc25Smrg adapt->pPortPrivates[0].ptr = (pointer) (pPriv); 715f29dbc25Smrg adapt->pAttributes = Attributes; 716f29dbc25Smrg adapt->nImages = ARRAY_SIZE(Images); 717f29dbc25Smrg adapt->nAttributes = ARRAY_SIZE(Attributes); 718f29dbc25Smrg adapt->pImages = Images; 719f29dbc25Smrg adapt->PutVideo = NULL; 720f29dbc25Smrg adapt->PutStill = NULL; 721f29dbc25Smrg adapt->GetVideo = NULL; 722f29dbc25Smrg adapt->GetStill = NULL; 723f29dbc25Smrg adapt->StopVideo = LXStopVideo; 724f29dbc25Smrg adapt->SetPortAttribute = LXSetPortAttribute; 725f29dbc25Smrg adapt->GetPortAttribute = LXGetPortAttribute; 726f29dbc25Smrg adapt->QueryBestSize = LXQueryBestSize; 727f29dbc25Smrg adapt->PutImage = LXPutImage; 728f29dbc25Smrg 729f29dbc25Smrg /* Use the common function */ 730f29dbc25Smrg adapt->QueryImageAttributes = GeodeQueryImageAttributes; 731f29dbc25Smrg 732f29dbc25Smrg pPriv->vidmem = NULL; 733f29dbc25Smrg pPriv->filter = 0; 734f29dbc25Smrg pPriv->colorKey = 0; 735f29dbc25Smrg pPriv->colorKeyMode = 0; 736f29dbc25Smrg pPriv->videoStatus = 0; 737f29dbc25Smrg pPriv->pwidth = 0; 738f29dbc25Smrg pPriv->pheight = 0; 739f29dbc25Smrg 740f29dbc25Smrg REGION_NULL(pScrn, &pPriv->clip); 741f29dbc25Smrg 742f29dbc25Smrg pGeode->adaptor = adapt; 743f29dbc25Smrg 744f29dbc25Smrg pGeode->BlockHandler = pScrn->BlockHandler; 745f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 746f29dbc25Smrg 747f29dbc25Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 748f29dbc25Smrg xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE"); 749f29dbc25Smrg xvFilter = MAKE_ATOM("XV_FILTER"); 750f29dbc25Smrg 751f29dbc25Smrg LXResetVideo(pScrni); 752f29dbc25Smrg 753f29dbc25Smrg return adapt; 754f29dbc25Smrg} 755f29dbc25Smrg 756f29dbc25Smrg/* Offscreen surface allocation */ 757f29dbc25Smrg 75804007ebaSmrgstruct OffscreenPrivRec { 759170d5fdcSmrg ExaOffscreenArea *vidmem; 760f29dbc25Smrg Bool isOn; 761f29dbc25Smrg}; 762f29dbc25Smrg 763f29dbc25Smrgstatic int 764f29dbc25SmrgLXDisplaySurface(XF86SurfacePtr surface, 76504007ebaSmrg short srcX, short srcY, short drawX, short drawY, 76604007ebaSmrg short srcW, short srcH, short drawW, short drawH, 76704007ebaSmrg RegionPtr clipBoxes) 768f29dbc25Smrg{ 769f29dbc25Smrg struct OffscreenPrivRec *pPriv = 77004007ebaSmrg (struct OffscreenPrivRec *) surface->devPrivate.ptr; 771f29dbc25Smrg 772f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 773f29dbc25Smrg GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni); 774f29dbc25Smrg 775f29dbc25Smrg BoxRec dstBox; 776f29dbc25Smrg 777f29dbc25Smrg dstBox.x1 = drawX; 778f29dbc25Smrg dstBox.x2 = drawX + drawW; 779f29dbc25Smrg dstBox.y1 = drawY; 780f29dbc25Smrg dstBox.y2 = drawY + drawH; 781f29dbc25Smrg 782f29dbc25Smrg if ((drawW <= 0) | (drawH <= 0)) 78304007ebaSmrg return Success; 784f29dbc25Smrg 785f29dbc25Smrg /* Is this still valid? */ 786f29dbc25Smrg 787f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 788f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 789f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 790f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 791f29dbc25Smrg 792f29dbc25Smrg xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes); 793f29dbc25Smrg 794f29dbc25Smrg videoScratch.dstOffset = surface->offsets[0]; 795f29dbc25Smrg videoScratch.dstPitch = surface->pitches[0]; 796f29dbc25Smrg 797f29dbc25Smrg LXDisplayVideo(pScrni, surface->id, surface->width, surface->height, 79804007ebaSmrg &dstBox, srcW, srcH, drawW, drawH); 799f29dbc25Smrg 800f29dbc25Smrg pPriv->isOn = TRUE; 801f29dbc25Smrg 802f29dbc25Smrg if (portPriv->videoStatus & CLIENT_VIDEO_ON) { 80304007ebaSmrg REGION_EMPTY(pScrni->pScreen, &portPriv->clip); 80404007ebaSmrg UpdateCurrentTime(); 80504007ebaSmrg portPriv->videoStatus = FREE_TIMER; 80604007ebaSmrg portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 807f29dbc25Smrg } 808f29dbc25Smrg 809f29dbc25Smrg return Success; 810f29dbc25Smrg} 811f29dbc25Smrg 812f29dbc25Smrgstatic int 813f29dbc25SmrgLXAllocateSurface(ScrnInfoPtr pScrni, int id, unsigned short w, 81404007ebaSmrg unsigned short h, XF86SurfacePtr surface) 815f29dbc25Smrg{ 816f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 817f29dbc25Smrg int pitch, lines; 818170d5fdcSmrg ExaOffscreenArea *vidmem; 819f29dbc25Smrg struct OffscreenPrivRec *pPriv; 820f29dbc25Smrg 821f29dbc25Smrg if (w > 1024 || h > 1024) 82204007ebaSmrg return BadAlloc; 823f29dbc25Smrg 824f29dbc25Smrg /* The width needs to be word aligned */ 825f29dbc25Smrg w = (w + 1) & ~1; 826f29dbc25Smrg 827f29dbc25Smrg pitch = ((w << 1) + 15) & ~15; 828f29dbc25Smrg lines = ((pitch * h) + (pGeode->Pitch - 1)) / pGeode->Pitch; 829f29dbc25Smrg 8307aef237fSmrg /* FIXME: is lines the right parameter to use here, 8317aef237fSmrg * or should it be height * pitch? */ 83204007ebaSmrg vidmem = exaOffscreenAlloc(pScrni->pScreen, lines, 4, TRUE, NULL, NULL); 833f29dbc25Smrg 834f29dbc25Smrg if (vidmem == NULL) { 83504007ebaSmrg ErrorF("Error while allocating an offscreen region.\n"); 83604007ebaSmrg return BadAlloc; 837f29dbc25Smrg } 838f29dbc25Smrg 839f29dbc25Smrg surface->width = w; 840f29dbc25Smrg surface->height = h; 841f29dbc25Smrg 842170d5fdcSmrg surface->pitches = malloc(sizeof(int)); 843f29dbc25Smrg 844170d5fdcSmrg surface->offsets = malloc(sizeof(int)); 845f29dbc25Smrg 846170d5fdcSmrg pPriv = malloc(sizeof(struct OffscreenPrivRec)); 847f29dbc25Smrg 848f29dbc25Smrg if (pPriv && surface->pitches && surface->offsets) { 849f29dbc25Smrg 85004007ebaSmrg pPriv->vidmem = vidmem; 851f29dbc25Smrg 85204007ebaSmrg pPriv->isOn = FALSE; 853f29dbc25Smrg 85404007ebaSmrg surface->pScrn = pScrni; 85504007ebaSmrg surface->id = id; 85604007ebaSmrg surface->pitches[0] = pitch; 85704007ebaSmrg surface->offsets[0] = vidmem->offset; 85804007ebaSmrg surface->devPrivate.ptr = (pointer) pPriv; 859f29dbc25Smrg 86004007ebaSmrg return Success; 861f29dbc25Smrg } 862f29dbc25Smrg 863f29dbc25Smrg if (surface->offsets) 86404007ebaSmrg free(surface->offsets); 865f29dbc25Smrg 866f29dbc25Smrg if (surface->pitches) 86704007ebaSmrg free(surface->pitches); 868f29dbc25Smrg 869170d5fdcSmrg if (vidmem) { 87004007ebaSmrg exaOffscreenFree(pScrni->pScreen, vidmem); 87104007ebaSmrg vidmem = NULL; 872170d5fdcSmrg } 873f29dbc25Smrg 874f29dbc25Smrg return BadAlloc; 875f29dbc25Smrg} 876f29dbc25Smrg 877f29dbc25Smrgstatic int 878f29dbc25SmrgLXStopSurface(XF86SurfacePtr surface) 879f29dbc25Smrg{ 880f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 88104007ebaSmrg surface->devPrivate.ptr; 882f29dbc25Smrg 883f29dbc25Smrg pPriv->isOn = FALSE; 884f29dbc25Smrg return Success; 885f29dbc25Smrg} 886f29dbc25Smrg 887f29dbc25Smrgstatic int 888f29dbc25SmrgLXFreeSurface(XF86SurfacePtr surface) 889f29dbc25Smrg{ 890f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 89104007ebaSmrg surface->devPrivate.ptr; 892f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 893f29dbc25Smrg 894f29dbc25Smrg if (pPriv->isOn) 89504007ebaSmrg LXStopSurface(surface); 896f29dbc25Smrg 897f29dbc25Smrg if (pPriv->vidmem) { 89804007ebaSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 89904007ebaSmrg pPriv->vidmem = NULL; 900f29dbc25Smrg } 901f29dbc25Smrg 902170d5fdcSmrg free(surface->pitches); 903170d5fdcSmrg free(surface->offsets); 904170d5fdcSmrg free(surface->devPrivate.ptr); 905f29dbc25Smrg 906f29dbc25Smrg return Success; 907f29dbc25Smrg} 908f29dbc25Smrg 909f29dbc25Smrgstatic int 91004007ebaSmrgLXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 *value) 911f29dbc25Smrg{ 912f29dbc25Smrg return LXGetPortAttribute(pScrni, attribute, value, 91304007ebaSmrg (pointer) (GET_PORT_PRIVATE(pScrni))); 914f29dbc25Smrg} 915f29dbc25Smrg 916f29dbc25Smrgstatic int 917f29dbc25SmrgLXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value) 918f29dbc25Smrg{ 919f29dbc25Smrg return LXSetPortAttribute(pScrni, attribute, value, 92004007ebaSmrg (pointer) (GET_PORT_PRIVATE(pScrni))); 921f29dbc25Smrg} 922f29dbc25Smrg 923f29dbc25Smrgstatic void 924f29dbc25SmrgLXInitOffscreenImages(ScreenPtr pScrn) 925f29dbc25Smrg{ 926f29dbc25Smrg XF86OffscreenImagePtr offscreenImages; 927f29dbc25Smrg 928f29dbc25Smrg /* need to free this someplace */ 929170d5fdcSmrg if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 93004007ebaSmrg return; 931f29dbc25Smrg 932f29dbc25Smrg offscreenImages[0].image = &Images[0]; 933f29dbc25Smrg offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 934f29dbc25Smrg offscreenImages[0].alloc_surface = LXAllocateSurface; 935f29dbc25Smrg offscreenImages[0].free_surface = LXFreeSurface; 936f29dbc25Smrg offscreenImages[0].display = LXDisplaySurface; 937f29dbc25Smrg offscreenImages[0].stop = LXStopSurface; 938f29dbc25Smrg offscreenImages[0].setAttribute = LXSetSurfaceAttribute; 939f29dbc25Smrg offscreenImages[0].getAttribute = LXGetSurfaceAttribute; 940f29dbc25Smrg offscreenImages[0].max_width = 1024; 941f29dbc25Smrg offscreenImages[0].max_height = 1024; 942f29dbc25Smrg offscreenImages[0].num_attributes = ARRAY_SIZE(Attributes); 943f29dbc25Smrg offscreenImages[0].attributes = Attributes; 944f29dbc25Smrg 945f29dbc25Smrg xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1); 946f29dbc25Smrg} 947f29dbc25Smrg 948f29dbc25Smrgvoid 949f29dbc25SmrgLXInitVideo(ScreenPtr pScrn) 950f29dbc25Smrg{ 951f29dbc25Smrg GeodeRec *pGeode; 95204007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 953f29dbc25Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 954f29dbc25Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 955f29dbc25Smrg int num_adaptors; 956f29dbc25Smrg 957f29dbc25Smrg pGeode = GEODEPTR(pScrni); 958f29dbc25Smrg 959f29dbc25Smrg if (pGeode->NoAccel) { 96004007ebaSmrg ErrorF("Cannot run Xv without accelerations!\n"); 96104007ebaSmrg return; 962f29dbc25Smrg } 963f29dbc25Smrg 964f29dbc25Smrg if (!(newAdaptor = LXSetupImageVideo(pScrn))) { 96504007ebaSmrg ErrorF("Error while setting up the adaptor.\n"); 96604007ebaSmrg return; 967f29dbc25Smrg } 968f29dbc25Smrg 969f29dbc25Smrg LXInitOffscreenImages(pScrn); 970f29dbc25Smrg 971f29dbc25Smrg num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors); 972f29dbc25Smrg 973f29dbc25Smrg if (!num_adaptors) { 97404007ebaSmrg num_adaptors = 1; 97504007ebaSmrg adaptors = &newAdaptor; 97604007ebaSmrg } 97704007ebaSmrg else { 97804007ebaSmrg newAdaptors = 97904007ebaSmrg malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); 98004007ebaSmrg 98104007ebaSmrg if (newAdaptors) { 98204007ebaSmrg memcpy(newAdaptors, adaptors, num_adaptors * 98304007ebaSmrg sizeof(XF86VideoAdaptorPtr)); 98404007ebaSmrg newAdaptors[num_adaptors] = newAdaptor; 98504007ebaSmrg adaptors = newAdaptors; 98604007ebaSmrg num_adaptors++; 98704007ebaSmrg } 98804007ebaSmrg else 98904007ebaSmrg ErrorF("Memory error while setting up the adaptor\n"); 990f29dbc25Smrg } 991f29dbc25Smrg 992f29dbc25Smrg if (num_adaptors) 99304007ebaSmrg xf86XVScreenInit(pScrn, adaptors, num_adaptors); 994f29dbc25Smrg 995f29dbc25Smrg if (newAdaptors) 99604007ebaSmrg free(newAdaptors); 997f29dbc25Smrg} 998