lx_video.c revision 7aef237f
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) 64f29dbc25Smrg#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a)))) 65f29dbc25Smrg 66f29dbc25Smrg/* Local function prototypes */ 67f29dbc25Smrgstatic void LXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit); 68f29dbc25Smrg 69f29dbc25Smrgstatic void 70f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 71f29dbc25Smrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH); 72f29dbc25Smrg 73f29dbc25Smrgstatic void LXResetVideo(ScrnInfoPtr pScrni); 74f29dbc25Smrg 75f29dbc25Smrgstatic XF86VideoEncodingRec DummyEncoding[1] = { 76f29dbc25Smrg {0, "XV_IMAGE", 1024, 1024, {1, 1}} 77f29dbc25Smrg}; 78f29dbc25Smrg 79f29dbc25Smrgstatic XF86VideoFormatRec Formats[] = { 80f29dbc25Smrg {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 81f29dbc25Smrg}; 82f29dbc25Smrg 83f29dbc25Smrgstatic XF86AttributeRec Attributes[] = { 84f29dbc25Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 85f29dbc25Smrg {XvSettable | XvGettable, 0, 1, "XV_FILTER"}, 86f29dbc25Smrg {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"} 87f29dbc25Smrg}; 88f29dbc25Smrg 89f29dbc25Smrgstatic XF86ImageRec Images[] = { 90f29dbc25Smrg XVIMAGE_UYVY, 91f29dbc25Smrg XVIMAGE_YUY2, 92f29dbc25Smrg XVIMAGE_Y2YU, 93f29dbc25Smrg XVIMAGE_YVYU, 94f29dbc25Smrg XVIMAGE_Y800, 95f29dbc25Smrg XVIMAGE_I420, 96f29dbc25Smrg XVIMAGE_YV12, 97f29dbc25Smrg XVIMAGE_RGB565 98f29dbc25Smrg}; 99f29dbc25Smrg 100f29dbc25Smrgtypedef struct 101f29dbc25Smrg{ 102170d5fdcSmrg ExaOffscreenArea *vidmem; 103f29dbc25Smrg RegionRec clip; 104f29dbc25Smrg CARD32 filter; 105f29dbc25Smrg CARD32 colorKey; 106f29dbc25Smrg CARD32 colorKeyMode; 107f29dbc25Smrg CARD32 videoStatus; 108f29dbc25Smrg Time offTime; 109f29dbc25Smrg Time freeTime; 110f29dbc25Smrg short pwidth, pheight; 111f29dbc25Smrg} GeodePortPrivRec, *GeodePortPrivPtr; 112f29dbc25Smrg 113f29dbc25Smrg#define GET_PORT_PRIVATE(pScrni) \ 114f29dbc25Smrg (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr) 115f29dbc25Smrg 116f29dbc25Smrgstatic void 117f29dbc25SmrgLXCopyFromSys(GeodeRec * pGeode, unsigned char *src, unsigned int dst, 118f29dbc25Smrg int dstPitch, int srcPitch, int h, int w) 119f29dbc25Smrg{ 120f29dbc25Smrg 121f29dbc25Smrg gp_declare_blt(0); 122170d5fdcSmrg gp_set_bpp((srcPitch / w) << 3); 123f29dbc25Smrg 124f29dbc25Smrg gp_set_raster_operation(0xCC); 125f29dbc25Smrg gp_set_strides(dstPitch, srcPitch); 126f29dbc25Smrg gp_set_solid_pattern(0); 127f29dbc25Smrg 128f29dbc25Smrg gp_color_bitmap_to_screen_blt(dst, 0, w, h, src, srcPitch); 129f29dbc25Smrg} 130f29dbc25Smrg 131f29dbc25Smrgstatic void 132f29dbc25SmrgLXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv) 133f29dbc25Smrg{ 134f29dbc25Smrg int red, green, blue; 135f29dbc25Smrg unsigned long key; 136f29dbc25Smrg 137f29dbc25Smrg switch (pScrni->depth) { 138f29dbc25Smrg case 8: 139f29dbc25Smrg vg_get_display_palette_entry(pPriv->colorKey & 0xFF, &key); 140f29dbc25Smrg red = ((key >> 16) & 0xFF); 141f29dbc25Smrg green = ((key >> 8) & 0xFF); 142f29dbc25Smrg blue = (key & 0xFF); 143f29dbc25Smrg break; 144f29dbc25Smrg case 16: 145f29dbc25Smrg red = (pPriv->colorKey & pScrni->mask.red) >> 146f29dbc25Smrg pScrni->offset.red << (8 - pScrni->weight.red); 147f29dbc25Smrg green = (pPriv->colorKey & pScrni->mask.green) >> 148f29dbc25Smrg pScrni->offset.green << (8 - pScrni->weight.green); 149f29dbc25Smrg blue = (pPriv->colorKey & pScrni->mask.blue) >> 150f29dbc25Smrg pScrni->offset.blue << (8 - pScrni->weight.blue); 151f29dbc25Smrg break; 152f29dbc25Smrg default: 153f29dbc25Smrg /* for > 16 bpp we send in the mask in xf86SetWeight. This 154f29dbc25Smrg * function is providing the offset by 1 more. So we take 155f29dbc25Smrg * this as a special case and subtract 1 for > 16 156f29dbc25Smrg */ 157f29dbc25Smrg 158f29dbc25Smrg red = (pPriv->colorKey & pScrni->mask.red) >> 159f29dbc25Smrg (pScrni->offset.red - 1) << (8 - pScrni->weight.red); 160f29dbc25Smrg green = (pPriv->colorKey & pScrni->mask.green) >> 161f29dbc25Smrg (pScrni->offset.green - 1) << (8 - pScrni->weight.green); 162f29dbc25Smrg blue = (pPriv->colorKey & pScrni->mask.blue) >> 163f29dbc25Smrg (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue); 164f29dbc25Smrg break; 165f29dbc25Smrg } 166f29dbc25Smrg 167f29dbc25Smrg df_set_video_color_key((blue | (green << 8) | (red << 16)), 168f29dbc25Smrg 0xFFFFFF, (pPriv->colorKeyMode == 0)); 169f29dbc25Smrg 170f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 171f29dbc25Smrg} 172f29dbc25Smrg 173f29dbc25Smrg/* A structure full of the scratch information that originates in the copy routines, 174f29dbc25Smrg but is needed for the video display - maybe we should figure out a way to attach 175f29dbc25Smrg this to structures? I hate to put it in pGeode since it will increase the size of 176f29dbc25Smrg the structure, and possibly cause us cache issues. 177f29dbc25Smrg*/ 178f29dbc25Smrg 179f29dbc25Smrgstruct 180f29dbc25Smrg{ 181f29dbc25Smrg unsigned int dstOffset; 182f29dbc25Smrg unsigned int dstPitch; 183f29dbc25Smrg unsigned int UVPitch; 184f29dbc25Smrg unsigned int UDstOffset; 185f29dbc25Smrg unsigned int VDstOffset; 186f29dbc25Smrg} videoScratch; 187f29dbc25Smrg 188f29dbc25Smrg/* Copy planar YUV data */ 189f29dbc25Smrg 190f29dbc25Smrgstatic Bool 191170d5fdcSmrgLXAllocateVidMem(ScrnInfoPtr pScrni, GeodePortPrivRec *pPriv, int size) 192f29dbc25Smrg{ 193f29dbc25Smrg if (!pPriv->vidmem || pPriv->vidmem->size < size) { 194170d5fdcSmrg if (pPriv->vidmem) { 195170d5fdcSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 196170d5fdcSmrg pPriv->vidmem = NULL; 197170d5fdcSmrg } 198f29dbc25Smrg 199170d5fdcSmrg pPriv->vidmem = exaOffscreenAlloc(pScrni->pScreen, size, 4, 200170d5fdcSmrg TRUE, NULL, NULL); 201f29dbc25Smrg 202f29dbc25Smrg if (pPriv->vidmem == NULL) { 203f29dbc25Smrg ErrorF("Could not allocate memory for the video\n"); 204f29dbc25Smrg return FALSE; 205f29dbc25Smrg } 206f29dbc25Smrg } 207f29dbc25Smrg 208f29dbc25Smrg return TRUE; 209f29dbc25Smrg} 210f29dbc25Smrg 211f29dbc25Smrgstatic Bool 212f29dbc25SmrgLXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, 213f29dbc25Smrg short x1, short y1, short x2, short y2, 214f29dbc25Smrg int width, int height, pointer data) 215f29dbc25Smrg{ 216f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 217f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 218f29dbc25Smrg 219f29dbc25Smrg unsigned int YSrcPitch, YDstPitch; 220f29dbc25Smrg unsigned int UVSrcPitch, UVDstPitch; 221f29dbc25Smrg unsigned int YSrcOffset, YDstOffset; 222f29dbc25Smrg unsigned int USrcOffset, UDstOffset; 223f29dbc25Smrg unsigned int VSrcOffset, VDstOffset; 224f29dbc25Smrg 225f29dbc25Smrg unsigned int size, lines, top, left, pixels; 226f29dbc25Smrg 227f29dbc25Smrg YSrcPitch = (width + 3) & ~3; 228f29dbc25Smrg YDstPitch = (width + 31) & ~31; 229f29dbc25Smrg 230f29dbc25Smrg UVSrcPitch = ((width >> 1) + 3) & ~3; 231f29dbc25Smrg UVDstPitch = ((width >> 1) + 15) & ~15; 232f29dbc25Smrg 233f29dbc25Smrg USrcOffset = YSrcPitch * height; 234f29dbc25Smrg VSrcOffset = USrcOffset + (UVSrcPitch * (height >> 1)); 235f29dbc25Smrg 236f29dbc25Smrg UDstOffset = YDstPitch * height; 237f29dbc25Smrg VDstOffset = UDstOffset + (UVDstPitch * (height >> 1)); 238f29dbc25Smrg 239f29dbc25Smrg size = YDstPitch * height; 240f29dbc25Smrg size += UVDstPitch * height; 241f29dbc25Smrg 242170d5fdcSmrg if (LXAllocateVidMem(pScrni, pPriv, size) == FALSE) { 243170d5fdcSmrg ErrorF("Error allocating an offscreen Planar region.\n"); 244f29dbc25Smrg return FALSE; 245170d5fdcSmrg } 246f29dbc25Smrg 247f29dbc25Smrg /* The top of the source region we want to copy */ 248f29dbc25Smrg top = y1 & ~1; 249f29dbc25Smrg 250f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 251f29dbc25Smrg left = x1 & ~1; 252f29dbc25Smrg 253f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 254f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 255f29dbc25Smrg 256f29dbc25Smrg /* Calculate the source offset */ 257f29dbc25Smrg YSrcOffset = (top * YSrcPitch) + left; 258f29dbc25Smrg USrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 259f29dbc25Smrg VSrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 260f29dbc25Smrg 261f29dbc25Smrg /* Calculate the destination offset */ 262f29dbc25Smrg YDstOffset = (top * YDstPitch) + left; 263f29dbc25Smrg UDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 264f29dbc25Smrg VDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 265f29dbc25Smrg 266f29dbc25Smrg lines = ((y2 + 1) & ~1) - top; 267f29dbc25Smrg 268f29dbc25Smrg /* Copy Y */ 269f29dbc25Smrg 270f29dbc25Smrg LXCopyFromSys(pGeode, buf + YSrcOffset, 271f29dbc25Smrg pPriv->vidmem->offset + YDstOffset, YDstPitch, YSrcPitch, lines, 272f29dbc25Smrg pixels); 273f29dbc25Smrg 274f29dbc25Smrg /* Copy U + V at the same time */ 275f29dbc25Smrg 276f29dbc25Smrg LXCopyFromSys(pGeode, buf + USrcOffset, 277f29dbc25Smrg pPriv->vidmem->offset + UDstOffset, UVDstPitch, UVSrcPitch, lines, 278f29dbc25Smrg pixels >> 1); 279f29dbc25Smrg 280f29dbc25Smrg videoScratch.dstOffset = pPriv->vidmem->offset + YDstOffset; 281f29dbc25Smrg videoScratch.dstPitch = YDstPitch; 282f29dbc25Smrg videoScratch.UVPitch = UVDstPitch; 283f29dbc25Smrg videoScratch.UDstOffset = pPriv->vidmem->offset + UDstOffset; 284f29dbc25Smrg videoScratch.VDstOffset = pPriv->vidmem->offset + VDstOffset; 285f29dbc25Smrg 286f29dbc25Smrg return TRUE; 287f29dbc25Smrg} 288f29dbc25Smrg 289f29dbc25Smrgstatic Bool 290f29dbc25SmrgLXCopyPacked(ScrnInfoPtr pScrni, int id, unsigned char *buf, 291f29dbc25Smrg short x1, short y1, short x2, short y2, 292f29dbc25Smrg int width, int height, pointer data) 293f29dbc25Smrg{ 294f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 295f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 296f29dbc25Smrg unsigned int dstPitch, srcPitch; 297f29dbc25Smrg unsigned int srcOffset, dstOffset; 298f29dbc25Smrg unsigned int lines, top, left, pixels; 299f29dbc25Smrg 300f29dbc25Smrg dstPitch = ((width << 1) + 3) & ~3; 301f29dbc25Smrg srcPitch = (width << 1); 302f29dbc25Smrg 303f29dbc25Smrg lines = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch; 304f29dbc25Smrg 3057aef237fSmrg if (LXAllocateVidMem(pScrni, pPriv, dstPitch * height) == FALSE) { 306170d5fdcSmrg ErrorF("Error allocating an offscreen Packed region.\n"); 307f29dbc25Smrg return FALSE; 308170d5fdcSmrg } 309f29dbc25Smrg 310f29dbc25Smrg /* The top of the source region we want to copy */ 311f29dbc25Smrg top = y1; 312f29dbc25Smrg 313f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 314f29dbc25Smrg left = x1 & ~1; 315f29dbc25Smrg 316f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 317f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 318f29dbc25Smrg 319f29dbc25Smrg /* Adjust the incoming buffer */ 320f29dbc25Smrg srcOffset = (top * srcPitch) + left; 321f29dbc25Smrg 322f29dbc25Smrg /* Calculate the destination offset */ 323f29dbc25Smrg dstOffset = pPriv->vidmem->offset + (top * dstPitch) + left; 324f29dbc25Smrg 325f29dbc25Smrg /* Make the copy happen */ 326f29dbc25Smrg 327f29dbc25Smrg if (id == FOURCC_Y800) { 328f29dbc25Smrg 329f29dbc25Smrg /* Use the shared (unaccelerated) greyscale copy - you could probably 330f29dbc25Smrg * accelerate it using a 2 pass blit and patterns, but it doesn't really 331f29dbc25Smrg * seem worth it 332f29dbc25Smrg */ 333f29dbc25Smrg 334f29dbc25Smrg GeodeCopyGreyscale(buf + srcOffset, pGeode->FBBase + dstOffset, 335f29dbc25Smrg srcPitch, dstPitch, height, pixels >> 1); 336f29dbc25Smrg } else 3377aef237fSmrg /* FIXME: should lines be used here instead of height? */ 338f29dbc25Smrg LXCopyFromSys(pGeode, buf + srcOffset, dstOffset, dstPitch, srcPitch, 339f29dbc25Smrg height, pixels); 340f29dbc25Smrg 341f29dbc25Smrg videoScratch.dstOffset = dstOffset; 342f29dbc25Smrg videoScratch.dstPitch = dstPitch; 343f29dbc25Smrg 344f29dbc25Smrg return TRUE; 345f29dbc25Smrg} 346f29dbc25Smrg 347f29dbc25Smrgstatic void 348f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 349f29dbc25Smrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH) 350f29dbc25Smrg{ 351f29dbc25Smrg long ystart, xend, yend; 352f29dbc25Smrg unsigned long lines = 0; 353f29dbc25Smrg unsigned long yExtra, uvExtra = 0; 354f29dbc25Smrg DF_VIDEO_POSITION vidPos; 355f29dbc25Smrg DF_VIDEO_SOURCE_PARAMS vSrcParams; 356f29dbc25Smrg int err; 357f29dbc25Smrg 358f29dbc25Smrg memset(&vSrcParams, 0, sizeof(vSrcParams)); 359f29dbc25Smrg 360f29dbc25Smrg gp_wait_until_idle(); 361f29dbc25Smrg 362f29dbc25Smrg switch (id) { 363f29dbc25Smrg case FOURCC_UYVY: 364f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_UYVY; 365f29dbc25Smrg break; 366f29dbc25Smrg 367f29dbc25Smrg case FOURCC_Y800: 368f29dbc25Smrg case FOURCC_YV12: 369f29dbc25Smrg case FOURCC_I420: 370f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_Y0Y1Y2Y3; 371f29dbc25Smrg break; 372f29dbc25Smrg case FOURCC_YUY2: 373f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_YUYV; 374f29dbc25Smrg break; 375f29dbc25Smrg case FOURCC_Y2YU: 376f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_Y2YU; 377f29dbc25Smrg break; 378f29dbc25Smrg case FOURCC_YVYU: 379f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_YVYU; 380f29dbc25Smrg break; 381f29dbc25Smrg case FOURCC_RGB565: 382f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_RGB; 383f29dbc25Smrg break; 384f29dbc25Smrg } 385f29dbc25Smrg 386f29dbc25Smrg vSrcParams.width = width; 387f29dbc25Smrg vSrcParams.height = height; 388f29dbc25Smrg vSrcParams.y_pitch = videoScratch.dstPitch; 389f29dbc25Smrg vSrcParams.uv_pitch = videoScratch.UVPitch; 390f29dbc25Smrg 391f29dbc25Smrg /* Set up scaling */ 392f29dbc25Smrg df_set_video_filter_coefficients(NULL, 1); 393f29dbc25Smrg 394f29dbc25Smrg err = df_set_video_scale(width, height, drawW, drawH, 395f29dbc25Smrg DF_SCALEFLAG_CHANGEX | DF_SCALEFLAG_CHANGEY); 396f29dbc25Smrg if (err != CIM_STATUS_OK) { 397f29dbc25Smrg /* Note the problem, but do nothing for now. */ 398f29dbc25Smrg ErrorF("Video scale factor too large: %dx%d -> %dx%d\n", 399f29dbc25Smrg width, height, drawW, drawH); 400f29dbc25Smrg } 401f29dbc25Smrg 402f29dbc25Smrg /* Figure out clipping */ 403f29dbc25Smrg 404f29dbc25Smrg xend = dstBox->x2; 405f29dbc25Smrg yend = dstBox->y2; 406f29dbc25Smrg 407f29dbc25Smrg if (dstBox->y1 < 0) { 408f29dbc25Smrg if (srcH < drawH) 409f29dbc25Smrg lines = ((-dstBox->y1) * srcH) / drawH; 410f29dbc25Smrg else 411f29dbc25Smrg lines = (-dstBox->y1); 412f29dbc25Smrg 413f29dbc25Smrg ystart = 0; 414f29dbc25Smrg drawH += dstBox->y1; 415f29dbc25Smrg } else { 416f29dbc25Smrg ystart = dstBox->y1; 417f29dbc25Smrg lines = 0; 418f29dbc25Smrg } 419f29dbc25Smrg 420f29dbc25Smrg yExtra = lines * videoScratch.dstPitch; 421f29dbc25Smrg uvExtra = (lines >> 1) * videoScratch.UVPitch; 422f29dbc25Smrg 423f29dbc25Smrg memset(&vidPos, 0, sizeof(vidPos)); 424f29dbc25Smrg 425f29dbc25Smrg vidPos.x = dstBox->x1; 426f29dbc25Smrg vidPos.y = ystart; 427f29dbc25Smrg vidPos.width = xend - dstBox->x1; 428f29dbc25Smrg vidPos.height = yend - ystart; 429f29dbc25Smrg 430f29dbc25Smrg df_set_video_position(&vidPos); 431f29dbc25Smrg 432f29dbc25Smrg vSrcParams.y_offset = videoScratch.dstOffset + yExtra; 433f29dbc25Smrg 434f29dbc25Smrg switch (id) { 435f29dbc25Smrg case FOURCC_Y800: 436f29dbc25Smrg case FOURCC_I420: 437f29dbc25Smrg vSrcParams.u_offset = videoScratch.UDstOffset + uvExtra; 438f29dbc25Smrg vSrcParams.v_offset = videoScratch.VDstOffset + uvExtra; 439f29dbc25Smrg break; 440f29dbc25Smrg case FOURCC_YV12: 441f29dbc25Smrg vSrcParams.v_offset = videoScratch.UDstOffset + uvExtra; 442f29dbc25Smrg vSrcParams.u_offset = videoScratch.VDstOffset + uvExtra; 443f29dbc25Smrg break; 444f29dbc25Smrg 445f29dbc25Smrg default: 446f29dbc25Smrg vSrcParams.u_offset = vSrcParams.v_offset = 0; 447f29dbc25Smrg break; 448f29dbc25Smrg } 449f29dbc25Smrg 450f29dbc25Smrg vSrcParams.flags = DF_SOURCEFLAG_IMPLICITSCALING; 451f29dbc25Smrg df_configure_video_source(&vSrcParams, &vSrcParams); 452f29dbc25Smrg 453f29dbc25Smrg /* Turn on the video palette */ 454f29dbc25Smrg df_set_video_palette(NULL); 455f29dbc25Smrg df_set_video_enable(1, 0); 456f29dbc25Smrg} 457f29dbc25Smrg 458f29dbc25Smrgstatic int 459f29dbc25SmrgLXPutImage(ScrnInfoPtr pScrni, 460f29dbc25Smrg short srcX, short srcY, short drawX, short drawY, 461f29dbc25Smrg short srcW, short srcH, short drawW, short drawH, 462f29dbc25Smrg int id, unsigned char *buf, 463f29dbc25Smrg short width, short height, Bool sync, RegionPtr clipBoxes, 464f29dbc25Smrg pointer data, DrawablePtr pDraw) 465f29dbc25Smrg{ 466f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 467f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 468f29dbc25Smrg INT32 x1, x2, y1, y2; 469f29dbc25Smrg BoxRec dstBox; 470f29dbc25Smrg Bool ret; 471f29dbc25Smrg 472f29dbc25Smrg if (pGeode->rotation != RR_Rotate_0) 473f29dbc25Smrg return Success; 474f29dbc25Smrg 475f29dbc25Smrg if (srcW <= 0 || srcH <= 0) { 476f29dbc25Smrg return Success; 477f29dbc25Smrg } 478f29dbc25Smrg 479f29dbc25Smrg if (drawW <= 0 || drawH <= 0) { 480f29dbc25Smrg return Success; 481f29dbc25Smrg } 482f29dbc25Smrg 483f29dbc25Smrg if (drawW > 16384) 484f29dbc25Smrg drawW = 16384; 485f29dbc25Smrg 486f29dbc25Smrg memset(&videoScratch, 0, sizeof(videoScratch)); 487f29dbc25Smrg 488f29dbc25Smrg x1 = srcX; 489f29dbc25Smrg x2 = srcX + srcW; 490f29dbc25Smrg y1 = srcY; 491f29dbc25Smrg y2 = srcY + srcH; 492f29dbc25Smrg 493f29dbc25Smrg dstBox.x1 = drawX; 494f29dbc25Smrg dstBox.x2 = drawX + drawW; 495f29dbc25Smrg dstBox.y1 = drawY; 496f29dbc25Smrg dstBox.y2 = drawY + drawH; 497f29dbc25Smrg 498f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 499f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 500f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 501f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 502f29dbc25Smrg 503f29dbc25Smrg if (id == FOURCC_YV12 || id == FOURCC_I420) 504f29dbc25Smrg ret = LXCopyPlanar(pScrni, id, buf, x1, y1, x2, y2, width, 505f29dbc25Smrg height, data); 506f29dbc25Smrg else 507f29dbc25Smrg ret = LXCopyPacked(pScrni, id, buf, x1, y1, x2, y2, width, 508f29dbc25Smrg height, data); 509f29dbc25Smrg 510f29dbc25Smrg if (ret == FALSE) 511f29dbc25Smrg return BadAlloc; 512f29dbc25Smrg 513f29dbc25Smrg if (!RegionsEqual(&pPriv->clip, clipBoxes) || 514f29dbc25Smrg (drawW != pPriv->pwidth || drawH != pPriv->pheight)) { 515f29dbc25Smrg REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes); 516f29dbc25Smrg 517f29dbc25Smrg if (pPriv->colorKeyMode == 0) { 518f29dbc25Smrg xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes); 519f29dbc25Smrg } 520f29dbc25Smrg 521f29dbc25Smrg LXDisplayVideo(pScrni, id, width, height, &dstBox, 522f29dbc25Smrg srcW, srcH, drawW, drawH); 523f29dbc25Smrg pPriv->pwidth = drawW; 524f29dbc25Smrg pPriv->pheight = drawH; 525f29dbc25Smrg } 526f29dbc25Smrg 527f29dbc25Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 528f29dbc25Smrg 529f29dbc25Smrg return Success; 530f29dbc25Smrg} 531f29dbc25Smrg 532f29dbc25Smrgstatic void 533f29dbc25SmrgLXQueryBestSize(ScrnInfoPtr pScrni, Bool motion, 534f29dbc25Smrg short vidW, short vidH, short drawW, short drawH, 535f29dbc25Smrg unsigned int *retW, unsigned int *retH, pointer data) 536f29dbc25Smrg{ 537f29dbc25Smrg *retW = drawW > 16384 ? 16384 : drawW; 538f29dbc25Smrg *retH = drawH; 539f29dbc25Smrg} 540f29dbc25Smrg 541f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter; 542f29dbc25Smrg 543f29dbc25Smrgstatic int 544f29dbc25SmrgLXGetPortAttribute(ScrnInfoPtr pScrni, 545f29dbc25Smrg Atom attribute, INT32 * value, pointer data) 546f29dbc25Smrg{ 547f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 548f29dbc25Smrg 549f29dbc25Smrg if (attribute == xvColorKey) 550f29dbc25Smrg *value = pPriv->colorKey; 551f29dbc25Smrg else if (attribute == xvColorKeyMode) 552f29dbc25Smrg *value = pPriv->colorKeyMode; 553f29dbc25Smrg else if (attribute == xvFilter) 554f29dbc25Smrg *value = pPriv->filter; 555f29dbc25Smrg else 556f29dbc25Smrg return BadMatch; 557f29dbc25Smrg 558f29dbc25Smrg return Success; 559f29dbc25Smrg} 560f29dbc25Smrg 561f29dbc25Smrgstatic int 562f29dbc25SmrgLXSetPortAttribute(ScrnInfoPtr pScrni, 563f29dbc25Smrg Atom attribute, INT32 value, pointer data) 564f29dbc25Smrg{ 565f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 566f29dbc25Smrg 567f29dbc25Smrg gp_wait_until_idle(); 568f29dbc25Smrg 569f29dbc25Smrg if (attribute == xvColorKey) { 570f29dbc25Smrg pPriv->colorKey = value; 571f29dbc25Smrg LXSetColorkey(pScrni, pPriv); 572f29dbc25Smrg } else if (attribute == xvColorKeyMode) { 573f29dbc25Smrg pPriv->colorKeyMode = value; 574f29dbc25Smrg LXSetColorkey(pScrni, pPriv); 575f29dbc25Smrg } else if (attribute == xvFilter) { 576f29dbc25Smrg if ((value < 0) || (value > 1)) 577f29dbc25Smrg return BadValue; 578f29dbc25Smrg pPriv->filter = value; 579f29dbc25Smrg } else 580f29dbc25Smrg return BadMatch; 581f29dbc25Smrg 582f29dbc25Smrg return Success; 583f29dbc25Smrg} 584f29dbc25Smrg 585f29dbc25Smrgstatic void 586f29dbc25SmrgLXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 587f29dbc25Smrg{ 588f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 589f29dbc25Smrg 590f29dbc25Smrg if (pPriv->videoStatus == 0) 591f29dbc25Smrg return; 592f29dbc25Smrg 593f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 594f29dbc25Smrg gp_wait_until_idle(); 595f29dbc25Smrg 596f29dbc25Smrg if (exit) { 597f29dbc25Smrg if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 598f29dbc25Smrg unsigned int val; 599f29dbc25Smrg 600f29dbc25Smrg df_set_video_enable(0, 0); 601f29dbc25Smrg /* Put the LUT back in bypass */ 602f29dbc25Smrg val = READ_VID32(DF_VID_MISC); 603f29dbc25Smrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 604f29dbc25Smrg } 605f29dbc25Smrg 606f29dbc25Smrg if (pPriv->vidmem) { 607170d5fdcSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 608f29dbc25Smrg pPriv->vidmem = NULL; 609f29dbc25Smrg } 610f29dbc25Smrg 611f29dbc25Smrg pPriv->videoStatus = 0; 612f29dbc25Smrg 613f29dbc25Smrg /* Eh? */ 614f29dbc25Smrg } else if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 615f29dbc25Smrg pPriv->videoStatus |= OFF_TIMER; 616f29dbc25Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 617f29dbc25Smrg } 618f29dbc25Smrg} 619f29dbc25Smrg 620f29dbc25Smrgstatic void 621f29dbc25SmrgLXResetVideo(ScrnInfoPtr pScrni) 622f29dbc25Smrg{ 623f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 624f29dbc25Smrg 625f29dbc25Smrg if (!pGeode->NoAccel) { 626f29dbc25Smrg GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr; 627f29dbc25Smrg 628f29dbc25Smrg gp_wait_until_idle(); 629f29dbc25Smrg df_set_video_palette(NULL); 630f29dbc25Smrg 631f29dbc25Smrg LXSetColorkey(pScrni, pPriv); 632f29dbc25Smrg } 633f29dbc25Smrg} 634f29dbc25Smrg 635f29dbc25Smrgstatic void 636f29dbc25SmrgLXVidBlockHandler(int i, pointer blockData, pointer pTimeout, 637f29dbc25Smrg pointer pReadmask) 638f29dbc25Smrg{ 639f29dbc25Smrg ScreenPtr pScrn = screenInfo.screens[i]; 640f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[i]; 641f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 642f29dbc25Smrg GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni); 643f29dbc25Smrg 644f29dbc25Smrg pScrn->BlockHandler = pGeode->BlockHandler; 645f29dbc25Smrg (*pScrn->BlockHandler) (i, blockData, pTimeout, pReadmask); 646f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 647f29dbc25Smrg 648f29dbc25Smrg if (pPriv->videoStatus & TIMER_MASK) { 649f29dbc25Smrg Time now = currentTime.milliseconds; 650f29dbc25Smrg 651f29dbc25Smrg if (pPriv->videoStatus & OFF_TIMER) { 652f29dbc25Smrg gp_wait_until_idle(); 653f29dbc25Smrg 654f29dbc25Smrg if (pPriv->offTime < now) { 655f29dbc25Smrg unsigned int val; 656f29dbc25Smrg 657f29dbc25Smrg df_set_video_enable(0, 0); 658f29dbc25Smrg pPriv->videoStatus = FREE_TIMER; 659f29dbc25Smrg pPriv->freeTime = now + FREE_DELAY; 660f29dbc25Smrg 661f29dbc25Smrg /* Turn off the video palette */ 662f29dbc25Smrg val = READ_VID32(DF_VID_MISC); 663f29dbc25Smrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 664f29dbc25Smrg } 665f29dbc25Smrg } else { 666f29dbc25Smrg if (pPriv->freeTime < now) { 667f29dbc25Smrg 668f29dbc25Smrg if (pPriv->vidmem) { 669170d5fdcSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 670f29dbc25Smrg pPriv->vidmem = NULL; 671f29dbc25Smrg } 672f29dbc25Smrg 673f29dbc25Smrg pPriv->videoStatus = 0; 674f29dbc25Smrg } 675f29dbc25Smrg } 676f29dbc25Smrg } 677f29dbc25Smrg} 678f29dbc25Smrg 679f29dbc25Smrgstatic XF86VideoAdaptorPtr 680f29dbc25SmrgLXSetupImageVideo(ScreenPtr pScrn) 681f29dbc25Smrg{ 682f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum]; 683f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 684f29dbc25Smrg XF86VideoAdaptorPtr adapt; 685f29dbc25Smrg GeodePortPrivRec *pPriv; 686f29dbc25Smrg 687170d5fdcSmrg adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 688f29dbc25Smrg sizeof(GeodePortPrivRec) + sizeof(DevUnion)); 689f29dbc25Smrg 690f29dbc25Smrg if (adapt == NULL) { 691f29dbc25Smrg ErrorF("Couldn't create the rec\n"); 692f29dbc25Smrg return NULL; 693f29dbc25Smrg } 694f29dbc25Smrg 695f29dbc25Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 696f29dbc25Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 697f29dbc25Smrg 698f29dbc25Smrg adapt->name = "AMD Geode LX"; 699f29dbc25Smrg adapt->nEncodings = 1; 700f29dbc25Smrg adapt->pEncodings = DummyEncoding; 701f29dbc25Smrg adapt->nFormats = ARRAY_SIZE(Formats); 702f29dbc25Smrg adapt->pFormats = Formats; 703f29dbc25Smrg adapt->nPorts = 1; 704f29dbc25Smrg adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 705f29dbc25Smrg pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]); 706f29dbc25Smrg adapt->pPortPrivates[0].ptr = (pointer) (pPriv); 707f29dbc25Smrg adapt->pAttributes = Attributes; 708f29dbc25Smrg adapt->nImages = ARRAY_SIZE(Images); 709f29dbc25Smrg adapt->nAttributes = ARRAY_SIZE(Attributes); 710f29dbc25Smrg adapt->pImages = Images; 711f29dbc25Smrg adapt->PutVideo = NULL; 712f29dbc25Smrg adapt->PutStill = NULL; 713f29dbc25Smrg adapt->GetVideo = NULL; 714f29dbc25Smrg adapt->GetStill = NULL; 715f29dbc25Smrg adapt->StopVideo = LXStopVideo; 716f29dbc25Smrg adapt->SetPortAttribute = LXSetPortAttribute; 717f29dbc25Smrg adapt->GetPortAttribute = LXGetPortAttribute; 718f29dbc25Smrg adapt->QueryBestSize = LXQueryBestSize; 719f29dbc25Smrg adapt->PutImage = LXPutImage; 720f29dbc25Smrg 721f29dbc25Smrg /* Use the common function */ 722f29dbc25Smrg adapt->QueryImageAttributes = GeodeQueryImageAttributes; 723f29dbc25Smrg 724f29dbc25Smrg pPriv->vidmem = NULL; 725f29dbc25Smrg pPriv->filter = 0; 726f29dbc25Smrg pPriv->colorKey = 0; 727f29dbc25Smrg pPriv->colorKeyMode = 0; 728f29dbc25Smrg pPriv->videoStatus = 0; 729f29dbc25Smrg pPriv->pwidth = 0; 730f29dbc25Smrg pPriv->pheight = 0; 731f29dbc25Smrg 732f29dbc25Smrg REGION_NULL(pScrn, &pPriv->clip); 733f29dbc25Smrg 734f29dbc25Smrg pGeode->adaptor = adapt; 735f29dbc25Smrg 736f29dbc25Smrg pGeode->BlockHandler = pScrn->BlockHandler; 737f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 738f29dbc25Smrg 739f29dbc25Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 740f29dbc25Smrg xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE"); 741f29dbc25Smrg xvFilter = MAKE_ATOM("XV_FILTER"); 742f29dbc25Smrg 743f29dbc25Smrg LXResetVideo(pScrni); 744f29dbc25Smrg 745f29dbc25Smrg return adapt; 746f29dbc25Smrg} 747f29dbc25Smrg 748f29dbc25Smrg/* Offscreen surface allocation */ 749f29dbc25Smrg 750f29dbc25Smrgstruct OffscreenPrivRec 751f29dbc25Smrg{ 752170d5fdcSmrg ExaOffscreenArea *vidmem; 753f29dbc25Smrg Bool isOn; 754f29dbc25Smrg}; 755f29dbc25Smrg 756f29dbc25Smrgstatic int 757f29dbc25SmrgLXDisplaySurface(XF86SurfacePtr surface, 758f29dbc25Smrg short srcX, short srcY, short drawX, short drawY, 759f29dbc25Smrg short srcW, short srcH, short drawW, short drawH, RegionPtr clipBoxes) 760f29dbc25Smrg{ 761f29dbc25Smrg struct OffscreenPrivRec *pPriv = 762f29dbc25Smrg (struct OffscreenPrivRec *)surface->devPrivate.ptr; 763f29dbc25Smrg 764f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 765f29dbc25Smrg GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni); 766f29dbc25Smrg 767f29dbc25Smrg BoxRec dstBox; 768f29dbc25Smrg 769f29dbc25Smrg dstBox.x1 = drawX; 770f29dbc25Smrg dstBox.x2 = drawX + drawW; 771f29dbc25Smrg dstBox.y1 = drawY; 772f29dbc25Smrg dstBox.y2 = drawY + drawH; 773f29dbc25Smrg 774f29dbc25Smrg if ((drawW <= 0) | (drawH <= 0)) 775f29dbc25Smrg return Success; 776f29dbc25Smrg 777f29dbc25Smrg /* Is this still valid? */ 778f29dbc25Smrg 779f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 780f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 781f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 782f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 783f29dbc25Smrg 784f29dbc25Smrg xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes); 785f29dbc25Smrg 786f29dbc25Smrg videoScratch.dstOffset = surface->offsets[0]; 787f29dbc25Smrg videoScratch.dstPitch = surface->pitches[0]; 788f29dbc25Smrg 789f29dbc25Smrg LXDisplayVideo(pScrni, surface->id, surface->width, surface->height, 790f29dbc25Smrg &dstBox, srcW, srcH, drawW, drawH); 791f29dbc25Smrg 792f29dbc25Smrg pPriv->isOn = TRUE; 793f29dbc25Smrg 794f29dbc25Smrg if (portPriv->videoStatus & CLIENT_VIDEO_ON) { 795f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &portPriv->clip); 796f29dbc25Smrg UpdateCurrentTime(); 797f29dbc25Smrg portPriv->videoStatus = FREE_TIMER; 798f29dbc25Smrg portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 799f29dbc25Smrg } 800f29dbc25Smrg 801f29dbc25Smrg return Success; 802f29dbc25Smrg} 803f29dbc25Smrg 804f29dbc25Smrgstatic int 805f29dbc25SmrgLXAllocateSurface(ScrnInfoPtr pScrni, int id, unsigned short w, 806f29dbc25Smrg unsigned short h, XF86SurfacePtr surface) 807f29dbc25Smrg{ 808f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 809f29dbc25Smrg int pitch, lines; 810170d5fdcSmrg ExaOffscreenArea *vidmem; 811f29dbc25Smrg struct OffscreenPrivRec *pPriv; 812f29dbc25Smrg 813f29dbc25Smrg if (w > 1024 || h > 1024) 814f29dbc25Smrg return BadAlloc; 815f29dbc25Smrg 816f29dbc25Smrg /* The width needs to be word aligned */ 817f29dbc25Smrg w = (w + 1) & ~1; 818f29dbc25Smrg 819f29dbc25Smrg pitch = ((w << 1) + 15) & ~15; 820f29dbc25Smrg lines = ((pitch * h) + (pGeode->Pitch - 1)) / pGeode->Pitch; 821f29dbc25Smrg 8227aef237fSmrg /* FIXME: is lines the right parameter to use here, 8237aef237fSmrg * or should it be height * pitch? */ 824170d5fdcSmrg vidmem = exaOffscreenAlloc(pScrni->pScreen, lines, 4, TRUE, 825170d5fdcSmrg NULL, NULL); 826f29dbc25Smrg 827f29dbc25Smrg if (vidmem == NULL) { 828f29dbc25Smrg ErrorF("Error while allocating an offscreen region.\n"); 829f29dbc25Smrg return BadAlloc; 830f29dbc25Smrg } 831f29dbc25Smrg 832f29dbc25Smrg surface->width = w; 833f29dbc25Smrg surface->height = h; 834f29dbc25Smrg 835170d5fdcSmrg surface->pitches = malloc(sizeof(int)); 836f29dbc25Smrg 837170d5fdcSmrg surface->offsets = malloc(sizeof(int)); 838f29dbc25Smrg 839170d5fdcSmrg pPriv = malloc(sizeof(struct OffscreenPrivRec)); 840f29dbc25Smrg 841f29dbc25Smrg if (pPriv && surface->pitches && surface->offsets) { 842f29dbc25Smrg 843f29dbc25Smrg pPriv->vidmem = vidmem; 844f29dbc25Smrg 845f29dbc25Smrg pPriv->isOn = FALSE; 846f29dbc25Smrg 847f29dbc25Smrg surface->pScrn = pScrni; 848f29dbc25Smrg surface->id = id; 849f29dbc25Smrg surface->pitches[0] = pitch; 850f29dbc25Smrg surface->offsets[0] = vidmem->offset; 851f29dbc25Smrg surface->devPrivate.ptr = (pointer) pPriv; 852f29dbc25Smrg 853f29dbc25Smrg return Success; 854f29dbc25Smrg } 855f29dbc25Smrg 856f29dbc25Smrg if (surface->offsets) 857170d5fdcSmrg free(surface->offsets); 858f29dbc25Smrg 859f29dbc25Smrg if (surface->pitches) 860170d5fdcSmrg free(surface->pitches); 861f29dbc25Smrg 862170d5fdcSmrg if (vidmem) { 863170d5fdcSmrg exaOffscreenFree(pScrni->pScreen, vidmem); 864170d5fdcSmrg vidmem = NULL; 865170d5fdcSmrg } 866f29dbc25Smrg 867f29dbc25Smrg return BadAlloc; 868f29dbc25Smrg} 869f29dbc25Smrg 870f29dbc25Smrgstatic int 871f29dbc25SmrgLXStopSurface(XF86SurfacePtr surface) 872f29dbc25Smrg{ 873f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 874f29dbc25Smrg surface->devPrivate.ptr; 875f29dbc25Smrg 876f29dbc25Smrg pPriv->isOn = FALSE; 877f29dbc25Smrg return Success; 878f29dbc25Smrg} 879f29dbc25Smrg 880f29dbc25Smrgstatic int 881f29dbc25SmrgLXFreeSurface(XF86SurfacePtr surface) 882f29dbc25Smrg{ 883f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 884f29dbc25Smrg surface->devPrivate.ptr; 885f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 886f29dbc25Smrg 887f29dbc25Smrg if (pPriv->isOn) 888f29dbc25Smrg LXStopSurface(surface); 889f29dbc25Smrg 890f29dbc25Smrg if (pPriv->vidmem) { 891170d5fdcSmrg exaOffscreenFree(pScrni->pScreen, pPriv->vidmem); 892f29dbc25Smrg pPriv->vidmem = NULL; 893f29dbc25Smrg } 894f29dbc25Smrg 895170d5fdcSmrg free(surface->pitches); 896170d5fdcSmrg free(surface->offsets); 897170d5fdcSmrg free(surface->devPrivate.ptr); 898f29dbc25Smrg 899f29dbc25Smrg return Success; 900f29dbc25Smrg} 901f29dbc25Smrg 902f29dbc25Smrgstatic int 903f29dbc25SmrgLXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value) 904f29dbc25Smrg{ 905f29dbc25Smrg return LXGetPortAttribute(pScrni, attribute, value, 906f29dbc25Smrg (pointer) (GET_PORT_PRIVATE(pScrni))); 907f29dbc25Smrg} 908f29dbc25Smrg 909f29dbc25Smrgstatic int 910f29dbc25SmrgLXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value) 911f29dbc25Smrg{ 912f29dbc25Smrg return LXSetPortAttribute(pScrni, attribute, value, 913f29dbc25Smrg (pointer) (GET_PORT_PRIVATE(pScrni))); 914f29dbc25Smrg} 915f29dbc25Smrg 916f29dbc25Smrgstatic void 917f29dbc25SmrgLXInitOffscreenImages(ScreenPtr pScrn) 918f29dbc25Smrg{ 919f29dbc25Smrg XF86OffscreenImagePtr offscreenImages; 920f29dbc25Smrg 921f29dbc25Smrg /* need to free this someplace */ 922170d5fdcSmrg if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 923f29dbc25Smrg return; 924f29dbc25Smrg 925f29dbc25Smrg offscreenImages[0].image = &Images[0]; 926f29dbc25Smrg offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 927f29dbc25Smrg offscreenImages[0].alloc_surface = LXAllocateSurface; 928f29dbc25Smrg offscreenImages[0].free_surface = LXFreeSurface; 929f29dbc25Smrg offscreenImages[0].display = LXDisplaySurface; 930f29dbc25Smrg offscreenImages[0].stop = LXStopSurface; 931f29dbc25Smrg offscreenImages[0].setAttribute = LXSetSurfaceAttribute; 932f29dbc25Smrg offscreenImages[0].getAttribute = LXGetSurfaceAttribute; 933f29dbc25Smrg offscreenImages[0].max_width = 1024; 934f29dbc25Smrg offscreenImages[0].max_height = 1024; 935f29dbc25Smrg offscreenImages[0].num_attributes = ARRAY_SIZE(Attributes); 936f29dbc25Smrg offscreenImages[0].attributes = Attributes; 937f29dbc25Smrg 938f29dbc25Smrg xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1); 939f29dbc25Smrg} 940f29dbc25Smrg 941f29dbc25Smrgvoid 942f29dbc25SmrgLXInitVideo(ScreenPtr pScrn) 943f29dbc25Smrg{ 944f29dbc25Smrg GeodeRec *pGeode; 945f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum]; 946f29dbc25Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 947f29dbc25Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 948f29dbc25Smrg int num_adaptors; 949f29dbc25Smrg 950f29dbc25Smrg pGeode = GEODEPTR(pScrni); 951f29dbc25Smrg 952f29dbc25Smrg if (pGeode->NoAccel) { 953f29dbc25Smrg ErrorF("Cannot run Xv without accelerations!\n"); 954f29dbc25Smrg return; 955f29dbc25Smrg } 956f29dbc25Smrg 957f29dbc25Smrg if (!(newAdaptor = LXSetupImageVideo(pScrn))) { 958f29dbc25Smrg ErrorF("Error while setting up the adaptor.\n"); 959f29dbc25Smrg return; 960f29dbc25Smrg } 961f29dbc25Smrg 962f29dbc25Smrg LXInitOffscreenImages(pScrn); 963f29dbc25Smrg 964f29dbc25Smrg num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors); 965f29dbc25Smrg 966f29dbc25Smrg if (!num_adaptors) { 967f29dbc25Smrg num_adaptors = 1; 968f29dbc25Smrg adaptors = &newAdaptor; 969f29dbc25Smrg } else { 970f29dbc25Smrg newAdaptors = 971170d5fdcSmrg malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); 972f29dbc25Smrg 973f29dbc25Smrg if (newAdaptors) { 974f29dbc25Smrg memcpy(newAdaptors, adaptors, num_adaptors * 975f29dbc25Smrg sizeof(XF86VideoAdaptorPtr)); 976f29dbc25Smrg newAdaptors[num_adaptors] = newAdaptor; 977f29dbc25Smrg adaptors = newAdaptors; 978f29dbc25Smrg num_adaptors++; 979f29dbc25Smrg } else 980f29dbc25Smrg ErrorF("Memory error while setting up the adaptor\n"); 981f29dbc25Smrg } 982f29dbc25Smrg 983f29dbc25Smrg if (num_adaptors) 984f29dbc25Smrg xf86XVScreenInit(pScrn, adaptors, num_adaptors); 985f29dbc25Smrg 986f29dbc25Smrg if (newAdaptors) 987170d5fdcSmrg free(newAdaptors); 988f29dbc25Smrg} 989