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