xenocara/driver/xf86-video-intel/xvmc/i915_xvmc.c
matthieu f6224eae74 Update to xf86-video-intel 2.99.909
Tested by jsg@, kettenis@ and myself on a wide range of intel cards.
2014-02-03 15:54:42 +00:00

1226 lines
40 KiB
C

/*
* 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();
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,
};