1fa225cbcSrjs/*
2fa225cbcSrjs * Copyright © 2008 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 * Author:
24fa225cbcSrjs *    Zou Nan hai <nanhai.zou@intel.com>
25fa225cbcSrjs *
26fa225cbcSrjs */
27fa225cbcSrjs#ifdef HAVE_CONFIG_H
28fa225cbcSrjs#include "config.h"
29fa225cbcSrjs#endif
30fa225cbcSrjs
31fa225cbcSrjs#include <X11/extensions/Xv.h>
32fa225cbcSrjs#include <X11/extensions/XvMC.h>
33fa225cbcSrjs#include <fourcc.h>
34fa225cbcSrjs#include <errno.h>
35fa225cbcSrjs
36fa225cbcSrjs#include "i830.h"
37fa225cbcSrjs#include "i830_dri.h"
38fa225cbcSrjs#define _INTEL_XVMC_SERVER_
39fa225cbcSrjs#include "i830_hwmc.h"
40fa225cbcSrjs#include "i965_hwmc.h"
41fa225cbcSrjs#include "intel_bufmgr.h"
42fa225cbcSrjs
43fa225cbcSrjs#define STRIDE(w)               (w)
44fa225cbcSrjs#define SIZE_YUV420(w, h)       (h * (STRIDE(w) + STRIDE(w >> 1)))
45fa225cbcSrjs#define VLD_MAX_SLICE_LEN	(32*1024)
46fa225cbcSrjs
47fa225cbcSrjs#ifndef XVMC_VLD
48fa225cbcSrjs#define XVMC_VLD  0x00020000
49fa225cbcSrjs#endif
50fa225cbcSrjs
51fa225cbcSrjsstatic PutImageFuncPtr XvPutImage;
52fa225cbcSrjs
53fa225cbcSrjs
54fa225cbcSrjsstatic int create_context(ScrnInfoPtr pScrn,
55fa225cbcSrjs	XvMCContextPtr context, int *num_privates, CARD32 **private)
56fa225cbcSrjs{
57fa225cbcSrjs    struct i965_xvmc_context *private_context, *context_dup;
58fa225cbcSrjs    I830Ptr I830 = I830PTR(pScrn);
59fa225cbcSrjs
60fa225cbcSrjs    unsigned int blocknum =
61fa225cbcSrjs	(((context->width + 15)/16)*((context->height+15)/16));
62fa225cbcSrjs    unsigned int blocksize = 6*blocknum*64*sizeof(short);
63fa225cbcSrjs    blocksize = (blocksize + 4095)&(~4095);
64fa225cbcSrjs    if ((private_context = Xcalloc(sizeof(*private_context))) == NULL) {
65fa225cbcSrjs	ErrorF("XVMC Can not allocate private context\n");
66fa225cbcSrjs	return BadAlloc;
67fa225cbcSrjs    }
68fa225cbcSrjs
69fa225cbcSrjs    if ((context_dup = Xcalloc(sizeof(*private_context))) == NULL) {
70fa225cbcSrjs	ErrorF("XVMC Can not allocate private context\n");
71fa225cbcSrjs	return BadAlloc;
72fa225cbcSrjs    }
73fa225cbcSrjs
74fa225cbcSrjs    private_context->is_g4x = IS_G4X(I830);
75fa225cbcSrjs    private_context->is_965_q = IS_965_Q(I830);
76fa225cbcSrjs    private_context->is_igdng = IS_IGDNG(I830);
77fa225cbcSrjs    private_context->comm.kernel_exec_fencing = I830->kernel_exec_fencing;
78fa225cbcSrjs    private_context->comm.type = xvmc_driver->flag;
79fa225cbcSrjs
80fa225cbcSrjs    *num_privates = sizeof(*private_context)/sizeof(CARD32);
81fa225cbcSrjs    *private = (CARD32 *)private_context;
82fa225cbcSrjs    memcpy(context_dup, private_context, sizeof(*private_context));
83fa225cbcSrjs    context->driver_priv = context_dup;
84fa225cbcSrjs
85fa225cbcSrjs    return Success;
86fa225cbcSrjs}
87fa225cbcSrjs
88fa225cbcSrjsstatic void destroy_context(ScrnInfoPtr pScrn, XvMCContextPtr context)
89fa225cbcSrjs{
90fa225cbcSrjs    struct i965_xvmc_context *private_context;
91fa225cbcSrjs    private_context = context->driver_priv;
92fa225cbcSrjs    Xfree(private_context);
93fa225cbcSrjs}
94fa225cbcSrjs
95fa225cbcSrjsstatic int create_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface,
96fa225cbcSrjs  int *num_priv, CARD32 **priv)
97fa225cbcSrjs{
98fa225cbcSrjs	XvMCContextPtr ctx = surface->context;
99fa225cbcSrjs
100fa225cbcSrjs	struct i965_xvmc_surface *priv_surface, *surface_dup;
101fa225cbcSrjs	struct i965_xvmc_context *priv_ctx = ctx->driver_priv;
102fa225cbcSrjs	int i;
103fa225cbcSrjs	for (i = 0 ; i < I965_MAX_SURFACES; i++) {
104fa225cbcSrjs	    if (priv_ctx->surfaces[i] == NULL) {
105fa225cbcSrjs		priv_surface = Xcalloc(sizeof(*priv_surface));
106fa225cbcSrjs		if (priv_surface == NULL)
107fa225cbcSrjs		    return BadAlloc;
108fa225cbcSrjs		surface_dup = Xcalloc(sizeof(*priv_surface));
109fa225cbcSrjs		if (surface_dup == NULL)
110fa225cbcSrjs		    return BadAlloc;
111fa225cbcSrjs
112fa225cbcSrjs		priv_surface->no = i;
113fa225cbcSrjs		priv_surface->handle = priv_surface;
114fa225cbcSrjs		priv_surface->w = ctx->width;
115fa225cbcSrjs		priv_surface->h = ctx->height;
116fa225cbcSrjs		priv_ctx->surfaces[i] = surface->driver_priv
117fa225cbcSrjs		    = priv_surface;
118fa225cbcSrjs		memcpy(surface_dup, priv_surface, sizeof(*priv_surface));
119fa225cbcSrjs		*num_priv = sizeof(*priv_surface)/sizeof(CARD32);
120fa225cbcSrjs		*priv = (CARD32 *)surface_dup;
121fa225cbcSrjs		break;
122fa225cbcSrjs	    }
123fa225cbcSrjs	}
124fa225cbcSrjs
125fa225cbcSrjs	if (i >= I965_MAX_SURFACES) {
126fa225cbcSrjs	    ErrorF("I965 XVMC too many surfaces in one context\n");
127fa225cbcSrjs	    return BadAlloc;
128fa225cbcSrjs	}
129fa225cbcSrjs
130fa225cbcSrjs	return Success;
131fa225cbcSrjs}
132fa225cbcSrjs
133fa225cbcSrjsstatic void destory_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface)
134fa225cbcSrjs{
135fa225cbcSrjs	XvMCContextPtr ctx = surface->context;
136fa225cbcSrjs	struct i965_xvmc_surface *priv_surface = surface->driver_priv;
137fa225cbcSrjs	struct i965_xvmc_context *priv_ctx = ctx->driver_priv;
138fa225cbcSrjs	priv_ctx->surfaces[priv_surface->no] = NULL;
139fa225cbcSrjs	Xfree(priv_surface);
140fa225cbcSrjs}
141fa225cbcSrjs
142fa225cbcSrjsstatic int create_subpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr subpicture,
143fa225cbcSrjs  int *num_priv, CARD32 **priv)
144fa225cbcSrjs{
145fa225cbcSrjs	return Success;
146fa225cbcSrjs}
147fa225cbcSrjs
148fa225cbcSrjsstatic void destroy_subpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr subpicture)
149fa225cbcSrjs{
150fa225cbcSrjs}
151fa225cbcSrjs
152fa225cbcSrjsstatic int put_image(ScrnInfoPtr pScrn,
153fa225cbcSrjs        short src_x, short src_y,
154fa225cbcSrjs        short drw_x, short drw_y, short src_w,
155fa225cbcSrjs        short src_h, short drw_w, short drw_h,
156fa225cbcSrjs        int id, unsigned char *buf, short width,
157fa225cbcSrjs        short height, Bool sync, RegionPtr clipBoxes, pointer data,
158fa225cbcSrjs        DrawablePtr pDraw)
159fa225cbcSrjs{
160fa225cbcSrjs	I830Ptr pI830 = I830PTR(pScrn);
161fa225cbcSrjs	struct intel_xvmc_command *cmd = (struct intel_xvmc_command *)buf;
162fa225cbcSrjs	dri_bo *bo;
163fa225cbcSrjs
164fa225cbcSrjs	if (id == FOURCC_XVMC) {
165fa225cbcSrjs            bo = intel_bo_gem_create_from_name(pI830->bufmgr, "surface", cmd->handle);
166fa225cbcSrjs            dri_bo_pin(bo, 0x1000);
167fa225cbcSrjs	    buf = pI830->FbBase + bo->offset;
168fa225cbcSrjs	}
169fa225cbcSrjs	XvPutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h,
170fa225cbcSrjs		drw_w, drw_h, id, buf, width, height, sync, clipBoxes,
171fa225cbcSrjs		data, pDraw);
172fa225cbcSrjs
173fa225cbcSrjs	if (id == FOURCC_XVMC) {
174fa225cbcSrjs	    dri_bo_unpin(bo);
175fa225cbcSrjs	    dri_bo_unreference(bo);
176fa225cbcSrjs	}
177fa225cbcSrjs
178fa225cbcSrjs	return Success;
179fa225cbcSrjs}
180fa225cbcSrjs
181fa225cbcSrjsstatic Bool init(ScrnInfoPtr screen_info, XF86VideoAdaptorPtr adaptor)
182fa225cbcSrjs{
183fa225cbcSrjs    XvPutImage = adaptor->PutImage;
184fa225cbcSrjs    adaptor->PutImage = put_image;
185fa225cbcSrjs
186fa225cbcSrjs    return TRUE;
187fa225cbcSrjs}
188fa225cbcSrjs
189fa225cbcSrjsstatic void fini(ScrnInfoPtr screen_info)
190fa225cbcSrjs{
191fa225cbcSrjs}
192fa225cbcSrjs
193fa225cbcSrjsstatic XF86MCSurfaceInfoRec yv12_mpeg2_vld_surface =
194fa225cbcSrjs{
195fa225cbcSrjs    FOURCC_YV12,
196fa225cbcSrjs    XVMC_CHROMA_FORMAT_420,
197fa225cbcSrjs    0,
198fa225cbcSrjs    1936,
199fa225cbcSrjs    1096,
200fa225cbcSrjs    1920,
201fa225cbcSrjs    1080,
202fa225cbcSrjs    XVMC_MPEG_2|XVMC_VLD,
203fa225cbcSrjs    XVMC_INTRA_UNSIGNED,
204fa225cbcSrjs    NULL
205fa225cbcSrjs};
206fa225cbcSrjs
207fa225cbcSrjsstatic XF86MCSurfaceInfoRec yv12_mpeg2_surface =
208fa225cbcSrjs{
209fa225cbcSrjs    FOURCC_YV12,
210fa225cbcSrjs    XVMC_CHROMA_FORMAT_420,
211fa225cbcSrjs    0,
212fa225cbcSrjs    1936,
213fa225cbcSrjs    1096,
214fa225cbcSrjs    1920,
215fa225cbcSrjs    1080,
216fa225cbcSrjs    XVMC_MPEG_2|XVMC_MOCOMP,
217fa225cbcSrjs    /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/
218fa225cbcSrjs    XVMC_INTRA_UNSIGNED,
219fa225cbcSrjs    /* &yv12_subpicture_list*/
220fa225cbcSrjs    NULL
221fa225cbcSrjs};
222fa225cbcSrjs
223fa225cbcSrjsstatic XF86MCSurfaceInfoRec yv12_mpeg1_surface =
224fa225cbcSrjs{
225fa225cbcSrjs    FOURCC_YV12,
226fa225cbcSrjs    XVMC_CHROMA_FORMAT_420,
227fa225cbcSrjs    0,
228fa225cbcSrjs    1920,
229fa225cbcSrjs    1080,
230fa225cbcSrjs    1920,
231fa225cbcSrjs    1080,
232fa225cbcSrjs    XVMC_MPEG_1|XVMC_MOCOMP,
233fa225cbcSrjs    /*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
234fa225cbcSrjs    XVMC_INTRA_UNSIGNED,*/
235fa225cbcSrjs    XVMC_INTRA_UNSIGNED,
236fa225cbcSrjs
237fa225cbcSrjs    /*&yv12_subpicture_list*/
238fa225cbcSrjs    NULL
239fa225cbcSrjs};
240fa225cbcSrjs
241fa225cbcSrjsstatic XF86MCSurfaceInfoPtr surface_info[] = {
242fa225cbcSrjs    &yv12_mpeg2_surface,
243fa225cbcSrjs    &yv12_mpeg1_surface
244fa225cbcSrjs};
245fa225cbcSrjs
246fa225cbcSrjsstatic XF86MCSurfaceInfoPtr surface_info_vld[] = {
247fa225cbcSrjs    &yv12_mpeg2_vld_surface,
248fa225cbcSrjs    &yv12_mpeg2_surface,
249fa225cbcSrjs};
250fa225cbcSrjs
251fa225cbcSrjsstatic XF86MCAdaptorRec adaptor_vld = {
252fa225cbcSrjs    .name               = "Intel(R) Textured Video",
253fa225cbcSrjs    .num_surfaces       = sizeof(surface_info_vld)/sizeof(surface_info_vld[0]),
254fa225cbcSrjs    .surfaces           = surface_info_vld,
255fa225cbcSrjs
256fa225cbcSrjs    .CreateContext 	= create_context,
257fa225cbcSrjs    .DestroyContext	= destroy_context,
258fa225cbcSrjs    .CreateSurface 	= create_surface,
259fa225cbcSrjs    .DestroySurface 	= destory_surface,
260fa225cbcSrjs    .CreateSubpicture   = create_subpicture,
261fa225cbcSrjs    .DestroySubpicture  = destroy_subpicture
262fa225cbcSrjs};
263fa225cbcSrjs
264fa225cbcSrjsstatic XF86MCAdaptorRec adaptor = {
265fa225cbcSrjs    .name               = "Intel(R) Textured Video",
266fa225cbcSrjs    .num_surfaces       = sizeof(surface_info)/sizeof(surface_info[0]),
267fa225cbcSrjs    .surfaces           = surface_info,
268fa225cbcSrjs
269fa225cbcSrjs    .CreateContext 	= create_context,
270fa225cbcSrjs    .DestroyContext	= destroy_context,
271fa225cbcSrjs    .CreateSurface 	= create_surface,
272fa225cbcSrjs    .DestroySurface 	= destory_surface,
273fa225cbcSrjs    .CreateSubpicture   = create_subpicture,
274fa225cbcSrjs    .DestroySubpicture  = destroy_subpicture
275fa225cbcSrjs};
276fa225cbcSrjs
277fa225cbcSrjsstruct intel_xvmc_driver i965_xvmc_driver = {
278fa225cbcSrjs    .name               = "i965_xvmc",
279fa225cbcSrjs    .adaptor            = &adaptor,
280fa225cbcSrjs    .flag               = XVMC_I965_MPEG2_MC,
281fa225cbcSrjs    .init 		= init,
282fa225cbcSrjs    .fini		= fini
283fa225cbcSrjs};
284fa225cbcSrjs
285fa225cbcSrjsstruct intel_xvmc_driver vld_xvmc_driver =  {
286fa225cbcSrjs    .name               = "xvmc_vld",
287fa225cbcSrjs    .adaptor            = &adaptor_vld,
288fa225cbcSrjs    .flag               = XVMC_I965_MPEG2_VLD,
289fa225cbcSrjs    .init 		= init,
290fa225cbcSrjs    .fini		= fini
291fa225cbcSrjs};
292fa225cbcSrjs
293