i915_hwmc.c revision fa225cbc
1/* 2 * Copyright © 2006 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Xiang Haihao <haihao.xiang@intel.com> 25 * 26 */ 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <string.h> 32 33#include "xf86.h" 34#include "xf86_OSproc.h" 35#include "compiler.h" 36#include "xf86PciInfo.h" 37#include "xf86Pci.h" 38#include "xf86fbman.h" 39#include "regionstr.h" 40 41#include "i830.h" 42#include "i830_dri.h" 43#include "i830_video.h" 44#include "xf86xv.h" 45#include "xf86xvmc.h" 46#include <X11/extensions/Xv.h> 47#include <X11/extensions/XvMC.h> 48#include "xaa.h" 49#include "xaalocal.h" 50#include "dixstruct.h" 51#include "fourcc.h" 52 53#if defined(X_NEED_XVPRIV_H) || defined (_XF86_FOURCC_H_) 54#include "xf86xvpriv.h" 55#endif 56 57#define _INTEL_XVMC_SERVER_ 58#include "i915_hwmc.h" 59 60#define I915_XVMC_MAX_BUFFERS 2 61#define I915_XVMC_MAX_CONTEXTS 4 62#define I915_XVMC_MAX_SURFACES 20 63 64typedef struct _I915XvMCSurfacePriv 65{ 66 i830_memory *surface; 67 unsigned long offsets[I915_XVMC_MAX_BUFFERS]; 68 drm_handle_t surface_handle; 69} I915XvMCSurfacePriv; 70 71typedef struct _I915XvMCContextPriv 72{ 73 i830_memory *mcStaticIndirectState; 74 drm_handle_t sis_handle; 75 i830_memory *mcSamplerState; 76 drm_handle_t ssb_handle; 77 i830_memory *mcMapState; 78 drm_handle_t msb_handle; 79 i830_memory *mcPixelShaderProgram; 80 drm_handle_t psp_handle; 81 i830_memory *mcPixelShaderConstants; 82 drm_handle_t psc_handle; 83 i830_memory *mcCorrdata; 84 drm_handle_t corrdata_handle; 85} I915XvMCContextPriv; 86 87typedef struct _I915XvMC 88{ 89 XID contexts[I915_XVMC_MAX_CONTEXTS]; 90 XID surfaces[I915_XVMC_MAX_SURFACES]; 91 I915XvMCSurfacePriv *sfprivs[I915_XVMC_MAX_SURFACES]; 92 I915XvMCContextPriv *ctxprivs[I915_XVMC_MAX_CONTEXTS]; 93 int ncontexts,nsurfaces; 94 PutImageFuncPtr savePutImage; 95} I915XvMC, *I915XvMCPtr; 96 97/* 98static int yv12_subpicture_index_list[2] = 99{ 100 FOURCC_IA44, 101 FOURCC_AI44 102}; 103 104static XF86MCImageIDList yv12_subpicture_list = 105{ 106 ARRARY_SIZE(yv12_subpicture_index_list), 107 yv12_subpicture_index_list 108}; 109 */ 110 111static XF86MCSurfaceInfoRec i915_YV12_mpg2_surface = 112{ 113 SURFACE_TYPE_MPEG2_MPML, 114 XVMC_CHROMA_FORMAT_420, 115 0, 116 720, 117 576, 118 720, 119 576, 120 XVMC_MPEG_2, 121 /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/ 122 0, 123 /* &yv12_subpicture_list*/ 124 NULL, 125}; 126 127static XF86MCSurfaceInfoRec i915_YV12_mpg1_surface = 128{ 129 SURFACE_TYPE_MPEG1_MPML, 130 XVMC_CHROMA_FORMAT_420, 131 0, 132 720, 133 576, 134 720, 135 576, 136 XVMC_MPEG_1, 137 /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/ 138 0, 139 /* &yv12_subpicture_list*/ 140 NULL, 141}; 142 143static XF86MCSurfaceInfoPtr ppSI[2] = 144{ 145 (XF86MCSurfaceInfoPtr)&i915_YV12_mpg2_surface, 146 (XF86MCSurfaceInfoPtr)&i915_YV12_mpg1_surface 147}; 148 149#if 0 150/* List of subpicture types that we support */ 151static XF86ImageRec ia44_subpicture = XVIMAGE_IA44; 152static XF86ImageRec ai44_subpicture = XVIMAGE_AI44; 153 154static XF86ImagePtr i915_subpicture_list[2] = 155{ 156 (XF86ImagePtr)&ia44_subpicture, 157 (XF86ImagePtr)&ai44_subpicture 158}; 159#endif 160 161/* Check context size not exceed surface type max */ 162static void 163i915_check_context_size(XvMCContextPtr ctx) 164{ 165 int i; 166 167 for (i = 0; i < ARRAY_SIZE(ppSI); i++) { 168 if (ctx->surface_type_id == ppSI[i]->surface_type_id) { 169 if (ctx->width > ppSI[i]->max_width) 170 ctx->width = ppSI[i]->max_width; 171 if (ctx->height > ppSI[i]->max_height) 172 ctx->height = ppSI[i]->max_height; 173 } 174 } 175} 176 177/* 178 * Init and clean up the screen private parts of XvMC. 179 */ 180static void initI915XvMC(I915XvMCPtr xvmc) 181{ 182 unsigned int i; 183 184 for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) { 185 xvmc->contexts[i] = 0; 186 xvmc->ctxprivs[i] = NULL; 187 } 188 189 for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) { 190 xvmc->surfaces[i] = 0; 191 xvmc->sfprivs[i] = NULL; 192 } 193 xvmc->ncontexts = 0; 194 xvmc->nsurfaces = 0; 195} 196 197static void cleanupI915XvMC(I915XvMCPtr xvmc) 198{ 199 int i; 200 201 for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) { 202 xvmc->contexts[i] = 0; 203 if (xvmc->ctxprivs[i]) { 204 xfree(xvmc->ctxprivs[i]); 205 xvmc->ctxprivs[i] = NULL; 206 } 207 } 208 209 for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) { 210 xvmc->surfaces[i] = 0; 211 if (xvmc->sfprivs[i]) { 212 xfree(xvmc->sfprivs[i]); 213 xvmc->sfprivs[i] = NULL; 214 } 215 } 216} 217 218static Bool i915_map_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv) 219{ 220 I830Ptr pI830 = I830PTR(pScrn); 221 222 if (drmAddMap(pI830->drmSubFD, 223 (drm_handle_t)(ctxpriv->mcStaticIndirectState->offset + pI830->LinearAddr), 224 ctxpriv->mcStaticIndirectState->size, DRM_AGP, 0, 225 (drmAddress)&ctxpriv->sis_handle) < 0) { 226 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 227 "[drm] drmAddMap(sis_handle) failed!\n"); 228 return FALSE; 229 } 230 231 if (drmAddMap(pI830->drmSubFD, 232 (drm_handle_t)(ctxpriv->mcSamplerState->offset + pI830->LinearAddr), 233 ctxpriv->mcSamplerState->size, DRM_AGP, 0, 234 (drmAddress)&ctxpriv->ssb_handle) < 0) { 235 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 236 "[drm] drmAddMap(ssb_handle) failed!\n"); 237 return FALSE; 238 } 239 240 if (drmAddMap(pI830->drmSubFD, 241 (drm_handle_t)(ctxpriv->mcMapState->offset + pI830->LinearAddr), 242 ctxpriv->mcMapState->size, DRM_AGP, 0, 243 (drmAddress)&ctxpriv->msb_handle) < 0) { 244 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 245 "[drm] drmAddMap(msb_handle) failed!\n"); 246 return FALSE; 247 } 248 249 if (drmAddMap(pI830->drmSubFD, 250 (drm_handle_t)(ctxpriv->mcPixelShaderProgram->offset + pI830->LinearAddr), 251 ctxpriv->mcPixelShaderProgram->size, DRM_AGP, 0, 252 (drmAddress)&ctxpriv->psp_handle) < 0) { 253 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 254 "[drm] drmAddMap(psp_handle) failed!\n"); 255 return FALSE; 256 } 257 258 if (drmAddMap(pI830->drmSubFD, 259 (drm_handle_t)(ctxpriv->mcPixelShaderConstants->offset + pI830->LinearAddr), 260 ctxpriv->mcPixelShaderConstants->size, DRM_AGP, 0, 261 (drmAddress)&ctxpriv->psc_handle) < 0) { 262 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 263 "[drm] drmAddMap(psc_handle) failed!\n"); 264 return FALSE; 265 } 266 267 if (drmAddMap(pI830->drmSubFD, 268 (drm_handle_t)(ctxpriv->mcCorrdata->offset + pI830->LinearAddr), 269 ctxpriv->mcCorrdata->size, DRM_AGP, 0, 270 (drmAddress)&ctxpriv->corrdata_handle) < 0) { 271 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 272 "[drm] drmAddMap(corrdata_handle) failed!\n"); 273 return FALSE; 274 } 275 276 277 return TRUE; 278} 279 280static void i915_unmap_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv) 281{ 282 I830Ptr pI830 = I830PTR(pScrn); 283 284 if (ctxpriv->sis_handle) { 285 drmRmMap(pI830->drmSubFD, ctxpriv->sis_handle); 286 ctxpriv->sis_handle = 0; 287 } 288 289 if (ctxpriv->ssb_handle) { 290 drmRmMap(pI830->drmSubFD, ctxpriv->ssb_handle); 291 ctxpriv->ssb_handle = 0; 292 } 293 294 if (ctxpriv->msb_handle) { 295 drmRmMap(pI830->drmSubFD, ctxpriv->msb_handle); 296 ctxpriv->msb_handle = 0; 297 } 298 299 if (ctxpriv->psp_handle) { 300 drmRmMap(pI830->drmSubFD, ctxpriv->psp_handle); 301 ctxpriv->psp_handle = 0; 302 } 303 304 if (ctxpriv->psc_handle) { 305 drmRmMap(pI830->drmSubFD, ctxpriv->psc_handle); 306 ctxpriv->psc_handle = 0; 307 } 308 309 if (ctxpriv->corrdata_handle) { 310 drmRmMap(pI830->drmSubFD, ctxpriv->corrdata_handle); 311 ctxpriv->corrdata_handle = 0; 312 } 313 314} 315 316static Bool i915_allocate_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv) 317{ 318 I830Ptr pI830 = I830PTR(pScrn); 319 int flags = ALIGN_BOTH_ENDS; 320 321 /* on 915G/GM, load indirect can only use physical address...sigh */ 322 if (IS_I915G(pI830) || IS_I915GM(pI830)) 323 flags |= NEED_PHYSICAL_ADDR; 324 325 if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Static Indirect State", 326 &(ctxpriv->mcStaticIndirectState), 4 * 1024, 327 flags)) { 328 return FALSE; 329 } 330 331 if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Sampler State", 332 &(ctxpriv->mcSamplerState), 4 * 1024, 333 flags)) { 334 return FALSE; 335 } 336 337 if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Map State", 338 &(ctxpriv->mcMapState), 4 * 1024, 339 flags)) { 340 return FALSE; 341 } 342 343 if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Pixel Shader Program", 344 &(ctxpriv->mcPixelShaderProgram), 4 * 1024, 345 flags)) { 346 return FALSE; 347 } 348 349 if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Pixel Shader Constants", 350 &(ctxpriv->mcPixelShaderConstants), 4 * 1024, 351 flags)) { 352 return FALSE; 353 } 354 355 if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Correction Data Buffer", 356 &(ctxpriv->mcCorrdata), 512 * 1024, 357 ALIGN_BOTH_ENDS)) { 358 return FALSE; 359 } 360 361 if (1) 362 i830_describe_allocations(pScrn, 1, "i915_mc: "); 363 364 return TRUE; 365} 366 367static void i915_free_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv) 368{ 369 if (ctxpriv->mcStaticIndirectState) { 370 i830_free_xvmc_buffer(pScrn, ctxpriv->mcStaticIndirectState); 371 ctxpriv->mcStaticIndirectState = NULL; 372 } 373 374 if (ctxpriv->mcSamplerState) { 375 i830_free_xvmc_buffer(pScrn, ctxpriv->mcSamplerState); 376 ctxpriv->mcSamplerState = NULL; 377 } 378 379 if (ctxpriv->mcMapState) { 380 i830_free_xvmc_buffer(pScrn, ctxpriv->mcMapState); 381 ctxpriv->mcMapState = NULL; 382 } 383 384 if (ctxpriv->mcPixelShaderProgram) { 385 i830_free_xvmc_buffer(pScrn, ctxpriv->mcPixelShaderProgram); 386 ctxpriv->mcPixelShaderProgram = NULL; 387 } 388 389 if (ctxpriv->mcPixelShaderConstants) { 390 i830_free_xvmc_buffer(pScrn, ctxpriv->mcPixelShaderConstants); 391 ctxpriv->mcPixelShaderConstants = NULL; 392 } 393 394 if (ctxpriv->mcCorrdata) { 395 i830_free_xvmc_buffer(pScrn, ctxpriv->mcCorrdata); 396 ctxpriv->mcCorrdata = NULL; 397 } 398 399} 400 401/* 402 * i915_xvmc_create_context 403 * 404 * Some info about the private data: 405 * 406 * Set *num_priv to the number of 32bit words that make up the size of 407 * of the data that priv will point to. 408 * 409 * *priv = (long *) xcalloc (elements, sizeof(element)) 410 * *num_priv = (elements * sizeof(element)) >> 2; 411 * 412 **************************************************************************/ 413 414static int i915_xvmc_create_context (ScrnInfoPtr pScrn, XvMCContextPtr pContext, 415 int *num_priv, long **priv ) 416{ 417 I830Ptr pI830 = I830PTR(pScrn); 418 I915XvMCCreateContextRec *contextRec = NULL; 419 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 420 I915XvMCContextPriv *ctxpriv = NULL; 421 int i; 422 423 *priv = NULL; 424 *num_priv = 0; 425 426 if (!pI830->XvMCEnabled) { 427 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 428 "[XvMC] i915: XvMC disabled!\n"); 429 return BadAlloc; 430 } 431 432 for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) { 433 if (!pXvMC->contexts[i]) 434 break; 435 } 436 437 if (i == I915_XVMC_MAX_CONTEXTS || 438 pXvMC->ncontexts >= I915_XVMC_MAX_CONTEXTS) { 439 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 440 "[XvMC] i915: Out of contexts.\n"); 441 return BadAlloc; 442 } 443 444 i915_check_context_size(pContext); 445 446 *priv = xcalloc(1, sizeof(I915XvMCCreateContextRec)); 447 contextRec = (I915XvMCCreateContextRec *)*priv; 448 449 if (!*priv) { 450 *num_priv = 0; 451 return BadAlloc; 452 } 453 454 *num_priv = sizeof(I915XvMCCreateContextRec) >> 2; 455 456 ctxpriv = (I915XvMCContextPriv *)xcalloc(1, sizeof(I915XvMCContextPriv)); 457 458 if (!ctxpriv) { 459 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 460 "[XvMC] i915: Unable to allocate memory!\n"); 461 xfree(*priv); 462 *priv = NULL; 463 *num_priv = 0; 464 return BadAlloc; 465 } 466 467 if (!i915_allocate_xvmc_buffers(pScrn, ctxpriv)) { 468 i915_free_xvmc_buffers(pScrn, ctxpriv); 469 xfree(ctxpriv); 470 ctxpriv = NULL; 471 xfree(*priv); 472 *priv = NULL; 473 *num_priv = 0; 474 return BadAlloc; 475 } 476 477 if (!i915_map_xvmc_buffers(pScrn, ctxpriv)) { 478 i915_unmap_xvmc_buffers(pScrn, ctxpriv); 479 i915_free_xvmc_buffers(pScrn, ctxpriv); 480 xfree(ctxpriv); 481 ctxpriv = NULL; 482 xfree(*priv); 483 *priv = NULL; 484 *num_priv = 0; 485 return BadAlloc; 486 } 487 488 /* common context items */ 489 contextRec->comm.type = xvmc_driver->flag; 490 contextRec->comm.batchbuffer.offset = xvmc_driver->batch->offset; 491 contextRec->comm.batchbuffer.size = xvmc_driver->batch->size; 492 contextRec->comm.batchbuffer.handle = xvmc_driver->batch_handle; 493 494 /* i915 private context */ 495 contextRec->ctxno = i; 496 contextRec->sis.handle = ctxpriv->sis_handle; 497 contextRec->sis.offset = ctxpriv->mcStaticIndirectState->offset; 498 contextRec->sis.size = ctxpriv->mcStaticIndirectState->size; 499 contextRec->ssb.handle = ctxpriv->ssb_handle; 500 contextRec->ssb.offset = ctxpriv->mcSamplerState->offset; 501 contextRec->ssb.size = ctxpriv->mcSamplerState->size; 502 contextRec->msb.handle = ctxpriv->msb_handle; 503 contextRec->msb.offset = ctxpriv->mcMapState->offset; 504 contextRec->msb.size = ctxpriv->mcMapState->size; 505 contextRec->psp.handle = ctxpriv->psp_handle; 506 contextRec->psp.offset = ctxpriv->mcPixelShaderProgram->offset; 507 contextRec->psp.size = ctxpriv->mcPixelShaderProgram->size; 508 contextRec->psc.handle = ctxpriv->psc_handle; 509 contextRec->psc.offset = ctxpriv->mcPixelShaderConstants->offset; 510 contextRec->psc.size = ctxpriv->mcPixelShaderConstants->size; 511 contextRec->corrdata.handle = ctxpriv->corrdata_handle; 512 contextRec->corrdata.offset = ctxpriv->mcCorrdata->offset; 513 contextRec->corrdata.size = ctxpriv->mcCorrdata->size; 514 contextRec->deviceID = DEVICE_ID(pI830->PciInfo); 515 516 if (IS_I915G(pI830) || IS_I915GM(pI830)) { 517 contextRec->sis.bus_addr = ctxpriv->mcStaticIndirectState->bus_addr; 518 contextRec->ssb.bus_addr = ctxpriv->mcSamplerState->bus_addr; 519 contextRec->msb.bus_addr = ctxpriv->mcMapState->bus_addr; 520 contextRec->psp.bus_addr = ctxpriv->mcPixelShaderProgram->bus_addr; 521 contextRec->psc.bus_addr = ctxpriv->mcPixelShaderConstants->bus_addr; 522 } 523 524 pXvMC->ncontexts++; 525 pXvMC->contexts[i] = pContext->context_id; 526 pXvMC->ctxprivs[i] = ctxpriv; 527 528 return Success; 529} 530 531static int i915_xvmc_create_surface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf, 532 int *num_priv, long **priv ) 533{ 534 I830Ptr pI830 = I830PTR(pScrn); 535 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 536 I915XvMCSurfacePriv *sfpriv = NULL; 537 I915XvMCCreateSurfaceRec *surfaceRec = NULL; 538 XvMCContextPtr ctx = NULL; 539 unsigned int srfno; 540 unsigned long bufsize; 541 542 if (!pI830->XvMCEnabled) { 543 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 544 "[XvMC] i915: XvMC disabled!\n"); 545 return BadAlloc; 546 } 547 548 *priv = NULL; 549 *num_priv = 0; 550 551 for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) { 552 if (!pXvMC->surfaces[srfno]) 553 break; 554 } 555 556 if (srfno == I915_XVMC_MAX_SURFACES || 557 pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) { 558 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 559 "[XvMC] i915: Too many surfaces !\n"); 560 return BadAlloc; 561 } 562 563 *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec)); 564 surfaceRec = (I915XvMCCreateSurfaceRec *)*priv; 565 566 if (!*priv) { 567 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 568 "[XvMC] i915:Unable to allocate surface priv ret memory!\n"); 569 return BadAlloc; 570 } 571 572 *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2; 573 sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv)); 574 575 if (!sfpriv) { 576 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 577 "[XvMC] i915: Unable to allocate surface priv memory!\n"); 578 xfree(*priv); 579 *priv = NULL; 580 *num_priv = 0; 581 return BadAlloc; 582 } 583 584 ctx = pSurf->context; 585 bufsize = SIZE_YUV420(ctx->width, ctx->height); 586 587 if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface", 588 &(sfpriv->surface), bufsize, 589 ALIGN_BOTH_ENDS)) { 590 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 591 "[XvMC] i915 : Failed to allocate XvMC surface space!\n"); 592 xfree(sfpriv); 593 xfree(*priv); 594 *priv = NULL; 595 *num_priv = 0; 596 return BadAlloc; 597 } 598 599 if (0) 600 i830_describe_allocations(pScrn, 1, ""); 601 602 if (drmAddMap(pI830->drmSubFD, 603 (drm_handle_t)(sfpriv->surface->offset + pI830->LinearAddr), 604 sfpriv->surface->size, DRM_AGP, 0, 605 (drmAddress)&sfpriv->surface_handle) < 0) { 606 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 607 "[drm] drmAddMap(surface_handle) failed!\n"); 608 i830_free_xvmc_buffer(pScrn, sfpriv->surface); 609 xfree(sfpriv); 610 xfree(*priv); 611 *priv = NULL; 612 *num_priv = 0; 613 return BadAlloc; 614 } 615 616 surfaceRec->srfno = srfno; 617 surfaceRec->srf.handle = sfpriv->surface_handle; 618 surfaceRec->srf.offset = sfpriv->surface->offset; 619 surfaceRec->srf.size = sfpriv->surface->size; 620 621 pXvMC->surfaces[srfno] = pSurf->surface_id; 622 pXvMC->sfprivs[srfno]= sfpriv; 623 pXvMC->nsurfaces++; 624 625 return Success; 626} 627 628static int i915_xvmc_create_subpict(ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp, 629 int *num_priv, long **priv ) 630{ 631 I830Ptr pI830 = I830PTR(pScrn); 632 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 633 I915XvMCSurfacePriv *sfpriv = NULL; 634 I915XvMCCreateSurfaceRec *surfaceRec = NULL; 635 XvMCContextPtr ctx = NULL; 636 unsigned int srfno; 637 unsigned int bufsize; 638 639 *priv = NULL; 640 *num_priv = 0; 641 642 for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) { 643 if (!pXvMC->surfaces[srfno]) 644 break; 645 } 646 647 if (srfno == I915_XVMC_MAX_SURFACES || 648 pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) { 649 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 650 "[XvMC] i915: Too many surfaces !\n"); 651 return BadAlloc; 652 } 653 654 *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec)); 655 surfaceRec = (I915XvMCCreateSurfaceRec *)*priv; 656 657 if (!*priv) { 658 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 659 "[XvMC] i915: Unable to allocate memory!\n"); 660 return BadAlloc; 661 } 662 663 *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2; 664 sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv)); 665 666 if (!sfpriv) { 667 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 668 "[XvMC] i915: Unable to allocate memory!\n"); 669 xfree(*priv); 670 *priv = NULL; 671 *num_priv = 0; 672 return BadAlloc; 673 } 674 675 ctx = pSubp->context; 676 bufsize = SIZE_XX44(ctx->width, ctx->height); 677 678 if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface", 679 &(sfpriv->surface), bufsize, 680 ALIGN_BOTH_ENDS)) { 681 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 682 "[XvMC] I915XvMCCreateSurface: Failed to allocate XvMC surface space!\n"); 683 xfree(sfpriv); 684 xfree(*priv); 685 *priv = NULL; 686 *num_priv = 0; 687 return BadAlloc; 688 } 689 690 if (drmAddMap(pI830->drmSubFD, 691 (drm_handle_t)(sfpriv->surface->offset + pI830->LinearAddr), 692 sfpriv->surface->size, DRM_AGP, 0, 693 (drmAddress)&sfpriv->surface_handle) < 0) { 694 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 695 "[drm] drmAddMap(surface_handle) failed!\n"); 696 i830_free_xvmc_buffer(pScrn, sfpriv->surface); 697 xfree(sfpriv); 698 xfree(*priv); 699 *priv = NULL; 700 *num_priv = 0; 701 return BadAlloc; 702 } 703 704 surfaceRec->srfno = srfno; 705 surfaceRec->srf.handle = sfpriv->surface_handle; 706 surfaceRec->srf.offset = sfpriv->surface->offset; 707 surfaceRec->srf.size = sfpriv->surface->size; 708 709 pXvMC->sfprivs[srfno] = sfpriv; 710 pXvMC->surfaces[srfno] = pSubp->subpicture_id; 711 pXvMC->nsurfaces++; 712 713 return Success; 714} 715 716static void i915_xvmc_destroy_context (ScrnInfoPtr pScrn, 717 XvMCContextPtr pContext) 718{ 719 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 720 int i; 721 722 for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) { 723 if (pXvMC->contexts[i] == pContext->context_id) { 724 i915_unmap_xvmc_buffers(pScrn, pXvMC->ctxprivs[i]); 725 i915_free_xvmc_buffers(pScrn, pXvMC->ctxprivs[i]); 726 xfree(pXvMC->ctxprivs[i]); 727 pXvMC->ctxprivs[i] = 0; 728 pXvMC->ncontexts--; 729 pXvMC->contexts[i] = 0; 730 return; 731 } 732 } 733 734 return; 735} 736 737static void i915_xvmc_destroy_surface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf) 738{ 739 I830Ptr pI830 = I830PTR(pScrn); 740 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 741 int i; 742 743 for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) { 744 if (pXvMC->surfaces[i] == pSurf->surface_id) { 745 drmRmMap(pI830->drmSubFD, pXvMC->sfprivs[i]->surface_handle); 746 i830_free_xvmc_buffer(pScrn, pXvMC->sfprivs[i]->surface); 747 xfree(pXvMC->sfprivs[i]); 748 pXvMC->nsurfaces--; 749 pXvMC->sfprivs[i] = 0; 750 pXvMC->surfaces[i] = 0; 751 return; 752 } 753 } 754 755 return; 756} 757 758static void i915_xvmc_destroy_subpict (ScrnInfoPtr pScrn, 759 XvMCSubpicturePtr pSubp) 760{ 761 I830Ptr pI830 = I830PTR(pScrn); 762 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 763 int i; 764 765 for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) { 766 if (pXvMC->surfaces[i] == pSubp->subpicture_id) { 767 drmRmMap(pI830->drmSubFD, pXvMC->sfprivs[i]->surface_handle); 768 i830_free_xvmc_buffer(pScrn, pXvMC->sfprivs[i]->surface); 769 xfree(pXvMC->sfprivs[i]); 770 pXvMC->nsurfaces--; 771 pXvMC->sfprivs[i] = 0; 772 pXvMC->surfaces[i] = 0; 773 return; 774 } 775 } 776 777 return; 778} 779 780static int i915_xvmc_put_image(ScrnInfoPtr pScrn, 781 short src_x, short src_y, 782 short drw_x, short drw_y, short src_w, 783 short src_h, short drw_w, short drw_h, 784 int id, unsigned char *buf, short width, 785 short height, Bool sync, RegionPtr clipBoxes, pointer data, 786 DrawablePtr pDraw) 787{ 788 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 789 struct intel_xvmc_command *xvmc_cmd = (struct intel_xvmc_command *)buf; 790 int ret; 791 792 if (FOURCC_XVMC == id) { 793 switch (xvmc_cmd->command) { 794 case INTEL_XVMC_COMMAND_DISPLAY: 795 if ((xvmc_cmd->srfNo >= I915_XVMC_MAX_SURFACES) || 796 !pXvMC->surfaces[xvmc_cmd->srfNo] || 797 !pXvMC->sfprivs[xvmc_cmd->srfNo]) { 798 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 799 "[XvMC] i915 put image: Invalid parameters!\n"); 800 return 1; 801 } 802 803 /* use char *buf to hold our surface offset...hacky! */ 804 buf = (unsigned char *)pXvMC->sfprivs[xvmc_cmd->srfNo]->surface->offset; 805 break; 806 default: 807 return 0; 808 } 809 } 810 811 ret = pXvMC->savePutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h, 812 drw_w, drw_h, id, buf, width, height, sync, clipBoxes, 813 data, pDraw); 814 return ret; 815} 816 817static Bool i915_xvmc_init(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr XvAdapt) 818{ 819 I915XvMCPtr pXvMC; 820 821 pXvMC = (I915XvMCPtr)xcalloc(1, sizeof(I915XvMC)); 822 if (!pXvMC) { 823 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 824 "[XvMC] alloc driver private failed!\n"); 825 return FALSE; 826 } 827 xvmc_driver->devPrivate = (void*)pXvMC; 828 if (!intel_xvmc_init_batch(pScrn)) { 829 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 830 "[XvMC] fail to init batch buffer\n"); 831 xfree(pXvMC); 832 return FALSE; 833 } 834 initI915XvMC(pXvMC); 835 836 /* set up wrappers */ 837 pXvMC->savePutImage = XvAdapt->PutImage; 838 XvAdapt->PutImage = i915_xvmc_put_image; 839 return TRUE; 840} 841 842static void i915_xvmc_fini(ScrnInfoPtr pScrn) 843{ 844 I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; 845 846 cleanupI915XvMC(pXvMC); 847 intel_xvmc_fini_batch(pScrn); 848 xfree(xvmc_driver->devPrivate); 849} 850 851/* Fill in the device dependent adaptor record. 852 * This is named "Intel(R) Textured Video" because this code falls under the 853 * XV extenstion, the name must match or it won't be used. 854 * 855 * Surface and Subpicture - see above 856 * Function pointers to functions below 857 */ 858static XF86MCAdaptorRec pAdapt = 859{ 860 .name = "Intel(R) Textured Video", 861 .num_surfaces = ARRAY_SIZE(ppSI), 862 .surfaces = ppSI, 863#if 0 864 .num_subpictures = ARRARY_SIZE(i915_subpicture_list), 865 .subpictures = i915_subpicture_list, 866#endif 867 .num_subpictures = 0, 868 .subpictures = NULL, 869 .CreateContext = (xf86XvMCCreateContextProcPtr) i915_xvmc_create_context, 870 .DestroyContext = (xf86XvMCDestroyContextProcPtr) i915_xvmc_destroy_context, 871 .CreateSurface = (xf86XvMCCreateSurfaceProcPtr) i915_xvmc_create_surface, 872 .DestroySurface = (xf86XvMCDestroySurfaceProcPtr) i915_xvmc_destroy_surface, 873 .CreateSubpicture = (xf86XvMCCreateSubpictureProcPtr) i915_xvmc_create_subpict, 874 .DestroySubpicture = (xf86XvMCDestroySubpictureProcPtr) i915_xvmc_destroy_subpict, 875}; 876 877/* new xvmc driver interface */ 878struct intel_xvmc_driver i915_xvmc_driver = { 879 .name = "i915_xvmc", 880 .adaptor = &pAdapt, 881 .flag = XVMC_I915_MPEG2_MC, 882 .init = i915_xvmc_init, 883 .fini = i915_xvmc_fini, 884}; 885