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