1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2006 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg * Authors:
24428d7b3dSmrg *    Xiang Haihao <haihao.xiang@intel.com>
25428d7b3dSmrg *
26428d7b3dSmrg */
27428d7b3dSmrg
28428d7b3dSmrg#include <sys/ioctl.h>
29428d7b3dSmrg
30428d7b3dSmrg#include "i915_xvmc.h"
31428d7b3dSmrg#include "i915_structs.h"
32428d7b3dSmrg#include "i915_program.h"
33428d7b3dSmrg
34428d7b3dSmrg#define ALIGN(i,m)		(((i) + (m) - 1) & ~((m) - 1))
35428d7b3dSmrg
36428d7b3dSmrg#define STRIDE(w)               (ALIGN((w), 1024))
37428d7b3dSmrg#define SIZE_Y420(w, h)         (h * STRIDE(w))
38428d7b3dSmrg#define SIZE_UV420(w, h)        ((h >> 1) * STRIDE(w >> 1))
39428d7b3dSmrg#define SIZE_YUV420(w, h)       (SIZE_Y420(w,h) + SIZE_UV420(w,h) * 2)
40428d7b3dSmrg#define UOFFSET(context)        (SIZE_Y420(context->width, context->height))
41428d7b3dSmrg#define VOFFSET(context)        (SIZE_Y420(context->width, context->height) + \
42428d7b3dSmrg                                 SIZE_UV420(context->width, context->height))
43428d7b3dSmrg
44428d7b3dSmrgtypedef union {
45428d7b3dSmrg	int16_t component[2];
46428d7b3dSmrg	int32_t v;
47428d7b3dSmrg} vector_t;
48428d7b3dSmrg
49428d7b3dSmrgstatic void i915_inst_arith(unsigned int *inst,
50428d7b3dSmrg			    unsigned int op,
51428d7b3dSmrg			    unsigned int dest,
52428d7b3dSmrg			    unsigned int mask,
53428d7b3dSmrg			    unsigned int saturate,
54428d7b3dSmrg			    unsigned int src0, unsigned int src1,
55428d7b3dSmrg			    unsigned int src2)
56428d7b3dSmrg{
57428d7b3dSmrg	dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
58428d7b3dSmrg	*inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
59428d7b3dSmrg	inst++;
60428d7b3dSmrg	*inst = (A1_SRC0(src0) | A1_SRC1(src1));
61428d7b3dSmrg	inst++;
62428d7b3dSmrg	*inst = (A2_SRC1(src1) | A2_SRC2(src2));
63428d7b3dSmrg}
64428d7b3dSmrg
65428d7b3dSmrgstatic void i915_inst_decl(unsigned int *inst,
66428d7b3dSmrg			   unsigned int type,
67428d7b3dSmrg			   unsigned int nr, unsigned int d0_flags)
68428d7b3dSmrg{
69428d7b3dSmrg	unsigned int reg = UREG(type, nr);
70428d7b3dSmrg
71428d7b3dSmrg	*inst = (D0_DCL | D0_DEST(reg) | d0_flags);
72428d7b3dSmrg	inst++;
73428d7b3dSmrg	*inst = D1_MBZ;
74428d7b3dSmrg	inst++;
75428d7b3dSmrg	*inst = D2_MBZ;
76428d7b3dSmrg}
77428d7b3dSmrg
78428d7b3dSmrgstatic void i915_inst_texld(unsigned int *inst,
79428d7b3dSmrg			    unsigned int op,
80428d7b3dSmrg			    unsigned int dest,
81428d7b3dSmrg			    unsigned int coord, unsigned int sampler)
82428d7b3dSmrg{
83428d7b3dSmrg	dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
84428d7b3dSmrg	*inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler));
85428d7b3dSmrg	inst++;
86428d7b3dSmrg	*inst = T1_ADDRESS_REG(coord);
87428d7b3dSmrg	inst++;
88428d7b3dSmrg	*inst = T2_MBZ;
89428d7b3dSmrg}
90428d7b3dSmrg
91428d7b3dSmrgstatic void i915_mc_one_time_context_init(XvMCContext * context)
92428d7b3dSmrg{
93428d7b3dSmrg	unsigned int dest, src0, src1, src2;
94428d7b3dSmrg	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
95428d7b3dSmrg	int i;
96428d7b3dSmrg	struct i915_3dstate_sampler_state *sampler_state;
97428d7b3dSmrg	struct i915_3dstate_pixel_shader_program *pixel_shader_program;
98428d7b3dSmrg	struct i915_3dstate_pixel_shader_constants *pixel_shader_constants;
99428d7b3dSmrg
100428d7b3dSmrg	/* sampler static state */
101428d7b3dSmrg	drm_intel_gem_bo_map_gtt(pI915XvMC->ssb_bo);
102428d7b3dSmrg	sampler_state = pI915XvMC->ssb_bo->virtual;
103428d7b3dSmrg
104428d7b3dSmrg	memset(sampler_state, 0, sizeof(*sampler_state));
105428d7b3dSmrg	sampler_state->dw0.type = CMD_3D;
106428d7b3dSmrg	sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE;
107428d7b3dSmrg	sampler_state->dw0.length = 6;
108428d7b3dSmrg	sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1;
109428d7b3dSmrg
110428d7b3dSmrg	sampler_state->sampler0.ts0.reverse_gamma = 0;
111428d7b3dSmrg	sampler_state->sampler0.ts0.planar2packet = 0;
112428d7b3dSmrg	sampler_state->sampler0.ts0.color_conversion = 0;
113428d7b3dSmrg	sampler_state->sampler0.ts0.chromakey_index = 0;
114428d7b3dSmrg	sampler_state->sampler0.ts0.base_level = 0;
115428d7b3dSmrg	sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE;	/* NONE */
116428d7b3dSmrg	sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR;	/* LINEAR */
117428d7b3dSmrg	sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR;	/* LINEAR */
118428d7b3dSmrg	sampler_state->sampler0.ts0.lod_bias = 0;	/* 0.0 */
119428d7b3dSmrg	sampler_state->sampler0.ts0.shadow_enable = 0;
120428d7b3dSmrg	sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2;
121428d7b3dSmrg	sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS;
122428d7b3dSmrg	sampler_state->sampler0.ts1.min_lod = 0;	/* 0.0 Maximum Mip Level */
123428d7b3dSmrg	sampler_state->sampler0.ts1.kill_pixel = 0;
124428d7b3dSmrg	sampler_state->sampler0.ts1.keyed_texture_filter = 0;
125428d7b3dSmrg	sampler_state->sampler0.ts1.chromakey_enable = 0;
126428d7b3dSmrg	sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP;
127428d7b3dSmrg	sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP;
128428d7b3dSmrg	sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP;
129428d7b3dSmrg	sampler_state->sampler0.ts1.normalized_coor = 0;
130428d7b3dSmrg	sampler_state->sampler0.ts1.map_index = 0;
131428d7b3dSmrg	sampler_state->sampler0.ts1.east_deinterlacer = 0;
132428d7b3dSmrg	sampler_state->sampler0.ts2.default_color = 0;
133428d7b3dSmrg
134428d7b3dSmrg	sampler_state->sampler1.ts0.reverse_gamma = 0;
135428d7b3dSmrg	sampler_state->sampler1.ts0.planar2packet = 0;
136428d7b3dSmrg	sampler_state->sampler1.ts0.color_conversion = 0;
137428d7b3dSmrg	sampler_state->sampler1.ts0.chromakey_index = 0;
138428d7b3dSmrg	sampler_state->sampler1.ts0.base_level = 0;
139428d7b3dSmrg	sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE;	/* NONE */
140428d7b3dSmrg	sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR;	/* LINEAR */
141428d7b3dSmrg	sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR;	/* LINEAR */
142428d7b3dSmrg	sampler_state->sampler1.ts0.lod_bias = 0;	/* 0.0 */
143428d7b3dSmrg	sampler_state->sampler1.ts0.shadow_enable = 0;
144428d7b3dSmrg	sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2;
145428d7b3dSmrg	sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS;
146428d7b3dSmrg	sampler_state->sampler1.ts1.min_lod = 0;	/* 0.0 Maximum Mip Level */
147428d7b3dSmrg	sampler_state->sampler1.ts1.kill_pixel = 0;
148428d7b3dSmrg	sampler_state->sampler1.ts1.keyed_texture_filter = 0;
149428d7b3dSmrg	sampler_state->sampler1.ts1.chromakey_enable = 0;
150428d7b3dSmrg	sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP;
151428d7b3dSmrg	sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP;
152428d7b3dSmrg	sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP;
153428d7b3dSmrg	sampler_state->sampler1.ts1.normalized_coor = 0;
154428d7b3dSmrg	sampler_state->sampler1.ts1.map_index = 1;
155428d7b3dSmrg	sampler_state->sampler1.ts1.east_deinterlacer = 0;
156428d7b3dSmrg	sampler_state->sampler1.ts2.default_color = 0;
157428d7b3dSmrg
158428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(pI915XvMC->ssb_bo);
159428d7b3dSmrg
160428d7b3dSmrg	/* pixel shader static state */
161428d7b3dSmrg	drm_intel_gem_bo_map_gtt(pI915XvMC->psp_bo);
162428d7b3dSmrg	pixel_shader_program = pI915XvMC->psp_bo->virtual;
163428d7b3dSmrg
164428d7b3dSmrg	memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
165428d7b3dSmrg	pixel_shader_program->shader0.type = CMD_3D;
166428d7b3dSmrg	pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
167428d7b3dSmrg	pixel_shader_program->shader0.retain = 1;
168428d7b3dSmrg	pixel_shader_program->shader0.length = 2;	/* 1 inst */
169428d7b3dSmrg	i = 0;
170428d7b3dSmrg
171428d7b3dSmrg	dest = UREG(REG_TYPE_OC, 0);
172428d7b3dSmrg	src0 = UREG(REG_TYPE_CONST, 0);
173428d7b3dSmrg	src1 = 0;
174428d7b3dSmrg	src2 = 0;
175428d7b3dSmrg	i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV,
176428d7b3dSmrg			dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
177428d7b3dSmrg			src2);
178428d7b3dSmrg
179428d7b3dSmrg	pixel_shader_program->shader1.type = CMD_3D;
180428d7b3dSmrg	pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
181428d7b3dSmrg	pixel_shader_program->shader1.retain = 1;
182428d7b3dSmrg	pixel_shader_program->shader1.length = 14;	/* 5 inst */
183428d7b3dSmrg	i = 0;
184428d7b3dSmrg	/* dcl t0.xy */
185428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0,
186428d7b3dSmrg		       D0_CHANNEL_XY);
187428d7b3dSmrg	i += 3;
188428d7b3dSmrg	/* dcl t1.xy */
189428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1,
190428d7b3dSmrg		       D0_CHANNEL_XY);
191428d7b3dSmrg	/* dcl_2D s0 */
192428d7b3dSmrg	i += 3;
193428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0,
194428d7b3dSmrg		       D0_SAMPLE_TYPE_2D);
195428d7b3dSmrg	/* texld r0, t0, s0 */
196428d7b3dSmrg	i += 3;
197428d7b3dSmrg	dest = UREG(REG_TYPE_R, 0);
198428d7b3dSmrg	src0 = UREG(REG_TYPE_T, 0);	/* COORD */
199428d7b3dSmrg	src1 = UREG(REG_TYPE_S, 0);	/* SAMPLER */
200428d7b3dSmrg	i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0,
201428d7b3dSmrg			src1);
202428d7b3dSmrg	/* mov oC, r0 */
203428d7b3dSmrg	i += 3;
204428d7b3dSmrg	dest = UREG(REG_TYPE_OC, 0);
205428d7b3dSmrg	src0 = UREG(REG_TYPE_R, 0);
206428d7b3dSmrg	src1 = src2 = 0;
207428d7b3dSmrg	i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest,
208428d7b3dSmrg			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
209428d7b3dSmrg			src2);
210428d7b3dSmrg
211428d7b3dSmrg	pixel_shader_program->shader2.type = CMD_3D;
212428d7b3dSmrg	pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
213428d7b3dSmrg	pixel_shader_program->shader2.retain = 1;
214428d7b3dSmrg	pixel_shader_program->shader2.length = 14;	/* 5 inst */
215428d7b3dSmrg	i = 0;
216428d7b3dSmrg	/* dcl t2.xy */
217428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2,
218428d7b3dSmrg		       D0_CHANNEL_XY);
219428d7b3dSmrg	/* dcl t3.xy */
220428d7b3dSmrg	i += 3;
221428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3,
222428d7b3dSmrg		       D0_CHANNEL_XY);
223428d7b3dSmrg	/* dcl_2D s1 */
224428d7b3dSmrg	i += 3;
225428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1,
226428d7b3dSmrg		       D0_SAMPLE_TYPE_2D);
227428d7b3dSmrg	/* texld r0, t2, s1 */
228428d7b3dSmrg	i += 3;
229428d7b3dSmrg	dest = UREG(REG_TYPE_R, 0);
230428d7b3dSmrg	src0 = UREG(REG_TYPE_T, 2);	/* COORD */
231428d7b3dSmrg	src1 = UREG(REG_TYPE_S, 1);	/* SAMPLER */
232428d7b3dSmrg	i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0,
233428d7b3dSmrg			src1);
234428d7b3dSmrg	/* mov oC, r0 */
235428d7b3dSmrg	i += 3;
236428d7b3dSmrg	dest = UREG(REG_TYPE_OC, 0);
237428d7b3dSmrg	src0 = UREG(REG_TYPE_R, 0);
238428d7b3dSmrg	src1 = src2 = 0;
239428d7b3dSmrg	i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest,
240428d7b3dSmrg			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
241428d7b3dSmrg			src2);
242428d7b3dSmrg
243428d7b3dSmrg	/* Shader 3 */
244428d7b3dSmrg	pixel_shader_program->shader3.type = CMD_3D;
245428d7b3dSmrg	pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
246428d7b3dSmrg	pixel_shader_program->shader3.retain = 1;
247428d7b3dSmrg	pixel_shader_program->shader3.length = 29;	/* 10 inst */
248428d7b3dSmrg	i = 0;
249428d7b3dSmrg	/* dcl t0.xy */
250428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0,
251428d7b3dSmrg		       D0_CHANNEL_XY);
252428d7b3dSmrg	/* dcl t1.xy */
253428d7b3dSmrg	i += 3;
254428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1,
255428d7b3dSmrg		       D0_CHANNEL_XY);
256428d7b3dSmrg	/* dcl t2.xy */
257428d7b3dSmrg	i += 3;
258428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2,
259428d7b3dSmrg		       D0_CHANNEL_XY);
260428d7b3dSmrg	/* dcl t3.xy */
261428d7b3dSmrg	i += 3;
262428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3,
263428d7b3dSmrg		       D0_CHANNEL_XY);
264428d7b3dSmrg	/* dcl_2D s0 */
265428d7b3dSmrg	i += 3;
266428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0,
267428d7b3dSmrg		       D0_SAMPLE_TYPE_2D);
268428d7b3dSmrg	/* dcl_2D s1 */
269428d7b3dSmrg	i += 3;
270428d7b3dSmrg	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1,
271428d7b3dSmrg		       D0_SAMPLE_TYPE_2D);
272428d7b3dSmrg	/* texld r0, t0, s0 */
273428d7b3dSmrg	i += 3;
274428d7b3dSmrg	dest = UREG(REG_TYPE_R, 0);
275428d7b3dSmrg	src0 = UREG(REG_TYPE_T, 0);	/* COORD */
276428d7b3dSmrg	src1 = UREG(REG_TYPE_S, 0);	/* SAMPLER */
277428d7b3dSmrg	i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
278428d7b3dSmrg			src1);
279428d7b3dSmrg	/* texld r1, t2, s1 */
280428d7b3dSmrg	i += 3;
281428d7b3dSmrg	dest = UREG(REG_TYPE_R, 1);
282428d7b3dSmrg	src0 = UREG(REG_TYPE_T, 2);	/* COORD */
283428d7b3dSmrg	src1 = UREG(REG_TYPE_S, 1);	/* SAMPLER */
284428d7b3dSmrg	i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
285428d7b3dSmrg			src1);
286428d7b3dSmrg	/* add r0, r0, r1 */
287428d7b3dSmrg	i += 3;
288428d7b3dSmrg	dest = UREG(REG_TYPE_R, 0);
289428d7b3dSmrg	src0 = UREG(REG_TYPE_R, 0);
290428d7b3dSmrg	src1 = UREG(REG_TYPE_R, 1);
291428d7b3dSmrg	src2 = 0;
292428d7b3dSmrg	i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest,
293428d7b3dSmrg			A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */ , src0,
294428d7b3dSmrg			src1, src2);
295428d7b3dSmrg	/* mul oC, r0, c0 */
296428d7b3dSmrg	i += 3;
297428d7b3dSmrg	dest = UREG(REG_TYPE_OC, 0);
298428d7b3dSmrg	src0 = UREG(REG_TYPE_R, 0);
299428d7b3dSmrg	src1 = UREG(REG_TYPE_CONST, 0);
300428d7b3dSmrg	src2 = 0;
301428d7b3dSmrg	i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest,
302428d7b3dSmrg			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
303428d7b3dSmrg			src2);
304428d7b3dSmrg
305428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(pI915XvMC->psp_bo);
306428d7b3dSmrg
307428d7b3dSmrg	/* pixel shader contant static state */
308428d7b3dSmrg	drm_intel_gem_bo_map_gtt(pI915XvMC->psc_bo);
309428d7b3dSmrg	pixel_shader_constants = pI915XvMC->psc_bo->virtual;
310428d7b3dSmrg
311428d7b3dSmrg	memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants));
312428d7b3dSmrg	pixel_shader_constants->dw0.type = CMD_3D;
313428d7b3dSmrg	pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS;
314428d7b3dSmrg	pixel_shader_constants->dw0.length = 4;
315428d7b3dSmrg	pixel_shader_constants->dw1.reg_mask = REG_CR0;
316428d7b3dSmrg	pixel_shader_constants->value.x = 0.5;
317428d7b3dSmrg	pixel_shader_constants->value.y = 0.5;
318428d7b3dSmrg	pixel_shader_constants->value.z = 0.5;
319428d7b3dSmrg	pixel_shader_constants->value.w = 0.5;
320428d7b3dSmrg
321428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(pI915XvMC->psc_bo);
322428d7b3dSmrg}
323428d7b3dSmrg
324428d7b3dSmrgstatic void i915_mc_one_time_state_emit(XvMCContext * context)
325428d7b3dSmrg{
326428d7b3dSmrg	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
327428d7b3dSmrg	uint32_t load_state_immediate_1, load_indirect, s3_dword, s6_dword;
328428d7b3dSmrg	int mem_select;
329428d7b3dSmrg	BATCH_LOCALS;
330428d7b3dSmrg
331428d7b3dSmrg	/* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */
332428d7b3dSmrg	BEGIN_BATCH(3 + 8);
333428d7b3dSmrg	load_state_immediate_1 = OP_3D_LOAD_STATE_IMMEDIATE_1;
334428d7b3dSmrg	load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S3;
335428d7b3dSmrg	load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S6;
336428d7b3dSmrg	load_state_immediate_1 |= 3 - 2; /* length */
337428d7b3dSmrg	OUT_BATCH(load_state_immediate_1);
338428d7b3dSmrg
339428d7b3dSmrg	s3_dword = S3_SET0_PCD | S3_SET1_PCD |
340428d7b3dSmrg		   S3_SET2_PCD | S3_SET3_PCD |
341428d7b3dSmrg		   S3_SET4_PCD | S3_SET5_PCD |
342428d7b3dSmrg		   S3_SET6_PCD | S3_SET7_PCD;
343428d7b3dSmrg	OUT_BATCH(s3_dword);
344428d7b3dSmrg
345428d7b3dSmrg	s6_dword = S6_COLOR_BUFFER_WRITE | S6_DEPTH_TEST_ENABLE;
346428d7b3dSmrg	s6_dword |= 1 << S6_SRC_BLEND_FACTOR_SHIFT;
347428d7b3dSmrg	s6_dword |= 1 << S6_DST_BLEND_FACTOR_SHIFT;
348428d7b3dSmrg	OUT_BATCH(s6_dword);
349428d7b3dSmrg
350428d7b3dSmrg	/* 3DSTATE_LOAD_INDIRECT */
351428d7b3dSmrg	load_indirect = OP_3D_LOAD_INDIRECT;
352428d7b3dSmrg	load_indirect |= (BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC)
353428d7b3dSmrg				<< BLOCK_MASK_SHIFT;
354428d7b3dSmrg	load_indirect |= 8 - 2; /* length */
355428d7b3dSmrg
356428d7b3dSmrg	if (pI915XvMC->use_phys_addr)
357428d7b3dSmrg		mem_select = 0;	/* use physical address */
358428d7b3dSmrg	else {
359428d7b3dSmrg		load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
360428d7b3dSmrg		mem_select = 1;	/* use gfx address */
361428d7b3dSmrg	}
362428d7b3dSmrg
363428d7b3dSmrg	OUT_BATCH(load_indirect);
364428d7b3dSmrg
365428d7b3dSmrg	/* Dynamic indirect state buffer */
366428d7b3dSmrg	OUT_BATCH(0); /* no dynamic indirect state */
367428d7b3dSmrg
368428d7b3dSmrg	/* Sample state buffer */
369428d7b3dSmrg	OUT_RELOC(pI915XvMC->ssb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
370428d7b3dSmrg			STATE_VALID | STATE_FORCE);
371428d7b3dSmrg	OUT_BATCH(7);	/* 8 - 1 */
372428d7b3dSmrg
373428d7b3dSmrg	/* Pixel shader program buffer */
374428d7b3dSmrg	OUT_RELOC(pI915XvMC->psp_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
375428d7b3dSmrg			STATE_VALID | STATE_FORCE);
376428d7b3dSmrg	OUT_BATCH(66);	/* 4 + 16 + 16 + 31 - 1 */
377428d7b3dSmrg
378428d7b3dSmrg	/* Pixel shader constant buffer */
379428d7b3dSmrg	OUT_RELOC(pI915XvMC->psc_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
380428d7b3dSmrg			STATE_VALID | STATE_FORCE);
381428d7b3dSmrg	OUT_BATCH(5);	/* 6 - 1 */
382428d7b3dSmrg	ADVANCE_BATCH();
383428d7b3dSmrg}
384428d7b3dSmrg
385428d7b3dSmrgstatic void i915_mc_static_indirect_state_set(XvMCContext * context,
386428d7b3dSmrg					      XvMCSurface * dest,
387428d7b3dSmrg					      unsigned int picture_structure,
388428d7b3dSmrg					      unsigned int flags,
389428d7b3dSmrg					      unsigned int picture_coding_type)
390428d7b3dSmrg{
391428d7b3dSmrg	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
392428d7b3dSmrg	struct intel_xvmc_surface *intel_surf = dest->privData;
393428d7b3dSmrg	struct i915_mc_static_indirect_state_buffer *buffer_info;
394428d7b3dSmrg
395428d7b3dSmrg	drm_intel_gem_bo_map_gtt(pI915XvMC->sis_bo);
396428d7b3dSmrg	buffer_info = pI915XvMC->sis_bo->virtual;
397428d7b3dSmrg
398428d7b3dSmrg	memset(buffer_info, 0, sizeof(*buffer_info));
399428d7b3dSmrg
400428d7b3dSmrg	/* dest Y */
401428d7b3dSmrg	buffer_info->dest_y.dw0.type = CMD_3D;
402428d7b3dSmrg	buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
403428d7b3dSmrg	buffer_info->dest_y.dw0.length = 1;
404428d7b3dSmrg	buffer_info->dest_y.dw1.aux_id = 0;
405428d7b3dSmrg	buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK;
406428d7b3dSmrg	buffer_info->dest_y.dw1.fence_regs = 0;	/* disabled *//* FIXME: tiled y for performance */
407428d7b3dSmrg	buffer_info->dest_y.dw1.tiled_surface = 0;	/* linear */
408428d7b3dSmrg	buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR;
409428d7b3dSmrg	buffer_info->dest_y.dw1.pitch = (pI915XvMC->yStride >> 2);	/* in DWords */
410428d7b3dSmrg	buffer_info->dest_y.dw2.base_address = intel_surf->bo->offset >> 2;	/* starting DWORD address */
411428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
412428d7b3dSmrg				offsetof(typeof(*buffer_info),dest_y.dw2),
413428d7b3dSmrg				intel_surf->bo, 0,
414428d7b3dSmrg				I915_GEM_DOMAIN_RENDER,
415428d7b3dSmrg				I915_GEM_DOMAIN_RENDER);
416428d7b3dSmrg
417428d7b3dSmrg	/* dest U */
418428d7b3dSmrg	buffer_info->dest_u.dw0.type = CMD_3D;
419428d7b3dSmrg	buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
420428d7b3dSmrg	buffer_info->dest_u.dw0.length = 1;
421428d7b3dSmrg	buffer_info->dest_u.dw1.aux_id = 0;
422428d7b3dSmrg	buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX;
423428d7b3dSmrg	buffer_info->dest_u.dw1.fence_regs = 0;
424428d7b3dSmrg	buffer_info->dest_u.dw1.tiled_surface = 0;
425428d7b3dSmrg	buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR;
426428d7b3dSmrg	buffer_info->dest_u.dw1.pitch = (pI915XvMC->uvStride >> 2);	/* in DWords */
427428d7b3dSmrg	buffer_info->dest_u.dw2.base_address =
428428d7b3dSmrg		(intel_surf->bo->offset + UOFFSET(context)) >> 2;
429428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
430428d7b3dSmrg				offsetof(typeof(*buffer_info),dest_u.dw2),
431428d7b3dSmrg				intel_surf->bo, UOFFSET(context),
432428d7b3dSmrg				I915_GEM_DOMAIN_RENDER,
433428d7b3dSmrg				I915_GEM_DOMAIN_RENDER);
434428d7b3dSmrg
435428d7b3dSmrg	/* dest V */
436428d7b3dSmrg	buffer_info->dest_v.dw0.type = CMD_3D;
437428d7b3dSmrg	buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
438428d7b3dSmrg	buffer_info->dest_v.dw0.length = 1;
439428d7b3dSmrg	buffer_info->dest_v.dw1.aux_id = 1;
440428d7b3dSmrg	buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX;
441428d7b3dSmrg	buffer_info->dest_v.dw1.fence_regs = 0;
442428d7b3dSmrg	buffer_info->dest_v.dw1.tiled_surface = 0;
443428d7b3dSmrg	buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR;
444428d7b3dSmrg	buffer_info->dest_v.dw1.pitch = (pI915XvMC->uvStride >> 2);	/* in Dwords */
445428d7b3dSmrg	buffer_info->dest_v.dw2.base_address =
446428d7b3dSmrg		(intel_surf->bo->offset + VOFFSET(context)) >> 2;
447428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
448428d7b3dSmrg				offsetof(typeof(*buffer_info),dest_v.dw2),
449428d7b3dSmrg				intel_surf->bo, VOFFSET(context),
450428d7b3dSmrg				I915_GEM_DOMAIN_RENDER,
451428d7b3dSmrg				I915_GEM_DOMAIN_RENDER);
452428d7b3dSmrg
453428d7b3dSmrg	/* Dest buffer parameters */
454428d7b3dSmrg	buffer_info->dest_buf.dw0.type = CMD_3D;
455428d7b3dSmrg	buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES;
456428d7b3dSmrg	buffer_info->dest_buf.dw0.length = 0;
457428d7b3dSmrg	buffer_info->dest_buf.dw1.dest_v_bias = 8;	/* 0.5 */
458428d7b3dSmrg	buffer_info->dest_buf.dw1.dest_h_bias = 8;	/* 0.5 */
459428d7b3dSmrg	buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT;
460428d7b3dSmrg	buffer_info->dest_buf.dw1.v_ls = 0;	/* fill later */
461428d7b3dSmrg	buffer_info->dest_buf.dw1.v_ls_offset = 0;	/* fill later */
462428d7b3dSmrg	if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
463428d7b3dSmrg		;
464428d7b3dSmrg	} else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) {
465428d7b3dSmrg		buffer_info->dest_buf.dw1.v_ls = 1;
466428d7b3dSmrg	} else if ((picture_structure & XVMC_FRAME_PICTURE) ==
467428d7b3dSmrg		   XVMC_BOTTOM_FIELD) {
468428d7b3dSmrg		buffer_info->dest_buf.dw1.v_ls = 1;
469428d7b3dSmrg		buffer_info->dest_buf.dw1.v_ls_offset = 1;
470428d7b3dSmrg	}
471428d7b3dSmrg
472428d7b3dSmrg	/* MPEG buffer parameters */
473428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw0.type = CMD_3D;
474428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw0.opcode =
475428d7b3dSmrg	    OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG;
476428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw0.length = 1;
477428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC;
478428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.rcontrol = 0;	/* for MPEG-1/MPEG-2 */
479428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0;	/* for MPEG-1/MPEG-2/MPEG-4 */
480428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1;
481428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.intra8 = 0;	/* 16-bit formatted correction data */
482428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.tff = 1;	/* fill later */
483428d7b3dSmrg
484428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V;
485428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H;
486428d7b3dSmrg
487428d7b3dSmrg	if (picture_structure & XVMC_FRAME_PICTURE) {
488428d7b3dSmrg		;
489428d7b3dSmrg	} else if (picture_structure & XVMC_TOP_FIELD) {
490428d7b3dSmrg		if (flags & XVMC_SECOND_FIELD)
491428d7b3dSmrg			buffer_info->dest_buf_mpeg.dw1.tff = 0;
492428d7b3dSmrg		else
493428d7b3dSmrg			buffer_info->dest_buf_mpeg.dw1.tff = 1;
494428d7b3dSmrg	} else if (picture_structure & XVMC_BOTTOM_FIELD) {
495428d7b3dSmrg		if (flags & XVMC_SECOND_FIELD)
496428d7b3dSmrg			buffer_info->dest_buf_mpeg.dw1.tff = 1;
497428d7b3dSmrg		else
498428d7b3dSmrg			buffer_info->dest_buf_mpeg.dw1.tff = 0;
499428d7b3dSmrg	}
500428d7b3dSmrg
501428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4);	/* in macroblocks */
502428d7b3dSmrg	buffer_info->dest_buf_mpeg.dw2.picture_coding_type =
503428d7b3dSmrg	    picture_coding_type;
504428d7b3dSmrg
505428d7b3dSmrg	buffer_info->corr.dw0.type = CMD_3D;
506428d7b3dSmrg	buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
507428d7b3dSmrg	buffer_info->corr.dw0.length = 1;
508428d7b3dSmrg	buffer_info->corr.dw1.aux_id = 0;
509428d7b3dSmrg	buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR;
510428d7b3dSmrg	buffer_info->corr.dw1.aux_id = 0;
511428d7b3dSmrg	buffer_info->corr.dw1.fence_regs = 0;
512428d7b3dSmrg	buffer_info->corr.dw1.tiled_surface = 0;
513428d7b3dSmrg	buffer_info->corr.dw1.walk = 0;
514428d7b3dSmrg	buffer_info->corr.dw1.pitch = 0;
515428d7b3dSmrg	buffer_info->corr.dw2.base_address = pI915XvMC->corrdata_bo->offset >> 2;	/* starting DWORD address */
516428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
517428d7b3dSmrg				offsetof(typeof(*buffer_info),corr.dw2),
518428d7b3dSmrg				pI915XvMC->corrdata_bo, 0,
519428d7b3dSmrg				I915_GEM_DOMAIN_RENDER, 0);
520428d7b3dSmrg
521428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(pI915XvMC->sis_bo);
522428d7b3dSmrg}
523428d7b3dSmrg
524428d7b3dSmrgstatic void i915_mc_map_state_set(XvMCContext * context,
525428d7b3dSmrg				  struct intel_xvmc_surface * privPast,
526428d7b3dSmrg				  struct intel_xvmc_surface * privFuture)
527428d7b3dSmrg{
528428d7b3dSmrg	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
529428d7b3dSmrg	struct i915_mc_map_state *map_state;
530428d7b3dSmrg	unsigned int w = context->width;
531428d7b3dSmrg	unsigned int h = context->height;
532428d7b3dSmrg
533428d7b3dSmrg	drm_intel_gem_bo_map_gtt(pI915XvMC->msb_bo);
534428d7b3dSmrg	map_state = pI915XvMC->msb_bo->virtual;
535428d7b3dSmrg
536428d7b3dSmrg	memset(map_state, 0, sizeof(*map_state));
537428d7b3dSmrg
538428d7b3dSmrg	/* 3DSATE_MAP_STATE: Y */
539428d7b3dSmrg	map_state->y_map.dw0.type = CMD_3D;
540428d7b3dSmrg	map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
541428d7b3dSmrg	map_state->y_map.dw0.retain = 1;
542428d7b3dSmrg	map_state->y_map.dw0.length = 6;
543428d7b3dSmrg	map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
544428d7b3dSmrg
545428d7b3dSmrg	/* Y Forward (Past) */
546428d7b3dSmrg	map_state->y_forward.tm0.v_ls_offset = 0;
547428d7b3dSmrg	map_state->y_forward.tm0.v_ls = 0;
548428d7b3dSmrg	map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR;
549428d7b3dSmrg	map_state->y_forward.tm1.tiled_surface = 0;
550428d7b3dSmrg	map_state->y_forward.tm1.utilize_fence_regs = 0;
551428d7b3dSmrg	map_state->y_forward.tm1.texel_fmt = 0;	/* 8bit */
552428d7b3dSmrg	map_state->y_forward.tm1.surface_fmt = 1;	/* 8bit */
553428d7b3dSmrg	map_state->y_forward.tm1.width = w - 1;
554428d7b3dSmrg	map_state->y_forward.tm1.height = h - 1;
555428d7b3dSmrg	map_state->y_forward.tm2.depth = 0;
556428d7b3dSmrg	map_state->y_forward.tm2.max_lod = 0;
557428d7b3dSmrg	map_state->y_forward.tm2.cube_face = 0;
558428d7b3dSmrg	map_state->y_forward.tm0.base_address = privPast->bo->offset >> 2;
559428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
560428d7b3dSmrg				offsetof(typeof(*map_state),y_forward.tm0),
561428d7b3dSmrg				privPast->bo, 0,
562428d7b3dSmrg				I915_GEM_DOMAIN_SAMPLER, 0);
563428d7b3dSmrg	map_state->y_forward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;	/* in DWords - 1 */
564428d7b3dSmrg
565428d7b3dSmrg	/* Y Backward (Future) */
566428d7b3dSmrg	map_state->y_backward.tm0.v_ls_offset = 0;
567428d7b3dSmrg	map_state->y_backward.tm0.v_ls = 0;
568428d7b3dSmrg	map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR;
569428d7b3dSmrg	map_state->y_backward.tm1.tiled_surface = 0;
570428d7b3dSmrg	map_state->y_backward.tm1.utilize_fence_regs = 0;
571428d7b3dSmrg	map_state->y_backward.tm1.texel_fmt = 0;	/* 8bit */
572428d7b3dSmrg	map_state->y_backward.tm1.surface_fmt = 1;	/* 8bit */
573428d7b3dSmrg	map_state->y_backward.tm1.width = w - 1;
574428d7b3dSmrg	map_state->y_backward.tm1.height = h - 1;
575428d7b3dSmrg	map_state->y_backward.tm2.depth = 0;
576428d7b3dSmrg	map_state->y_backward.tm2.max_lod = 0;
577428d7b3dSmrg	map_state->y_backward.tm2.cube_face = 0;
578428d7b3dSmrg	map_state->y_backward.tm0.base_address = privFuture->bo->offset >> 2;
579428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
580428d7b3dSmrg				offsetof(typeof(*map_state),y_backward.tm0),
581428d7b3dSmrg				privFuture->bo, 0,
582428d7b3dSmrg				I915_GEM_DOMAIN_SAMPLER, 0);
583428d7b3dSmrg	map_state->y_backward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;
584428d7b3dSmrg
585428d7b3dSmrg	/* 3DSATE_MAP_STATE: U */
586428d7b3dSmrg	map_state->u_map.dw0.type = CMD_3D;
587428d7b3dSmrg	map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
588428d7b3dSmrg	map_state->u_map.dw0.retain = 1;
589428d7b3dSmrg	map_state->u_map.dw0.length = 6;
590428d7b3dSmrg	map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
591428d7b3dSmrg
592428d7b3dSmrg	/* U Forward */
593428d7b3dSmrg	map_state->u_forward.tm0.v_ls_offset = 0;
594428d7b3dSmrg	map_state->u_forward.tm0.v_ls = 0;
595428d7b3dSmrg	map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR;
596428d7b3dSmrg	map_state->u_forward.tm1.tiled_surface = 0;
597428d7b3dSmrg	map_state->u_forward.tm1.utilize_fence_regs = 0;
598428d7b3dSmrg	map_state->u_forward.tm1.texel_fmt = 0;	/* 8bit */
599428d7b3dSmrg	map_state->u_forward.tm1.surface_fmt = 1;	/* 8bit */
600428d7b3dSmrg	map_state->u_forward.tm1.width = (w >> 1) - 1;
601428d7b3dSmrg	map_state->u_forward.tm1.height = (h >> 1) - 1;
602428d7b3dSmrg	map_state->u_forward.tm2.depth = 0;
603428d7b3dSmrg	map_state->u_forward.tm2.max_lod = 0;
604428d7b3dSmrg	map_state->u_forward.tm2.cube_face = 0;
605428d7b3dSmrg	map_state->u_forward.tm0.base_address =
606428d7b3dSmrg		(privPast->bo->offset + UOFFSET(context)) >> 2;
607428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
608428d7b3dSmrg				offsetof(typeof(*map_state),u_forward.tm0),
609428d7b3dSmrg				privPast->bo, UOFFSET(context),
610428d7b3dSmrg				I915_GEM_DOMAIN_SAMPLER, 0);
611428d7b3dSmrg	map_state->u_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;	/* in DWords - 1 */
612428d7b3dSmrg
613428d7b3dSmrg	/* U Backward */
614428d7b3dSmrg	map_state->u_backward.tm0.v_ls_offset = 0;
615428d7b3dSmrg	map_state->u_backward.tm0.v_ls = 0;
616428d7b3dSmrg	map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR;
617428d7b3dSmrg	map_state->u_backward.tm1.tiled_surface = 0;
618428d7b3dSmrg	map_state->u_backward.tm1.utilize_fence_regs = 0;
619428d7b3dSmrg	map_state->u_backward.tm1.texel_fmt = 0;
620428d7b3dSmrg	map_state->u_backward.tm1.surface_fmt = 1;
621428d7b3dSmrg	map_state->u_backward.tm1.width = (w >> 1) - 1;
622428d7b3dSmrg	map_state->u_backward.tm1.height = (h >> 1) - 1;
623428d7b3dSmrg	map_state->u_backward.tm2.depth = 0;
624428d7b3dSmrg	map_state->u_backward.tm2.max_lod = 0;
625428d7b3dSmrg	map_state->u_backward.tm2.cube_face = 0;
626428d7b3dSmrg	map_state->u_backward.tm0.base_address =
627428d7b3dSmrg		(privFuture->bo->offset + UOFFSET(context)) >> 2;
628428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
629428d7b3dSmrg				offsetof(typeof(*map_state),u_backward.tm0),
630428d7b3dSmrg				privFuture->bo, UOFFSET(context),
631428d7b3dSmrg				I915_GEM_DOMAIN_SAMPLER, 0);
632428d7b3dSmrg	map_state->u_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
633428d7b3dSmrg
634428d7b3dSmrg	/* 3DSATE_MAP_STATE: V */
635428d7b3dSmrg	map_state->v_map.dw0.type = CMD_3D;
636428d7b3dSmrg	map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
637428d7b3dSmrg	map_state->v_map.dw0.retain = 1;
638428d7b3dSmrg	map_state->v_map.dw0.length = 6;
639428d7b3dSmrg	map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
640428d7b3dSmrg
641428d7b3dSmrg	/* V Forward */
642428d7b3dSmrg	map_state->v_forward.tm0.v_ls_offset = 0;
643428d7b3dSmrg	map_state->v_forward.tm0.v_ls = 0;
644428d7b3dSmrg	map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR;
645428d7b3dSmrg	map_state->v_forward.tm1.tiled_surface = 0;
646428d7b3dSmrg	map_state->v_forward.tm1.utilize_fence_regs = 0;
647428d7b3dSmrg	map_state->v_forward.tm1.texel_fmt = 0;
648428d7b3dSmrg	map_state->v_forward.tm1.surface_fmt = 1;
649428d7b3dSmrg	map_state->v_forward.tm1.width = (w >> 1) - 1;
650428d7b3dSmrg	map_state->v_forward.tm1.height = (h >> 1) - 1;
651428d7b3dSmrg	map_state->v_forward.tm2.depth = 0;
652428d7b3dSmrg	map_state->v_forward.tm2.max_lod = 0;
653428d7b3dSmrg	map_state->v_forward.tm2.cube_face = 0;
654428d7b3dSmrg	map_state->v_forward.tm0.base_address =
655428d7b3dSmrg		(privPast->bo->offset + VOFFSET(context)) >> 2;
656428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
657428d7b3dSmrg				offsetof(typeof(*map_state),v_forward.tm0),
658428d7b3dSmrg				privPast->bo, VOFFSET(context),
659428d7b3dSmrg				I915_GEM_DOMAIN_SAMPLER, 0);
660428d7b3dSmrg	map_state->v_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;	/* in DWords - 1 */
661428d7b3dSmrg
662428d7b3dSmrg	/* V Backward */
663428d7b3dSmrg	map_state->v_backward.tm0.v_ls_offset = 0;
664428d7b3dSmrg	map_state->v_backward.tm0.v_ls = 0;
665428d7b3dSmrg	map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR;
666428d7b3dSmrg	map_state->v_backward.tm1.tiled_surface = 0;
667428d7b3dSmrg	map_state->v_backward.tm1.utilize_fence_regs = 0;
668428d7b3dSmrg	map_state->v_backward.tm1.texel_fmt = 0;
669428d7b3dSmrg	map_state->v_backward.tm1.surface_fmt = 1;
670428d7b3dSmrg	map_state->v_backward.tm1.width = (w >> 1) - 1;
671428d7b3dSmrg	map_state->v_backward.tm1.height = (h >> 1) - 1;
672428d7b3dSmrg	map_state->v_backward.tm2.depth = 0;
673428d7b3dSmrg	map_state->v_backward.tm2.max_lod = 0;
674428d7b3dSmrg	map_state->v_backward.tm2.cube_face = 0;
675428d7b3dSmrg	map_state->v_backward.tm0.base_address =
676428d7b3dSmrg		(privFuture->bo->offset + VOFFSET(context)) >> 2;
677428d7b3dSmrg	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
678428d7b3dSmrg				offsetof(typeof(*map_state),v_backward.tm0),
679428d7b3dSmrg				privFuture->bo, VOFFSET(context),
680428d7b3dSmrg				I915_GEM_DOMAIN_SAMPLER, 0);
681428d7b3dSmrg	map_state->v_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
682428d7b3dSmrg
683428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(pI915XvMC->msb_bo);
684428d7b3dSmrg}
685428d7b3dSmrg
686428d7b3dSmrgstatic void i915_mc_load_indirect_render_emit(XvMCContext * context)
687428d7b3dSmrg{
688428d7b3dSmrg	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
689428d7b3dSmrg	int mem_select;
690428d7b3dSmrg	uint32_t load_indirect;
691428d7b3dSmrg	BATCH_LOCALS;
692428d7b3dSmrg
693428d7b3dSmrg	BEGIN_BATCH(5);
694428d7b3dSmrg	load_indirect = OP_3D_LOAD_INDIRECT;
695428d7b3dSmrg	load_indirect |= (BLOCK_SIS | BLOCK_MSB) << BLOCK_MASK_SHIFT;
696428d7b3dSmrg	load_indirect |= 5 - 2; /* length */
697428d7b3dSmrg
698428d7b3dSmrg	if (pI915XvMC->use_phys_addr)
699428d7b3dSmrg		mem_select = 0;	/* use physical address */
700428d7b3dSmrg	else {
701428d7b3dSmrg		load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
702428d7b3dSmrg		mem_select = 1;	/* use gfx address */
703428d7b3dSmrg	}
704428d7b3dSmrg	OUT_BATCH(load_indirect);
705428d7b3dSmrg
706428d7b3dSmrg	/* Static Indirect state buffer (dest buffer info) */
707428d7b3dSmrg	OUT_RELOC(pI915XvMC->sis_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
708428d7b3dSmrg			STATE_VALID | STATE_FORCE);
709428d7b3dSmrg	OUT_BATCH(16);	/* 4 * 3 + 2 + 3 - 1 */
710428d7b3dSmrg
711428d7b3dSmrg	/* Map state buffer (reference buffer info) */
712428d7b3dSmrg	OUT_RELOC(pI915XvMC->msb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
713428d7b3dSmrg			STATE_VALID | STATE_FORCE);
714428d7b3dSmrg	OUT_BATCH(23);	/* 3 * 8 - 1 */
715428d7b3dSmrg	ADVANCE_BATCH();
716428d7b3dSmrg}
717428d7b3dSmrg
718428d7b3dSmrgstatic void i915_mc_mpeg_set_origin(XvMCContext * context, XvMCMacroBlock * mb)
719428d7b3dSmrg{
720428d7b3dSmrg	struct i915_3dmpeg_set_origin set_origin;
721428d7b3dSmrg
722428d7b3dSmrg	/* 3DMPEG_SET_ORIGIN */
723428d7b3dSmrg	memset(&set_origin, 0, sizeof(set_origin));
724428d7b3dSmrg	set_origin.dw0.type = CMD_3D;
725428d7b3dSmrg	set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN;
726428d7b3dSmrg	set_origin.dw0.length = 0;
727428d7b3dSmrg	set_origin.dw1.h_origin = mb->x;
728428d7b3dSmrg	set_origin.dw1.v_origin = mb->y;
729428d7b3dSmrg
730428d7b3dSmrg	intelBatchbufferData(&set_origin, sizeof(set_origin), 0);
731428d7b3dSmrg}
732428d7b3dSmrg
733428d7b3dSmrgstatic void i915_mc_mpeg_macroblock_ipicture(XvMCContext * context,
734428d7b3dSmrg					     XvMCMacroBlock * mb)
735428d7b3dSmrg{
736428d7b3dSmrg	struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture;
737428d7b3dSmrg
738428d7b3dSmrg	/* 3DMPEG_MACROBLOCK_IPICTURE */
739428d7b3dSmrg	memset(&macroblock_ipicture, 0, sizeof(macroblock_ipicture));
740428d7b3dSmrg	macroblock_ipicture.dw0.type = CMD_3D;
741428d7b3dSmrg	macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE;
742428d7b3dSmrg	macroblock_ipicture.dw0.dct_type =
743428d7b3dSmrg	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
744428d7b3dSmrg
745428d7b3dSmrg	intelBatchbufferData(&macroblock_ipicture, sizeof(macroblock_ipicture),
746428d7b3dSmrg			     0);
747428d7b3dSmrg}
748428d7b3dSmrg
749428d7b3dSmrgstatic void i915_mc_mpeg_macroblock_1fbmv(XvMCContext * context,
750428d7b3dSmrg					  XvMCMacroBlock * mb)
751428d7b3dSmrg{
752428d7b3dSmrg	struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv;
753428d7b3dSmrg	vector_t mv0[2];
754428d7b3dSmrg
755428d7b3dSmrg	/* 3DMPEG_MACROBLOCK(1fbmv) */
756428d7b3dSmrg	memset(&macroblock_1fbmv, 0, sizeof(macroblock_1fbmv));
757428d7b3dSmrg	macroblock_1fbmv.header.dw0.type = CMD_3D;
758428d7b3dSmrg	macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
759428d7b3dSmrg	macroblock_1fbmv.header.dw0.length = 2;
760428d7b3dSmrg	macroblock_1fbmv.header.dw1.mb_intra = 0;	/* should be 0 */
761428d7b3dSmrg	macroblock_1fbmv.header.dw1.forward =
762428d7b3dSmrg	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
763428d7b3dSmrg	macroblock_1fbmv.header.dw1.backward =
764428d7b3dSmrg	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
765428d7b3dSmrg	macroblock_1fbmv.header.dw1.h263_4mv = 0;	/* should be 0 */
766428d7b3dSmrg	macroblock_1fbmv.header.dw1.dct_type =
767428d7b3dSmrg	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
768428d7b3dSmrg
769428d7b3dSmrg	if (!(mb->coded_block_pattern & 0x3f))
770428d7b3dSmrg		macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
771428d7b3dSmrg
772428d7b3dSmrg	macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
773428d7b3dSmrg	macroblock_1fbmv.header.dw1.vertical_field_select =
774428d7b3dSmrg	    (mb->motion_vertical_field_select & 0x0f);
775428d7b3dSmrg	macroblock_1fbmv.header.dw1.coded_block_pattern =
776428d7b3dSmrg	    mb->coded_block_pattern;
777428d7b3dSmrg	macroblock_1fbmv.header.dw1.skipped_macroblocks = 0;
778428d7b3dSmrg
779428d7b3dSmrg	mv0[0].component[0] = mb->PMV[0][0][0];
780428d7b3dSmrg	mv0[0].component[1] = mb->PMV[0][0][1];
781428d7b3dSmrg	mv0[1].component[0] = mb->PMV[0][1][0];
782428d7b3dSmrg	mv0[1].component[1] = mb->PMV[0][1][1];
783428d7b3dSmrg
784428d7b3dSmrg	macroblock_1fbmv.dw2 = mv0[0].v;
785428d7b3dSmrg	macroblock_1fbmv.dw3 = mv0[1].v;
786428d7b3dSmrg
787428d7b3dSmrg	intelBatchbufferData(&macroblock_1fbmv, sizeof(macroblock_1fbmv), 0);
788428d7b3dSmrg}
789428d7b3dSmrg
790428d7b3dSmrgstatic void i915_mc_mpeg_macroblock_2fbmv(XvMCContext * context,
791428d7b3dSmrg					  XvMCMacroBlock * mb, unsigned int ps)
792428d7b3dSmrg{
793428d7b3dSmrg	struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv;
794428d7b3dSmrg	vector_t mv0[2];
795428d7b3dSmrg	vector_t mv1[2];
796428d7b3dSmrg
797428d7b3dSmrg	/* 3DMPEG_MACROBLOCK(2fbmv) */
798428d7b3dSmrg	memset(&macroblock_2fbmv, 0, sizeof(macroblock_2fbmv));
799428d7b3dSmrg	macroblock_2fbmv.header.dw0.type = CMD_3D;
800428d7b3dSmrg	macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
801428d7b3dSmrg	macroblock_2fbmv.header.dw0.length = 4;
802428d7b3dSmrg	macroblock_2fbmv.header.dw1.mb_intra = 0;	/* should be 0 */
803428d7b3dSmrg	macroblock_2fbmv.header.dw1.forward =
804428d7b3dSmrg	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
805428d7b3dSmrg	macroblock_2fbmv.header.dw1.backward =
806428d7b3dSmrg	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
807428d7b3dSmrg	macroblock_2fbmv.header.dw1.h263_4mv = 0;	/* should be 0 */
808428d7b3dSmrg	macroblock_2fbmv.header.dw1.dct_type =
809428d7b3dSmrg	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
810428d7b3dSmrg
811428d7b3dSmrg	if (!(mb->coded_block_pattern & 0x3f))
812428d7b3dSmrg		macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
813428d7b3dSmrg
814428d7b3dSmrg	macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
815428d7b3dSmrg	macroblock_2fbmv.header.dw1.vertical_field_select =
816428d7b3dSmrg	    (mb->motion_vertical_field_select & 0x0f);
817428d7b3dSmrg	macroblock_2fbmv.header.dw1.coded_block_pattern =
818428d7b3dSmrg	    mb->coded_block_pattern;
819428d7b3dSmrg	macroblock_2fbmv.header.dw1.skipped_macroblocks = 0;
820428d7b3dSmrg
821428d7b3dSmrg	mv0[0].component[0] = mb->PMV[0][0][0];
822428d7b3dSmrg	mv0[0].component[1] = mb->PMV[0][0][1];
823428d7b3dSmrg	mv0[1].component[0] = mb->PMV[0][1][0];
824428d7b3dSmrg	mv0[1].component[1] = mb->PMV[0][1][1];
825428d7b3dSmrg	mv1[0].component[0] = mb->PMV[1][0][0];
826428d7b3dSmrg	mv1[0].component[1] = mb->PMV[1][0][1];
827428d7b3dSmrg	mv1[1].component[0] = mb->PMV[1][1][0];
828428d7b3dSmrg	mv1[1].component[1] = mb->PMV[1][1][1];
829428d7b3dSmrg
830428d7b3dSmrg	if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
831428d7b3dSmrg		if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) {
832428d7b3dSmrg			mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
833428d7b3dSmrg			mv0[1].component[1] = mb->PMV[0][1][1] >> 1;
834428d7b3dSmrg			mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
835428d7b3dSmrg			mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
836428d7b3dSmrg		} else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) {
837428d7b3dSmrg			mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
838428d7b3dSmrg			mv0[1].component[1] = mb->PMV[0][1][1] >> 1;	// MPEG2 MV[0][1] isn't used
839428d7b3dSmrg			mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
840428d7b3dSmrg			mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
841428d7b3dSmrg		}
842428d7b3dSmrg	}
843428d7b3dSmrg
844428d7b3dSmrg	macroblock_2fbmv.dw2 = mv0[0].v;
845428d7b3dSmrg	macroblock_2fbmv.dw3 = mv0[1].v;
846428d7b3dSmrg	macroblock_2fbmv.dw4 = mv1[0].v;
847428d7b3dSmrg	macroblock_2fbmv.dw5 = mv1[1].v;
848428d7b3dSmrg
849428d7b3dSmrg	intelBatchbufferData(&macroblock_2fbmv, sizeof(macroblock_2fbmv), 0);
850428d7b3dSmrg}
851428d7b3dSmrg
852428d7b3dSmrgstatic int i915_xvmc_alloc_one_time_buffers(i915XvMCContext *pI915XvMC)
853428d7b3dSmrg{
854428d7b3dSmrg	pI915XvMC->ssb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
855428d7b3dSmrg					       "ssb",
856428d7b3dSmrg					       GTT_PAGE_SIZE,
857428d7b3dSmrg					       GTT_PAGE_SIZE);
858428d7b3dSmrg	if (!pI915XvMC->ssb_bo)
859428d7b3dSmrg		return 0;
860428d7b3dSmrg
861428d7b3dSmrg	pI915XvMC->psp_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
862428d7b3dSmrg					       "psp",
863428d7b3dSmrg					       GTT_PAGE_SIZE,
864428d7b3dSmrg					       GTT_PAGE_SIZE);
865428d7b3dSmrg	if (!pI915XvMC->psp_bo)
866428d7b3dSmrg		return 0;
867428d7b3dSmrg
868428d7b3dSmrg	pI915XvMC->psc_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
869428d7b3dSmrg					       "psc",
870428d7b3dSmrg					       GTT_PAGE_SIZE,
871428d7b3dSmrg					       GTT_PAGE_SIZE);
872428d7b3dSmrg	if (!pI915XvMC->psc_bo)
873428d7b3dSmrg		return 0;
874428d7b3dSmrg
875428d7b3dSmrg	return 1;
876428d7b3dSmrg}
877428d7b3dSmrg
878428d7b3dSmrgstatic void i915_xvmc_free_one_time_buffers(i915XvMCContext *pI915XvMC)
879428d7b3dSmrg{
880428d7b3dSmrg	drm_intel_bo_unreference(pI915XvMC->ssb_bo);
881428d7b3dSmrg	drm_intel_bo_unreference(pI915XvMC->psp_bo);
882428d7b3dSmrg	drm_intel_bo_unreference(pI915XvMC->psc_bo);
883428d7b3dSmrg}
884428d7b3dSmrg
885428d7b3dSmrg/*
886428d7b3dSmrg * Function: i915_release_resource
887428d7b3dSmrg */
888428d7b3dSmrgstatic void i915_release_resource(Display * display, XvMCContext * context)
889428d7b3dSmrg{
890428d7b3dSmrg	i915XvMCContext *pI915XvMC;
891428d7b3dSmrg
892428d7b3dSmrg	if (!(pI915XvMC = context->privData))
893428d7b3dSmrg		return;
894428d7b3dSmrg
895428d7b3dSmrg	i915_xvmc_free_one_time_buffers(pI915XvMC);
896428d7b3dSmrg
897428d7b3dSmrg	free(pI915XvMC);
898428d7b3dSmrg	context->privData = NULL;
899428d7b3dSmrg}
900428d7b3dSmrg
901428d7b3dSmrgstatic Status i915_xvmc_mc_create_context(Display * display,
902428d7b3dSmrg					  XvMCContext * context, int priv_count,
903428d7b3dSmrg					  CARD32 * priv_data)
904428d7b3dSmrg{
905428d7b3dSmrg	i915XvMCContext *pI915XvMC = NULL;
906428d7b3dSmrg	struct intel_xvmc_hw_context *tmpComm = NULL;
907428d7b3dSmrg
908428d7b3dSmrg	if (priv_count != (sizeof(struct intel_xvmc_hw_context) >> 2)) {
909428d7b3dSmrg		XVMC_ERR
910428d7b3dSmrg		    ("_xvmc_create_context() returned incorrect data size!");
911428d7b3dSmrg		XVMC_INFO("\tExpected %d, got %d",
912428d7b3dSmrg			  (int)(sizeof(struct intel_xvmc_hw_context) >> 2),
913428d7b3dSmrg			  priv_count);
914428d7b3dSmrg		_xvmc_destroy_context(display, context);
915428d7b3dSmrg		XFree(priv_data);
916428d7b3dSmrg		context->privData = NULL;
917428d7b3dSmrg		return BadValue;
918428d7b3dSmrg	}
919428d7b3dSmrg
920428d7b3dSmrg	context->privData = (void *)calloc(1, sizeof(i915XvMCContext));
921428d7b3dSmrg	if (!context->privData) {
922428d7b3dSmrg		XVMC_ERR("Unable to allocate resources for XvMC context.");
923428d7b3dSmrg		return BadAlloc;
924428d7b3dSmrg	}
925428d7b3dSmrg	pI915XvMC = (i915XvMCContext *) context->privData;
926428d7b3dSmrg
927428d7b3dSmrg	tmpComm = (struct intel_xvmc_hw_context *) priv_data;
928428d7b3dSmrg	pI915XvMC->use_phys_addr = tmpComm->i915.use_phys_addr;
929428d7b3dSmrg	pI915XvMC->comm.surface_bo_size = SIZE_YUV420(context->width,
930428d7b3dSmrg						      context->height);
931428d7b3dSmrg
932428d7b3dSmrg	/* Must free the private data we were passed from X */
933428d7b3dSmrg	XFree(priv_data);
934428d7b3dSmrg	priv_data = NULL;
935428d7b3dSmrg
936428d7b3dSmrg	if (!i915_xvmc_alloc_one_time_buffers(pI915XvMC))
937428d7b3dSmrg		goto free_one_time_buffers;
938428d7b3dSmrg
939428d7b3dSmrg	/* Initialize private context values */
940428d7b3dSmrg	pI915XvMC->yStride = STRIDE(context->width);
941428d7b3dSmrg	pI915XvMC->uvStride = STRIDE(context->width >> 1);
942428d7b3dSmrg
943428d7b3dSmrg	/* pre-init state buffers */
944428d7b3dSmrg	i915_mc_one_time_context_init(context);
945428d7b3dSmrg
946428d7b3dSmrg	return Success;
947428d7b3dSmrg
948428d7b3dSmrgfree_one_time_buffers:
949428d7b3dSmrg	i915_xvmc_free_one_time_buffers(pI915XvMC);
950428d7b3dSmrg	free(pI915XvMC);
951428d7b3dSmrg	context->privData = NULL;
952428d7b3dSmrg	return BadAlloc;
953428d7b3dSmrg}
954428d7b3dSmrg
955428d7b3dSmrgstatic int i915_xvmc_mc_destroy_context(Display * display,
956428d7b3dSmrg					XvMCContext * context)
957428d7b3dSmrg{
958428d7b3dSmrg	i915XvMCContext *pI915XvMC;
959428d7b3dSmrg
960428d7b3dSmrg	if (!(pI915XvMC = context->privData))
961428d7b3dSmrg		return XvMCBadContext;
962428d7b3dSmrg
963428d7b3dSmrg	/* Pass Control to the X server to destroy the drm_context_t */
964428d7b3dSmrg	i915_release_resource(display, context);
965428d7b3dSmrg
966428d7b3dSmrg	return Success;
967428d7b3dSmrg}
968428d7b3dSmrg
969428d7b3dSmrgstatic int i915_xvmc_alloc_render_state_buffers(i915XvMCContext *pI915XvMC)
970428d7b3dSmrg{
971428d7b3dSmrg	pI915XvMC->sis_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
972428d7b3dSmrg					       "sis",
973428d7b3dSmrg					       GTT_PAGE_SIZE,
974428d7b3dSmrg					       GTT_PAGE_SIZE);
975428d7b3dSmrg	if (!pI915XvMC->sis_bo)
976428d7b3dSmrg		return 0;
977428d7b3dSmrg
978428d7b3dSmrg	pI915XvMC->msb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
979428d7b3dSmrg					       "msb",
980428d7b3dSmrg					       GTT_PAGE_SIZE,
981428d7b3dSmrg					       GTT_PAGE_SIZE);
982428d7b3dSmrg	if (!pI915XvMC->msb_bo)
983428d7b3dSmrg		return 0;
984428d7b3dSmrg
985428d7b3dSmrg	pI915XvMC->corrdata_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
986428d7b3dSmrg					       "corrdata",
987428d7b3dSmrg					       CORRDATA_SIZE,
988428d7b3dSmrg					       GTT_PAGE_SIZE);
989428d7b3dSmrg	if (!pI915XvMC->corrdata_bo)
990428d7b3dSmrg		return 0;
991428d7b3dSmrg
992428d7b3dSmrg	return 1;
993428d7b3dSmrg}
994428d7b3dSmrg
995428d7b3dSmrgstatic void i915_xvmc_free_render_state_buffers(i915XvMCContext *pI915XvMC)
996428d7b3dSmrg{
997428d7b3dSmrg	drm_intel_bo_unreference(pI915XvMC->sis_bo);
998428d7b3dSmrg	drm_intel_bo_unreference(pI915XvMC->msb_bo);
999428d7b3dSmrg	drm_intel_bo_unreference(pI915XvMC->corrdata_bo);
1000428d7b3dSmrg}
1001428d7b3dSmrg
1002428d7b3dSmrgstatic int i915_xvmc_mc_render_surface(Display * display, XvMCContext * context,
1003428d7b3dSmrg				       unsigned int picture_structure,
1004428d7b3dSmrg				       XvMCSurface * target_surface,
1005428d7b3dSmrg				       XvMCSurface * past_surface,
1006428d7b3dSmrg				       XvMCSurface * future_surface,
1007428d7b3dSmrg				       unsigned int flags,
1008428d7b3dSmrg				       unsigned int num_macroblocks,
1009428d7b3dSmrg				       unsigned int first_macroblock,
1010428d7b3dSmrg				       XvMCMacroBlockArray * macroblock_array,
1011428d7b3dSmrg				       XvMCBlockArray * blocks)
1012428d7b3dSmrg{
1013428d7b3dSmrg	int i;
1014428d7b3dSmrg	int picture_coding_type = MPEG_I_PICTURE;
1015428d7b3dSmrg	/* correction data buffer */
1016428d7b3dSmrg	char *corrdata_ptr;
1017428d7b3dSmrg	int corrdata_size = 0;
1018428d7b3dSmrg
1019428d7b3dSmrg	/* Block Pointer */
1020428d7b3dSmrg	short *block_ptr;
1021428d7b3dSmrg	/* Current Macroblock Pointer */
1022428d7b3dSmrg	XvMCMacroBlock *mb;
1023428d7b3dSmrg
1024428d7b3dSmrg	intel_xvmc_context_ptr intel_ctx;
1025428d7b3dSmrg
1026428d7b3dSmrg	struct intel_xvmc_surface *privTarget = NULL;
1027428d7b3dSmrg	struct intel_xvmc_surface *privFuture = NULL;
1028428d7b3dSmrg	struct intel_xvmc_surface *privPast = NULL;
1029428d7b3dSmrg	i915XvMCContext *pI915XvMC = NULL;
1030428d7b3dSmrg
1031428d7b3dSmrg	/* Check Parameters for validity */
1032428d7b3dSmrg	if (!display || !context || !target_surface) {
1033428d7b3dSmrg		XVMC_ERR("Invalid Display, Context or Target!");
1034428d7b3dSmrg		return BadValue;
1035428d7b3dSmrg	}
1036428d7b3dSmrg
1037428d7b3dSmrg	if (!num_macroblocks)
1038428d7b3dSmrg		return Success;
1039428d7b3dSmrg
1040428d7b3dSmrg	if (!macroblock_array || !blocks) {
1041428d7b3dSmrg		XVMC_ERR("Invalid block data!");
1042428d7b3dSmrg		return BadValue;
1043428d7b3dSmrg	}
1044428d7b3dSmrg
1045428d7b3dSmrg	if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
1046428d7b3dSmrg		XVMC_ERR("Too many macroblocks requested for MB array size.");
1047428d7b3dSmrg		return BadValue;
1048428d7b3dSmrg	}
1049428d7b3dSmrg
1050428d7b3dSmrg	if (!(pI915XvMC = context->privData))
1051428d7b3dSmrg		return XvMCBadContext;
1052428d7b3dSmrg
1053428d7b3dSmrg	if (!(privTarget = target_surface->privData))
1054428d7b3dSmrg		return XvMCBadSurface;
1055428d7b3dSmrg
1056428d7b3dSmrg	if (!i915_xvmc_alloc_render_state_buffers(pI915XvMC))
1057428d7b3dSmrg		return BadAlloc;
1058428d7b3dSmrg
1059428d7b3dSmrg	intel_ctx = context->privData;
1060428d7b3dSmrg	if (!intel_ctx) {
1061428d7b3dSmrg		XVMC_ERR("Can't find intel xvmc context\n");
1062428d7b3dSmrg		return BadValue;
1063428d7b3dSmrg	}
1064428d7b3dSmrg
1065428d7b3dSmrg	/* P Frame Test */
1066428d7b3dSmrg	if (!past_surface) {
1067428d7b3dSmrg		/* Just to avoid some ifs later. */
1068428d7b3dSmrg		privPast = privTarget;
1069428d7b3dSmrg	} else {
1070428d7b3dSmrg		if (!(privPast = past_surface->privData)) {
1071428d7b3dSmrg			return XvMCBadSurface;
1072428d7b3dSmrg		}
1073428d7b3dSmrg		picture_coding_type = MPEG_P_PICTURE;
1074428d7b3dSmrg	}
1075428d7b3dSmrg
1076428d7b3dSmrg	/* B Frame Test */
1077428d7b3dSmrg	if (!future_surface) {
1078428d7b3dSmrg		privFuture = privPast;	// privTarget;
1079428d7b3dSmrg	} else {
1080428d7b3dSmrg		if (!past_surface) {
1081428d7b3dSmrg			XVMC_ERR("No Past Surface!");
1082428d7b3dSmrg			return BadValue;
1083428d7b3dSmrg		}
1084428d7b3dSmrg
1085428d7b3dSmrg		if (!(privFuture = future_surface->privData)) {
1086428d7b3dSmrg			XVMC_ERR("Invalid Future Surface!");
1087428d7b3dSmrg			return XvMCBadSurface;
1088428d7b3dSmrg		}
1089428d7b3dSmrg
1090428d7b3dSmrg		picture_coding_type = MPEG_B_PICTURE;
1091428d7b3dSmrg	}
1092428d7b3dSmrg
1093428d7b3dSmrg	LOCK_HARDWARE(intel_ctx->hw_context);
1094428d7b3dSmrg	drm_intel_gem_bo_map_gtt(pI915XvMC->corrdata_bo);
1095428d7b3dSmrg	corrdata_ptr = pI915XvMC->corrdata_bo->virtual;
1096428d7b3dSmrg	corrdata_size = 0;
1097428d7b3dSmrg
1098428d7b3dSmrg	for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
1099428d7b3dSmrg	     i++) {
1100428d7b3dSmrg		int bspm = 0;
1101428d7b3dSmrg		mb = &macroblock_array->macro_blocks[i];
1102428d7b3dSmrg		block_ptr = &(blocks->blocks[mb->index << 6]);
1103428d7b3dSmrg
1104428d7b3dSmrg		/* Lockup can happen if the coordinates are too far out of range */
1105428d7b3dSmrg		if (mb->x > (target_surface->width >> 4)) {
1106428d7b3dSmrg			mb->x = 0;
1107428d7b3dSmrg			XVMC_INFO("reset x");
1108428d7b3dSmrg		}
1109428d7b3dSmrg
1110428d7b3dSmrg		if (mb->y > (target_surface->height >> 4)) {
1111428d7b3dSmrg			mb->y = 0;
1112428d7b3dSmrg			XVMC_INFO("reset y");
1113428d7b3dSmrg		}
1114428d7b3dSmrg
1115428d7b3dSmrg		/* Catch no pattern case */
1116428d7b3dSmrg		if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) &&
1117428d7b3dSmrg		    !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) &&
1118428d7b3dSmrg		    mb->coded_block_pattern) {
1119428d7b3dSmrg			mb->coded_block_pattern = 0;
1120428d7b3dSmrg			XVMC_INFO("no coded blocks present!");
1121428d7b3dSmrg		}
1122428d7b3dSmrg
1123428d7b3dSmrg		bspm = mb_bytes_420[mb->coded_block_pattern];
1124428d7b3dSmrg
1125428d7b3dSmrg		if (!bspm)
1126428d7b3dSmrg			continue;
1127428d7b3dSmrg
1128428d7b3dSmrg		corrdata_size += bspm;
1129428d7b3dSmrg
1130428d7b3dSmrg		if (corrdata_size > CORRDATA_SIZE) {
1131428d7b3dSmrg			XVMC_ERR("correction data buffer overflow.");
1132428d7b3dSmrg			break;
1133428d7b3dSmrg		}
1134428d7b3dSmrg		memcpy(corrdata_ptr, block_ptr, bspm);
1135428d7b3dSmrg		corrdata_ptr += bspm;
1136428d7b3dSmrg	}
1137428d7b3dSmrg
1138428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(pI915XvMC->corrdata_bo);
1139428d7b3dSmrg
1140428d7b3dSmrg	// i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB
1141428d7b3dSmrg	// | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC);
1142428d7b3dSmrg
1143428d7b3dSmrg	i915_mc_one_time_state_emit(context);
1144428d7b3dSmrg
1145428d7b3dSmrg	i915_mc_static_indirect_state_set(context, target_surface,
1146428d7b3dSmrg					  picture_structure, flags,
1147428d7b3dSmrg					  picture_coding_type);
1148428d7b3dSmrg	/* setup reference surfaces */
1149428d7b3dSmrg	i915_mc_map_state_set(context, privPast, privFuture);
1150428d7b3dSmrg
1151428d7b3dSmrg	i915_mc_load_indirect_render_emit(context);
1152428d7b3dSmrg
1153428d7b3dSmrg	i915_mc_mpeg_set_origin(context,
1154428d7b3dSmrg				&macroblock_array->macro_blocks
1155428d7b3dSmrg				[first_macroblock]);
1156428d7b3dSmrg
1157428d7b3dSmrg	for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
1158428d7b3dSmrg	     i++) {
1159428d7b3dSmrg		mb = &macroblock_array->macro_blocks[i];
1160428d7b3dSmrg
1161428d7b3dSmrg		/* Intra Blocks */
1162428d7b3dSmrg		if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
1163428d7b3dSmrg			i915_mc_mpeg_macroblock_ipicture(context, mb);
1164428d7b3dSmrg		} else if ((picture_structure & XVMC_FRAME_PICTURE) ==
1165428d7b3dSmrg			   XVMC_FRAME_PICTURE) {
1166428d7b3dSmrg			/* Frame Picture */
1167428d7b3dSmrg			switch (mb->motion_type & 3) {
1168428d7b3dSmrg			case XVMC_PREDICTION_FIELD:	/* Field Based */
1169428d7b3dSmrg				i915_mc_mpeg_macroblock_2fbmv(context, mb,
1170428d7b3dSmrg							      picture_structure);
1171428d7b3dSmrg				break;
1172428d7b3dSmrg
1173428d7b3dSmrg			case XVMC_PREDICTION_FRAME:	/* Frame Based */
1174428d7b3dSmrg				i915_mc_mpeg_macroblock_1fbmv(context, mb);
1175428d7b3dSmrg				break;
1176428d7b3dSmrg
1177428d7b3dSmrg			case XVMC_PREDICTION_DUAL_PRIME:	/* Dual Prime */
1178428d7b3dSmrg				i915_mc_mpeg_macroblock_2fbmv(context, mb,
1179428d7b3dSmrg							      picture_structure);
1180428d7b3dSmrg				break;
1181428d7b3dSmrg
1182428d7b3dSmrg			default:	/* No Motion Type */
1183428d7b3dSmrg				XVMC_ERR
1184428d7b3dSmrg				    ("Invalid Macroblock Parameters found.");
1185428d7b3dSmrg				break;
1186428d7b3dSmrg			}
1187428d7b3dSmrg		} else {	/* Field Picture */
1188428d7b3dSmrg			switch (mb->motion_type & 3) {
1189428d7b3dSmrg			case XVMC_PREDICTION_FIELD:	/* Field Based */
1190428d7b3dSmrg				i915_mc_mpeg_macroblock_1fbmv(context, mb);
1191428d7b3dSmrg				break;
1192428d7b3dSmrg
1193428d7b3dSmrg			case XVMC_PREDICTION_16x8:	/* 16x8 MC */
1194428d7b3dSmrg				i915_mc_mpeg_macroblock_2fbmv(context, mb,
1195428d7b3dSmrg							      picture_structure);
1196428d7b3dSmrg				break;
1197428d7b3dSmrg
1198428d7b3dSmrg			case XVMC_PREDICTION_DUAL_PRIME:	/* Dual Prime */
1199428d7b3dSmrg				i915_mc_mpeg_macroblock_1fbmv(context, mb);
1200428d7b3dSmrg				break;
1201428d7b3dSmrg
1202428d7b3dSmrg			default:	/* No Motion Type */
1203428d7b3dSmrg				XVMC_ERR
1204428d7b3dSmrg				    ("Invalid Macroblock Parameters found.");
1205428d7b3dSmrg				break;
1206428d7b3dSmrg			}
1207428d7b3dSmrg		}
1208428d7b3dSmrg	}
1209428d7b3dSmrg
1210428d7b3dSmrg	intelFlushBatch();
1211428d7b3dSmrg
1212428d7b3dSmrg	i915_xvmc_free_render_state_buffers(pI915XvMC);
1213428d7b3dSmrg
1214428d7b3dSmrg	UNLOCK_HARDWARE(intel_ctx->hw_context);
1215428d7b3dSmrg	return 0;
1216428d7b3dSmrg}
1217428d7b3dSmrg
1218428d7b3dSmrgstruct _intel_xvmc_driver i915_xvmc_mc_driver = {
1219428d7b3dSmrg	.type = XVMC_I915_MPEG2_MC,
1220428d7b3dSmrg	.num_ctx = 0,
1221428d7b3dSmrg	.ctx_list = NULL,
1222428d7b3dSmrg	.create_context = i915_xvmc_mc_create_context,
1223428d7b3dSmrg	.destroy_context = i915_xvmc_mc_destroy_context,
1224428d7b3dSmrg	.render_surface = i915_xvmc_mc_render_surface,
1225428d7b3dSmrg};
1226