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