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