i915_hwmc.c 26.1 KB
Newer Older
Haihao Xiang's avatar
Haihao Xiang committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright © 2006 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *    Xiang Haihao <haihao.xiang@intel.com>
 *
 */
Haihao Xiang's avatar
Haihao Xiang committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>

#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86fbman.h"
#include "regionstr.h"

#include "i830.h"
#include "i830_dri.h"
#include "i830_video.h"
#include "xf86xv.h"
#include "xf86xvmc.h"
#include <X11/extensions/Xv.h>
#include <X11/extensions/XvMC.h>
#include "xaa.h"
#include "xaalocal.h"
#include "dixstruct.h"
#include "fourcc.h"

#if defined(X_NEED_XVPRIV_H) || defined (_XF86_FOURCC_H_)
#include "xf86xvpriv.h"
#endif

58
#define _INTEL_XVMC_SERVER_
Haihao Xiang's avatar
Haihao Xiang committed
59 60 61 62 63 64 65 66 67 68
#include "i915_hwmc.h"

#define I915_XVMC_MAX_BUFFERS 2
#define I915_XVMC_MAX_CONTEXTS 4
#define I915_XVMC_MAX_SURFACES 20

typedef struct _I915XvMCSurfacePriv
{
    i830_memory *surface;
    unsigned long offsets[I915_XVMC_MAX_BUFFERS];
Haihao Xiang's avatar
Haihao Xiang committed
69
    drm_handle_t surface_handle;
Haihao Xiang's avatar
Haihao Xiang committed
70 71 72 73
} I915XvMCSurfacePriv;

typedef struct _I915XvMCContextPriv
{
root's avatar
root committed
74 75 76 77 78 79 80 81 82 83
    i830_memory *mcStaticIndirectState;
    drm_handle_t sis_handle;
    i830_memory *mcSamplerState;
    drm_handle_t ssb_handle;
    i830_memory *mcMapState;
    drm_handle_t msb_handle;
    i830_memory *mcPixelShaderProgram;
    drm_handle_t psp_handle;
    i830_memory *mcPixelShaderConstants;
    drm_handle_t psc_handle;
Haihao Xiang's avatar
Haihao Xiang committed
84 85 86 87
    i830_memory *mcCorrdata;
    drm_handle_t corrdata_handle;
} I915XvMCContextPriv;

Zhenyu Wang's avatar
Zhenyu Wang committed
88
typedef struct _I915XvMC
Haihao Xiang's avatar
Haihao Xiang committed
89 90 91 92 93 94
{
    XID contexts[I915_XVMC_MAX_CONTEXTS];
    XID surfaces[I915_XVMC_MAX_SURFACES];
    I915XvMCSurfacePriv *sfprivs[I915_XVMC_MAX_SURFACES];
    I915XvMCContextPriv *ctxprivs[I915_XVMC_MAX_CONTEXTS];
    int ncontexts,nsurfaces;
Zhenyu Wang's avatar
Zhenyu Wang committed
95
    PutImageFuncPtr savePutImage;
Haihao Xiang's avatar
Haihao Xiang committed
96 97 98 99
} I915XvMC, *I915XvMCPtr;

#define ARRARY_SIZE(a) (sizeof(a) / sizeof(a[0]))

100
/*
Zhenyu Wang's avatar
Zhenyu Wang committed
101
static int yv12_subpicture_index_list[2] =
Haihao Xiang's avatar
Haihao Xiang committed
102 103 104 105 106 107 108 109 110 111
{
    FOURCC_IA44,
    FOURCC_AI44
};

static XF86MCImageIDList yv12_subpicture_list =
{
    ARRARY_SIZE(yv12_subpicture_index_list),
    yv12_subpicture_index_list
};
112
 */
Zhenyu Wang's avatar
Zhenyu Wang committed
113

Haihao Xiang's avatar
Haihao Xiang committed
114 115
static XF86MCSurfaceInfoRec i915_YV12_mpg2_surface =
{
Zhenyu Wang's avatar
Zhenyu Wang committed
116
    FOURCC_YV12,
Haihao Xiang's avatar
Haihao Xiang committed
117 118 119 120 121 122 123
    XVMC_CHROMA_FORMAT_420,
    0,
    720,
    576,
    720,
    576,
    XVMC_MPEG_2,
Zhenyu Wang's avatar
Zhenyu Wang committed
124 125 126 127
    /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/
    0,
    /* &yv12_subpicture_list*/
    NULL,
Haihao Xiang's avatar
Haihao Xiang committed
128 129 130 131
};

static XF86MCSurfaceInfoRec i915_YV12_mpg1_surface =
{
Zhenyu Wang's avatar
Zhenyu Wang committed
132
    FOURCC_YV12,
Haihao Xiang's avatar
Haihao Xiang committed
133 134 135 136 137 138 139
    XVMC_CHROMA_FORMAT_420,
    0,
    720,
    576,
    720,
    576,
    XVMC_MPEG_1,
Zhenyu Wang's avatar
Zhenyu Wang committed
140 141 142 143
    /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/
    0,
    /* &yv12_subpicture_list*/
    NULL,
Haihao Xiang's avatar
Haihao Xiang committed
144 145
};

Zhenyu Wang's avatar
Zhenyu Wang committed
146
static XF86MCSurfaceInfoPtr ppSI[2] =
Haihao Xiang's avatar
Haihao Xiang committed
147 148 149 150 151
{
    (XF86MCSurfaceInfoPtr)&i915_YV12_mpg2_surface,
    (XF86MCSurfaceInfoPtr)&i915_YV12_mpg1_surface
};

152
#if 0
Haihao Xiang's avatar
Haihao Xiang committed
153 154 155 156 157 158 159 160 161
/* List of subpicture types that we support */
static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;

static XF86ImagePtr i915_subpicture_list[2] =
{
    (XF86ImagePtr)&ia44_subpicture,
    (XF86ImagePtr)&ai44_subpicture
};
162
#endif
Haihao Xiang's avatar
Haihao Xiang committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

/*
 * Init and clean up the screen private parts of XvMC.
 */
static void initI915XvMC(I915XvMCPtr xvmc)
{
    unsigned int i;

    for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
        xvmc->contexts[i] = 0;
        xvmc->ctxprivs[i] = NULL;
    }

    for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
        xvmc->surfaces[i] = 0;
        xvmc->sfprivs[i] = NULL;
    }
180 181
    xvmc->ncontexts = 0;
    xvmc->nsurfaces = 0;
Haihao Xiang's avatar
Haihao Xiang committed
182 183
}

184
static void cleanupI915XvMC(I915XvMCPtr xvmc)
Haihao Xiang's avatar
Haihao Xiang committed
185
{
186
    int i;
Haihao Xiang's avatar
Haihao Xiang committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

    for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
        xvmc->contexts[i] = 0;
        if (xvmc->ctxprivs[i]) {
            xfree(xvmc->ctxprivs[i]);
            xvmc->ctxprivs[i] = NULL;
        }
    }

    for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
        xvmc->surfaces[i] = 0;
        if (xvmc->sfprivs[i]) {
            xfree(xvmc->sfprivs[i]);
            xvmc->sfprivs[i] = NULL;
        }
    }
}

static Bool i915_map_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
{
    I830Ptr pI830 = I830PTR(pScrn);

    if (drmAddMap(pI830->drmSubFD,
root's avatar
root committed
210 211 212
                  (drm_handle_t)(ctxpriv->mcStaticIndirectState->offset + pI830->LinearAddr),
                  ctxpriv->mcStaticIndirectState->size, DRM_AGP, 0,
                  (drmAddress)&ctxpriv->sis_handle) < 0) {
Haihao Xiang's avatar
Haihao Xiang committed
213
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
root's avatar
root committed
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
                   "[drm] drmAddMap(sis_handle) failed!\n");
        return FALSE;
    }

    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(ctxpriv->mcSamplerState->offset + pI830->LinearAddr),
                  ctxpriv->mcSamplerState->size, DRM_AGP, 0,
                  (drmAddress)&ctxpriv->ssb_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(ssb_handle) failed!\n");
        return FALSE;
    }

    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(ctxpriv->mcMapState->offset + pI830->LinearAddr),
                  ctxpriv->mcMapState->size, DRM_AGP, 0,
                  (drmAddress)&ctxpriv->msb_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(msb_handle) failed!\n");
        return FALSE;
    }

    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(ctxpriv->mcPixelShaderProgram->offset + pI830->LinearAddr),
                  ctxpriv->mcPixelShaderProgram->size, DRM_AGP, 0,
                  (drmAddress)&ctxpriv->psp_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(psp_handle) failed!\n");
        return FALSE;
    }

    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(ctxpriv->mcPixelShaderConstants->offset + pI830->LinearAddr),
                  ctxpriv->mcPixelShaderConstants->size, DRM_AGP, 0,
                  (drmAddress)&ctxpriv->psc_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(psc_handle) failed!\n");
Haihao Xiang's avatar
Haihao Xiang committed
251 252 253 254 255 256 257 258 259 260 261 262
        return FALSE;
    }

    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(ctxpriv->mcCorrdata->offset + pI830->LinearAddr),
                  ctxpriv->mcCorrdata->size, DRM_AGP, 0,
                  (drmAddress)&ctxpriv->corrdata_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(corrdata_handle) failed!\n");
        return FALSE;
    }

root's avatar
root committed
263
        
Haihao Xiang's avatar
Haihao Xiang committed
264 265 266 267 268 269 270
    return TRUE;
}

static void i915_unmap_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
{
    I830Ptr pI830 = I830PTR(pScrn);
    
root's avatar
root committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
    if (ctxpriv->sis_handle) {
        drmRmMap(pI830->drmSubFD, ctxpriv->sis_handle);
        ctxpriv->sis_handle = 0;
    }

    if (ctxpriv->ssb_handle) {
        drmRmMap(pI830->drmSubFD, ctxpriv->ssb_handle);
        ctxpriv->ssb_handle = 0;
    }

    if (ctxpriv->msb_handle) {
        drmRmMap(pI830->drmSubFD, ctxpriv->msb_handle);
        ctxpriv->msb_handle = 0;
    }

    if (ctxpriv->psp_handle) {
        drmRmMap(pI830->drmSubFD, ctxpriv->psp_handle);
        ctxpriv->psp_handle = 0;
    }

    if (ctxpriv->psc_handle) {
        drmRmMap(pI830->drmSubFD, ctxpriv->psc_handle);
        ctxpriv->psc_handle = 0;
Haihao Xiang's avatar
Haihao Xiang committed
294 295 296 297 298 299
    }

    if (ctxpriv->corrdata_handle) {
        drmRmMap(pI830->drmSubFD, ctxpriv->corrdata_handle);
        ctxpriv->corrdata_handle = 0;
    }
root's avatar
root committed
300

Haihao Xiang's avatar
Haihao Xiang committed
301 302 303 304
}

static Bool i915_allocate_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
{
root's avatar
root committed
305
    I830Ptr pI830 = I830PTR(pScrn);
306
    int flags = ALIGN_BOTH_ENDS;
307 308 309 310 311

    if (IS_I915G(pI830) || IS_I915GM(pI830) ||
	    IS_I945G(pI830) || IS_I945GM(pI830))
        flags |= NEED_PHYSICAL_ADDR;

root's avatar
root committed
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Static Indirect State",
                                  &(ctxpriv->mcStaticIndirectState), 4 * 1024,
                                  flags)) {
        return FALSE;
    }

    if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Sampler State",
                                  &(ctxpriv->mcSamplerState), 4 * 1024,
                                  flags)) {
        return FALSE;
    }

    if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Map State",
                                  &(ctxpriv->mcMapState), 4 * 1024,
                                  flags)) {
        return FALSE;
    }

    if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Pixel Shader Program",
                                  &(ctxpriv->mcPixelShaderProgram), 4 * 1024,
                                  flags)) {
        return FALSE;
    }

    if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Pixel Shader Constants",
                                  &(ctxpriv->mcPixelShaderConstants), 4 * 1024,
                                  flags)) {
        return FALSE;
    }

    if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Correction Data Buffer", 
                                   &(ctxpriv->mcCorrdata), 512 * 1024,
344
                                   ALIGN_BOTH_ENDS)) {
Haihao Xiang's avatar
Haihao Xiang committed
345 346 347
        return FALSE;
    }

Zhenyu Wang's avatar
Zhenyu Wang committed
348 349
    if (0)
	i830_describe_allocations(pScrn, 1, "");
Haihao Xiang's avatar
Haihao Xiang committed
350 351 352 353 354 355

    return TRUE;
}

static void i915_free_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
{
root's avatar
root committed
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
    if (ctxpriv->mcStaticIndirectState) {
        i830_free_memory(pScrn, ctxpriv->mcStaticIndirectState);
        ctxpriv->mcStaticIndirectState = NULL;
    }

    if (ctxpriv->mcSamplerState) {
        i830_free_memory(pScrn, ctxpriv->mcSamplerState);
        ctxpriv->mcSamplerState = NULL;
    }

    if (ctxpriv->mcMapState) {
        i830_free_memory(pScrn, ctxpriv->mcMapState);
        ctxpriv->mcMapState = NULL;
    }

    if (ctxpriv->mcPixelShaderProgram) {
        i830_free_memory(pScrn, ctxpriv->mcPixelShaderProgram);
        ctxpriv->mcPixelShaderProgram = NULL;
    }

    if (ctxpriv->mcPixelShaderConstants) {
        i830_free_memory(pScrn, ctxpriv->mcPixelShaderConstants);
        ctxpriv->mcPixelShaderConstants = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
379 380 381 382 383 384
    }

    if (ctxpriv->mcCorrdata) {
        i830_free_memory(pScrn, ctxpriv->mcCorrdata);
        ctxpriv->mcCorrdata = NULL;
    }
root's avatar
root committed
385

Haihao Xiang's avatar
Haihao Xiang committed
386 387
}

Zhenyu Wang's avatar
Zhenyu Wang committed
388 389
/*
 *  i915_xvmc_create_context
Haihao Xiang's avatar
Haihao Xiang committed
390 391 392 393 394 395 396 397 398 399 400
 *
 *  Some info about the private data:
 *
 *  Set *num_priv to the number of 32bit words that make up the size of
 *  of the data that priv will point to.
 *
 *  *priv = (long *) xcalloc (elements, sizeof(element))
 *  *num_priv = (elements * sizeof(element)) >> 2;
 *
 **************************************************************************/

Zhenyu Wang's avatar
Zhenyu Wang committed
401
static int i915_xvmc_create_context (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
Haihao Xiang's avatar
Haihao Xiang committed
402 403 404 405
                                  int *num_priv, long **priv )
{
    I830Ptr pI830 = I830PTR(pScrn);
    DRIInfoPtr pDRIInfo = pI830->pDRIInfo;
root's avatar
root committed
406
    I830DRIPtr pI830DRI = pDRIInfo->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
407
    I915XvMCCreateContextRec *contextRec = NULL;
408
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
409 410 411 412 413 414
    I915XvMCContextPriv *ctxpriv = NULL;
    int i;

    *priv = NULL;
    *num_priv = 0;

Zhenyu Wang's avatar
Zhenyu Wang committed
415
    if (!pI830->XvMCEnabled) {
Haihao Xiang's avatar
Haihao Xiang committed
416
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
417
                   "[XvMC] i915: XvMC disabled!\n");
Haihao Xiang's avatar
Haihao Xiang committed
418 419 420
        return BadAlloc;
    }

421 422 423 424 425
    for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
        if (!pXvMC->contexts[i])
            break;
    }

Zhenyu Wang's avatar
Zhenyu Wang committed
426
    if (i == I915_XVMC_MAX_CONTEXTS ||
427
	    pXvMC->ncontexts >= I915_XVMC_MAX_CONTEXTS) {
Haihao Xiang's avatar
Haihao Xiang committed
428
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
429
                   "[XvMC] i915: Out of contexts.\n");
Haihao Xiang's avatar
Haihao Xiang committed
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
        return BadAlloc;
    }

    *priv = xcalloc(1, sizeof(I915XvMCCreateContextRec));
    contextRec = (I915XvMCCreateContextRec *)*priv;

    if (!*priv) {
        *num_priv = 0;
        return BadAlloc;
    }

    *num_priv = sizeof(I915XvMCCreateContextRec) >> 2;

    ctxpriv = (I915XvMCContextPriv *)xcalloc(1, sizeof(I915XvMCContextPriv));

    if (!ctxpriv) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
447
                   "[XvMC] i915: Unable to allocate memory!\n");
Haihao Xiang's avatar
Haihao Xiang committed
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
    }

    if (!i915_allocate_xvmc_buffers(pScrn, ctxpriv)) {
        i915_free_xvmc_buffers(pScrn, ctxpriv);
        xfree(ctxpriv);
        ctxpriv = NULL;
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
    }

    if (!i915_map_xvmc_buffers(pScrn, ctxpriv)) {
        i915_unmap_xvmc_buffers(pScrn, ctxpriv);
        i915_free_xvmc_buffers(pScrn, ctxpriv);
        xfree(ctxpriv);
        ctxpriv = NULL;
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
    }

475
    /* common context items */
476
    contextRec->comm.type = xvmc_driver->flag;
477
    contextRec->comm.sarea_size = pDRIInfo->SAREASize;
478 479 480 481 482
    contextRec->comm.batchbuffer.offset = xvmc_driver->batch->offset;
    contextRec->comm.batchbuffer.size = xvmc_driver->batch->size;
    contextRec->comm.batchbuffer.handle = xvmc_driver->batch_handle;

    /* i915 private context */
Haihao Xiang's avatar
Haihao Xiang committed
483
    contextRec->ctxno = i;
root's avatar
root committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    contextRec->sis.handle = ctxpriv->sis_handle;
    contextRec->sis.offset = ctxpriv->mcStaticIndirectState->offset;
    contextRec->sis.size = ctxpriv->mcStaticIndirectState->size;
    contextRec->sis.bus_addr = ctxpriv->mcStaticIndirectState->bus_addr;
    contextRec->ssb.handle = ctxpriv->ssb_handle;
    contextRec->ssb.offset = ctxpriv->mcSamplerState->offset;
    contextRec->ssb.size = ctxpriv->mcSamplerState->size;
    contextRec->ssb.bus_addr = ctxpriv->mcSamplerState->bus_addr;
    contextRec->msb.handle = ctxpriv->msb_handle;
    contextRec->msb.offset = ctxpriv->mcMapState->offset;
    contextRec->msb.size = ctxpriv->mcMapState->size;
    contextRec->msb.bus_addr = ctxpriv->mcMapState->bus_addr;
    contextRec->psp.handle = ctxpriv->psp_handle;
    contextRec->psp.offset = ctxpriv->mcPixelShaderProgram->offset;
    contextRec->psp.size = ctxpriv->mcPixelShaderProgram->size;
    contextRec->psp.bus_addr = ctxpriv->mcPixelShaderProgram->bus_addr;
    contextRec->psc.handle = ctxpriv->psc_handle;
    contextRec->psc.offset = ctxpriv->mcPixelShaderConstants->offset;
    contextRec->psc.size = ctxpriv->mcPixelShaderConstants->size;
    contextRec->psc.bus_addr = ctxpriv->mcPixelShaderConstants->bus_addr;
Haihao Xiang's avatar
Haihao Xiang committed
504 505 506 507
    contextRec->corrdata.handle = ctxpriv->corrdata_handle;
    contextRec->corrdata.offset = ctxpriv->mcCorrdata->offset;
    contextRec->corrdata.size = ctxpriv->mcCorrdata->size;
    contextRec->sarea_priv_offset = sizeof(XF86DRISAREARec);
root's avatar
root committed
508
    contextRec->deviceID = pI830DRI->deviceID;
Haihao Xiang's avatar
Haihao Xiang committed
509 510 511 512 513 514 515 516

    pXvMC->ncontexts++;
    pXvMC->contexts[i] = pContext->context_id;
    pXvMC->ctxprivs[i] = ctxpriv;

    return Success;
}

Zhenyu Wang's avatar
Zhenyu Wang committed
517
static int i915_xvmc_create_surface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
Haihao Xiang's avatar
Haihao Xiang committed
518 519 520
                                 int *num_priv, long **priv )
{
    I830Ptr pI830 = I830PTR(pScrn);
521
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
522
    I915XvMCSurfacePriv *sfpriv = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
523
    I915XvMCCreateSurfaceRec *surfaceRec = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
524
    XvMCContextPtr ctx = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
525
    unsigned int srfno;
Haihao Xiang's avatar
Haihao Xiang committed
526 527
    unsigned long bufsize;

528 529
    if (!pI830->XvMCEnabled) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
530
                   "[XvMC] i915: XvMC disabled!\n");
531 532 533
        return BadAlloc;
    }

Haihao Xiang's avatar
Haihao Xiang committed
534 535 536
    *priv = NULL;
    *num_priv = 0;

537 538 539 540 541 542 543
    for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) {
        if (!pXvMC->surfaces[srfno])
            break;
    }

    if (srfno == I915_XVMC_MAX_SURFACES ||
	    pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) {
Haihao Xiang's avatar
Haihao Xiang committed
544
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
545
                   "[XvMC] i915: Too many surfaces !\n");
Haihao Xiang's avatar
Haihao Xiang committed
546 547 548
        return BadAlloc;
    }

Haihao Xiang's avatar
Haihao Xiang committed
549
    *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec));
Zhenyu Wang's avatar
Zhenyu Wang committed
550
    surfaceRec = (I915XvMCCreateSurfaceRec *)*priv;
Haihao Xiang's avatar
Haihao Xiang committed
551

Haihao Xiang's avatar
Haihao Xiang committed
552
    if (!*priv) {
Haihao Xiang's avatar
Haihao Xiang committed
553
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
554
                   "[XvMC] i915:Unable to allocate surface priv ret memory!\n");
Haihao Xiang's avatar
Haihao Xiang committed
555 556 557
        return BadAlloc;
    }

Haihao Xiang's avatar
Haihao Xiang committed
558 559 560 561
    *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2;
    sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv));

    if (!sfpriv) {
Haihao Xiang's avatar
Haihao Xiang committed
562
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
563
                   "[XvMC] i915: Unable to allocate surface priv memory!\n");
Haihao Xiang's avatar
Haihao Xiang committed
564 565
        xfree(*priv);
        *priv = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
566 567 568 569 570
        *num_priv = 0;
        return BadAlloc;
    }

    ctx = pSurf->context;
571
    bufsize = SIZE_YUV420(ctx->width, ctx->height);
Haihao Xiang's avatar
Haihao Xiang committed
572

Zhenyu Wang's avatar
Zhenyu Wang committed
573
    if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface",
root's avatar
root committed
574
                                   &(sfpriv->surface), bufsize,
575
                                   ALIGN_BOTH_ENDS)) {
Haihao Xiang's avatar
Haihao Xiang committed
576
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
577
                   "[XvMC] i915 : Failed to allocate XvMC surface space!\n");
Haihao Xiang's avatar
Haihao Xiang committed
578 579 580 581 582 583
        xfree(sfpriv);
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
    }
Zhenyu Wang's avatar
Zhenyu Wang committed
584 585 586 587

    if (0)
	i830_describe_allocations(pScrn, 1, "");

Haihao Xiang's avatar
Haihao Xiang committed
588 589 590 591 592 593 594 595 596 597 598 599
    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(sfpriv->surface->offset + pI830->LinearAddr),
                  sfpriv->surface->size, DRM_AGP, 0,
                  (drmAddress)&sfpriv->surface_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(surface_handle) failed!\n");
        i830_free_memory(pScrn, sfpriv->surface);
        xfree(sfpriv);
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
Haihao Xiang's avatar
Haihao Xiang committed
600 601
    }

Haihao Xiang's avatar
Haihao Xiang committed
602 603 604 605 606 607 608
    surfaceRec->srfno = srfno;
    surfaceRec->srf.handle = sfpriv->surface_handle;
    surfaceRec->srf.offset = sfpriv->surface->offset;
    surfaceRec->srf.size = sfpriv->surface->size;

    pXvMC->surfaces[srfno] = pSurf->surface_id;
    pXvMC->sfprivs[srfno]= sfpriv;
Haihao Xiang's avatar
Haihao Xiang committed
609 610 611 612 613
    pXvMC->nsurfaces++;

    return Success;
}

Zhenyu Wang's avatar
Zhenyu Wang committed
614
static int i915_xvmc_create_subpict(ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
Haihao Xiang's avatar
Haihao Xiang committed
615 616 617
                                     int *num_priv, long **priv )
{
    I830Ptr pI830 = I830PTR(pScrn);
618
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
619
    I915XvMCSurfacePriv *sfpriv = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
620
    I915XvMCCreateSurfaceRec *surfaceRec = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
621
    XvMCContextPtr ctx = NULL;
622 623
    unsigned int srfno;
    unsigned int bufsize;
Haihao Xiang's avatar
Haihao Xiang committed
624

Haihao Xiang's avatar
Haihao Xiang committed
625 626 627
    *priv = NULL;
    *num_priv = 0;

628 629 630 631 632 633 634
    for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) {
        if (!pXvMC->surfaces[srfno])
            break;
    }

    if (srfno == I915_XVMC_MAX_SURFACES ||
	    pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) {
Haihao Xiang's avatar
Haihao Xiang committed
635
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
636
                   "[XvMC] i915: Too many surfaces !\n");
Haihao Xiang's avatar
Haihao Xiang committed
637 638 639
        return BadAlloc;
    }

Haihao Xiang's avatar
Haihao Xiang committed
640 641
    *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec));
    surfaceRec = (I915XvMCCreateSurfaceRec *)*priv;     
Haihao Xiang's avatar
Haihao Xiang committed
642

Haihao Xiang's avatar
Haihao Xiang committed
643
    if (!*priv) {
Haihao Xiang's avatar
Haihao Xiang committed
644
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
645
                   "[XvMC] i915: Unable to allocate memory!\n");
Haihao Xiang's avatar
Haihao Xiang committed
646 647 648
        return BadAlloc;
    }

Haihao Xiang's avatar
Haihao Xiang committed
649 650
    *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2;
    sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv));
Haihao Xiang's avatar
Haihao Xiang committed
651

Haihao Xiang's avatar
Haihao Xiang committed
652
    if (!sfpriv) {
Haihao Xiang's avatar
Haihao Xiang committed
653
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
654
                   "[XvMC] i915: Unable to allocate memory!\n");
Haihao Xiang's avatar
Haihao Xiang committed
655 656
        xfree(*priv);
        *priv = NULL;
Haihao Xiang's avatar
Haihao Xiang committed
657 658 659 660 661
        *num_priv = 0;
        return BadAlloc;
    }

    ctx = pSubp->context;
662
    bufsize = SIZE_XX44(ctx->width, ctx->height);
Haihao Xiang's avatar
Haihao Xiang committed
663

root's avatar
root committed
664 665 666
    if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface", 
                                   &(sfpriv->surface), bufsize,
                                   ALIGN_BOTH_ENDS)) {
Haihao Xiang's avatar
Haihao Xiang committed
667 668 669
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[XvMC] I915XvMCCreateSurface: Failed to allocate XvMC surface space!\n");
        xfree(sfpriv);
Haihao Xiang's avatar
Haihao Xiang committed
670 671 672 673 674 675 676 677 678 679 680 681 682 683
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
    }

    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(sfpriv->surface->offset + pI830->LinearAddr),
                  sfpriv->surface->size, DRM_AGP, 0,
                  (drmAddress)&sfpriv->surface_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "[drm] drmAddMap(surface_handle) failed!\n");
        i830_free_memory(pScrn, sfpriv->surface);
        xfree(sfpriv);
Haihao Xiang's avatar
Haihao Xiang committed
684 685 686 687 688 689
        xfree(*priv);
        *priv = NULL;
        *num_priv = 0;
        return BadAlloc;
    }

Haihao Xiang's avatar
Haihao Xiang committed
690 691 692 693 694
    surfaceRec->srfno = srfno;
    surfaceRec->srf.handle = sfpriv->surface_handle;
    surfaceRec->srf.offset = sfpriv->surface->offset;
    surfaceRec->srf.size = sfpriv->surface->size;

Haihao Xiang's avatar
Haihao Xiang committed
695 696 697 698 699 700 701
    pXvMC->sfprivs[srfno] = sfpriv;
    pXvMC->surfaces[srfno] = pSubp->subpicture_id;
    pXvMC->nsurfaces++;

    return Success;
}

Zhenyu Wang's avatar
Zhenyu Wang committed
702 703
static void i915_xvmc_destroy_context (ScrnInfoPtr pScrn,
					XvMCContextPtr pContext)
Haihao Xiang's avatar
Haihao Xiang committed
704
{
705
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
    int i;

    for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
        if (pXvMC->contexts[i] == pContext->context_id) {
            i915_unmap_xvmc_buffers(pScrn, pXvMC->ctxprivs[i]);
            i915_free_xvmc_buffers(pScrn, pXvMC->ctxprivs[i]);
            xfree(pXvMC->ctxprivs[i]);
            pXvMC->ctxprivs[i] = 0;
            pXvMC->ncontexts--;
            pXvMC->contexts[i] = 0;
            return;
        }
    }

    return;
}

Zhenyu Wang's avatar
Zhenyu Wang committed
723
static void i915_xvmc_destroy_surface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
Haihao Xiang's avatar
Haihao Xiang committed
724 725
{
    I830Ptr pI830 = I830PTR(pScrn);
726
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
727 728 729 730
    int i;

    for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
        if (pXvMC->surfaces[i] == pSurf->surface_id) {
731
            drmRmMap(pI830->drmSubFD, pXvMC->sfprivs[i]->surface_handle);
Zhenyu Wang's avatar
Zhenyu Wang committed
732
            i830_free_memory(pScrn, pXvMC->sfprivs[i]->surface);
Haihao Xiang's avatar
Haihao Xiang committed
733 734 735 736 737 738 739 740 741 742 743
            xfree(pXvMC->sfprivs[i]);
            pXvMC->nsurfaces--;
            pXvMC->sfprivs[i] = 0;
            pXvMC->surfaces[i] = 0;
            return;
        }
    }

    return;
}

Zhenyu Wang's avatar
Zhenyu Wang committed
744 745
static void i915_xvmc_destroy_subpict (ScrnInfoPtr pScrn,
					XvMCSubpicturePtr pSubp)
Haihao Xiang's avatar
Haihao Xiang committed
746 747
{
    I830Ptr pI830 = I830PTR(pScrn);
748
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Haihao Xiang's avatar
Haihao Xiang committed
749 750 751 752
    int i;

    for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
        if (pXvMC->surfaces[i] == pSubp->subpicture_id) {
753
            drmRmMap(pI830->drmSubFD, pXvMC->sfprivs[i]->surface_handle);
Zhenyu Wang's avatar
Zhenyu Wang committed
754
            i830_free_memory(pScrn, pXvMC->sfprivs[i]->surface);
Haihao Xiang's avatar
Haihao Xiang committed
755 756 757 758 759 760 761 762 763 764 765
            xfree(pXvMC->sfprivs[i]);
            pXvMC->nsurfaces--;
            pXvMC->sfprivs[i] = 0;
            pXvMC->surfaces[i] = 0;
            return;
        }
    }

    return;
}

Zhenyu Wang's avatar
Zhenyu Wang committed
766 767 768 769 770 771 772
static int i915_xvmc_put_image(ScrnInfoPtr pScrn,
	short src_x, short src_y,
	short drw_x, short drw_y, short src_w,
	short src_h, short drw_w, short drw_h,
	int id, unsigned char *buf, short width,
	short height, Bool sync, RegionPtr clipBoxes, pointer data,
	DrawablePtr pDraw)
Haihao Xiang's avatar
Haihao Xiang committed
773
{
774
    I830Ptr pI830 = I830PTR(pScrn);
775
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
776
    struct intel_xvmc_command *xvmc_cmd = (struct intel_xvmc_command *)buf;
777
    int ret;
Haihao Xiang's avatar
Haihao Xiang committed
778

Zhenyu Wang's avatar
Zhenyu Wang committed
779
    if (pI830->XvMCEnabled) {
Haihao Xiang's avatar
Haihao Xiang committed
780
        if (FOURCC_XVMC == id) {
781
            switch (xvmc_cmd->command) {
782
            case INTEL_XVMC_COMMAND_DISPLAY:
783 784 785
		if ((xvmc_cmd->srfNo >= I915_XVMC_MAX_SURFACES) ||
			!pXvMC->surfaces[xvmc_cmd->srfNo] ||
			!pXvMC->sfprivs[xvmc_cmd->srfNo]) {
Zhenyu Wang's avatar
Zhenyu Wang committed
786
		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Zhenyu Wang's avatar
Zhenyu Wang committed
787
			    "[XvMC] i915 put image: Invalid parameters!\n");
Zhenyu Wang's avatar
Zhenyu Wang committed
788 789
		    return 1;
		}
790

Zhenyu Wang's avatar
Zhenyu Wang committed
791
		buf = pI830->FbBase +
792 793
		    pXvMC->sfprivs[xvmc_cmd->srfNo]->surface->offset;
		id = xvmc_cmd->real_id;
Zhenyu Wang's avatar
Zhenyu Wang committed
794 795
		pI830->IsXvMCSurface = 1;
		break;
Haihao Xiang's avatar
Haihao Xiang committed
796 797 798 799 800 801
            default:
                return 0;
            }
        }
    }

Zhenyu Wang's avatar
Zhenyu Wang committed
802
    ret = pXvMC->savePutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h,
Zhenyu Wang's avatar
Zhenyu Wang committed
803 804
                        drw_w, drw_h, id, buf, width, height, sync, clipBoxes,
			data, pDraw);
805 806
    pI830->IsXvMCSurface = 0;
    return ret;
Haihao Xiang's avatar
Haihao Xiang committed
807 808
}

809
static Bool i915_xvmc_init(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr XvAdapt)
Haihao Xiang's avatar
Haihao Xiang committed
810
{
Zhenyu Wang's avatar
Zhenyu Wang committed
811
    I915XvMCPtr pXvMC;
Haihao Xiang's avatar
Haihao Xiang committed
812

Zhenyu Wang's avatar
Zhenyu Wang committed
813
    pXvMC = (I915XvMCPtr)xcalloc(1, sizeof(I915XvMC));
Haihao Xiang's avatar
Haihao Xiang committed
814 815
    if (!pXvMC) {
        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
Zhenyu Wang's avatar
Zhenyu Wang committed
816 817
                   "[XvMC] alloc driver private failed!\n");
        return FALSE;
Haihao Xiang's avatar
Haihao Xiang committed
818
    }
819
    xvmc_driver->devPrivate = (void*)pXvMC;
820
    if (!intel_xvmc_init_batch(pScrn)) {
821 822 823 824 825
        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		"[XvMC] fail to init batch buffer\n");
	xfree(pXvMC);
	return FALSE;
    }
Haihao Xiang's avatar
Haihao Xiang committed
826 827
    initI915XvMC(pXvMC);

Zhenyu Wang's avatar
Zhenyu Wang committed
828 829
    /* set up wrappers */
    pXvMC->savePutImage = XvAdapt->PutImage;
Zhenyu Wang's avatar
Zhenyu Wang committed
830
    XvAdapt->PutImage = i915_xvmc_put_image;
Zhenyu Wang's avatar
Zhenyu Wang committed
831 832 833
    return TRUE;
}

834
static void i915_xvmc_fini(ScrnInfoPtr pScrn)
Zhenyu Wang's avatar
Zhenyu Wang committed
835
{
836
    I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate;
Zhenyu Wang's avatar
Zhenyu Wang committed
837

838
    cleanupI915XvMC(pXvMC);
839
    intel_xvmc_fini_batch(pScrn);
840
    xfree(xvmc_driver->devPrivate);
Haihao Xiang's avatar
Haihao Xiang committed
841 842
}

Zhenyu Wang's avatar
Zhenyu Wang committed
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
/* Fill in the device dependent adaptor record.
 * This is named "Intel(R) Textured Video" because this code falls under the
 * XV extenstion, the name must match or it won't be used.
 *
 * Surface and Subpicture - see above
 * Function pointers to functions below
 */
static XF86MCAdaptorRec pAdapt =
{
    .name		= "Intel(R) Textured Video",
    .num_surfaces	= ARRARY_SIZE(ppSI),
    .surfaces		= ppSI,
#if 0
    .num_subpictures	= ARRARY_SIZE(i915_subpicture_list),
    .subpictures	= i915_subpicture_list,
#endif
    .num_subpictures	= 0,
    .subpictures	= NULL,
    .CreateContext	= (xf86XvMCCreateContextProcPtr) i915_xvmc_create_context,
    .DestroyContext	= (xf86XvMCDestroyContextProcPtr) i915_xvmc_destroy_context,
    .CreateSurface	= (xf86XvMCCreateSurfaceProcPtr) i915_xvmc_create_surface,
    .DestroySurface	= (xf86XvMCDestroySurfaceProcPtr) i915_xvmc_destroy_surface,
    .CreateSubpicture	= (xf86XvMCCreateSubpictureProcPtr) i915_xvmc_create_subpict,
    .DestroySubpicture	= (xf86XvMCDestroySubpictureProcPtr) i915_xvmc_destroy_subpict,
};

869 870
/* new xvmc driver interface */
struct intel_xvmc_driver i915_xvmc_driver = {
Zhenyu Wang's avatar
Zhenyu Wang committed
871 872 873 874 875
    .name		= "i915_xvmc",
    .adaptor		= &pAdapt,
    .flag		= XVMC_I915_MPEG2_MC,
    .init		= i915_xvmc_init,
    .fini		= i915_xvmc_fini,
876
};