i915_xvmc.c revision 42542f5f
1/*
2 * Copyright © 2006 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Xiang Haihao <haihao.xiang@intel.com>
25 *
26 */
27
28#include <sys/ioctl.h>
29
30#include "i915_xvmc.h"
31#include "i915_structs.h"
32#include "i915_program.h"
33
34#define ALIGN(i,m)		(((i) + (m) - 1) & ~((m) - 1))
35
36#define STRIDE(w)               (ALIGN((w), 1024))
37#define SIZE_Y420(w, h)         (h * STRIDE(w))
38#define SIZE_UV420(w, h)        ((h >> 1) * STRIDE(w >> 1))
39#define SIZE_YUV420(w, h)       (SIZE_Y420(w,h) + SIZE_UV420(w,h) * 2)
40#define UOFFSET(context)        (SIZE_Y420(context->width, context->height))
41#define VOFFSET(context)        (SIZE_Y420(context->width, context->height) + \
42                                 SIZE_UV420(context->width, context->height))
43
44typedef union {
45	int16_t component[2];
46	int32_t v;
47} vector_t;
48
49static void i915_inst_arith(unsigned int *inst,
50			    unsigned int op,
51			    unsigned int dest,
52			    unsigned int mask,
53			    unsigned int saturate,
54			    unsigned int src0, unsigned int src1,
55			    unsigned int src2)
56{
57	dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
58	*inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
59	inst++;
60	*inst = (A1_SRC0(src0) | A1_SRC1(src1));
61	inst++;
62	*inst = (A2_SRC1(src1) | A2_SRC2(src2));
63}
64
65static void i915_inst_decl(unsigned int *inst,
66			   unsigned int type,
67			   unsigned int nr, unsigned int d0_flags)
68{
69	unsigned int reg = UREG(type, nr);
70
71	*inst = (D0_DCL | D0_DEST(reg) | d0_flags);
72	inst++;
73	*inst = D1_MBZ;
74	inst++;
75	*inst = D2_MBZ;
76}
77
78static void i915_inst_texld(unsigned int *inst,
79			    unsigned int op,
80			    unsigned int dest,
81			    unsigned int coord, unsigned int sampler)
82{
83	dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
84	*inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler));
85	inst++;
86	*inst = T1_ADDRESS_REG(coord);
87	inst++;
88	*inst = T2_MBZ;
89}
90
91static void i915_mc_one_time_context_init(XvMCContext * context)
92{
93	unsigned int dest, src0, src1, src2;
94	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
95	int i;
96	struct i915_3dstate_sampler_state *sampler_state;
97	struct i915_3dstate_pixel_shader_program *pixel_shader_program;
98	struct i915_3dstate_pixel_shader_constants *pixel_shader_constants;
99
100	/* sampler static state */
101	drm_intel_gem_bo_map_gtt(pI915XvMC->ssb_bo);
102	sampler_state = pI915XvMC->ssb_bo->virtual;
103
104	memset(sampler_state, 0, sizeof(*sampler_state));
105	sampler_state->dw0.type = CMD_3D;
106	sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE;
107	sampler_state->dw0.length = 6;
108	sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1;
109
110	sampler_state->sampler0.ts0.reverse_gamma = 0;
111	sampler_state->sampler0.ts0.planar2packet = 0;
112	sampler_state->sampler0.ts0.color_conversion = 0;
113	sampler_state->sampler0.ts0.chromakey_index = 0;
114	sampler_state->sampler0.ts0.base_level = 0;
115	sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE;	/* NONE */
116	sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR;	/* LINEAR */
117	sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR;	/* LINEAR */
118	sampler_state->sampler0.ts0.lod_bias = 0;	/* 0.0 */
119	sampler_state->sampler0.ts0.shadow_enable = 0;
120	sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2;
121	sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS;
122	sampler_state->sampler0.ts1.min_lod = 0;	/* 0.0 Maximum Mip Level */
123	sampler_state->sampler0.ts1.kill_pixel = 0;
124	sampler_state->sampler0.ts1.keyed_texture_filter = 0;
125	sampler_state->sampler0.ts1.chromakey_enable = 0;
126	sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP;
127	sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP;
128	sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP;
129	sampler_state->sampler0.ts1.normalized_coor = 0;
130	sampler_state->sampler0.ts1.map_index = 0;
131	sampler_state->sampler0.ts1.east_deinterlacer = 0;
132	sampler_state->sampler0.ts2.default_color = 0;
133
134	sampler_state->sampler1.ts0.reverse_gamma = 0;
135	sampler_state->sampler1.ts0.planar2packet = 0;
136	sampler_state->sampler1.ts0.color_conversion = 0;
137	sampler_state->sampler1.ts0.chromakey_index = 0;
138	sampler_state->sampler1.ts0.base_level = 0;
139	sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE;	/* NONE */
140	sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR;	/* LINEAR */
141	sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR;	/* LINEAR */
142	sampler_state->sampler1.ts0.lod_bias = 0;	/* 0.0 */
143	sampler_state->sampler1.ts0.shadow_enable = 0;
144	sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2;
145	sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS;
146	sampler_state->sampler1.ts1.min_lod = 0;	/* 0.0 Maximum Mip Level */
147	sampler_state->sampler1.ts1.kill_pixel = 0;
148	sampler_state->sampler1.ts1.keyed_texture_filter = 0;
149	sampler_state->sampler1.ts1.chromakey_enable = 0;
150	sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP;
151	sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP;
152	sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP;
153	sampler_state->sampler1.ts1.normalized_coor = 0;
154	sampler_state->sampler1.ts1.map_index = 1;
155	sampler_state->sampler1.ts1.east_deinterlacer = 0;
156	sampler_state->sampler1.ts2.default_color = 0;
157
158	drm_intel_gem_bo_unmap_gtt(pI915XvMC->ssb_bo);
159
160	/* pixel shader static state */
161	drm_intel_gem_bo_map_gtt(pI915XvMC->psp_bo);
162	pixel_shader_program = pI915XvMC->psp_bo->virtual;
163
164	memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
165	pixel_shader_program->shader0.type = CMD_3D;
166	pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
167	pixel_shader_program->shader0.retain = 1;
168	pixel_shader_program->shader0.length = 2;	/* 1 inst */
169	i = 0;
170
171	dest = UREG(REG_TYPE_OC, 0);
172	src0 = UREG(REG_TYPE_CONST, 0);
173	src1 = 0;
174	src2 = 0;
175	i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV,
176			dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
177			src2);
178
179	pixel_shader_program->shader1.type = CMD_3D;
180	pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
181	pixel_shader_program->shader1.retain = 1;
182	pixel_shader_program->shader1.length = 14;	/* 5 inst */
183	i = 0;
184	/* dcl t0.xy */
185	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0,
186		       D0_CHANNEL_XY);
187	i += 3;
188	/* dcl t1.xy */
189	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1,
190		       D0_CHANNEL_XY);
191	/* dcl_2D s0 */
192	i += 3;
193	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0,
194		       D0_SAMPLE_TYPE_2D);
195	/* texld r0, t0, s0 */
196	i += 3;
197	dest = UREG(REG_TYPE_R, 0);
198	src0 = UREG(REG_TYPE_T, 0);	/* COORD */
199	src1 = UREG(REG_TYPE_S, 0);	/* SAMPLER */
200	i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0,
201			src1);
202	/* mov oC, r0 */
203	i += 3;
204	dest = UREG(REG_TYPE_OC, 0);
205	src0 = UREG(REG_TYPE_R, 0);
206	src1 = src2 = 0;
207	i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest,
208			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
209			src2);
210
211	pixel_shader_program->shader2.type = CMD_3D;
212	pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
213	pixel_shader_program->shader2.retain = 1;
214	pixel_shader_program->shader2.length = 14;	/* 5 inst */
215	i = 0;
216	/* dcl t2.xy */
217	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2,
218		       D0_CHANNEL_XY);
219	/* dcl t3.xy */
220	i += 3;
221	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3,
222		       D0_CHANNEL_XY);
223	/* dcl_2D s1 */
224	i += 3;
225	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1,
226		       D0_SAMPLE_TYPE_2D);
227	/* texld r0, t2, s1 */
228	i += 3;
229	dest = UREG(REG_TYPE_R, 0);
230	src0 = UREG(REG_TYPE_T, 2);	/* COORD */
231	src1 = UREG(REG_TYPE_S, 1);	/* SAMPLER */
232	i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0,
233			src1);
234	/* mov oC, r0 */
235	i += 3;
236	dest = UREG(REG_TYPE_OC, 0);
237	src0 = UREG(REG_TYPE_R, 0);
238	src1 = src2 = 0;
239	i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest,
240			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
241			src2);
242
243	/* Shader 3 */
244	pixel_shader_program->shader3.type = CMD_3D;
245	pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
246	pixel_shader_program->shader3.retain = 1;
247	pixel_shader_program->shader3.length = 29;	/* 10 inst */
248	i = 0;
249	/* dcl t0.xy */
250	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0,
251		       D0_CHANNEL_XY);
252	/* dcl t1.xy */
253	i += 3;
254	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1,
255		       D0_CHANNEL_XY);
256	/* dcl t2.xy */
257	i += 3;
258	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2,
259		       D0_CHANNEL_XY);
260	/* dcl t3.xy */
261	i += 3;
262	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3,
263		       D0_CHANNEL_XY);
264	/* dcl_2D s0 */
265	i += 3;
266	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0,
267		       D0_SAMPLE_TYPE_2D);
268	/* dcl_2D s1 */
269	i += 3;
270	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1,
271		       D0_SAMPLE_TYPE_2D);
272	/* texld r0, t0, s0 */
273	i += 3;
274	dest = UREG(REG_TYPE_R, 0);
275	src0 = UREG(REG_TYPE_T, 0);	/* COORD */
276	src1 = UREG(REG_TYPE_S, 0);	/* SAMPLER */
277	i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
278			src1);
279	/* texld r1, t2, s1 */
280	i += 3;
281	dest = UREG(REG_TYPE_R, 1);
282	src0 = UREG(REG_TYPE_T, 2);	/* COORD */
283	src1 = UREG(REG_TYPE_S, 1);	/* SAMPLER */
284	i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
285			src1);
286	/* add r0, r0, r1 */
287	i += 3;
288	dest = UREG(REG_TYPE_R, 0);
289	src0 = UREG(REG_TYPE_R, 0);
290	src1 = UREG(REG_TYPE_R, 1);
291	src2 = 0;
292	i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest,
293			A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */ , src0,
294			src1, src2);
295	/* mul oC, r0, c0 */
296	i += 3;
297	dest = UREG(REG_TYPE_OC, 0);
298	src0 = UREG(REG_TYPE_R, 0);
299	src1 = UREG(REG_TYPE_CONST, 0);
300	src2 = 0;
301	i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest,
302			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
303			src2);
304
305	drm_intel_gem_bo_unmap_gtt(pI915XvMC->psp_bo);
306
307	/* pixel shader contant static state */
308	drm_intel_gem_bo_map_gtt(pI915XvMC->psc_bo);
309	pixel_shader_constants = pI915XvMC->psc_bo->virtual;
310
311	memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants));
312	pixel_shader_constants->dw0.type = CMD_3D;
313	pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS;
314	pixel_shader_constants->dw0.length = 4;
315	pixel_shader_constants->dw1.reg_mask = REG_CR0;
316	pixel_shader_constants->value.x = 0.5;
317	pixel_shader_constants->value.y = 0.5;
318	pixel_shader_constants->value.z = 0.5;
319	pixel_shader_constants->value.w = 0.5;
320
321	drm_intel_gem_bo_unmap_gtt(pI915XvMC->psc_bo);
322}
323
324static void i915_mc_one_time_state_emit(XvMCContext * context)
325{
326	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
327	uint32_t load_state_immediate_1, load_indirect, s3_dword, s6_dword;
328	int mem_select;
329	BATCH_LOCALS;
330
331	/* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */
332	BEGIN_BATCH(3 + 8);
333	load_state_immediate_1 = OP_3D_LOAD_STATE_IMMEDIATE_1;
334	load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S3;
335	load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S6;
336	load_state_immediate_1 |= 3 - 2; /* length */
337	OUT_BATCH(load_state_immediate_1);
338
339	s3_dword = S3_SET0_PCD | S3_SET1_PCD |
340		   S3_SET2_PCD | S3_SET3_PCD |
341		   S3_SET4_PCD | S3_SET5_PCD |
342		   S3_SET6_PCD | S3_SET7_PCD;
343	OUT_BATCH(s3_dword);
344
345	s6_dword = S6_COLOR_BUFFER_WRITE | S6_DEPTH_TEST_ENABLE;
346	s6_dword |= 1 << S6_SRC_BLEND_FACTOR_SHIFT;
347	s6_dword |= 1 << S6_DST_BLEND_FACTOR_SHIFT;
348	OUT_BATCH(s6_dword);
349
350	/* 3DSTATE_LOAD_INDIRECT */
351	load_indirect = OP_3D_LOAD_INDIRECT;
352	load_indirect |= (BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC)
353				<< BLOCK_MASK_SHIFT;
354	load_indirect |= 8 - 2; /* length */
355
356	if (pI915XvMC->use_phys_addr)
357		mem_select = 0;	/* use physical address */
358	else {
359		load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
360		mem_select = 1;	/* use gfx address */
361	}
362
363	OUT_BATCH(load_indirect);
364
365	/* Dynamic indirect state buffer */
366	OUT_BATCH(0); /* no dynamic indirect state */
367
368	/* Sample state buffer */
369	OUT_RELOC(pI915XvMC->ssb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
370			STATE_VALID | STATE_FORCE);
371	OUT_BATCH(7);	/* 8 - 1 */
372
373	/* Pixel shader program buffer */
374	OUT_RELOC(pI915XvMC->psp_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
375			STATE_VALID | STATE_FORCE);
376	OUT_BATCH(66);	/* 4 + 16 + 16 + 31 - 1 */
377
378	/* Pixel shader constant buffer */
379	OUT_RELOC(pI915XvMC->psc_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
380			STATE_VALID | STATE_FORCE);
381	OUT_BATCH(5);	/* 6 - 1 */
382	ADVANCE_BATCH();
383}
384
385static void i915_mc_static_indirect_state_set(XvMCContext * context,
386					      XvMCSurface * dest,
387					      unsigned int picture_structure,
388					      unsigned int flags,
389					      unsigned int picture_coding_type)
390{
391	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
392	struct intel_xvmc_surface *intel_surf = dest->privData;
393	struct i915_mc_static_indirect_state_buffer *buffer_info;
394
395	drm_intel_gem_bo_map_gtt(pI915XvMC->sis_bo);
396	buffer_info = pI915XvMC->sis_bo->virtual;
397
398	memset(buffer_info, 0, sizeof(*buffer_info));
399
400	/* dest Y */
401	buffer_info->dest_y.dw0.type = CMD_3D;
402	buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
403	buffer_info->dest_y.dw0.length = 1;
404	buffer_info->dest_y.dw1.aux_id = 0;
405	buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK;
406	buffer_info->dest_y.dw1.fence_regs = 0;	/* disabled *//* FIXME: tiled y for performance */
407	buffer_info->dest_y.dw1.tiled_surface = 0;	/* linear */
408	buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR;
409	buffer_info->dest_y.dw1.pitch = (pI915XvMC->yStride >> 2);	/* in DWords */
410	buffer_info->dest_y.dw2.base_address = intel_surf->bo->offset >> 2;	/* starting DWORD address */
411	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
412				offsetof(typeof(*buffer_info),dest_y.dw2),
413				intel_surf->bo, 0,
414				I915_GEM_DOMAIN_RENDER,
415				I915_GEM_DOMAIN_RENDER);
416
417	/* dest U */
418	buffer_info->dest_u.dw0.type = CMD_3D;
419	buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
420	buffer_info->dest_u.dw0.length = 1;
421	buffer_info->dest_u.dw1.aux_id = 0;
422	buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX;
423	buffer_info->dest_u.dw1.fence_regs = 0;
424	buffer_info->dest_u.dw1.tiled_surface = 0;
425	buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR;
426	buffer_info->dest_u.dw1.pitch = (pI915XvMC->uvStride >> 2);	/* in DWords */
427	buffer_info->dest_u.dw2.base_address =
428		(intel_surf->bo->offset + UOFFSET(context)) >> 2;
429	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
430				offsetof(typeof(*buffer_info),dest_u.dw2),
431				intel_surf->bo, UOFFSET(context),
432				I915_GEM_DOMAIN_RENDER,
433				I915_GEM_DOMAIN_RENDER);
434
435	/* dest V */
436	buffer_info->dest_v.dw0.type = CMD_3D;
437	buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
438	buffer_info->dest_v.dw0.length = 1;
439	buffer_info->dest_v.dw1.aux_id = 1;
440	buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX;
441	buffer_info->dest_v.dw1.fence_regs = 0;
442	buffer_info->dest_v.dw1.tiled_surface = 0;
443	buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR;
444	buffer_info->dest_v.dw1.pitch = (pI915XvMC->uvStride >> 2);	/* in Dwords */
445	buffer_info->dest_v.dw2.base_address =
446		(intel_surf->bo->offset + VOFFSET(context)) >> 2;
447	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
448				offsetof(typeof(*buffer_info),dest_v.dw2),
449				intel_surf->bo, VOFFSET(context),
450				I915_GEM_DOMAIN_RENDER,
451				I915_GEM_DOMAIN_RENDER);
452
453	/* Dest buffer parameters */
454	buffer_info->dest_buf.dw0.type = CMD_3D;
455	buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES;
456	buffer_info->dest_buf.dw0.length = 0;
457	buffer_info->dest_buf.dw1.dest_v_bias = 8;	/* 0.5 */
458	buffer_info->dest_buf.dw1.dest_h_bias = 8;	/* 0.5 */
459	buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT;
460	buffer_info->dest_buf.dw1.v_ls = 0;	/* fill later */
461	buffer_info->dest_buf.dw1.v_ls_offset = 0;	/* fill later */
462	if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
463		;
464	} else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) {
465		buffer_info->dest_buf.dw1.v_ls = 1;
466	} else if ((picture_structure & XVMC_FRAME_PICTURE) ==
467		   XVMC_BOTTOM_FIELD) {
468		buffer_info->dest_buf.dw1.v_ls = 1;
469		buffer_info->dest_buf.dw1.v_ls_offset = 1;
470	}
471
472	/* MPEG buffer parameters */
473	buffer_info->dest_buf_mpeg.dw0.type = CMD_3D;
474	buffer_info->dest_buf_mpeg.dw0.opcode =
475	    OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG;
476	buffer_info->dest_buf_mpeg.dw0.length = 1;
477	buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC;
478	buffer_info->dest_buf_mpeg.dw1.rcontrol = 0;	/* for MPEG-1/MPEG-2 */
479	buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0;	/* for MPEG-1/MPEG-2/MPEG-4 */
480	buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1;
481	buffer_info->dest_buf_mpeg.dw1.intra8 = 0;	/* 16-bit formatted correction data */
482	buffer_info->dest_buf_mpeg.dw1.tff = 1;	/* fill later */
483
484	buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V;
485	buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H;
486
487	if (picture_structure & XVMC_FRAME_PICTURE) {
488		;
489	} else if (picture_structure & XVMC_TOP_FIELD) {
490		if (flags & XVMC_SECOND_FIELD)
491			buffer_info->dest_buf_mpeg.dw1.tff = 0;
492		else
493			buffer_info->dest_buf_mpeg.dw1.tff = 1;
494	} else if (picture_structure & XVMC_BOTTOM_FIELD) {
495		if (flags & XVMC_SECOND_FIELD)
496			buffer_info->dest_buf_mpeg.dw1.tff = 1;
497		else
498			buffer_info->dest_buf_mpeg.dw1.tff = 0;
499	}
500
501	buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4);	/* in macroblocks */
502	buffer_info->dest_buf_mpeg.dw2.picture_coding_type =
503	    picture_coding_type;
504
505	buffer_info->corr.dw0.type = CMD_3D;
506	buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
507	buffer_info->corr.dw0.length = 1;
508	buffer_info->corr.dw1.aux_id = 0;
509	buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR;
510	buffer_info->corr.dw1.aux_id = 0;
511	buffer_info->corr.dw1.fence_regs = 0;
512	buffer_info->corr.dw1.tiled_surface = 0;
513	buffer_info->corr.dw1.walk = 0;
514	buffer_info->corr.dw1.pitch = 0;
515	buffer_info->corr.dw2.base_address = pI915XvMC->corrdata_bo->offset >> 2;	/* starting DWORD address */
516	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
517				offsetof(typeof(*buffer_info),corr.dw2),
518				pI915XvMC->corrdata_bo, 0,
519				I915_GEM_DOMAIN_RENDER, 0);
520
521	drm_intel_gem_bo_unmap_gtt(pI915XvMC->sis_bo);
522}
523
524static void i915_mc_map_state_set(XvMCContext * context,
525				  struct intel_xvmc_surface * privPast,
526				  struct intel_xvmc_surface * privFuture)
527{
528	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
529	struct i915_mc_map_state *map_state;
530	unsigned int w = context->width;
531	unsigned int h = context->height;
532
533	drm_intel_gem_bo_map_gtt(pI915XvMC->msb_bo);
534	map_state = pI915XvMC->msb_bo->virtual;
535
536	memset(map_state, 0, sizeof(*map_state));
537
538	/* 3DSATE_MAP_STATE: Y */
539	map_state->y_map.dw0.type = CMD_3D;
540	map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
541	map_state->y_map.dw0.retain = 1;
542	map_state->y_map.dw0.length = 6;
543	map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
544
545	/* Y Forward (Past) */
546	map_state->y_forward.tm0.v_ls_offset = 0;
547	map_state->y_forward.tm0.v_ls = 0;
548	map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR;
549	map_state->y_forward.tm1.tiled_surface = 0;
550	map_state->y_forward.tm1.utilize_fence_regs = 0;
551	map_state->y_forward.tm1.texel_fmt = 0;	/* 8bit */
552	map_state->y_forward.tm1.surface_fmt = 1;	/* 8bit */
553	map_state->y_forward.tm1.width = w - 1;
554	map_state->y_forward.tm1.height = h - 1;
555	map_state->y_forward.tm2.depth = 0;
556	map_state->y_forward.tm2.max_lod = 0;
557	map_state->y_forward.tm2.cube_face = 0;
558	map_state->y_forward.tm0.base_address = privPast->bo->offset >> 2;
559	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
560				offsetof(typeof(*map_state),y_forward.tm0),
561				privPast->bo, 0,
562				I915_GEM_DOMAIN_SAMPLER, 0);
563	map_state->y_forward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;	/* in DWords - 1 */
564
565	/* Y Backward (Future) */
566	map_state->y_backward.tm0.v_ls_offset = 0;
567	map_state->y_backward.tm0.v_ls = 0;
568	map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR;
569	map_state->y_backward.tm1.tiled_surface = 0;
570	map_state->y_backward.tm1.utilize_fence_regs = 0;
571	map_state->y_backward.tm1.texel_fmt = 0;	/* 8bit */
572	map_state->y_backward.tm1.surface_fmt = 1;	/* 8bit */
573	map_state->y_backward.tm1.width = w - 1;
574	map_state->y_backward.tm1.height = h - 1;
575	map_state->y_backward.tm2.depth = 0;
576	map_state->y_backward.tm2.max_lod = 0;
577	map_state->y_backward.tm2.cube_face = 0;
578	map_state->y_backward.tm0.base_address = privFuture->bo->offset >> 2;
579	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
580				offsetof(typeof(*map_state),y_backward.tm0),
581				privFuture->bo, 0,
582				I915_GEM_DOMAIN_SAMPLER, 0);
583	map_state->y_backward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;
584
585	/* 3DSATE_MAP_STATE: U */
586	map_state->u_map.dw0.type = CMD_3D;
587	map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
588	map_state->u_map.dw0.retain = 1;
589	map_state->u_map.dw0.length = 6;
590	map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
591
592	/* U Forward */
593	map_state->u_forward.tm0.v_ls_offset = 0;
594	map_state->u_forward.tm0.v_ls = 0;
595	map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR;
596	map_state->u_forward.tm1.tiled_surface = 0;
597	map_state->u_forward.tm1.utilize_fence_regs = 0;
598	map_state->u_forward.tm1.texel_fmt = 0;	/* 8bit */
599	map_state->u_forward.tm1.surface_fmt = 1;	/* 8bit */
600	map_state->u_forward.tm1.width = (w >> 1) - 1;
601	map_state->u_forward.tm1.height = (h >> 1) - 1;
602	map_state->u_forward.tm2.depth = 0;
603	map_state->u_forward.tm2.max_lod = 0;
604	map_state->u_forward.tm2.cube_face = 0;
605	map_state->u_forward.tm0.base_address =
606		(privPast->bo->offset + UOFFSET(context)) >> 2;
607	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
608				offsetof(typeof(*map_state),u_forward.tm0),
609				privPast->bo, UOFFSET(context),
610				I915_GEM_DOMAIN_SAMPLER, 0);
611	map_state->u_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;	/* in DWords - 1 */
612
613	/* U Backward */
614	map_state->u_backward.tm0.v_ls_offset = 0;
615	map_state->u_backward.tm0.v_ls = 0;
616	map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR;
617	map_state->u_backward.tm1.tiled_surface = 0;
618	map_state->u_backward.tm1.utilize_fence_regs = 0;
619	map_state->u_backward.tm1.texel_fmt = 0;
620	map_state->u_backward.tm1.surface_fmt = 1;
621	map_state->u_backward.tm1.width = (w >> 1) - 1;
622	map_state->u_backward.tm1.height = (h >> 1) - 1;
623	map_state->u_backward.tm2.depth = 0;
624	map_state->u_backward.tm2.max_lod = 0;
625	map_state->u_backward.tm2.cube_face = 0;
626	map_state->u_backward.tm0.base_address =
627		(privFuture->bo->offset + UOFFSET(context)) >> 2;
628	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
629				offsetof(typeof(*map_state),u_backward.tm0),
630				privFuture->bo, UOFFSET(context),
631				I915_GEM_DOMAIN_SAMPLER, 0);
632	map_state->u_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
633
634	/* 3DSATE_MAP_STATE: V */
635	map_state->v_map.dw0.type = CMD_3D;
636	map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
637	map_state->v_map.dw0.retain = 1;
638	map_state->v_map.dw0.length = 6;
639	map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
640
641	/* V Forward */
642	map_state->v_forward.tm0.v_ls_offset = 0;
643	map_state->v_forward.tm0.v_ls = 0;
644	map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR;
645	map_state->v_forward.tm1.tiled_surface = 0;
646	map_state->v_forward.tm1.utilize_fence_regs = 0;
647	map_state->v_forward.tm1.texel_fmt = 0;
648	map_state->v_forward.tm1.surface_fmt = 1;
649	map_state->v_forward.tm1.width = (w >> 1) - 1;
650	map_state->v_forward.tm1.height = (h >> 1) - 1;
651	map_state->v_forward.tm2.depth = 0;
652	map_state->v_forward.tm2.max_lod = 0;
653	map_state->v_forward.tm2.cube_face = 0;
654	map_state->v_forward.tm0.base_address =
655		(privPast->bo->offset + VOFFSET(context)) >> 2;
656	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
657				offsetof(typeof(*map_state),v_forward.tm0),
658				privPast->bo, VOFFSET(context),
659				I915_GEM_DOMAIN_SAMPLER, 0);
660	map_state->v_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;	/* in DWords - 1 */
661
662	/* V Backward */
663	map_state->v_backward.tm0.v_ls_offset = 0;
664	map_state->v_backward.tm0.v_ls = 0;
665	map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR;
666	map_state->v_backward.tm1.tiled_surface = 0;
667	map_state->v_backward.tm1.utilize_fence_regs = 0;
668	map_state->v_backward.tm1.texel_fmt = 0;
669	map_state->v_backward.tm1.surface_fmt = 1;
670	map_state->v_backward.tm1.width = (w >> 1) - 1;
671	map_state->v_backward.tm1.height = (h >> 1) - 1;
672	map_state->v_backward.tm2.depth = 0;
673	map_state->v_backward.tm2.max_lod = 0;
674	map_state->v_backward.tm2.cube_face = 0;
675	map_state->v_backward.tm0.base_address =
676		(privFuture->bo->offset + VOFFSET(context)) >> 2;
677	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
678				offsetof(typeof(*map_state),v_backward.tm0),
679				privFuture->bo, VOFFSET(context),
680				I915_GEM_DOMAIN_SAMPLER, 0);
681	map_state->v_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
682
683	drm_intel_gem_bo_unmap_gtt(pI915XvMC->msb_bo);
684}
685
686static void i915_mc_load_indirect_render_emit(XvMCContext * context)
687{
688	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
689	int mem_select;
690	uint32_t load_indirect;
691	BATCH_LOCALS;
692
693	BEGIN_BATCH(5);
694	load_indirect = OP_3D_LOAD_INDIRECT;
695	load_indirect |= (BLOCK_SIS | BLOCK_MSB) << BLOCK_MASK_SHIFT;
696	load_indirect |= 5 - 2; /* length */
697
698	if (pI915XvMC->use_phys_addr)
699		mem_select = 0;	/* use physical address */
700	else {
701		load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
702		mem_select = 1;	/* use gfx address */
703	}
704	OUT_BATCH(load_indirect);
705
706	/* Static Indirect state buffer (dest buffer info) */
707	OUT_RELOC(pI915XvMC->sis_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
708			STATE_VALID | STATE_FORCE);
709	OUT_BATCH(16);	/* 4 * 3 + 2 + 3 - 1 */
710
711	/* Map state buffer (reference buffer info) */
712	OUT_RELOC(pI915XvMC->msb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
713			STATE_VALID | STATE_FORCE);
714	OUT_BATCH(23);	/* 3 * 8 - 1 */
715	ADVANCE_BATCH();
716}
717
718static void i915_mc_mpeg_set_origin(XvMCContext * context, XvMCMacroBlock * mb)
719{
720	struct i915_3dmpeg_set_origin set_origin;
721
722	/* 3DMPEG_SET_ORIGIN */
723	memset(&set_origin, 0, sizeof(set_origin));
724	set_origin.dw0.type = CMD_3D;
725	set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN;
726	set_origin.dw0.length = 0;
727	set_origin.dw1.h_origin = mb->x;
728	set_origin.dw1.v_origin = mb->y;
729
730	intelBatchbufferData(&set_origin, sizeof(set_origin), 0);
731}
732
733static void i915_mc_mpeg_macroblock_ipicture(XvMCContext * context,
734					     XvMCMacroBlock * mb)
735{
736	struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture;
737
738	/* 3DMPEG_MACROBLOCK_IPICTURE */
739	memset(&macroblock_ipicture, 0, sizeof(macroblock_ipicture));
740	macroblock_ipicture.dw0.type = CMD_3D;
741	macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE;
742	macroblock_ipicture.dw0.dct_type =
743	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
744
745	intelBatchbufferData(&macroblock_ipicture, sizeof(macroblock_ipicture),
746			     0);
747}
748
749static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext * context,
750					  XvMCMacroBlock * mb)
751{
752	struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv;
753	vector_t mv0[2];
754
755	/* 3DMPEG_MACROBLOCK(1fbmv) */
756	memset(&macroblock_1fbmv, 0, sizeof(macroblock_1fbmv));
757	macroblock_1fbmv.header.dw0.type = CMD_3D;
758	macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
759	macroblock_1fbmv.header.dw0.length = 2;
760	macroblock_1fbmv.header.dw1.mb_intra = 0;	/* should be 0 */
761	macroblock_1fbmv.header.dw1.forward =
762	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
763	macroblock_1fbmv.header.dw1.backward =
764	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
765	macroblock_1fbmv.header.dw1.h263_4mv = 0;	/* should be 0 */
766	macroblock_1fbmv.header.dw1.dct_type =
767	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
768
769	if (!(mb->coded_block_pattern & 0x3f))
770		macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
771
772	macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
773	macroblock_1fbmv.header.dw1.vertical_field_select =
774	    (mb->motion_vertical_field_select & 0x0f);
775	macroblock_1fbmv.header.dw1.coded_block_pattern =
776	    mb->coded_block_pattern;
777	macroblock_1fbmv.header.dw1.skipped_macroblocks = 0;
778
779	mv0[0].component[0] = mb->PMV[0][0][0];
780	mv0[0].component[1] = mb->PMV[0][0][1];
781	mv0[1].component[0] = mb->PMV[0][1][0];
782	mv0[1].component[1] = mb->PMV[0][1][1];
783
784	macroblock_1fbmv.dw2 = mv0[0].v;
785	macroblock_1fbmv.dw3 = mv0[1].v;
786
787	intelBatchbufferData(&macroblock_1fbmv, sizeof(macroblock_1fbmv), 0);
788}
789
790static void i915_mc_mpeg_macroblock_2fbmv(XvMCContext * context,
791					  XvMCMacroBlock * mb, unsigned int ps)
792{
793	struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv;
794	vector_t mv0[2];
795	vector_t mv1[2];
796
797	/* 3DMPEG_MACROBLOCK(2fbmv) */
798	memset(&macroblock_2fbmv, 0, sizeof(macroblock_2fbmv));
799	macroblock_2fbmv.header.dw0.type = CMD_3D;
800	macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
801	macroblock_2fbmv.header.dw0.length = 4;
802	macroblock_2fbmv.header.dw1.mb_intra = 0;	/* should be 0 */
803	macroblock_2fbmv.header.dw1.forward =
804	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
805	macroblock_2fbmv.header.dw1.backward =
806	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
807	macroblock_2fbmv.header.dw1.h263_4mv = 0;	/* should be 0 */
808	macroblock_2fbmv.header.dw1.dct_type =
809	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
810
811	if (!(mb->coded_block_pattern & 0x3f))
812		macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
813
814	macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
815	macroblock_2fbmv.header.dw1.vertical_field_select =
816	    (mb->motion_vertical_field_select & 0x0f);
817	macroblock_2fbmv.header.dw1.coded_block_pattern =
818	    mb->coded_block_pattern;
819	macroblock_2fbmv.header.dw1.skipped_macroblocks = 0;
820
821	mv0[0].component[0] = mb->PMV[0][0][0];
822	mv0[0].component[1] = mb->PMV[0][0][1];
823	mv0[1].component[0] = mb->PMV[0][1][0];
824	mv0[1].component[1] = mb->PMV[0][1][1];
825	mv1[0].component[0] = mb->PMV[1][0][0];
826	mv1[0].component[1] = mb->PMV[1][0][1];
827	mv1[1].component[0] = mb->PMV[1][1][0];
828	mv1[1].component[1] = mb->PMV[1][1][1];
829
830	if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
831		if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) {
832			mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
833			mv0[1].component[1] = mb->PMV[0][1][1] >> 1;
834			mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
835			mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
836		} else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) {
837			mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
838			mv0[1].component[1] = mb->PMV[0][1][1] >> 1;	// MPEG2 MV[0][1] isn't used
839			mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
840			mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
841		}
842	}
843
844	macroblock_2fbmv.dw2 = mv0[0].v;
845	macroblock_2fbmv.dw3 = mv0[1].v;
846	macroblock_2fbmv.dw4 = mv1[0].v;
847	macroblock_2fbmv.dw5 = mv1[1].v;
848
849	intelBatchbufferData(&macroblock_2fbmv, sizeof(macroblock_2fbmv), 0);
850}
851
852static int i915_xvmc_alloc_one_time_buffers(i915XvMCContext *pI915XvMC)
853{
854	pI915XvMC->ssb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
855					       "ssb",
856					       GTT_PAGE_SIZE,
857					       GTT_PAGE_SIZE);
858	if (!pI915XvMC->ssb_bo)
859		return 0;
860
861	pI915XvMC->psp_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
862					       "psp",
863					       GTT_PAGE_SIZE,
864					       GTT_PAGE_SIZE);
865	if (!pI915XvMC->psp_bo)
866		return 0;
867
868	pI915XvMC->psc_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
869					       "psc",
870					       GTT_PAGE_SIZE,
871					       GTT_PAGE_SIZE);
872	if (!pI915XvMC->psc_bo)
873		return 0;
874
875	return 1;
876}
877
878static void i915_xvmc_free_one_time_buffers(i915XvMCContext *pI915XvMC)
879{
880	drm_intel_bo_unreference(pI915XvMC->ssb_bo);
881	drm_intel_bo_unreference(pI915XvMC->psp_bo);
882	drm_intel_bo_unreference(pI915XvMC->psc_bo);
883}
884
885/*
886 * Function: i915_release_resource
887 */
888static void i915_release_resource(Display * display, XvMCContext * context)
889{
890	i915XvMCContext *pI915XvMC;
891
892	if (!(pI915XvMC = context->privData))
893		return;
894
895	i915_xvmc_free_one_time_buffers(pI915XvMC);
896
897	free(pI915XvMC);
898	context->privData = NULL;
899}
900
901static Status i915_xvmc_mc_create_context(Display * display,
902					  XvMCContext * context, int priv_count,
903					  CARD32 * priv_data)
904{
905	i915XvMCContext *pI915XvMC = NULL;
906	struct intel_xvmc_hw_context *tmpComm = NULL;
907
908	if (priv_count != (sizeof(struct intel_xvmc_hw_context) >> 2)) {
909		XVMC_ERR
910		    ("_xvmc_create_context() returned incorrect data size!");
911		XVMC_INFO("\tExpected %d, got %d",
912			  (int)(sizeof(struct intel_xvmc_hw_context) >> 2),
913			  priv_count);
914		_xvmc_destroy_context(display, context);
915		XFree(priv_data);
916		context->privData = NULL;
917		return BadValue;
918	}
919
920	context->privData = (void *)calloc(1, sizeof(i915XvMCContext));
921	if (!context->privData) {
922		XVMC_ERR("Unable to allocate resources for XvMC context.");
923		return BadAlloc;
924	}
925	pI915XvMC = (i915XvMCContext *) context->privData;
926
927	tmpComm = (struct intel_xvmc_hw_context *) priv_data;
928	pI915XvMC->use_phys_addr = tmpComm->i915.use_phys_addr;
929	pI915XvMC->comm.surface_bo_size = SIZE_YUV420(context->width,
930						      context->height);
931
932	/* Must free the private data we were passed from X */
933	XFree(priv_data);
934	priv_data = NULL;
935
936	if (!i915_xvmc_alloc_one_time_buffers(pI915XvMC))
937		goto free_one_time_buffers;
938
939	/* Initialize private context values */
940	pI915XvMC->yStride = STRIDE(context->width);
941	pI915XvMC->uvStride = STRIDE(context->width >> 1);
942
943	/* pre-init state buffers */
944	i915_mc_one_time_context_init(context);
945
946	return Success;
947
948free_one_time_buffers:
949	i915_xvmc_free_one_time_buffers(pI915XvMC);
950	free(pI915XvMC);
951	context->privData = NULL;
952	return BadAlloc;
953}
954
955static int i915_xvmc_mc_destroy_context(Display * display,
956					XvMCContext * context)
957{
958	i915XvMCContext *pI915XvMC;
959
960	if (!(pI915XvMC = context->privData))
961		return XvMCBadContext;
962
963	/* Pass Control to the X server to destroy the drm_context_t */
964	i915_release_resource(display, context);
965
966	return Success;
967}
968
969static int i915_xvmc_alloc_render_state_buffers(i915XvMCContext *pI915XvMC)
970{
971	pI915XvMC->sis_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
972					       "sis",
973					       GTT_PAGE_SIZE,
974					       GTT_PAGE_SIZE);
975	if (!pI915XvMC->sis_bo)
976		return 0;
977
978	pI915XvMC->msb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
979					       "msb",
980					       GTT_PAGE_SIZE,
981					       GTT_PAGE_SIZE);
982	if (!pI915XvMC->msb_bo)
983		return 0;
984
985	pI915XvMC->corrdata_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
986					       "corrdata",
987					       CORRDATA_SIZE,
988					       GTT_PAGE_SIZE);
989	if (!pI915XvMC->corrdata_bo)
990		return 0;
991
992	return 1;
993}
994
995static void i915_xvmc_free_render_state_buffers(i915XvMCContext *pI915XvMC)
996{
997	drm_intel_bo_unreference(pI915XvMC->sis_bo);
998	drm_intel_bo_unreference(pI915XvMC->msb_bo);
999	drm_intel_bo_unreference(pI915XvMC->corrdata_bo);
1000}
1001
1002static int i915_xvmc_mc_render_surface(Display * display, XvMCContext * context,
1003				       unsigned int picture_structure,
1004				       XvMCSurface * target_surface,
1005				       XvMCSurface * past_surface,
1006				       XvMCSurface * future_surface,
1007				       unsigned int flags,
1008				       unsigned int num_macroblocks,
1009				       unsigned int first_macroblock,
1010				       XvMCMacroBlockArray * macroblock_array,
1011				       XvMCBlockArray * blocks)
1012{
1013	int i;
1014	int picture_coding_type = MPEG_I_PICTURE;
1015	/* correction data buffer */
1016	char *corrdata_ptr;
1017	int corrdata_size = 0;
1018
1019	/* Block Pointer */
1020	short *block_ptr;
1021	/* Current Macroblock Pointer */
1022	XvMCMacroBlock *mb;
1023
1024	intel_xvmc_context_ptr intel_ctx;
1025
1026	struct intel_xvmc_surface *privTarget = NULL;
1027	struct intel_xvmc_surface *privFuture = NULL;
1028	struct intel_xvmc_surface *privPast = NULL;
1029	i915XvMCContext *pI915XvMC = NULL;
1030
1031	/* Check Parameters for validity */
1032	if (!display || !context || !target_surface) {
1033		XVMC_ERR("Invalid Display, Context or Target!");
1034		return BadValue;
1035	}
1036
1037	if (!num_macroblocks)
1038		return Success;
1039
1040	if (!macroblock_array || !blocks) {
1041		XVMC_ERR("Invalid block data!");
1042		return BadValue;
1043	}
1044
1045	if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
1046		XVMC_ERR("Too many macroblocks requested for MB array size.");
1047		return BadValue;
1048	}
1049
1050	if (!(pI915XvMC = context->privData))
1051		return XvMCBadContext;
1052
1053	if (!(privTarget = target_surface->privData))
1054		return XvMCBadSurface;
1055
1056	if (!i915_xvmc_alloc_render_state_buffers(pI915XvMC))
1057		return BadAlloc;
1058
1059	intel_ctx = context->privData;
1060	if (!intel_ctx) {
1061		XVMC_ERR("Can't find intel xvmc context\n");
1062		return BadValue;
1063	}
1064
1065	/* P Frame Test */
1066	if (!past_surface) {
1067		/* Just to avoid some ifs later. */
1068		privPast = privTarget;
1069	} else {
1070		if (!(privPast = past_surface->privData)) {
1071			return XvMCBadSurface;
1072		}
1073		picture_coding_type = MPEG_P_PICTURE;
1074	}
1075
1076	/* B Frame Test */
1077	if (!future_surface) {
1078		privFuture = privPast;	// privTarget;
1079	} else {
1080		if (!past_surface) {
1081			XVMC_ERR("No Past Surface!");
1082			return BadValue;
1083		}
1084
1085		if (!(privFuture = future_surface->privData)) {
1086			XVMC_ERR("Invalid Future Surface!");
1087			return XvMCBadSurface;
1088		}
1089
1090		picture_coding_type = MPEG_B_PICTURE;
1091	}
1092
1093	LOCK_HARDWARE(intel_ctx->hw_context);
1094	drm_intel_gem_bo_map_gtt(pI915XvMC->corrdata_bo);
1095	corrdata_ptr = pI915XvMC->corrdata_bo->virtual;
1096	corrdata_size = 0;
1097
1098	for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
1099	     i++) {
1100		int bspm = 0;
1101		mb = &macroblock_array->macro_blocks[i];
1102		block_ptr = &(blocks->blocks[mb->index << 6]);
1103
1104		/* Lockup can happen if the coordinates are too far out of range */
1105		if (mb->x > (target_surface->width >> 4)) {
1106			mb->x = 0;
1107			XVMC_INFO("reset x");
1108		}
1109
1110		if (mb->y > (target_surface->height >> 4)) {
1111			mb->y = 0;
1112			XVMC_INFO("reset y");
1113		}
1114
1115		/* Catch no pattern case */
1116		if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) &&
1117		    !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) &&
1118		    mb->coded_block_pattern) {
1119			mb->coded_block_pattern = 0;
1120			XVMC_INFO("no coded blocks present!");
1121		}
1122
1123		bspm = mb_bytes_420[mb->coded_block_pattern];
1124
1125		if (!bspm)
1126			continue;
1127
1128		corrdata_size += bspm;
1129
1130		if (corrdata_size > CORRDATA_SIZE) {
1131			XVMC_ERR("correction data buffer overflow.");
1132			break;
1133		}
1134		memcpy(corrdata_ptr, block_ptr, bspm);
1135		corrdata_ptr += bspm;
1136	}
1137
1138	drm_intel_gem_bo_unmap_gtt(pI915XvMC->corrdata_bo);
1139
1140	// i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB
1141	// | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC);
1142
1143	i915_mc_one_time_state_emit(context);
1144
1145	i915_mc_static_indirect_state_set(context, target_surface,
1146					  picture_structure, flags,
1147					  picture_coding_type);
1148	/* setup reference surfaces */
1149	i915_mc_map_state_set(context, privPast, privFuture);
1150
1151	i915_mc_load_indirect_render_emit(context);
1152
1153	i915_mc_mpeg_set_origin(context,
1154				&macroblock_array->macro_blocks
1155				[first_macroblock]);
1156
1157	for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
1158	     i++) {
1159		mb = &macroblock_array->macro_blocks[i];
1160
1161		/* Intra Blocks */
1162		if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
1163			i915_mc_mpeg_macroblock_ipicture(context, mb);
1164		} else if ((picture_structure & XVMC_FRAME_PICTURE) ==
1165			   XVMC_FRAME_PICTURE) {
1166			/* Frame Picture */
1167			switch (mb->motion_type & 3) {
1168			case XVMC_PREDICTION_FIELD:	/* Field Based */
1169				i915_mc_mpeg_macroblock_2fbmv(context, mb,
1170							      picture_structure);
1171				break;
1172
1173			case XVMC_PREDICTION_FRAME:	/* Frame Based */
1174				i915_mc_mpeg_macroblock_1fbmv(context, mb);
1175				break;
1176
1177			case XVMC_PREDICTION_DUAL_PRIME:	/* Dual Prime */
1178				i915_mc_mpeg_macroblock_2fbmv(context, mb,
1179							      picture_structure);
1180				break;
1181
1182			default:	/* No Motion Type */
1183				XVMC_ERR
1184				    ("Invalid Macroblock Parameters found.");
1185				break;
1186			}
1187		} else {	/* Field Picture */
1188			switch (mb->motion_type & 3) {
1189			case XVMC_PREDICTION_FIELD:	/* Field Based */
1190				i915_mc_mpeg_macroblock_1fbmv(context, mb);
1191				break;
1192
1193			case XVMC_PREDICTION_16x8:	/* 16x8 MC */
1194				i915_mc_mpeg_macroblock_2fbmv(context, mb,
1195							      picture_structure);
1196				break;
1197
1198			case XVMC_PREDICTION_DUAL_PRIME:	/* Dual Prime */
1199				i915_mc_mpeg_macroblock_1fbmv(context, mb);
1200				break;
1201
1202			default:	/* No Motion Type */
1203				XVMC_ERR
1204				    ("Invalid Macroblock Parameters found.");
1205				break;
1206			}
1207		}
1208	}
1209
1210	intelFlushBatch();
1211
1212	i915_xvmc_free_render_state_buffers(pI915XvMC);
1213
1214	UNLOCK_HARDWARE(intel_ctx->hw_context);
1215	return 0;
1216}
1217
1218struct _intel_xvmc_driver i915_xvmc_mc_driver = {
1219	.type = XVMC_I915_MPEG2_MC,
1220	.num_ctx = 0,
1221	.ctx_list = NULL,
1222	.create_context = i915_xvmc_mc_create_context,
1223	.destroy_context = i915_xvmc_mc_destroy_context,
1224	.render_surface = i915_xvmc_mc_render_surface,
1225};
1226