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