radeon_textured_video.c revision 921a55d8
1/* 2 * Copyright 2008 Alex Deucher 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * 24 * Based on radeon_exa_render.c and kdrive ati_video.c by Eric Anholt, et al. 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include <stdlib.h> 33#include <string.h> 34#include <stdio.h> 35#include <math.h> 36 37#include "radeon.h" 38#include "radeon_reg.h" 39#include "radeon_macros.h" 40#include "radeon_probe.h" 41#include "radeon_video.h" 42 43#include <X11/extensions/Xv.h> 44#include "fourcc.h" 45 46extern void 47R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); 48 49#ifdef XF86DRM_MODE 50extern void 51EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); 52#endif 53 54extern Bool 55R600CopyToVRAM(ScrnInfoPtr pScrn, 56 char *src, int src_pitch, 57 uint32_t dst_pitch, uint32_t dst_mc_addr, uint32_t dst_width, uint32_t dst_height, int bpp, 58 int x, int y, int w, int h); 59 60#define IMAGE_MAX_WIDTH 2048 61#define IMAGE_MAX_HEIGHT 2048 62 63#define IMAGE_MAX_WIDTH_R500 4096 64#define IMAGE_MAX_HEIGHT_R500 4096 65 66#define IMAGE_MAX_WIDTH_R600 8192 67#define IMAGE_MAX_HEIGHT_R600 8192 68 69static Bool 70RADEONTilingEnabled(ScrnInfoPtr pScrn, PixmapPtr pPix) 71{ 72 RADEONInfoPtr info = RADEONPTR(pScrn); 73 74#ifdef USE_EXA 75 if (info->useEXA) { 76 if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0) 77 return TRUE; 78 else 79 return FALSE; 80 } else 81#endif 82 { 83 if (info->tilingEnabled && ((pPix->devPrivate.ptr - info->FB) == 0)) 84 return TRUE; 85 else 86 return FALSE; 87 } 88} 89 90static __inline__ uint32_t F_TO_DW(float val) 91{ 92 union { 93 float f; 94 uint32_t l; 95 } tmp; 96 tmp.f = val; 97 return tmp.l; 98} 99 100/* Borrowed from Mesa */ 101static __inline__ uint32_t F_TO_24(float val) 102{ 103 float mantissa; 104 int exponent; 105 uint32_t float24 = 0; 106 107 if (val == 0.0) 108 return 0; 109 110 mantissa = frexpf(val, &exponent); 111 112 /* Handle -ve */ 113 if (mantissa < 0) { 114 float24 |= (1 << 23); 115 mantissa = mantissa * -1.0; 116 } 117 /* Handle exponent, bias of 63 */ 118 exponent += 62; 119 float24 |= (exponent << 16); 120 /* Kill 7 LSB of mantissa */ 121 float24 |= (F_TO_DW(mantissa) & 0x7FFFFF) >> 7; 122 123 return float24; 124} 125 126static __inline__ uint32_t float4touint(float fr, float fg, float fb, float fa) 127{ 128 unsigned ur = fr * 255.0 + 0.5; 129 unsigned ug = fg * 255.0 + 0.5; 130 unsigned ub = fb * 255.0 + 0.5; 131 unsigned ua = fa * 255.0 + 0.5; 132 return (ua << 24) | (ur << 16) | (ug << 8) | ub; 133} 134 135/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces 136 note the difference to the parameters used in overlay are due 137 to 10bit vs. float calcs */ 138static REF_TRANSFORM trans[2] = 139{ 140 {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */ 141 {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */ 142}; 143 144#define ACCEL_MMIO 145#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 146#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 147#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 148#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) 149#define OUT_RELOC(x, read, write) do {} while(0) 150#define FINISH_ACCEL() 151 152#include "radeon_textured_videofuncs.c" 153 154#undef ACCEL_MMIO 155#undef ACCEL_PREAMBLE 156#undef BEGIN_ACCEL 157#undef OUT_ACCEL_REG 158#undef OUT_ACCEL_REG_F 159#undef OUT_RELOC 160#undef FINISH_ACCEL 161 162#ifdef XF86DRI 163 164#define ACCEL_CP 165#define ACCEL_PREAMBLE() \ 166 RING_LOCALS; \ 167 RADEONCP_REFRESH(pScrn, info) 168#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 169#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 170#define OUT_ACCEL_REG_F(reg, val) OUT_ACCEL_REG(reg, F_TO_DW(val)) 171#define FINISH_ACCEL() ADVANCE_RING() 172#define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) 173#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) 174 175#include "radeon_textured_videofuncs.c" 176 177#undef ACCEL_CP 178#undef ACCEL_PREAMBLE 179#undef BEGIN_ACCEL 180#undef OUT_ACCEL_REG 181#undef OUT_ACCEL_REG_F 182#undef FINISH_ACCEL 183#undef OUT_RING_F 184 185#endif /* XF86DRI */ 186 187static void 188R600CopyData( 189 ScrnInfoPtr pScrn, 190 unsigned char *src, 191 unsigned char *dst, 192 unsigned int srcPitch, 193 unsigned int dstPitch, 194 unsigned int h, 195 unsigned int w, 196 unsigned int cpp 197){ 198 RADEONInfoPtr info = RADEONPTR( pScrn ); 199 200 if (cpp == 2) { 201 w *= 2; 202 cpp = 1; 203 } 204 205 if (info->DMAForXv) { 206 uint32_t dst_mc_addr = dst - (unsigned char *)info->FB + info->fbLocation; 207 208 R600CopyToVRAM(pScrn, 209 (char *)src, srcPitch, 210 dstPitch, dst_mc_addr, w, h, cpp * 8, 211 0, 0, w, h); 212 } else { 213 if (srcPitch == dstPitch) 214 memcpy(dst, src, srcPitch * h); 215 else { 216 while (h--) { 217 memcpy(dst, src, srcPitch); 218 src += srcPitch; 219 dst += dstPitch; 220 } 221 } 222 } 223} 224 225static int 226RADEONPutImageTextured(ScrnInfoPtr pScrn, 227 short src_x, short src_y, 228 short drw_x, short drw_y, 229 short src_w, short src_h, 230 short drw_w, short drw_h, 231 int id, 232 unsigned char *buf, 233 short width, 234 short height, 235 Bool sync, 236 RegionPtr clipBoxes, 237 pointer data, 238 DrawablePtr pDraw) 239{ 240 ScreenPtr pScreen = pScrn->pScreen; 241 RADEONInfoPtr info = RADEONPTR(pScrn); 242 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 243 INT32 x1, x2, y1, y2; 244 int srcPitch, srcPitch2, dstPitch, dstPitch2 = 0; 245 int s2offset, s3offset, tmp; 246 int d2line, d3line; 247 int top, nlines, size; 248 BoxRec dstBox; 249 int dst_width = width, dst_height = height; 250 int hw_align; 251 252 /* make the compiler happy */ 253 s2offset = s3offset = srcPitch2 = 0; 254 255 /* Clip */ 256 x1 = src_x; 257 x2 = src_x + src_w; 258 y1 = src_y; 259 y2 = src_y + src_h; 260 261 dstBox.x1 = drw_x; 262 dstBox.x2 = drw_x + drw_w; 263 dstBox.y1 = drw_y; 264 dstBox.y2 = drw_y + drw_h; 265 266 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) 267 return Success; 268 269 if ((x1 >= x2) || (y1 >= y2)) 270 return Success; 271 272 /* Bicubic filter setup */ 273 pPriv->bicubic_enabled = (pPriv->bicubic_state != BICUBIC_OFF); 274 if (!(IS_R300_3D || IS_R500_3D)) { 275 pPriv->bicubic_enabled = FALSE; 276 pPriv->bicubic_state = BICUBIC_OFF; 277 } 278 if (pPriv->bicubic_enabled && (pPriv->bicubic_state == BICUBIC_AUTO)) { 279 /* 280 * Applying the bicubic filter with a scale of less than 200% 281 * results in a blurred picture, so disable the filter. 282 */ 283 if ((src_w > drw_w / 2) || (src_h > drw_h / 2)) 284 pPriv->bicubic_enabled = FALSE; 285 } 286 287 if (info->ChipFamily >= CHIP_FAMILY_R600) 288 hw_align = 256; 289 else 290 hw_align = 64; 291 292 switch(id) { 293 case FOURCC_YV12: 294 case FOURCC_I420: 295 srcPitch = RADEON_ALIGN(width, 4); 296 srcPitch2 = RADEON_ALIGN(width >> 1, 4); 297 if (pPriv->bicubic_state != BICUBIC_OFF) { 298 dstPitch = RADEON_ALIGN(dst_width << 1, hw_align); 299 dstPitch2 = 0; 300 } else { 301 dstPitch = RADEON_ALIGN(dst_width, hw_align); 302 dstPitch2 = RADEON_ALIGN(dstPitch >> 1, hw_align); 303 } 304 break; 305 case FOURCC_UYVY: 306 case FOURCC_YUY2: 307 default: 308 dstPitch = RADEON_ALIGN(dst_width << 1, hw_align); 309 srcPitch = (width << 1); 310 srcPitch2 = 0; 311 break; 312 } 313 314 size = dstPitch * dst_height + 2 * dstPitch2 * ((dst_height + 1) >> 1); 315 size = RADEON_ALIGN(size, hw_align); 316 317 if (size != pPriv->size) { 318 RADEONFreeVideoMemory(pScrn, pPriv); 319 } 320 321 if (pPriv->video_memory == NULL) { 322 pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, 323 &pPriv->video_memory, 324 size, hw_align, 325 RADEON_GEM_DOMAIN_GTT); 326 if (pPriv->video_offset == 0) 327 return BadAlloc; 328 329 if (info->cs) { 330 pPriv->src_bo[0] = pPriv->video_memory; 331 radeon_legacy_allocate_memory(pScrn, (void*)&pPriv->src_bo[1], size, 332 hw_align, 333 RADEON_GEM_DOMAIN_GTT); 334 } 335 } 336 337 /* Bicubic filter loading */ 338 if (pPriv->bicubic_enabled) { 339 if (info->bicubic_offset == 0) 340 pPriv->bicubic_enabled = FALSE; 341 pPriv->bicubic_src_offset = info->bicubic_offset; 342 } 343 344 if (pDraw->type == DRAWABLE_WINDOW) 345 pPriv->pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); 346 else 347 pPriv->pPixmap = (PixmapPtr)pDraw; 348 349#ifdef USE_EXA 350 if (info->useEXA) { 351 /* Force the pixmap into framebuffer so we can draw to it. */ 352 info->exa_force_create = TRUE; 353 exaMoveInPixmap(pPriv->pPixmap); 354 info->exa_force_create = FALSE; 355 } 356#endif 357 358 if (!info->useEXA && 359 (((char *)pPriv->pPixmap->devPrivate.ptr < (char *)info->FB) || 360 ((char *)pPriv->pPixmap->devPrivate.ptr >= (char *)info->FB + 361 info->FbMapSize))) { 362 /* If the pixmap wasn't in framebuffer, then we have no way in XAA to 363 * force it there. So, we simply refuse to draw and fail. 364 */ 365 return BadAlloc; 366 } 367 368 /* copy data */ 369 top = (y1 >> 16) & ~1; 370 nlines = RADEON_ALIGN((y2 + 0xffff) >> 16, 2) - top; 371 372 pPriv->src_offset = pPriv->video_offset; 373 if (info->cs) { 374 struct radeon_bo *src_bo; 375 int ret; 376 377 pPriv->currentBuffer ^= 1; 378 379 src_bo = pPriv->src_bo[pPriv->currentBuffer]; 380 381 ret = radeon_bo_map(src_bo, 1); 382 if (ret) 383 return BadAlloc; 384 385 pPriv->src_addr = src_bo->ptr; 386 } else { 387 pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset); 388 RADEONWaitForIdleMMIO(pScrn); 389 } 390 pPriv->src_pitch = dstPitch; 391 392 pPriv->planeu_offset = dstPitch * dst_height; 393 pPriv->planeu_offset = RADEON_ALIGN(pPriv->planeu_offset, hw_align); 394 pPriv->planev_offset = pPriv->planeu_offset + dstPitch2 * ((dst_height + 1) >> 1); 395 pPriv->planev_offset = RADEON_ALIGN(pPriv->planev_offset, hw_align); 396 397 pPriv->size = size; 398 pPriv->pDraw = pDraw; 399 400 switch(id) { 401 case FOURCC_YV12: 402 case FOURCC_I420: 403 s2offset = srcPitch * (RADEON_ALIGN(height, 2)); 404 s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1)); 405 s2offset += ((top >> 1) * srcPitch2); 406 s3offset += ((top >> 1) * srcPitch2); 407 if (pPriv->bicubic_state != BICUBIC_OFF) { 408 if (id == FOURCC_I420) { 409 tmp = s2offset; 410 s2offset = s3offset; 411 s3offset = tmp; 412 } 413 RADEONCopyMungedData(pScrn, buf + (top * srcPitch), 414 buf + s2offset, buf + s3offset, pPriv->src_addr + (top * dstPitch), 415 srcPitch, srcPitch2, dstPitch, nlines, width); 416 } else { 417 if (id == FOURCC_YV12) { 418 tmp = s2offset; 419 s2offset = s3offset; 420 s3offset = tmp; 421 } 422 d2line = pPriv->planeu_offset + ((top >> 1) * dstPitch2); 423 d3line = pPriv->planev_offset + ((top >> 1) * dstPitch2); 424 425 if (info->ChipFamily >= CHIP_FAMILY_R600) { 426 R600CopyData(pScrn, buf + (top * srcPitch), pPriv->src_addr + (top * dstPitch), 427 srcPitch, dstPitch, nlines, width, 1); 428 R600CopyData(pScrn, buf + s2offset, pPriv->src_addr + d2line, 429 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 430 R600CopyData(pScrn, buf + s3offset, pPriv->src_addr + d3line, 431 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 432 } else { 433 RADEONCopyData(pScrn, buf + (top * srcPitch), pPriv->src_addr + (top * dstPitch), 434 srcPitch, dstPitch, nlines, width, 1); 435 RADEONCopyData(pScrn, buf + s2offset, pPriv->src_addr + d2line, 436 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 437 RADEONCopyData(pScrn, buf + s3offset, pPriv->src_addr + d3line, 438 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 439 } 440 } 441 break; 442 case FOURCC_UYVY: 443 case FOURCC_YUY2: 444 default: 445 if (info->ChipFamily >= CHIP_FAMILY_R600) 446 R600CopyData(pScrn, buf + (top * srcPitch), 447 pPriv->src_addr + (top * dstPitch), 448 srcPitch, dstPitch, nlines, width, 2); 449 else 450 RADEONCopyData(pScrn, buf + (top * srcPitch), 451 pPriv->src_addr + (top * dstPitch), 452 srcPitch, dstPitch, nlines, width, 2); 453 break; 454 } 455 456 /* update cliplist */ 457 if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 458 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 459 } 460 461 pPriv->id = id; 462 pPriv->src_w = src_w; 463 pPriv->src_h = src_h; 464 pPriv->src_x = src_x; 465 pPriv->src_y = src_y; 466 pPriv->drw_x = drw_x; 467 pPriv->drw_y = drw_y; 468 pPriv->dst_w = drw_w; 469 pPriv->dst_h = drw_h; 470 pPriv->w = width; 471 pPriv->h = height; 472 473#if defined(XF86DRM_MODE) 474 if (info->cs) 475 radeon_bo_unmap(pPriv->src_bo[pPriv->currentBuffer]); 476#endif 477#ifdef XF86DRI 478 if (info->directRenderingEnabled) { 479#ifdef XF86DRM_MODE 480 if (IS_EVERGREEN_3D) 481 EVERGREENDisplayTexturedVideo(pScrn, pPriv); 482 else 483#endif 484 if (IS_R600_3D) 485 R600DisplayTexturedVideo(pScrn, pPriv); 486 else if (IS_R500_3D) 487 R500DisplayTexturedVideoCP(pScrn, pPriv); 488 else if (IS_R300_3D) 489 R300DisplayTexturedVideoCP(pScrn, pPriv); 490 else if (IS_R200_3D) 491 R200DisplayTexturedVideoCP(pScrn, pPriv); 492 else 493 RADEONDisplayTexturedVideoCP(pScrn, pPriv); 494 } else 495#endif 496 { 497 if (IS_R500_3D) 498 R500DisplayTexturedVideoMMIO(pScrn, pPriv); 499 else if (IS_R300_3D) 500 R300DisplayTexturedVideoMMIO(pScrn, pPriv); 501 else if (IS_R200_3D) 502 R200DisplayTexturedVideoMMIO(pScrn, pPriv); 503 else 504 RADEONDisplayTexturedVideoMMIO(pScrn, pPriv); 505 } 506 507 return Success; 508} 509 510/* client libraries expect an encoding */ 511static XF86VideoEncodingRec DummyEncoding[1] = 512{ 513 { 514 0, 515 "XV_IMAGE", 516 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 517 {1, 1} 518 } 519}; 520 521static XF86VideoEncodingRec DummyEncodingR500[1] = 522{ 523 { 524 0, 525 "XV_IMAGE", 526 IMAGE_MAX_WIDTH_R500, IMAGE_MAX_HEIGHT_R500, 527 {1, 1} 528 } 529}; 530 531static XF86VideoEncodingRec DummyEncodingR600[1] = 532{ 533 { 534 0, 535 "XV_IMAGE", 536 IMAGE_MAX_WIDTH_R600, IMAGE_MAX_HEIGHT_R600, 537 {1, 1} 538 } 539}; 540 541#define NUM_FORMATS 3 542 543static XF86VideoFormatRec Formats[NUM_FORMATS] = 544{ 545 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 546}; 547 548#define NUM_ATTRIBUTES 2 549 550static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] = 551{ 552 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 553 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 554 {0, 0, 0, NULL} 555}; 556 557#define NUM_ATTRIBUTES_R200 7 558 559static XF86AttributeRec Attributes_r200[NUM_ATTRIBUTES_R200+1] = 560{ 561 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 562 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 563 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 564 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 565 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 566 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 567 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 568 {0, 0, 0, NULL} 569}; 570 571#define NUM_ATTRIBUTES_R300 9 572 573static XF86AttributeRec Attributes_r300[NUM_ATTRIBUTES_R300+1] = 574{ 575 {XvSettable | XvGettable, 0, 2, "XV_BICUBIC"}, 576 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 577 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 578 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 579 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 580 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 581 {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, 582 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 583 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 584 {0, 0, 0, NULL} 585}; 586 587#define NUM_ATTRIBUTES_R500 8 588 589static XF86AttributeRec Attributes_r500[NUM_ATTRIBUTES_R500+1] = 590{ 591 {XvSettable | XvGettable, 0, 2, "XV_BICUBIC"}, 592 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 593 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 594 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 595 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 596 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 597 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 598 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 599 {0, 0, 0, NULL} 600}; 601 602#define NUM_ATTRIBUTES_R600 7 603 604static XF86AttributeRec Attributes_r600[NUM_ATTRIBUTES_R600+1] = 605{ 606 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 607 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 608 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 609 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 610 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 611 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 612 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 613 {0, 0, 0, NULL} 614}; 615 616static XF86AttributeRec Attributes_eg[NUM_ATTRIBUTES_R600+1] = 617{ 618 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 619 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 620 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 621 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 622 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 623 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 624 {XvSettable | XvGettable, -1, 5, "XV_CRTC"}, 625 {0, 0, 0, NULL} 626}; 627 628static Atom xvBicubic; 629static Atom xvVSync; 630static Atom xvBrightness, xvContrast, xvSaturation, xvHue; 631static Atom xvGamma, xvColorspace; 632static Atom xvCRTC; 633 634#define NUM_IMAGES 4 635 636static XF86ImageRec Images[NUM_IMAGES] = 637{ 638 XVIMAGE_YUY2, 639 XVIMAGE_YV12, 640 XVIMAGE_I420, 641 XVIMAGE_UYVY 642}; 643 644int 645RADEONGetTexPortAttribute(ScrnInfoPtr pScrn, 646 Atom attribute, 647 INT32 *value, 648 pointer data) 649{ 650 RADEONInfoPtr info = RADEONPTR(pScrn); 651 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 652 653 if (info->accelOn) RADEON_SYNC(info, pScrn); 654 655 if (attribute == xvBicubic) 656 *value = pPriv->bicubic_state; 657 else if (attribute == xvVSync) 658 *value = pPriv->vsync; 659 else if (attribute == xvBrightness) 660 *value = pPriv->brightness; 661 else if (attribute == xvContrast) 662 *value = pPriv->contrast; 663 else if (attribute == xvSaturation) 664 *value = pPriv->saturation; 665 else if (attribute == xvHue) 666 *value = pPriv->hue; 667 else if (attribute == xvGamma) 668 *value = pPriv->gamma; 669 else if(attribute == xvColorspace) 670 *value = pPriv->transform_index; 671 else if(attribute == xvCRTC) { 672 int c; 673 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 674 for (c = 0; c < xf86_config->num_crtc; c++) 675 if (xf86_config->crtc[c] == pPriv->desired_crtc) 676 break; 677 if (c == xf86_config->num_crtc) 678 c = -1; 679 *value = c; 680 } else 681 return BadMatch; 682 683 return Success; 684} 685 686int 687RADEONSetTexPortAttribute(ScrnInfoPtr pScrn, 688 Atom attribute, 689 INT32 value, 690 pointer data) 691{ 692 RADEONInfoPtr info = RADEONPTR(pScrn); 693 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 694 695 RADEON_SYNC(info, pScrn); 696 697 if (attribute == xvBicubic) 698 pPriv->bicubic_state = ClipValue (value, 0, 2); 699 else if (attribute == xvVSync) 700 pPriv->vsync = ClipValue (value, 0, 1); 701 else if (attribute == xvBrightness) 702 pPriv->brightness = ClipValue (value, -1000, 1000); 703 else if (attribute == xvContrast) 704 pPriv->contrast = ClipValue (value, -1000, 1000); 705 else if (attribute == xvSaturation) 706 pPriv->saturation = ClipValue (value, -1000, 1000); 707 else if (attribute == xvHue) 708 pPriv->hue = ClipValue (value, -1000, 1000); 709 else if (attribute == xvGamma) 710 pPriv->gamma = ClipValue (value, 100, 10000); 711 else if(attribute == xvColorspace) 712 pPriv->transform_index = ClipValue (value, 0, 1); 713 else if(attribute == xvCRTC) { 714 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 715 if ((value < -1) || (value > xf86_config->num_crtc)) 716 return BadValue; 717 if (value < 0) 718 pPriv->desired_crtc = NULL; 719 else 720 pPriv->desired_crtc = xf86_config->crtc[value]; 721 } else 722 return BadMatch; 723 724 return Success; 725} 726 727Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn) 728{ 729 RADEONInfoPtr info = RADEONPTR(pScrn); 730 731 /* Bicubic filter loading */ 732 info->bicubic_offset = radeon_legacy_allocate_memory(pScrn, 733 &info->bicubic_memory, 734 sizeof(bicubic_tex_512), 64, 735 RADEON_GEM_DOMAIN_VRAM); 736 if (info->bicubic_offset == 0) 737 return FALSE; 738 739 if (info->cs) 740 info->bicubic_bo = info->bicubic_memory; 741 742 /* Upload bicubic filter tex */ 743 if (info->ChipFamily < CHIP_FAMILY_R600) { 744 uint8_t *bicubic_addr; 745 int ret; 746 if (info->cs) { 747 ret = radeon_bo_map(info->bicubic_bo, 1); 748 if (ret) 749 return FALSE; 750 751 bicubic_addr = info->bicubic_bo->ptr; 752 } else 753 bicubic_addr = (uint8_t *)(info->FB + info->bicubic_offset); 754 755 RADEONCopySwap(bicubic_addr, (uint8_t *)bicubic_tex_512, 1024, 756#if X_BYTE_ORDER == X_BIG_ENDIAN 757 RADEON_HOST_DATA_SWAP_16BIT 758#else 759 RADEON_HOST_DATA_SWAP_NONE 760#endif 761); 762 if (info->cs) 763 radeon_bo_unmap(info->bicubic_bo); 764 } 765 return TRUE; 766} 767 768#if 0 769/* XXX */ 770static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn) 771{ 772 RADEONInfoPtr info = RADEONPTR(pScrn); 773 774 if (info->bicubic_memory != NULL) { 775 radeon_legacy_free_memory(pScrn, info->bicubic_memory); 776 info->bicubic_memory = NULL; 777 } 778 779} 780#endif 781 782XF86VideoAdaptorPtr 783RADEONSetupImageTexturedVideo(ScreenPtr pScreen) 784{ 785 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 786 RADEONInfoPtr info = RADEONPTR(pScrn); 787 RADEONPortPrivPtr pPortPriv; 788 XF86VideoAdaptorPtr adapt; 789 int i; 790 int num_texture_ports = 16; 791 792 adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports * 793 (sizeof(RADEONPortPrivRec) + sizeof(DevUnion))); 794 if (adapt == NULL) 795 return NULL; 796 797 xvBicubic = MAKE_ATOM("XV_BICUBIC"); 798 xvVSync = MAKE_ATOM("XV_VSYNC"); 799 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 800 xvContrast = MAKE_ATOM("XV_CONTRAST"); 801 xvSaturation = MAKE_ATOM("XV_SATURATION"); 802 xvHue = MAKE_ATOM("XV_HUE"); 803 xvGamma = MAKE_ATOM("XV_GAMMA"); 804 xvColorspace = MAKE_ATOM("XV_COLORSPACE"); 805 xvCRTC = MAKE_ATOM("XV_CRTC"); 806 807 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 808 adapt->flags = 0; 809 adapt->name = "Radeon Textured Video"; 810 adapt->nEncodings = 1; 811 if (IS_R600_3D) 812 adapt->pEncodings = DummyEncodingR600; 813 else if (IS_R500_3D) 814 adapt->pEncodings = DummyEncodingR500; 815 else 816 adapt->pEncodings = DummyEncoding; 817 adapt->nFormats = NUM_FORMATS; 818 adapt->pFormats = Formats; 819 adapt->nPorts = num_texture_ports; 820 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 821 822 pPortPriv = 823 (RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]); 824 825 if (IS_EVERGREEN_3D) { 826 adapt->pAttributes = Attributes_eg; 827 adapt->nAttributes = NUM_ATTRIBUTES_R600; 828 } 829 else if (IS_R600_3D) { 830 adapt->pAttributes = Attributes_r600; 831 adapt->nAttributes = NUM_ATTRIBUTES_R600; 832 } 833 else if (IS_R500_3D) { 834 adapt->pAttributes = Attributes_r500; 835 adapt->nAttributes = NUM_ATTRIBUTES_R500; 836 } 837 else if (IS_R300_3D) { 838 adapt->pAttributes = Attributes_r300; 839 adapt->nAttributes = NUM_ATTRIBUTES_R300; 840 } 841 else if (IS_R200_3D) { 842 adapt->pAttributes = Attributes_r200; 843 adapt->nAttributes = NUM_ATTRIBUTES_R200; 844 } 845 else { 846 adapt->pAttributes = Attributes; 847 adapt->nAttributes = NUM_ATTRIBUTES; 848 } 849 adapt->pImages = Images; 850 adapt->nImages = NUM_IMAGES; 851 adapt->PutVideo = NULL; 852 adapt->PutStill = NULL; 853 adapt->GetVideo = NULL; 854 adapt->GetStill = NULL; 855 adapt->StopVideo = RADEONStopVideo; 856 adapt->SetPortAttribute = RADEONSetTexPortAttribute; 857 adapt->GetPortAttribute = RADEONGetTexPortAttribute; 858 adapt->QueryBestSize = RADEONQueryBestSize; 859 adapt->PutImage = RADEONPutImageTextured; 860 adapt->ReputImage = NULL; 861 adapt->QueryImageAttributes = RADEONQueryImageAttributes; 862 863 for (i = 0; i < num_texture_ports; i++) { 864 RADEONPortPrivPtr pPriv = &pPortPriv[i]; 865 866 pPriv->textured = TRUE; 867 pPriv->videoStatus = 0; 868 pPriv->currentBuffer = 0; 869 pPriv->doubleBuffer = 0; 870 pPriv->bicubic_state = BICUBIC_OFF; 871 pPriv->vsync = TRUE; 872 pPriv->brightness = 0; 873 pPriv->contrast = 0; 874 pPriv->saturation = 0; 875 pPriv->hue = 0; 876 pPriv->gamma = 1000; 877 pPriv->transform_index = 0; 878 pPriv->desired_crtc = NULL; 879 880 /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */ 881 REGION_NULL(pScreen, &pPriv->clip); 882 adapt->pPortPrivates[i].ptr = (pointer) (pPriv); 883 } 884 885 if (IS_R500_3D || IS_R300_3D) 886 radeon_load_bicubic_texture(pScrn); 887 888 info->xv_max_width = adapt->pEncodings->width; 889 info->xv_max_height = adapt->pEncodings->height; 890 891 return adapt; 892} 893 894