/* * 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 * */ #include #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(¯oblock_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(¯oblock_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(¯oblock_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(¯oblock_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(¯oblock_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(¯oblock_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 = ¯oblock_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, ¯oblock_array->macro_blocks [first_macroblock]); for (i = first_macroblock; i < (num_macroblocks + first_macroblock); i++) { mb = ¯oblock_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(); 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, };