summaryrefslogtreecommitdiff
path: root/xvmc/i915_xvmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'xvmc/i915_xvmc.c')
-rw-r--r--xvmc/i915_xvmc.c1225
1 files changed, 1225 insertions, 0 deletions
diff --git a/xvmc/i915_xvmc.c b/xvmc/i915_xvmc.c
new file mode 100644
index 00000000..fbd4555e
--- /dev/null
+++ b/xvmc/i915_xvmc.c
@@ -0,0 +1,1225 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Xiang Haihao <haihao.xiang@intel.com>
+ *
+ */
+
+#include <sys/ioctl.h>
+
+#include "i915_xvmc.h"
+#include "i915_structs.h"
+#include "i915_program.h"
+
+#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
+
+#define STRIDE(w) (ALIGN((w), 1024))
+#define SIZE_Y420(w, h) (h * STRIDE(w))
+#define SIZE_UV420(w, h) ((h >> 1) * STRIDE(w >> 1))
+#define SIZE_YUV420(w, h) (SIZE_Y420(w,h) + SIZE_UV420(w,h) * 2)
+#define UOFFSET(context) (SIZE_Y420(context->width, context->height))
+#define VOFFSET(context) (SIZE_Y420(context->width, context->height) + \
+ SIZE_UV420(context->width, context->height))
+
+typedef union {
+ int16_t component[2];
+ int32_t v;
+} vector_t;
+
+static void i915_inst_arith(unsigned int *inst,
+ unsigned int op,
+ unsigned int dest,
+ unsigned int mask,
+ unsigned int saturate,
+ unsigned int src0, unsigned int src1,
+ unsigned int src2)
+{
+ dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
+ *inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
+ inst++;
+ *inst = (A1_SRC0(src0) | A1_SRC1(src1));
+ inst++;
+ *inst = (A2_SRC1(src1) | A2_SRC2(src2));
+}
+
+static void i915_inst_decl(unsigned int *inst,
+ unsigned int type,
+ unsigned int nr, unsigned int d0_flags)
+{
+ unsigned int reg = UREG(type, nr);
+
+ *inst = (D0_DCL | D0_DEST(reg) | d0_flags);
+ inst++;
+ *inst = D1_MBZ;
+ inst++;
+ *inst = D2_MBZ;
+}
+
+static void i915_inst_texld(unsigned int *inst,
+ unsigned int op,
+ unsigned int dest,
+ unsigned int coord, unsigned int sampler)
+{
+ dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
+ *inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler));
+ inst++;
+ *inst = T1_ADDRESS_REG(coord);
+ inst++;
+ *inst = T2_MBZ;
+}
+
+static void i915_mc_one_time_context_init(XvMCContext * context)
+{
+ unsigned int dest, src0, src1, src2;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
+ int i;
+ struct i915_3dstate_sampler_state *sampler_state;
+ struct i915_3dstate_pixel_shader_program *pixel_shader_program;
+ struct i915_3dstate_pixel_shader_constants *pixel_shader_constants;
+
+ /* sampler static state */
+ drm_intel_gem_bo_map_gtt(pI915XvMC->ssb_bo);
+ sampler_state = pI915XvMC->ssb_bo->virtual;
+
+ memset(sampler_state, 0, sizeof(*sampler_state));
+ sampler_state->dw0.type = CMD_3D;
+ sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE;
+ sampler_state->dw0.length = 6;
+ sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1;
+
+ sampler_state->sampler0.ts0.reverse_gamma = 0;
+ sampler_state->sampler0.ts0.planar2packet = 0;
+ sampler_state->sampler0.ts0.color_conversion = 0;
+ sampler_state->sampler0.ts0.chromakey_index = 0;
+ sampler_state->sampler0.ts0.base_level = 0;
+ sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ sampler_state->sampler0.ts0.lod_bias = 0; /* 0.0 */
+ sampler_state->sampler0.ts0.shadow_enable = 0;
+ sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2;
+ sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS;
+ sampler_state->sampler0.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */
+ sampler_state->sampler0.ts1.kill_pixel = 0;
+ sampler_state->sampler0.ts1.keyed_texture_filter = 0;
+ sampler_state->sampler0.ts1.chromakey_enable = 0;
+ sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ sampler_state->sampler0.ts1.normalized_coor = 0;
+ sampler_state->sampler0.ts1.map_index = 0;
+ sampler_state->sampler0.ts1.east_deinterlacer = 0;
+ sampler_state->sampler0.ts2.default_color = 0;
+
+ sampler_state->sampler1.ts0.reverse_gamma = 0;
+ sampler_state->sampler1.ts0.planar2packet = 0;
+ sampler_state->sampler1.ts0.color_conversion = 0;
+ sampler_state->sampler1.ts0.chromakey_index = 0;
+ sampler_state->sampler1.ts0.base_level = 0;
+ sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ sampler_state->sampler1.ts0.lod_bias = 0; /* 0.0 */
+ sampler_state->sampler1.ts0.shadow_enable = 0;
+ sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2;
+ sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS;
+ sampler_state->sampler1.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */
+ sampler_state->sampler1.ts1.kill_pixel = 0;
+ sampler_state->sampler1.ts1.keyed_texture_filter = 0;
+ sampler_state->sampler1.ts1.chromakey_enable = 0;
+ sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ sampler_state->sampler1.ts1.normalized_coor = 0;
+ sampler_state->sampler1.ts1.map_index = 1;
+ sampler_state->sampler1.ts1.east_deinterlacer = 0;
+ sampler_state->sampler1.ts2.default_color = 0;
+
+ drm_intel_gem_bo_unmap_gtt(pI915XvMC->ssb_bo);
+
+ /* pixel shader static state */
+ drm_intel_gem_bo_map_gtt(pI915XvMC->psp_bo);
+ pixel_shader_program = pI915XvMC->psp_bo->virtual;
+
+ memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
+ pixel_shader_program->shader0.type = CMD_3D;
+ pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->shader0.retain = 1;
+ pixel_shader_program->shader0.length = 2; /* 1 inst */
+ i = 0;
+
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_CONST, 0);
+ src1 = 0;
+ src2 = 0;
+ i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV,
+ dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
+ src2);
+
+ pixel_shader_program->shader1.type = CMD_3D;
+ pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->shader1.retain = 1;
+ pixel_shader_program->shader1.length = 14; /* 5 inst */
+ i = 0;
+ /* dcl t0.xy */
+ i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0,
+ D0_CHANNEL_XY);
+ i += 3;
+ /* dcl t1.xy */
+ i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1,
+ D0_CHANNEL_XY);
+ /* dcl_2D s0 */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0,
+ D0_SAMPLE_TYPE_2D);
+ /* texld r0, t0, s0 */
+ i += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_T, 0); /* COORD */
+ src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */
+ i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0,
+ src1);
+ /* mov oC, r0 */
+ i += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_R, 0);
+ src1 = src2 = 0;
+ i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest,
+ A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
+ src2);
+
+ pixel_shader_program->shader2.type = CMD_3D;
+ pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->shader2.retain = 1;
+ pixel_shader_program->shader2.length = 14; /* 5 inst */
+ i = 0;
+ /* dcl t2.xy */
+ i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2,
+ D0_CHANNEL_XY);
+ /* dcl t3.xy */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3,
+ D0_CHANNEL_XY);
+ /* dcl_2D s1 */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1,
+ D0_SAMPLE_TYPE_2D);
+ /* texld r0, t2, s1 */
+ i += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_T, 2); /* COORD */
+ src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */
+ i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0,
+ src1);
+ /* mov oC, r0 */
+ i += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_R, 0);
+ src1 = src2 = 0;
+ i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest,
+ A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
+ src2);
+
+ /* Shader 3 */
+ pixel_shader_program->shader3.type = CMD_3D;
+ pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->shader3.retain = 1;
+ pixel_shader_program->shader3.length = 29; /* 10 inst */
+ i = 0;
+ /* dcl t0.xy */
+ i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0,
+ D0_CHANNEL_XY);
+ /* dcl t1.xy */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1,
+ D0_CHANNEL_XY);
+ /* dcl t2.xy */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2,
+ D0_CHANNEL_XY);
+ /* dcl t3.xy */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3,
+ D0_CHANNEL_XY);
+ /* dcl_2D s0 */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0,
+ D0_SAMPLE_TYPE_2D);
+ /* dcl_2D s1 */
+ i += 3;
+ i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1,
+ D0_SAMPLE_TYPE_2D);
+ /* texld r0, t0, s0 */
+ i += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_T, 0); /* COORD */
+ src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */
+ i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
+ src1);
+ /* texld r1, t2, s1 */
+ i += 3;
+ dest = UREG(REG_TYPE_R, 1);
+ src0 = UREG(REG_TYPE_T, 2); /* COORD */
+ src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */
+ i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0,
+ src1);
+ /* add r0, r0, r1 */
+ i += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_R, 0);
+ src1 = UREG(REG_TYPE_R, 1);
+ src2 = 0;
+ i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest,
+ A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */ , src0,
+ src1, src2);
+ /* mul oC, r0, c0 */
+ i += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_R, 0);
+ src1 = UREG(REG_TYPE_CONST, 0);
+ src2 = 0;
+ i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest,
+ A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1,
+ src2);
+
+ drm_intel_gem_bo_unmap_gtt(pI915XvMC->psp_bo);
+
+ /* pixel shader contant static state */
+ drm_intel_gem_bo_map_gtt(pI915XvMC->psc_bo);
+ pixel_shader_constants = pI915XvMC->psc_bo->virtual;
+
+ memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants));
+ pixel_shader_constants->dw0.type = CMD_3D;
+ pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS;
+ pixel_shader_constants->dw0.length = 4;
+ pixel_shader_constants->dw1.reg_mask = REG_CR0;
+ pixel_shader_constants->value.x = 0.5;
+ pixel_shader_constants->value.y = 0.5;
+ pixel_shader_constants->value.z = 0.5;
+ pixel_shader_constants->value.w = 0.5;
+
+ drm_intel_gem_bo_unmap_gtt(pI915XvMC->psc_bo);
+}
+
+static void i915_mc_one_time_state_emit(XvMCContext * context)
+{
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
+ uint32_t load_state_immediate_1, load_indirect, s3_dword, s6_dword;
+ int mem_select;
+ BATCH_LOCALS;
+
+ /* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */
+ BEGIN_BATCH(3 + 8);
+ load_state_immediate_1 = OP_3D_LOAD_STATE_IMMEDIATE_1;
+ load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S3;
+ load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S6;
+ load_state_immediate_1 |= 3 - 2; /* length */
+ OUT_BATCH(load_state_immediate_1);
+
+ s3_dword = S3_SET0_PCD | S3_SET1_PCD |
+ S3_SET2_PCD | S3_SET3_PCD |
+ S3_SET4_PCD | S3_SET5_PCD |
+ S3_SET6_PCD | S3_SET7_PCD;
+ OUT_BATCH(s3_dword);
+
+ s6_dword = S6_COLOR_BUFFER_WRITE | S6_DEPTH_TEST_ENABLE;
+ s6_dword |= 1 << S6_SRC_BLEND_FACTOR_SHIFT;
+ s6_dword |= 1 << S6_DST_BLEND_FACTOR_SHIFT;
+ OUT_BATCH(s6_dword);
+
+ /* 3DSTATE_LOAD_INDIRECT */
+ load_indirect = OP_3D_LOAD_INDIRECT;
+ load_indirect |= (BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC)
+ << BLOCK_MASK_SHIFT;
+ load_indirect |= 8 - 2; /* length */
+
+ if (pI915XvMC->use_phys_addr)
+ mem_select = 0; /* use physical address */
+ else {
+ load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
+ mem_select = 1; /* use gfx address */
+ }
+
+ OUT_BATCH(load_indirect);
+
+ /* Dynamic indirect state buffer */
+ OUT_BATCH(0); /* no dynamic indirect state */
+
+ /* Sample state buffer */
+ OUT_RELOC(pI915XvMC->ssb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
+ STATE_VALID | STATE_FORCE);
+ OUT_BATCH(7); /* 8 - 1 */
+
+ /* Pixel shader program buffer */
+ OUT_RELOC(pI915XvMC->psp_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
+ STATE_VALID | STATE_FORCE);
+ OUT_BATCH(66); /* 4 + 16 + 16 + 31 - 1 */
+
+ /* Pixel shader constant buffer */
+ OUT_RELOC(pI915XvMC->psc_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
+ STATE_VALID | STATE_FORCE);
+ OUT_BATCH(5); /* 6 - 1 */
+ ADVANCE_BATCH();
+}
+
+static void i915_mc_static_indirect_state_set(XvMCContext * context,
+ XvMCSurface * dest,
+ unsigned int picture_structure,
+ unsigned int flags,
+ unsigned int picture_coding_type)
+{
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
+ struct intel_xvmc_surface *intel_surf = dest->privData;
+ struct i915_mc_static_indirect_state_buffer *buffer_info;
+
+ drm_intel_gem_bo_map_gtt(pI915XvMC->sis_bo);
+ buffer_info = pI915XvMC->sis_bo->virtual;
+
+ memset(buffer_info, 0, sizeof(*buffer_info));
+
+ /* dest Y */
+ buffer_info->dest_y.dw0.type = CMD_3D;
+ buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dest_y.dw0.length = 1;
+ buffer_info->dest_y.dw1.aux_id = 0;
+ buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK;
+ buffer_info->dest_y.dw1.fence_regs = 0; /* disabled *//* FIXME: tiled y for performance */
+ buffer_info->dest_y.dw1.tiled_surface = 0; /* linear */
+ buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dest_y.dw1.pitch = (pI915XvMC->yStride >> 2); /* in DWords */
+ buffer_info->dest_y.dw2.base_address = intel_surf->bo->offset >> 2; /* starting DWORD address */
+ drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
+ offsetof(typeof(*buffer_info),dest_y.dw2),
+ intel_surf->bo, 0,
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER);
+
+ /* dest U */
+ buffer_info->dest_u.dw0.type = CMD_3D;
+ buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dest_u.dw0.length = 1;
+ buffer_info->dest_u.dw1.aux_id = 0;
+ buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX;
+ buffer_info->dest_u.dw1.fence_regs = 0;
+ buffer_info->dest_u.dw1.tiled_surface = 0;
+ buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dest_u.dw1.pitch = (pI915XvMC->uvStride >> 2); /* in DWords */
+ buffer_info->dest_u.dw2.base_address =
+ (intel_surf->bo->offset + UOFFSET(context)) >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
+ offsetof(typeof(*buffer_info),dest_u.dw2),
+ intel_surf->bo, UOFFSET(context),
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER);
+
+ /* dest V */
+ buffer_info->dest_v.dw0.type = CMD_3D;
+ buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dest_v.dw0.length = 1;
+ buffer_info->dest_v.dw1.aux_id = 1;
+ buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX;
+ buffer_info->dest_v.dw1.fence_regs = 0;
+ buffer_info->dest_v.dw1.tiled_surface = 0;
+ buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dest_v.dw1.pitch = (pI915XvMC->uvStride >> 2); /* in Dwords */
+ buffer_info->dest_v.dw2.base_address =
+ (intel_surf->bo->offset + VOFFSET(context)) >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
+ offsetof(typeof(*buffer_info),dest_v.dw2),
+ intel_surf->bo, VOFFSET(context),
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER);
+
+ /* Dest buffer parameters */
+ buffer_info->dest_buf.dw0.type = CMD_3D;
+ buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES;
+ buffer_info->dest_buf.dw0.length = 0;
+ buffer_info->dest_buf.dw1.dest_v_bias = 8; /* 0.5 */
+ buffer_info->dest_buf.dw1.dest_h_bias = 8; /* 0.5 */
+ buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT;
+ buffer_info->dest_buf.dw1.v_ls = 0; /* fill later */
+ buffer_info->dest_buf.dw1.v_ls_offset = 0; /* fill later */
+ if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
+ ;
+ } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) {
+ buffer_info->dest_buf.dw1.v_ls = 1;
+ } else if ((picture_structure & XVMC_FRAME_PICTURE) ==
+ XVMC_BOTTOM_FIELD) {
+ buffer_info->dest_buf.dw1.v_ls = 1;
+ buffer_info->dest_buf.dw1.v_ls_offset = 1;
+ }
+
+ /* MPEG buffer parameters */
+ buffer_info->dest_buf_mpeg.dw0.type = CMD_3D;
+ buffer_info->dest_buf_mpeg.dw0.opcode =
+ OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG;
+ buffer_info->dest_buf_mpeg.dw0.length = 1;
+ buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC;
+ buffer_info->dest_buf_mpeg.dw1.rcontrol = 0; /* for MPEG-1/MPEG-2 */
+ buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0; /* for MPEG-1/MPEG-2/MPEG-4 */
+ buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1;
+ buffer_info->dest_buf_mpeg.dw1.intra8 = 0; /* 16-bit formatted correction data */
+ buffer_info->dest_buf_mpeg.dw1.tff = 1; /* fill later */
+
+ buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V;
+ buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H;
+
+ if (picture_structure & XVMC_FRAME_PICTURE) {
+ ;
+ } else if (picture_structure & XVMC_TOP_FIELD) {
+ if (flags & XVMC_SECOND_FIELD)
+ buffer_info->dest_buf_mpeg.dw1.tff = 0;
+ else
+ buffer_info->dest_buf_mpeg.dw1.tff = 1;
+ } else if (picture_structure & XVMC_BOTTOM_FIELD) {
+ if (flags & XVMC_SECOND_FIELD)
+ buffer_info->dest_buf_mpeg.dw1.tff = 1;
+ else
+ buffer_info->dest_buf_mpeg.dw1.tff = 0;
+ }
+
+ buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4); /* in macroblocks */
+ buffer_info->dest_buf_mpeg.dw2.picture_coding_type =
+ picture_coding_type;
+
+ buffer_info->corr.dw0.type = CMD_3D;
+ buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->corr.dw0.length = 1;
+ buffer_info->corr.dw1.aux_id = 0;
+ buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR;
+ buffer_info->corr.dw1.aux_id = 0;
+ buffer_info->corr.dw1.fence_regs = 0;
+ buffer_info->corr.dw1.tiled_surface = 0;
+ buffer_info->corr.dw1.walk = 0;
+ buffer_info->corr.dw1.pitch = 0;
+ buffer_info->corr.dw2.base_address = pI915XvMC->corrdata_bo->offset >> 2; /* starting DWORD address */
+ drm_intel_bo_emit_reloc(pI915XvMC->sis_bo,
+ offsetof(typeof(*buffer_info),corr.dw2),
+ pI915XvMC->corrdata_bo, 0,
+ I915_GEM_DOMAIN_RENDER, 0);
+
+ drm_intel_gem_bo_unmap_gtt(pI915XvMC->sis_bo);
+}
+
+static void i915_mc_map_state_set(XvMCContext * context,
+ struct intel_xvmc_surface * privPast,
+ struct intel_xvmc_surface * privFuture)
+{
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
+ struct i915_mc_map_state *map_state;
+ unsigned int w = context->width;
+ unsigned int h = context->height;
+
+ drm_intel_gem_bo_map_gtt(pI915XvMC->msb_bo);
+ map_state = pI915XvMC->msb_bo->virtual;
+
+ memset(map_state, 0, sizeof(*map_state));
+
+ /* 3DSATE_MAP_STATE: Y */
+ map_state->y_map.dw0.type = CMD_3D;
+ map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->y_map.dw0.retain = 1;
+ map_state->y_map.dw0.length = 6;
+ map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
+
+ /* Y Forward (Past) */
+ map_state->y_forward.tm0.v_ls_offset = 0;
+ map_state->y_forward.tm0.v_ls = 0;
+ map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR;
+ map_state->y_forward.tm1.tiled_surface = 0;
+ map_state->y_forward.tm1.utilize_fence_regs = 0;
+ map_state->y_forward.tm1.texel_fmt = 0; /* 8bit */
+ map_state->y_forward.tm1.surface_fmt = 1; /* 8bit */
+ map_state->y_forward.tm1.width = w - 1;
+ map_state->y_forward.tm1.height = h - 1;
+ map_state->y_forward.tm2.depth = 0;
+ map_state->y_forward.tm2.max_lod = 0;
+ map_state->y_forward.tm2.cube_face = 0;
+ map_state->y_forward.tm0.base_address = privPast->bo->offset >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
+ offsetof(typeof(*map_state),y_forward.tm0),
+ privPast->bo, 0,
+ I915_GEM_DOMAIN_SAMPLER, 0);
+ map_state->y_forward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1; /* in DWords - 1 */
+
+ /* Y Backward (Future) */
+ map_state->y_backward.tm0.v_ls_offset = 0;
+ map_state->y_backward.tm0.v_ls = 0;
+ map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR;
+ map_state->y_backward.tm1.tiled_surface = 0;
+ map_state->y_backward.tm1.utilize_fence_regs = 0;
+ map_state->y_backward.tm1.texel_fmt = 0; /* 8bit */
+ map_state->y_backward.tm1.surface_fmt = 1; /* 8bit */
+ map_state->y_backward.tm1.width = w - 1;
+ map_state->y_backward.tm1.height = h - 1;
+ map_state->y_backward.tm2.depth = 0;
+ map_state->y_backward.tm2.max_lod = 0;
+ map_state->y_backward.tm2.cube_face = 0;
+ map_state->y_backward.tm0.base_address = privFuture->bo->offset >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
+ offsetof(typeof(*map_state),y_backward.tm0),
+ privFuture->bo, 0,
+ I915_GEM_DOMAIN_SAMPLER, 0);
+ map_state->y_backward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1;
+
+ /* 3DSATE_MAP_STATE: U */
+ map_state->u_map.dw0.type = CMD_3D;
+ map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->u_map.dw0.retain = 1;
+ map_state->u_map.dw0.length = 6;
+ map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
+
+ /* U Forward */
+ map_state->u_forward.tm0.v_ls_offset = 0;
+ map_state->u_forward.tm0.v_ls = 0;
+ map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR;
+ map_state->u_forward.tm1.tiled_surface = 0;
+ map_state->u_forward.tm1.utilize_fence_regs = 0;
+ map_state->u_forward.tm1.texel_fmt = 0; /* 8bit */
+ map_state->u_forward.tm1.surface_fmt = 1; /* 8bit */
+ map_state->u_forward.tm1.width = (w >> 1) - 1;
+ map_state->u_forward.tm1.height = (h >> 1) - 1;
+ map_state->u_forward.tm2.depth = 0;
+ map_state->u_forward.tm2.max_lod = 0;
+ map_state->u_forward.tm2.cube_face = 0;
+ map_state->u_forward.tm0.base_address =
+ (privPast->bo->offset + UOFFSET(context)) >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
+ offsetof(typeof(*map_state),u_forward.tm0),
+ privPast->bo, UOFFSET(context),
+ I915_GEM_DOMAIN_SAMPLER, 0);
+ map_state->u_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; /* in DWords - 1 */
+
+ /* U Backward */
+ map_state->u_backward.tm0.v_ls_offset = 0;
+ map_state->u_backward.tm0.v_ls = 0;
+ map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR;
+ map_state->u_backward.tm1.tiled_surface = 0;
+ map_state->u_backward.tm1.utilize_fence_regs = 0;
+ map_state->u_backward.tm1.texel_fmt = 0;
+ map_state->u_backward.tm1.surface_fmt = 1;
+ map_state->u_backward.tm1.width = (w >> 1) - 1;
+ map_state->u_backward.tm1.height = (h >> 1) - 1;
+ map_state->u_backward.tm2.depth = 0;
+ map_state->u_backward.tm2.max_lod = 0;
+ map_state->u_backward.tm2.cube_face = 0;
+ map_state->u_backward.tm0.base_address =
+ (privFuture->bo->offset + UOFFSET(context)) >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
+ offsetof(typeof(*map_state),u_backward.tm0),
+ privFuture->bo, UOFFSET(context),
+ I915_GEM_DOMAIN_SAMPLER, 0);
+ map_state->u_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
+
+ /* 3DSATE_MAP_STATE: V */
+ map_state->v_map.dw0.type = CMD_3D;
+ map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->v_map.dw0.retain = 1;
+ map_state->v_map.dw0.length = 6;
+ map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1;
+
+ /* V Forward */
+ map_state->v_forward.tm0.v_ls_offset = 0;
+ map_state->v_forward.tm0.v_ls = 0;
+ map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR;
+ map_state->v_forward.tm1.tiled_surface = 0;
+ map_state->v_forward.tm1.utilize_fence_regs = 0;
+ map_state->v_forward.tm1.texel_fmt = 0;
+ map_state->v_forward.tm1.surface_fmt = 1;
+ map_state->v_forward.tm1.width = (w >> 1) - 1;
+ map_state->v_forward.tm1.height = (h >> 1) - 1;
+ map_state->v_forward.tm2.depth = 0;
+ map_state->v_forward.tm2.max_lod = 0;
+ map_state->v_forward.tm2.cube_face = 0;
+ map_state->v_forward.tm0.base_address =
+ (privPast->bo->offset + VOFFSET(context)) >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
+ offsetof(typeof(*map_state),v_forward.tm0),
+ privPast->bo, VOFFSET(context),
+ I915_GEM_DOMAIN_SAMPLER, 0);
+ map_state->v_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; /* in DWords - 1 */
+
+ /* V Backward */
+ map_state->v_backward.tm0.v_ls_offset = 0;
+ map_state->v_backward.tm0.v_ls = 0;
+ map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR;
+ map_state->v_backward.tm1.tiled_surface = 0;
+ map_state->v_backward.tm1.utilize_fence_regs = 0;
+ map_state->v_backward.tm1.texel_fmt = 0;
+ map_state->v_backward.tm1.surface_fmt = 1;
+ map_state->v_backward.tm1.width = (w >> 1) - 1;
+ map_state->v_backward.tm1.height = (h >> 1) - 1;
+ map_state->v_backward.tm2.depth = 0;
+ map_state->v_backward.tm2.max_lod = 0;
+ map_state->v_backward.tm2.cube_face = 0;
+ map_state->v_backward.tm0.base_address =
+ (privFuture->bo->offset + VOFFSET(context)) >> 2;
+ drm_intel_bo_emit_reloc(pI915XvMC->msb_bo,
+ offsetof(typeof(*map_state),v_backward.tm0),
+ privFuture->bo, VOFFSET(context),
+ I915_GEM_DOMAIN_SAMPLER, 0);
+ map_state->v_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1;
+
+ drm_intel_gem_bo_unmap_gtt(pI915XvMC->msb_bo);
+}
+
+static void i915_mc_load_indirect_render_emit(XvMCContext * context)
+{
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData;
+ int mem_select;
+ uint32_t load_indirect;
+ BATCH_LOCALS;
+
+ BEGIN_BATCH(5);
+ load_indirect = OP_3D_LOAD_INDIRECT;
+ load_indirect |= (BLOCK_SIS | BLOCK_MSB) << BLOCK_MASK_SHIFT;
+ load_indirect |= 5 - 2; /* length */
+
+ if (pI915XvMC->use_phys_addr)
+ mem_select = 0; /* use physical address */
+ else {
+ load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR;
+ mem_select = 1; /* use gfx address */
+ }
+ OUT_BATCH(load_indirect);
+
+ /* Static Indirect state buffer (dest buffer info) */
+ OUT_RELOC(pI915XvMC->sis_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
+ STATE_VALID | STATE_FORCE);
+ OUT_BATCH(16); /* 4 * 3 + 2 + 3 - 1 */
+
+ /* Map state buffer (reference buffer info) */
+ OUT_RELOC(pI915XvMC->msb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
+ STATE_VALID | STATE_FORCE);
+ OUT_BATCH(23); /* 3 * 8 - 1 */
+ ADVANCE_BATCH();
+}
+
+static void i915_mc_mpeg_set_origin(XvMCContext * context, XvMCMacroBlock * mb)
+{
+ struct i915_3dmpeg_set_origin set_origin;
+
+ /* 3DMPEG_SET_ORIGIN */
+ memset(&set_origin, 0, sizeof(set_origin));
+ set_origin.dw0.type = CMD_3D;
+ set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN;
+ set_origin.dw0.length = 0;
+ set_origin.dw1.h_origin = mb->x;
+ set_origin.dw1.v_origin = mb->y;
+
+ intelBatchbufferData(&set_origin, sizeof(set_origin), 0);
+}
+
+static void i915_mc_mpeg_macroblock_ipicture(XvMCContext * context,
+ XvMCMacroBlock * mb)
+{
+ struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture;
+
+ /* 3DMPEG_MACROBLOCK_IPICTURE */
+ memset(&macroblock_ipicture, 0, sizeof(macroblock_ipicture));
+ macroblock_ipicture.dw0.type = CMD_3D;
+ macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE;
+ macroblock_ipicture.dw0.dct_type =
+ (mb->dct_type == XVMC_DCT_TYPE_FIELD);
+
+ intelBatchbufferData(&macroblock_ipicture, sizeof(macroblock_ipicture),
+ 0);
+}
+
+static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext * context,
+ XvMCMacroBlock * mb)
+{
+ struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv;
+ vector_t mv0[2];
+
+ /* 3DMPEG_MACROBLOCK(1fbmv) */
+ memset(&macroblock_1fbmv, 0, sizeof(macroblock_1fbmv));
+ macroblock_1fbmv.header.dw0.type = CMD_3D;
+ macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
+ macroblock_1fbmv.header.dw0.length = 2;
+ macroblock_1fbmv.header.dw1.mb_intra = 0; /* should be 0 */
+ macroblock_1fbmv.header.dw1.forward =
+ ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
+ macroblock_1fbmv.header.dw1.backward =
+ ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
+ macroblock_1fbmv.header.dw1.h263_4mv = 0; /* should be 0 */
+ macroblock_1fbmv.header.dw1.dct_type =
+ (mb->dct_type == XVMC_DCT_TYPE_FIELD);
+
+ if (!(mb->coded_block_pattern & 0x3f))
+ macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
+
+ macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
+ macroblock_1fbmv.header.dw1.vertical_field_select =
+ (mb->motion_vertical_field_select & 0x0f);
+ macroblock_1fbmv.header.dw1.coded_block_pattern =
+ mb->coded_block_pattern;
+ macroblock_1fbmv.header.dw1.skipped_macroblocks = 0;
+
+ mv0[0].component[0] = mb->PMV[0][0][0];
+ mv0[0].component[1] = mb->PMV[0][0][1];
+ mv0[1].component[0] = mb->PMV[0][1][0];
+ mv0[1].component[1] = mb->PMV[0][1][1];
+
+ macroblock_1fbmv.dw2 = mv0[0].v;
+ macroblock_1fbmv.dw3 = mv0[1].v;
+
+ intelBatchbufferData(&macroblock_1fbmv, sizeof(macroblock_1fbmv), 0);
+}
+
+static void i915_mc_mpeg_macroblock_2fbmv(XvMCContext * context,
+ XvMCMacroBlock * mb, unsigned int ps)
+{
+ struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv;
+ vector_t mv0[2];
+ vector_t mv1[2];
+
+ /* 3DMPEG_MACROBLOCK(2fbmv) */
+ memset(&macroblock_2fbmv, 0, sizeof(macroblock_2fbmv));
+ macroblock_2fbmv.header.dw0.type = CMD_3D;
+ macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
+ macroblock_2fbmv.header.dw0.length = 4;
+ macroblock_2fbmv.header.dw1.mb_intra = 0; /* should be 0 */
+ macroblock_2fbmv.header.dw1.forward =
+ ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0);
+ macroblock_2fbmv.header.dw1.backward =
+ ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0);
+ macroblock_2fbmv.header.dw1.h263_4mv = 0; /* should be 0 */
+ macroblock_2fbmv.header.dw1.dct_type =
+ (mb->dct_type == XVMC_DCT_TYPE_FIELD);
+
+ if (!(mb->coded_block_pattern & 0x3f))
+ macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
+
+ macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03);
+ macroblock_2fbmv.header.dw1.vertical_field_select =
+ (mb->motion_vertical_field_select & 0x0f);
+ macroblock_2fbmv.header.dw1.coded_block_pattern =
+ mb->coded_block_pattern;
+ macroblock_2fbmv.header.dw1.skipped_macroblocks = 0;
+
+ mv0[0].component[0] = mb->PMV[0][0][0];
+ mv0[0].component[1] = mb->PMV[0][0][1];
+ mv0[1].component[0] = mb->PMV[0][1][0];
+ mv0[1].component[1] = mb->PMV[0][1][1];
+ mv1[0].component[0] = mb->PMV[1][0][0];
+ mv1[0].component[1] = mb->PMV[1][0][1];
+ mv1[1].component[0] = mb->PMV[1][1][0];
+ mv1[1].component[1] = mb->PMV[1][1][1];
+
+ if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
+ if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) {
+ mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
+ mv0[1].component[1] = mb->PMV[0][1][1] >> 1;
+ mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
+ mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
+ } else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) {
+ mv0[0].component[1] = mb->PMV[0][0][1] >> 1;
+ mv0[1].component[1] = mb->PMV[0][1][1] >> 1; // MPEG2 MV[0][1] isn't used
+ mv1[0].component[1] = mb->PMV[1][0][1] >> 1;
+ mv1[1].component[1] = mb->PMV[1][1][1] >> 1;
+ }
+ }
+
+ macroblock_2fbmv.dw2 = mv0[0].v;
+ macroblock_2fbmv.dw3 = mv0[1].v;
+ macroblock_2fbmv.dw4 = mv1[0].v;
+ macroblock_2fbmv.dw5 = mv1[1].v;
+
+ intelBatchbufferData(&macroblock_2fbmv, sizeof(macroblock_2fbmv), 0);
+}
+
+static int i915_xvmc_alloc_one_time_buffers(i915XvMCContext *pI915XvMC)
+{
+ pI915XvMC->ssb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
+ "ssb",
+ GTT_PAGE_SIZE,
+ GTT_PAGE_SIZE);
+ if (!pI915XvMC->ssb_bo)
+ return 0;
+
+ pI915XvMC->psp_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
+ "psp",
+ GTT_PAGE_SIZE,
+ GTT_PAGE_SIZE);
+ if (!pI915XvMC->psp_bo)
+ return 0;
+
+ pI915XvMC->psc_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
+ "psc",
+ GTT_PAGE_SIZE,
+ GTT_PAGE_SIZE);
+ if (!pI915XvMC->psc_bo)
+ return 0;
+
+ return 1;
+}
+
+static void i915_xvmc_free_one_time_buffers(i915XvMCContext *pI915XvMC)
+{
+ drm_intel_bo_unreference(pI915XvMC->ssb_bo);
+ drm_intel_bo_unreference(pI915XvMC->psp_bo);
+ drm_intel_bo_unreference(pI915XvMC->psc_bo);
+}
+
+/*
+ * Function: i915_release_resource
+ */
+static void i915_release_resource(Display * display, XvMCContext * context)
+{
+ i915XvMCContext *pI915XvMC;
+
+ if (!(pI915XvMC = context->privData))
+ return;
+
+ i915_xvmc_free_one_time_buffers(pI915XvMC);
+
+ free(pI915XvMC);
+ context->privData = NULL;
+}
+
+static Status i915_xvmc_mc_create_context(Display * display,
+ XvMCContext * context, int priv_count,
+ CARD32 * priv_data)
+{
+ i915XvMCContext *pI915XvMC = NULL;
+ struct intel_xvmc_hw_context *tmpComm = NULL;
+
+ if (priv_count != (sizeof(struct intel_xvmc_hw_context) >> 2)) {
+ XVMC_ERR
+ ("_xvmc_create_context() returned incorrect data size!");
+ XVMC_INFO("\tExpected %d, got %d",
+ (int)(sizeof(struct intel_xvmc_hw_context) >> 2),
+ priv_count);
+ _xvmc_destroy_context(display, context);
+ XFree(priv_data);
+ context->privData = NULL;
+ return BadValue;
+ }
+
+ context->privData = (void *)calloc(1, sizeof(i915XvMCContext));
+ if (!context->privData) {
+ XVMC_ERR("Unable to allocate resources for XvMC context.");
+ return BadAlloc;
+ }
+ pI915XvMC = (i915XvMCContext *) context->privData;
+
+ tmpComm = (struct intel_xvmc_hw_context *) priv_data;
+ pI915XvMC->use_phys_addr = tmpComm->i915.use_phys_addr;
+ pI915XvMC->comm.surface_bo_size = SIZE_YUV420(context->width,
+ context->height);
+
+ /* Must free the private data we were passed from X */
+ XFree(priv_data);
+ priv_data = NULL;
+
+ if (!i915_xvmc_alloc_one_time_buffers(pI915XvMC))
+ goto free_one_time_buffers;
+
+ /* Initialize private context values */
+ pI915XvMC->yStride = STRIDE(context->width);
+ pI915XvMC->uvStride = STRIDE(context->width >> 1);
+
+ /* pre-init state buffers */
+ i915_mc_one_time_context_init(context);
+
+ return Success;
+
+free_one_time_buffers:
+ i915_xvmc_free_one_time_buffers(pI915XvMC);
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAlloc;
+}
+
+static int i915_xvmc_mc_destroy_context(Display * display,
+ XvMCContext * context)
+{
+ i915XvMCContext *pI915XvMC;
+
+ if (!(pI915XvMC = context->privData))
+ return XvMCBadContext;
+
+ /* Pass Control to the X server to destroy the drm_context_t */
+ i915_release_resource(display, context);
+
+ return Success;
+}
+
+static int i915_xvmc_alloc_render_state_buffers(i915XvMCContext *pI915XvMC)
+{
+ pI915XvMC->sis_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
+ "sis",
+ GTT_PAGE_SIZE,
+ GTT_PAGE_SIZE);
+ if (!pI915XvMC->sis_bo)
+ return 0;
+
+ pI915XvMC->msb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
+ "msb",
+ GTT_PAGE_SIZE,
+ GTT_PAGE_SIZE);
+ if (!pI915XvMC->msb_bo)
+ return 0;
+
+ pI915XvMC->corrdata_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
+ "corrdata",
+ CORRDATA_SIZE,
+ GTT_PAGE_SIZE);
+ if (!pI915XvMC->corrdata_bo)
+ return 0;
+
+ return 1;
+}
+
+static void i915_xvmc_free_render_state_buffers(i915XvMCContext *pI915XvMC)
+{
+ drm_intel_bo_unreference(pI915XvMC->sis_bo);
+ drm_intel_bo_unreference(pI915XvMC->msb_bo);
+ drm_intel_bo_unreference(pI915XvMC->corrdata_bo);
+}
+
+static int i915_xvmc_mc_render_surface(Display * display, XvMCContext * context,
+ unsigned int picture_structure,
+ XvMCSurface * target_surface,
+ XvMCSurface * past_surface,
+ XvMCSurface * future_surface,
+ unsigned int flags,
+ unsigned int num_macroblocks,
+ unsigned int first_macroblock,
+ XvMCMacroBlockArray * macroblock_array,
+ XvMCBlockArray * blocks)
+{
+ int i;
+ int picture_coding_type = MPEG_I_PICTURE;
+ /* correction data buffer */
+ char *corrdata_ptr;
+ int corrdata_size = 0;
+
+ /* Block Pointer */
+ short *block_ptr;
+ /* Current Macroblock Pointer */
+ XvMCMacroBlock *mb;
+
+ intel_xvmc_context_ptr intel_ctx;
+
+ struct intel_xvmc_surface *privTarget = NULL;
+ struct intel_xvmc_surface *privFuture = NULL;
+ struct intel_xvmc_surface *privPast = NULL;
+ i915XvMCContext *pI915XvMC = NULL;
+
+ /* Check Parameters for validity */
+ if (!display || !context || !target_surface) {
+ XVMC_ERR("Invalid Display, Context or Target!");
+ return BadValue;
+ }
+
+ if (!num_macroblocks)
+ return Success;
+
+ if (!macroblock_array || !blocks) {
+ XVMC_ERR("Invalid block data!");
+ return BadValue;
+ }
+
+ if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
+ XVMC_ERR("Too many macroblocks requested for MB array size.");
+ return BadValue;
+ }
+
+ if (!(pI915XvMC = context->privData))
+ return XvMCBadContext;
+
+ if (!(privTarget = target_surface->privData))
+ return XvMCBadSurface;
+
+ if (!i915_xvmc_alloc_render_state_buffers(pI915XvMC))
+ return BadAlloc;
+
+ intel_ctx = context->privData;
+ if (!intel_ctx) {
+ XVMC_ERR("Can't find intel xvmc context\n");
+ return BadValue;
+ }
+
+ /* P Frame Test */
+ if (!past_surface) {
+ /* Just to avoid some ifs later. */
+ privPast = privTarget;
+ } else {
+ if (!(privPast = past_surface->privData)) {
+ return XvMCBadSurface;
+ }
+ picture_coding_type = MPEG_P_PICTURE;
+ }
+
+ /* B Frame Test */
+ if (!future_surface) {
+ privFuture = privPast; // privTarget;
+ } else {
+ if (!past_surface) {
+ XVMC_ERR("No Past Surface!");
+ return BadValue;
+ }
+
+ if (!(privFuture = future_surface->privData)) {
+ XVMC_ERR("Invalid Future Surface!");
+ return XvMCBadSurface;
+ }
+
+ picture_coding_type = MPEG_B_PICTURE;
+ }
+
+ LOCK_HARDWARE(intel_ctx->hw_context);
+ drm_intel_gem_bo_map_gtt(pI915XvMC->corrdata_bo);
+ corrdata_ptr = pI915XvMC->corrdata_bo->virtual;
+ corrdata_size = 0;
+
+ for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
+ i++) {
+ int bspm = 0;
+ mb = &macroblock_array->macro_blocks[i];
+ block_ptr = &(blocks->blocks[mb->index << 6]);
+
+ /* Lockup can happen if the coordinates are too far out of range */
+ if (mb->x > (target_surface->width >> 4)) {
+ mb->x = 0;
+ XVMC_INFO("reset x");
+ }
+
+ if (mb->y > (target_surface->height >> 4)) {
+ mb->y = 0;
+ XVMC_INFO("reset y");
+ }
+
+ /* Catch no pattern case */
+ if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) &&
+ !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) &&
+ mb->coded_block_pattern) {
+ mb->coded_block_pattern = 0;
+ XVMC_INFO("no coded blocks present!");
+ }
+
+ bspm = mb_bytes_420[mb->coded_block_pattern];
+
+ if (!bspm)
+ continue;
+
+ corrdata_size += bspm;
+
+ if (corrdata_size > CORRDATA_SIZE) {
+ XVMC_ERR("correction data buffer overflow.");
+ break;
+ }
+ memcpy(corrdata_ptr, block_ptr, bspm);
+ corrdata_ptr += bspm;
+ }
+
+ drm_intel_gem_bo_unmap_gtt(pI915XvMC->corrdata_bo);
+
+ // i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB
+ // | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC);
+
+ i915_mc_one_time_state_emit(context);
+
+ i915_mc_static_indirect_state_set(context, target_surface,
+ picture_structure, flags,
+ picture_coding_type);
+ /* setup reference surfaces */
+ i915_mc_map_state_set(context, privPast, privFuture);
+
+ i915_mc_load_indirect_render_emit(context);
+
+ i915_mc_mpeg_set_origin(context,
+ &macroblock_array->macro_blocks
+ [first_macroblock]);
+
+ for (i = first_macroblock; i < (num_macroblocks + first_macroblock);
+ i++) {
+ mb = &macroblock_array->macro_blocks[i];
+
+ /* Intra Blocks */
+ if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ i915_mc_mpeg_macroblock_ipicture(context, mb);
+ } else if ((picture_structure & XVMC_FRAME_PICTURE) ==
+ XVMC_FRAME_PICTURE) {
+ /* Frame Picture */
+ switch (mb->motion_type & 3) {
+ case XVMC_PREDICTION_FIELD: /* Field Based */
+ i915_mc_mpeg_macroblock_2fbmv(context, mb,
+ picture_structure);
+ break;
+
+ case XVMC_PREDICTION_FRAME: /* Frame Based */
+ i915_mc_mpeg_macroblock_1fbmv(context, mb);
+ break;
+
+ case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */
+ i915_mc_mpeg_macroblock_2fbmv(context, mb,
+ picture_structure);
+ break;
+
+ default: /* No Motion Type */
+ XVMC_ERR
+ ("Invalid Macroblock Parameters found.");
+ break;
+ }
+ } else { /* Field Picture */
+ switch (mb->motion_type & 3) {
+ case XVMC_PREDICTION_FIELD: /* Field Based */
+ i915_mc_mpeg_macroblock_1fbmv(context, mb);
+ break;
+
+ case XVMC_PREDICTION_16x8: /* 16x8 MC */
+ i915_mc_mpeg_macroblock_2fbmv(context, mb,
+ picture_structure);
+ break;
+
+ case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */
+ i915_mc_mpeg_macroblock_1fbmv(context, mb);
+ break;
+
+ default: /* No Motion Type */
+ XVMC_ERR
+ ("Invalid Macroblock Parameters found.");
+ break;
+ }
+ }
+ }
+
+ intelFlushBatch(TRUE);
+
+ i915_xvmc_free_render_state_buffers(pI915XvMC);
+
+ UNLOCK_HARDWARE(intel_ctx->hw_context);
+ return 0;
+}
+
+struct _intel_xvmc_driver i915_xvmc_mc_driver = {
+ .type = XVMC_I915_MPEG2_MC,
+ .num_ctx = 0,
+ .ctx_list = NULL,
+ .create_context = i915_xvmc_mc_create_context,
+ .destroy_context = i915_xvmc_mc_destroy_context,
+ .render_surface = i915_xvmc_mc_render_surface,
+};