103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2006 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Authors:
2403b705cfSriastradh *    Xiang Haihao <haihao.xiang@intel.com>
2503b705cfSriastradh *
2603b705cfSriastradh */
2703b705cfSriastradh
2803b705cfSriastradh#include <sys/ioctl.h>
2903b705cfSriastradh
3003b705cfSriastradh#include "i915_xvmc.h"
3103b705cfSriastradh#include "i915_structs.h"
3203b705cfSriastradh#include "i915_program.h"
3303b705cfSriastradh
3403b705cfSriastradh#define ALIGN(i,m)		(((i) + (m) - 1) & ~((m) - 1))
3503b705cfSriastradh
3603b705cfSriastradh#define STRIDE(w)               (ALIGN((w), 1024))
3703b705cfSriastradh#define SIZE_Y420(w, h)         (h * STRIDE(w))
3803b705cfSriastradh#define SIZE_UV420(w, h)        ((h >> 1) * STRIDE(w >> 1))
3903b705cfSriastradh#define SIZE_YUV420(w, h)       (SIZE_Y420(w,h) + SIZE_UV420(w,h) * 2)
4003b705cfSriastradh#define UOFFSET(context)        (SIZE_Y420(context->width, context->height))
4103b705cfSriastradh#define VOFFSET(context)        (SIZE_Y420(context->width, context->height) + \
4203b705cfSriastradh                                 SIZE_UV420(context->width, context->height))
4303b705cfSriastradh
4403b705cfSriastradhtypedef union {
4503b705cfSriastradh	int16_t component[2];
4603b705cfSriastradh	int32_t v;
4703b705cfSriastradh} vector_t;
4803b705cfSriastradh
4903b705cfSriastradhstatic void i915_inst_arith(unsigned int *inst,
5003b705cfSriastradh			    unsigned int op,
5103b705cfSriastradh			    unsigned int dest,
5203b705cfSriastradh			    unsigned int mask,
5303b705cfSriastradh			    unsigned int saturate,
5403b705cfSriastradh			    unsigned int src0, unsigned int src1,
5503b705cfSriastradh			    unsigned int src2)
5603b705cfSriastradh{
5703b705cfSriastradh	dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
5803b705cfSriastradh	*inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
5903b705cfSriastradh	inst++;
6003b705cfSriastradh	*inst = (A1_SRC0(src0) | A1_SRC1(src1));
6103b705cfSriastradh	inst++;
6203b705cfSriastradh	*inst = (A2_SRC1(src1) | A2_SRC2(src2));
6303b705cfSriastradh}
6403b705cfSriastradh
6503b705cfSriastradhstatic void i915_inst_decl(unsigned int *inst,
6603b705cfSriastradh			   unsigned int type,
6703b705cfSriastradh			   unsigned int nr, unsigned int d0_flags)
6803b705cfSriastradh{
6903b705cfSriastradh	unsigned int reg = UREG(type, nr);
7003b705cfSriastradh
7103b705cfSriastradh	*inst = (D0_DCL | D0_DEST(reg) | d0_flags);
7203b705cfSriastradh	inst++;
7303b705cfSriastradh	*inst = D1_MBZ;
7403b705cfSriastradh	inst++;
7503b705cfSriastradh	*inst = D2_MBZ;
7603b705cfSriastradh}
7703b705cfSriastradh
7803b705cfSriastradhstatic void i915_inst_texld(unsigned int *inst,
7903b705cfSriastradh			    unsigned int op,
8003b705cfSriastradh			    unsigned int dest,
8103b705cfSriastradh			    unsigned int coord, unsigned int sampler)
8203b705cfSriastradh{
8303b705cfSriastradh	dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
8403b705cfSriastradh	*inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler));
8503b705cfSriastradh	inst++;
8603b705cfSriastradh	*inst = T1_ADDRESS_REG(coord);
8703b705cfSriastradh	inst++;
8803b705cfSriastradh	*inst = T2_MBZ;
8903b705cfSriastradh}
9003b705cfSriastradh
9103b705cfSriastradhstatic void i915_mc_one_time_context_init(XvMCContext * context)
9203b705cfSriastradh{
9303b705cfSriastradh	unsigned int dest, src0, src1, src2;
9403b705cfSriastradh	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
9503b705cfSriastradh	int i;
9603b705cfSriastradh	struct i915_3dstate_sampler_state *sampler_state;
9703b705cfSriastradh	struct i915_3dstate_pixel_shader_program *pixel_shader_program;
9803b705cfSriastradh	struct i915_3dstate_pixel_shader_constants *pixel_shader_constants;
9903b705cfSriastradh
10003b705cfSriastradh	/* sampler static state */
10103b705cfSriastradh	drm_intel_gem_bo_map_gtt(pI915XvMC->ssb_bo);
10203b705cfSriastradh	sampler_state = pI915XvMC->ssb_bo->virtual;
10303b705cfSriastradh
10403b705cfSriastradh	memset(sampler_state, 0, sizeof(*sampler_state));
10503b705cfSriastradh	sampler_state->dw0.type = CMD_3D;
10603b705cfSriastradh	sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE;
10703b705cfSriastradh	sampler_state->dw0.length = 6;
10803b705cfSriastradh	sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1;
10903b705cfSriastradh
11003b705cfSriastradh	sampler_state->sampler0.ts0.reverse_gamma = 0;
11103b705cfSriastradh	sampler_state->sampler0.ts0.planar2packet = 0;
11203b705cfSriastradh	sampler_state->sampler0.ts0.color_conversion = 0;
11303b705cfSriastradh	sampler_state->sampler0.ts0.chromakey_index = 0;
11403b705cfSriastradh	sampler_state->sampler0.ts0.base_level = 0;
11503b705cfSriastradh	sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE;	/* NONE */
11603b705cfSriastradh	sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR;	/* LINEAR */
11703b705cfSriastradh	sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR;	/* LINEAR */
11803b705cfSriastradh	sampler_state->sampler0.ts0.lod_bias = 0;	/* 0.0 */
11903b705cfSriastradh	sampler_state->sampler0.ts0.shadow_enable = 0;
12003b705cfSriastradh	sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2;
12103b705cfSriastradh	sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS;
12203b705cfSriastradh	sampler_state->sampler0.ts1.min_lod = 0;	/* 0.0 Maximum Mip Level */
12303b705cfSriastradh	sampler_state->sampler0.ts1.kill_pixel = 0;
12403b705cfSriastradh	sampler_state->sampler0.ts1.keyed_texture_filter = 0;
12503b705cfSriastradh	sampler_state->sampler0.ts1.chromakey_enable = 0;
12603b705cfSriastradh	sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP;
12703b705cfSriastradh	sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP;
12803b705cfSriastradh	sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP;
12903b705cfSriastradh	sampler_state->sampler0.ts1.normalized_coor = 0;
13003b705cfSriastradh	sampler_state->sampler0.ts1.map_index = 0;
13103b705cfSriastradh	sampler_state->sampler0.ts1.east_deinterlacer = 0;
13203b705cfSriastradh	sampler_state->sampler0.ts2.default_color = 0;
13303b705cfSriastradh
13403b705cfSriastradh	sampler_state->sampler1.ts0.reverse_gamma = 0;
13503b705cfSriastradh	sampler_state->sampler1.ts0.planar2packet = 0;
13603b705cfSriastradh	sampler_state->sampler1.ts0.color_conversion = 0;
13703b705cfSriastradh	sampler_state->sampler1.ts0.chromakey_index = 0;
13803b705cfSriastradh	sampler_state->sampler1.ts0.base_level = 0;
13903b705cfSriastradh	sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE;	/* NONE */
14003b705cfSriastradh	sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR;	/* LINEAR */
14103b705cfSriastradh	sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR;	/* LINEAR */
14203b705cfSriastradh	sampler_state->sampler1.ts0.lod_bias = 0;	/* 0.0 */
14303b705cfSriastradh	sampler_state->sampler1.ts0.shadow_enable = 0;
14403b705cfSriastradh	sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2;
14503b705cfSriastradh	sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS;
14603b705cfSriastradh	sampler_state->sampler1.ts1.min_lod = 0;	/* 0.0 Maximum Mip Level */
14703b705cfSriastradh	sampler_state->sampler1.ts1.kill_pixel = 0;
14803b705cfSriastradh	sampler_state->sampler1.ts1.keyed_texture_filter = 0;
14903b705cfSriastradh	sampler_state->sampler1.ts1.chromakey_enable = 0;
15003b705cfSriastradh	sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP;
15103b705cfSriastradh	sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP;
15203b705cfSriastradh	sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP;
15303b705cfSriastradh	sampler_state->sampler1.ts1.normalized_coor = 0;
15403b705cfSriastradh	sampler_state->sampler1.ts1.map_index = 1;
15503b705cfSriastradh	sampler_state->sampler1.ts1.east_deinterlacer = 0;
15603b705cfSriastradh	sampler_state->sampler1.ts2.default_color = 0;
15703b705cfSriastradh
15803b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(pI915XvMC->ssb_bo);
15903b705cfSriastradh
16003b705cfSriastradh	/* pixel shader static state */
16103b705cfSriastradh	drm_intel_gem_bo_map_gtt(pI915XvMC->psp_bo);
16203b705cfSriastradh	pixel_shader_program = pI915XvMC->psp_bo->virtual;
16303b705cfSriastradh
16403b705cfSriastradh	memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
16503b705cfSriastradh	pixel_shader_program->shader0.type = CMD_3D;
16603b705cfSriastradh	pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
16703b705cfSriastradh	pixel_shader_program->shader0.retain = 1;
16803b705cfSriastradh	pixel_shader_program->shader0.length = 2;	/* 1 inst */
16903b705cfSriastradh	i = 0;
17003b705cfSriastradh
17103b705cfSriastradh	dest = UREG(REG_TYPE_OC, 0);
17203b705cfSriastradh	src0 = UREG(REG_TYPE_CONST, 0);
17303b705cfSriastradh	src1 = 0;
17403b705cfSriastradh	src2 = 0;
17503b705cfSriastradh	i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV,
17603b705cfSriastradh			dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
17703b705cfSriastradh			src2);
17803b705cfSriastradh
17903b705cfSriastradh	pixel_shader_program->shader1.type = CMD_3D;
18003b705cfSriastradh	pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
18103b705cfSriastradh	pixel_shader_program->shader1.retain = 1;
18203b705cfSriastradh	pixel_shader_program->shader1.length = 14;	/* 5 inst */
18303b705cfSriastradh	i = 0;
18403b705cfSriastradh	/* dcl t0.xy */
18503b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0,
18603b705cfSriastradh		       D0_CHANNEL_XY);
18703b705cfSriastradh	i += 3;
18803b705cfSriastradh	/* dcl t1.xy */
18903b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1,
19003b705cfSriastradh		       D0_CHANNEL_XY);
19103b705cfSriastradh	/* dcl_2D s0 */
19203b705cfSriastradh	i += 3;
19303b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0,
19403b705cfSriastradh		       D0_SAMPLE_TYPE_2D);
19503b705cfSriastradh	/* texld r0, t0, s0 */
19603b705cfSriastradh	i += 3;
19703b705cfSriastradh	dest = UREG(REG_TYPE_R, 0);
19803b705cfSriastradh	src0 = UREG(REG_TYPE_T, 0);	/* COORD */
19903b705cfSriastradh	src1 = UREG(REG_TYPE_S, 0);	/* SAMPLER */
20003b705cfSriastradh	i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0,
20103b705cfSriastradh			src1);
20203b705cfSriastradh	/* mov oC, r0 */
20303b705cfSriastradh	i += 3;
20403b705cfSriastradh	dest = UREG(REG_TYPE_OC, 0);
20503b705cfSriastradh	src0 = UREG(REG_TYPE_R, 0);
20603b705cfSriastradh	src1 = src2 = 0;
20703b705cfSriastradh	i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest,
20803b705cfSriastradh			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
20903b705cfSriastradh			src2);
21003b705cfSriastradh
21103b705cfSriastradh	pixel_shader_program->shader2.type = CMD_3D;
21203b705cfSriastradh	pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
21303b705cfSriastradh	pixel_shader_program->shader2.retain = 1;
21403b705cfSriastradh	pixel_shader_program->shader2.length = 14;	/* 5 inst */
21503b705cfSriastradh	i = 0;
21603b705cfSriastradh	/* dcl t2.xy */
21703b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2,
21803b705cfSriastradh		       D0_CHANNEL_XY);
21903b705cfSriastradh	/* dcl t3.xy */
22003b705cfSriastradh	i += 3;
22103b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3,
22203b705cfSriastradh		       D0_CHANNEL_XY);
22303b705cfSriastradh	/* dcl_2D s1 */
22403b705cfSriastradh	i += 3;
22503b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1,
22603b705cfSriastradh		       D0_SAMPLE_TYPE_2D);
22703b705cfSriastradh	/* texld r0, t2, s1 */
22803b705cfSriastradh	i += 3;
22903b705cfSriastradh	dest = UREG(REG_TYPE_R, 0);
23003b705cfSriastradh	src0 = UREG(REG_TYPE_T, 2);	/* COORD */
23103b705cfSriastradh	src1 = UREG(REG_TYPE_S, 1);	/* SAMPLER */
23203b705cfSriastradh	i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0,
23303b705cfSriastradh			src1);
23403b705cfSriastradh	/* mov oC, r0 */
23503b705cfSriastradh	i += 3;
23603b705cfSriastradh	dest = UREG(REG_TYPE_OC, 0);
23703b705cfSriastradh	src0 = UREG(REG_TYPE_R, 0);
23803b705cfSriastradh	src1 = src2 = 0;
23903b705cfSriastradh	i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest,
24003b705cfSriastradh			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
24103b705cfSriastradh			src2);
24203b705cfSriastradh
24303b705cfSriastradh	/* Shader 3 */
24403b705cfSriastradh	pixel_shader_program->shader3.type = CMD_3D;
24503b705cfSriastradh	pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
24603b705cfSriastradh	pixel_shader_program->shader3.retain = 1;
24703b705cfSriastradh	pixel_shader_program->shader3.length = 29;	/* 10 inst */
24803b705cfSriastradh	i = 0;
24903b705cfSriastradh	/* dcl t0.xy */
25003b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0,
25103b705cfSriastradh		       D0_CHANNEL_XY);
25203b705cfSriastradh	/* dcl t1.xy */
25303b705cfSriastradh	i += 3;
25403b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1,
25503b705cfSriastradh		       D0_CHANNEL_XY);
25603b705cfSriastradh	/* dcl t2.xy */
25703b705cfSriastradh	i += 3;
25803b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2,
25903b705cfSriastradh		       D0_CHANNEL_XY);
26003b705cfSriastradh	/* dcl t3.xy */
26103b705cfSriastradh	i += 3;
26203b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3,
26303b705cfSriastradh		       D0_CHANNEL_XY);
26403b705cfSriastradh	/* dcl_2D s0 */
26503b705cfSriastradh	i += 3;
26603b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0,
26703b705cfSriastradh		       D0_SAMPLE_TYPE_2D);
26803b705cfSriastradh	/* dcl_2D s1 */
26903b705cfSriastradh	i += 3;
27003b705cfSriastradh	i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1,
27103b705cfSriastradh		       D0_SAMPLE_TYPE_2D);
27203b705cfSriastradh	/* texld r0, t0, s0 */
27303b705cfSriastradh	i += 3;
27403b705cfSriastradh	dest = UREG(REG_TYPE_R, 0);
27503b705cfSriastradh	src0 = UREG(REG_TYPE_T, 0);	/* COORD */
27603b705cfSriastradh	src1 = UREG(REG_TYPE_S, 0);	/* SAMPLER */
27703b705cfSriastradh	i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
27803b705cfSriastradh			src1);
27903b705cfSriastradh	/* texld r1, t2, s1 */
28003b705cfSriastradh	i += 3;
28103b705cfSriastradh	dest = UREG(REG_TYPE_R, 1);
28203b705cfSriastradh	src0 = UREG(REG_TYPE_T, 2);	/* COORD */
28303b705cfSriastradh	src1 = UREG(REG_TYPE_S, 1);	/* SAMPLER */
28403b705cfSriastradh	i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
28503b705cfSriastradh			src1);
28603b705cfSriastradh	/* add r0, r0, r1 */
28703b705cfSriastradh	i += 3;
28803b705cfSriastradh	dest = UREG(REG_TYPE_R, 0);
28903b705cfSriastradh	src0 = UREG(REG_TYPE_R, 0);
29003b705cfSriastradh	src1 = UREG(REG_TYPE_R, 1);
29103b705cfSriastradh	src2 = 0;
29203b705cfSriastradh	i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest,
29303b705cfSriastradh			A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */ , src0,
29403b705cfSriastradh			src1, src2);
29503b705cfSriastradh	/* mul oC, r0, c0 */
29603b705cfSriastradh	i += 3;
29703b705cfSriastradh	dest = UREG(REG_TYPE_OC, 0);
29803b705cfSriastradh	src0 = UREG(REG_TYPE_R, 0);
29903b705cfSriastradh	src1 = UREG(REG_TYPE_CONST, 0);
30003b705cfSriastradh	src2 = 0;
30103b705cfSriastradh	i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest,
30203b705cfSriastradh			A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
30303b705cfSriastradh			src2);
30403b705cfSriastradh
30503b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(pI915XvMC->psp_bo);
30603b705cfSriastradh
30703b705cfSriastradh	/* pixel shader contant static state */
30803b705cfSriastradh	drm_intel_gem_bo_map_gtt(pI915XvMC->psc_bo);
30903b705cfSriastradh	pixel_shader_constants = pI915XvMC->psc_bo->virtual;
31003b705cfSriastradh
31103b705cfSriastradh	memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants));
31203b705cfSriastradh	pixel_shader_constants->dw0.type = CMD_3D;
31303b705cfSriastradh	pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS;
31403b705cfSriastradh	pixel_shader_constants->dw0.length = 4;
31503b705cfSriastradh	pixel_shader_constants->dw1.reg_mask = REG_CR0;
31603b705cfSriastradh	pixel_shader_constants->value.x = 0.5;
31703b705cfSriastradh	pixel_shader_constants->value.y = 0.5;
31803b705cfSriastradh	pixel_shader_constants->value.z = 0.5;
31903b705cfSriastradh	pixel_shader_constants->value.w = 0.5;
32003b705cfSriastradh
32103b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(pI915XvMC->psc_bo);
32203b705cfSriastradh}
32303b705cfSriastradh
32403b705cfSriastradhstatic void i915_mc_one_time_state_emit(XvMCContext * context)
32503b705cfSriastradh{
32603b705cfSriastradh	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
32703b705cfSriastradh	uint32_t load_state_immediate_1, load_indirect, s3_dword, s6_dword;
32803b705cfSriastradh	int mem_select;
32903b705cfSriastradh	BATCH_LOCALS;
33003b705cfSriastradh
33103b705cfSriastradh	/* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */
33203b705cfSriastradh	BEGIN_BATCH(3 + 8);
33303b705cfSriastradh	load_state_immediate_1 = OP_3D_LOAD_STATE_IMMEDIATE_1;
33403b705cfSriastradh	load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S3;
33503b705cfSriastradh	load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S6;
33603b705cfSriastradh	load_state_immediate_1 |= 3 - 2; /* length */
33703b705cfSriastradh	OUT_BATCH(load_state_immediate_1);
33803b705cfSriastradh
33903b705cfSriastradh	s3_dword = S3_SET0_PCD | S3_SET1_PCD |
34003b705cfSriastradh		   S3_SET2_PCD | S3_SET3_PCD |
34103b705cfSriastradh		   S3_SET4_PCD | S3_SET5_PCD |
34203b705cfSriastradh		   S3_SET6_PCD | S3_SET7_PCD;
34303b705cfSriastradh	OUT_BATCH(s3_dword);
34403b705cfSriastradh
34503b705cfSriastradh	s6_dword = S6_COLOR_BUFFER_WRITE | S6_DEPTH_TEST_ENABLE;
34603b705cfSriastradh	s6_dword |= 1 << S6_SRC_BLEND_FACTOR_SHIFT;
34703b705cfSriastradh	s6_dword |= 1 << S6_DST_BLEND_FACTOR_SHIFT;
34803b705cfSriastradh	OUT_BATCH(s6_dword);
34903b705cfSriastradh
35003b705cfSriastradh	/* 3DSTATE_LOAD_INDIRECT */
35103b705cfSriastradh	load_indirect = OP_3D_LOAD_INDIRECT;
35203b705cfSriastradh	load_indirect |= (BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC)
35303b705cfSriastradh				<< BLOCK_MASK_SHIFT;
35403b705cfSriastradh	load_indirect |= 8 - 2; /* length */
35503b705cfSriastradh
35603b705cfSriastradh	if (pI915XvMC->use_phys_addr)
35703b705cfSriastradh		mem_select = 0;	/* use physical address */
35803b705cfSriastradh	else {
35903b705cfSriastradh		load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
36003b705cfSriastradh		mem_select = 1;	/* use gfx address */
36103b705cfSriastradh	}
36203b705cfSriastradh
36303b705cfSriastradh	OUT_BATCH(load_indirect);
36403b705cfSriastradh
36503b705cfSriastradh	/* Dynamic indirect state buffer */
36603b705cfSriastradh	OUT_BATCH(0); /* no dynamic indirect state */
36703b705cfSriastradh
36803b705cfSriastradh	/* Sample state buffer */
36903b705cfSriastradh	OUT_RELOC(pI915XvMC->ssb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
37003b705cfSriastradh			STATE_VALID | STATE_FORCE);
37103b705cfSriastradh	OUT_BATCH(7);	/* 8 - 1 */
37203b705cfSriastradh
37303b705cfSriastradh	/* Pixel shader program buffer */
37403b705cfSriastradh	OUT_RELOC(pI915XvMC->psp_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
37503b705cfSriastradh			STATE_VALID | STATE_FORCE);
37603b705cfSriastradh	OUT_BATCH(66);	/* 4 + 16 + 16 + 31 - 1 */
37703b705cfSriastradh
37803b705cfSriastradh	/* Pixel shader constant buffer */
37903b705cfSriastradh	OUT_RELOC(pI915XvMC->psc_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
38003b705cfSriastradh			STATE_VALID | STATE_FORCE);
38103b705cfSriastradh	OUT_BATCH(5);	/* 6 - 1 */
38203b705cfSriastradh	ADVANCE_BATCH();
38303b705cfSriastradh}
38403b705cfSriastradh
38503b705cfSriastradhstatic void i915_mc_static_indirect_state_set(XvMCContext * context,
38603b705cfSriastradh					      XvMCSurface * dest,
38703b705cfSriastradh					      unsigned int picture_structure,
38803b705cfSriastradh					      unsigned int flags,
38903b705cfSriastradh					      unsigned int picture_coding_type)
39003b705cfSriastradh{
39103b705cfSriastradh	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
39203b705cfSriastradh	struct intel_xvmc_surface *intel_surf = dest->privData;
39303b705cfSriastradh	struct i915_mc_static_indirect_state_buffer *buffer_info;
39403b705cfSriastradh
39503b705cfSriastradh	drm_intel_gem_bo_map_gtt(pI915XvMC->sis_bo);
39603b705cfSriastradh	buffer_info = pI915XvMC->sis_bo->virtual;
39703b705cfSriastradh
39803b705cfSriastradh	memset(buffer_info, 0, sizeof(*buffer_info));
39903b705cfSriastradh
40003b705cfSriastradh	/* dest Y */
40103b705cfSriastradh	buffer_info->dest_y.dw0.type = CMD_3D;
40203b705cfSriastradh	buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
40303b705cfSriastradh	buffer_info->dest_y.dw0.length = 1;
40403b705cfSriastradh	buffer_info->dest_y.dw1.aux_id = 0;
40503b705cfSriastradh	buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK;
40603b705cfSriastradh	buffer_info->dest_y.dw1.fence_regs = 0;	/* disabled *//* FIXME: tiled y for performance */
40703b705cfSriastradh	buffer_info->dest_y.dw1.tiled_surface = 0;	/* linear */
40803b705cfSriastradh	buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR;
40903b705cfSriastradh	buffer_info->dest_y.dw1.pitch = (pI915XvMC->yStride >> 2);	/* in DWords */
41003b705cfSriastradh	buffer_info->dest_y.dw2.base_address = intel_surf->bo->offset >> 2;	/* starting DWORD address */
41103b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
41203b705cfSriastradh				offsetof(typeof(*buffer_info),dest_y.dw2),
41303b705cfSriastradh				intel_surf->bo, 0,
41403b705cfSriastradh				I915_GEM_DOMAIN_RENDER,
41503b705cfSriastradh				I915_GEM_DOMAIN_RENDER);
41603b705cfSriastradh
41703b705cfSriastradh	/* dest U */
41803b705cfSriastradh	buffer_info->dest_u.dw0.type = CMD_3D;
41903b705cfSriastradh	buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
42003b705cfSriastradh	buffer_info->dest_u.dw0.length = 1;
42103b705cfSriastradh	buffer_info->dest_u.dw1.aux_id = 0;
42203b705cfSriastradh	buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX;
42303b705cfSriastradh	buffer_info->dest_u.dw1.fence_regs = 0;
42403b705cfSriastradh	buffer_info->dest_u.dw1.tiled_surface = 0;
42503b705cfSriastradh	buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR;
42603b705cfSriastradh	buffer_info->dest_u.dw1.pitch = (pI915XvMC->uvStride >> 2);	/* in DWords */
42703b705cfSriastradh	buffer_info->dest_u.dw2.base_address =
42803b705cfSriastradh		(intel_surf->bo->offset + UOFFSET(context)) >> 2;
42903b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
43003b705cfSriastradh				offsetof(typeof(*buffer_info),dest_u.dw2),
43103b705cfSriastradh				intel_surf->bo, UOFFSET(context),
43203b705cfSriastradh				I915_GEM_DOMAIN_RENDER,
43303b705cfSriastradh				I915_GEM_DOMAIN_RENDER);
43403b705cfSriastradh
43503b705cfSriastradh	/* dest V */
43603b705cfSriastradh	buffer_info->dest_v.dw0.type = CMD_3D;
43703b705cfSriastradh	buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
43803b705cfSriastradh	buffer_info->dest_v.dw0.length = 1;
43903b705cfSriastradh	buffer_info->dest_v.dw1.aux_id = 1;
44003b705cfSriastradh	buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX;
44103b705cfSriastradh	buffer_info->dest_v.dw1.fence_regs = 0;
44203b705cfSriastradh	buffer_info->dest_v.dw1.tiled_surface = 0;
44303b705cfSriastradh	buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR;
44403b705cfSriastradh	buffer_info->dest_v.dw1.pitch = (pI915XvMC->uvStride >> 2);	/* in Dwords */
44503b705cfSriastradh	buffer_info->dest_v.dw2.base_address =
44603b705cfSriastradh		(intel_surf->bo->offset + VOFFSET(context)) >> 2;
44703b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
44803b705cfSriastradh				offsetof(typeof(*buffer_info),dest_v.dw2),
44903b705cfSriastradh				intel_surf->bo, VOFFSET(context),
45003b705cfSriastradh				I915_GEM_DOMAIN_RENDER,
45103b705cfSriastradh				I915_GEM_DOMAIN_RENDER);
45203b705cfSriastradh
45303b705cfSriastradh	/* Dest buffer parameters */
45403b705cfSriastradh	buffer_info->dest_buf.dw0.type = CMD_3D;
45503b705cfSriastradh	buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES;
45603b705cfSriastradh	buffer_info->dest_buf.dw0.length = 0;
45703b705cfSriastradh	buffer_info->dest_buf.dw1.dest_v_bias = 8;	/* 0.5 */
45803b705cfSriastradh	buffer_info->dest_buf.dw1.dest_h_bias = 8;	/* 0.5 */
45903b705cfSriastradh	buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT;
46003b705cfSriastradh	buffer_info->dest_buf.dw1.v_ls = 0;	/* fill later */
46103b705cfSriastradh	buffer_info->dest_buf.dw1.v_ls_offset = 0;	/* fill later */
46203b705cfSriastradh	if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
46303b705cfSriastradh		;
46403b705cfSriastradh	} else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) {
46503b705cfSriastradh		buffer_info->dest_buf.dw1.v_ls = 1;
46603b705cfSriastradh	} else if ((picture_structure & XVMC_FRAME_PICTURE) ==
46703b705cfSriastradh		   XVMC_BOTTOM_FIELD) {
46803b705cfSriastradh		buffer_info->dest_buf.dw1.v_ls = 1;
46903b705cfSriastradh		buffer_info->dest_buf.dw1.v_ls_offset = 1;
47003b705cfSriastradh	}
47103b705cfSriastradh
47203b705cfSriastradh	/* MPEG buffer parameters */
47303b705cfSriastradh	buffer_info->dest_buf_mpeg.dw0.type = CMD_3D;
47403b705cfSriastradh	buffer_info->dest_buf_mpeg.dw0.opcode =
47503b705cfSriastradh	    OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG;
47603b705cfSriastradh	buffer_info->dest_buf_mpeg.dw0.length = 1;
47703b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC;
47803b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.rcontrol = 0;	/* for MPEG-1/MPEG-2 */
47903b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0;	/* for MPEG-1/MPEG-2/MPEG-4 */
48003b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1;
48103b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.intra8 = 0;	/* 16-bit formatted correction data */
48203b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.tff = 1;	/* fill later */
48303b705cfSriastradh
48403b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V;
48503b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H;
48603b705cfSriastradh
48703b705cfSriastradh	if (picture_structure & XVMC_FRAME_PICTURE) {
48803b705cfSriastradh		;
48903b705cfSriastradh	} else if (picture_structure & XVMC_TOP_FIELD) {
49003b705cfSriastradh		if (flags & XVMC_SECOND_FIELD)
49103b705cfSriastradh			buffer_info->dest_buf_mpeg.dw1.tff = 0;
49203b705cfSriastradh		else
49303b705cfSriastradh			buffer_info->dest_buf_mpeg.dw1.tff = 1;
49403b705cfSriastradh	} else if (picture_structure & XVMC_BOTTOM_FIELD) {
49503b705cfSriastradh		if (flags & XVMC_SECOND_FIELD)
49603b705cfSriastradh			buffer_info->dest_buf_mpeg.dw1.tff = 1;
49703b705cfSriastradh		else
49803b705cfSriastradh			buffer_info->dest_buf_mpeg.dw1.tff = 0;
49903b705cfSriastradh	}
50003b705cfSriastradh
50103b705cfSriastradh	buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4);	/* in macroblocks */
50203b705cfSriastradh	buffer_info->dest_buf_mpeg.dw2.picture_coding_type =
50303b705cfSriastradh	    picture_coding_type;
50403b705cfSriastradh
50503b705cfSriastradh	buffer_info->corr.dw0.type = CMD_3D;
50603b705cfSriastradh	buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
50703b705cfSriastradh	buffer_info->corr.dw0.length = 1;
50803b705cfSriastradh	buffer_info->corr.dw1.aux_id = 0;
50903b705cfSriastradh	buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR;
51003b705cfSriastradh	buffer_info->corr.dw1.aux_id = 0;
51103b705cfSriastradh	buffer_info->corr.dw1.fence_regs = 0;
51203b705cfSriastradh	buffer_info->corr.dw1.tiled_surface = 0;
51303b705cfSriastradh	buffer_info->corr.dw1.walk = 0;
51403b705cfSriastradh	buffer_info->corr.dw1.pitch = 0;
51503b705cfSriastradh	buffer_info->corr.dw2.base_address = pI915XvMC->corrdata_bo->offset >> 2;	/* starting DWORD address */
51603b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
51703b705cfSriastradh				offsetof(typeof(*buffer_info),corr.dw2),
51803b705cfSriastradh				pI915XvMC->corrdata_bo, 0,
51903b705cfSriastradh				I915_GEM_DOMAIN_RENDER, 0);
52003b705cfSriastradh
52103b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(pI915XvMC->sis_bo);
52203b705cfSriastradh}
52303b705cfSriastradh
52403b705cfSriastradhstatic void i915_mc_map_state_set(XvMCContext * context,
52503b705cfSriastradh				  struct intel_xvmc_surface * privPast,
52603b705cfSriastradh				  struct intel_xvmc_surface * privFuture)
52703b705cfSriastradh{
52803b705cfSriastradh	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
52903b705cfSriastradh	struct i915_mc_map_state *map_state;
53003b705cfSriastradh	unsigned int w = context->width;
53103b705cfSriastradh	unsigned int h = context->height;
53203b705cfSriastradh
53303b705cfSriastradh	drm_intel_gem_bo_map_gtt(pI915XvMC->msb_bo);
53403b705cfSriastradh	map_state = pI915XvMC->msb_bo->virtual;
53503b705cfSriastradh
53603b705cfSriastradh	memset(map_state, 0, sizeof(*map_state));
53703b705cfSriastradh
53803b705cfSriastradh	/* 3DSATE_MAP_STATE: Y */
53903b705cfSriastradh	map_state->y_map.dw0.type = CMD_3D;
54003b705cfSriastradh	map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
54103b705cfSriastradh	map_state->y_map.dw0.retain = 1;
54203b705cfSriastradh	map_state->y_map.dw0.length = 6;
54303b705cfSriastradh	map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
54403b705cfSriastradh
54503b705cfSriastradh	/* Y Forward (Past) */
54603b705cfSriastradh	map_state->y_forward.tm0.v_ls_offset = 0;
54703b705cfSriastradh	map_state->y_forward.tm0.v_ls = 0;
54803b705cfSriastradh	map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR;
54903b705cfSriastradh	map_state->y_forward.tm1.tiled_surface = 0;
55003b705cfSriastradh	map_state->y_forward.tm1.utilize_fence_regs = 0;
55103b705cfSriastradh	map_state->y_forward.tm1.texel_fmt = 0;	/* 8bit */
55203b705cfSriastradh	map_state->y_forward.tm1.surface_fmt = 1;	/* 8bit */
55303b705cfSriastradh	map_state->y_forward.tm1.width = w - 1;
55403b705cfSriastradh	map_state->y_forward.tm1.height = h - 1;
55503b705cfSriastradh	map_state->y_forward.tm2.depth = 0;
55603b705cfSriastradh	map_state->y_forward.tm2.max_lod = 0;
55703b705cfSriastradh	map_state->y_forward.tm2.cube_face = 0;
55803b705cfSriastradh	map_state->y_forward.tm0.base_address = privPast->bo->offset >> 2;
55903b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
56003b705cfSriastradh				offsetof(typeof(*map_state),y_forward.tm0),
56103b705cfSriastradh				privPast->bo, 0,
56203b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
56303b705cfSriastradh	map_state->y_forward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;	/* in DWords - 1 */
56403b705cfSriastradh
56503b705cfSriastradh	/* Y Backward (Future) */
56603b705cfSriastradh	map_state->y_backward.tm0.v_ls_offset = 0;
56703b705cfSriastradh	map_state->y_backward.tm0.v_ls = 0;
56803b705cfSriastradh	map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR;
56903b705cfSriastradh	map_state->y_backward.tm1.tiled_surface = 0;
57003b705cfSriastradh	map_state->y_backward.tm1.utilize_fence_regs = 0;
57103b705cfSriastradh	map_state->y_backward.tm1.texel_fmt = 0;	/* 8bit */
57203b705cfSriastradh	map_state->y_backward.tm1.surface_fmt = 1;	/* 8bit */
57303b705cfSriastradh	map_state->y_backward.tm1.width = w - 1;
57403b705cfSriastradh	map_state->y_backward.tm1.height = h - 1;
57503b705cfSriastradh	map_state->y_backward.tm2.depth = 0;
57603b705cfSriastradh	map_state->y_backward.tm2.max_lod = 0;
57703b705cfSriastradh	map_state->y_backward.tm2.cube_face = 0;
57803b705cfSriastradh	map_state->y_backward.tm0.base_address = privFuture->bo->offset >> 2;
57903b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
58003b705cfSriastradh				offsetof(typeof(*map_state),y_backward.tm0),
58103b705cfSriastradh				privFuture->bo, 0,
58203b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
58303b705cfSriastradh	map_state->y_backward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;
58403b705cfSriastradh
58503b705cfSriastradh	/* 3DSATE_MAP_STATE: U */
58603b705cfSriastradh	map_state->u_map.dw0.type = CMD_3D;
58703b705cfSriastradh	map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
58803b705cfSriastradh	map_state->u_map.dw0.retain = 1;
58903b705cfSriastradh	map_state->u_map.dw0.length = 6;
59003b705cfSriastradh	map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
59103b705cfSriastradh
59203b705cfSriastradh	/* U Forward */
59303b705cfSriastradh	map_state->u_forward.tm0.v_ls_offset = 0;
59403b705cfSriastradh	map_state->u_forward.tm0.v_ls = 0;
59503b705cfSriastradh	map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR;
59603b705cfSriastradh	map_state->u_forward.tm1.tiled_surface = 0;
59703b705cfSriastradh	map_state->u_forward.tm1.utilize_fence_regs = 0;
59803b705cfSriastradh	map_state->u_forward.tm1.texel_fmt = 0;	/* 8bit */
59903b705cfSriastradh	map_state->u_forward.tm1.surface_fmt = 1;	/* 8bit */
60003b705cfSriastradh	map_state->u_forward.tm1.width = (w >> 1) - 1;
60103b705cfSriastradh	map_state->u_forward.tm1.height = (h >> 1) - 1;
60203b705cfSriastradh	map_state->u_forward.tm2.depth = 0;
60303b705cfSriastradh	map_state->u_forward.tm2.max_lod = 0;
60403b705cfSriastradh	map_state->u_forward.tm2.cube_face = 0;
60503b705cfSriastradh	map_state->u_forward.tm0.base_address =
60603b705cfSriastradh		(privPast->bo->offset + UOFFSET(context)) >> 2;
60703b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
60803b705cfSriastradh				offsetof(typeof(*map_state),u_forward.tm0),
60903b705cfSriastradh				privPast->bo, UOFFSET(context),
61003b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
61103b705cfSriastradh	map_state->u_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;	/* in DWords - 1 */
61203b705cfSriastradh
61303b705cfSriastradh	/* U Backward */
61403b705cfSriastradh	map_state->u_backward.tm0.v_ls_offset = 0;
61503b705cfSriastradh	map_state->u_backward.tm0.v_ls = 0;
61603b705cfSriastradh	map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR;
61703b705cfSriastradh	map_state->u_backward.tm1.tiled_surface = 0;
61803b705cfSriastradh	map_state->u_backward.tm1.utilize_fence_regs = 0;
61903b705cfSriastradh	map_state->u_backward.tm1.texel_fmt = 0;
62003b705cfSriastradh	map_state->u_backward.tm1.surface_fmt = 1;
62103b705cfSriastradh	map_state->u_backward.tm1.width = (w >> 1) - 1;
62203b705cfSriastradh	map_state->u_backward.tm1.height = (h >> 1) - 1;
62303b705cfSriastradh	map_state->u_backward.tm2.depth = 0;
62403b705cfSriastradh	map_state->u_backward.tm2.max_lod = 0;
62503b705cfSriastradh	map_state->u_backward.tm2.cube_face = 0;
62603b705cfSriastradh	map_state->u_backward.tm0.base_address =
62703b705cfSriastradh		(privFuture->bo->offset + UOFFSET(context)) >> 2;
62803b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
62903b705cfSriastradh				offsetof(typeof(*map_state),u_backward.tm0),
63003b705cfSriastradh				privFuture->bo, UOFFSET(context),
63103b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
63203b705cfSriastradh	map_state->u_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
63303b705cfSriastradh
63403b705cfSriastradh	/* 3DSATE_MAP_STATE: V */
63503b705cfSriastradh	map_state->v_map.dw0.type = CMD_3D;
63603b705cfSriastradh	map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
63703b705cfSriastradh	map_state->v_map.dw0.retain = 1;
63803b705cfSriastradh	map_state->v_map.dw0.length = 6;
63903b705cfSriastradh	map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
64003b705cfSriastradh
64103b705cfSriastradh	/* V Forward */
64203b705cfSriastradh	map_state->v_forward.tm0.v_ls_offset = 0;
64303b705cfSriastradh	map_state->v_forward.tm0.v_ls = 0;
64403b705cfSriastradh	map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR;
64503b705cfSriastradh	map_state->v_forward.tm1.tiled_surface = 0;
64603b705cfSriastradh	map_state->v_forward.tm1.utilize_fence_regs = 0;
64703b705cfSriastradh	map_state->v_forward.tm1.texel_fmt = 0;
64803b705cfSriastradh	map_state->v_forward.tm1.surface_fmt = 1;
64903b705cfSriastradh	map_state->v_forward.tm1.width = (w >> 1) - 1;
65003b705cfSriastradh	map_state->v_forward.tm1.height = (h >> 1) - 1;
65103b705cfSriastradh	map_state->v_forward.tm2.depth = 0;
65203b705cfSriastradh	map_state->v_forward.tm2.max_lod = 0;
65303b705cfSriastradh	map_state->v_forward.tm2.cube_face = 0;
65403b705cfSriastradh	map_state->v_forward.tm0.base_address =
65503b705cfSriastradh		(privPast->bo->offset + VOFFSET(context)) >> 2;
65603b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
65703b705cfSriastradh				offsetof(typeof(*map_state),v_forward.tm0),
65803b705cfSriastradh				privPast->bo, VOFFSET(context),
65903b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
66003b705cfSriastradh	map_state->v_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;	/* in DWords - 1 */
66103b705cfSriastradh
66203b705cfSriastradh	/* V Backward */
66303b705cfSriastradh	map_state->v_backward.tm0.v_ls_offset = 0;
66403b705cfSriastradh	map_state->v_backward.tm0.v_ls = 0;
66503b705cfSriastradh	map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR;
66603b705cfSriastradh	map_state->v_backward.tm1.tiled_surface = 0;
66703b705cfSriastradh	map_state->v_backward.tm1.utilize_fence_regs = 0;
66803b705cfSriastradh	map_state->v_backward.tm1.texel_fmt = 0;
66903b705cfSriastradh	map_state->v_backward.tm1.surface_fmt = 1;
67003b705cfSriastradh	map_state->v_backward.tm1.width = (w >> 1) - 1;
67103b705cfSriastradh	map_state->v_backward.tm1.height = (h >> 1) - 1;
67203b705cfSriastradh	map_state->v_backward.tm2.depth = 0;
67303b705cfSriastradh	map_state->v_backward.tm2.max_lod = 0;
67403b705cfSriastradh	map_state->v_backward.tm2.cube_face = 0;
67503b705cfSriastradh	map_state->v_backward.tm0.base_address =
67603b705cfSriastradh		(privFuture->bo->offset + VOFFSET(context)) >> 2;
67703b705cfSriastradh	drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
67803b705cfSriastradh				offsetof(typeof(*map_state),v_backward.tm0),
67903b705cfSriastradh				privFuture->bo, VOFFSET(context),
68003b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
68103b705cfSriastradh	map_state->v_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
68203b705cfSriastradh
68303b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(pI915XvMC->msb_bo);
68403b705cfSriastradh}
68503b705cfSriastradh
68603b705cfSriastradhstatic void i915_mc_load_indirect_render_emit(XvMCContext * context)
68703b705cfSriastradh{
68803b705cfSriastradh	i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
68903b705cfSriastradh	int mem_select;
69003b705cfSriastradh	uint32_t load_indirect;
69103b705cfSriastradh	BATCH_LOCALS;
69203b705cfSriastradh
69303b705cfSriastradh	BEGIN_BATCH(5);
69403b705cfSriastradh	load_indirect = OP_3D_LOAD_INDIRECT;
69503b705cfSriastradh	load_indirect |= (BLOCK_SIS | BLOCK_MSB) << BLOCK_MASK_SHIFT;
69603b705cfSriastradh	load_indirect |= 5 - 2; /* length */
69703b705cfSriastradh
69803b705cfSriastradh	if (pI915XvMC->use_phys_addr)
69903b705cfSriastradh		mem_select = 0;	/* use physical address */
70003b705cfSriastradh	else {
70103b705cfSriastradh		load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
70203b705cfSriastradh		mem_select = 1;	/* use gfx address */
70303b705cfSriastradh	}
70403b705cfSriastradh	OUT_BATCH(load_indirect);
70503b705cfSriastradh
70603b705cfSriastradh	/* Static Indirect state buffer (dest buffer info) */
70703b705cfSriastradh	OUT_RELOC(pI915XvMC->sis_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
70803b705cfSriastradh			STATE_VALID | STATE_FORCE);
70903b705cfSriastradh	OUT_BATCH(16);	/* 4 * 3 + 2 + 3 - 1 */
71003b705cfSriastradh
71103b705cfSriastradh	/* Map state buffer (reference buffer info) */
71203b705cfSriastradh	OUT_RELOC(pI915XvMC->msb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
71303b705cfSriastradh			STATE_VALID | STATE_FORCE);
71403b705cfSriastradh	OUT_BATCH(23);	/* 3 * 8 - 1 */
71503b705cfSriastradh	ADVANCE_BATCH();
71603b705cfSriastradh}
71703b705cfSriastradh
71803b705cfSriastradhstatic void i915_mc_mpeg_set_origin(XvMCContext * context, XvMCMacroBlock * mb)
71903b705cfSriastradh{
72003b705cfSriastradh	struct i915_3dmpeg_set_origin set_origin;
72103b705cfSriastradh
72203b705cfSriastradh	/* 3DMPEG_SET_ORIGIN */
72303b705cfSriastradh	memset(&set_origin, 0, sizeof(set_origin));
72403b705cfSriastradh	set_origin.dw0.type = CMD_3D;
72503b705cfSriastradh	set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN;
72603b705cfSriastradh	set_origin.dw0.length = 0;
72703b705cfSriastradh	set_origin.dw1.h_origin = mb->x;
72803b705cfSriastradh	set_origin.dw1.v_origin = mb->y;
72903b705cfSriastradh
73003b705cfSriastradh	intelBatchbufferData(&set_origin, sizeof(set_origin), 0);
73103b705cfSriastradh}
73203b705cfSriastradh
73303b705cfSriastradhstatic void i915_mc_mpeg_macroblock_ipicture(XvMCContext * context,
73403b705cfSriastradh					     XvMCMacroBlock * mb)
73503b705cfSriastradh{
73603b705cfSriastradh	struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture;
73703b705cfSriastradh
73803b705cfSriastradh	/* 3DMPEG_MACROBLOCK_IPICTURE */
73903b705cfSriastradh	memset(&macroblock_ipicture, 0, sizeof(macroblock_ipicture));
74003b705cfSriastradh	macroblock_ipicture.dw0.type = CMD_3D;
74103b705cfSriastradh	macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE;
74203b705cfSriastradh	macroblock_ipicture.dw0.dct_type =
74303b705cfSriastradh	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
74403b705cfSriastradh
74503b705cfSriastradh	intelBatchbufferData(&macroblock_ipicture, sizeof(macroblock_ipicture),
74603b705cfSriastradh			     0);
74703b705cfSriastradh}
74803b705cfSriastradh
74903b705cfSriastradhstatic void i915_mc_mpeg_macroblock_1fbmv(XvMCContext * context,
75003b705cfSriastradh					  XvMCMacroBlock * mb)
75103b705cfSriastradh{
75203b705cfSriastradh	struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv;
75303b705cfSriastradh	vector_t mv0[2];
75403b705cfSriastradh
75503b705cfSriastradh	/* 3DMPEG_MACROBLOCK(1fbmv) */
75603b705cfSriastradh	memset(&macroblock_1fbmv, 0, sizeof(macroblock_1fbmv));
75703b705cfSriastradh	macroblock_1fbmv.header.dw0.type = CMD_3D;
75803b705cfSriastradh	macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
75903b705cfSriastradh	macroblock_1fbmv.header.dw0.length = 2;
76003b705cfSriastradh	macroblock_1fbmv.header.dw1.mb_intra = 0;	/* should be 0 */
76103b705cfSriastradh	macroblock_1fbmv.header.dw1.forward =
76203b705cfSriastradh	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
76303b705cfSriastradh	macroblock_1fbmv.header.dw1.backward =
76403b705cfSriastradh	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
76503b705cfSriastradh	macroblock_1fbmv.header.dw1.h263_4mv = 0;	/* should be 0 */
76603b705cfSriastradh	macroblock_1fbmv.header.dw1.dct_type =
76703b705cfSriastradh	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
76803b705cfSriastradh
76903b705cfSriastradh	if (!(mb->coded_block_pattern & 0x3f))
77003b705cfSriastradh		macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
77103b705cfSriastradh
77203b705cfSriastradh	macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
77303b705cfSriastradh	macroblock_1fbmv.header.dw1.vertical_field_select =
77403b705cfSriastradh	    (mb->motion_vertical_field_select & 0x0f);
77503b705cfSriastradh	macroblock_1fbmv.header.dw1.coded_block_pattern =
77603b705cfSriastradh	    mb->coded_block_pattern;
77703b705cfSriastradh	macroblock_1fbmv.header.dw1.skipped_macroblocks = 0;
77803b705cfSriastradh
77903b705cfSriastradh	mv0[0].component[0] = mb->PMV[0][0][0];
78003b705cfSriastradh	mv0[0].component[1] = mb->PMV[0][0][1];
78103b705cfSriastradh	mv0[1].component[0] = mb->PMV[0][1][0];
78203b705cfSriastradh	mv0[1].component[1] = mb->PMV[0][1][1];
78303b705cfSriastradh
78403b705cfSriastradh	macroblock_1fbmv.dw2 = mv0[0].v;
78503b705cfSriastradh	macroblock_1fbmv.dw3 = mv0[1].v;
78603b705cfSriastradh
78703b705cfSriastradh	intelBatchbufferData(&macroblock_1fbmv, sizeof(macroblock_1fbmv), 0);
78803b705cfSriastradh}
78903b705cfSriastradh
79003b705cfSriastradhstatic void i915_mc_mpeg_macroblock_2fbmv(XvMCContext * context,
79103b705cfSriastradh					  XvMCMacroBlock * mb, unsigned int ps)
79203b705cfSriastradh{
79303b705cfSriastradh	struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv;
79403b705cfSriastradh	vector_t mv0[2];
79503b705cfSriastradh	vector_t mv1[2];
79603b705cfSriastradh
79703b705cfSriastradh	/* 3DMPEG_MACROBLOCK(2fbmv) */
79803b705cfSriastradh	memset(&macroblock_2fbmv, 0, sizeof(macroblock_2fbmv));
79903b705cfSriastradh	macroblock_2fbmv.header.dw0.type = CMD_3D;
80003b705cfSriastradh	macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
80103b705cfSriastradh	macroblock_2fbmv.header.dw0.length = 4;
80203b705cfSriastradh	macroblock_2fbmv.header.dw1.mb_intra = 0;	/* should be 0 */
80303b705cfSriastradh	macroblock_2fbmv.header.dw1.forward =
80403b705cfSriastradh	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
80503b705cfSriastradh	macroblock_2fbmv.header.dw1.backward =
80603b705cfSriastradh	    ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
80703b705cfSriastradh	macroblock_2fbmv.header.dw1.h263_4mv = 0;	/* should be 0 */
80803b705cfSriastradh	macroblock_2fbmv.header.dw1.dct_type =
80903b705cfSriastradh	    (mb->dct_type == XVMC_DCT_TYPE_FIELD);
81003b705cfSriastradh
81103b705cfSriastradh	if (!(mb->coded_block_pattern & 0x3f))
81203b705cfSriastradh		macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
81303b705cfSriastradh
81403b705cfSriastradh	macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
81503b705cfSriastradh	macroblock_2fbmv.header.dw1.vertical_field_select =
81603b705cfSriastradh	    (mb->motion_vertical_field_select & 0x0f);
81703b705cfSriastradh	macroblock_2fbmv.header.dw1.coded_block_pattern =
81803b705cfSriastradh	    mb->coded_block_pattern;
81903b705cfSriastradh	macroblock_2fbmv.header.dw1.skipped_macroblocks = 0;
82003b705cfSriastradh
82103b705cfSriastradh	mv0[0].component[0] = mb->PMV[0][0][0];
82203b705cfSriastradh	mv0[0].component[1] = mb->PMV[0][0][1];
82303b705cfSriastradh	mv0[1].component[0] = mb->PMV[0][1][0];
82403b705cfSriastradh	mv0[1].component[1] = mb->PMV[0][1][1];
82503b705cfSriastradh	mv1[0].component[0] = mb->PMV[1][0][0];
82603b705cfSriastradh	mv1[0].component[1] = mb->PMV[1][0][1];
82703b705cfSriastradh	mv1[1].component[0] = mb->PMV[1][1][0];
82803b705cfSriastradh	mv1[1].component[1] = mb->PMV[1][1][1];
82903b705cfSriastradh
83003b705cfSriastradh	if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
83103b705cfSriastradh		if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) {
83203b705cfSriastradh			mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
83303b705cfSriastradh			mv0[1].component[1] = mb->PMV[0][1][1] >> 1;
83403b705cfSriastradh			mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
83503b705cfSriastradh			mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
83603b705cfSriastradh		} else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) {
83703b705cfSriastradh			mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
83803b705cfSriastradh			mv0[1].component[1] = mb->PMV[0][1][1] >> 1;	// MPEG2 MV[0][1] isn't used
83903b705cfSriastradh			mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
84003b705cfSriastradh			mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
84103b705cfSriastradh		}
84203b705cfSriastradh	}
84303b705cfSriastradh
84403b705cfSriastradh	macroblock_2fbmv.dw2 = mv0[0].v;
84503b705cfSriastradh	macroblock_2fbmv.dw3 = mv0[1].v;
84603b705cfSriastradh	macroblock_2fbmv.dw4 = mv1[0].v;
84703b705cfSriastradh	macroblock_2fbmv.dw5 = mv1[1].v;
84803b705cfSriastradh
84903b705cfSriastradh	intelBatchbufferData(&macroblock_2fbmv, sizeof(macroblock_2fbmv), 0);
85003b705cfSriastradh}
85103b705cfSriastradh
85203b705cfSriastradhstatic int i915_xvmc_alloc_one_time_buffers(i915XvMCContext *pI915XvMC)
85303b705cfSriastradh{
85403b705cfSriastradh	pI915XvMC->ssb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
85503b705cfSriastradh					       "ssb",
85603b705cfSriastradh					       GTT_PAGE_SIZE,
85703b705cfSriastradh					       GTT_PAGE_SIZE);
85803b705cfSriastradh	if (!pI915XvMC->ssb_bo)
85903b705cfSriastradh		return 0;
86003b705cfSriastradh
86103b705cfSriastradh	pI915XvMC->psp_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
86203b705cfSriastradh					       "psp",
86303b705cfSriastradh					       GTT_PAGE_SIZE,
86403b705cfSriastradh					       GTT_PAGE_SIZE);
86503b705cfSriastradh	if (!pI915XvMC->psp_bo)
86603b705cfSriastradh		return 0;
86703b705cfSriastradh
86803b705cfSriastradh	pI915XvMC->psc_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
86903b705cfSriastradh					       "psc",
87003b705cfSriastradh					       GTT_PAGE_SIZE,
87103b705cfSriastradh					       GTT_PAGE_SIZE);
87203b705cfSriastradh	if (!pI915XvMC->psc_bo)
87303b705cfSriastradh		return 0;
87403b705cfSriastradh
87503b705cfSriastradh	return 1;
87603b705cfSriastradh}
87703b705cfSriastradh
87803b705cfSriastradhstatic void i915_xvmc_free_one_time_buffers(i915XvMCContext *pI915XvMC)
87903b705cfSriastradh{
88003b705cfSriastradh	drm_intel_bo_unreference(pI915XvMC->ssb_bo);
88103b705cfSriastradh	drm_intel_bo_unreference(pI915XvMC->psp_bo);
88203b705cfSriastradh	drm_intel_bo_unreference(pI915XvMC->psc_bo);
88303b705cfSriastradh}
88403b705cfSriastradh
88503b705cfSriastradh/*
88603b705cfSriastradh * Function: i915_release_resource
88703b705cfSriastradh */
88803b705cfSriastradhstatic void i915_release_resource(Display * display, XvMCContext * context)
88903b705cfSriastradh{
89003b705cfSriastradh	i915XvMCContext *pI915XvMC;
89103b705cfSriastradh
89203b705cfSriastradh	if (!(pI915XvMC = context->privData))
89303b705cfSriastradh		return;
89403b705cfSriastradh
89503b705cfSriastradh	i915_xvmc_free_one_time_buffers(pI915XvMC);
89603b705cfSriastradh
89703b705cfSriastradh	free(pI915XvMC);
89803b705cfSriastradh	context->privData = NULL;
89903b705cfSriastradh}
90003b705cfSriastradh
90103b705cfSriastradhstatic Status i915_xvmc_mc_create_context(Display * display,
90203b705cfSriastradh					  XvMCContext * context, int priv_count,
90303b705cfSriastradh					  CARD32 * priv_data)
90403b705cfSriastradh{
90503b705cfSriastradh	i915XvMCContext *pI915XvMC = NULL;
90603b705cfSriastradh	struct intel_xvmc_hw_context *tmpComm = NULL;
90703b705cfSriastradh
90803b705cfSriastradh	if (priv_count != (sizeof(struct intel_xvmc_hw_context) >> 2)) {
90903b705cfSriastradh		XVMC_ERR
91003b705cfSriastradh		    ("_xvmc_create_context() returned incorrect data size!");
91103b705cfSriastradh		XVMC_INFO("\tExpected %d, got %d",
91203b705cfSriastradh			  (int)(sizeof(struct intel_xvmc_hw_context) >> 2),
91303b705cfSriastradh			  priv_count);
91403b705cfSriastradh		_xvmc_destroy_context(display, context);
91503b705cfSriastradh		XFree(priv_data);
91603b705cfSriastradh		context->privData = NULL;
91703b705cfSriastradh		return BadValue;
91803b705cfSriastradh	}
91903b705cfSriastradh
92003b705cfSriastradh	context->privData = (void *)calloc(1, sizeof(i915XvMCContext));
92103b705cfSriastradh	if (!context->privData) {
92203b705cfSriastradh		XVMC_ERR("Unable to allocate resources for XvMC context.");
92303b705cfSriastradh		return BadAlloc;
92403b705cfSriastradh	}
92503b705cfSriastradh	pI915XvMC = (i915XvMCContext *) context->privData;
92603b705cfSriastradh
92703b705cfSriastradh	tmpComm = (struct intel_xvmc_hw_context *) priv_data;
92803b705cfSriastradh	pI915XvMC->use_phys_addr = tmpComm->i915.use_phys_addr;
92903b705cfSriastradh	pI915XvMC->comm.surface_bo_size = SIZE_YUV420(context->width,
93003b705cfSriastradh						      context->height);
93103b705cfSriastradh
93203b705cfSriastradh	/* Must free the private data we were passed from X */
93303b705cfSriastradh	XFree(priv_data);
93403b705cfSriastradh	priv_data = NULL;
93503b705cfSriastradh
93603b705cfSriastradh	if (!i915_xvmc_alloc_one_time_buffers(pI915XvMC))
93703b705cfSriastradh		goto free_one_time_buffers;
93803b705cfSriastradh
93903b705cfSriastradh	/* Initialize private context values */
94003b705cfSriastradh	pI915XvMC->yStride = STRIDE(context->width);
94103b705cfSriastradh	pI915XvMC->uvStride = STRIDE(context->width >> 1);
94203b705cfSriastradh
94303b705cfSriastradh	/* pre-init state buffers */
94403b705cfSriastradh	i915_mc_one_time_context_init(context);
94503b705cfSriastradh
94603b705cfSriastradh	return Success;
94703b705cfSriastradh
94803b705cfSriastradhfree_one_time_buffers:
94903b705cfSriastradh	i915_xvmc_free_one_time_buffers(pI915XvMC);
95003b705cfSriastradh	free(pI915XvMC);
95103b705cfSriastradh	context->privData = NULL;
95203b705cfSriastradh	return BadAlloc;
95303b705cfSriastradh}
95403b705cfSriastradh
95503b705cfSriastradhstatic int i915_xvmc_mc_destroy_context(Display * display,
95603b705cfSriastradh					XvMCContext * context)
95703b705cfSriastradh{
95803b705cfSriastradh	i915XvMCContext *pI915XvMC;
95903b705cfSriastradh
96003b705cfSriastradh	if (!(pI915XvMC = context->privData))
96103b705cfSriastradh		return XvMCBadContext;
96203b705cfSriastradh
96303b705cfSriastradh	/* Pass Control to the X server to destroy the drm_context_t */
96403b705cfSriastradh	i915_release_resource(display, context);
96503b705cfSriastradh
96603b705cfSriastradh	return Success;
96703b705cfSriastradh}
96803b705cfSriastradh
96903b705cfSriastradhstatic int i915_xvmc_alloc_render_state_buffers(i915XvMCContext *pI915XvMC)
97003b705cfSriastradh{
97103b705cfSriastradh	pI915XvMC->sis_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
97203b705cfSriastradh					       "sis",
97303b705cfSriastradh					       GTT_PAGE_SIZE,
97403b705cfSriastradh					       GTT_PAGE_SIZE);
97503b705cfSriastradh	if (!pI915XvMC->sis_bo)
97603b705cfSriastradh		return 0;
97703b705cfSriastradh
97803b705cfSriastradh	pI915XvMC->msb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
97903b705cfSriastradh					       "msb",
98003b705cfSriastradh					       GTT_PAGE_SIZE,
98103b705cfSriastradh					       GTT_PAGE_SIZE);
98203b705cfSriastradh	if (!pI915XvMC->msb_bo)
98303b705cfSriastradh		return 0;
98403b705cfSriastradh
98503b705cfSriastradh	pI915XvMC->corrdata_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
98603b705cfSriastradh					       "corrdata",
98703b705cfSriastradh					       CORRDATA_SIZE,
98803b705cfSriastradh					       GTT_PAGE_SIZE);
98903b705cfSriastradh	if (!pI915XvMC->corrdata_bo)
99003b705cfSriastradh		return 0;
99103b705cfSriastradh
99203b705cfSriastradh	return 1;
99303b705cfSriastradh}
99403b705cfSriastradh
99503b705cfSriastradhstatic void i915_xvmc_free_render_state_buffers(i915XvMCContext *pI915XvMC)
99603b705cfSriastradh{
99703b705cfSriastradh	drm_intel_bo_unreference(pI915XvMC->sis_bo);
99803b705cfSriastradh	drm_intel_bo_unreference(pI915XvMC->msb_bo);
99903b705cfSriastradh	drm_intel_bo_unreference(pI915XvMC->corrdata_bo);
100003b705cfSriastradh}
100103b705cfSriastradh
100203b705cfSriastradhstatic int i915_xvmc_mc_render_surface(Display * display, XvMCContext * context,
100303b705cfSriastradh				       unsigned int picture_structure,
100403b705cfSriastradh				       XvMCSurface * target_surface,
100503b705cfSriastradh				       XvMCSurface * past_surface,
100603b705cfSriastradh				       XvMCSurface * future_surface,
100703b705cfSriastradh				       unsigned int flags,
100803b705cfSriastradh				       unsigned int num_macroblocks,
100903b705cfSriastradh				       unsigned int first_macroblock,
101003b705cfSriastradh				       XvMCMacroBlockArray * macroblock_array,
101103b705cfSriastradh				       XvMCBlockArray * blocks)
101203b705cfSriastradh{
101303b705cfSriastradh	int i;
101403b705cfSriastradh	int picture_coding_type = MPEG_I_PICTURE;
101503b705cfSriastradh	/* correction data buffer */
101603b705cfSriastradh	char *corrdata_ptr;
101703b705cfSriastradh	int corrdata_size = 0;
101803b705cfSriastradh
101903b705cfSriastradh	/* Block Pointer */
102003b705cfSriastradh	short *block_ptr;
102103b705cfSriastradh	/* Current Macroblock Pointer */
102203b705cfSriastradh	XvMCMacroBlock *mb;
102303b705cfSriastradh
102403b705cfSriastradh	intel_xvmc_context_ptr intel_ctx;
102503b705cfSriastradh
102603b705cfSriastradh	struct intel_xvmc_surface *privTarget = NULL;
102703b705cfSriastradh	struct intel_xvmc_surface *privFuture = NULL;
102803b705cfSriastradh	struct intel_xvmc_surface *privPast = NULL;
102903b705cfSriastradh	i915XvMCContext *pI915XvMC = NULL;
103003b705cfSriastradh
103103b705cfSriastradh	/* Check Parameters for validity */
103203b705cfSriastradh	if (!display || !context || !target_surface) {
103303b705cfSriastradh		XVMC_ERR("Invalid Display, Context or Target!");
103403b705cfSriastradh		return BadValue;
103503b705cfSriastradh	}
103603b705cfSriastradh
103703b705cfSriastradh	if (!num_macroblocks)
103803b705cfSriastradh		return Success;
103903b705cfSriastradh
104003b705cfSriastradh	if (!macroblock_array || !blocks) {
104103b705cfSriastradh		XVMC_ERR("Invalid block data!");
104203b705cfSriastradh		return BadValue;
104303b705cfSriastradh	}
104403b705cfSriastradh
104503b705cfSriastradh	if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
104603b705cfSriastradh		XVMC_ERR("Too many macroblocks requested for MB array size.");
104703b705cfSriastradh		return BadValue;
104803b705cfSriastradh	}
104903b705cfSriastradh
105003b705cfSriastradh	if (!(pI915XvMC = context->privData))
105103b705cfSriastradh		return XvMCBadContext;
105203b705cfSriastradh
105303b705cfSriastradh	if (!(privTarget = target_surface->privData))
105403b705cfSriastradh		return XvMCBadSurface;
105503b705cfSriastradh
105603b705cfSriastradh	if (!i915_xvmc_alloc_render_state_buffers(pI915XvMC))
105703b705cfSriastradh		return BadAlloc;
105803b705cfSriastradh
105903b705cfSriastradh	intel_ctx = context->privData;
106003b705cfSriastradh	if (!intel_ctx) {
106103b705cfSriastradh		XVMC_ERR("Can't find intel xvmc context\n");
106203b705cfSriastradh		return BadValue;
106303b705cfSriastradh	}
106403b705cfSriastradh
106503b705cfSriastradh	/* P Frame Test */
106603b705cfSriastradh	if (!past_surface) {
106703b705cfSriastradh		/* Just to avoid some ifs later. */
106803b705cfSriastradh		privPast = privTarget;
106903b705cfSriastradh	} else {
107003b705cfSriastradh		if (!(privPast = past_surface->privData)) {
107103b705cfSriastradh			return XvMCBadSurface;
107203b705cfSriastradh		}
107303b705cfSriastradh		picture_coding_type = MPEG_P_PICTURE;
107403b705cfSriastradh	}
107503b705cfSriastradh
107603b705cfSriastradh	/* B Frame Test */
107703b705cfSriastradh	if (!future_surface) {
107803b705cfSriastradh		privFuture = privPast;	// privTarget;
107903b705cfSriastradh	} else {
108003b705cfSriastradh		if (!past_surface) {
108103b705cfSriastradh			XVMC_ERR("No Past Surface!");
108203b705cfSriastradh			return BadValue;
108303b705cfSriastradh		}
108403b705cfSriastradh
108503b705cfSriastradh		if (!(privFuture = future_surface->privData)) {
108603b705cfSriastradh			XVMC_ERR("Invalid Future Surface!");
108703b705cfSriastradh			return XvMCBadSurface;
108803b705cfSriastradh		}
108903b705cfSriastradh
109003b705cfSriastradh		picture_coding_type = MPEG_B_PICTURE;
109103b705cfSriastradh	}
109203b705cfSriastradh
109303b705cfSriastradh	LOCK_HARDWARE(intel_ctx->hw_context);
109403b705cfSriastradh	drm_intel_gem_bo_map_gtt(pI915XvMC->corrdata_bo);
109503b705cfSriastradh	corrdata_ptr = pI915XvMC->corrdata_bo->virtual;
109603b705cfSriastradh	corrdata_size = 0;
109703b705cfSriastradh
109803b705cfSriastradh	for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
109903b705cfSriastradh	     i++) {
110003b705cfSriastradh		int bspm = 0;
110103b705cfSriastradh		mb = &macroblock_array->macro_blocks[i];
110203b705cfSriastradh		block_ptr = &(blocks->blocks[mb->index << 6]);
110303b705cfSriastradh
110403b705cfSriastradh		/* Lockup can happen if the coordinates are too far out of range */
110503b705cfSriastradh		if (mb->x > (target_surface->width >> 4)) {
110603b705cfSriastradh			mb->x = 0;
110703b705cfSriastradh			XVMC_INFO("reset x");
110803b705cfSriastradh		}
110903b705cfSriastradh
111003b705cfSriastradh		if (mb->y > (target_surface->height >> 4)) {
111103b705cfSriastradh			mb->y = 0;
111203b705cfSriastradh			XVMC_INFO("reset y");
111303b705cfSriastradh		}
111403b705cfSriastradh
111503b705cfSriastradh		/* Catch no pattern case */
111603b705cfSriastradh		if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) &&
111703b705cfSriastradh		    !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) &&
111803b705cfSriastradh		    mb->coded_block_pattern) {
111903b705cfSriastradh			mb->coded_block_pattern = 0;
112003b705cfSriastradh			XVMC_INFO("no coded blocks present!");
112103b705cfSriastradh		}
112203b705cfSriastradh
112303b705cfSriastradh		bspm = mb_bytes_420[mb->coded_block_pattern];
112403b705cfSriastradh
112503b705cfSriastradh		if (!bspm)
112603b705cfSriastradh			continue;
112703b705cfSriastradh
112803b705cfSriastradh		corrdata_size += bspm;
112903b705cfSriastradh
113003b705cfSriastradh		if (corrdata_size > CORRDATA_SIZE) {
113103b705cfSriastradh			XVMC_ERR("correction data buffer overflow.");
113203b705cfSriastradh			break;
113303b705cfSriastradh		}
113403b705cfSriastradh		memcpy(corrdata_ptr, block_ptr, bspm);
113503b705cfSriastradh		corrdata_ptr += bspm;
113603b705cfSriastradh	}
113703b705cfSriastradh
113803b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(pI915XvMC->corrdata_bo);
113903b705cfSriastradh
114003b705cfSriastradh	// i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB
114103b705cfSriastradh	// | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC);
114203b705cfSriastradh
114303b705cfSriastradh	i915_mc_one_time_state_emit(context);
114403b705cfSriastradh
114503b705cfSriastradh	i915_mc_static_indirect_state_set(context, target_surface,
114603b705cfSriastradh					  picture_structure, flags,
114703b705cfSriastradh					  picture_coding_type);
114803b705cfSriastradh	/* setup reference surfaces */
114903b705cfSriastradh	i915_mc_map_state_set(context, privPast, privFuture);
115003b705cfSriastradh
115103b705cfSriastradh	i915_mc_load_indirect_render_emit(context);
115203b705cfSriastradh
115303b705cfSriastradh	i915_mc_mpeg_set_origin(context,
115403b705cfSriastradh				&macroblock_array->macro_blocks
115503b705cfSriastradh				[first_macroblock]);
115603b705cfSriastradh
115703b705cfSriastradh	for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
115803b705cfSriastradh	     i++) {
115903b705cfSriastradh		mb = &macroblock_array->macro_blocks[i];
116003b705cfSriastradh
116103b705cfSriastradh		/* Intra Blocks */
116203b705cfSriastradh		if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
116303b705cfSriastradh			i915_mc_mpeg_macroblock_ipicture(context, mb);
116403b705cfSriastradh		} else if ((picture_structure & XVMC_FRAME_PICTURE) ==
116503b705cfSriastradh			   XVMC_FRAME_PICTURE) {
116603b705cfSriastradh			/* Frame Picture */
116703b705cfSriastradh			switch (mb->motion_type & 3) {
116803b705cfSriastradh			case XVMC_PREDICTION_FIELD:	/* Field Based */
116903b705cfSriastradh				i915_mc_mpeg_macroblock_2fbmv(context, mb,
117003b705cfSriastradh							      picture_structure);
117103b705cfSriastradh				break;
117203b705cfSriastradh
117303b705cfSriastradh			case XVMC_PREDICTION_FRAME:	/* Frame Based */
117403b705cfSriastradh				i915_mc_mpeg_macroblock_1fbmv(context, mb);
117503b705cfSriastradh				break;
117603b705cfSriastradh
117703b705cfSriastradh			case XVMC_PREDICTION_DUAL_PRIME:	/* Dual Prime */
117803b705cfSriastradh				i915_mc_mpeg_macroblock_2fbmv(context, mb,
117903b705cfSriastradh							      picture_structure);
118003b705cfSriastradh				break;
118103b705cfSriastradh
118203b705cfSriastradh			default:	/* No Motion Type */
118303b705cfSriastradh				XVMC_ERR
118403b705cfSriastradh				    ("Invalid Macroblock Parameters found.");
118503b705cfSriastradh				break;
118603b705cfSriastradh			}
118703b705cfSriastradh		} else {	/* Field Picture */
118803b705cfSriastradh			switch (mb->motion_type & 3) {
118903b705cfSriastradh			case XVMC_PREDICTION_FIELD:	/* Field Based */
119003b705cfSriastradh				i915_mc_mpeg_macroblock_1fbmv(context, mb);
119103b705cfSriastradh				break;
119203b705cfSriastradh
119303b705cfSriastradh			case XVMC_PREDICTION_16x8:	/* 16x8 MC */
119403b705cfSriastradh				i915_mc_mpeg_macroblock_2fbmv(context, mb,
119503b705cfSriastradh							      picture_structure);
119603b705cfSriastradh				break;
119703b705cfSriastradh
119803b705cfSriastradh			case XVMC_PREDICTION_DUAL_PRIME:	/* Dual Prime */
119903b705cfSriastradh				i915_mc_mpeg_macroblock_1fbmv(context, mb);
120003b705cfSriastradh				break;
120103b705cfSriastradh
120203b705cfSriastradh			default:	/* No Motion Type */
120303b705cfSriastradh				XVMC_ERR
120403b705cfSriastradh				    ("Invalid Macroblock Parameters found.");
120503b705cfSriastradh				break;
120603b705cfSriastradh			}
120703b705cfSriastradh		}
120803b705cfSriastradh	}
120903b705cfSriastradh
121042542f5fSchristos	intelFlushBatch();
121103b705cfSriastradh
121203b705cfSriastradh	i915_xvmc_free_render_state_buffers(pI915XvMC);
121303b705cfSriastradh
121403b705cfSriastradh	UNLOCK_HARDWARE(intel_ctx->hw_context);
121503b705cfSriastradh	return 0;
121603b705cfSriastradh}
121703b705cfSriastradh
121803b705cfSriastradhstruct _intel_xvmc_driver i915_xvmc_mc_driver = {
121903b705cfSriastradh	.type = XVMC_I915_MPEG2_MC,
122003b705cfSriastradh	.num_ctx = 0,
122103b705cfSriastradh	.ctx_list = NULL,
122203b705cfSriastradh	.create_context = i915_xvmc_mc_create_context,
122303b705cfSriastradh	.destroy_context = i915_xvmc_mc_destroy_context,
122403b705cfSriastradh	.render_surface = i915_xvmc_mc_render_surface,
122503b705cfSriastradh};
1226