lx_video.c revision f29dbc25
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{ 102f29dbc25Smrg GeodeMemPtr 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); 122f29dbc25Smrg gp_set_bpp(16); 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 191f29dbc25SmrgLXAllocMem(GeodeRec *pGeode, GeodePortPrivRec *pPriv, int size) 192f29dbc25Smrg{ 193f29dbc25Smrg if (!pPriv->vidmem || pPriv->vidmem->size < size) { 194f29dbc25Smrg if (pPriv->vidmem) 195f29dbc25Smrg GeodeFreeOffscreen(pGeode, pPriv->vidmem); 196f29dbc25Smrg 197f29dbc25Smrg pPriv->vidmem = GeodeAllocOffscreen(pGeode, size, 4); 198f29dbc25Smrg 199f29dbc25Smrg if (pPriv->vidmem == NULL) { 200f29dbc25Smrg ErrorF("Could not allocate memory for the video\n"); 201f29dbc25Smrg return FALSE; 202f29dbc25Smrg } 203f29dbc25Smrg } 204f29dbc25Smrg 205f29dbc25Smrg return TRUE; 206f29dbc25Smrg} 207f29dbc25Smrg 208f29dbc25Smrgstatic Bool 209f29dbc25SmrgLXCopyPlanar(ScrnInfoPtr pScrni, int id, unsigned char *buf, 210f29dbc25Smrg short x1, short y1, short x2, short y2, 211f29dbc25Smrg int width, int height, pointer data) 212f29dbc25Smrg{ 213f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 214f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 215f29dbc25Smrg 216f29dbc25Smrg unsigned int YSrcPitch, YDstPitch; 217f29dbc25Smrg unsigned int UVSrcPitch, UVDstPitch; 218f29dbc25Smrg unsigned int YSrcOffset, YDstOffset; 219f29dbc25Smrg unsigned int USrcOffset, UDstOffset; 220f29dbc25Smrg unsigned int VSrcOffset, VDstOffset; 221f29dbc25Smrg 222f29dbc25Smrg unsigned int size, lines, top, left, pixels; 223f29dbc25Smrg 224f29dbc25Smrg YSrcPitch = (width + 3) & ~3; 225f29dbc25Smrg YDstPitch = (width + 31) & ~31; 226f29dbc25Smrg 227f29dbc25Smrg UVSrcPitch = ((width >> 1) + 3) & ~3; 228f29dbc25Smrg UVDstPitch = ((width >> 1) + 15) & ~15; 229f29dbc25Smrg 230f29dbc25Smrg USrcOffset = YSrcPitch * height; 231f29dbc25Smrg VSrcOffset = USrcOffset + (UVSrcPitch * (height >> 1)); 232f29dbc25Smrg 233f29dbc25Smrg UDstOffset = YDstPitch * height; 234f29dbc25Smrg VDstOffset = UDstOffset + (UVDstPitch * (height >> 1)); 235f29dbc25Smrg 236f29dbc25Smrg size = YDstPitch * height; 237f29dbc25Smrg size += UVDstPitch * height; 238f29dbc25Smrg 239f29dbc25Smrg if (LXAllocMem(pGeode, pPriv, size) == FALSE) 240f29dbc25Smrg return FALSE; 241f29dbc25Smrg 242f29dbc25Smrg /* The top of the source region we want to copy */ 243f29dbc25Smrg top = y1 & ~1; 244f29dbc25Smrg 245f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 246f29dbc25Smrg left = x1 & ~1; 247f29dbc25Smrg 248f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 249f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 250f29dbc25Smrg 251f29dbc25Smrg /* Calculate the source offset */ 252f29dbc25Smrg YSrcOffset = (top * YSrcPitch) + left; 253f29dbc25Smrg USrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 254f29dbc25Smrg VSrcOffset += ((top >> 1) * UVSrcPitch) + (left >> 1); 255f29dbc25Smrg 256f29dbc25Smrg /* Calculate the destination offset */ 257f29dbc25Smrg YDstOffset = (top * YDstPitch) + left; 258f29dbc25Smrg UDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 259f29dbc25Smrg VDstOffset += ((top >> 1) * UVDstPitch) + (left >> 1); 260f29dbc25Smrg 261f29dbc25Smrg lines = ((y2 + 1) & ~1) - top; 262f29dbc25Smrg 263f29dbc25Smrg /* Copy Y */ 264f29dbc25Smrg 265f29dbc25Smrg LXCopyFromSys(pGeode, buf + YSrcOffset, 266f29dbc25Smrg pPriv->vidmem->offset + YDstOffset, YDstPitch, YSrcPitch, lines, 267f29dbc25Smrg pixels); 268f29dbc25Smrg 269f29dbc25Smrg /* Copy U + V at the same time */ 270f29dbc25Smrg 271f29dbc25Smrg LXCopyFromSys(pGeode, buf + USrcOffset, 272f29dbc25Smrg pPriv->vidmem->offset + UDstOffset, UVDstPitch, UVSrcPitch, lines, 273f29dbc25Smrg pixels >> 1); 274f29dbc25Smrg 275f29dbc25Smrg videoScratch.dstOffset = pPriv->vidmem->offset + YDstOffset; 276f29dbc25Smrg videoScratch.dstPitch = YDstPitch; 277f29dbc25Smrg videoScratch.UVPitch = UVDstPitch; 278f29dbc25Smrg videoScratch.UDstOffset = pPriv->vidmem->offset + UDstOffset; 279f29dbc25Smrg videoScratch.VDstOffset = pPriv->vidmem->offset + VDstOffset; 280f29dbc25Smrg 281f29dbc25Smrg return TRUE; 282f29dbc25Smrg} 283f29dbc25Smrg 284f29dbc25Smrgstatic Bool 285f29dbc25SmrgLXCopyPacked(ScrnInfoPtr pScrni, int id, unsigned char *buf, 286f29dbc25Smrg short x1, short y1, short x2, short y2, 287f29dbc25Smrg int width, int height, pointer data) 288f29dbc25Smrg{ 289f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 290f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 291f29dbc25Smrg unsigned int dstPitch, srcPitch; 292f29dbc25Smrg unsigned int srcOffset, dstOffset; 293f29dbc25Smrg unsigned int lines, top, left, pixels; 294f29dbc25Smrg 295f29dbc25Smrg dstPitch = ((width << 1) + 3) & ~3; 296f29dbc25Smrg srcPitch = (width << 1); 297f29dbc25Smrg 298f29dbc25Smrg lines = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch; 299f29dbc25Smrg 300f29dbc25Smrg if (LXAllocMem(pGeode, pPriv, lines) == FALSE) 301f29dbc25Smrg return FALSE; 302f29dbc25Smrg 303f29dbc25Smrg /* The top of the source region we want to copy */ 304f29dbc25Smrg top = y1; 305f29dbc25Smrg 306f29dbc25Smrg /* The left hand side of the source region, aligned on a word */ 307f29dbc25Smrg left = x1 & ~1; 308f29dbc25Smrg 309f29dbc25Smrg /* Number of bytes to copy, also word aligned */ 310f29dbc25Smrg pixels = ((x2 + 1) & ~1) - left; 311f29dbc25Smrg 312f29dbc25Smrg /* Adjust the incoming buffer */ 313f29dbc25Smrg srcOffset = (top * srcPitch) + left; 314f29dbc25Smrg 315f29dbc25Smrg /* Calculate the destination offset */ 316f29dbc25Smrg dstOffset = pPriv->vidmem->offset + (top * dstPitch) + left; 317f29dbc25Smrg 318f29dbc25Smrg /* Make the copy happen */ 319f29dbc25Smrg 320f29dbc25Smrg if (id == FOURCC_Y800) { 321f29dbc25Smrg 322f29dbc25Smrg /* Use the shared (unaccelerated) greyscale copy - you could probably 323f29dbc25Smrg * accelerate it using a 2 pass blit and patterns, but it doesn't really 324f29dbc25Smrg * seem worth it 325f29dbc25Smrg */ 326f29dbc25Smrg 327f29dbc25Smrg GeodeCopyGreyscale(buf + srcOffset, pGeode->FBBase + dstOffset, 328f29dbc25Smrg srcPitch, dstPitch, height, pixels >> 1); 329f29dbc25Smrg } else 330f29dbc25Smrg LXCopyFromSys(pGeode, buf + srcOffset, dstOffset, dstPitch, srcPitch, 331f29dbc25Smrg height, pixels); 332f29dbc25Smrg 333f29dbc25Smrg videoScratch.dstOffset = dstOffset; 334f29dbc25Smrg videoScratch.dstPitch = dstPitch; 335f29dbc25Smrg 336f29dbc25Smrg return TRUE; 337f29dbc25Smrg} 338f29dbc25Smrg 339f29dbc25Smrgstatic void 340f29dbc25SmrgLXDisplayVideo(ScrnInfoPtr pScrni, int id, short width, short height, 341f29dbc25Smrg BoxPtr dstBox, short srcW, short srcH, short drawW, short drawH) 342f29dbc25Smrg{ 343f29dbc25Smrg long ystart, xend, yend; 344f29dbc25Smrg unsigned long lines = 0; 345f29dbc25Smrg unsigned long yExtra, uvExtra = 0; 346f29dbc25Smrg DF_VIDEO_POSITION vidPos; 347f29dbc25Smrg DF_VIDEO_SOURCE_PARAMS vSrcParams; 348f29dbc25Smrg int err; 349f29dbc25Smrg 350f29dbc25Smrg memset(&vSrcParams, 0, sizeof(vSrcParams)); 351f29dbc25Smrg 352f29dbc25Smrg gp_wait_until_idle(); 353f29dbc25Smrg 354f29dbc25Smrg switch (id) { 355f29dbc25Smrg case FOURCC_UYVY: 356f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_UYVY; 357f29dbc25Smrg break; 358f29dbc25Smrg 359f29dbc25Smrg case FOURCC_Y800: 360f29dbc25Smrg case FOURCC_YV12: 361f29dbc25Smrg case FOURCC_I420: 362f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_Y0Y1Y2Y3; 363f29dbc25Smrg break; 364f29dbc25Smrg case FOURCC_YUY2: 365f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_YUYV; 366f29dbc25Smrg break; 367f29dbc25Smrg case FOURCC_Y2YU: 368f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_Y2YU; 369f29dbc25Smrg break; 370f29dbc25Smrg case FOURCC_YVYU: 371f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_YVYU; 372f29dbc25Smrg break; 373f29dbc25Smrg case FOURCC_RGB565: 374f29dbc25Smrg vSrcParams.video_format = DF_VIDFMT_RGB; 375f29dbc25Smrg break; 376f29dbc25Smrg } 377f29dbc25Smrg 378f29dbc25Smrg vSrcParams.width = width; 379f29dbc25Smrg vSrcParams.height = height; 380f29dbc25Smrg vSrcParams.y_pitch = videoScratch.dstPitch; 381f29dbc25Smrg vSrcParams.uv_pitch = videoScratch.UVPitch; 382f29dbc25Smrg 383f29dbc25Smrg /* Set up scaling */ 384f29dbc25Smrg df_set_video_filter_coefficients(NULL, 1); 385f29dbc25Smrg 386f29dbc25Smrg err = df_set_video_scale(width, height, drawW, drawH, 387f29dbc25Smrg DF_SCALEFLAG_CHANGEX | DF_SCALEFLAG_CHANGEY); 388f29dbc25Smrg if (err != CIM_STATUS_OK) { 389f29dbc25Smrg /* Note the problem, but do nothing for now. */ 390f29dbc25Smrg ErrorF("Video scale factor too large: %dx%d -> %dx%d\n", 391f29dbc25Smrg width, height, drawW, drawH); 392f29dbc25Smrg } 393f29dbc25Smrg 394f29dbc25Smrg /* Figure out clipping */ 395f29dbc25Smrg 396f29dbc25Smrg xend = dstBox->x2; 397f29dbc25Smrg yend = dstBox->y2; 398f29dbc25Smrg 399f29dbc25Smrg if (dstBox->y1 < 0) { 400f29dbc25Smrg if (srcH < drawH) 401f29dbc25Smrg lines = ((-dstBox->y1) * srcH) / drawH; 402f29dbc25Smrg else 403f29dbc25Smrg lines = (-dstBox->y1); 404f29dbc25Smrg 405f29dbc25Smrg ystart = 0; 406f29dbc25Smrg drawH += dstBox->y1; 407f29dbc25Smrg } else { 408f29dbc25Smrg ystart = dstBox->y1; 409f29dbc25Smrg lines = 0; 410f29dbc25Smrg } 411f29dbc25Smrg 412f29dbc25Smrg yExtra = lines * videoScratch.dstPitch; 413f29dbc25Smrg uvExtra = (lines >> 1) * videoScratch.UVPitch; 414f29dbc25Smrg 415f29dbc25Smrg memset(&vidPos, 0, sizeof(vidPos)); 416f29dbc25Smrg 417f29dbc25Smrg vidPos.x = dstBox->x1; 418f29dbc25Smrg vidPos.y = ystart; 419f29dbc25Smrg vidPos.width = xend - dstBox->x1; 420f29dbc25Smrg vidPos.height = yend - ystart; 421f29dbc25Smrg 422f29dbc25Smrg df_set_video_position(&vidPos); 423f29dbc25Smrg 424f29dbc25Smrg vSrcParams.y_offset = videoScratch.dstOffset + yExtra; 425f29dbc25Smrg 426f29dbc25Smrg switch (id) { 427f29dbc25Smrg case FOURCC_Y800: 428f29dbc25Smrg case FOURCC_I420: 429f29dbc25Smrg vSrcParams.u_offset = videoScratch.UDstOffset + uvExtra; 430f29dbc25Smrg vSrcParams.v_offset = videoScratch.VDstOffset + uvExtra; 431f29dbc25Smrg break; 432f29dbc25Smrg case FOURCC_YV12: 433f29dbc25Smrg vSrcParams.v_offset = videoScratch.UDstOffset + uvExtra; 434f29dbc25Smrg vSrcParams.u_offset = videoScratch.VDstOffset + uvExtra; 435f29dbc25Smrg break; 436f29dbc25Smrg 437f29dbc25Smrg default: 438f29dbc25Smrg vSrcParams.u_offset = vSrcParams.v_offset = 0; 439f29dbc25Smrg break; 440f29dbc25Smrg } 441f29dbc25Smrg 442f29dbc25Smrg vSrcParams.flags = DF_SOURCEFLAG_IMPLICITSCALING; 443f29dbc25Smrg df_configure_video_source(&vSrcParams, &vSrcParams); 444f29dbc25Smrg 445f29dbc25Smrg /* Turn on the video palette */ 446f29dbc25Smrg df_set_video_palette(NULL); 447f29dbc25Smrg df_set_video_enable(1, 0); 448f29dbc25Smrg} 449f29dbc25Smrg 450f29dbc25Smrgstatic int 451f29dbc25SmrgLXPutImage(ScrnInfoPtr pScrni, 452f29dbc25Smrg short srcX, short srcY, short drawX, short drawY, 453f29dbc25Smrg short srcW, short srcH, short drawW, short drawH, 454f29dbc25Smrg int id, unsigned char *buf, 455f29dbc25Smrg short width, short height, Bool sync, RegionPtr clipBoxes, 456f29dbc25Smrg pointer data, DrawablePtr pDraw) 457f29dbc25Smrg{ 458f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 459f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 460f29dbc25Smrg INT32 x1, x2, y1, y2; 461f29dbc25Smrg BoxRec dstBox; 462f29dbc25Smrg Bool ret; 463f29dbc25Smrg 464f29dbc25Smrg if (pGeode->rotation != RR_Rotate_0) 465f29dbc25Smrg return Success; 466f29dbc25Smrg 467f29dbc25Smrg if (srcW <= 0 || srcH <= 0) { 468f29dbc25Smrg return Success; 469f29dbc25Smrg } 470f29dbc25Smrg 471f29dbc25Smrg if (drawW <= 0 || drawH <= 0) { 472f29dbc25Smrg return Success; 473f29dbc25Smrg } 474f29dbc25Smrg 475f29dbc25Smrg if (drawW > 16384) 476f29dbc25Smrg drawW = 16384; 477f29dbc25Smrg 478f29dbc25Smrg memset(&videoScratch, 0, sizeof(videoScratch)); 479f29dbc25Smrg 480f29dbc25Smrg x1 = srcX; 481f29dbc25Smrg x2 = srcX + srcW; 482f29dbc25Smrg y1 = srcY; 483f29dbc25Smrg y2 = srcY + srcH; 484f29dbc25Smrg 485f29dbc25Smrg dstBox.x1 = drawX; 486f29dbc25Smrg dstBox.x2 = drawX + drawW; 487f29dbc25Smrg dstBox.y1 = drawY; 488f29dbc25Smrg dstBox.y2 = drawY + drawH; 489f29dbc25Smrg 490f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 491f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 492f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 493f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 494f29dbc25Smrg 495f29dbc25Smrg if (id == FOURCC_YV12 || id == FOURCC_I420) 496f29dbc25Smrg ret = LXCopyPlanar(pScrni, id, buf, x1, y1, x2, y2, width, 497f29dbc25Smrg height, data); 498f29dbc25Smrg else 499f29dbc25Smrg ret = LXCopyPacked(pScrni, id, buf, x1, y1, x2, y2, width, 500f29dbc25Smrg height, data); 501f29dbc25Smrg 502f29dbc25Smrg if (ret == FALSE) 503f29dbc25Smrg return BadAlloc; 504f29dbc25Smrg 505f29dbc25Smrg if (!RegionsEqual(&pPriv->clip, clipBoxes) || 506f29dbc25Smrg (drawW != pPriv->pwidth || drawH != pPriv->pheight)) { 507f29dbc25Smrg REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes); 508f29dbc25Smrg 509f29dbc25Smrg if (pPriv->colorKeyMode == 0) { 510f29dbc25Smrg xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes); 511f29dbc25Smrg } 512f29dbc25Smrg 513f29dbc25Smrg LXDisplayVideo(pScrni, id, width, height, &dstBox, 514f29dbc25Smrg srcW, srcH, drawW, drawH); 515f29dbc25Smrg pPriv->pwidth = drawW; 516f29dbc25Smrg pPriv->pheight = drawH; 517f29dbc25Smrg } 518f29dbc25Smrg 519f29dbc25Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 520f29dbc25Smrg 521f29dbc25Smrg return Success; 522f29dbc25Smrg} 523f29dbc25Smrg 524f29dbc25Smrgstatic void 525f29dbc25SmrgLXQueryBestSize(ScrnInfoPtr pScrni, Bool motion, 526f29dbc25Smrg short vidW, short vidH, short drawW, short drawH, 527f29dbc25Smrg unsigned int *retW, unsigned int *retH, pointer data) 528f29dbc25Smrg{ 529f29dbc25Smrg *retW = drawW > 16384 ? 16384 : drawW; 530f29dbc25Smrg *retH = drawH; 531f29dbc25Smrg} 532f29dbc25Smrg 533f29dbc25Smrgstatic Atom xvColorKey, xvColorKeyMode, xvFilter; 534f29dbc25Smrg 535f29dbc25Smrgstatic int 536f29dbc25SmrgLXGetPortAttribute(ScrnInfoPtr pScrni, 537f29dbc25Smrg Atom attribute, INT32 * value, pointer data) 538f29dbc25Smrg{ 539f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 540f29dbc25Smrg 541f29dbc25Smrg if (attribute == xvColorKey) 542f29dbc25Smrg *value = pPriv->colorKey; 543f29dbc25Smrg else if (attribute == xvColorKeyMode) 544f29dbc25Smrg *value = pPriv->colorKeyMode; 545f29dbc25Smrg else if (attribute == xvFilter) 546f29dbc25Smrg *value = pPriv->filter; 547f29dbc25Smrg else 548f29dbc25Smrg return BadMatch; 549f29dbc25Smrg 550f29dbc25Smrg return Success; 551f29dbc25Smrg} 552f29dbc25Smrg 553f29dbc25Smrgstatic int 554f29dbc25SmrgLXSetPortAttribute(ScrnInfoPtr pScrni, 555f29dbc25Smrg Atom attribute, INT32 value, pointer data) 556f29dbc25Smrg{ 557f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 558f29dbc25Smrg 559f29dbc25Smrg gp_wait_until_idle(); 560f29dbc25Smrg 561f29dbc25Smrg if (attribute == xvColorKey) { 562f29dbc25Smrg pPriv->colorKey = value; 563f29dbc25Smrg LXSetColorkey(pScrni, pPriv); 564f29dbc25Smrg } else if (attribute == xvColorKeyMode) { 565f29dbc25Smrg pPriv->colorKeyMode = value; 566f29dbc25Smrg LXSetColorkey(pScrni, pPriv); 567f29dbc25Smrg } else if (attribute == xvFilter) { 568f29dbc25Smrg if ((value < 0) || (value > 1)) 569f29dbc25Smrg return BadValue; 570f29dbc25Smrg pPriv->filter = value; 571f29dbc25Smrg } else 572f29dbc25Smrg return BadMatch; 573f29dbc25Smrg 574f29dbc25Smrg return Success; 575f29dbc25Smrg} 576f29dbc25Smrg 577f29dbc25Smrgstatic void 578f29dbc25SmrgLXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 579f29dbc25Smrg{ 580f29dbc25Smrg GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 581f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 582f29dbc25Smrg 583f29dbc25Smrg if (pPriv->videoStatus == 0) 584f29dbc25Smrg return; 585f29dbc25Smrg 586f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 587f29dbc25Smrg gp_wait_until_idle(); 588f29dbc25Smrg 589f29dbc25Smrg if (exit) { 590f29dbc25Smrg if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 591f29dbc25Smrg unsigned int val; 592f29dbc25Smrg 593f29dbc25Smrg df_set_video_enable(0, 0); 594f29dbc25Smrg /* Put the LUT back in bypass */ 595f29dbc25Smrg val = READ_VID32(DF_VID_MISC); 596f29dbc25Smrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 597f29dbc25Smrg } 598f29dbc25Smrg 599f29dbc25Smrg if (pPriv->vidmem) { 600f29dbc25Smrg GeodeFreeOffscreen(pGeode, pPriv->vidmem); 601f29dbc25Smrg pPriv->vidmem = NULL; 602f29dbc25Smrg } 603f29dbc25Smrg 604f29dbc25Smrg pPriv->videoStatus = 0; 605f29dbc25Smrg 606f29dbc25Smrg /* Eh? */ 607f29dbc25Smrg } else if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 608f29dbc25Smrg pPriv->videoStatus |= OFF_TIMER; 609f29dbc25Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 610f29dbc25Smrg } 611f29dbc25Smrg} 612f29dbc25Smrg 613f29dbc25Smrgstatic void 614f29dbc25SmrgLXResetVideo(ScrnInfoPtr pScrni) 615f29dbc25Smrg{ 616f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 617f29dbc25Smrg 618f29dbc25Smrg if (!pGeode->NoAccel) { 619f29dbc25Smrg GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr; 620f29dbc25Smrg 621f29dbc25Smrg gp_wait_until_idle(); 622f29dbc25Smrg df_set_video_palette(NULL); 623f29dbc25Smrg 624f29dbc25Smrg LXSetColorkey(pScrni, pPriv); 625f29dbc25Smrg } 626f29dbc25Smrg} 627f29dbc25Smrg 628f29dbc25Smrgstatic void 629f29dbc25SmrgLXVidBlockHandler(int i, pointer blockData, pointer pTimeout, 630f29dbc25Smrg pointer pReadmask) 631f29dbc25Smrg{ 632f29dbc25Smrg ScreenPtr pScrn = screenInfo.screens[i]; 633f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[i]; 634f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 635f29dbc25Smrg GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni); 636f29dbc25Smrg 637f29dbc25Smrg pScrn->BlockHandler = pGeode->BlockHandler; 638f29dbc25Smrg (*pScrn->BlockHandler) (i, blockData, pTimeout, pReadmask); 639f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 640f29dbc25Smrg 641f29dbc25Smrg if (pPriv->videoStatus & TIMER_MASK) { 642f29dbc25Smrg Time now = currentTime.milliseconds; 643f29dbc25Smrg 644f29dbc25Smrg if (pPriv->videoStatus & OFF_TIMER) { 645f29dbc25Smrg gp_wait_until_idle(); 646f29dbc25Smrg 647f29dbc25Smrg if (pPriv->offTime < now) { 648f29dbc25Smrg unsigned int val; 649f29dbc25Smrg 650f29dbc25Smrg df_set_video_enable(0, 0); 651f29dbc25Smrg pPriv->videoStatus = FREE_TIMER; 652f29dbc25Smrg pPriv->freeTime = now + FREE_DELAY; 653f29dbc25Smrg 654f29dbc25Smrg /* Turn off the video palette */ 655f29dbc25Smrg val = READ_VID32(DF_VID_MISC); 656f29dbc25Smrg WRITE_VID32(DF_VID_MISC, val | DF_GAMMA_BYPASS_BOTH); 657f29dbc25Smrg } 658f29dbc25Smrg } else { 659f29dbc25Smrg if (pPriv->freeTime < now) { 660f29dbc25Smrg 661f29dbc25Smrg if (pPriv->vidmem) { 662f29dbc25Smrg GeodeFreeOffscreen(pGeode, pPriv->vidmem); 663f29dbc25Smrg pPriv->vidmem = NULL; 664f29dbc25Smrg } 665f29dbc25Smrg 666f29dbc25Smrg pPriv->videoStatus = 0; 667f29dbc25Smrg } 668f29dbc25Smrg } 669f29dbc25Smrg } 670f29dbc25Smrg} 671f29dbc25Smrg 672f29dbc25Smrgstatic XF86VideoAdaptorPtr 673f29dbc25SmrgLXSetupImageVideo(ScreenPtr pScrn) 674f29dbc25Smrg{ 675f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum]; 676f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 677f29dbc25Smrg XF86VideoAdaptorPtr adapt; 678f29dbc25Smrg GeodePortPrivRec *pPriv; 679f29dbc25Smrg 680f29dbc25Smrg adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 681f29dbc25Smrg sizeof(GeodePortPrivRec) + sizeof(DevUnion)); 682f29dbc25Smrg 683f29dbc25Smrg if (adapt == NULL) { 684f29dbc25Smrg ErrorF("Couldn't create the rec\n"); 685f29dbc25Smrg return NULL; 686f29dbc25Smrg } 687f29dbc25Smrg 688f29dbc25Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 689f29dbc25Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 690f29dbc25Smrg 691f29dbc25Smrg adapt->name = "AMD Geode LX"; 692f29dbc25Smrg adapt->nEncodings = 1; 693f29dbc25Smrg adapt->pEncodings = DummyEncoding; 694f29dbc25Smrg adapt->nFormats = ARRAY_SIZE(Formats); 695f29dbc25Smrg adapt->pFormats = Formats; 696f29dbc25Smrg adapt->nPorts = 1; 697f29dbc25Smrg adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 698f29dbc25Smrg pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]); 699f29dbc25Smrg adapt->pPortPrivates[0].ptr = (pointer) (pPriv); 700f29dbc25Smrg adapt->pAttributes = Attributes; 701f29dbc25Smrg adapt->nImages = ARRAY_SIZE(Images); 702f29dbc25Smrg adapt->nAttributes = ARRAY_SIZE(Attributes); 703f29dbc25Smrg adapt->pImages = Images; 704f29dbc25Smrg adapt->PutVideo = NULL; 705f29dbc25Smrg adapt->PutStill = NULL; 706f29dbc25Smrg adapt->GetVideo = NULL; 707f29dbc25Smrg adapt->GetStill = NULL; 708f29dbc25Smrg adapt->StopVideo = LXStopVideo; 709f29dbc25Smrg adapt->SetPortAttribute = LXSetPortAttribute; 710f29dbc25Smrg adapt->GetPortAttribute = LXGetPortAttribute; 711f29dbc25Smrg adapt->QueryBestSize = LXQueryBestSize; 712f29dbc25Smrg adapt->PutImage = LXPutImage; 713f29dbc25Smrg 714f29dbc25Smrg /* Use the common function */ 715f29dbc25Smrg adapt->QueryImageAttributes = GeodeQueryImageAttributes; 716f29dbc25Smrg 717f29dbc25Smrg pPriv->vidmem = NULL; 718f29dbc25Smrg pPriv->filter = 0; 719f29dbc25Smrg pPriv->colorKey = 0; 720f29dbc25Smrg pPriv->colorKeyMode = 0; 721f29dbc25Smrg pPriv->videoStatus = 0; 722f29dbc25Smrg pPriv->pwidth = 0; 723f29dbc25Smrg pPriv->pheight = 0; 724f29dbc25Smrg 725f29dbc25Smrg REGION_NULL(pScrn, &pPriv->clip); 726f29dbc25Smrg 727f29dbc25Smrg pGeode->adaptor = adapt; 728f29dbc25Smrg 729f29dbc25Smrg pGeode->BlockHandler = pScrn->BlockHandler; 730f29dbc25Smrg pScrn->BlockHandler = LXVidBlockHandler; 731f29dbc25Smrg 732f29dbc25Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 733f29dbc25Smrg xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE"); 734f29dbc25Smrg xvFilter = MAKE_ATOM("XV_FILTER"); 735f29dbc25Smrg 736f29dbc25Smrg LXResetVideo(pScrni); 737f29dbc25Smrg 738f29dbc25Smrg return adapt; 739f29dbc25Smrg} 740f29dbc25Smrg 741f29dbc25Smrg/* Offscreen surface allocation */ 742f29dbc25Smrg 743f29dbc25Smrgstruct OffscreenPrivRec 744f29dbc25Smrg{ 745f29dbc25Smrg GeodeMemPtr vidmem; 746f29dbc25Smrg Bool isOn; 747f29dbc25Smrg}; 748f29dbc25Smrg 749f29dbc25Smrgstatic int 750f29dbc25SmrgLXDisplaySurface(XF86SurfacePtr surface, 751f29dbc25Smrg short srcX, short srcY, short drawX, short drawY, 752f29dbc25Smrg short srcW, short srcH, short drawW, short drawH, RegionPtr clipBoxes) 753f29dbc25Smrg{ 754f29dbc25Smrg struct OffscreenPrivRec *pPriv = 755f29dbc25Smrg (struct OffscreenPrivRec *)surface->devPrivate.ptr; 756f29dbc25Smrg 757f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 758f29dbc25Smrg GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni); 759f29dbc25Smrg 760f29dbc25Smrg BoxRec dstBox; 761f29dbc25Smrg 762f29dbc25Smrg dstBox.x1 = drawX; 763f29dbc25Smrg dstBox.x2 = drawX + drawW; 764f29dbc25Smrg dstBox.y1 = drawY; 765f29dbc25Smrg dstBox.y2 = drawY + drawH; 766f29dbc25Smrg 767f29dbc25Smrg if ((drawW <= 0) | (drawH <= 0)) 768f29dbc25Smrg return Success; 769f29dbc25Smrg 770f29dbc25Smrg /* Is this still valid? */ 771f29dbc25Smrg 772f29dbc25Smrg dstBox.x1 -= pScrni->frameX0; 773f29dbc25Smrg dstBox.x2 -= pScrni->frameX0; 774f29dbc25Smrg dstBox.y1 -= pScrni->frameY0; 775f29dbc25Smrg dstBox.y2 -= pScrni->frameY0; 776f29dbc25Smrg 777f29dbc25Smrg xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes); 778f29dbc25Smrg 779f29dbc25Smrg videoScratch.dstOffset = surface->offsets[0]; 780f29dbc25Smrg videoScratch.dstPitch = surface->pitches[0]; 781f29dbc25Smrg 782f29dbc25Smrg LXDisplayVideo(pScrni, surface->id, surface->width, surface->height, 783f29dbc25Smrg &dstBox, srcW, srcH, drawW, drawH); 784f29dbc25Smrg 785f29dbc25Smrg pPriv->isOn = TRUE; 786f29dbc25Smrg 787f29dbc25Smrg if (portPriv->videoStatus & CLIENT_VIDEO_ON) { 788f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &portPriv->clip); 789f29dbc25Smrg UpdateCurrentTime(); 790f29dbc25Smrg portPriv->videoStatus = FREE_TIMER; 791f29dbc25Smrg portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 792f29dbc25Smrg } 793f29dbc25Smrg 794f29dbc25Smrg return Success; 795f29dbc25Smrg} 796f29dbc25Smrg 797f29dbc25Smrgstatic int 798f29dbc25SmrgLXAllocateSurface(ScrnInfoPtr pScrni, int id, unsigned short w, 799f29dbc25Smrg unsigned short h, XF86SurfacePtr surface) 800f29dbc25Smrg{ 801f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 802f29dbc25Smrg int pitch, lines; 803f29dbc25Smrg GeodeMemPtr vidmem; 804f29dbc25Smrg struct OffscreenPrivRec *pPriv; 805f29dbc25Smrg 806f29dbc25Smrg if (w > 1024 || h > 1024) 807f29dbc25Smrg return BadAlloc; 808f29dbc25Smrg 809f29dbc25Smrg /* The width needs to be word aligned */ 810f29dbc25Smrg w = (w + 1) & ~1; 811f29dbc25Smrg 812f29dbc25Smrg pitch = ((w << 1) + 15) & ~15; 813f29dbc25Smrg lines = ((pitch * h) + (pGeode->Pitch - 1)) / pGeode->Pitch; 814f29dbc25Smrg 815f29dbc25Smrg vidmem = GeodeAllocOffscreen(pGeode, lines, 4); 816f29dbc25Smrg 817f29dbc25Smrg if (vidmem == NULL) { 818f29dbc25Smrg ErrorF("Error while allocating an offscreen region.\n"); 819f29dbc25Smrg return BadAlloc; 820f29dbc25Smrg } 821f29dbc25Smrg 822f29dbc25Smrg surface->width = w; 823f29dbc25Smrg surface->height = h; 824f29dbc25Smrg 825f29dbc25Smrg surface->pitches = xalloc(sizeof(int)); 826f29dbc25Smrg 827f29dbc25Smrg surface->offsets = xalloc(sizeof(int)); 828f29dbc25Smrg 829f29dbc25Smrg pPriv = xalloc(sizeof(struct OffscreenPrivRec)); 830f29dbc25Smrg 831f29dbc25Smrg if (pPriv && surface->pitches && surface->offsets) { 832f29dbc25Smrg 833f29dbc25Smrg pPriv->vidmem = vidmem; 834f29dbc25Smrg 835f29dbc25Smrg pPriv->isOn = FALSE; 836f29dbc25Smrg 837f29dbc25Smrg surface->pScrn = pScrni; 838f29dbc25Smrg surface->id = id; 839f29dbc25Smrg surface->pitches[0] = pitch; 840f29dbc25Smrg surface->offsets[0] = vidmem->offset; 841f29dbc25Smrg surface->devPrivate.ptr = (pointer) pPriv; 842f29dbc25Smrg 843f29dbc25Smrg return Success; 844f29dbc25Smrg } 845f29dbc25Smrg 846f29dbc25Smrg if (surface->offsets) 847f29dbc25Smrg xfree(surface->offsets); 848f29dbc25Smrg 849f29dbc25Smrg if (surface->pitches) 850f29dbc25Smrg xfree(surface->pitches); 851f29dbc25Smrg 852f29dbc25Smrg if (vidmem) 853f29dbc25Smrg GeodeFreeOffscreen(pGeode, vidmem); 854f29dbc25Smrg 855f29dbc25Smrg return BadAlloc; 856f29dbc25Smrg} 857f29dbc25Smrg 858f29dbc25Smrgstatic int 859f29dbc25SmrgLXStopSurface(XF86SurfacePtr surface) 860f29dbc25Smrg{ 861f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 862f29dbc25Smrg surface->devPrivate.ptr; 863f29dbc25Smrg 864f29dbc25Smrg pPriv->isOn = FALSE; 865f29dbc25Smrg return Success; 866f29dbc25Smrg} 867f29dbc25Smrg 868f29dbc25Smrgstatic int 869f29dbc25SmrgLXFreeSurface(XF86SurfacePtr surface) 870f29dbc25Smrg{ 871f29dbc25Smrg struct OffscreenPrivRec *pPriv = (struct OffscreenPrivRec *) 872f29dbc25Smrg surface->devPrivate.ptr; 873f29dbc25Smrg ScrnInfoPtr pScrni = surface->pScrn; 874f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 875f29dbc25Smrg 876f29dbc25Smrg if (pPriv->isOn) 877f29dbc25Smrg LXStopSurface(surface); 878f29dbc25Smrg 879f29dbc25Smrg if (pPriv->vidmem) { 880f29dbc25Smrg GeodeFreeOffscreen(pGeode, pPriv->vidmem); 881f29dbc25Smrg pPriv->vidmem = NULL; 882f29dbc25Smrg } 883f29dbc25Smrg 884f29dbc25Smrg xfree(surface->pitches); 885f29dbc25Smrg xfree(surface->offsets); 886f29dbc25Smrg xfree(surface->devPrivate.ptr); 887f29dbc25Smrg 888f29dbc25Smrg return Success; 889f29dbc25Smrg} 890f29dbc25Smrg 891f29dbc25Smrgstatic int 892f29dbc25SmrgLXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value) 893f29dbc25Smrg{ 894f29dbc25Smrg return LXGetPortAttribute(pScrni, attribute, value, 895f29dbc25Smrg (pointer) (GET_PORT_PRIVATE(pScrni))); 896f29dbc25Smrg} 897f29dbc25Smrg 898f29dbc25Smrgstatic int 899f29dbc25SmrgLXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value) 900f29dbc25Smrg{ 901f29dbc25Smrg return LXSetPortAttribute(pScrni, attribute, value, 902f29dbc25Smrg (pointer) (GET_PORT_PRIVATE(pScrni))); 903f29dbc25Smrg} 904f29dbc25Smrg 905f29dbc25Smrgstatic void 906f29dbc25SmrgLXInitOffscreenImages(ScreenPtr pScrn) 907f29dbc25Smrg{ 908f29dbc25Smrg XF86OffscreenImagePtr offscreenImages; 909f29dbc25Smrg 910f29dbc25Smrg /* need to free this someplace */ 911f29dbc25Smrg if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) 912f29dbc25Smrg return; 913f29dbc25Smrg 914f29dbc25Smrg offscreenImages[0].image = &Images[0]; 915f29dbc25Smrg offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 916f29dbc25Smrg offscreenImages[0].alloc_surface = LXAllocateSurface; 917f29dbc25Smrg offscreenImages[0].free_surface = LXFreeSurface; 918f29dbc25Smrg offscreenImages[0].display = LXDisplaySurface; 919f29dbc25Smrg offscreenImages[0].stop = LXStopSurface; 920f29dbc25Smrg offscreenImages[0].setAttribute = LXSetSurfaceAttribute; 921f29dbc25Smrg offscreenImages[0].getAttribute = LXGetSurfaceAttribute; 922f29dbc25Smrg offscreenImages[0].max_width = 1024; 923f29dbc25Smrg offscreenImages[0].max_height = 1024; 924f29dbc25Smrg offscreenImages[0].num_attributes = ARRAY_SIZE(Attributes); 925f29dbc25Smrg offscreenImages[0].attributes = Attributes; 926f29dbc25Smrg 927f29dbc25Smrg xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1); 928f29dbc25Smrg} 929f29dbc25Smrg 930f29dbc25Smrgvoid 931f29dbc25SmrgLXInitVideo(ScreenPtr pScrn) 932f29dbc25Smrg{ 933f29dbc25Smrg GeodeRec *pGeode; 934f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum]; 935f29dbc25Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 936f29dbc25Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 937f29dbc25Smrg int num_adaptors; 938f29dbc25Smrg 939f29dbc25Smrg pGeode = GEODEPTR(pScrni); 940f29dbc25Smrg 941f29dbc25Smrg if (pGeode->NoAccel) { 942f29dbc25Smrg ErrorF("Cannot run Xv without accelerations!\n"); 943f29dbc25Smrg return; 944f29dbc25Smrg } 945f29dbc25Smrg 946f29dbc25Smrg if (!(newAdaptor = LXSetupImageVideo(pScrn))) { 947f29dbc25Smrg ErrorF("Error while setting up the adaptor.\n"); 948f29dbc25Smrg return; 949f29dbc25Smrg } 950f29dbc25Smrg 951f29dbc25Smrg LXInitOffscreenImages(pScrn); 952f29dbc25Smrg 953f29dbc25Smrg num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors); 954f29dbc25Smrg 955f29dbc25Smrg if (!num_adaptors) { 956f29dbc25Smrg num_adaptors = 1; 957f29dbc25Smrg adaptors = &newAdaptor; 958f29dbc25Smrg } else { 959f29dbc25Smrg newAdaptors = 960f29dbc25Smrg xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); 961f29dbc25Smrg 962f29dbc25Smrg if (newAdaptors) { 963f29dbc25Smrg memcpy(newAdaptors, adaptors, num_adaptors * 964f29dbc25Smrg sizeof(XF86VideoAdaptorPtr)); 965f29dbc25Smrg newAdaptors[num_adaptors] = newAdaptor; 966f29dbc25Smrg adaptors = newAdaptors; 967f29dbc25Smrg num_adaptors++; 968f29dbc25Smrg } else 969f29dbc25Smrg ErrorF("Memory error while setting up the adaptor\n"); 970f29dbc25Smrg } 971f29dbc25Smrg 972f29dbc25Smrg if (num_adaptors) 973f29dbc25Smrg xf86XVScreenInit(pScrn, adaptors, num_adaptors); 974f29dbc25Smrg 975f29dbc25Smrg if (newAdaptors) 976f29dbc25Smrg xfree(newAdaptors); 977f29dbc25Smrg} 978