1/*************************************************************************** 2 3Copyright 2001 Intel Corporation. All Rights Reserved. 4 5Permission is hereby granted, free of charge, to any person obtaining a 6copy of this software and associated documentation files (the 7"Software"), to deal in the Software without restriction, including 8without limitation the rights to use, copy, modify, merge, publish, 9distribute, sub license, and/or sell copies of the Software, and to 10permit persons to whom the Software is furnished to do so, subject to 11the following conditions: 12 13The above copyright notice and this permission notice (including the 14next paragraph) shall be included in all copies or substantial portions 15of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 23THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25**************************************************************************/ 26 27/************************************************************************* 28** File libI810XvMC.c 29** 30** Authors: 31** Matt Sottek <matthew.j.sottek@intel.com> 32** Bob Paauwe <bob.j.paauwe@intel.com> 33** 34** 35***************************************************************************/ 36#include <stdio.h> 37#include <stdlib.h> 38#include <unistd.h> 39#include <errno.h> 40#include <signal.h> 41#include <fcntl.h> 42#include <dirent.h> 43#include <string.h> 44 45#include <sys/ioctl.h> 46#include <X11/Xlibint.h> 47#include <fourcc.h> 48#include <X11/extensions/Xv.h> 49#include <X11/extensions/Xvlib.h> 50#include <X11/extensions/XvMC.h> 51#include <X11/extensions/XvMClib.h> 52#include "I810XvMC.h" 53 54static int error_base; 55static int event_base; 56 57/*************************************************************************** 58// Function: i810_get_free_buffer 59// Description: Allocates a free dma page using kernel ioctls, then 60// programs the data into the already allocated dma buffer list. 61// Arguments: pI810XvMC private data structure from the current context. 62// Notes: We faked the drmMapBufs for the i810's security so now we have 63// to insert an allocated page into the correct spot in the faked 64// list to keep up appearences. 65// Concept for this function was taken from Mesa sources. 66// Returns: drmBufPtr containing the information about the allocated page. 67***************************************************************************/ 68drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) { 69 drmI810DMA dma; 70 drmBufPtr buf; 71 72 dma.granted = 0; 73 dma.request_size = 4096; 74 while(!dma.granted) { 75 if(GET_BUFFER(pI810XvMC, dma) || !dma.granted) 76 FLUSH(pI810XvMC); 77 } /* No DMA granted */ 78 79 buf = &(pI810XvMC->dmabufs->list[dma.request_idx]); 80 buf->idx = dma.request_idx; 81 buf->used = 0; 82 buf->total = dma.request_size; 83 buf->address = (drmAddress)dma.virtual; 84 return buf; 85} 86 87/*************************************************************************** 88// Function: free_privContext 89// Description: Free's the private context structure if the reference 90// count is 0. 91***************************************************************************/ 92void i810_free_privContext(i810XvMCContext *pI810XvMC) { 93 94 I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); 95 96 97 pI810XvMC->ref--; 98 if(!pI810XvMC->ref) { 99 drmUnmapBufs(pI810XvMC->dmabufs); 100 drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size); 101 drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size); 102 drmClose(pI810XvMC->fd); 103 104 free(pI810XvMC->dmabufs->list); 105 free(pI810XvMC); 106 } 107 108 I810_UNLOCK(pI810XvMC); 109} 110 111 112/*************************************************************************** 113// Function: XvMCCreateContext 114// Description: Create a XvMC context for the given surface parameters. 115// Arguments: 116// display - Connection to the X server. 117// port - XvPortID to use as avertised by the X connection. 118// surface_type_id - Unique identifier for the Surface type. 119// width - Width of the surfaces. 120// height - Height of the surfaces. 121// flags - one or more of the following 122// XVMC_DIRECT - A direct rendered context is requested. 123// 124// Notes: surface_type_id and width/height parameters must match those 125// returned by XvMCListSurfaceTypes. 126// Returns: Status 127***************************************************************************/ 128_X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port, 129 int surface_type_id, int width, int height, int flags, 130 XvMCContext *context) { 131 i810XvMCContext *pI810XvMC; 132 int priv_count; 133 uint *priv_data; 134 uint magic; 135 Status ret; 136 int major, minor; 137 138 /* Verify Obvious things first */ 139 if(context == NULL) { 140 return XvMCBadContext; 141 } 142 143 if(!(flags & XVMC_DIRECT)) { 144 /* Indirect */ 145 printf("Indirect Rendering not supported!\nUsing Direct."); 146 } 147 148 /* Limit use to root for now */ 149 if(geteuid()) { 150 printf("Use of XvMC on i810 is currently limited to root\n"); 151 return BadAccess; 152 } 153 154 /* FIXME: Check $DISPLAY for legal values here */ 155 156 context->surface_type_id = surface_type_id; 157 context->width = (unsigned short)width; 158 context->height = (unsigned short)height; 159 context->flags = flags; 160 context->port = port; 161 /* 162 Width, Height, and flags are checked against surface_type_id 163 and port for validity inside the X server, no need to check 164 here. 165 */ 166 167 /* Allocate private Context data */ 168 context->privData = (void *)malloc(sizeof(i810XvMCContext)); 169 if(!context->privData) { 170 printf("Unable to allocate resources for XvMC context.\n"); 171 return BadAlloc; 172 } 173 pI810XvMC = (i810XvMCContext *)context->privData; 174 175 176 /* Verify the XvMC extension exists */ 177 if(! XvMCQueryExtension(display, &event_base, 178 &error_base)) { 179 printf("XvMC Extension is not available!\n"); 180 return BadAlloc; 181 } 182 /* Verify XvMC version */ 183 ret = XvMCQueryVersion(display, &major, &minor); 184 if(ret) { 185 printf("XvMCQuery Version Failed, unable to determine protocol version\n"); 186 } 187 /* FIXME: Check Major and Minor here */ 188 189 /* Check for drm */ 190 if(! drmAvailable()) { 191 printf("Direct Rendering is not avilable on this system!\n"); 192 return BadAlloc; 193 } 194 195 /* 196 Build the Attribute Atoms, and Initialize the ones that exist 197 in Xv. 198 */ 199 pI810XvMC->xv_colorkey = XInternAtom(display,"XV_COLORKEY",0); 200 if(!pI810XvMC->xv_colorkey) { 201 return XvBadPort; 202 } 203 ret = XvGetPortAttribute(display,port,pI810XvMC->xv_colorkey, 204 &pI810XvMC->colorkey); 205 if(ret) { 206 return ret; 207 } 208 pI810XvMC->xv_brightness = XInternAtom(display,"XV_BRIGHTNESS",0); 209 pI810XvMC->xv_saturation = XInternAtom(display,"XV_SATURATION",0); 210 pI810XvMC->xv_contrast = XInternAtom(display,"XV_CONTRAST",0); 211 pI810XvMC->brightness = 0; 212 pI810XvMC->saturation = 0x80; /* 1.0 in 3.7 format */ 213 pI810XvMC->contrast = 0x40; /* 1.0 in 3.6 format */ 214 215 /* Open DRI Device */ 216 if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) { 217 printf("DRM Device for i810 could not be opened.\n"); 218 free(pI810XvMC); 219 return BadAccess; 220 } /* !pI810XvMC->fd */ 221 222 /* Get magic number and put it in privData for passing */ 223 drmGetMagic(pI810XvMC->fd,&magic); 224 context->flags = (unsigned long)magic; 225 226 /* 227 Pass control to the X server to create a drm_context_t for us and 228 validate the with/height and flags. 229 */ 230 if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) { 231 printf("Unable to create XvMC Context.\n"); 232 return ret; 233 } 234 235 /* 236 X server returns a structure like this: 237 drm_context_t 238 fbBase 239 OverlayOffset 240 OverlaySize 241 SurfacesOffset 242 SurfacesSize 243 busIdString = 9 char + 1 244 */ 245 if(priv_count != 9) { 246 printf("_xvmc_create_context() returned incorrect data size!\n"); 247 printf("\tExpected 9, got %d\n",priv_count); 248 _xvmc_destroy_context(display, context); 249 free(pI810XvMC); 250 return BadAlloc; 251 } 252 pI810XvMC->drmcontext = priv_data[0]; 253 pI810XvMC->fb_base = priv_data[1]; 254 pI810XvMC->overlay.offset = priv_data[2] + priv_data[1]; 255 pI810XvMC->overlay.size = priv_data[3]; 256 pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1]; 257 pI810XvMC->surfaces.size = priv_data[5]; 258 strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9); 259 pI810XvMC->busIdString[9] = '\0'; 260 261 /* Must free the private data we were passed from X */ 262 free(priv_data); 263 264 /* Initialize private context values */ 265 pI810XvMC->current = 0; 266 pI810XvMC->lock = 0; 267 pI810XvMC->last_flip = 0; 268 pI810XvMC->dual_prime = 0; 269 270 /* 271 Map dma Buffers: Not really, this would be a drmMapBufs 272 but due to the i810 security model we have to just create an 273 empty data structure to fake it. 274 */ 275 pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap)); 276 if(pI810XvMC->dmabufs == NULL) { 277 printf("Dma Bufs could not be mapped.\n"); 278 _xvmc_destroy_context(display, context); 279 free(pI810XvMC); 280 return BadAlloc; 281 } /* pI810XvMC->dmabufs == NULL */ 282 memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap)); 283 pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) * 284 I810_DMA_BUF_NR); 285 if(pI810XvMC->dmabufs->list == NULL) { 286 printf("Dma Bufs could not be mapped.\n"); 287 _xvmc_destroy_context(display, context); 288 free(pI810XvMC); 289 return BadAlloc; 290 } /* pI810XvMC->dmabufs->list == NULL */ 291 memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR); 292 293 /* Map the Overlay memory */ 294 if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset, 295 pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) { 296 printf("Unable to map Overlay at offset 0x%x and size 0x%x\n", 297 (unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size); 298 _xvmc_destroy_context(display, context); 299 free(pI810XvMC->dmabufs->list); 300 free(pI810XvMC); 301 return BadAlloc; 302 } /* drmMap() < 0 */ 303 304 /* Overlay Regs are offset 1024 into Overlay Map */ 305 pI810XvMC->oregs = (i810OverlayRec *) 306 ((unsigned char *)pI810XvMC->overlay.address + 1024); 307 308 /* Map Surfaces */ 309 if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset, 310 pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) { 311 printf("Unable to map XvMC Surfaces.\n"); 312 _xvmc_destroy_context(display, context); 313 free(pI810XvMC->dmabufs->list); 314 free(pI810XvMC); 315 return BadAlloc; 316 } /* drmMap() < 0 */ 317 318 /* 319 There is a tiny chance that someone was using the overlay and 320 issued a flip that hasn't finished. To be 100% sure I'll just 321 take the lock and sleep for the worst case time for a flip. 322 */ 323 I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); 324 usleep(20000); /* 1/50th Sec for 50hz refresh */ 325 326 /* Set up Overlay regs with Initial Values */ 327 pI810XvMC->oregs->YRGB_VPH = 0; 328 pI810XvMC->oregs->UV_VPH = 0; 329 pI810XvMC->oregs->HORZ_PH = 0; 330 pI810XvMC->oregs->INIT_PH = 0; 331 pI810XvMC->oregs->DWINPOS = 0; 332 pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) | 333 I810_XVMC_MAXWIDTH; 334 pI810XvMC->oregs->SWID = I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15); 335 pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) | 336 (I810_XVMC_MAXWIDTH << 12); 337 pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT | 338 (I810_XVMC_MAXHEIGHT << 15); 339 pI810XvMC->oregs->YRGBSCALE = 0x80004000; /* scale factor 1 */ 340 pI810XvMC->oregs->UVSCALE = 0x80004000; /* scale factor 1 */ 341 pI810XvMC->oregs->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ 342 pI810XvMC->oregs->OV0CLRC1 = 0x80; /* saturation: bypass */ 343 344 /* Destination Colorkey Setup */ 345 pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey); 346 pI810XvMC->oregs->DCLRKM = 0x80070307; 347 348 349 pI810XvMC->oregs->SCLRKVH = 0; 350 pI810XvMC->oregs->SCLRKVL = 0; 351 pI810XvMC->oregs->SCLRKM = 0; /* source color key disable */ 352 pI810XvMC->oregs->OV0CONF = 0; /* two 720 pixel line buffers */ 353 354 pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | 355 Y_ADJUST | YUV_420; 356 357 pI810XvMC->ref = 1; 358 359 I810_UNLOCK(pI810XvMC); 360 361 return Success; 362 363} 364 365/*************************************************************************** 366// Function: XvMCDestroyContext 367// Description: Destorys the specified context. 368// 369// Arguments: 370// display - Specifies the connection to the server. 371// context - The context to be destroyed. 372// 373// Returns: Status 374***************************************************************************/ 375_X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context) { 376 i810XvMCContext *pI810XvMC; 377 378 if(context == NULL) { 379 return (error_base + XvMCBadContext); 380 } 381 if(context->privData == NULL) { 382 return (error_base + XvMCBadContext); 383 } 384 pI810XvMC = (i810XvMCContext *)context->privData; 385 386 /* Turn off the overlay */ 387 if(pI810XvMC->last_flip) { 388 I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); 389 390 /* Make sure last flip is done */ 391 BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); 392 393 pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | 394 Y_ADJUST; 395 pI810XvMC->current = !pI810XvMC->current; 396 if(pI810XvMC->current == 1) { 397 pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0; 398 } 399 else { 400 pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0; 401 } 402 OVERLAY_FLIP(pI810XvMC); 403 pI810XvMC->last_flip++; 404 405 /* Wait for the flip */ 406 BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); 407 408 I810_UNLOCK(pI810XvMC); 409 } 410 411 /* Pass Control to the X server to destroy the drm_context_t */ 412 _xvmc_destroy_context(display, context); 413 414 i810_free_privContext(pI810XvMC); 415 context->privData = NULL; 416 417 return Success; 418} 419 420 421/*************************************************************************** 422// Function: XvMCCreateSurface 423***************************************************************************/ 424_X_EXPORT Status XvMCCreateSurface( Display *display, XvMCContext *context, 425 XvMCSurface *surface) { 426 i810XvMCContext *pI810XvMC; 427 i810XvMCSurface *pI810Surface; 428 int priv_count; 429 uint *priv_data; 430 Status ret; 431 432 if((surface == NULL) || (context == NULL) || (display == NULL)){ 433 return BadValue; 434 } 435 436 pI810XvMC = (i810XvMCContext *)context->privData; 437 if(pI810XvMC == NULL) { 438 return (error_base + XvMCBadContext); 439 } 440 441 442 surface->privData = (i810XvMCSurface *)malloc(sizeof(i810XvMCSurface)); 443 if(!surface->privData) { 444 return BadAlloc; 445 } 446 pI810Surface = (i810XvMCSurface *)surface->privData; 447 448 /* Initialize private values */ 449 pI810Surface->privContext = pI810XvMC; 450 pI810Surface->last_render = 0; 451 pI810Surface->last_flip = 0; 452 pI810Surface->second_field = 0; 453 454 if((ret = _xvmc_create_surface(display, context, surface, 455 &priv_count, &priv_data))) { 456 free(pI810Surface); 457 printf("Unable to create XvMCSurface.\n"); 458 return ret; 459 } 460 461 /* 462 _xvmc_create_subpicture returns 2 uints with the offset into 463 the DRM map for the Y surface and UV surface. 464 */ 465 if(priv_count != 2) { 466 printf("_xvmc_create_surface() return incorrect data size.\n"); 467 printf("Expected 2 got %d\n",priv_count); 468 free(priv_data); 469 free(pI810Surface); 470 return BadAlloc; 471 } 472 /* Data == Client Address, offset == Physical address offset */ 473 pI810Surface->data = pI810XvMC->surfaces.address; 474 pI810Surface->offset = pI810XvMC->surfaces.offset; 475 476 477 /* 478 i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch 479 and the Tiler need 512k aligned surfaces, basically we are 480 stuck with fixed memory with pitch 1024 for Y data. UV = 512. 481 */ 482 pI810Surface->pitch = 10; 483 if((surface->surface_type_id == FOURCC_UYVY) || 484 (surface->surface_type_id == FOURCC_YUY2)) { 485 /* This is not implemented server side. */ 486 pI810Surface->pitch++; 487 } 488 489 /* 490 offsets[0,1,2] == Offsets from either data or offset for the Y 491 U and V surfaces. 492 */ 493 pI810Surface->offsets[0] = priv_data[0]; 494 if(((unsigned long)pI810Surface->data + pI810Surface->offsets[0]) & 4095) { 495 printf("XvMCCreateSurface: Surface offset 0 is not 4096 aligned\n"); 496 } 497 498 if((surface->surface_type_id == FOURCC_UYVY) || 499 (surface->surface_type_id == FOURCC_YUY2)) { 500 /* Packed surface, not fully implemented */ 501 pI810Surface->offsets[1] = 0; 502 pI810Surface->offsets[2] = 0; 503 } 504 else { 505 /* Planar surface */ 506 pI810Surface->offsets[1] = priv_data[1]; 507 if(((unsigned long)pI810Surface->data + pI810Surface->offsets[1]) & 2047) { 508 printf("XvMCCreateSurface: Surface offset 1 is not 2048 aligned\n"); 509 } 510 511 pI810Surface->offsets[2] = ((unsigned long)pI810Surface->offsets[1] + 512 (1<<(pI810Surface->pitch - 1)) * 288); 513 if(((unsigned long)pI810Surface->data + pI810Surface->offsets[2]) & 2047) { 514 printf("XvMCCreateSurface: Surface offset 2 is not 2048 aligned\n"); 515 } 516 517 } 518 519 /* Free data returned from xvmc_create_surface */ 520 free(priv_data); 521 522 /* Clear the surface to 0 */ 523 memset((void *)((unsigned long)pI810Surface->data + (unsigned long)pI810Surface->offsets[0]), 524 0, ((1<<pI810Surface->pitch) * surface->height)); 525 526 switch(surface->surface_type_id) { 527 case FOURCC_YV12: 528 case FOURCC_I420: 529 /* Destination buffer info command */ 530 pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset + 531 pI810Surface->offsets[0]) & ~0xfc000fff) | 532 (pI810Surface->pitch - 9)); 533 pI810Surface->dbi1u = ((((unsigned int)pI810Surface->offset + 534 pI810Surface->offsets[1]) & ~0xfc000fff) | 535 (pI810Surface->pitch - 10)); 536 pI810Surface->dbi1v = ((((unsigned int)pI810Surface->offset + 537 pI810Surface->offsets[2]) & ~0xfc000fff) | 538 (pI810Surface->pitch - 10)); 539 540 /* Destination buffer variables command */ 541 pI810Surface->dbv1 = (0x8<<20) | (0x8<<16); 542 /* Map info command */ 543 pI810Surface->mi1y = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 3); 544 pI810Surface->mi1u = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4); 545 pI810Surface->mi1v = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4); 546 547 pI810Surface->mi2y = (((unsigned int)surface->height - 1)<<16) | 548 ((unsigned int)surface->width - 1); 549 pI810Surface->mi2u = (((unsigned int)surface->height - 1)<<15) | 550 (((unsigned int)surface->width - 1)>>1); 551 pI810Surface->mi2v = pI810Surface->mi2u; 552 553 pI810Surface->mi3y = ((unsigned int)pI810Surface->offset + 554 pI810Surface->offsets[0]) & ~0x0000000f; 555 pI810Surface->mi3u = ((unsigned int)pI810Surface->offset + 556 pI810Surface->offsets[1]) & ~0x0000000f; 557 pI810Surface->mi3v = ((unsigned int)pI810Surface->offset + 558 pI810Surface->offsets[2]) & ~0x0000000f; 559 break; 560 case FOURCC_UYVY: 561 case FOURCC_YUY2: 562 default: 563 /* Destination buffer info command */ 564 pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset + 565 pI810Surface->offsets[0]) & ~0xfc000fff) | 566 (pI810Surface->pitch - 9)); 567 /* Destination buffer variables command */ 568 if(surface->surface_type_id == FOURCC_YUY2) { 569 pI810Surface->dbv1 = 0x5<<8; 570 pI810Surface->mi1y = 0x5<<24 | pI810Surface->pitch | 0x1<<21; 571 } 572 else { 573 pI810Surface->dbv1 = 0x4<<8; 574 pI810Surface->mi1y = 0x5<<24 | (pI810Surface->pitch - 3); 575 } 576 pI810Surface->mi2y = (((unsigned int)surface->width - 1)<<16) | 577 ((unsigned int)surface->height - 1); 578 pI810Surface->mi3y = ((unsigned int)pI810Surface->offset + 579 pI810Surface->offsets[0]) & ~0xfc000fff; 580 break; 581 } 582 pI810XvMC->ref++; 583 584 return Success; 585} 586 587 588/*************************************************************************** 589// Function: XvMCDestroySurface 590***************************************************************************/ 591_X_EXPORT Status XvMCDestroySurface(Display *display, XvMCSurface *surface) { 592 i810XvMCSurface *pI810Surface; 593 i810XvMCContext *pI810XvMC; 594 595 if((display == NULL) || (surface == NULL)) { 596 return BadValue; 597 } 598 if(surface->privData == NULL) { 599 return (error_base + XvMCBadSurface); 600 } 601 602 pI810Surface = (i810XvMCSurface *)surface->privData; 603 if(pI810Surface->last_flip) { 604 XvMCSyncSurface(display,surface); 605 } 606 pI810XvMC = (i810XvMCContext *)pI810Surface->privContext; 607 608 _xvmc_destroy_surface(display,surface); 609 610 i810_free_privContext(pI810XvMC); 611 612 free(pI810Surface); 613 surface->privData = NULL; 614 return Success; 615} 616 617/*************************************************************************** 618// Function: XvMCCreateBlocks 619***************************************************************************/ 620_X_EXPORT Status XvMCCreateBlocks(Display *display, XvMCContext *context, 621 unsigned int num_blocks, 622 XvMCBlockArray *block) { 623 624 if((display == NULL) || (context == NULL) || (num_blocks == 0)) { 625 return BadValue; 626 } 627 628 block->blocks = (short *)malloc(num_blocks<<6 * sizeof(short)); 629 if(block->blocks == NULL) { 630 return BadAlloc; 631 } 632 633 block->num_blocks = num_blocks; 634 block->context_id = context->context_id; 635 636 block->privData = NULL; 637 638 return Success; 639} 640 641/*************************************************************************** 642// Function: XvMCDestroyBlocks 643***************************************************************************/ 644_X_EXPORT Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) { 645 if(display == NULL) { 646 return BadValue; 647 } 648 649 free(block->blocks); 650 block->num_blocks = 0; 651 block->context_id = 0; 652 block->privData = NULL; 653 return Success; 654} 655 656/*************************************************************************** 657// Function: XvMCCreateMacroBlocks 658***************************************************************************/ 659_X_EXPORT Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, 660 unsigned int num_blocks, 661 XvMCMacroBlockArray *blocks) { 662 663 if((display == NULL) || (context == NULL) || (blocks == NULL) || 664 (num_blocks == 0)) { 665 return BadValue; 666 } 667 memset(blocks,0,sizeof(XvMCMacroBlockArray)); 668 blocks->context_id = context->context_id; 669 blocks->privData = NULL; 670 671 blocks->macro_blocks = (XvMCMacroBlock *) 672 malloc(num_blocks * sizeof(XvMCMacroBlock)); 673 if(blocks->macro_blocks == NULL) { 674 return BadAlloc; 675 } 676 blocks->num_blocks = num_blocks; 677 678 return Success; 679} 680 681/*************************************************************************** 682// Function: XvMCDestroyMacroBlocks 683***************************************************************************/ 684_X_EXPORT Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block) { 685 if((display == NULL) || (block == NULL)) { 686 return BadValue; 687 } 688 if(block->macro_blocks) { 689 free(block->macro_blocks); 690 } 691 block->context_id = 0; 692 block->num_blocks = 0; 693 block->privData = NULL; 694 695 return Success; 696} 697 698 699/*************************************************************************** 700// Function: dp (Debug Print) 701// Description: This function prints out in hex i * uint32_t at the address 702// supplied. This enables you to print out the dma buffers from 703// within the debugger even though they are not in your address space. 704***************************************************************************/ 705void dp(unsigned int *address, unsigned int i) { 706 int j; 707 708 printf("DebugPrint:\n"); 709 for(j=0; j<i; j++) { 710 printf("0x%8.8x ",address[j]); 711 if(j && !(j & 7)) { printf("\n");} 712 } 713} 714 715/*************************************************************************** 716// Macro: PACK_* 717// Description: Packs 16bit signed data from blocks into either 8bit unsigned 718// intra data or 16bit signed correction data, both packed into 719// 32 bit integers. 720***************************************************************************/ 721#define PACK_INTRA_DATA(d,b,n) \ 722 do { \ 723 char *dp = (char *)d; \ 724 char *bp = (char *)b; \ 725 int counter; \ 726 for(counter = 0; counter < n; counter++) { \ 727 *dp++ = *bp; \ 728 bp += 2; \ 729 } \ 730 }while(0); 731 732#define PACK_CORR_DATA(d,b,n) \ 733 memcpy(d,b,n); \ 734 d = (uint *)((unsigned long)d + n); 735 736#define MARK_CORR_DATA(d,n) \ 737 do { \ 738 uint* q = (uint*)((unsigned long)d - n); \ 739 while((unsigned long)q < (unsigned long)d) { \ 740 *q++ += 0x00330033; \ 741 } \ 742 }while(0); 743 744#define MARK_INTRA_BLOCK(d) \ 745 do { \ 746 int q; \ 747 for(q=0; q<16; q++) { \ 748 d[q] += 0x33333333; \ 749 } \ 750 }while(0); 751 752/* 753 Used for DCT 1 when we need DCT 0. Instead 754 of reading from one block we read from two and 755 interlace. 756*/ 757#define PACK_CORR_DATA_1to0(d,top,bottom) \ 758 do { \ 759 short *t = top,*b = bottom; \ 760 PACK_CORR_DATA(d,t,16); \ 761 t = (short *)((unsigned long)t + 16); \ 762 PACK_CORR_DATA(d,b,16); \ 763 b = (short *)((unsigned long)b + 16); \ 764 PACK_CORR_DATA(d,t,16); \ 765 t = (short *)((unsigned long)t + 16); \ 766 PACK_CORR_DATA(d,b,16); \ 767 b = (short *)((unsigned long)b + 16); \ 768 PACK_CORR_DATA(d,t,16); \ 769 t = (short *)((unsigned long)t + 16); \ 770 PACK_CORR_DATA(d,b,16); \ 771 b = (short *)((unsigned long)b + 16); \ 772 PACK_CORR_DATA(d,t,16); \ 773 t = (short *)((unsigned long)t + 16); \ 774 PACK_CORR_DATA(d,b,16); \ 775 b = (short *)((unsigned long)b + 16); \ 776 }while(0); 777 778/* Used for DCT 0 when we need DCT 1. */ 779#define PACK_CORR_DATA_0to1(d,top,bottom) \ 780 do{ \ 781 short *t = top,*b = bottom; \ 782 PACK_CORR_DATA(d,t,16); \ 783 t = (short *)((unsigned long)t + 32); \ 784 PACK_CORR_DATA(d,t,16); \ 785 t = (short *)((unsigned long)t + 32); \ 786 PACK_CORR_DATA(d,t,16); \ 787 t = (short *)((unsigned long)t + 32); \ 788 PACK_CORR_DATA(d,t,16); \ 789 t = (short *)((unsigned long)t + 32); \ 790 PACK_CORR_DATA(d,b,16); \ 791 b = (short *)((unsigned long)b + 32); \ 792 PACK_CORR_DATA(d,b,16); \ 793 b = (short *)((unsigned long)b + 32); \ 794 PACK_CORR_DATA(d,b,16); \ 795 b = (short *)((unsigned long)b + 32); \ 796 PACK_CORR_DATA(d,b,16); \ 797 b = (short *)((unsigned long)b + 32); \ 798 }while(0); 799 800#define PACK_CORR_DATA_SHORT(d,block) \ 801 do { \ 802 short *b = block; \ 803 PACK_CORR_DATA(d,b,16); \ 804 b = (short *)((unsigned long)b + 32); \ 805 PACK_CORR_DATA(d,b,16); \ 806 b = (short *)((unsigned long)b + 32); \ 807 PACK_CORR_DATA(d,b,16); \ 808 b = (short *)((unsigned long)b + 32); \ 809 PACK_CORR_DATA(d,b,16); \ 810 b = (short *)((unsigned long)b + 32); \ 811 }while(0); 812 813/* Lookup tables to speed common calculations */ 814static unsigned int drps_table[] = {2<<6,3<<6}; 815 816static unsigned int mvfs_table[] = { 817 0x12, 818 0x1a, 819 0x13, 820 0x1b 821}; 822 823static unsigned int type_table[] = { 824 0x1<<12, /* This is an error so make it Forward motion */ 825 0x1<<12, 826 0x1<<12, 827 0x1<<12, 828 0x2<<12, 829 0x2<<12, 830 0x3<<12, 831 0x3<<12, 832 0x1<<12, /* Pattern but no Motion, Make motion Forward */ 833 0x1<<12, 834 0x1<<12, 835 0x1<<12, 836 0x2<<12, 837 0x2<<12, 838 0x3<<12, 839 0x3<<12 840}; 841 842static unsigned int y_frame_bytes[] = { 843 0,0,0,0,128,128,128,128, 844 128,128,128,128,256,256,256,256, 845 128,128,128,128,256,256,256,256, 846 256,256,256,256,384,384,384,384, 847 128,128,128,128,256,256,256,256, 848 256,256,256,256,384,384,384,384, 849 256,256,256,256,384,384,384,384, 850 384,384,384,384,512,512,512,512 851}; 852 853static unsigned int u_frame_bytes[] = { 854 0,0,128,128,0,0,128,128, 855 0,0,128,128,0,0,128,128, 856 0,0,128,128,0,0,128,128, 857 0,0,128,128,0,0,128,128, 858 0,0,128,128,0,0,128,128, 859 0,0,128,128,0,0,128,128, 860 0,0,128,128,0,0,128,128, 861 0,0,128,128,0,0,128,128 862}; 863 864static unsigned int v_frame_bytes[] = { 865 0,128,0,128,0,128,0,128, 866 0,128,0,128,0,128,0,128, 867 0,128,0,128,0,128,0,128, 868 0,128,0,128,0,128,0,128, 869 0,128,0,128,0,128,0,128, 870 0,128,0,128,0,128,0,128, 871 0,128,0,128,0,128,0,128, 872 0,128,0,128,0,128,0,128 873}; 874 875static unsigned int y_first_field_bytes[] = { 876 0,0,0,0,0,0,0,0, 877 0,0,0,0,0,0,0,0, 878 128,128,128,128,128,128,128,128, 879 128,128,128,128,128,128,128,128, 880 128,128,128,128,128,128,128,128, 881 128,128,128,128,128,128,128,128, 882 256,256,256,256,256,256,256,256, 883 256,256,256,256,256,256,256,256 884}; 885 886static unsigned int y_second_field_bytes[] = { 887 0,0,0,0,128,128,128,128, 888 128,128,128,128,256,256,256,256, 889 0,0,0,0,128,128,128,128, 890 128,128,128,128,256,256,256,256, 891 0,0,0,0,128,128,128,128, 892 128,128,128,128,256,256,256,256, 893 0,0,0,0,128,128,128,128, 894 128,128,128,128,256,256,256,256 895}; 896 897static unsigned int y_dct0_field_bytes[] = { 898 0,0,0,0,128,128,128,128, 899 128,128,128,128,256,256,256,256, 900 128,128,128,128,128,128,128,128, 901 256,256,256,256,256,256,256,256, 902 128,128,128,128,256,256,256,256, 903 128,128,128,128,256,256,256,256, 904 256,256,256,256,256,256,256,256, 905 256,256,256,256,256,256,256,256 906}; 907 908static unsigned int y_dct1_frame_bytes[] = { 909 0,0,0,0,256,256,256,256, 910 256,256,256,256,512,512,512,512, 911 256,256,256,256,256,256,256,256, 912 512,512,512,512,512,512,512,512, 913 256,256,256,256,512,512,512,512, 914 256,256,256,256,512,512,512,512, 915 512,512,512,512,512,512,512,512, 916 512,512,512,512,512,512,512,512 917}; 918 919static unsigned int u_field_bytes[] = { 920 0,0,64,64,0,0,64,64, 921 0,0,64,64,0,0,64,64, 922 0,0,64,64,0,0,64,64, 923 0,0,64,64,0,0,64,64, 924 0,0,64,64,0,0,64,64, 925 0,0,64,64,0,0,64,64, 926 0,0,64,64,0,0,64,64, 927 0,0,64,64,0,0,64,64 928}; 929 930static unsigned int v_field_bytes[] = { 931 0,64,0,64,0,64,0,64, 932 0,64,0,64,0,64,0,64, 933 0,64,0,64,0,64,0,64, 934 0,64,0,64,0,64,0,64, 935 0,64,0,64,0,64,0,64, 936 0,64,0,64,0,64,0,64, 937 0,64,0,64,0,64,0,64, 938 0,64,0,64,0,64,0,64 939}; 940 941static short empty_block[] = { 942 0,0,0,0,0,0,0,0, 943 0,0,0,0,0,0,0,0, 944 0,0,0,0,0,0,0,0, 945 0,0,0,0,0,0,0,0, 946 0,0,0,0,0,0,0,0, 947 0,0,0,0,0,0,0,0, 948 0,0,0,0,0,0,0,0, 949 0,0,0,0,0,0,0,0 950}; 951 952 953/*************************************************************************** 954// Function: dispatchYContext 955// Description: Allocate a DMA buffer write the Y MC Context info in it, 956// and dispatch it to hardware. 957***************************************************************************/ 958 959static __inline__ void dispatchYContext(i810XvMCSurface *privTarget, 960 i810XvMCSurface *privPast, 961 i810XvMCSurface *privFuture, 962 i810XvMCContext *pI810XvMC) { 963 uint *data; 964 drmBufPtr pDMA; 965 drm_i810_mc_t mc; 966 967 pDMA = i810_get_free_buffer(pI810XvMC); 968 data = pDMA->address; 969 *data++ = CMD_FLUSH; 970 *data++ = BOOLEAN_ENA_2; 971 *data++ = CMD_FLUSH; 972 *data++ = DEST_BUFFER_INFO; 973 *data++ = privTarget->dbi1y; 974 *data++ = DEST_BUFFER_VAR; 975 *data++ = privTarget->dbv1; 976 /* Past Surface */ 977 *data++ = CMD_MAP_INFO; 978 *data++ = privPast->mi1y; 979 *data++ = privPast->mi2y; 980 *data++ = privPast->mi3y; 981 /* Future Surface */ 982 *data++ = CMD_MAP_INFO; 983 *data++ = privFuture->mi1y | 0x1<<28; 984 *data++ = privFuture->mi2y; 985 *data++ = privFuture->mi3y; 986 987 mc.idx = pDMA->idx; 988 mc.used = (unsigned long)data - (unsigned long)pDMA->address; 989 mc.last_render = ++pI810XvMC->last_render; 990 privTarget->last_render = pI810XvMC->last_render; 991 I810_MC(pI810XvMC,mc); 992} 993 994static __inline__ void renderError(void) { 995 printf("Invalid Macroblock Parameters found.\n"); 996 return; 997} 998 999/*************************************************************************** 1000// Function: renderIntrainFrame 1001// Description: inline function that sets hardware parameters for an Intra 1002// encoded macroblock in a Frame picture. 1003***************************************************************************/ 1004static __inline__ void renderIntrainFrame(uint **datay,uint **datau, 1005 uint **datav, 1006 XvMCMacroBlock *mb, 1007 short *block_ptr) { 1008 1009 register uint *dy = *datay; 1010 register uint *du = *datau; 1011 register uint *dv = *datav; 1012 1013 /* Y Blocks */ 1014 *dy++ = GFXBLOCK + 68; 1015 *dy++ = (1<<30) | (3<<28) | (0xf<<24); 1016 *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1017 *dy++ = (16<<16) | 16; 1018 *dy++ = 0; 1019 *dy++ = 0; 1020 PACK_INTRA_DATA(dy,block_ptr,256); 1021 dy += 64; 1022 block_ptr += 256; 1023 /* End Y Blocks */ 1024 1025 /* U Block */ 1026 *du++ = GFXBLOCK + 20; 1027 *du++ = (2<<30) | (1<<28) | (1<<23); 1028 *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); 1029 *du++ = (8<<16) | 8; 1030 *du++ = 0; 1031 *du++ = 0; 1032 PACK_INTRA_DATA(du,block_ptr,64); 1033 du += 16; 1034 block_ptr += 64; 1035 1036 /* V Block */ 1037 *dv++ = GFXBLOCK + 20; 1038 *dv++ = (3<<30) | (1<<28) | (1<<22); 1039 *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); 1040 *dv++ = (8<<16) | 8; 1041 *dv++ = 0; 1042 *dv++ = 0; 1043 PACK_INTRA_DATA(dv,block_ptr,64); 1044 dv += 16; 1045 block_ptr += 64; 1046 1047 *datay = dy; 1048 *datau = du; 1049 *datav = dv; 1050} 1051 1052/*************************************************************************** 1053// Function: renderIntrainFrameDCT1 1054// Description: inline function that sets hardware parameters for an Intra 1055// encoded macroblock in a Frame picture with DCT type 1. 1056***************************************************************************/ 1057static __inline__ void renderIntrainFrameDCT1(uint **datay,uint **datau, 1058 uint **datav,XvMCMacroBlock *mb, 1059 short *block_ptr,uint flags) { 1060 1061 register uint *dy = *datay; 1062 register uint *du = *datau; 1063 register uint *dv = *datav; 1064 1065 1066 /* Y Blocks */ 1067 *dy++ = GFXBLOCK + 36; 1068 *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x2<<6); 1069 *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3); 1070 *dy++ = (8<<16) | 16; 1071 *dy++ = 0; 1072 *dy++ = 0; 1073 PACK_INTRA_DATA(dy,block_ptr,128); 1074 dy += 32; 1075 block_ptr += 128; 1076 1077 /* Second Y block */ 1078 *dy++ = GFXBLOCK + 36; 1079 *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x3<<6); 1080 *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3); 1081 *dy++ = (8<<16) | 16; 1082 *dy++ = 0; 1083 *dy++ = 0; 1084 PACK_INTRA_DATA(dy,block_ptr,128); 1085 dy += 32; 1086 block_ptr += 128; 1087 /* End Y Blocks */ 1088 1089 1090 /* U Block */ 1091 *du++ = GFXBLOCK + 20; 1092 *du++ = (2<<30) | (1<<28) | (1<<23); 1093 *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); 1094 *du++ = (8<<16) | 8; 1095 *du++ = 0; 1096 *du++ = 0; 1097 PACK_INTRA_DATA(du,block_ptr,64); 1098 du += 16; 1099 block_ptr += 64; 1100 1101 /* V Block */ 1102 *dv++ = GFXBLOCK + 20; 1103 *dv++ = (3<<30) | (1<<28) | (1<<22); 1104 *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); 1105 *dv++ = (8<<16) | 8; 1106 *dv++ = 0; 1107 *dv++ = 0; 1108 PACK_INTRA_DATA(dv,block_ptr,64); 1109 dv += 16; 1110 block_ptr += 64; 1111 1112 *datay = dy; 1113 *datau = du; 1114 *datav = dv; 1115} 1116 1117 1118/*************************************************************************** 1119// Function: renderIntrainField 1120// Description: inline function that sets hardware parameters for an Intra 1121// encoded macroblock in Field pictures. 1122***************************************************************************/ 1123static __inline__ void renderIntrainField(uint **datay,uint **datau, 1124 uint **datav, 1125 XvMCMacroBlock *mb,short *block_ptr, 1126 uint ps) { 1127 1128 register uint *dy = *datay; 1129 register uint *du = *datau; 1130 register uint *dv = *datav; 1131 1132 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1133 uint dw1 = drps_table[~ps & 0x1]; 1134 1135 /* Y Blocks */ 1136 *dy++ = GFXBLOCK + 68; 1137 *dy++ = (1<<30) | (3<<28) | (0xf<<24) | dw1; 1138 *dy++ = xy; 1139 *dy++ = (16<<16) | 16; 1140 *dy++ = 0; 1141 *dy++ = 0; 1142 PACK_INTRA_DATA(dy,block_ptr,256); 1143 dy += 64; 1144 block_ptr += 256; 1145 /* End Y Blocks */ 1146 1147 xy >>= 1; 1148 1149 /* U Block */ 1150 *du++ = GFXBLOCK + 20; 1151 *du++ = (2<<30) | (1<<28) | (1<<23) | dw1; 1152 *du++ = xy; 1153 *du++ = (8<<16) | 8; 1154 *du++ = 0; 1155 *du++ = 0; 1156 PACK_INTRA_DATA(du,block_ptr,64); 1157 du += 16; 1158 block_ptr += 64; 1159 1160 /* V Block */ 1161 *dv++ = GFXBLOCK + 20; 1162 *dv++ = (3<<30) | (1<<28) | (1<<22) | dw1; 1163 *dv++ = xy; 1164 *dv++ = (8<<16) | 8; 1165 *dv++ = 0; 1166 *dv++ = 0; 1167 PACK_INTRA_DATA(dv,block_ptr,64); 1168 dv += 16; 1169 block_ptr += 64; 1170 1171 *datay = dy; 1172 *datau = du; 1173 *datav = dv; 1174} 1175 1176 1177/*************************************************************************** 1178// Function: renderFieldinField 1179// Description: inline function that sets hardware parameters for a Field 1180// encoded macroblock in a Field Picture. 1181***************************************************************************/ 1182static __inline__ void renderFieldinField(uint **datay,uint **datau, 1183 uint **datav, 1184 XvMCMacroBlock *mb,short *block_ptr, 1185 uint ps, uint flags) { 1186 1187 register uint *dy = *datay; 1188 register uint *du = *datau; 1189 register uint *dv = *datav; 1190 1191 /* Motion Vectors */ 1192 short fmv[2]; 1193 short bmv[2]; 1194 /* gfxblock dword 1 */ 1195 uint dw1; 1196 1197 uint parity = ~ps & XVMC_TOP_FIELD; 1198 1199 uint ysize = y_frame_bytes[mb->coded_block_pattern]; 1200 uint usize = u_frame_bytes[mb->coded_block_pattern]; 1201 uint vsize = v_frame_bytes[mb->coded_block_pattern]; 1202 1203 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1204 1205 /* i810 Specific flag used to identify the second field in a P frame */ 1206 if(flags & 0x80000000) { 1207 /* P Frame */ 1208 if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) == 1209 parity) { 1210 /* Same parity, use reference field (map0) */ 1211 dw1 = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) | 1212 (((uint)mb->coded_block_pattern)<<22); 1213 fmv[0] = mb->PMV[0][0][1]; 1214 fmv[1] = mb->PMV[0][0][0]; 1215 bmv[0] = 0; 1216 bmv[1] = 0; 1217 } 1218 else { 1219 /* 1220 Opposite parity, set up as if it were backward 1221 motion and use map1. 1222 */ 1223 dw1 = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) | 1224 (((uint)mb->coded_block_pattern)<<22); 1225 bmv[0] = mb->PMV[0][0][1]; 1226 bmv[1] = mb->PMV[0][0][0]; 1227 fmv[0] = 0; 1228 fmv[1] = 0; 1229 } 1230 } 1231 else { 1232 dw1 = type_table[mb->macroblock_type & 0xf] | 1233 drps_table[~ps & 0x1] | 1234 mvfs_table[mb->motion_vertical_field_select & 3] | 1235 (((uint)mb->coded_block_pattern)<<22); 1236 1237 fmv[0] = mb->PMV[0][0][1]; 1238 fmv[1] = mb->PMV[0][0][0]; 1239 1240 bmv[0] = mb->PMV[0][1][1]; 1241 bmv[1] = mb->PMV[0][1][0]; 1242 } 1243 1244 /* Y Block */ 1245 *dy++ = GFXBLOCK + 4 + (ysize>>2); 1246 *dy++ = (1<<30) | (3<<28) | dw1; 1247 *dy++ = xy; 1248 *dy++ = (16<<16) | 16; 1249 *dy++ = *(uint *)fmv; 1250 *dy++ = *(uint *)bmv; 1251 PACK_CORR_DATA(dy,block_ptr,ysize); 1252 block_ptr = (short *)((unsigned long)block_ptr + ysize); 1253 /* End Y Blocks */ 1254 1255 fmv[0] /= 2; 1256 fmv[1] /= 2; 1257 bmv[0] /= 2; 1258 bmv[1] /= 2; 1259 xy >>= 1; 1260 1261 /* U Block */ 1262 *du++ = GFXBLOCK + 4 + (usize>>2); 1263 *du++ = (2<<30) | (1<<28) | dw1; 1264 *du++ = xy; 1265 *du++ = (8<<16) | 8; 1266 *du++ = *(uint *)fmv; 1267 *du++ = *(uint *)bmv; 1268 PACK_CORR_DATA(du,block_ptr,usize); 1269 block_ptr = (short *)((unsigned long)block_ptr + usize); 1270 1271 /* V Block */ 1272 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1273 *dv++ = (3<<30) | (1<<28) | dw1; 1274 *dv++ = xy; 1275 *dv++ = (8<<16) | 8; 1276 *dv++ = *(uint *)fmv; 1277 *dv++ = *(uint *)bmv; 1278 PACK_CORR_DATA(dv,block_ptr,vsize); 1279 block_ptr = (short *)((unsigned long)block_ptr + vsize); 1280 1281 *datay = dy; 1282 *datau = du; 1283 *datav = dv; 1284} 1285 1286/*************************************************************************** 1287// Function: render16x8inField 1288// Description: inline function that sets hardware parameters for a 16x8 1289// encoded macroblock in a field picture. 1290***************************************************************************/ 1291static __inline__ void render16x8inField(uint **datay,uint **datau, 1292 uint **datav, 1293 XvMCMacroBlock *mb,short *block_ptr, 1294 uint ps, uint flags) { 1295 1296 register uint *dy = *datay; 1297 register uint *du = *datau; 1298 register uint *dv = *datav; 1299 1300 /* Motion Vectors */ 1301 short fmv[4]; 1302 short bmv[4]; 1303 /* gfxblock dword 1 */ 1304 uint dw1[2]; 1305 1306 uint y1size = y_first_field_bytes[mb->coded_block_pattern]; 1307 uint y2size = y_second_field_bytes[mb->coded_block_pattern]; 1308 uint usize = u_field_bytes[mb->coded_block_pattern]; 1309 uint vsize = v_field_bytes[mb->coded_block_pattern]; 1310 1311 uint parity = ~ps & XVMC_TOP_FIELD; 1312 1313 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1314 1315 /* i810 Specific flag used to identify the second field in a P frame */ 1316 if(flags & 0x80000000) { 1317 /* P Frame */ 1318 if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) == 1319 parity) { 1320 /* Same parity, use reference field (map0) */ 1321 dw1[0] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) | 1322 (((uint)mb->coded_block_pattern)<<22); 1323 1324 fmv[0] = mb->PMV[0][0][1]; 1325 fmv[1] = mb->PMV[0][0][0]; 1326 bmv[0] = 0; 1327 bmv[1] = 0; 1328 } 1329 else { 1330 /* 1331 Opposite parity, set up as if it were backward 1332 motion and use map1. 1333 */ 1334 dw1[0] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) | 1335 (((uint)mb->coded_block_pattern)<<22); 1336 1337 bmv[0] = mb->PMV[0][0][1]; 1338 bmv[1] = mb->PMV[0][0][0]; 1339 fmv[0] = 0; 1340 fmv[1] = 0; 1341 } 1342 if((mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD) == 1343 (parity<<2)) { 1344 /* Same parity, use reference field (map0) */ 1345 dw1[1] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) | 1346 ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) | 1347 (((uint)mb->coded_block_pattern<<24) & (0x3<<26))); 1348 1349 fmv[2] = mb->PMV[1][0][1]; 1350 fmv[3] = mb->PMV[1][0][0]; 1351 bmv[2] = 0; 1352 bmv[3] = 0; 1353 } 1354 else { 1355 /* 1356 Opposite parity, set up as if it were backward 1357 motion and use map1. 1358 */ 1359 dw1[1] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) | 1360 ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) | 1361 (((uint)mb->coded_block_pattern<<24) & (0x3<<26))); 1362 1363 bmv[2] = mb->PMV[1][0][1]; 1364 bmv[3] = mb->PMV[1][0][0]; 1365 fmv[2] = 0; 1366 fmv[3] = 0; 1367 } 1368 } 1369 else { 1370 dw1[0] = type_table[mb->macroblock_type & 0xf] | 1371 drps_table[~ps & 0x1] | 1372 mvfs_table[mb->motion_vertical_field_select & 3] | 1373 (((uint)mb->coded_block_pattern)<<22); 1374 1375 dw1[1] = type_table[mb->macroblock_type & 0xf] | 1376 drps_table[~ps & 0x1] | 1377 mvfs_table[(mb->motion_vertical_field_select>>2) & 0x3] | 1378 ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) | 1379 (((uint)mb->coded_block_pattern<<24) & (0x3<<26))); 1380 1381 fmv[0] = mb->PMV[0][0][1]; 1382 fmv[1] = mb->PMV[0][0][0]; 1383 fmv[2] = mb->PMV[1][0][1]; 1384 fmv[3] = mb->PMV[1][0][0]; 1385 1386 bmv[0] = mb->PMV[0][1][1]; 1387 bmv[1] = mb->PMV[0][1][0]; 1388 bmv[2] = mb->PMV[1][1][1]; 1389 bmv[3] = mb->PMV[1][1][0]; 1390 } 1391 1392 /* First Y Block */ 1393 *dy++ = GFXBLOCK + 4 + (y1size>>2); 1394 *dy++ = (1<<30) | (2<<28) | dw1[0]; 1395 *dy++ = xy; 1396 *dy++ = (8<<16) | 16; 1397 *dy++ = *(uint *)fmv; 1398 *dy++ = *(uint *)bmv; 1399 PACK_CORR_DATA(dy,block_ptr,y1size); 1400 block_ptr = (short *)((unsigned long)block_ptr + y1size); 1401 1402 /* Second Y Block */ 1403 *dy++ = GFXBLOCK + 4 + (y2size>>2); 1404 *dy++ = (1<<30) | (2<<28) | dw1[1]; 1405 *dy++ = (xy + 8); 1406 *dy++ = (8<<16) | 16; 1407 *dy++ = *(uint *)&fmv[2]; 1408 *dy++ = *(uint *)&bmv[2]; 1409 PACK_CORR_DATA(dy,block_ptr,y2size); 1410 block_ptr = (short *)((unsigned long)block_ptr + y2size); 1411 /* End Y Blocks */ 1412 1413 fmv[0] /= 2; 1414 fmv[1] /= 2; 1415 fmv[2] /= 2; 1416 fmv[3] /= 2; 1417 1418 bmv[0] /= 2; 1419 bmv[1] /= 2; 1420 bmv[2] /= 2; 1421 bmv[3] /= 2; 1422 1423 xy >>= 1; 1424 1425 /* U Blocks */ 1426 *du++ = GFXBLOCK + 4 + (usize>>2); 1427 *du++ = (2<<30) | (1<<28) | dw1[0]; 1428 *du++ = xy; 1429 *du++ = (4<<16) | 8; 1430 *du++ = *(uint *)fmv; 1431 *du++ = *(uint *)bmv; 1432 PACK_CORR_DATA(du,block_ptr,usize); 1433 block_ptr = (short *)((unsigned long)block_ptr + usize); 1434 1435 /* Second U block */ 1436 *du++ = GFXBLOCK + 4 + (usize>>2); 1437 *du++ = (2<<30) | (1<<28) | dw1[1]; 1438 *du++ = (xy + 4); 1439 *du++ = (4<<16) | 8; 1440 *du++ = *(uint *)&fmv[2]; 1441 *du++ = *(uint *)&bmv[2]; 1442 PACK_CORR_DATA(du,block_ptr,usize); 1443 block_ptr = (short *)((unsigned long)block_ptr + usize); 1444 /* End U Blocks */ 1445 1446 /* V Blocks */ 1447 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1448 *dv++ = (3<<30) | (1<<28) | dw1[0]; 1449 *dv++ = xy; 1450 *dv++ = (4<<16) | 8; 1451 *dv++ = *(uint *)fmv; 1452 *dv++ = *(uint *)bmv; 1453 PACK_CORR_DATA(dv,block_ptr,vsize); 1454 block_ptr = (short *)((unsigned long)block_ptr + vsize); 1455 1456 /* Second V Block */ 1457 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1458 *dv++ = (3<<30) | (1<<28) | dw1[1]; 1459 *dv++ = (xy + 4); 1460 *dv++ = (4<<16) | 8; 1461 *dv++ = *(uint *)&fmv[2]; 1462 *dv++ = *(uint *)&bmv[2]; 1463 PACK_CORR_DATA(dv,block_ptr,vsize); 1464 block_ptr = (short *)((unsigned long)block_ptr + vsize); 1465 /* End V Blocks */ 1466 1467 *datay = dy; 1468 *datau = du; 1469 *datav = dv; 1470} 1471 1472/*************************************************************************** 1473// Function: renderDualPrimeinField 1474// Description: inline function that sets hardware parameters for a Dual 1475// prime encoded macroblock in a field picture. 1476***************************************************************************/ 1477static __inline__ void renderDualPrimeinField(uint **datay,uint **datau, 1478 uint **datav,XvMCMacroBlock *mb, 1479 short *block_ptr,uint ps, 1480 uint flags) { 1481 1482 register uint *dy = *datay; 1483 register uint *du = *datau; 1484 register uint *dv = *datav; 1485 1486 /* Motion Vectors */ 1487 short fmv[2]; 1488 short bmv[2]; 1489 /* gfxblock dword 1 */ 1490 uint dw1; 1491 1492 1493 uint ysize = y_frame_bytes[mb->coded_block_pattern]; 1494 uint usize = u_frame_bytes[mb->coded_block_pattern]; 1495 uint vsize = v_frame_bytes[mb->coded_block_pattern]; 1496 1497 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1498 1499 1500 if(ps & XVMC_TOP_FIELD) { 1501 dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 2<<6 | 2<<3 | 3; 1502 } 1503 else { 1504 dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 3<<6 | 3<<3 | 2; 1505 } 1506 fmv[0] = mb->PMV[0][0][1]; 1507 fmv[1] = mb->PMV[0][0][0]; 1508 bmv[0] = mb->PMV[0][1][1]; 1509 bmv[1] = mb->PMV[0][1][0]; 1510 1511 /* Y Block */ 1512 *dy++ = GFXBLOCK + 4 + (ysize>>2); 1513 *dy++ = (1<<30) | (3<<28) | dw1; 1514 *dy++ = xy; 1515 *dy++ = (16<<16) | 16; 1516 *dy++ = *(uint *)fmv; 1517 *dy++ = *(uint *)bmv; 1518 PACK_CORR_DATA(dy,block_ptr,ysize); 1519 block_ptr = (short *)((unsigned long)block_ptr + ysize); 1520 /* End Y Blocks */ 1521 1522 fmv[0] /= 2; 1523 fmv[1] /= 2; 1524 bmv[0] /= 2; 1525 bmv[1] /= 2; 1526 xy >>= 1; 1527 1528 /* U Block */ 1529 *du++ = GFXBLOCK + 4 + (usize>>2); 1530 *du++ = (2<<30) | (1<<28) | dw1; 1531 *du++ = xy; 1532 *du++ = (8<<16) | 8; 1533 *du++ = *(uint *)fmv; 1534 *du++ = *(uint *)bmv; 1535 PACK_CORR_DATA(du,block_ptr,usize); 1536 block_ptr = (short *)((unsigned long)block_ptr + usize); 1537 1538 /* V Block */ 1539 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1540 *dv++ = (3<<30) | (1<<28) | dw1; 1541 *dv++ = xy; 1542 *dv++ = (8<<16) | 8; 1543 *dv++ = *(uint *)fmv; 1544 *dv++ = *(uint *)bmv; 1545 PACK_CORR_DATA(dv,block_ptr,vsize); 1546 block_ptr = (short *)((unsigned long)block_ptr + vsize); 1547 1548 *datay = dy; 1549 *datau = du; 1550 *datav = dv; 1551} 1552 1553/*************************************************************************** 1554// Function: renderFieldinFrame 1555// Description: inline function that sets hardware parameters for a Field 1556// encoded macroblock in a frame picture. 1557***************************************************************************/ 1558typedef union { 1559 short s[4]; 1560 uint u[2]; 1561} su_t; 1562 1563static __inline__ void renderFieldinFrame(uint **datay,uint **datau, 1564 uint **datav, 1565 XvMCMacroBlock *mb,short *block_ptr, 1566 uint flags) { 1567 1568 register uint *dy = *datay; 1569 register uint *du = *datau; 1570 register uint *dv = *datav; 1571 1572 /* Motion Vectors */ 1573 su_t fmv; 1574 su_t bmv; 1575 /* gfxblock dword 1 */ 1576 uint dw1[2]; 1577 1578 uint y1size = y_first_field_bytes[mb->coded_block_pattern]; 1579 uint y2size = y_second_field_bytes[mb->coded_block_pattern]; 1580 uint usize = u_field_bytes[mb->coded_block_pattern]; 1581 uint vsize = v_field_bytes[mb->coded_block_pattern]; 1582 1583 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); 1584 1585 dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) | 1586 mvfs_table[mb->motion_vertical_field_select & 3] | 1587 (((uint)mb->coded_block_pattern)<<22); 1588 1589 dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) | 1590 mvfs_table[mb->motion_vertical_field_select>>2] | 1591 (((mb->coded_block_pattern & 0x3) | 1592 ((mb->coded_block_pattern & 0xc)<<2))<<22); 1593 1594 fmv.s[0] = mb->PMV[0][0][1]/2; 1595 fmv.s[1] = mb->PMV[0][0][0]; 1596 fmv.s[2] = mb->PMV[1][0][1]/2; 1597 fmv.s[3] = mb->PMV[1][0][0]; 1598 1599 bmv.s[0] = mb->PMV[0][1][1]/2; 1600 bmv.s[1] = mb->PMV[0][1][0]; 1601 bmv.s[2] = mb->PMV[1][1][1]/2; 1602 bmv.s[3] = mb->PMV[1][1][0]; 1603 1604 /* First Y Block */ 1605 *dy++ = GFXBLOCK + 4 + (y1size>>2); 1606 *dy++ = (1<<30) | (2<<28) | dw1[0]; 1607 *dy++ = xy; 1608 *dy++ = (8<<16) | 16; 1609 *dy++ = fmv.u[0]; 1610 *dy++ = bmv.u[0]; 1611 PACK_CORR_DATA(dy,block_ptr,y1size); 1612 block_ptr = (short *)((unsigned long)block_ptr + y1size); 1613 1614 /* Second Y Block */ 1615 *dy++ = GFXBLOCK + 4 + (y2size>>2); 1616 *dy++ = (1<<30) | (2<<28) | dw1[1]; 1617 *dy++ = xy; 1618 *dy++ = (8<<16) | 16; 1619 *dy++ = fmv.u[1]; 1620 *dy++ = bmv.u[1]; 1621 PACK_CORR_DATA(dy,block_ptr,y2size); 1622 block_ptr = (short *)((unsigned long)block_ptr + y2size); 1623 /* End Y Blocks */ 1624 1625 fmv.s[0] /= 2; 1626 fmv.s[1] /= 2; 1627 fmv.s[2] /= 2; 1628 fmv.s[3] /= 2; 1629 1630 bmv.s[0] /= 2; 1631 bmv.s[1] /= 2; 1632 bmv.s[2] /= 2; 1633 bmv.s[3] /= 2; 1634 1635 xy >>= 1; 1636 1637 /* U Blocks */ 1638 *du++ = GFXBLOCK + 4 + (usize>>2); 1639 *du++ = (2<<30) | (1<<28) | dw1[0]; 1640 *du++ = xy; 1641 *du++ = (4<<16) | 8; 1642 *du++ = fmv.u[0]; 1643 *du++ = bmv.u[0]; 1644 if(usize) { 1645 PACK_CORR_DATA_SHORT(du,block_ptr); 1646 } 1647 1648 /* Second U Block */ 1649 *du++ = GFXBLOCK + 4 + (usize>>2); 1650 *du++ = (2<<30) | (1<<28) | dw1[1]; 1651 *du++ = xy; 1652 *du++ = (4<<16) | 8; 1653 *du++ = fmv.u[1]; 1654 *du++ = bmv.u[1]; 1655 if(usize) { 1656 block_ptr = (short *)((unsigned long)block_ptr + 16); 1657 PACK_CORR_DATA_SHORT(du,block_ptr); 1658 block_ptr = (short *)((unsigned long)block_ptr + 112); 1659 } 1660 /* End U Blocks */ 1661 1662 /* V Blocks */ 1663 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1664 *dv++ = (3<<30) | (1<<28) | dw1[0]; 1665 *dv++ = xy; 1666 *dv++ = (4<<16) | 8; 1667 *dv++ = fmv.u[0]; 1668 *dv++ = bmv.u[0]; 1669 if(vsize) { 1670 PACK_CORR_DATA_SHORT(dv,block_ptr); 1671 } 1672 1673 /* Second V Block */ 1674 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1675 *dv++ = (3<<30) | (1<<28) | dw1[1]; 1676 *dv++ = xy; 1677 *dv++ = (4<<16) | 8; 1678 *dv++ = fmv.u[1]; 1679 *dv++ = bmv.u[1]; 1680 if(vsize) { 1681 block_ptr = (short *)((unsigned long)block_ptr + 16); 1682 PACK_CORR_DATA_SHORT(dv,block_ptr); 1683 block_ptr = (short *)((unsigned long)block_ptr + 112); 1684 } 1685 /* End V Blocks */ 1686 1687 *datay = dy; 1688 *datau = du; 1689 *datav = dv; 1690} 1691 1692/*************************************************************************** 1693// Function: renderFieldinFrameDCT0 1694// Description: inline function that sets hardware parameters for a Field 1695// encoded macroblock in a frame picture with DCT0. 1696***************************************************************************/ 1697static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, 1698 uint **datav,XvMCMacroBlock *mb, 1699 short *block_ptr,uint flags) { 1700 1701 register uint *dy = *datay; 1702 register uint *du = *datau; 1703 register uint *dv = *datav; 1704 1705 /* Motion Vectors */ 1706 su_t fmv; 1707 su_t bmv; 1708 /* CBP */ 1709 uint cbp = (uint)mb->coded_block_pattern; 1710 /* gfxblock dword 1 */ 1711 uint dw1[2]; 1712 1713 short * top_left_b = NULL; 1714 short * top_right_b = NULL; 1715 short * bottom_left_b = NULL; 1716 short * bottom_right_b = NULL; 1717 1718 unsigned int ysize = y_dct0_field_bytes[cbp]; 1719 unsigned int usize = u_field_bytes[cbp]; 1720 unsigned int vsize = v_field_bytes[cbp]; 1721 1722 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); 1723 1724 dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) | 1725 mvfs_table[mb->motion_vertical_field_select & 3] | 1726 ((cbp | ((cbp<<2) & 0x30))<<22); 1727 1728 dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) | 1729 mvfs_table[mb->motion_vertical_field_select>>2] | 1730 ((cbp | ((cbp<<2) & 0x30))<<22); 1731 1732 1733 fmv.s[0] = mb->PMV[0][0][1]/2; 1734 fmv.s[1] = mb->PMV[0][0][0]; 1735 fmv.s[2] = mb->PMV[1][0][1]/2; 1736 fmv.s[3] = mb->PMV[1][0][0]; 1737 1738 bmv.s[0] = mb->PMV[0][1][1]/2; 1739 bmv.s[1] = mb->PMV[0][1][0]; 1740 bmv.s[2] = mb->PMV[1][1][1]/2; 1741 bmv.s[3] = mb->PMV[1][1][0]; 1742 1743 /* 1744 The i810 cannot use DCT0 directly with field motion, we have to 1745 interlace the data for it. We use a zero block when the CBP has 1746 one half of the to-be-interlaced data but not the other half. 1747 */ 1748 top_left_b = &empty_block[0]; 1749 if(cbp & 0x20) { 1750 top_left_b = block_ptr; 1751 block_ptr += 64; 1752 } 1753 1754 top_right_b = &empty_block[0]; 1755 if(cbp & 0x10) { 1756 top_right_b = block_ptr; 1757 block_ptr += 64; 1758 } 1759 1760 bottom_left_b = &empty_block[0]; 1761 if(cbp & 0x8) { 1762 bottom_left_b = block_ptr; 1763 block_ptr += 64; 1764 } 1765 1766 bottom_right_b = &empty_block[0]; 1767 if(cbp & 0x4) { 1768 bottom_right_b = block_ptr; 1769 block_ptr += 64; 1770 } 1771 1772 /* First Y Block */ 1773 *dy++ = GFXBLOCK + 4 + (ysize>>2); 1774 *dy++ = (1<<30) | (2<<28) | dw1[0]; 1775 *dy++ = xy; 1776 *dy++ = (8<<16) | 16; 1777 *dy++ = fmv.u[0]; 1778 *dy++ = bmv.u[0]; 1779 if(dw1[0] & (1<<27)) { 1780 PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); 1781 } 1782 if(dw1[0] & (1<<26)) { 1783 PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); 1784 } 1785 1786 /* Second Y Block */ 1787 *dy++ = GFXBLOCK + 4 + (ysize>>2); 1788 *dy++ = (1<<30) | (2<<28) | dw1[1]; 1789 *dy++ = xy; 1790 *dy++ = (8<<16) | 16; 1791 *dy++ = fmv.u[1]; 1792 *dy++ = bmv.u[1]; 1793 if(dw1[1] & (1<<27)) { 1794 top_left_b = (short *)((unsigned long)top_left_b + 16); 1795 bottom_left_b = (short *)((unsigned long)bottom_left_b + 16); 1796 PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); 1797 } 1798 if(dw1[1] & (1<<26)) { 1799 top_right_b = (short *)((unsigned long)top_right_b + 16); 1800 bottom_right_b = (short *)((unsigned long)bottom_right_b + 16); 1801 PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); 1802 } 1803 /* End Y Blocks */ 1804 1805 fmv.s[0] /= 2; 1806 fmv.s[1] /= 2; 1807 fmv.s[2] /= 2; 1808 fmv.s[3] /= 2; 1809 1810 bmv.s[0] /= 2; 1811 bmv.s[1] /= 2; 1812 bmv.s[2] /= 2; 1813 bmv.s[3] /= 2; 1814 1815 xy >>= 1; 1816 1817 /* U Blocks */ 1818 *du++ = GFXBLOCK + 4 + (usize>>2); 1819 *du++ = (2<<30) | (1<<28) | dw1[0]; 1820 *du++ = xy; 1821 *du++ = (4<<16) | 8; 1822 *du++ = fmv.u[0]; 1823 *du++ = bmv.u[0]; 1824 if(usize) { 1825 PACK_CORR_DATA_SHORT(du,block_ptr); 1826 } 1827 1828 /* Second U Block */ 1829 *du++ = GFXBLOCK + 4 + (usize>>2); 1830 *du++ = (2<<30) | (1<<28) | dw1[1]; 1831 *du++ = xy; 1832 *du++ = (4<<16) | 8; 1833 *du++ = fmv.u[1]; 1834 *du++ = bmv.u[1]; 1835 if(usize) { 1836 block_ptr = (short *)((unsigned long)block_ptr + 16); 1837 PACK_CORR_DATA_SHORT(du,block_ptr); 1838 block_ptr = (short *)((unsigned long)block_ptr + 112); 1839 } 1840 /* End U Blocks */ 1841 1842 /* V Blocks */ 1843 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1844 *dv++ = (3<<30) | (1<<28) | dw1[0]; 1845 *dv++ = xy; 1846 *dv++ = (4<<16) | 8; 1847 *dv++ = fmv.u[0]; 1848 *dv++ = bmv.u[0]; 1849 if(vsize) { 1850 PACK_CORR_DATA_SHORT(dv,block_ptr); 1851 } 1852 1853 /* Second V Block */ 1854 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1855 *dv++ = (3<<30) | (1<<28) | dw1[1]; 1856 *dv++ = xy; 1857 *dv++ = (4<<16) | 8; 1858 *dv++ = fmv.u[1]; 1859 *dv++ = bmv.u[1]; 1860 if(vsize) { 1861 block_ptr = (short *)((unsigned long)block_ptr + 16); 1862 PACK_CORR_DATA_SHORT(dv,block_ptr); 1863 block_ptr = (short *)((unsigned long)block_ptr + 112); 1864 } 1865 /* End V Blocks */ 1866 1867 *datay = dy; 1868 *datau = du; 1869 *datav = dv; 1870} 1871 1872/*************************************************************************** 1873// Function: renderFrameinFrame 1874// Description: inline function that sets hardware parameters for a Frame 1875// encoded macroblock in a frame picture. 1876***************************************************************************/ 1877static __inline__ void renderFrameinFrame(uint **datay,uint **datau, 1878 uint **datav, 1879 XvMCMacroBlock *mb,short *block_ptr, 1880 uint flags) { 1881 1882 register uint *dy = *datay; 1883 register uint *du = *datau; 1884 register uint *dv = *datav; 1885 1886 /* Motion Vectors */ 1887 su_t fmv; 1888 su_t bmv; 1889 /* gfxblock dword 1 */ 1890 uint dw1; 1891 1892 unsigned int ysize = y_frame_bytes[mb->coded_block_pattern]; 1893 unsigned int usize = u_frame_bytes[mb->coded_block_pattern]; 1894 unsigned int vsize = v_frame_bytes[mb->coded_block_pattern]; 1895 1896 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1897 1898 dw1 = type_table[mb->macroblock_type & 0xf] | 1899 (((uint)mb->coded_block_pattern)<<22); 1900 1901 1902 fmv.s[0] = mb->PMV[0][0][1]; 1903 fmv.s[1] = mb->PMV[0][0][0]; 1904 1905 bmv.s[0] = mb->PMV[0][1][1]; 1906 bmv.s[1] = mb->PMV[0][1][0]; 1907 1908 /* Y Block */ 1909 *dy++ = GFXBLOCK + 4 + (ysize>>2); 1910 *dy++ = (1<<30) | (3<<28) | dw1; 1911 *dy++ = xy; 1912 *dy++ = (16<<16) | 16; 1913 *dy++ = fmv.u[0]; 1914 *dy++ = bmv.u[0]; 1915 PACK_CORR_DATA(dy,block_ptr,ysize); 1916 block_ptr = (short *)((unsigned long)block_ptr + ysize); 1917 /* End Y Blocks */ 1918 1919 fmv.s[0] /= 2; 1920 fmv.s[1] /= 2; 1921 1922 bmv.s[0] /= 2; 1923 bmv.s[1] /= 2; 1924 1925 xy >>= 1; 1926 1927 /* U Block */ 1928 *du++ = GFXBLOCK + 4 + (usize>>2); 1929 *du++ = (2<<30) | (1<<28) | dw1; 1930 *du++ = xy; 1931 *du++ = (8<<16) | 8; 1932 *du++ = fmv.u[0]; 1933 *du++ = bmv.u[0]; 1934 PACK_CORR_DATA(du,block_ptr,usize); 1935 block_ptr = (short *)((unsigned long)block_ptr + usize); 1936 /* End U Block */ 1937 1938 /* V Block */ 1939 *dv++ = GFXBLOCK + 4 + (vsize>>2); 1940 *dv++ = (3<<30) | (1<<28) | dw1; 1941 *dv++ = xy; 1942 *dv++ = (8<<16) | 8; 1943 *dv++ = fmv.u[0]; 1944 *dv++ = bmv.u[0]; 1945 PACK_CORR_DATA(dv,block_ptr,vsize); 1946 block_ptr = (short *)((unsigned long)block_ptr + vsize); 1947 /* End V Block */ 1948 1949 *datay = dy; 1950 *datau = du; 1951 *datav = dv; 1952} 1953 1954/*************************************************************************** 1955// Function: renderFrameinFrameDCT1 1956// Description: inline function that sets hardware parameters for a Frame 1957// encoded macroblock in a frame picture with DCT type 1. 1958***************************************************************************/ 1959static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, 1960 uint **datav,XvMCMacroBlock *mb, 1961 short *block_ptr,uint flags) { 1962 1963 register uint *dy = *datay; 1964 register uint *du = *datau; 1965 register uint *dv = *datav; 1966 1967 /* Motion Vectors */ 1968 su_t fmv; 1969 su_t bmv; 1970 1971 short * top_left_b = NULL; 1972 short * top_right_b = NULL; 1973 short * bottom_left_b = NULL; 1974 short * bottom_right_b = NULL; 1975 1976 uint temp_bp = 0; 1977 1978 uint ysize = y_dct1_frame_bytes[mb->coded_block_pattern]; 1979 uint usize = u_frame_bytes[mb->coded_block_pattern]; 1980 uint vsize = v_frame_bytes[mb->coded_block_pattern]; 1981 1982 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); 1983 1984 uint dw1 = type_table[mb->macroblock_type & 0xf] | 1985 (((uint)mb->coded_block_pattern)<<22); 1986 1987 fmv.s[0] = mb->PMV[0][0][1]; 1988 fmv.s[1] = mb->PMV[0][0][0]; 1989 1990 bmv.s[0] = mb->PMV[0][1][1]; 1991 bmv.s[1] = mb->PMV[0][1][0]; 1992 1993 /* 1994 It is easiest to find out what blocks are in need of reading first 1995 rather than as we go. 1996 */ 1997 top_left_b = &empty_block[0]; 1998 if(dw1 & (1<<27)) { 1999 temp_bp |= (1<<25); 2000 top_left_b = block_ptr; 2001 block_ptr += 64; 2002 } 2003 2004 top_right_b = &empty_block[0]; 2005 if(dw1 & (1<<26)) { 2006 temp_bp |= (1<<24); 2007 top_right_b = block_ptr; 2008 block_ptr += 64; 2009 } 2010 2011 bottom_left_b = &empty_block[0]; 2012 if(dw1 & (1<<25)) { 2013 temp_bp |= (1<<27); 2014 bottom_left_b = block_ptr; 2015 block_ptr += 64; 2016 } 2017 2018 bottom_right_b = &empty_block[0]; 2019 if(dw1 & (1<<24)) { 2020 temp_bp |= (1<<26); 2021 bottom_right_b = block_ptr; 2022 block_ptr += 64; 2023 } 2024 dw1 |= temp_bp; 2025 2026 /* Y Block */ 2027 *dy++ = GFXBLOCK + 4 + (ysize>>2); 2028 *dy++ = (1<<30) | (3<<28) | dw1; 2029 *dy++ = xy; 2030 *dy++ = (16<<16) | 16; 2031 *dy++ = fmv.u[0]; 2032 *dy++ = bmv.u[0]; 2033 if(dw1 & (1<<27)) { 2034 PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b); 2035 top_left_b = (short *)((unsigned long)top_left_b + 64); 2036 bottom_left_b = (short *)((unsigned long)bottom_left_b + 64); 2037 } 2038 if(dw1 & (1<<26)) { 2039 PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b); 2040 top_right_b = (short *)((unsigned long)top_right_b + 64); 2041 bottom_right_b = (short *)((unsigned long)bottom_right_b + 64); 2042 } 2043 if(dw1 & (1<<27)) { 2044 PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b); 2045 } 2046 if(dw1 & (1<<26)) { 2047 PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b); 2048 } 2049 /* End Y Block */ 2050 2051 fmv.s[0] /= 2; 2052 fmv.s[1] /= 2; 2053 2054 bmv.s[0] /= 2; 2055 bmv.s[1] /= 2; 2056 2057 xy >>= 1; 2058 2059 /* U Block */ 2060 *du++ = GFXBLOCK + 4 + (usize>>2); 2061 *du++ = (2<<30) | (1<<28) | dw1; 2062 *du++ = xy; 2063 *du++ = (8<<16) | 8; 2064 *du++ = fmv.u[0]; 2065 *du++ = bmv.u[0]; 2066 PACK_CORR_DATA(du,block_ptr,usize); 2067 block_ptr = (short *)((unsigned long)block_ptr + usize); 2068 2069 /* V Block */ 2070 *dv++ = GFXBLOCK + 4 + (vsize>>2); 2071 *dv++ = (3<<30) | (1<<28) | dw1; 2072 *dv++ = xy; 2073 *dv++ = (8<<16) | 8; 2074 *dv++ = fmv.u[0]; 2075 *dv++ = bmv.u[0]; 2076 PACK_CORR_DATA(dv,block_ptr,vsize); 2077 block_ptr = (short *)((unsigned long)block_ptr + vsize); 2078 2079 *datay = dy; 2080 *datau = du; 2081 *datav = dv; 2082} 2083 2084/*************************************************************************** 2085// Function: renderDualPrimeinFrame 2086// Description: inline function that sets hardware parameters for a Dual 2087// Prime encoded macroblock in a frame picture with dct 1. 2088***************************************************************************/ 2089static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, 2090 uint **datav,XvMCMacroBlock *mb, 2091 short *block_ptr,uint flags) { 2092 2093 register uint *dy = *datay; 2094 register uint *du = *datau; 2095 register uint *dv = *datav; 2096 2097 /* Motion Vectors */ 2098 su_t fmv; 2099 su_t bmv; 2100 /* gfxblock dword 1 */ 2101 uint dw1[2]; 2102 2103 uint y1size = y_first_field_bytes[mb->coded_block_pattern]; 2104 uint y2size = y_second_field_bytes[mb->coded_block_pattern]; 2105 uint usize = u_field_bytes[mb->coded_block_pattern]; 2106 uint vsize = v_field_bytes[mb->coded_block_pattern]; 2107 2108 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); 2109 2110 /* 2111 Past Surface (map 0) is used for same parity prediction, 2112 Future surface (map 1) is used for opposite. 2113 */ 2114 dw1[0] = (((uint)mb->coded_block_pattern)<<22) | 2115 3<<12 | 2<<6 | 2<<3 | 3; 2116 dw1[1] = (((mb->coded_block_pattern & 0x3) | 2117 ((mb->coded_block_pattern & 0xc)<<2))<<22) | 2118 3<<12 | 3<<6 | 3<<3 | 2; 2119 2120 fmv.s[0] = mb->PMV[0][0][1]; 2121 fmv.s[1] = mb->PMV[0][0][0]; 2122 bmv.s[0] = mb->PMV[1][0][1]; 2123 bmv.s[1] = mb->PMV[1][0][0]; 2124 2125 fmv.s[2] = mb->PMV[0][0][1]; 2126 fmv.s[3] = mb->PMV[0][0][0]; 2127 bmv.s[2] = mb->PMV[1][1][1]; 2128 bmv.s[3] = mb->PMV[1][1][0]; 2129 2130 /* First Y Block */ 2131 *dy++ = GFXBLOCK + 4 + (y1size>>2); 2132 *dy++ = (1<<30) | (2<<28) | dw1[0]; 2133 *dy++ = xy; 2134 *dy++ = (8<<16) | 16; 2135 *dy++ = fmv.u[0]; 2136 *dy++ = bmv.u[0];; 2137 PACK_CORR_DATA(dy,block_ptr,y1size); 2138 block_ptr = (short *)((unsigned long)block_ptr + y1size); 2139 2140 /* Second Y Block */ 2141 *dy++ = GFXBLOCK + 4 + (y2size>>2); 2142 *dy++ = (1<<30) | (2<<28) | dw1[1]; 2143 *dy++ = xy; 2144 *dy++ = (8<<16) | 16; 2145 *dy++ = fmv.u[1]; 2146 *dy++ = bmv.u[1]; 2147 PACK_CORR_DATA(dy,block_ptr,y2size); 2148 block_ptr = (short *)((unsigned long)block_ptr + y2size); 2149 2150 fmv.s[0] /= 2; 2151 fmv.s[1] /= 2; 2152 bmv.s[0] /= 2; 2153 bmv.s[1] /= 2; 2154 2155 fmv.s[2] /= 2; 2156 fmv.s[3] /= 2; 2157 bmv.s[2] /= 2; 2158 bmv.s[3] /= 2; 2159 2160 xy >>= 1; 2161 2162 /* U Blocks */ 2163 *du++ = GFXBLOCK + 4 + (usize>>2); 2164 *du++ = (2<<30) | (1<<28) | dw1[0]; 2165 *du++ = xy; 2166 *du++ = (4<<16) | 8; 2167 *du++ = fmv.u[0]; 2168 *du++ = bmv.u[0]; 2169 if(dw1[0] & (1<<23)) { 2170 PACK_CORR_DATA_SHORT(du,block_ptr); 2171 } 2172 2173 /* Second U Block */ 2174 *du++ = GFXBLOCK + 4 + (usize>>2); 2175 *du++ = (2<<30) | (1<<28) | dw1[1]; 2176 *du++ = xy; 2177 *du++ = (4<<16) | 8; 2178 *du++ = fmv.u[1]; 2179 *du++ = bmv.u[1]; 2180 if(dw1[1] & (1<<23)) { 2181 block_ptr = (short *)((unsigned long)block_ptr + 16); 2182 PACK_CORR_DATA_SHORT(du,block_ptr); 2183 block_ptr = (short *)((unsigned long)block_ptr + 112); 2184 } 2185 /* End U Blocks */ 2186 2187 /* V Blocks */ 2188 *dv++ = GFXBLOCK + 4 + (vsize>>2); 2189 *dv++ = (3<<30) | (1<<28) | dw1[0]; 2190 *dv++ = xy; 2191 *dv++ = (4<<16) | 8; 2192 *dv++ = fmv.u[0]; 2193 *dv++ = bmv.u[0]; 2194 if(dw1[0] & (1<<22)) { 2195 PACK_CORR_DATA_SHORT(dv,block_ptr); 2196 } 2197 2198 /* Second V Block */ 2199 *dv++ = GFXBLOCK + 4 + (vsize>>2); 2200 *dv++ = (3<<30) | (1<<28) | dw1[1]; 2201 *dv++ = xy; 2202 *dv++ = (4<<16) | 8; 2203 *dv++ = fmv.u[1]; 2204 *dv++ = bmv.u[1]; 2205 if(dw1[1] & (1<<22)) { 2206 block_ptr = (short *)((unsigned long)block_ptr + 16); 2207 PACK_CORR_DATA_SHORT(dv,block_ptr); 2208 block_ptr = (short *)((unsigned long)block_ptr + 112); 2209 } 2210 /* End V Blocks */ 2211 2212 *datay = dy; 2213 *datau = du; 2214 *datav = dv; 2215} 2216 2217/*************************************************************************** 2218// Function: renderDualPrimeinFrameDCT0 2219// Description: inline function that sets hardware parameters for a Dual 2220// Prime encoded macroblock in a frame picture with dct 0. 2221***************************************************************************/ 2222static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, 2223 uint **datav, 2224 XvMCMacroBlock *mb, 2225 short *block_ptr, 2226 uint flags) { 2227 2228 register uint *dy = *datay; 2229 register uint *du = *datau; 2230 register uint *dv = *datav; 2231 2232 /* Motion Vectors */ 2233 su_t fmv; 2234 su_t bmv; 2235 /* gfxblock dword 1 */ 2236 uint dw1[2]; 2237 2238 short * top_left_b = NULL; 2239 short * top_right_b = NULL; 2240 short * bottom_left_b = NULL; 2241 short * bottom_right_b = NULL; 2242 2243 uint cbp = (uint)mb->coded_block_pattern; 2244 2245 uint ysize = y_dct0_field_bytes[cbp]; 2246 uint usize = u_field_bytes[cbp]; 2247 uint vsize = v_field_bytes[cbp]; 2248 2249 uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); 2250 2251 /* 2252 Past Surface (map 0) is used for same parity prediction, 2253 Future surface (map 1) is used for opposite. 2254 */ 2255 dw1[0] = ((cbp | ((cbp<<2) & 0x30))<<22) | 2256 3<<12 | 2<<6 | 2<<3 | 3; 2257 dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) | 2258 3<<12 | 3<<6 | 3<<3 | 2; 2259 2260 fmv.s[0] = mb->PMV[0][0][1]; 2261 fmv.s[1] = mb->PMV[0][0][0]; 2262 bmv.s[0] = mb->PMV[1][0][1]; 2263 bmv.s[1] = mb->PMV[1][0][0]; 2264 2265 fmv.s[2] = mb->PMV[0][0][1]; 2266 fmv.s[3] = mb->PMV[0][0][0]; 2267 bmv.s[2] = mb->PMV[1][1][1]; 2268 bmv.s[3] = mb->PMV[1][1][0]; 2269 2270 /* 2271 The i810 cannot use DCT0 directly with field motion, we have to 2272 interlace the data for it. We use a zero block when the CBP has 2273 one half of the to-be-interlaced data but not the other half. 2274 */ 2275 top_left_b = &empty_block[0]; 2276 if(cbp & 0x20) { 2277 top_left_b = block_ptr; 2278 block_ptr += 64; 2279 } 2280 2281 top_right_b = &empty_block[0]; 2282 if(cbp & 0x10) { 2283 top_right_b = block_ptr; 2284 block_ptr += 64; 2285 } 2286 2287 bottom_left_b = &empty_block[0]; 2288 if(cbp & 0x8) { 2289 bottom_left_b = block_ptr; 2290 block_ptr += 64; 2291 } 2292 2293 bottom_right_b = &empty_block[0]; 2294 if(cbp & 0x4) { 2295 bottom_right_b = block_ptr; 2296 block_ptr += 64; 2297 } 2298 2299 /* First Y Block */ 2300 *dy++ = GFXBLOCK + 4 + (ysize>>2); 2301 *dy++ = (1<<30) | (2<<28) | dw1[0]; 2302 *dy++ = xy; 2303 *dy++ = (8<<16) | 16; 2304 *dy++ = fmv.u[0]; 2305 *dy++ = bmv.u[0]; 2306 if(cbp & 0x20) { 2307 PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); 2308 } 2309 if(cbp & 0x10) { 2310 PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); 2311 } 2312 2313 /* Second Y Block */ 2314 *dy++ = GFXBLOCK + 4 + (ysize>>2); 2315 *dy++ = (1<<30) | (2<<28) | dw1[1]; 2316 *dy++ = xy; 2317 *dy++ = (8<<16) | 16; 2318 *dy++ = fmv.u[1]; 2319 *dy++ = bmv.u[1]; 2320 if(cbp & 0x20) { 2321 top_left_b = (short *)((unsigned long)top_left_b + 16); 2322 bottom_left_b = (short *)((unsigned long)bottom_left_b + 16); 2323 PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); 2324 } 2325 if(cbp & 0x10) { 2326 top_right_b = (short *)((unsigned long)top_right_b + 16); 2327 bottom_right_b = (short *)((unsigned long)bottom_right_b + 16); 2328 PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); 2329 } 2330 /* End Y Blocks */ 2331 2332 2333 fmv.s[0] /= 2; 2334 fmv.s[1] /= 2; 2335 bmv.s[0] /= 2; 2336 bmv.s[1] /= 2; 2337 2338 fmv.s[2] /= 2; 2339 fmv.s[3] /= 2; 2340 bmv.s[2] /= 2; 2341 bmv.s[3] /= 2; 2342 2343 xy >>= 1; 2344 2345 /* U Blocks */ 2346 *du++ = GFXBLOCK + 4 + (usize>>2); 2347 *du++ = (2<<30) | (1<<28) | dw1[0]; 2348 *du++ = xy; 2349 *du++ = (4<<16) | 8; 2350 *du++ = fmv.u[0]; 2351 *du++ = bmv.u[0]; 2352 if(cbp & (1<<23)) { 2353 PACK_CORR_DATA_SHORT(du,block_ptr); 2354 } 2355 2356 /* Second U Block */ 2357 *du++ = GFXBLOCK + 4 + (usize>>2); 2358 *du++ = (2<<30) | (1<<28) | dw1[1]; 2359 *du++ = xy; 2360 *du++ = (4<<16) | 8; 2361 *du++ = fmv.u[1]; 2362 *du++ = bmv.u[1]; 2363 if(cbp & (1<<23)) { 2364 block_ptr = (short *)((unsigned long)block_ptr + 16); 2365 PACK_CORR_DATA_SHORT(du,block_ptr); 2366 block_ptr = (short *)((unsigned long)block_ptr + 112); 2367 } 2368 /* End U Blocks */ 2369 2370 /* V Blocks */ 2371 *dv++ = GFXBLOCK + 4 + (vsize>>2); 2372 *dv++ = (3<<30) | (1<<28) | dw1[0]; 2373 *dv++ = xy; 2374 *dv++ = (4<<16) | 8; 2375 *dv++ = fmv.u[0]; 2376 *dv++ = bmv.u[0]; 2377 if(cbp & (1<<22)) { 2378 PACK_CORR_DATA_SHORT(dv,block_ptr); 2379 } 2380 2381 /* Second V Block */ 2382 *dv++ = GFXBLOCK + 4 + (vsize>>2); 2383 *dv++ = (3<<30) | (1<<28) | dw1[1]; 2384 *dv++ = xy; 2385 *dv++ = (4<<16) | 8; 2386 *dv++ = fmv.u[1]; 2387 *dv++ = bmv.u[1]; 2388 if(cbp & (1<<22)) { 2389 block_ptr = (short *)((unsigned long)block_ptr + 16); 2390 PACK_CORR_DATA_SHORT(dv,block_ptr); 2391 block_ptr = (short *)((unsigned long)block_ptr + 112); 2392 } 2393 /* End V Blocks */ 2394 2395 *datay = dy; 2396 *datau = du; 2397 *datav = dv; 2398} 2399 2400 2401/*************************************************************************** 2402// Function: XvMCRenderSurface 2403// Description: This function does the actual HWMC. Given a list of 2404// macroblock structures it dispatched the hardware commands to execute 2405// them. DMA buffer containing Y data are dispatched as they fill up 2406// U and V DMA buffers are queued until all Y's are done. This minimizes 2407// the context flipping and flushing required when switching between Y 2408// U and V surfaces. 2409***************************************************************************/ 2410#define UV_QUEUE 14 2411_X_EXPORT Status XvMCRenderSurface(Display *display, XvMCContext *context, 2412 unsigned int picture_structure, 2413 XvMCSurface *target_surface, 2414 XvMCSurface *past_surface, 2415 XvMCSurface *future_surface, 2416 unsigned int flags, 2417 unsigned int num_macroblocks, 2418 unsigned int first_macroblock, 2419 XvMCMacroBlockArray *macroblock_array, 2420 XvMCBlockArray *blocks) { 2421 /* Dma Data Structures */ 2422 drmBufPtr pDMAy = NULL,pDMAu[UV_QUEUE],pDMAv[UV_QUEUE]; 2423 int u_index = 0,v_index = 0; 2424 int dirty_context = 1; 2425 2426 /* Block Pointer */ 2427 short *block_ptr; 2428 /* Current Macroblock Pointer */ 2429 XvMCMacroBlock *mb; 2430 2431 drm_i810_mc_t mc; 2432 int i,j; 2433 i810XvMCSurface *privTarget; 2434 i810XvMCSurface *privFuture = NULL; 2435 i810XvMCSurface *privPast = NULL; 2436 i810XvMCContext *pI810XvMC; 2437 2438 /* DMA Pointers set to NULL */ 2439 uint *datay = NULL; 2440 uint *datau = NULL; 2441 uint *datav = NULL; 2442 2443 2444 /* Check Parameters for validity */ 2445 if((target_surface == NULL) || (context == NULL) || (display == NULL)) { 2446 printf("Error, Invalid Target,Context, or DIsplay!\n"); 2447 return BadValue; 2448 } 2449 2450 if(num_macroblocks == 0) {return Success;} 2451 if((macroblock_array == NULL) || (blocks == NULL)) {return BadValue;} 2452 if(context->privData == NULL) {return BadValue;} 2453 pI810XvMC = (i810XvMCContext *)context->privData; 2454 2455 2456 if(target_surface->privData == NULL) { 2457 printf("Error, Invalid Target Surface!\n"); 2458 return BadValue; 2459 } 2460 privTarget = (i810XvMCSurface *)target_surface->privData; 2461 2462 if(macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) { 2463 printf("Error, Too many macroblocks requested for MB array size.\n"); 2464 return BadValue; 2465 } 2466 2467 /* Test For YV12 Surface */ 2468 if(context->surface_type_id != FOURCC_YV12) { 2469 printf("Error, HWMC only possible on YV12 Surfaces\n"); 2470 return BadValue; 2471 } 2472 2473 /* P Frame Test */ 2474 if(past_surface == NULL) { 2475 /* Just to avoid some ifs later. */ 2476 privPast = privTarget; 2477 } 2478 else { 2479 if(past_surface->privData == NULL) { 2480 printf("Error, Invalid Past Surface!\n"); 2481 return BadValue; 2482 } 2483 privPast = (i810XvMCSurface *)past_surface->privData; 2484 } 2485 2486 2487 /* B Frame Test */ 2488 if(future_surface == NULL) { 2489 privFuture = privTarget; 2490 if(pI810XvMC->dual_prime) { 2491 privFuture = privPast; 2492 /* I810 Specific flag for marking when dual prime is in use. */ 2493 flags |= 0x40000000; 2494 } 2495 2496 /* 2497 References are different for the Second Field Picture. The 2498 i810 needs to know if it is the second field picture in a 2499 P picture. We use a Private flag to mark this. 2500 */ 2501 if(flags & XVMC_SECOND_FIELD) { 2502 /* I810 Specific flag for marking second fields. */ 2503 flags |= 0x80000000; 2504 } 2505 } 2506 else { 2507 if((future_surface->privData == NULL) || (past_surface == NULL)) { 2508 printf("Error, Invalid Future Surface or No Past Surface!\n"); 2509 return BadValue; 2510 } 2511 privFuture = (i810XvMCSurface *)future_surface->privData; 2512 2513 /* 2514 Undo Second Field flag since the second field in B frames is just like 2515 the first. 2516 */ 2517 flags &= ~0x80000000; 2518 } 2519 2520 /* Lock For DMA */ 2521 I810_LOCK(pI810XvMC,0); 2522 2523 for(i=first_macroblock; i<(num_macroblocks + first_macroblock); i++) { 2524 /* Set up values needed for each macroblock */ 2525 mb = ¯oblock_array->macro_blocks[i]; 2526 block_ptr = &(blocks->blocks[mb->index<<6]); 2527 2528 /* Lockup can happen if the coordinates are too far out of range */ 2529 if(mb->x > target_surface->width>>4) { 2530 mb->x = 0; 2531 } 2532 if(mb->y > target_surface->height>>4) { 2533 mb->y = 0; 2534 } 2535 2536 /* If buffers are almost full dispatch them */ 2537 if(datay) { 2538 pDMAy->used = (unsigned long)datay - (unsigned long)pDMAy->address; 2539 if(pDMAy->used > 3520) { 2540 if(dirty_context) { 2541 dispatchYContext(privTarget,privPast,privFuture,pI810XvMC); 2542 } 2543 dirty_context = 0; 2544 mc.idx = pDMAy->idx; 2545 mc.used = pDMAy->used; 2546 datay = NULL; 2547 mc.last_render = ++pI810XvMC->last_render; 2548 privTarget->last_render = pI810XvMC->last_render; 2549 I810_MC(pI810XvMC,mc); 2550 } /* datay near full */ 2551 } /* if(datay) */ 2552 if(datau) { 2553 pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address; 2554 if(pDMAu[u_index]->used > 3904) { 2555 u_index++; 2556 datau = NULL; 2557 if(u_index == UV_QUEUE) { 2558 for(j=0; j<UV_QUEUE; j++) { 2559 mc.idx = pDMAu[j]->idx; 2560 mc.used = pDMAu[j]->used; 2561 mc.last_render = ++pI810XvMC->last_render; 2562 privTarget->last_render = pI810XvMC->last_render; 2563 I810_MC(pI810XvMC,mc); 2564 } 2565 u_index = 0; 2566 dirty_context = 1; 2567 } /* if(u_index == UV_QUEUE) */ 2568 } /* datau near full */ 2569 } /* if(datau) */ 2570 if(datav) { 2571 pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address; 2572 if(pDMAv[v_index]->used > 3904) { 2573 v_index++; 2574 datav = NULL; 2575 if(v_index == UV_QUEUE) { 2576 for(j=0; j<UV_QUEUE; j++) { 2577 mc.idx = pDMAv[j]->idx; 2578 mc.used = pDMAv[j]->used; 2579 mc.last_render = ++pI810XvMC->last_render; 2580 privTarget->last_render = pI810XvMC->last_render; 2581 I810_MC(pI810XvMC,mc); 2582 } 2583 v_index = 0; 2584 dirty_context = 1; 2585 } /* if(v_index == UV_QUEUE) */ 2586 } /* datav near full */ 2587 } /* if(datav) */ 2588 2589 /* Allocate buffers if this is the first loop,or if we just dispatched */ 2590 if(datay == NULL) { 2591 pDMAy = i810_get_free_buffer(pI810XvMC); 2592 datay = pDMAy->address; 2593 }/* if(datay == NULL) */ 2594 if(datau == NULL) { 2595 pDMAu[u_index] = i810_get_free_buffer(pI810XvMC); 2596 datau = pDMAu[u_index]->address; 2597 if(u_index == 0) { 2598 *datau++ = CMD_FLUSH; 2599 *datau++ = BOOLEAN_ENA_2; 2600 *datau++ = CMD_FLUSH; 2601 *datau++ = DEST_BUFFER_INFO; 2602 *datau++ = privTarget->dbi1u; 2603 *datau++ = DEST_BUFFER_VAR; 2604 *datau++ = privTarget->dbv1; 2605 /* Past Surface */ 2606 *datau++ = CMD_MAP_INFO; 2607 *datau++ = privPast->mi1u; 2608 *datau++ = privPast->mi2u; 2609 *datau++ = privPast->mi3u; 2610 /* Future Surface */ 2611 *datau++ = CMD_MAP_INFO; 2612 *datau++ = privFuture->mi1u | 0x1<<28; 2613 *datau++ = privFuture->mi2u; 2614 *datau++ = privFuture->mi3u; 2615 } 2616 } /* if(datau == NULL) */ 2617 if(datav == NULL) { 2618 pDMAv[v_index] = i810_get_free_buffer(pI810XvMC); 2619 datav = pDMAv[v_index]->address; 2620 if(v_index == 0) { 2621 *datav++ = CMD_FLUSH; 2622 *datav++ = BOOLEAN_ENA_2; 2623 *datav++ = CMD_FLUSH; 2624 *datav++ = DEST_BUFFER_INFO; 2625 *datav++ = privTarget->dbi1v; 2626 *datav++ = DEST_BUFFER_VAR; 2627 *datav++ = privTarget->dbv1; 2628 /* Past Surface */ 2629 *datav++ = CMD_MAP_INFO; 2630 *datav++ = privPast->mi1v; 2631 *datav++ = privPast->mi2v; 2632 *datav++ = privPast->mi3v; 2633 /* Future Surface */ 2634 *datav++ = CMD_MAP_INFO; 2635 *datav++ = privFuture->mi1v | 0x1<<28; 2636 *datav++ = privFuture->mi2v; 2637 *datav++ = privFuture->mi3v; 2638 } 2639 }/* if(datav == NULL) */ 2640 2641 /* Catch no pattern case */ 2642 if(!(mb->macroblock_type & 0x8)) { 2643 mb->coded_block_pattern = 0; 2644 } 2645 2646 2647 if(mb->motion_type == XVMC_PREDICTION_DUAL_PRIME) { 2648 /* 2649 By default the maps will not be set up for dual 2650 prime. We have to change them. 2651 */ 2652 if(!pI810XvMC->dual_prime) { 2653 pI810XvMC->dual_prime = 1; 2654 privFuture = privPast; 2655 /* Y */ 2656 *datay++ = CMD_MAP_INFO; 2657 *datay++ = privFuture->mi1y | 0x1<<28; 2658 *datay++ = privFuture->mi2y; 2659 *datay++ = privFuture->mi3y; 2660 /* U */ 2661 *datau++ = CMD_MAP_INFO; 2662 *datau++ = privFuture->mi1u | 0x1<<28; 2663 *datau++ = privFuture->mi2u; 2664 *datau++ = privFuture->mi3u; 2665 /* V */ 2666 *datav++ = CMD_MAP_INFO; 2667 *datav++ = privFuture->mi1v | 0x1<<28; 2668 *datav++ = privFuture->mi2v; 2669 *datav++ = privFuture->mi3v; 2670 } 2671 } 2672 if((pI810XvMC->dual_prime) && 2673 (mb->motion_type != XVMC_PREDICTION_DUAL_PRIME)) { 2674 pI810XvMC->dual_prime = 0; 2675 privFuture = privTarget; 2676 /* Y */ 2677 *datay++ = CMD_MAP_INFO; 2678 *datay++ = privFuture->mi1y | 0x1<<28; 2679 *datay++ = privFuture->mi2y; 2680 *datay++ = privFuture->mi3y; 2681 /* U */ 2682 *datau++ = CMD_MAP_INFO; 2683 *datau++ = privFuture->mi1u | 0x1<<28; 2684 *datau++ = privFuture->mi2u; 2685 *datau++ = privFuture->mi3u; 2686 /* V */ 2687 *datav++ = CMD_MAP_INFO; 2688 *datav++ = privFuture->mi1v | 0x1<<28; 2689 *datav++ = privFuture->mi2v; 2690 *datav++ = privFuture->mi3v; 2691 } 2692 2693 2694 /* Frame Picture */ 2695 if((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { 2696 /* Intra Blocks */ 2697 if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 2698 if(mb->dct_type) { 2699 renderIntrainFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags); 2700 continue; 2701 } 2702 renderIntrainFrame(&datay,&datau,&datav,mb,block_ptr); 2703 continue; 2704 } 2705 switch((mb->motion_type & 0x3) | (mb->dct_type<<2)) { 2706 case 0x2: /* Frame DCT0 */ 2707 renderFrameinFrame(&datay,&datau,&datav,mb,block_ptr,flags); 2708 continue; 2709 case 0x5: /* Field DCT1 */ 2710 renderFieldinFrame(&datay,&datau,&datav,mb,block_ptr,flags); 2711 continue; 2712 case 0x6: /* Frame DCT1 */ 2713 renderFrameinFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags); 2714 continue; 2715 case 0x1: /* Field DCT0 */ 2716 renderFieldinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags); 2717 continue; 2718 case 0x3: /* Dual Prime DCT0 */ 2719 renderDualPrimeinFrame(&datay,&datau,&datav,mb,block_ptr,flags); 2720 continue; 2721 case 0x7: /* Dual Prime DCT1 */ 2722 renderDualPrimeinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags); 2723 continue; 2724 default: /* No Motion Type */ 2725 renderError(); 2726 continue; 2727 } /* Switch */ 2728 } /* Frame Picture */ 2729 2730 /* Field Pictures */ 2731 if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 2732 renderIntrainField(&datay,&datau,&datav,mb,block_ptr,picture_structure); 2733 continue; 2734 } 2735 switch(mb->motion_type & 0x3) { 2736 case 0x1: /* Field Motion */ 2737 renderFieldinField(&datay,&datau,&datav,mb,block_ptr,picture_structure, 2738 flags); 2739 continue; 2740 case 0x2: /* 16x8 Motion */ 2741 render16x8inField(&datay,&datau,&datav,mb,block_ptr,picture_structure, 2742 flags); 2743 continue; 2744 case 0x3: /* Dual Prime */ 2745 renderDualPrimeinField(&datay,&datau,&datav,mb,block_ptr, 2746 picture_structure,flags); 2747 continue; 2748 default: /* No Motion Type */ 2749 renderError(); 2750 continue; 2751 } 2752 continue; 2753 2754 } /* for each Macroblock */ 2755 2756 /* Dispatch remaining DMA buffers */ 2757 if(dirty_context) { 2758 dispatchYContext(privTarget,privPast,privFuture,pI810XvMC); 2759 } 2760 mc.idx = pDMAy->idx; 2761 mc.used = (unsigned long)datay - (unsigned long)pDMAy->address; 2762 mc.last_render = ++pI810XvMC->last_render; 2763 privTarget->last_render = pI810XvMC->last_render; 2764 I810_MC(pI810XvMC,mc); 2765 2766 pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address; 2767 for(j=0; j<=u_index; j++) { 2768 mc.idx = pDMAu[j]->idx; 2769 mc.used = pDMAu[j]->used; 2770 mc.last_render = ++pI810XvMC->last_render; 2771 privTarget->last_render = pI810XvMC->last_render; 2772 I810_MC(pI810XvMC,mc); 2773 } 2774 pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address; 2775 for(j=0; j<=v_index; j++) { 2776 mc.idx = pDMAv[j]->idx; 2777 mc.used = pDMAv[j]->used; 2778 mc.last_render = ++pI810XvMC->last_render; 2779 privTarget->last_render = pI810XvMC->last_render; 2780 I810_MC(pI810XvMC,mc); 2781 } 2782 2783 I810_UNLOCK(pI810XvMC); 2784 2785 return Success; 2786} 2787 2788/*************************************************************************** 2789// Function: XvMCPutSurface 2790// Description: 2791// Arguments: 2792// display: Connection to X server 2793// surface: Surface to be displayed 2794// draw: X Drawable on which to display the surface 2795// srcx: X coordinate of the top left corner of the region to be 2796// displayed within the surface. 2797// srcy: Y coordinate of the top left corner of the region to be 2798// displayed within the surface. 2799// srcw: Width of the region to be displayed. 2800// srch: Height of the region to be displayed. 2801// destx: X cordinate of the top left corner of the destination region 2802// in the drawable coordinates. 2803// desty: Y cordinate of the top left corner of the destination region 2804// in the drawable coordinates. 2805// destw: Width of the destination region. 2806// desth: Height of the destination region. 2807// flags: One or more of the following. 2808// XVMC_TOP_FIELD - Display only the Top field of the surface. 2809// XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface. 2810// XVMC_FRAME_PICTURE - Display both fields or frame. 2811// 2812// Info: Portions of this function derived from i810_video.c (XFree86) 2813// 2814// This function is organized so that we wait as long as possible before 2815// touching the overlay registers. Since we don't know that the last 2816// flip has happened yet we want to give the overlay as long as 2817// possible to catch up before we have to check on its progress. This 2818// makes it unlikely that we have to wait on the last flip. 2819***************************************************************************/ 2820_X_EXPORT Status XvMCPutSurface(Display *display,XvMCSurface *surface, 2821 Drawable draw, short srcx, short srcy, 2822 unsigned short srcw, unsigned short srch, 2823 short destx, short desty, 2824 unsigned short destw, unsigned short desth, 2825 int flags) { 2826 i810XvMCContext *pI810XvMC; 2827 i810XvMCSurface *pI810Surface; 2828 i810OverlayRecPtr pORegs; 2829 unsigned int ysrc_offset,uvsrc_offset; 2830 Box extents; 2831 uint window_width,window_height; 2832 unsigned int xscaleInt = 0,xscaleFract = 0,yscaleInt = 0,yscaleFract = 0; 2833 unsigned int xscaleFractUV = 0,xscaleIntUV = 0,yscaleFractUV = 0; 2834 unsigned int yscaleIntUV = 0,yPitch = 0,uvPitch = 0; 2835 unsigned int ovcmd = 0; 2836 uint d; 2837 double xscale,yscale; 2838 int diff; 2839 int clipped_srcx, clipped_srcy, clipped_destx, clipped_desty; 2840 int clipped_srcw, clipped_srch, clipped_destw, clipped_desth; 2841 uint x1,y1,root_width,root_height; 2842 int x2 = 0, y2 = 0,unused; 2843 uint nChilds; 2844 int stat; 2845 Window win,root,parent,*pChilds; 2846 2847 2848 if((display == NULL) || (surface == NULL)) { 2849 return BadValue; 2850 } 2851 2852 if(surface->privData == NULL) { 2853 return (error_base + XvMCBadSurface); 2854 } 2855 pI810Surface = (i810XvMCSurface *)surface->privData; 2856 pI810XvMC = (i810XvMCContext *)pI810Surface->privContext; 2857 pORegs = (i810OverlayRecPtr)pI810XvMC->oregs; 2858 2859 2860 switch(surface->surface_type_id) { 2861 case FOURCC_YV12: 2862 case FOURCC_I420: 2863 yPitch = (srcw + 7) & ~7; 2864 uvPitch = ((srcw>>1) + 7) & ~7; 2865 if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) { 2866 srch = srch>>1; 2867 } 2868 break; 2869 case FOURCC_UYVY: 2870 case FOURCC_YUY2: 2871 default: 2872 /* FIXME: Non Planar not fully implemented. */ 2873 return BadValue; 2874 yPitch = ((srcw + 7) & ~7) << 1; 2875 break; 2876 }/* switch(surface->surface_type_id) */ 2877 2878 /* 2879 FIXME: This should be using the DRI's clip rect but that isn't 2880 all hooked up yet. This has some latency but we get by. 2881 */ 2882 win = draw; 2883 XQueryTree(display,win,&root,&parent,&pChilds,&nChilds); 2884 if(nChilds) XFree(pChilds); 2885 XGetGeometry(display,win, &root, &x2, &y2, &window_width, 2886 &window_height, &d, &d); 2887 x1 = x2; 2888 y1 = y2; 2889 win = parent; 2890 do { 2891 XQueryTree(display,win,&root,&parent,&pChilds,&nChilds); 2892 if(nChilds) XFree(pChilds); 2893 XGetGeometry(display,win, &root, &x2, &y2, &d, &d, &d, &d); 2894 x1 += x2; 2895 y1 += y2; 2896 win = parent; 2897 }while(win != root); 2898 XGetGeometry(display,root, &root, &unused, &unused, 2899 &root_width, &root_height, &d, &d); 2900 2901 /* Left edge of Video window clipped to screen */ 2902 extents.x1 = 0; 2903 if(x1 > extents.x1) { 2904 extents.x1 = x1; 2905 } 2906 /* Right edge of Video window clipped to screen */ 2907 extents.x2 = root_width; 2908 if(extents.x2 > (x1 + window_width)) { 2909 extents.x2 = x1 + window_width; 2910 } 2911 /* Top edge of Video window clipped to screen */ 2912 extents.y1 = 0; 2913 if(y1 > extents.y1) { 2914 extents.y1 = y1; 2915 } 2916 /* Bottom edge of Video window clipped to screen */ 2917 extents.y2 = root_height; 2918 if(extents.y2 > (y1 + window_height)) { 2919 extents.y2 = y1 + window_height; 2920 } 2921 2922 /* 2923 Clipping is more difficult than is seems. We need to keep the 2924 scaling factors even if the destination window needs to be clipped. 2925 We clip the destination window first then apply a scaled version 2926 to the source window. 2927 */ 2928 2929 /* Put destination coords in screen coords */ 2930 destx += x1; 2931 desty += y1; 2932 2933 /* Scale factors requested */ 2934 xscale = (double)srcw / (double)destw; 2935 yscale = (double)srch / (double)desth; 2936 2937 /* 2938 If destination window needs to be clipped we actually adjust both 2939 the src and dest window so as to keep the scaling that was requested 2940 */ 2941 clipped_srcx = srcx; 2942 clipped_srcy = srcy; 2943 clipped_destx = destx; 2944 clipped_desty = desty; 2945 clipped_srcw = srcw; 2946 clipped_srch = srch; 2947 clipped_destw = destw; 2948 clipped_desth = desth; 2949 2950 /* Clip to the source surface boundaries */ 2951 if(clipped_srcx < 0) { 2952 clipped_destx += (0 - clipped_srcx) / xscale; 2953 clipped_srcw -= clipped_srcx; 2954 clipped_destw -= clipped_srcx / xscale; 2955 clipped_srcx = 0; 2956 } 2957 if((clipped_srcw + clipped_srcx) > surface->width) { 2958 clipped_srcw = surface->width - clipped_srcx; 2959 clipped_destw -= (clipped_srcw - srcw) / xscale; 2960 } 2961 if(clipped_srcy < 0) { 2962 clipped_desty += (0 - clipped_srcy) / yscale; 2963 clipped_srch -= clipped_srcy; 2964 clipped_desth -= clipped_srcy / yscale; 2965 clipped_srcy = 0; 2966 } 2967 if((clipped_srch + clipped_srcy) > surface->height) { 2968 clipped_srch = surface->height - clipped_srcy; 2969 clipped_desth -= (clipped_srch - srch) / yscale; 2970 } 2971 2972 /* Clip to the extents */ 2973 if(clipped_destx < extents.x1) { 2974 diff = extents.x1 - clipped_destx; 2975 clipped_srcx += diff * xscale; 2976 clipped_srcw -= diff * xscale; 2977 clipped_destw -= diff; 2978 clipped_destx = extents.x1; 2979 } 2980 2981 diff = (clipped_destx + clipped_destw) - extents.x2; 2982 if(diff > 0) { 2983 clipped_destw -= diff; 2984 clipped_srcw -= diff * xscale; 2985 } 2986 2987 if(clipped_desty < extents.y1) { 2988 diff = extents.y1 - clipped_desty; 2989 clipped_srcy += diff * yscale; 2990 clipped_srch -= diff * yscale; 2991 clipped_desth -= diff; 2992 clipped_desty = 0; 2993 } 2994 2995 diff = (clipped_desty + clipped_desth) - extents.y2; 2996 if(diff > 0) { 2997 clipped_desth -= diff; 2998 clipped_srch -= diff * yscale; 2999 } 3000 3001 /* If the whole window is clipped turn off the overlay */ 3002 if((clipped_destx + clipped_destw < extents.x1) || 3003 (clipped_desty + clipped_desth < extents.y1) || 3004 (clipped_destx > extents.x2) || 3005 (clipped_desty > extents.y2)) { 3006 return XvMCHideSurface(display, surface); 3007 } 3008 3009 /* 3010 Adjust the source offset width and height according to the clipped 3011 destination window. 3012 */ 3013 ysrc_offset = ((clipped_srcx + 1) & ~1) + 3014 ((clipped_srcy + 1) & ~1) * (1<<pI810Surface->pitch); 3015 uvsrc_offset = (clipped_srcx>>1) + 3016 (clipped_srcy>>1) * (1<<(pI810Surface->pitch - 1)); 3017 3018 /* 3019 Initially, YCbCr and Overlay Enable and 3020 vertical chrominance up interpolation and horozontal chrominance 3021 up interpolation 3022 */ 3023 ovcmd = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | 3024 Y_ADJUST | OVERLAY_ENABLE; 3025 3026 if ((clipped_destw != clipped_srcw) || 3027 (clipped_desth != clipped_srch)) { 3028 xscaleInt = (clipped_srcw / clipped_destw) & 0x3; 3029 xscaleFract = (clipped_srcw << 12) / clipped_destw; 3030 yscaleInt = (clipped_srch / clipped_desth) & 0x3; 3031 yscaleFract = (clipped_srch << 12) / clipped_desth; 3032 3033 if (clipped_destw > clipped_srcw) { 3034 /* horizontal up-scaling */ 3035 ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER; 3036 ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER; 3037 ovcmd |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION); 3038 } 3039 3040 if (clipped_desth > clipped_srch) { 3041 /* vertical up-scaling */ 3042 ovcmd &= ~VERTICAL_CHROMINANCE_FILTER; 3043 ovcmd &= ~VERTICAL_LUMINANCE_FILTER; 3044 ovcmd |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION); 3045 } 3046 3047 if (clipped_destw < clipped_srcw) { 3048 /* horizontal down-scaling */ 3049 ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER; 3050 ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER; 3051 ovcmd |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION); 3052 } 3053 3054 if (clipped_desth < clipped_srch) { 3055 /* vertical down-scaling */ 3056 ovcmd &= ~VERTICAL_CHROMINANCE_FILTER; 3057 ovcmd &= ~VERTICAL_LUMINANCE_FILTER; 3058 ovcmd |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION); 3059 } 3060 3061 /* now calculate the UV scaling factor */ 3062 if (xscaleFract) { 3063 xscaleFractUV = xscaleFract >> MINUV_SCALE; 3064 ovcmd &= ~HC_DOWN_INTERPOLATION; 3065 ovcmd |= HC_UP_INTERPOLATION; 3066 } 3067 3068 if (xscaleInt) { 3069 xscaleIntUV = xscaleInt >> MINUV_SCALE; 3070 if (xscaleIntUV) { 3071 ovcmd &= ~HC_UP_INTERPOLATION; 3072 } 3073 } 3074 3075 if (yscaleFract) { 3076 yscaleFractUV = yscaleFract >> MINUV_SCALE; 3077 ovcmd &= ~VC_DOWN_INTERPOLATION; 3078 ovcmd |= VC_UP_INTERPOLATION; 3079 } 3080 3081 if (yscaleInt) { 3082 yscaleIntUV = yscaleInt >> MINUV_SCALE; 3083 if (yscaleIntUV) { 3084 ovcmd &= ~VC_UP_INTERPOLATION; 3085 ovcmd |= VC_DOWN_INTERPOLATION; 3086 } 3087 } 3088 3089 }/* if((destw != srcw) || (desth != srch)) */ 3090 3091 /* Lock the DRM */ 3092 I810_LOCK(pI810XvMC,0); 3093 3094 /* Block until rendering on this surface is finished */ 3095 stat = XVMC_RENDERING; 3096 while(stat & XVMC_RENDERING) { 3097 XvMCGetSurfaceStatus(display,surface,&stat); 3098 } 3099 /* Block until the last flip is finished */ 3100 if(pI810XvMC->last_flip) { 3101 BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); 3102 } 3103 3104 pI810XvMC->current = !pI810XvMC->current; 3105 pORegs->OV0CMD = ovcmd; 3106 3107 if ((clipped_destw != clipped_srcw) || 3108 (clipped_desth != clipped_srch)) { 3109 pORegs->YRGBSCALE = (xscaleInt << 15) | 3110 ((xscaleFract & 0xFFF) << 3) | (yscaleInt) | 3111 ((yscaleFract & 0xFFF) << 20); 3112 3113 pORegs->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) | 3114 ((yscaleFractUV & 0xFFF) << 20); 3115 } 3116 else { 3117 /* Normal 1:1 scaling */ 3118 pORegs->YRGBSCALE = 0x80004000; 3119 pORegs->UVSCALE = 0x80004000; 3120 } 3121 3122 pORegs->SHEIGHT = clipped_srch | (clipped_srch << 15); 3123 pORegs->DWINPOS = (clipped_desty << 16) | clipped_destx; 3124 pORegs->DWINSZ = ((clipped_desth<< 16) | (clipped_destw)); 3125 3126 /* Attributes */ 3127 pORegs->OV0CLRC0 = ((pI810XvMC->contrast & 0x1ff)<<8) | 3128 (pI810XvMC->brightness & 0xff); 3129 pORegs->OV0CLRC1 = (pI810XvMC->saturation & 0x3ff); 3130 3131 /* Destination Colorkey Setup */ 3132 pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey); 3133 3134 /* buffer locations, add the offset from the clipping */ 3135 if(pI810XvMC->current) { 3136 pORegs->OBUF_1Y = (unsigned long)pI810Surface->offset + 3137 (unsigned long)pI810Surface->offsets[0] + ysrc_offset; 3138 pORegs->OBUF_1V = (unsigned long)pI810Surface->offset + 3139 (unsigned long)pI810Surface->offsets[2] + uvsrc_offset; 3140 pORegs->OBUF_1U = (unsigned long)pI810Surface->offset + 3141 (unsigned long)pI810Surface->offsets[1] + uvsrc_offset; 3142 } 3143 else { 3144 pORegs->OBUF_0Y = (unsigned long)pI810Surface->offset + 3145 (unsigned long)pI810Surface->offsets[0] + ysrc_offset; 3146 pORegs->OBUF_0V = (unsigned long)pI810Surface->offset + 3147 (unsigned long)pI810Surface->offsets[2] + uvsrc_offset; 3148 pORegs->OBUF_0U = (unsigned long)pI810Surface->offset + 3149 (unsigned long)pI810Surface->offsets[1] + uvsrc_offset; 3150 } 3151 3152 switch(surface->surface_type_id) { 3153 case FOURCC_YV12: 3154 case FOURCC_I420: 3155 pORegs->SWID = (uvPitch << 16) | yPitch; 3156 pORegs->SWIDQW = (uvPitch << 13) | (yPitch >> 3); 3157 pORegs->OV0STRIDE = (1<<pI810Surface->pitch) | 3158 ((1<<pI810Surface->pitch) << 15); 3159 pORegs->OV0CMD &= ~SOURCE_FORMAT; 3160 pORegs->OV0CMD |= YUV_420; 3161 if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) { 3162 /* Top Field Only */ 3163 if(flags & XVMC_TOP_FIELD) { 3164 if(pI810XvMC->current == 1) { 3165 pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | 3166 BUFFER1_FIELD0); 3167 } 3168 else { 3169 pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | 3170 BUFFER0_FIELD0); 3171 } 3172 pORegs->YRGB_VPH = 1<<15 | 1<<31; 3173 pORegs->UV_VPH = 3<<14 | 3<<30; 3174 pORegs->INIT_PH = 0x06 | 0x18; 3175 } 3176 /* Bottom Field Only */ 3177 else { 3178 if(pI810XvMC->current == 1) { 3179 pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | 3180 BUFFER1_FIELD1); 3181 } 3182 else { 3183 pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | 3184 BUFFER0_FIELD1); 3185 } 3186 pORegs->YRGB_VPH = 0; 3187 pORegs->UV_VPH = 7<<29 | 7<<13; 3188 pORegs->INIT_PH = 0x06; 3189 } 3190 } 3191 /* Frame Picture */ 3192 else { 3193 if(pI810XvMC->current == 1) { 3194 pORegs->OV0CMD |= BUFFER1_FIELD0; 3195 } 3196 else { 3197 pORegs->OV0CMD |= BUFFER0_FIELD0; 3198 } 3199 pORegs->YRGB_VPH = 0; 3200 pORegs->UV_VPH = 0; 3201 pORegs->INIT_PH = 0; 3202 } 3203 break; 3204 case FOURCC_UYVY: 3205 case FOURCC_YUY2: 3206 default: 3207 pORegs->SWID = srcw; 3208 pORegs->SWIDQW = srcw >> 3; 3209 pORegs->OV0STRIDE = pI810Surface->pitch; 3210 pORegs->OV0CMD &= ~SOURCE_FORMAT; 3211 pORegs->OV0CMD |= YUV_422; 3212 pORegs->OV0CMD &= ~OV_BYTE_ORDER; 3213 if (surface->surface_type_id == FOURCC_UYVY) { 3214 pORegs->OV0CMD |= Y_SWAP; 3215 } 3216 3217 pORegs->OV0CMD &= ~BUFFER_AND_FIELD; 3218 if(pI810XvMC->current == 1) { 3219 pORegs->OV0CMD |= BUFFER1_FIELD0; 3220 } 3221 else { 3222 pORegs->OV0CMD |= BUFFER0_FIELD0; 3223 } 3224 3225 break; 3226 } /* switch(surface->surface_type_id) */ 3227 3228 3229 3230 OVERLAY_FLIP(pI810XvMC); 3231 3232 /* 3233 The Overlay only flips when it knows you changed 3234 something. So the first time change stuff while it 3235 is watching to be sure. 3236 */ 3237 if(!pI810XvMC->last_flip) { 3238 pORegs->OV0CMD &= ~0x4; 3239 if(pI810XvMC->current == 1) { 3240 pORegs->OV0CMD |= BUFFER1_FIELD0; 3241 } 3242 else { 3243 pORegs->OV0CMD |= BUFFER0_FIELD0; 3244 } 3245 } 3246 pI810Surface->last_flip = ++pI810XvMC->last_flip; 3247 I810_UNLOCK(pI810XvMC); 3248 3249 return Success; 3250} 3251 3252/*************************************************************************** 3253// Function: XvMCSyncSurface 3254// Arguments: 3255// display - Connection to the X server 3256// surface - The surface to synchronize 3257// Info: 3258// Returns: Status 3259***************************************************************************/ 3260_X_EXPORT Status XvMCSyncSurface(Display *display,XvMCSurface *surface) { 3261 Status ret; 3262 int stat=0; 3263 /* 3264 FIXME: Perhaps a timer here to prevent lockup? 3265 FIXME: Perhaps a usleep to not be busy waiting? 3266 */ 3267 do { 3268 ret = XvMCGetSurfaceStatus(display,surface,&stat); 3269 }while(!ret && (stat & XVMC_RENDERING)); 3270 return ret; 3271} 3272 3273/*************************************************************************** 3274// Function: XvMCFlushSurface 3275// Description: 3276// This function commits pending rendering requests to ensure that they 3277// wll be completed in a finite amount of time. 3278// Arguments: 3279// display - Connection to X server 3280// surface - Surface to flush 3281// Info: 3282// This command is a noop for i810 becuase we always dispatch buffers in 3283// render. There is little gain to be had with 4k buffers. 3284// Returns: Status 3285***************************************************************************/ 3286_X_EXPORT Status XvMCFlushSurface(Display * display, XvMCSurface *surface) { 3287 return Success; 3288} 3289 3290/*************************************************************************** 3291// Function: XvMCGetSurfaceStatus 3292// Description: 3293// Arguments: 3294// display: connection to X server 3295// surface: The surface to query 3296// stat: One of the Following 3297// XVMC_RENDERING - The last XvMCRenderSurface command has not 3298// completed. 3299// XVMC_DISPLAYING - The surface is currently being displayed or a 3300// display is pending. 3301***************************************************************************/ 3302_X_EXPORT Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, 3303 int *stat) { 3304 i810XvMCSurface *privSurface; 3305 i810XvMCContext *pI810XvMC; 3306 int temp; 3307 3308 if((display == NULL) || (surface == NULL) || (stat == NULL)) { 3309 return BadValue; 3310 } 3311 if(surface->privData == NULL) { 3312 return BadValue; 3313 } 3314 *stat = 0; 3315 privSurface = surface->privData; 3316 3317 pI810XvMC = privSurface->privContext; 3318 if(pI810XvMC == NULL) { 3319 return (error_base + XvMCBadSurface); 3320 } 3321 3322 I810_LOCK(pI810XvMC,0); 3323 if(privSurface->last_flip) { 3324 /* This can not happen */ 3325 if(pI810XvMC->last_flip < privSurface->last_flip) { 3326 printf("Error: Context last flip is less than surface last flip.\n"); 3327 return BadValue; 3328 } 3329 /* 3330 If the context has 2 or more flips after this surface it 3331 cannot be displaying. Don't bother to check. 3332 */ 3333 if(!(pI810XvMC->last_flip > (privSurface->last_flip + 1))) { 3334 /* 3335 If this surface was the last flipped it is either displaying 3336 or about to be so don't bother checking. 3337 */ 3338 if(pI810XvMC->last_flip == privSurface->last_flip) { 3339 *stat |= XVMC_DISPLAYING; 3340 } 3341 else { 3342 /* 3343 In this case there has been one more flip since our surface's 3344 but we need to check if it is finished or not. 3345 */ 3346 temp = GET_FSTATUS(pI810XvMC); 3347 if(((temp & (1<<20))>>20) != pI810XvMC->current) { 3348 *stat |= XVMC_DISPLAYING; 3349 } 3350 } 3351 } 3352 } 3353 3354 if(privSurface->last_render && 3355 (privSurface->last_render > GET_RSTATUS(pI810XvMC))) { 3356 *stat |= XVMC_RENDERING; 3357 } 3358 I810_UNLOCK(pI810XvMC); 3359 3360 return Success; 3361} 3362 3363/*************************************************************************** 3364// 3365// Surface manipulation functions 3366// 3367***************************************************************************/ 3368 3369/*************************************************************************** 3370// Function: XvMCHideSurface 3371// Description: Stops the display of a surface. 3372// Arguments: 3373// display - Connection to the X server. 3374// surface - surface to be hidden. 3375// 3376// Returns: Status 3377***************************************************************************/ 3378_X_EXPORT Status XvMCHideSurface(Display *display, XvMCSurface *surface) { 3379 i810XvMCSurface *pI810Surface; 3380 i810XvMCContext *pI810XvMC; 3381 int ss, xx; 3382 3383 /* Did we get a good display and surface passed into us? */ 3384 if(display == NULL) { 3385 return BadValue; 3386 } 3387 3388 if(surface == NULL) { 3389 return (error_base + XvMCBadSurface); 3390 } 3391 3392 XvMCSyncSurface(display, surface); 3393 3394 /* Get surface private data pointer */ 3395 if(surface->privData == NULL) { 3396 return (error_base + XvMCBadSurface); 3397 } 3398 pI810Surface = (i810XvMCSurface *)surface->privData; 3399 3400 /* 3401 Get the status of the surface, if it is not currently displayed 3402 we don't need to worry about it. 3403 */ 3404 if((xx = XvMCGetSurfaceStatus(display, surface, &ss)) != Success) { 3405 return xx; 3406 } 3407 if(! (ss & XVMC_DISPLAYING)) { 3408 return Success; 3409 } 3410 3411 /* Get the associated context pointer */ 3412 pI810XvMC = (i810XvMCContext *)pI810Surface->privContext; 3413 if(pI810XvMC == NULL) { 3414 return (error_base + XvMCBadSurface); 3415 } 3416 3417 if(pI810XvMC->last_flip) { 3418 I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); 3419 3420 /* Make sure last flip is done */ 3421 BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); 3422 3423 /* Set the registers to turn the overlay off */ 3424 pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | 3425 Y_ADJUST; 3426 pI810XvMC->current = !pI810XvMC->current; 3427 if(pI810XvMC->current == 1) { 3428 pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0; 3429 } 3430 else { 3431 pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0; 3432 } 3433 OVERLAY_FLIP(pI810XvMC); 3434 /* 3435 Increment the context flip but not the surface. This way no 3436 surface has the last flip #. 3437 */ 3438 pI810XvMC->last_flip++; 3439 3440 3441 /* Now wait until the hardware reads the registers and makes the change. */ 3442 BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current) 3443 3444 I810_UNLOCK(pI810XvMC); 3445 } 3446 3447 return Success; 3448} 3449 3450 3451 3452 3453/*************************************************************************** 3454// 3455// Functions that deal with subpictures 3456// 3457***************************************************************************/ 3458 3459 3460 3461/*************************************************************************** 3462// Function: XvMCCreateSubpicture 3463// Description: This creates a subpicture by filling out the XvMCSubpicture 3464// structure passed to it and returning Success. 3465// Arguments: 3466// display - Connection to the X server. 3467// context - The context to create the subpicture for. 3468// subpicture - Pre-allocated XvMCSubpicture structure to be filled in. 3469// width - of subpicture 3470// height - of subpicture 3471// xvimage_id - The id describing the XvImage format. 3472// 3473// Returns: Status 3474***************************************************************************/ 3475_X_EXPORT Status XvMCCreateSubpicture(Display *display, XvMCContext *context, 3476 XvMCSubpicture *subpicture, 3477 unsigned short width, unsigned short height, 3478 int xvimage_id) { 3479 i810XvMCContext *pI810XvMC; 3480 i810XvMCSubpicture *pI810Subpicture; 3481 int priv_count; 3482 uint *priv_data; 3483 Status ret; 3484 3485 if((subpicture == NULL) || (context == NULL) || (display == NULL)){ 3486 return BadValue; 3487 } 3488 3489 pI810XvMC = (i810XvMCContext *)context->privData; 3490 if(pI810XvMC == NULL) { 3491 return (error_base + XvMCBadContext); 3492 } 3493 3494 3495 subpicture->context_id = context->context_id; 3496 subpicture->xvimage_id = xvimage_id; 3497 3498 /* These need to be checked to make sure they are not too big! */ 3499 subpicture->width = width; 3500 subpicture->height = height; 3501 3502 subpicture->privData = 3503 (i810XvMCSubpicture *)malloc(sizeof(i810XvMCSubpicture)); 3504 3505 if(!subpicture->privData) { 3506 return BadAlloc; 3507 } 3508 pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; 3509 3510 3511 if((ret = _xvmc_create_subpicture(display, context, subpicture, 3512 &priv_count, &priv_data))) { 3513 printf("Unable to create XvMCSubpicture.\n"); 3514 return ret; 3515 } 3516 3517 if(priv_count != 1) { 3518 printf("_xvmc_create_subpicture() returned incorrect data size.\n"); 3519 printf("Expected 1 got %d\n",priv_count); 3520 free(priv_data); 3521 return BadAlloc; 3522 } 3523 /* Data == Client Address, offset == Physical address offset */ 3524 pI810Subpicture->data = pI810XvMC->surfaces.address; 3525 pI810Subpicture->offset = pI810XvMC->surfaces.offset; 3526 3527 /* Initialize private values */ 3528 pI810Subpicture->privContext = pI810XvMC; 3529 3530 pI810Subpicture->last_render = 0; 3531 pI810Subpicture->last_flip = 0; 3532 3533 /* Based on the xvimage_id we will need to set the other values */ 3534 subpicture->num_palette_entries = 16; 3535 subpicture->entry_bytes = 3; 3536 strcpy(subpicture->component_order,"YUV"); 3537 3538 /* 3539 i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch 3540 and the Tiler need 512k aligned surfaces, basically we are 3541 stuck with fixed memory with pitch 1024. 3542 */ 3543 pI810Subpicture->pitch = 10; 3544 3545 /* 3546 offsets[0] == offset into the map described by either 3547 address (Client memeory address) or offset (physical offset from fb base) 3548 */ 3549 pI810Subpicture->offsets[0] = priv_data[0]; 3550 if(((unsigned long)pI810Subpicture->data + pI810Subpicture->offsets[0]) & 4095) { 3551 printf("XvMCCreateSubpicture: Subpicture offset 0 is not 4096 aligned\n"); 3552 } 3553 3554 /* Free data returned from xvmc_create_surface */ 3555 free(priv_data); 3556 3557 /* Clear the surface to 0 */ 3558 memset((void *)((unsigned long)pI810Subpicture->data + (unsigned long)pI810Subpicture->offsets[0]), 3559 0, ((1<<pI810Subpicture->pitch) * subpicture->height)); 3560 3561 switch(subpicture->xvimage_id) { 3562 case FOURCC_IA44: 3563 case FOURCC_AI44: 3564 /* Destination buffer info command */ 3565 pI810Subpicture->dbi1 = ((((unsigned int)pI810Subpicture->offset + 3566 pI810Subpicture->offsets[0]) & ~0xfc000fff) | 3567 (pI810Subpicture->pitch - 9)); 3568 3569 /* Destination buffer variables command */ 3570 pI810Subpicture->dbv1 = (0x8<<20) | (0x8<<16); 3571 3572 /* Map info command */ 3573 pI810Subpicture->mi1 = (0x0<<24) | (3<<21) | (1<<9) | 3574 (pI810Subpicture->pitch - 3); 3575 3576 pI810Subpicture->mi2 = (((unsigned int)subpicture->height - 1)<<16) | 3577 ((unsigned int)subpicture->width - 1); 3578 3579 pI810Subpicture->mi3 = ((unsigned int)pI810Subpicture->offset + 3580 pI810Subpicture->offsets[0]) & ~0xfc00000f; 3581 break; 3582 default: 3583 free(subpicture->privData); 3584 return BadMatch; 3585 } 3586 3587 pI810XvMC->ref++; 3588 return Success; 3589} 3590 3591 3592 3593/*************************************************************************** 3594// Function: XvMCClearSubpicture 3595// Description: Clear the area of the given subpicture to "color". 3596// structure passed to it and returning Success. 3597// Arguments: 3598// display - Connection to the X server. 3599// subpicture - Subpicture to clear. 3600// x, y, width, height - rectangle in the subpicture to clear. 3601// color - The data to file the rectangle with. 3602// 3603// Returns: Status 3604***************************************************************************/ 3605_X_EXPORT Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture, 3606 short x, short y, 3607 unsigned short width, unsigned short height, 3608 unsigned int color) { 3609 3610 i810XvMCContext *pI810XvMC; 3611 i810XvMCSubpicture *pI810Subpicture; 3612 int i; 3613 3614 if((subpicture == NULL) || (display == NULL)){ 3615 return BadValue; 3616 } 3617 3618 if(!subpicture->privData) { 3619 return (error_base + XvMCBadSubpicture); 3620 } 3621 pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; 3622 3623 pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext; 3624 if(pI810XvMC == NULL) { 3625 return (error_base + XvMCBadSubpicture); 3626 } 3627 3628 if((x < 0) || (x + width > subpicture->width)) { 3629 return BadValue; 3630 } 3631 3632 if((y < 0) || (y + height > subpicture->height)) { 3633 return BadValue; 3634 } 3635 3636 for(i=y; i<y + height; i++) { 3637 memset((void *)((unsigned long)pI810Subpicture->data + 3638 (unsigned long)pI810Subpicture->offsets[0] + x + 3639 (1<<pI810Subpicture->pitch) * i),(char)color,width); 3640 } 3641 3642 return Success; 3643} 3644 3645/*************************************************************************** 3646// Function: XvMCCompositeSubpicture 3647// Description: Composite the XvImae on the subpicture. This composit uses 3648// non-premultiplied alpha. Destination alpha is utilized 3649// except for with indexed subpictures. Indexed subpictures 3650// use a simple "replace". 3651// Arguments: 3652// display - Connection to the X server. 3653// subpicture - Subpicture to clear. 3654// image - the XvImage to be used as the source of the composite. 3655// srcx, srcy, width, height - The rectangle from the image to be used. 3656// dstx, dsty - location in the subpicture to composite the source. 3657// 3658// Returns: Status 3659***************************************************************************/ 3660_X_EXPORT Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture, 3661 XvImage *image, 3662 short srcx, short srcy, 3663 unsigned short width, unsigned short height, 3664 short dstx, short dsty) { 3665 3666 i810XvMCContext *pI810XvMC; 3667 i810XvMCSubpicture *pI810Subpicture; 3668 int i; 3669 3670 if((subpicture == NULL) || (display == NULL)){ 3671 return BadValue; 3672 } 3673 3674 if(!subpicture->privData) { 3675 return (error_base + XvMCBadSubpicture); 3676 } 3677 pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; 3678 3679 pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext; 3680 if(pI810XvMC == NULL) { 3681 return (error_base + XvMCBadSubpicture); 3682 } 3683 3684 if((srcx < 0) || (srcx + width > image->width)) { 3685 return BadValue; 3686 } 3687 3688 if((dstx < 0) || (dstx + width > subpicture->width)) { 3689 return BadValue; 3690 } 3691 3692 if((srcy < 0) || (srcy + height > image->height)) { 3693 return BadValue; 3694 } 3695 3696 if((dsty < 0) || (dsty + height > subpicture->height)) { 3697 return BadValue; 3698 } 3699 3700 for(i=0; i<height; i++) { 3701 memcpy((void *)((unsigned long)pI810Subpicture->data + 3702 (unsigned long)pI810Subpicture->offsets[0] + dstx + 3703 (1<<pI810Subpicture->pitch) * (i + dsty)), 3704 (void *)((unsigned long)image->data + 3705 (unsigned long)image->offsets[0] + srcx + 3706 image->pitches[0] * (i + srcy)) 3707 ,width); 3708 } 3709 3710 return Success; 3711 3712} 3713 3714 3715/*************************************************************************** 3716// Function: XvMCDestroySubpicture 3717// Description: Destroys the specified subpicture. 3718// Arguments: 3719// display - Connection to the X server. 3720// subpicture - Subpicture to be destroyed. 3721// 3722// Returns: Status 3723***************************************************************************/ 3724_X_EXPORT Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) { 3725 3726 i810XvMCSubpicture *pI810Subpicture; 3727 i810XvMCContext *pI810XvMC; 3728 3729 if((display == NULL) || (subpicture == NULL)) { 3730 return BadValue; 3731 } 3732 if(!subpicture->privData) { 3733 return (error_base + XvMCBadSubpicture); 3734 } 3735 pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; 3736 3737 pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext; 3738 if(!pI810XvMC) { 3739 return (error_base + XvMCBadSubpicture); 3740 } 3741 3742 3743 if(pI810Subpicture->last_render) { 3744 XvMCSyncSubpicture(display,subpicture); 3745 } 3746 3747 _xvmc_destroy_subpicture(display,subpicture); 3748 3749 i810_free_privContext(pI810XvMC); 3750 3751 free(pI810Subpicture); 3752 subpicture->privData = NULL; 3753 return Success; 3754} 3755 3756 3757/*************************************************************************** 3758// Function: XvMCSetSubpicturePalette 3759// Description: Set the subpictures palette 3760// Arguments: 3761// display - Connection to the X server. 3762// subpicture - Subpiture to set palette for. 3763// palette - A pointer to an array holding the palette data. The array 3764// is num_palette_entries * entry_bytes in size. 3765// Returns: Status 3766***************************************************************************/ 3767 3768_X_EXPORT Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, 3769 unsigned char *palette) { 3770 i810XvMCSubpicture *privSubpicture; 3771 int i,j; 3772 3773 if((display == NULL) || (subpicture == NULL)) { 3774 return BadValue; 3775 } 3776 if(subpicture->privData == NULL) { 3777 return (error_base + XvMCBadSubpicture); 3778 } 3779 privSubpicture = (i810XvMCSubpicture *)subpicture->privData; 3780 3781 j=0; 3782 for(i=0; i<16; i++) { 3783 privSubpicture->palette[0][i] = palette[j++]; 3784 privSubpicture->palette[1][i] = palette[j++]; 3785 privSubpicture->palette[2][i] = palette[j++]; 3786 } 3787 return Success; 3788} 3789 3790/*************************************************************************** 3791// Function: XvMCBlendSubpicture 3792// Description: 3793// The behavior of this function is different depending on whether 3794// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo. 3795// i810 only support frontend behavior. 3796// 3797// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior): 3798// 3799// XvMCBlendSubpicture is a no-op in this case. 3800// 3801// Arguments: 3802// display - Connection to the X server. 3803// subpicture - The subpicture to be blended into the video. 3804// target_surface - The surface to be displayed with the blended subpic. 3805// source_surface - Source surface prior to blending. 3806// subx, suby, subw, subh - The rectangle from the subpicture to use. 3807// surfx, surfy, surfw, surfh - The rectangle in the surface to blend 3808// blend the subpicture rectangle into. Scaling can ocure if 3809// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set. 3810// 3811// Returns: Status 3812***************************************************************************/ 3813_X_EXPORT Status XvMCBlendSubpicture(Display *display, XvMCSurface *target_surface, 3814 XvMCSubpicture *subpicture, 3815 short subx, short suby, 3816 unsigned short subw, unsigned short subh, 3817 short surfx, short surfy, 3818 unsigned short surfw, unsigned short surfh) { 3819 3820 return BadMatch; 3821} 3822 3823 3824 3825/*************************************************************************** 3826// Function: XvMCBlendSubpicture2 3827// Description: 3828// The behavior of this function is different depending on whether 3829// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo. 3830// i810 only supports frontend blending. 3831// 3832// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior): 3833// 3834// XvMCBlendSubpicture2 blends the source_surface and subpicture and 3835// puts it in the target_surface. This does not effect the status of 3836// the source surface but will cause the target_surface to query 3837// XVMC_RENDERING until the blend is completed. 3838// 3839// Arguments: 3840// display - Connection to the X server. 3841// subpicture - The subpicture to be blended into the video. 3842// target_surface - The surface to be displayed with the blended subpic. 3843// source_surface - Source surface prior to blending. 3844// subx, suby, subw, subh - The rectangle from the subpicture to use. 3845// surfx, surfy, surfw, surfh - The rectangle in the surface to blend 3846// blend the subpicture rectangle into. Scaling can ocure if 3847// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set. 3848// 3849// Returns: Status 3850***************************************************************************/ 3851_X_EXPORT Status XvMCBlendSubpicture2(Display *display, 3852 XvMCSurface *source_surface, 3853 XvMCSurface *target_surface, 3854 XvMCSubpicture *subpicture, 3855 short subx, short suby, 3856 unsigned short subw, unsigned short subh, 3857 short surfx, short surfy, 3858 unsigned short surfw, unsigned short surfh) { 3859 drmBufPtr pDMA; 3860 unsigned int *data; 3861 i810XvMCContext *pI810XvMC; 3862 i810XvMCSubpicture *privSubpicture; 3863 i810XvMCSurface *privTarget; 3864 i810XvMCSurface *privSource; 3865 drm_i810_mc_t mc; 3866 int i,j; 3867 3868 if(display == NULL) { 3869 return BadValue; 3870 } 3871 3872 if(subpicture == NULL) { 3873 return (error_base + XvMCBadSubpicture); 3874 } 3875 3876 if((target_surface == NULL) || (source_surface == NULL)) { 3877 return (error_base + XvMCBadSurface); 3878 } 3879 3880 if((subpicture->xvimage_id != FOURCC_AI44) && 3881 (subpicture->xvimage_id != FOURCC_IA44)) { 3882 return (error_base + XvMCBadSubpicture); 3883 } 3884 3885 if(!subpicture->privData) { 3886 return (error_base + XvMCBadSubpicture); 3887 } 3888 privSubpicture = (i810XvMCSubpicture *)subpicture->privData; 3889 3890 pI810XvMC = (i810XvMCContext *)privSubpicture->privContext; 3891 if(pI810XvMC == NULL) { 3892 return (error_base + XvMCBadSubpicture); 3893 } 3894 3895 if(!target_surface->privData) { 3896 return (error_base + XvMCBadSurface); 3897 } 3898 privTarget = (i810XvMCSurface *)target_surface->privData; 3899 3900 if(!source_surface->privData) { 3901 return (error_base + XvMCBadSurface); 3902 } 3903 privSource = (i810XvMCSurface *)source_surface->privData; 3904 3905 3906 /* Check that size isn't bigger than subpicture */ 3907 if((subx + subw) > subpicture->width) { 3908 return BadValue; 3909 } 3910 if((suby + subh) > subpicture->height) { 3911 return BadValue; 3912 } 3913 /* Check that dest isn't bigger than surface */ 3914 if((surfx + surfw) > target_surface->width) { 3915 return BadValue; 3916 } 3917 if((surfy + surfh) > target_surface->height) { 3918 return BadValue; 3919 } 3920 /* Make sure surfaces match */ 3921 if(target_surface->width != source_surface->width) { 3922 return BadValue; 3923 } 3924 if(target_surface->height != source_surface->height) { 3925 return BadValue; 3926 } 3927 3928 /* Lock For DMA */ 3929 I810_LOCK(pI810XvMC,0); 3930 3931 /* Allocate DMA buffer */ 3932 pDMA = i810_get_free_buffer(pI810XvMC); 3933 data = pDMA->address; 3934 3935 /* Copy Y data first */ 3936 /* SOURCE_COPY_BLT */ 3937 *data++ = (2<<29) | (0x43<<22) | 0x4; 3938 *data++ = (0xcc<<16) | (1<<26) | (1<<privTarget->pitch); 3939 *data++ = (target_surface->height<<16) | target_surface->width; 3940 *data++ = privTarget->offset + privTarget->offsets[0]; 3941 *data++ = (1<<privSource->pitch); 3942 *data++ = privSource->offset + privSource->offsets[0]; 3943 3944 /* Select Context 1 for loading */ 3945 *data++ = CMD_FLUSH; 3946 *data++ = (5<<23) | (1<<17) | (1<<8); 3947 *data++ = CMD_FLUSH; 3948 3949 /* Load Palette */ 3950 *data++ = MAP_PALETTE_LOAD; 3951 /* 16 levels of alpha for each Y */ 3952 switch(subpicture->xvimage_id) { 3953 case FOURCC_IA44: 3954 for(i=0; i<16; i++) { 3955 for(j=0; j<16; j++) { 3956 *data++ = (j<<12) | (j<<8) | privSubpicture->palette[0][i]; 3957 } 3958 } 3959 break; 3960 case FOURCC_AI44: 3961 for(i=0; i<16; i++) { 3962 for(j=0; j<16; j++) { 3963 *data++ = (i<<12) | (i<<8) | privSubpicture->palette[0][j]; 3964 } 3965 } 3966 break; 3967 } 3968 /* TARGET */ 3969 /* *data++ = CMD_FLUSH; */ 3970 /* *data++ = BOOLEAN_ENA_2; */ 3971 *data++ = CMD_FLUSH; 3972 *data++ = DEST_BUFFER_INFO; 3973 *data++ = privTarget->dbi1y; 3974 *data++ = DEST_BUFFER_VAR; 3975 *data++ = privTarget->dbv1; 3976 3977 /* ALPHA */ 3978 *data++ = CMD_MAP_INFO; 3979 *data++ = privSubpicture->mi1; 3980 *data++ = privSubpicture->mi2; 3981 *data++ = privSubpicture->mi3; 3982 3983 *data++ = VERTEX_FORMAT | (1<<8) | (3<<1); 3984 *data++ = BOOLEAN_ENA_1; 3985 *data++ = SRC_DEST_BLEND_MONO | (0x940); 3986 /* Map Filter */ 3987 *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (0x224); 3988 3989 /* Use context 1 */ 3990 *data++ = CMD_FLUSH; 3991 *data++ = (5<<23) | (1<<16) | 1; 3992 *data++ = CMD_FLUSH; 3993 3994 /* Drawing Rect Info */ 3995 *data++ = DRAWING_RECT_INFO; 3996 *data++ = 0x0; 3997 *data++ = 0x0; 3998 *data++ = 0x0; 3999 *data++ = 0x0; 4000 *data++ = 0x0; 4001 4002 /* GFXPRIMITIVE RECTANGLE */ 4003 *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11; 4004 /* Bottom Right Vertex */ 4005 *(float *)data++ = (float) (surfx + surfw); 4006 *(float *)data++ = (float) (surfy + surfh); 4007 *(float *)data++ = (float) (subx + subw); 4008 *(float *)data++ = (float) (suby + subh); 4009 /* Bottom Left Vertex */ 4010 *(float *)data++ = (float) surfx; 4011 *(float *)data++ = (float) (surfy + surfh); 4012 *(float *)data++ = (float) subx; 4013 *(float *)data++ = (float) (suby + subh); 4014 /* Top Left Vertex */ 4015 *(float *)data++ = (float) surfx; 4016 *(float *)data++ = (float) surfy; 4017 *(float *)data++ = (float) subx; 4018 *(float *)data++ = (float) suby; 4019 4020 /* Load and Use Context 0 */ 4021 *data++ = CMD_FLUSH; 4022 *data++ = (5<<23) | (1<<17) | (1<<16); 4023 *data++ = CMD_FLUSH; 4024 4025 /* U data */ 4026 /* SOURCE_COPY_BLT */ 4027 *data++ = (2<<29) | (0x43<<22) | 0x4; 4028 *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1)); 4029 *data++ = (target_surface->height<<15) | (target_surface->width>>1); 4030 *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[1]; 4031 *data++ = (1<<(privSource->pitch - 1)); 4032 *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[1]; 4033 4034 /* Context 1 select */ 4035 *data++ = CMD_FLUSH; 4036 *data++ = (5<<23) | (1<<17) | (1<<8); 4037 *data++ = CMD_FLUSH; 4038 /* ALPHA PALETTE */ 4039 *data++ = MAP_PALETTE_LOAD; 4040 /* 16 levels of alpha for each Y */ 4041 switch(subpicture->xvimage_id) { 4042 case FOURCC_IA44: 4043 for(i=0; i<16; i++) { 4044 for(j=0; j<16; j++) { 4045 *data++ = (j<<12) | (j<<8) | privSubpicture->palette[2][i]; 4046 } 4047 } 4048 break; 4049 case FOURCC_AI44: 4050 for(i=0; i<16; i++) { 4051 for(j=0; j<16; j++) { 4052 *data++ = (i<<12) | (i<<8) | privSubpicture->palette[2][j]; 4053 } 4054 } 4055 break; 4056 } 4057 /* TARGET */ 4058 *data++ = CMD_FLUSH; 4059 *data++ = BOOLEAN_ENA_2; 4060 *data++ = CMD_FLUSH; 4061 *data++ = DEST_BUFFER_INFO; 4062 *data++ = privTarget->dbi1u; 4063 *data++ = DEST_BUFFER_VAR; 4064 *data++ = privTarget->dbv1; 4065 4066 /* ALPHA */ 4067 *data++ = CMD_MAP_INFO; 4068 *data++ = privSubpicture->mi1; 4069 *data++ = privSubpicture->mi2; 4070 *data++ = privSubpicture->mi3; 4071 4072 *data++ = VERTEX_FORMAT | (1<<8) | (3<<1); 4073 *data++ = BOOLEAN_ENA_1; 4074 *data++ = SRC_DEST_BLEND_MONO | (0x940); 4075 /* Map Filter */ 4076 *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224); 4077 4078 /* Use context 1 */ 4079 *data++ = CMD_FLUSH; 4080 *data++ = (5<<23) | (1<<16) | 1; 4081 *data++ = CMD_FLUSH; 4082 4083 /* Drawing Rect Info */ 4084 *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3; 4085 *data++ = 0; 4086 *data++ = 0; 4087 *data++ = 0; 4088 *data++ = 0; 4089 *data++ = 0; 4090 4091 /* Rectangle */ 4092 *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11; 4093 /* Bottom Right */ 4094 *(float *)data++ = (float) ((surfx + surfw)>>1); 4095 *(float *)data++ = (float) ((surfy + surfh)>>1); 4096 *(float *)data++ = (float) subx + subw; 4097 *(float *)data++ = (float) suby + subh; 4098 /* Bottom Left */ 4099 *(float *)data++ = (float) (surfx>>1); 4100 *(float *)data++ = (float) ((surfy + surfh)>>1); 4101 *(float *)data++ = (float) subx; 4102 *(float *)data++ = (float) suby + subh; 4103 /* Top Left */ 4104 *(float *)data++ = (float) (surfx>>1); 4105 *(float *)data++ = (float) (surfy>>1); 4106 *(float *)data++ = (float) subx; 4107 *(float *)data++ = (float) suby; 4108 4109 /* Load and Use Context 0 */ 4110 *data++ = CMD_FLUSH; 4111 *data++ = (5<<23) | (1<<17) | (1<<16); 4112 *data++ = CMD_FLUSH; 4113 4114 /* V data */ 4115 /* SOURCE_COPY_BLT */ 4116 *data++ = (2<<29) | (0x43<<22) | 0x4; 4117 *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1)); 4118 *data++ = (target_surface->height<<15) | (target_surface->width>>1); 4119 *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[2]; 4120 *data++ = (1<<(privSource->pitch - 1)); 4121 *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[2]; 4122 4123 /* Context 1 select */ 4124 *data++ = CMD_FLUSH; 4125 *data++ = (5<<23) | (1<<17) | (1<<8); 4126 *data++ = CMD_FLUSH; 4127 4128 /* ALPHA PALETTE */ 4129 *data++ = MAP_PALETTE_LOAD; 4130 /* 16 levels of alpha for each Y */ 4131 switch(subpicture->xvimage_id) { 4132 case FOURCC_IA44: 4133 for(i=0; i<16; i++) { 4134 for(j=0; j<16; j++) { 4135 *data++ = (j<<12) | (j<<8) | privSubpicture->palette[1][i]; 4136 } 4137 } 4138 break; 4139 case FOURCC_AI44: 4140 for(i=0; i<16; i++) { 4141 for(j=0; j<16; j++) { 4142 *data++ = (i<<12) | (i<<8) | privSubpicture->palette[1][j]; 4143 } 4144 } 4145 break; 4146 } 4147 /* TARGET */ 4148 *data++ = CMD_FLUSH; 4149 *data++ = BOOLEAN_ENA_2; 4150 *data++ = CMD_FLUSH; 4151 *data++ = DEST_BUFFER_INFO; 4152 *data++ = privTarget->dbi1v; 4153 *data++ = DEST_BUFFER_VAR; 4154 *data++ = privTarget->dbv1; 4155 4156 /* ALPHA */ 4157 *data++ = CMD_MAP_INFO; 4158 *data++ = privSubpicture->mi1; 4159 *data++ = privSubpicture->mi2; 4160 *data++ = privSubpicture->mi3; 4161 4162 *data++ = VERTEX_FORMAT | (1<<8) | (3<<1); 4163 *data++ = BOOLEAN_ENA_1; 4164 *data++ = SRC_DEST_BLEND_MONO | (0x940); 4165 /* Map Filter */ 4166 *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224); 4167 4168 /* Use context 1 */ 4169 *data++ = CMD_FLUSH; 4170 *data++ = (5<<23) | (1<<16) | 1; 4171 *data++ = CMD_FLUSH; 4172 4173 /* Drawing Rect Info */ 4174 *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3; 4175 *data++ = 0; 4176 *data++ = 0; 4177 *data++ = 0; 4178 *data++ = 0; 4179 *data++ = 0; 4180 4181 /* Rectangle */ 4182 *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11; 4183 /* Bottom Right */ 4184 *(float *)data++ = (float) ((surfx + surfw)>>1); 4185 *(float *)data++ = (float) ((surfy + surfh)>>1); 4186 *(float *)data++ = (float) subx + subw; 4187 *(float *)data++ = (float) suby + subh; 4188 /* Bottom Left */ 4189 *(float *)data++ = (float) (surfx>>1); 4190 *(float *)data++ = (float) ((surfy + surfh)>>1); 4191 *(float *)data++ = (float) subx; 4192 *(float *)data++ = (float) suby + subh; 4193 /* Top Left */ 4194 *(float *)data++ = (float) (surfx>>1); 4195 *(float *)data++ = (float) (surfy>>1); 4196 *(float *)data++ = (float) subx; 4197 *(float *)data++ = (float) suby; 4198 4199 /* Load and Use Context 0 */ 4200 *data++ = CMD_FLUSH; 4201 *data++ = (5<<23) | (1<<17) | (1<<16); 4202 *data++ = CMD_FLUSH; 4203 4204 4205 /* Dispatch */ 4206 pDMA->used = (unsigned long)data - (unsigned long)pDMA->address; 4207 mc.idx = pDMA->idx; 4208 mc.used = pDMA->used; 4209 mc.last_render = ++pI810XvMC->last_render; 4210 privTarget->last_render = pI810XvMC->last_render; 4211 I810_MC(pI810XvMC,mc); 4212 4213 I810_UNLOCK(pI810XvMC); 4214 return Success; 4215} 4216 4217 4218 4219/*************************************************************************** 4220// Function: XvMCSyncSubpicture 4221// Description: This function blocks until all composite/clear requests on 4222// the subpicture have been complete. 4223// Arguments: 4224// display - Connection to the X server. 4225// subpicture - The subpicture to synchronize 4226// 4227// Returns: Status 4228***************************************************************************/ 4229_X_EXPORT Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) { 4230 Status ret; 4231 int stat=0; 4232 do { 4233 ret = XvMCGetSubpictureStatus(display,subpicture,&stat); 4234 }while(!ret && (stat & XVMC_RENDERING)); 4235 return ret; 4236} 4237 4238 4239 4240/*************************************************************************** 4241// Function: XvMCFlushSubpicture 4242// Description: This function commits pending composite/clear requests to 4243// ensure that they will be completed in a finite amount of 4244// time. 4245// Arguments: 4246// display - Connection to the X server. 4247// subpicture - The subpicture whos compsiting should be flushed 4248// 4249// Returns: Status 4250// NOTES: i810 always dispatches commands so flush is a no-op 4251***************************************************************************/ 4252_X_EXPORT Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) { 4253 if(display == NULL) { 4254 return BadValue; 4255 } 4256 if(subpicture == NULL) { 4257 return (error_base + XvMCBadSubpicture); 4258 } 4259 4260 return Success; 4261} 4262 4263 4264 4265/*************************************************************************** 4266// Function: XvMCGetSubpictureStatus 4267// Description: This function gets the current status of a subpicture 4268// 4269// Arguments: 4270// display - Connection to the X server. 4271// subpicture - The subpicture whos status is being queried 4272// stat - The status of the subpicture. It can be any of the following 4273// OR'd together: 4274// XVMC_RENDERING - Last composite or clear request not completed 4275// XVMC_DISPLAYING - Suppicture currently being displayed. 4276// 4277// Returns: Status 4278// Notes: i810 always blends into a third surface so the subpicture is 4279// never actually displaying, only a copy of it is displaying. We only 4280// have to worry about the rendering case. 4281***************************************************************************/ 4282_X_EXPORT Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, 4283 int *stat) { 4284 4285 i810XvMCSubpicture *privSubpicture; 4286 i810XvMCContext *pI810XvMC; 4287 4288 if((display == NULL) || (stat == NULL)) { 4289 return BadValue; 4290 } 4291 if((subpicture == NULL) || (subpicture->privData == NULL)) { 4292 return (error_base + XvMCBadSubpicture); 4293 } 4294 *stat = 0; 4295 privSubpicture = (i810XvMCSubpicture *)subpicture->privData; 4296 4297 pI810XvMC = (i810XvMCContext *)privSubpicture->privContext; 4298 if(pI810XvMC == NULL) { 4299 return (error_base + XvMCBadSubpicture); 4300 } 4301 4302 I810_LOCK(pI810XvMC,0); 4303 4304 if(privSubpicture->last_render && 4305 (privSubpicture->last_render > GET_RSTATUS(pI810XvMC))) { 4306 *stat |= XVMC_RENDERING; 4307 } 4308 I810_UNLOCK(pI810XvMC); 4309 4310 return Success; 4311} 4312 4313#define NUM_XVMC_ATTRIBUTES 4 4314static XvAttribute I810_XVMC_ATTRIBUTES[] = { 4315 {XvGettable | XvSettable, 0, 0xffffff, "XV_COLORKEY"}, 4316 {XvGettable | XvSettable, -127, +127, "XV_BRIGHTNESS"}, 4317 {XvGettable | XvSettable, 0, 0x1ff, "XV_CONTRAST"}, 4318 {XvGettable | XvSettable, 0, 0x3ff, "XV_SATURATION"} 4319}; 4320 4321 4322/*************************************************************************** 4323// Function: XvMCQueryAttributes 4324// Description: An array of XvAttributes of size "number" is returned by 4325// this function. If there are no attributes, NULL is returned and number 4326// is set to 0. The array may be freed with xfree(). 4327// 4328// Arguments: 4329// display - Connection to the X server. 4330// context - The context whos attributes we are querying. 4331// number - The number of returned atoms. 4332// 4333// Returns: 4334// An array of XvAttributes. 4335// Notes: 4336// For i810 we support these Attributes: 4337// XV_COLORKEY: The colorkey value, initialized from the Xv value at 4338// context creation time. 4339// XV_BRIGHTNESS 4340// XV_CONTRAST 4341// XV_SATURATION 4342***************************************************************************/ 4343_X_EXPORT XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context, 4344 int *number) { 4345 i810XvMCContext *pI810XvMC; 4346 XvAttribute *attributes; 4347 4348 if(number == NULL) { 4349 return NULL; 4350 } 4351 if(display == NULL) { 4352 *number = 0; 4353 return NULL; 4354 } 4355 if(context == NULL) { 4356 *number = 0; 4357 return NULL; 4358 } 4359 pI810XvMC = context->privData; 4360 if(pI810XvMC == NULL) { 4361 *number = 0; 4362 return NULL; 4363 } 4364 4365 attributes = (XvAttribute *)malloc(NUM_XVMC_ATTRIBUTES * 4366 sizeof(XvAttribute)); 4367 if(attributes == NULL) { 4368 *number = 0; 4369 return NULL; 4370 } 4371 4372 memcpy(attributes,I810_XVMC_ATTRIBUTES,(NUM_XVMC_ATTRIBUTES * 4373 sizeof(XvAttribute))); 4374 4375 *number = NUM_XVMC_ATTRIBUTES; 4376 return attributes; 4377} 4378 4379/*************************************************************************** 4380// Function: XvMCSetAttribute 4381// Description: This function sets a context-specific attribute. 4382// 4383// Arguments: 4384// display - Connection to the X server. 4385// context - The context whos attributes we are querying. 4386// attribute - The X atom of the attribute to be changed. 4387// value - The new value for the attribute. 4388// 4389// Returns: 4390// Status 4391// Notes: 4392// For i810 we support these Attributes: 4393// XV_COLORKEY: The colorkey value, initialized from the Xv value at 4394// context creation time. 4395// XV_BRIGHTNESS 4396// XV_CONTRAST 4397// XV_SATURATION 4398***************************************************************************/ 4399_X_EXPORT Status XvMCSetAttribute(Display *display, XvMCContext *context, 4400 Atom attribute, int value) { 4401 i810XvMCContext *pI810XvMC; 4402 4403 if(display == NULL) { 4404 return BadValue; 4405 } 4406 if(context == NULL) { 4407 return (error_base + XvMCBadContext); 4408 } 4409 pI810XvMC = context->privData; 4410 if(pI810XvMC == NULL) { 4411 return (error_base + XvMCBadContext); 4412 } 4413 4414 if(attribute == pI810XvMC->xv_colorkey) { 4415 if((value < I810_XVMC_ATTRIBUTES[0].min_value) || 4416 (value > I810_XVMC_ATTRIBUTES[0].max_value)) { 4417 return BadValue; 4418 } 4419 pI810XvMC->colorkey = value; 4420 return Success; 4421 } 4422 if(attribute == pI810XvMC->xv_brightness) { 4423 if((value < I810_XVMC_ATTRIBUTES[1].min_value) || 4424 (value > I810_XVMC_ATTRIBUTES[1].max_value)) { 4425 return BadValue; 4426 } 4427 pI810XvMC->brightness = value; 4428 return Success; 4429 } 4430 if(attribute == pI810XvMC->xv_saturation) { 4431 if((value < I810_XVMC_ATTRIBUTES[2].min_value) || 4432 (value > I810_XVMC_ATTRIBUTES[2].max_value)) { 4433 return BadValue; 4434 } 4435 pI810XvMC->saturation = value; 4436 return Success; 4437 } 4438 if(attribute == pI810XvMC->xv_contrast) { 4439 if((value < I810_XVMC_ATTRIBUTES[3].min_value) || 4440 (value > I810_XVMC_ATTRIBUTES[3].max_value)) { 4441 return BadValue; 4442 } 4443 pI810XvMC->contrast = value; 4444 return Success; 4445 } 4446 return BadValue; 4447} 4448 4449/*************************************************************************** 4450// Function: XvMCGetAttribute 4451// Description: This function queries a context-specific attribute and 4452// returns the value. 4453// 4454// Arguments: 4455// display - Connection to the X server. 4456// context - The context whos attributes we are querying. 4457// attribute - The X atom of the attribute to be queried 4458// value - The returned attribute value 4459// 4460// Returns: 4461// Status 4462// Notes: 4463// For i810 we support these Attributes: 4464// XV_COLORKEY: The colorkey value, initialized from the Xv value at 4465// context creation time. 4466// XV_BRIGHTNESS 4467// XV_CONTRAST 4468// XV_SATURATION 4469***************************************************************************/ 4470_X_EXPORT Status XvMCGetAttribute(Display *display, XvMCContext *context, 4471 Atom attribute, int *value) { 4472 i810XvMCContext *pI810XvMC; 4473 4474 if(display == NULL) { 4475 return BadValue; 4476 } 4477 if(context == NULL) { 4478 return (error_base + XvMCBadContext); 4479 } 4480 pI810XvMC = context->privData; 4481 if(pI810XvMC == NULL) { 4482 return (error_base + XvMCBadContext); 4483 } 4484 if(value == NULL) { 4485 return BadValue; 4486 } 4487 4488 if(attribute == pI810XvMC->xv_colorkey) { 4489 *value = pI810XvMC->colorkey; 4490 return Success; 4491 } 4492 if(attribute == pI810XvMC->xv_brightness) { 4493 *value = pI810XvMC->brightness; 4494 return Success; 4495 } 4496 if(attribute == pI810XvMC->xv_saturation) { 4497 *value = pI810XvMC->saturation; 4498 return Success; 4499 } 4500 if(attribute == pI810XvMC->xv_contrast) { 4501 *value = pI810XvMC->contrast; 4502 return Success; 4503 } 4504 return BadValue; 4505} 4506 4507 4508 4509 4510