radeon_textured_video.c revision 30d12090
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 aligned_height; 251#ifdef XF86DRM_MODE 252 int h_align = drmmode_get_height_align(pScrn, 0); 253#else 254 int h_align = 1; 255#endif 256 /* make the compiler happy */ 257 s2offset = s3offset = srcPitch2 = 0; 258 259 /* Clip */ 260 x1 = src_x; 261 x2 = src_x + src_w; 262 y1 = src_y; 263 y2 = src_y + src_h; 264 265 dstBox.x1 = drw_x; 266 dstBox.x2 = drw_x + drw_w; 267 dstBox.y1 = drw_y; 268 dstBox.y2 = drw_y + drw_h; 269 270 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) 271 return Success; 272 273 if ((x1 >= x2) || (y1 >= y2)) 274 return Success; 275 276 /* Bicubic filter setup */ 277 pPriv->bicubic_enabled = (pPriv->bicubic_state != BICUBIC_OFF); 278 if (!(IS_R300_3D || IS_R500_3D)) { 279 pPriv->bicubic_enabled = FALSE; 280 pPriv->bicubic_state = BICUBIC_OFF; 281 } 282 if (pPriv->bicubic_enabled && (pPriv->bicubic_state == BICUBIC_AUTO)) { 283 /* 284 * Applying the bicubic filter with a scale of less than 200% 285 * results in a blurred picture, so disable the filter. 286 */ 287 if ((src_w > drw_w / 2) || (src_h > drw_h / 2)) 288 pPriv->bicubic_enabled = FALSE; 289 } 290 291#ifdef XF86DRM_MODE 292 if (info->cs) { 293 if (info->ChipFamily >= CHIP_FAMILY_R600) 294 pPriv->hw_align = drmmode_get_base_align(pScrn, 2, 0); 295 else 296 pPriv->hw_align = 64; 297 } else 298#endif 299 { 300 if (info->ChipFamily >= CHIP_FAMILY_R600) 301 pPriv->hw_align = 256; 302 else 303 pPriv->hw_align = 64; 304 } 305 306 aligned_height = RADEON_ALIGN(dst_height, h_align); 307 308 switch(id) { 309 case FOURCC_YV12: 310 case FOURCC_I420: 311 srcPitch = RADEON_ALIGN(width, 4); 312 srcPitch2 = RADEON_ALIGN(width >> 1, 4); 313 if (pPriv->bicubic_state != BICUBIC_OFF) { 314 dstPitch = RADEON_ALIGN(dst_width << 1, pPriv->hw_align); 315 dstPitch2 = 0; 316 } else { 317 dstPitch = RADEON_ALIGN(dst_width, pPriv->hw_align); 318 dstPitch2 = RADEON_ALIGN(dstPitch >> 1, pPriv->hw_align); 319 } 320 break; 321 case FOURCC_UYVY: 322 case FOURCC_YUY2: 323 default: 324 dstPitch = RADEON_ALIGN(dst_width << 1, pPriv->hw_align); 325 srcPitch = (width << 1); 326 srcPitch2 = 0; 327 break; 328 } 329 330 size = dstPitch * aligned_height + 2 * dstPitch2 * RADEON_ALIGN(((aligned_height + 1) >> 1), h_align); 331 size = RADEON_ALIGN(size, pPriv->hw_align); 332 333 if (size != pPriv->size) { 334 RADEONFreeVideoMemory(pScrn, pPriv); 335 } 336 337 if (pPriv->video_memory == NULL) { 338 pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, 339 &pPriv->video_memory, 340 size, pPriv->hw_align, 341 RADEON_GEM_DOMAIN_GTT); 342 if (pPriv->video_offset == 0) 343 return BadAlloc; 344 345 if (info->cs) { 346 pPriv->src_bo[0] = pPriv->video_memory; 347 radeon_legacy_allocate_memory(pScrn, (void*)&pPriv->src_bo[1], size, 348 pPriv->hw_align, 349 RADEON_GEM_DOMAIN_GTT); 350 } 351 } 352 353 /* Bicubic filter loading */ 354 if (pPriv->bicubic_enabled) { 355 if (info->bicubic_offset == 0) 356 pPriv->bicubic_enabled = FALSE; 357 pPriv->bicubic_src_offset = info->bicubic_offset; 358 } 359 360 if (pDraw->type == DRAWABLE_WINDOW) 361 pPriv->pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); 362 else 363 pPriv->pPixmap = (PixmapPtr)pDraw; 364 365#ifdef USE_EXA 366 if (info->useEXA) { 367 /* Force the pixmap into framebuffer so we can draw to it. */ 368 info->exa_force_create = TRUE; 369 exaMoveInPixmap(pPriv->pPixmap); 370 info->exa_force_create = FALSE; 371 } 372#endif 373 374 if (!info->useEXA && 375 (((char *)pPriv->pPixmap->devPrivate.ptr < (char *)info->FB) || 376 ((char *)pPriv->pPixmap->devPrivate.ptr >= (char *)info->FB + 377 info->FbMapSize))) { 378 /* If the pixmap wasn't in framebuffer, then we have no way in XAA to 379 * force it there. So, we simply refuse to draw and fail. 380 */ 381 return BadAlloc; 382 } 383 384 /* copy data */ 385 top = (y1 >> 16) & ~1; 386 nlines = RADEON_ALIGN((y2 + 0xffff) >> 16, 2) - top; 387 388 pPriv->src_offset = pPriv->video_offset; 389 if (info->cs) { 390 struct radeon_bo *src_bo; 391 int ret; 392 393 pPriv->currentBuffer ^= 1; 394 395 src_bo = pPriv->src_bo[pPriv->currentBuffer]; 396 397 ret = radeon_bo_map(src_bo, 1); 398 if (ret) 399 return BadAlloc; 400 401 pPriv->src_addr = src_bo->ptr; 402 } else { 403 pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset); 404 RADEONWaitForIdleMMIO(pScrn); 405 } 406 pPriv->src_pitch = dstPitch; 407 408 pPriv->planeu_offset = dstPitch * aligned_height; 409 pPriv->planeu_offset = RADEON_ALIGN(pPriv->planeu_offset, pPriv->hw_align); 410 pPriv->planev_offset = pPriv->planeu_offset + dstPitch2 * RADEON_ALIGN(((aligned_height + 1) >> 1), h_align); 411 pPriv->planev_offset = RADEON_ALIGN(pPriv->planev_offset, pPriv->hw_align); 412 413 pPriv->size = size; 414 pPriv->pDraw = pDraw; 415 416 switch(id) { 417 case FOURCC_YV12: 418 case FOURCC_I420: 419 s2offset = srcPitch * (RADEON_ALIGN(height, 2)); 420 s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1)); 421 s2offset += ((top >> 1) * srcPitch2); 422 s3offset += ((top >> 1) * srcPitch2); 423 if (pPriv->bicubic_state != BICUBIC_OFF) { 424 if (id == FOURCC_I420) { 425 tmp = s2offset; 426 s2offset = s3offset; 427 s3offset = tmp; 428 } 429 RADEONCopyMungedData(pScrn, buf + (top * srcPitch), 430 buf + s2offset, buf + s3offset, pPriv->src_addr + (top * dstPitch), 431 srcPitch, srcPitch2, dstPitch, nlines, width); 432 } else { 433 if (id == FOURCC_YV12) { 434 tmp = s2offset; 435 s2offset = s3offset; 436 s3offset = tmp; 437 } 438 d2line = pPriv->planeu_offset + ((top >> 1) * dstPitch2); 439 d3line = pPriv->planev_offset + ((top >> 1) * dstPitch2); 440 441 if (info->ChipFamily >= CHIP_FAMILY_R600) { 442 R600CopyData(pScrn, buf + (top * srcPitch), pPriv->src_addr + (top * dstPitch), 443 srcPitch, dstPitch, nlines, width, 1); 444 R600CopyData(pScrn, buf + s2offset, pPriv->src_addr + d2line, 445 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 446 R600CopyData(pScrn, buf + s3offset, pPriv->src_addr + d3line, 447 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 448 } else { 449 RADEONCopyData(pScrn, buf + (top * srcPitch), pPriv->src_addr + (top * dstPitch), 450 srcPitch, dstPitch, nlines, width, 1); 451 RADEONCopyData(pScrn, buf + s2offset, pPriv->src_addr + d2line, 452 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 453 RADEONCopyData(pScrn, buf + s3offset, pPriv->src_addr + d3line, 454 srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1); 455 } 456 } 457 break; 458 case FOURCC_UYVY: 459 case FOURCC_YUY2: 460 default: 461 if (info->ChipFamily >= CHIP_FAMILY_R600) 462 R600CopyData(pScrn, buf + (top * srcPitch), 463 pPriv->src_addr + (top * dstPitch), 464 srcPitch, dstPitch, nlines, width, 2); 465 else 466 RADEONCopyData(pScrn, buf + (top * srcPitch), 467 pPriv->src_addr + (top * dstPitch), 468 srcPitch, dstPitch, nlines, width, 2); 469 break; 470 } 471 472 /* update cliplist */ 473 if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 474 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 475 } 476 477 pPriv->id = id; 478 pPriv->src_w = src_w; 479 pPriv->src_h = src_h; 480 pPriv->src_x = src_x; 481 pPriv->src_y = src_y; 482 pPriv->drw_x = drw_x; 483 pPriv->drw_y = drw_y; 484 pPriv->dst_w = drw_w; 485 pPriv->dst_h = drw_h; 486 pPriv->w = width; 487 pPriv->h = height; 488 489#if defined(XF86DRM_MODE) 490 if (info->cs) 491 radeon_bo_unmap(pPriv->src_bo[pPriv->currentBuffer]); 492#endif 493#ifdef XF86DRI 494 if (info->directRenderingEnabled) { 495#ifdef XF86DRM_MODE 496 if (IS_EVERGREEN_3D) 497 EVERGREENDisplayTexturedVideo(pScrn, pPriv); 498 else 499#endif 500 if (IS_R600_3D) 501 R600DisplayTexturedVideo(pScrn, pPriv); 502 else if (IS_R500_3D) 503 R500DisplayTexturedVideoCP(pScrn, pPriv); 504 else if (IS_R300_3D) 505 R300DisplayTexturedVideoCP(pScrn, pPriv); 506 else if (IS_R200_3D) 507 R200DisplayTexturedVideoCP(pScrn, pPriv); 508 else 509 RADEONDisplayTexturedVideoCP(pScrn, pPriv); 510 } else 511#endif 512 { 513 if (IS_R500_3D) 514 R500DisplayTexturedVideoMMIO(pScrn, pPriv); 515 else if (IS_R300_3D) 516 R300DisplayTexturedVideoMMIO(pScrn, pPriv); 517 else if (IS_R200_3D) 518 R200DisplayTexturedVideoMMIO(pScrn, pPriv); 519 else 520 RADEONDisplayTexturedVideoMMIO(pScrn, pPriv); 521 } 522 523 return Success; 524} 525 526/* client libraries expect an encoding */ 527static XF86VideoEncodingRec DummyEncoding[1] = 528{ 529 { 530 0, 531 "XV_IMAGE", 532 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 533 {1, 1} 534 } 535}; 536 537static XF86VideoEncodingRec DummyEncodingR500[1] = 538{ 539 { 540 0, 541 "XV_IMAGE", 542 IMAGE_MAX_WIDTH_R500, IMAGE_MAX_HEIGHT_R500, 543 {1, 1} 544 } 545}; 546 547static XF86VideoEncodingRec DummyEncodingR600[1] = 548{ 549 { 550 0, 551 "XV_IMAGE", 552 IMAGE_MAX_WIDTH_R600, IMAGE_MAX_HEIGHT_R600, 553 {1, 1} 554 } 555}; 556 557#define NUM_FORMATS 3 558 559static XF86VideoFormatRec Formats[NUM_FORMATS] = 560{ 561 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 562}; 563 564#define NUM_ATTRIBUTES 2 565 566static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] = 567{ 568 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 569 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 570 {0, 0, 0, NULL} 571}; 572 573#define NUM_ATTRIBUTES_R200 7 574 575static XF86AttributeRec Attributes_r200[NUM_ATTRIBUTES_R200+1] = 576{ 577 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 578 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 579 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 580 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 581 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 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_R300 9 588 589static XF86AttributeRec Attributes_r300[NUM_ATTRIBUTES_R300+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, 100, 10000, "XV_GAMMA"}, 598 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 599 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 600 {0, 0, 0, NULL} 601}; 602 603#define NUM_ATTRIBUTES_R500 8 604 605static XF86AttributeRec Attributes_r500[NUM_ATTRIBUTES_R500+1] = 606{ 607 {XvSettable | XvGettable, 0, 2, "XV_BICUBIC"}, 608 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 609 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 610 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 611 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 612 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 613 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 614 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 615 {0, 0, 0, NULL} 616}; 617 618#define NUM_ATTRIBUTES_R600 7 619 620static XF86AttributeRec Attributes_r600[NUM_ATTRIBUTES_R600+1] = 621{ 622 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 623 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 624 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 625 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 626 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 627 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 628 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 629 {0, 0, 0, NULL} 630}; 631 632static XF86AttributeRec Attributes_eg[NUM_ATTRIBUTES_R600+1] = 633{ 634 {XvSettable | XvGettable, 0, 1, "XV_VSYNC"}, 635 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 636 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 637 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 638 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 639 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 640 {XvSettable | XvGettable, -1, 5, "XV_CRTC"}, 641 {0, 0, 0, NULL} 642}; 643 644static Atom xvBicubic; 645static Atom xvVSync; 646static Atom xvBrightness, xvContrast, xvSaturation, xvHue; 647static Atom xvGamma, xvColorspace; 648static Atom xvCRTC; 649 650#define NUM_IMAGES 4 651 652static XF86ImageRec Images[NUM_IMAGES] = 653{ 654 XVIMAGE_YUY2, 655 XVIMAGE_YV12, 656 XVIMAGE_I420, 657 XVIMAGE_UYVY 658}; 659 660int 661RADEONGetTexPortAttribute(ScrnInfoPtr pScrn, 662 Atom attribute, 663 INT32 *value, 664 pointer data) 665{ 666 RADEONInfoPtr info = RADEONPTR(pScrn); 667 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 668 669 if (info->accelOn) RADEON_SYNC(info, pScrn); 670 671 if (attribute == xvBicubic) 672 *value = pPriv->bicubic_state; 673 else if (attribute == xvVSync) 674 *value = pPriv->vsync; 675 else if (attribute == xvBrightness) 676 *value = pPriv->brightness; 677 else if (attribute == xvContrast) 678 *value = pPriv->contrast; 679 else if (attribute == xvSaturation) 680 *value = pPriv->saturation; 681 else if (attribute == xvHue) 682 *value = pPriv->hue; 683 else if (attribute == xvGamma) 684 *value = pPriv->gamma; 685 else if(attribute == xvColorspace) 686 *value = pPriv->transform_index; 687 else if(attribute == xvCRTC) { 688 int c; 689 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 690 for (c = 0; c < xf86_config->num_crtc; c++) 691 if (xf86_config->crtc[c] == pPriv->desired_crtc) 692 break; 693 if (c == xf86_config->num_crtc) 694 c = -1; 695 *value = c; 696 } else 697 return BadMatch; 698 699 return Success; 700} 701 702int 703RADEONSetTexPortAttribute(ScrnInfoPtr pScrn, 704 Atom attribute, 705 INT32 value, 706 pointer data) 707{ 708 RADEONInfoPtr info = RADEONPTR(pScrn); 709 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 710 711 RADEON_SYNC(info, pScrn); 712 713 if (attribute == xvBicubic) 714 pPriv->bicubic_state = ClipValue (value, 0, 2); 715 else if (attribute == xvVSync) 716 pPriv->vsync = ClipValue (value, 0, 1); 717 else if (attribute == xvBrightness) 718 pPriv->brightness = ClipValue (value, -1000, 1000); 719 else if (attribute == xvContrast) 720 pPriv->contrast = ClipValue (value, -1000, 1000); 721 else if (attribute == xvSaturation) 722 pPriv->saturation = ClipValue (value, -1000, 1000); 723 else if (attribute == xvHue) 724 pPriv->hue = ClipValue (value, -1000, 1000); 725 else if (attribute == xvGamma) 726 pPriv->gamma = ClipValue (value, 100, 10000); 727 else if(attribute == xvColorspace) 728 pPriv->transform_index = ClipValue (value, 0, 1); 729 else if(attribute == xvCRTC) { 730 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 731 if ((value < -1) || (value > xf86_config->num_crtc)) 732 return BadValue; 733 if (value < 0) 734 pPriv->desired_crtc = NULL; 735 else 736 pPriv->desired_crtc = xf86_config->crtc[value]; 737 } else 738 return BadMatch; 739 740 return Success; 741} 742 743Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn) 744{ 745 RADEONInfoPtr info = RADEONPTR(pScrn); 746 747 /* Bicubic filter loading */ 748 info->bicubic_offset = radeon_legacy_allocate_memory(pScrn, 749 &info->bicubic_memory, 750 sizeof(bicubic_tex_512), 64, 751 RADEON_GEM_DOMAIN_VRAM); 752 if (info->bicubic_offset == 0) 753 return FALSE; 754 755 if (info->cs) 756 info->bicubic_bo = info->bicubic_memory; 757 758 /* Upload bicubic filter tex */ 759 if (info->ChipFamily < CHIP_FAMILY_R600) { 760 uint8_t *bicubic_addr; 761 int ret; 762 if (info->cs) { 763 ret = radeon_bo_map(info->bicubic_bo, 1); 764 if (ret) 765 return FALSE; 766 767 bicubic_addr = info->bicubic_bo->ptr; 768 } else 769 bicubic_addr = (uint8_t *)(info->FB + info->bicubic_offset); 770 771 RADEONCopySwap(bicubic_addr, (uint8_t *)bicubic_tex_512, 1024, 772#if X_BYTE_ORDER == X_BIG_ENDIAN 773 RADEON_HOST_DATA_SWAP_16BIT 774#else 775 RADEON_HOST_DATA_SWAP_NONE 776#endif 777); 778 if (info->cs) 779 radeon_bo_unmap(info->bicubic_bo); 780 } 781 return TRUE; 782} 783 784#if 0 785/* XXX */ 786static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn) 787{ 788 RADEONInfoPtr info = RADEONPTR(pScrn); 789 790 if (info->bicubic_memory != NULL) { 791 radeon_legacy_free_memory(pScrn, info->bicubic_memory); 792 info->bicubic_memory = NULL; 793 } 794 795} 796#endif 797 798XF86VideoAdaptorPtr 799RADEONSetupImageTexturedVideo(ScreenPtr pScreen) 800{ 801 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 802 RADEONInfoPtr info = RADEONPTR(pScrn); 803 RADEONPortPrivPtr pPortPriv; 804 XF86VideoAdaptorPtr adapt; 805 int i; 806 int num_texture_ports = 16; 807 808 adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports * 809 (sizeof(RADEONPortPrivRec) + sizeof(DevUnion))); 810 if (adapt == NULL) 811 return NULL; 812 813 xvBicubic = MAKE_ATOM("XV_BICUBIC"); 814 xvVSync = MAKE_ATOM("XV_VSYNC"); 815 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 816 xvContrast = MAKE_ATOM("XV_CONTRAST"); 817 xvSaturation = MAKE_ATOM("XV_SATURATION"); 818 xvHue = MAKE_ATOM("XV_HUE"); 819 xvGamma = MAKE_ATOM("XV_GAMMA"); 820 xvColorspace = MAKE_ATOM("XV_COLORSPACE"); 821 xvCRTC = MAKE_ATOM("XV_CRTC"); 822 823 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 824 adapt->flags = 0; 825 adapt->name = "Radeon Textured Video"; 826 adapt->nEncodings = 1; 827 if (IS_R600_3D) 828 adapt->pEncodings = DummyEncodingR600; 829 else if (IS_R500_3D) 830 adapt->pEncodings = DummyEncodingR500; 831 else 832 adapt->pEncodings = DummyEncoding; 833 adapt->nFormats = NUM_FORMATS; 834 adapt->pFormats = Formats; 835 adapt->nPorts = num_texture_ports; 836 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 837 838 pPortPriv = 839 (RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]); 840 841 if (IS_EVERGREEN_3D) { 842 adapt->pAttributes = Attributes_eg; 843 adapt->nAttributes = NUM_ATTRIBUTES_R600; 844 } 845 else if (IS_R600_3D) { 846 adapt->pAttributes = Attributes_r600; 847 adapt->nAttributes = NUM_ATTRIBUTES_R600; 848 } 849 else if (IS_R500_3D) { 850 adapt->pAttributes = Attributes_r500; 851 adapt->nAttributes = NUM_ATTRIBUTES_R500; 852 } 853 else if (IS_R300_3D) { 854 adapt->pAttributes = Attributes_r300; 855 adapt->nAttributes = NUM_ATTRIBUTES_R300; 856 } 857 else if (IS_R200_3D) { 858 adapt->pAttributes = Attributes_r200; 859 adapt->nAttributes = NUM_ATTRIBUTES_R200; 860 } 861 else { 862 adapt->pAttributes = Attributes; 863 adapt->nAttributes = NUM_ATTRIBUTES; 864 } 865 adapt->pImages = Images; 866 adapt->nImages = NUM_IMAGES; 867 adapt->PutVideo = NULL; 868 adapt->PutStill = NULL; 869 adapt->GetVideo = NULL; 870 adapt->GetStill = NULL; 871 adapt->StopVideo = RADEONStopVideo; 872 adapt->SetPortAttribute = RADEONSetTexPortAttribute; 873 adapt->GetPortAttribute = RADEONGetTexPortAttribute; 874 adapt->QueryBestSize = RADEONQueryBestSize; 875 adapt->PutImage = RADEONPutImageTextured; 876 adapt->ReputImage = NULL; 877 adapt->QueryImageAttributes = RADEONQueryImageAttributes; 878 879 for (i = 0; i < num_texture_ports; i++) { 880 RADEONPortPrivPtr pPriv = &pPortPriv[i]; 881 882 pPriv->textured = TRUE; 883 pPriv->videoStatus = 0; 884 pPriv->currentBuffer = 0; 885 pPriv->doubleBuffer = 0; 886 pPriv->bicubic_state = BICUBIC_OFF; 887 pPriv->vsync = TRUE; 888 pPriv->brightness = 0; 889 pPriv->contrast = 0; 890 pPriv->saturation = 0; 891 pPriv->hue = 0; 892 pPriv->gamma = 1000; 893 pPriv->transform_index = 0; 894 pPriv->desired_crtc = NULL; 895 896 /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */ 897 REGION_NULL(pScreen, &pPriv->clip); 898 adapt->pPortPrivates[i].ptr = (pointer) (pPriv); 899 } 900 901 if (IS_R500_3D || IS_R300_3D) 902 radeon_load_bicubic_texture(pScrn); 903 904 info->xv_max_width = adapt->pEncodings->width; 905 info->xv_max_height = adapt->pEncodings->height; 906 907 return adapt; 908} 909 910