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