1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 2006 Intel Corporation 3428d7b3dSmrg * 4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"), 6428d7b3dSmrg * to deal in the Software without restriction, including without limitation 7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions: 10428d7b3dSmrg * 11428d7b3dSmrg * The above copyright notice and this permission notice (including the next 12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the 13428d7b3dSmrg * Software. 14428d7b3dSmrg * 15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21428d7b3dSmrg * SOFTWARE. 22428d7b3dSmrg * 23428d7b3dSmrg * Authors: 24428d7b3dSmrg * Xiang Haihao <haihao.xiang@intel.com> 25428d7b3dSmrg * 26428d7b3dSmrg */ 27428d7b3dSmrg 28428d7b3dSmrg#include <sys/ioctl.h> 29428d7b3dSmrg 30428d7b3dSmrg#include "i915_xvmc.h" 31428d7b3dSmrg#include "i915_structs.h" 32428d7b3dSmrg#include "i915_program.h" 33428d7b3dSmrg 34428d7b3dSmrg#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) 35428d7b3dSmrg 36428d7b3dSmrg#define STRIDE(w) (ALIGN((w), 1024)) 37428d7b3dSmrg#define SIZE_Y420(w, h) (h * STRIDE(w)) 38428d7b3dSmrg#define SIZE_UV420(w, h) ((h >> 1) * STRIDE(w >> 1)) 39428d7b3dSmrg#define SIZE_YUV420(w, h) (SIZE_Y420(w,h) + SIZE_UV420(w,h) * 2) 40428d7b3dSmrg#define UOFFSET(context) (SIZE_Y420(context->width, context->height)) 41428d7b3dSmrg#define VOFFSET(context) (SIZE_Y420(context->width, context->height) + \ 42428d7b3dSmrg SIZE_UV420(context->width, context->height)) 43428d7b3dSmrg 44428d7b3dSmrgtypedef union { 45428d7b3dSmrg int16_t component[2]; 46428d7b3dSmrg int32_t v; 47428d7b3dSmrg} vector_t; 48428d7b3dSmrg 49428d7b3dSmrgstatic void i915_inst_arith(unsigned int *inst, 50428d7b3dSmrg unsigned int op, 51428d7b3dSmrg unsigned int dest, 52428d7b3dSmrg unsigned int mask, 53428d7b3dSmrg unsigned int saturate, 54428d7b3dSmrg unsigned int src0, unsigned int src1, 55428d7b3dSmrg unsigned int src2) 56428d7b3dSmrg{ 57428d7b3dSmrg dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); 58428d7b3dSmrg *inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); 59428d7b3dSmrg inst++; 60428d7b3dSmrg *inst = (A1_SRC0(src0) | A1_SRC1(src1)); 61428d7b3dSmrg inst++; 62428d7b3dSmrg *inst = (A2_SRC1(src1) | A2_SRC2(src2)); 63428d7b3dSmrg} 64428d7b3dSmrg 65428d7b3dSmrgstatic void i915_inst_decl(unsigned int *inst, 66428d7b3dSmrg unsigned int type, 67428d7b3dSmrg unsigned int nr, unsigned int d0_flags) 68428d7b3dSmrg{ 69428d7b3dSmrg unsigned int reg = UREG(type, nr); 70428d7b3dSmrg 71428d7b3dSmrg *inst = (D0_DCL | D0_DEST(reg) | d0_flags); 72428d7b3dSmrg inst++; 73428d7b3dSmrg *inst = D1_MBZ; 74428d7b3dSmrg inst++; 75428d7b3dSmrg *inst = D2_MBZ; 76428d7b3dSmrg} 77428d7b3dSmrg 78428d7b3dSmrgstatic void i915_inst_texld(unsigned int *inst, 79428d7b3dSmrg unsigned int op, 80428d7b3dSmrg unsigned int dest, 81428d7b3dSmrg unsigned int coord, unsigned int sampler) 82428d7b3dSmrg{ 83428d7b3dSmrg dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); 84428d7b3dSmrg *inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler)); 85428d7b3dSmrg inst++; 86428d7b3dSmrg *inst = T1_ADDRESS_REG(coord); 87428d7b3dSmrg inst++; 88428d7b3dSmrg *inst = T2_MBZ; 89428d7b3dSmrg} 90428d7b3dSmrg 91428d7b3dSmrgstatic void i915_mc_one_time_context_init(XvMCContext * context) 92428d7b3dSmrg{ 93428d7b3dSmrg unsigned int dest, src0, src1, src2; 94428d7b3dSmrg i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 95428d7b3dSmrg int i; 96428d7b3dSmrg struct i915_3dstate_sampler_state *sampler_state; 97428d7b3dSmrg struct i915_3dstate_pixel_shader_program *pixel_shader_program; 98428d7b3dSmrg struct i915_3dstate_pixel_shader_constants *pixel_shader_constants; 99428d7b3dSmrg 100428d7b3dSmrg /* sampler static state */ 101428d7b3dSmrg drm_intel_gem_bo_map_gtt(pI915XvMC->ssb_bo); 102428d7b3dSmrg sampler_state = pI915XvMC->ssb_bo->virtual; 103428d7b3dSmrg 104428d7b3dSmrg memset(sampler_state, 0, sizeof(*sampler_state)); 105428d7b3dSmrg sampler_state->dw0.type = CMD_3D; 106428d7b3dSmrg sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE; 107428d7b3dSmrg sampler_state->dw0.length = 6; 108428d7b3dSmrg sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1; 109428d7b3dSmrg 110428d7b3dSmrg sampler_state->sampler0.ts0.reverse_gamma = 0; 111428d7b3dSmrg sampler_state->sampler0.ts0.planar2packet = 0; 112428d7b3dSmrg sampler_state->sampler0.ts0.color_conversion = 0; 113428d7b3dSmrg sampler_state->sampler0.ts0.chromakey_index = 0; 114428d7b3dSmrg sampler_state->sampler0.ts0.base_level = 0; 115428d7b3dSmrg sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE; /* NONE */ 116428d7b3dSmrg sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ 117428d7b3dSmrg sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ 118428d7b3dSmrg sampler_state->sampler0.ts0.lod_bias = 0; /* 0.0 */ 119428d7b3dSmrg sampler_state->sampler0.ts0.shadow_enable = 0; 120428d7b3dSmrg sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2; 121428d7b3dSmrg sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS; 122428d7b3dSmrg sampler_state->sampler0.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ 123428d7b3dSmrg sampler_state->sampler0.ts1.kill_pixel = 0; 124428d7b3dSmrg sampler_state->sampler0.ts1.keyed_texture_filter = 0; 125428d7b3dSmrg sampler_state->sampler0.ts1.chromakey_enable = 0; 126428d7b3dSmrg sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP; 127428d7b3dSmrg sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP; 128428d7b3dSmrg sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP; 129428d7b3dSmrg sampler_state->sampler0.ts1.normalized_coor = 0; 130428d7b3dSmrg sampler_state->sampler0.ts1.map_index = 0; 131428d7b3dSmrg sampler_state->sampler0.ts1.east_deinterlacer = 0; 132428d7b3dSmrg sampler_state->sampler0.ts2.default_color = 0; 133428d7b3dSmrg 134428d7b3dSmrg sampler_state->sampler1.ts0.reverse_gamma = 0; 135428d7b3dSmrg sampler_state->sampler1.ts0.planar2packet = 0; 136428d7b3dSmrg sampler_state->sampler1.ts0.color_conversion = 0; 137428d7b3dSmrg sampler_state->sampler1.ts0.chromakey_index = 0; 138428d7b3dSmrg sampler_state->sampler1.ts0.base_level = 0; 139428d7b3dSmrg sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE; /* NONE */ 140428d7b3dSmrg sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ 141428d7b3dSmrg sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ 142428d7b3dSmrg sampler_state->sampler1.ts0.lod_bias = 0; /* 0.0 */ 143428d7b3dSmrg sampler_state->sampler1.ts0.shadow_enable = 0; 144428d7b3dSmrg sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2; 145428d7b3dSmrg sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS; 146428d7b3dSmrg sampler_state->sampler1.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ 147428d7b3dSmrg sampler_state->sampler1.ts1.kill_pixel = 0; 148428d7b3dSmrg sampler_state->sampler1.ts1.keyed_texture_filter = 0; 149428d7b3dSmrg sampler_state->sampler1.ts1.chromakey_enable = 0; 150428d7b3dSmrg sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP; 151428d7b3dSmrg sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP; 152428d7b3dSmrg sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP; 153428d7b3dSmrg sampler_state->sampler1.ts1.normalized_coor = 0; 154428d7b3dSmrg sampler_state->sampler1.ts1.map_index = 1; 155428d7b3dSmrg sampler_state->sampler1.ts1.east_deinterlacer = 0; 156428d7b3dSmrg sampler_state->sampler1.ts2.default_color = 0; 157428d7b3dSmrg 158428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(pI915XvMC->ssb_bo); 159428d7b3dSmrg 160428d7b3dSmrg /* pixel shader static state */ 161428d7b3dSmrg drm_intel_gem_bo_map_gtt(pI915XvMC->psp_bo); 162428d7b3dSmrg pixel_shader_program = pI915XvMC->psp_bo->virtual; 163428d7b3dSmrg 164428d7b3dSmrg memset(pixel_shader_program, 0, sizeof(*pixel_shader_program)); 165428d7b3dSmrg pixel_shader_program->shader0.type = CMD_3D; 166428d7b3dSmrg pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 167428d7b3dSmrg pixel_shader_program->shader0.retain = 1; 168428d7b3dSmrg pixel_shader_program->shader0.length = 2; /* 1 inst */ 169428d7b3dSmrg i = 0; 170428d7b3dSmrg 171428d7b3dSmrg dest = UREG(REG_TYPE_OC, 0); 172428d7b3dSmrg src0 = UREG(REG_TYPE_CONST, 0); 173428d7b3dSmrg src1 = 0; 174428d7b3dSmrg src2 = 0; 175428d7b3dSmrg i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV, 176428d7b3dSmrg dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 177428d7b3dSmrg src2); 178428d7b3dSmrg 179428d7b3dSmrg pixel_shader_program->shader1.type = CMD_3D; 180428d7b3dSmrg pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 181428d7b3dSmrg pixel_shader_program->shader1.retain = 1; 182428d7b3dSmrg pixel_shader_program->shader1.length = 14; /* 5 inst */ 183428d7b3dSmrg i = 0; 184428d7b3dSmrg /* dcl t0.xy */ 185428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0, 186428d7b3dSmrg D0_CHANNEL_XY); 187428d7b3dSmrg i += 3; 188428d7b3dSmrg /* dcl t1.xy */ 189428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1, 190428d7b3dSmrg D0_CHANNEL_XY); 191428d7b3dSmrg /* dcl_2D s0 */ 192428d7b3dSmrg i += 3; 193428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0, 194428d7b3dSmrg D0_SAMPLE_TYPE_2D); 195428d7b3dSmrg /* texld r0, t0, s0 */ 196428d7b3dSmrg i += 3; 197428d7b3dSmrg dest = UREG(REG_TYPE_R, 0); 198428d7b3dSmrg src0 = UREG(REG_TYPE_T, 0); /* COORD */ 199428d7b3dSmrg src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ 200428d7b3dSmrg i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0, 201428d7b3dSmrg src1); 202428d7b3dSmrg /* mov oC, r0 */ 203428d7b3dSmrg i += 3; 204428d7b3dSmrg dest = UREG(REG_TYPE_OC, 0); 205428d7b3dSmrg src0 = UREG(REG_TYPE_R, 0); 206428d7b3dSmrg src1 = src2 = 0; 207428d7b3dSmrg i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest, 208428d7b3dSmrg A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 209428d7b3dSmrg src2); 210428d7b3dSmrg 211428d7b3dSmrg pixel_shader_program->shader2.type = CMD_3D; 212428d7b3dSmrg pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 213428d7b3dSmrg pixel_shader_program->shader2.retain = 1; 214428d7b3dSmrg pixel_shader_program->shader2.length = 14; /* 5 inst */ 215428d7b3dSmrg i = 0; 216428d7b3dSmrg /* dcl t2.xy */ 217428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2, 218428d7b3dSmrg D0_CHANNEL_XY); 219428d7b3dSmrg /* dcl t3.xy */ 220428d7b3dSmrg i += 3; 221428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3, 222428d7b3dSmrg D0_CHANNEL_XY); 223428d7b3dSmrg /* dcl_2D s1 */ 224428d7b3dSmrg i += 3; 225428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1, 226428d7b3dSmrg D0_SAMPLE_TYPE_2D); 227428d7b3dSmrg /* texld r0, t2, s1 */ 228428d7b3dSmrg i += 3; 229428d7b3dSmrg dest = UREG(REG_TYPE_R, 0); 230428d7b3dSmrg src0 = UREG(REG_TYPE_T, 2); /* COORD */ 231428d7b3dSmrg src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ 232428d7b3dSmrg i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0, 233428d7b3dSmrg src1); 234428d7b3dSmrg /* mov oC, r0 */ 235428d7b3dSmrg i += 3; 236428d7b3dSmrg dest = UREG(REG_TYPE_OC, 0); 237428d7b3dSmrg src0 = UREG(REG_TYPE_R, 0); 238428d7b3dSmrg src1 = src2 = 0; 239428d7b3dSmrg i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest, 240428d7b3dSmrg A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 241428d7b3dSmrg src2); 242428d7b3dSmrg 243428d7b3dSmrg /* Shader 3 */ 244428d7b3dSmrg pixel_shader_program->shader3.type = CMD_3D; 245428d7b3dSmrg pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 246428d7b3dSmrg pixel_shader_program->shader3.retain = 1; 247428d7b3dSmrg pixel_shader_program->shader3.length = 29; /* 10 inst */ 248428d7b3dSmrg i = 0; 249428d7b3dSmrg /* dcl t0.xy */ 250428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0, 251428d7b3dSmrg D0_CHANNEL_XY); 252428d7b3dSmrg /* dcl t1.xy */ 253428d7b3dSmrg i += 3; 254428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1, 255428d7b3dSmrg D0_CHANNEL_XY); 256428d7b3dSmrg /* dcl t2.xy */ 257428d7b3dSmrg i += 3; 258428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2, 259428d7b3dSmrg D0_CHANNEL_XY); 260428d7b3dSmrg /* dcl t3.xy */ 261428d7b3dSmrg i += 3; 262428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3, 263428d7b3dSmrg D0_CHANNEL_XY); 264428d7b3dSmrg /* dcl_2D s0 */ 265428d7b3dSmrg i += 3; 266428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0, 267428d7b3dSmrg D0_SAMPLE_TYPE_2D); 268428d7b3dSmrg /* dcl_2D s1 */ 269428d7b3dSmrg i += 3; 270428d7b3dSmrg i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1, 271428d7b3dSmrg D0_SAMPLE_TYPE_2D); 272428d7b3dSmrg /* texld r0, t0, s0 */ 273428d7b3dSmrg i += 3; 274428d7b3dSmrg dest = UREG(REG_TYPE_R, 0); 275428d7b3dSmrg src0 = UREG(REG_TYPE_T, 0); /* COORD */ 276428d7b3dSmrg src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ 277428d7b3dSmrg i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0, 278428d7b3dSmrg src1); 279428d7b3dSmrg /* texld r1, t2, s1 */ 280428d7b3dSmrg i += 3; 281428d7b3dSmrg dest = UREG(REG_TYPE_R, 1); 282428d7b3dSmrg src0 = UREG(REG_TYPE_T, 2); /* COORD */ 283428d7b3dSmrg src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ 284428d7b3dSmrg i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0, 285428d7b3dSmrg src1); 286428d7b3dSmrg /* add r0, r0, r1 */ 287428d7b3dSmrg i += 3; 288428d7b3dSmrg dest = UREG(REG_TYPE_R, 0); 289428d7b3dSmrg src0 = UREG(REG_TYPE_R, 0); 290428d7b3dSmrg src1 = UREG(REG_TYPE_R, 1); 291428d7b3dSmrg src2 = 0; 292428d7b3dSmrg i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest, 293428d7b3dSmrg A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */ , src0, 294428d7b3dSmrg src1, src2); 295428d7b3dSmrg /* mul oC, r0, c0 */ 296428d7b3dSmrg i += 3; 297428d7b3dSmrg dest = UREG(REG_TYPE_OC, 0); 298428d7b3dSmrg src0 = UREG(REG_TYPE_R, 0); 299428d7b3dSmrg src1 = UREG(REG_TYPE_CONST, 0); 300428d7b3dSmrg src2 = 0; 301428d7b3dSmrg i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest, 302428d7b3dSmrg A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 303428d7b3dSmrg src2); 304428d7b3dSmrg 305428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(pI915XvMC->psp_bo); 306428d7b3dSmrg 307428d7b3dSmrg /* pixel shader contant static state */ 308428d7b3dSmrg drm_intel_gem_bo_map_gtt(pI915XvMC->psc_bo); 309428d7b3dSmrg pixel_shader_constants = pI915XvMC->psc_bo->virtual; 310428d7b3dSmrg 311428d7b3dSmrg memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants)); 312428d7b3dSmrg pixel_shader_constants->dw0.type = CMD_3D; 313428d7b3dSmrg pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS; 314428d7b3dSmrg pixel_shader_constants->dw0.length = 4; 315428d7b3dSmrg pixel_shader_constants->dw1.reg_mask = REG_CR0; 316428d7b3dSmrg pixel_shader_constants->value.x = 0.5; 317428d7b3dSmrg pixel_shader_constants->value.y = 0.5; 318428d7b3dSmrg pixel_shader_constants->value.z = 0.5; 319428d7b3dSmrg pixel_shader_constants->value.w = 0.5; 320428d7b3dSmrg 321428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(pI915XvMC->psc_bo); 322428d7b3dSmrg} 323428d7b3dSmrg 324428d7b3dSmrgstatic void i915_mc_one_time_state_emit(XvMCContext * context) 325428d7b3dSmrg{ 326428d7b3dSmrg i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 327428d7b3dSmrg uint32_t load_state_immediate_1, load_indirect, s3_dword, s6_dword; 328428d7b3dSmrg int mem_select; 329428d7b3dSmrg BATCH_LOCALS; 330428d7b3dSmrg 331428d7b3dSmrg /* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */ 332428d7b3dSmrg BEGIN_BATCH(3 + 8); 333428d7b3dSmrg load_state_immediate_1 = OP_3D_LOAD_STATE_IMMEDIATE_1; 334428d7b3dSmrg load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S3; 335428d7b3dSmrg load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S6; 336428d7b3dSmrg load_state_immediate_1 |= 3 - 2; /* length */ 337428d7b3dSmrg OUT_BATCH(load_state_immediate_1); 338428d7b3dSmrg 339428d7b3dSmrg s3_dword = S3_SET0_PCD | S3_SET1_PCD | 340428d7b3dSmrg S3_SET2_PCD | S3_SET3_PCD | 341428d7b3dSmrg S3_SET4_PCD | S3_SET5_PCD | 342428d7b3dSmrg S3_SET6_PCD | S3_SET7_PCD; 343428d7b3dSmrg OUT_BATCH(s3_dword); 344428d7b3dSmrg 345428d7b3dSmrg s6_dword = S6_COLOR_BUFFER_WRITE | S6_DEPTH_TEST_ENABLE; 346428d7b3dSmrg s6_dword |= 1 << S6_SRC_BLEND_FACTOR_SHIFT; 347428d7b3dSmrg s6_dword |= 1 << S6_DST_BLEND_FACTOR_SHIFT; 348428d7b3dSmrg OUT_BATCH(s6_dword); 349428d7b3dSmrg 350428d7b3dSmrg /* 3DSTATE_LOAD_INDIRECT */ 351428d7b3dSmrg load_indirect = OP_3D_LOAD_INDIRECT; 352428d7b3dSmrg load_indirect |= (BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC) 353428d7b3dSmrg << BLOCK_MASK_SHIFT; 354428d7b3dSmrg load_indirect |= 8 - 2; /* length */ 355428d7b3dSmrg 356428d7b3dSmrg if (pI915XvMC->use_phys_addr) 357428d7b3dSmrg mem_select = 0; /* use physical address */ 358428d7b3dSmrg else { 359428d7b3dSmrg load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR; 360428d7b3dSmrg mem_select = 1; /* use gfx address */ 361428d7b3dSmrg } 362428d7b3dSmrg 363428d7b3dSmrg OUT_BATCH(load_indirect); 364428d7b3dSmrg 365428d7b3dSmrg /* Dynamic indirect state buffer */ 366428d7b3dSmrg OUT_BATCH(0); /* no dynamic indirect state */ 367428d7b3dSmrg 368428d7b3dSmrg /* Sample state buffer */ 369428d7b3dSmrg OUT_RELOC(pI915XvMC->ssb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 370428d7b3dSmrg STATE_VALID | STATE_FORCE); 371428d7b3dSmrg OUT_BATCH(7); /* 8 - 1 */ 372428d7b3dSmrg 373428d7b3dSmrg /* Pixel shader program buffer */ 374428d7b3dSmrg OUT_RELOC(pI915XvMC->psp_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 375428d7b3dSmrg STATE_VALID | STATE_FORCE); 376428d7b3dSmrg OUT_BATCH(66); /* 4 + 16 + 16 + 31 - 1 */ 377428d7b3dSmrg 378428d7b3dSmrg /* Pixel shader constant buffer */ 379428d7b3dSmrg OUT_RELOC(pI915XvMC->psc_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 380428d7b3dSmrg STATE_VALID | STATE_FORCE); 381428d7b3dSmrg OUT_BATCH(5); /* 6 - 1 */ 382428d7b3dSmrg ADVANCE_BATCH(); 383428d7b3dSmrg} 384428d7b3dSmrg 385428d7b3dSmrgstatic void i915_mc_static_indirect_state_set(XvMCContext * context, 386428d7b3dSmrg XvMCSurface * dest, 387428d7b3dSmrg unsigned int picture_structure, 388428d7b3dSmrg unsigned int flags, 389428d7b3dSmrg unsigned int picture_coding_type) 390428d7b3dSmrg{ 391428d7b3dSmrg i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 392428d7b3dSmrg struct intel_xvmc_surface *intel_surf = dest->privData; 393428d7b3dSmrg struct i915_mc_static_indirect_state_buffer *buffer_info; 394428d7b3dSmrg 395428d7b3dSmrg drm_intel_gem_bo_map_gtt(pI915XvMC->sis_bo); 396428d7b3dSmrg buffer_info = pI915XvMC->sis_bo->virtual; 397428d7b3dSmrg 398428d7b3dSmrg memset(buffer_info, 0, sizeof(*buffer_info)); 399428d7b3dSmrg 400428d7b3dSmrg /* dest Y */ 401428d7b3dSmrg buffer_info->dest_y.dw0.type = CMD_3D; 402428d7b3dSmrg buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 403428d7b3dSmrg buffer_info->dest_y.dw0.length = 1; 404428d7b3dSmrg buffer_info->dest_y.dw1.aux_id = 0; 405428d7b3dSmrg buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK; 406428d7b3dSmrg buffer_info->dest_y.dw1.fence_regs = 0; /* disabled *//* FIXME: tiled y for performance */ 407428d7b3dSmrg buffer_info->dest_y.dw1.tiled_surface = 0; /* linear */ 408428d7b3dSmrg buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR; 409428d7b3dSmrg buffer_info->dest_y.dw1.pitch = (pI915XvMC->yStride >> 2); /* in DWords */ 410428d7b3dSmrg buffer_info->dest_y.dw2.base_address = intel_surf->bo->offset >> 2; /* starting DWORD address */ 411428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 412428d7b3dSmrg offsetof(typeof(*buffer_info),dest_y.dw2), 413428d7b3dSmrg intel_surf->bo, 0, 414428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 415428d7b3dSmrg I915_GEM_DOMAIN_RENDER); 416428d7b3dSmrg 417428d7b3dSmrg /* dest U */ 418428d7b3dSmrg buffer_info->dest_u.dw0.type = CMD_3D; 419428d7b3dSmrg buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 420428d7b3dSmrg buffer_info->dest_u.dw0.length = 1; 421428d7b3dSmrg buffer_info->dest_u.dw1.aux_id = 0; 422428d7b3dSmrg buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX; 423428d7b3dSmrg buffer_info->dest_u.dw1.fence_regs = 0; 424428d7b3dSmrg buffer_info->dest_u.dw1.tiled_surface = 0; 425428d7b3dSmrg buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR; 426428d7b3dSmrg buffer_info->dest_u.dw1.pitch = (pI915XvMC->uvStride >> 2); /* in DWords */ 427428d7b3dSmrg buffer_info->dest_u.dw2.base_address = 428428d7b3dSmrg (intel_surf->bo->offset + UOFFSET(context)) >> 2; 429428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 430428d7b3dSmrg offsetof(typeof(*buffer_info),dest_u.dw2), 431428d7b3dSmrg intel_surf->bo, UOFFSET(context), 432428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 433428d7b3dSmrg I915_GEM_DOMAIN_RENDER); 434428d7b3dSmrg 435428d7b3dSmrg /* dest V */ 436428d7b3dSmrg buffer_info->dest_v.dw0.type = CMD_3D; 437428d7b3dSmrg buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 438428d7b3dSmrg buffer_info->dest_v.dw0.length = 1; 439428d7b3dSmrg buffer_info->dest_v.dw1.aux_id = 1; 440428d7b3dSmrg buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX; 441428d7b3dSmrg buffer_info->dest_v.dw1.fence_regs = 0; 442428d7b3dSmrg buffer_info->dest_v.dw1.tiled_surface = 0; 443428d7b3dSmrg buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR; 444428d7b3dSmrg buffer_info->dest_v.dw1.pitch = (pI915XvMC->uvStride >> 2); /* in Dwords */ 445428d7b3dSmrg buffer_info->dest_v.dw2.base_address = 446428d7b3dSmrg (intel_surf->bo->offset + VOFFSET(context)) >> 2; 447428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 448428d7b3dSmrg offsetof(typeof(*buffer_info),dest_v.dw2), 449428d7b3dSmrg intel_surf->bo, VOFFSET(context), 450428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 451428d7b3dSmrg I915_GEM_DOMAIN_RENDER); 452428d7b3dSmrg 453428d7b3dSmrg /* Dest buffer parameters */ 454428d7b3dSmrg buffer_info->dest_buf.dw0.type = CMD_3D; 455428d7b3dSmrg buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES; 456428d7b3dSmrg buffer_info->dest_buf.dw0.length = 0; 457428d7b3dSmrg buffer_info->dest_buf.dw1.dest_v_bias = 8; /* 0.5 */ 458428d7b3dSmrg buffer_info->dest_buf.dw1.dest_h_bias = 8; /* 0.5 */ 459428d7b3dSmrg buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT; 460428d7b3dSmrg buffer_info->dest_buf.dw1.v_ls = 0; /* fill later */ 461428d7b3dSmrg buffer_info->dest_buf.dw1.v_ls_offset = 0; /* fill later */ 462428d7b3dSmrg if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { 463428d7b3dSmrg ; 464428d7b3dSmrg } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) { 465428d7b3dSmrg buffer_info->dest_buf.dw1.v_ls = 1; 466428d7b3dSmrg } else if ((picture_structure & XVMC_FRAME_PICTURE) == 467428d7b3dSmrg XVMC_BOTTOM_FIELD) { 468428d7b3dSmrg buffer_info->dest_buf.dw1.v_ls = 1; 469428d7b3dSmrg buffer_info->dest_buf.dw1.v_ls_offset = 1; 470428d7b3dSmrg } 471428d7b3dSmrg 472428d7b3dSmrg /* MPEG buffer parameters */ 473428d7b3dSmrg buffer_info->dest_buf_mpeg.dw0.type = CMD_3D; 474428d7b3dSmrg buffer_info->dest_buf_mpeg.dw0.opcode = 475428d7b3dSmrg OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG; 476428d7b3dSmrg buffer_info->dest_buf_mpeg.dw0.length = 1; 477428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC; 478428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.rcontrol = 0; /* for MPEG-1/MPEG-2 */ 479428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0; /* for MPEG-1/MPEG-2/MPEG-4 */ 480428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1; 481428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.intra8 = 0; /* 16-bit formatted correction data */ 482428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.tff = 1; /* fill later */ 483428d7b3dSmrg 484428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V; 485428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H; 486428d7b3dSmrg 487428d7b3dSmrg if (picture_structure & XVMC_FRAME_PICTURE) { 488428d7b3dSmrg ; 489428d7b3dSmrg } else if (picture_structure & XVMC_TOP_FIELD) { 490428d7b3dSmrg if (flags & XVMC_SECOND_FIELD) 491428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.tff = 0; 492428d7b3dSmrg else 493428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.tff = 1; 494428d7b3dSmrg } else if (picture_structure & XVMC_BOTTOM_FIELD) { 495428d7b3dSmrg if (flags & XVMC_SECOND_FIELD) 496428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.tff = 1; 497428d7b3dSmrg else 498428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.tff = 0; 499428d7b3dSmrg } 500428d7b3dSmrg 501428d7b3dSmrg buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4); /* in macroblocks */ 502428d7b3dSmrg buffer_info->dest_buf_mpeg.dw2.picture_coding_type = 503428d7b3dSmrg picture_coding_type; 504428d7b3dSmrg 505428d7b3dSmrg buffer_info->corr.dw0.type = CMD_3D; 506428d7b3dSmrg buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 507428d7b3dSmrg buffer_info->corr.dw0.length = 1; 508428d7b3dSmrg buffer_info->corr.dw1.aux_id = 0; 509428d7b3dSmrg buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR; 510428d7b3dSmrg buffer_info->corr.dw1.aux_id = 0; 511428d7b3dSmrg buffer_info->corr.dw1.fence_regs = 0; 512428d7b3dSmrg buffer_info->corr.dw1.tiled_surface = 0; 513428d7b3dSmrg buffer_info->corr.dw1.walk = 0; 514428d7b3dSmrg buffer_info->corr.dw1.pitch = 0; 515428d7b3dSmrg buffer_info->corr.dw2.base_address = pI915XvMC->corrdata_bo->offset >> 2; /* starting DWORD address */ 516428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 517428d7b3dSmrg offsetof(typeof(*buffer_info),corr.dw2), 518428d7b3dSmrg pI915XvMC->corrdata_bo, 0, 519428d7b3dSmrg I915_GEM_DOMAIN_RENDER, 0); 520428d7b3dSmrg 521428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(pI915XvMC->sis_bo); 522428d7b3dSmrg} 523428d7b3dSmrg 524428d7b3dSmrgstatic void i915_mc_map_state_set(XvMCContext * context, 525428d7b3dSmrg struct intel_xvmc_surface * privPast, 526428d7b3dSmrg struct intel_xvmc_surface * privFuture) 527428d7b3dSmrg{ 528428d7b3dSmrg i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 529428d7b3dSmrg struct i915_mc_map_state *map_state; 530428d7b3dSmrg unsigned int w = context->width; 531428d7b3dSmrg unsigned int h = context->height; 532428d7b3dSmrg 533428d7b3dSmrg drm_intel_gem_bo_map_gtt(pI915XvMC->msb_bo); 534428d7b3dSmrg map_state = pI915XvMC->msb_bo->virtual; 535428d7b3dSmrg 536428d7b3dSmrg memset(map_state, 0, sizeof(*map_state)); 537428d7b3dSmrg 538428d7b3dSmrg /* 3DSATE_MAP_STATE: Y */ 539428d7b3dSmrg map_state->y_map.dw0.type = CMD_3D; 540428d7b3dSmrg map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; 541428d7b3dSmrg map_state->y_map.dw0.retain = 1; 542428d7b3dSmrg map_state->y_map.dw0.length = 6; 543428d7b3dSmrg map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; 544428d7b3dSmrg 545428d7b3dSmrg /* Y Forward (Past) */ 546428d7b3dSmrg map_state->y_forward.tm0.v_ls_offset = 0; 547428d7b3dSmrg map_state->y_forward.tm0.v_ls = 0; 548428d7b3dSmrg map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR; 549428d7b3dSmrg map_state->y_forward.tm1.tiled_surface = 0; 550428d7b3dSmrg map_state->y_forward.tm1.utilize_fence_regs = 0; 551428d7b3dSmrg map_state->y_forward.tm1.texel_fmt = 0; /* 8bit */ 552428d7b3dSmrg map_state->y_forward.tm1.surface_fmt = 1; /* 8bit */ 553428d7b3dSmrg map_state->y_forward.tm1.width = w - 1; 554428d7b3dSmrg map_state->y_forward.tm1.height = h - 1; 555428d7b3dSmrg map_state->y_forward.tm2.depth = 0; 556428d7b3dSmrg map_state->y_forward.tm2.max_lod = 0; 557428d7b3dSmrg map_state->y_forward.tm2.cube_face = 0; 558428d7b3dSmrg map_state->y_forward.tm0.base_address = privPast->bo->offset >> 2; 559428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 560428d7b3dSmrg offsetof(typeof(*map_state),y_forward.tm0), 561428d7b3dSmrg privPast->bo, 0, 562428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 563428d7b3dSmrg map_state->y_forward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1; /* in DWords - 1 */ 564428d7b3dSmrg 565428d7b3dSmrg /* Y Backward (Future) */ 566428d7b3dSmrg map_state->y_backward.tm0.v_ls_offset = 0; 567428d7b3dSmrg map_state->y_backward.tm0.v_ls = 0; 568428d7b3dSmrg map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR; 569428d7b3dSmrg map_state->y_backward.tm1.tiled_surface = 0; 570428d7b3dSmrg map_state->y_backward.tm1.utilize_fence_regs = 0; 571428d7b3dSmrg map_state->y_backward.tm1.texel_fmt = 0; /* 8bit */ 572428d7b3dSmrg map_state->y_backward.tm1.surface_fmt = 1; /* 8bit */ 573428d7b3dSmrg map_state->y_backward.tm1.width = w - 1; 574428d7b3dSmrg map_state->y_backward.tm1.height = h - 1; 575428d7b3dSmrg map_state->y_backward.tm2.depth = 0; 576428d7b3dSmrg map_state->y_backward.tm2.max_lod = 0; 577428d7b3dSmrg map_state->y_backward.tm2.cube_face = 0; 578428d7b3dSmrg map_state->y_backward.tm0.base_address = privFuture->bo->offset >> 2; 579428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 580428d7b3dSmrg offsetof(typeof(*map_state),y_backward.tm0), 581428d7b3dSmrg privFuture->bo, 0, 582428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 583428d7b3dSmrg map_state->y_backward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1; 584428d7b3dSmrg 585428d7b3dSmrg /* 3DSATE_MAP_STATE: U */ 586428d7b3dSmrg map_state->u_map.dw0.type = CMD_3D; 587428d7b3dSmrg map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; 588428d7b3dSmrg map_state->u_map.dw0.retain = 1; 589428d7b3dSmrg map_state->u_map.dw0.length = 6; 590428d7b3dSmrg map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; 591428d7b3dSmrg 592428d7b3dSmrg /* U Forward */ 593428d7b3dSmrg map_state->u_forward.tm0.v_ls_offset = 0; 594428d7b3dSmrg map_state->u_forward.tm0.v_ls = 0; 595428d7b3dSmrg map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR; 596428d7b3dSmrg map_state->u_forward.tm1.tiled_surface = 0; 597428d7b3dSmrg map_state->u_forward.tm1.utilize_fence_regs = 0; 598428d7b3dSmrg map_state->u_forward.tm1.texel_fmt = 0; /* 8bit */ 599428d7b3dSmrg map_state->u_forward.tm1.surface_fmt = 1; /* 8bit */ 600428d7b3dSmrg map_state->u_forward.tm1.width = (w >> 1) - 1; 601428d7b3dSmrg map_state->u_forward.tm1.height = (h >> 1) - 1; 602428d7b3dSmrg map_state->u_forward.tm2.depth = 0; 603428d7b3dSmrg map_state->u_forward.tm2.max_lod = 0; 604428d7b3dSmrg map_state->u_forward.tm2.cube_face = 0; 605428d7b3dSmrg map_state->u_forward.tm0.base_address = 606428d7b3dSmrg (privPast->bo->offset + UOFFSET(context)) >> 2; 607428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 608428d7b3dSmrg offsetof(typeof(*map_state),u_forward.tm0), 609428d7b3dSmrg privPast->bo, UOFFSET(context), 610428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 611428d7b3dSmrg map_state->u_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; /* in DWords - 1 */ 612428d7b3dSmrg 613428d7b3dSmrg /* U Backward */ 614428d7b3dSmrg map_state->u_backward.tm0.v_ls_offset = 0; 615428d7b3dSmrg map_state->u_backward.tm0.v_ls = 0; 616428d7b3dSmrg map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR; 617428d7b3dSmrg map_state->u_backward.tm1.tiled_surface = 0; 618428d7b3dSmrg map_state->u_backward.tm1.utilize_fence_regs = 0; 619428d7b3dSmrg map_state->u_backward.tm1.texel_fmt = 0; 620428d7b3dSmrg map_state->u_backward.tm1.surface_fmt = 1; 621428d7b3dSmrg map_state->u_backward.tm1.width = (w >> 1) - 1; 622428d7b3dSmrg map_state->u_backward.tm1.height = (h >> 1) - 1; 623428d7b3dSmrg map_state->u_backward.tm2.depth = 0; 624428d7b3dSmrg map_state->u_backward.tm2.max_lod = 0; 625428d7b3dSmrg map_state->u_backward.tm2.cube_face = 0; 626428d7b3dSmrg map_state->u_backward.tm0.base_address = 627428d7b3dSmrg (privFuture->bo->offset + UOFFSET(context)) >> 2; 628428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 629428d7b3dSmrg offsetof(typeof(*map_state),u_backward.tm0), 630428d7b3dSmrg privFuture->bo, UOFFSET(context), 631428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 632428d7b3dSmrg map_state->u_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; 633428d7b3dSmrg 634428d7b3dSmrg /* 3DSATE_MAP_STATE: V */ 635428d7b3dSmrg map_state->v_map.dw0.type = CMD_3D; 636428d7b3dSmrg map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; 637428d7b3dSmrg map_state->v_map.dw0.retain = 1; 638428d7b3dSmrg map_state->v_map.dw0.length = 6; 639428d7b3dSmrg map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; 640428d7b3dSmrg 641428d7b3dSmrg /* V Forward */ 642428d7b3dSmrg map_state->v_forward.tm0.v_ls_offset = 0; 643428d7b3dSmrg map_state->v_forward.tm0.v_ls = 0; 644428d7b3dSmrg map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR; 645428d7b3dSmrg map_state->v_forward.tm1.tiled_surface = 0; 646428d7b3dSmrg map_state->v_forward.tm1.utilize_fence_regs = 0; 647428d7b3dSmrg map_state->v_forward.tm1.texel_fmt = 0; 648428d7b3dSmrg map_state->v_forward.tm1.surface_fmt = 1; 649428d7b3dSmrg map_state->v_forward.tm1.width = (w >> 1) - 1; 650428d7b3dSmrg map_state->v_forward.tm1.height = (h >> 1) - 1; 651428d7b3dSmrg map_state->v_forward.tm2.depth = 0; 652428d7b3dSmrg map_state->v_forward.tm2.max_lod = 0; 653428d7b3dSmrg map_state->v_forward.tm2.cube_face = 0; 654428d7b3dSmrg map_state->v_forward.tm0.base_address = 655428d7b3dSmrg (privPast->bo->offset + VOFFSET(context)) >> 2; 656428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 657428d7b3dSmrg offsetof(typeof(*map_state),v_forward.tm0), 658428d7b3dSmrg privPast->bo, VOFFSET(context), 659428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 660428d7b3dSmrg map_state->v_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; /* in DWords - 1 */ 661428d7b3dSmrg 662428d7b3dSmrg /* V Backward */ 663428d7b3dSmrg map_state->v_backward.tm0.v_ls_offset = 0; 664428d7b3dSmrg map_state->v_backward.tm0.v_ls = 0; 665428d7b3dSmrg map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR; 666428d7b3dSmrg map_state->v_backward.tm1.tiled_surface = 0; 667428d7b3dSmrg map_state->v_backward.tm1.utilize_fence_regs = 0; 668428d7b3dSmrg map_state->v_backward.tm1.texel_fmt = 0; 669428d7b3dSmrg map_state->v_backward.tm1.surface_fmt = 1; 670428d7b3dSmrg map_state->v_backward.tm1.width = (w >> 1) - 1; 671428d7b3dSmrg map_state->v_backward.tm1.height = (h >> 1) - 1; 672428d7b3dSmrg map_state->v_backward.tm2.depth = 0; 673428d7b3dSmrg map_state->v_backward.tm2.max_lod = 0; 674428d7b3dSmrg map_state->v_backward.tm2.cube_face = 0; 675428d7b3dSmrg map_state->v_backward.tm0.base_address = 676428d7b3dSmrg (privFuture->bo->offset + VOFFSET(context)) >> 2; 677428d7b3dSmrg drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 678428d7b3dSmrg offsetof(typeof(*map_state),v_backward.tm0), 679428d7b3dSmrg privFuture->bo, VOFFSET(context), 680428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 681428d7b3dSmrg map_state->v_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; 682428d7b3dSmrg 683428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(pI915XvMC->msb_bo); 684428d7b3dSmrg} 685428d7b3dSmrg 686428d7b3dSmrgstatic void i915_mc_load_indirect_render_emit(XvMCContext * context) 687428d7b3dSmrg{ 688428d7b3dSmrg i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 689428d7b3dSmrg int mem_select; 690428d7b3dSmrg uint32_t load_indirect; 691428d7b3dSmrg BATCH_LOCALS; 692428d7b3dSmrg 693428d7b3dSmrg BEGIN_BATCH(5); 694428d7b3dSmrg load_indirect = OP_3D_LOAD_INDIRECT; 695428d7b3dSmrg load_indirect |= (BLOCK_SIS | BLOCK_MSB) << BLOCK_MASK_SHIFT; 696428d7b3dSmrg load_indirect |= 5 - 2; /* length */ 697428d7b3dSmrg 698428d7b3dSmrg if (pI915XvMC->use_phys_addr) 699428d7b3dSmrg mem_select = 0; /* use physical address */ 700428d7b3dSmrg else { 701428d7b3dSmrg load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR; 702428d7b3dSmrg mem_select = 1; /* use gfx address */ 703428d7b3dSmrg } 704428d7b3dSmrg OUT_BATCH(load_indirect); 705428d7b3dSmrg 706428d7b3dSmrg /* Static Indirect state buffer (dest buffer info) */ 707428d7b3dSmrg OUT_RELOC(pI915XvMC->sis_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 708428d7b3dSmrg STATE_VALID | STATE_FORCE); 709428d7b3dSmrg OUT_BATCH(16); /* 4 * 3 + 2 + 3 - 1 */ 710428d7b3dSmrg 711428d7b3dSmrg /* Map state buffer (reference buffer info) */ 712428d7b3dSmrg OUT_RELOC(pI915XvMC->msb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 713428d7b3dSmrg STATE_VALID | STATE_FORCE); 714428d7b3dSmrg OUT_BATCH(23); /* 3 * 8 - 1 */ 715428d7b3dSmrg ADVANCE_BATCH(); 716428d7b3dSmrg} 717428d7b3dSmrg 718428d7b3dSmrgstatic void i915_mc_mpeg_set_origin(XvMCContext * context, XvMCMacroBlock * mb) 719428d7b3dSmrg{ 720428d7b3dSmrg struct i915_3dmpeg_set_origin set_origin; 721428d7b3dSmrg 722428d7b3dSmrg /* 3DMPEG_SET_ORIGIN */ 723428d7b3dSmrg memset(&set_origin, 0, sizeof(set_origin)); 724428d7b3dSmrg set_origin.dw0.type = CMD_3D; 725428d7b3dSmrg set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN; 726428d7b3dSmrg set_origin.dw0.length = 0; 727428d7b3dSmrg set_origin.dw1.h_origin = mb->x; 728428d7b3dSmrg set_origin.dw1.v_origin = mb->y; 729428d7b3dSmrg 730428d7b3dSmrg intelBatchbufferData(&set_origin, sizeof(set_origin), 0); 731428d7b3dSmrg} 732428d7b3dSmrg 733428d7b3dSmrgstatic void i915_mc_mpeg_macroblock_ipicture(XvMCContext * context, 734428d7b3dSmrg XvMCMacroBlock * mb) 735428d7b3dSmrg{ 736428d7b3dSmrg struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture; 737428d7b3dSmrg 738428d7b3dSmrg /* 3DMPEG_MACROBLOCK_IPICTURE */ 739428d7b3dSmrg memset(¯oblock_ipicture, 0, sizeof(macroblock_ipicture)); 740428d7b3dSmrg macroblock_ipicture.dw0.type = CMD_3D; 741428d7b3dSmrg macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE; 742428d7b3dSmrg macroblock_ipicture.dw0.dct_type = 743428d7b3dSmrg (mb->dct_type == XVMC_DCT_TYPE_FIELD); 744428d7b3dSmrg 745428d7b3dSmrg intelBatchbufferData(¯oblock_ipicture, sizeof(macroblock_ipicture), 746428d7b3dSmrg 0); 747428d7b3dSmrg} 748428d7b3dSmrg 749428d7b3dSmrgstatic void i915_mc_mpeg_macroblock_1fbmv(XvMCContext * context, 750428d7b3dSmrg XvMCMacroBlock * mb) 751428d7b3dSmrg{ 752428d7b3dSmrg struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv; 753428d7b3dSmrg vector_t mv0[2]; 754428d7b3dSmrg 755428d7b3dSmrg /* 3DMPEG_MACROBLOCK(1fbmv) */ 756428d7b3dSmrg memset(¯oblock_1fbmv, 0, sizeof(macroblock_1fbmv)); 757428d7b3dSmrg macroblock_1fbmv.header.dw0.type = CMD_3D; 758428d7b3dSmrg macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; 759428d7b3dSmrg macroblock_1fbmv.header.dw0.length = 2; 760428d7b3dSmrg macroblock_1fbmv.header.dw1.mb_intra = 0; /* should be 0 */ 761428d7b3dSmrg macroblock_1fbmv.header.dw1.forward = 762428d7b3dSmrg ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); 763428d7b3dSmrg macroblock_1fbmv.header.dw1.backward = 764428d7b3dSmrg ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); 765428d7b3dSmrg macroblock_1fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ 766428d7b3dSmrg macroblock_1fbmv.header.dw1.dct_type = 767428d7b3dSmrg (mb->dct_type == XVMC_DCT_TYPE_FIELD); 768428d7b3dSmrg 769428d7b3dSmrg if (!(mb->coded_block_pattern & 0x3f)) 770428d7b3dSmrg macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; 771428d7b3dSmrg 772428d7b3dSmrg macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); 773428d7b3dSmrg macroblock_1fbmv.header.dw1.vertical_field_select = 774428d7b3dSmrg (mb->motion_vertical_field_select & 0x0f); 775428d7b3dSmrg macroblock_1fbmv.header.dw1.coded_block_pattern = 776428d7b3dSmrg mb->coded_block_pattern; 777428d7b3dSmrg macroblock_1fbmv.header.dw1.skipped_macroblocks = 0; 778428d7b3dSmrg 779428d7b3dSmrg mv0[0].component[0] = mb->PMV[0][0][0]; 780428d7b3dSmrg mv0[0].component[1] = mb->PMV[0][0][1]; 781428d7b3dSmrg mv0[1].component[0] = mb->PMV[0][1][0]; 782428d7b3dSmrg mv0[1].component[1] = mb->PMV[0][1][1]; 783428d7b3dSmrg 784428d7b3dSmrg macroblock_1fbmv.dw2 = mv0[0].v; 785428d7b3dSmrg macroblock_1fbmv.dw3 = mv0[1].v; 786428d7b3dSmrg 787428d7b3dSmrg intelBatchbufferData(¯oblock_1fbmv, sizeof(macroblock_1fbmv), 0); 788428d7b3dSmrg} 789428d7b3dSmrg 790428d7b3dSmrgstatic void i915_mc_mpeg_macroblock_2fbmv(XvMCContext * context, 791428d7b3dSmrg XvMCMacroBlock * mb, unsigned int ps) 792428d7b3dSmrg{ 793428d7b3dSmrg struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv; 794428d7b3dSmrg vector_t mv0[2]; 795428d7b3dSmrg vector_t mv1[2]; 796428d7b3dSmrg 797428d7b3dSmrg /* 3DMPEG_MACROBLOCK(2fbmv) */ 798428d7b3dSmrg memset(¯oblock_2fbmv, 0, sizeof(macroblock_2fbmv)); 799428d7b3dSmrg macroblock_2fbmv.header.dw0.type = CMD_3D; 800428d7b3dSmrg macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; 801428d7b3dSmrg macroblock_2fbmv.header.dw0.length = 4; 802428d7b3dSmrg macroblock_2fbmv.header.dw1.mb_intra = 0; /* should be 0 */ 803428d7b3dSmrg macroblock_2fbmv.header.dw1.forward = 804428d7b3dSmrg ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); 805428d7b3dSmrg macroblock_2fbmv.header.dw1.backward = 806428d7b3dSmrg ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); 807428d7b3dSmrg macroblock_2fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ 808428d7b3dSmrg macroblock_2fbmv.header.dw1.dct_type = 809428d7b3dSmrg (mb->dct_type == XVMC_DCT_TYPE_FIELD); 810428d7b3dSmrg 811428d7b3dSmrg if (!(mb->coded_block_pattern & 0x3f)) 812428d7b3dSmrg macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; 813428d7b3dSmrg 814428d7b3dSmrg macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); 815428d7b3dSmrg macroblock_2fbmv.header.dw1.vertical_field_select = 816428d7b3dSmrg (mb->motion_vertical_field_select & 0x0f); 817428d7b3dSmrg macroblock_2fbmv.header.dw1.coded_block_pattern = 818428d7b3dSmrg mb->coded_block_pattern; 819428d7b3dSmrg macroblock_2fbmv.header.dw1.skipped_macroblocks = 0; 820428d7b3dSmrg 821428d7b3dSmrg mv0[0].component[0] = mb->PMV[0][0][0]; 822428d7b3dSmrg mv0[0].component[1] = mb->PMV[0][0][1]; 823428d7b3dSmrg mv0[1].component[0] = mb->PMV[0][1][0]; 824428d7b3dSmrg mv0[1].component[1] = mb->PMV[0][1][1]; 825428d7b3dSmrg mv1[0].component[0] = mb->PMV[1][0][0]; 826428d7b3dSmrg mv1[0].component[1] = mb->PMV[1][0][1]; 827428d7b3dSmrg mv1[1].component[0] = mb->PMV[1][1][0]; 828428d7b3dSmrg mv1[1].component[1] = mb->PMV[1][1][1]; 829428d7b3dSmrg 830428d7b3dSmrg if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { 831428d7b3dSmrg if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) { 832428d7b3dSmrg mv0[0].component[1] = mb->PMV[0][0][1] >> 1; 833428d7b3dSmrg mv0[1].component[1] = mb->PMV[0][1][1] >> 1; 834428d7b3dSmrg mv1[0].component[1] = mb->PMV[1][0][1] >> 1; 835428d7b3dSmrg mv1[1].component[1] = mb->PMV[1][1][1] >> 1; 836428d7b3dSmrg } else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) { 837428d7b3dSmrg mv0[0].component[1] = mb->PMV[0][0][1] >> 1; 838428d7b3dSmrg mv0[1].component[1] = mb->PMV[0][1][1] >> 1; // MPEG2 MV[0][1] isn't used 839428d7b3dSmrg mv1[0].component[1] = mb->PMV[1][0][1] >> 1; 840428d7b3dSmrg mv1[1].component[1] = mb->PMV[1][1][1] >> 1; 841428d7b3dSmrg } 842428d7b3dSmrg } 843428d7b3dSmrg 844428d7b3dSmrg macroblock_2fbmv.dw2 = mv0[0].v; 845428d7b3dSmrg macroblock_2fbmv.dw3 = mv0[1].v; 846428d7b3dSmrg macroblock_2fbmv.dw4 = mv1[0].v; 847428d7b3dSmrg macroblock_2fbmv.dw5 = mv1[1].v; 848428d7b3dSmrg 849428d7b3dSmrg intelBatchbufferData(¯oblock_2fbmv, sizeof(macroblock_2fbmv), 0); 850428d7b3dSmrg} 851428d7b3dSmrg 852428d7b3dSmrgstatic int i915_xvmc_alloc_one_time_buffers(i915XvMCContext *pI915XvMC) 853428d7b3dSmrg{ 854428d7b3dSmrg pI915XvMC->ssb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 855428d7b3dSmrg "ssb", 856428d7b3dSmrg GTT_PAGE_SIZE, 857428d7b3dSmrg GTT_PAGE_SIZE); 858428d7b3dSmrg if (!pI915XvMC->ssb_bo) 859428d7b3dSmrg return 0; 860428d7b3dSmrg 861428d7b3dSmrg pI915XvMC->psp_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 862428d7b3dSmrg "psp", 863428d7b3dSmrg GTT_PAGE_SIZE, 864428d7b3dSmrg GTT_PAGE_SIZE); 865428d7b3dSmrg if (!pI915XvMC->psp_bo) 866428d7b3dSmrg return 0; 867428d7b3dSmrg 868428d7b3dSmrg pI915XvMC->psc_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 869428d7b3dSmrg "psc", 870428d7b3dSmrg GTT_PAGE_SIZE, 871428d7b3dSmrg GTT_PAGE_SIZE); 872428d7b3dSmrg if (!pI915XvMC->psc_bo) 873428d7b3dSmrg return 0; 874428d7b3dSmrg 875428d7b3dSmrg return 1; 876428d7b3dSmrg} 877428d7b3dSmrg 878428d7b3dSmrgstatic void i915_xvmc_free_one_time_buffers(i915XvMCContext *pI915XvMC) 879428d7b3dSmrg{ 880428d7b3dSmrg drm_intel_bo_unreference(pI915XvMC->ssb_bo); 881428d7b3dSmrg drm_intel_bo_unreference(pI915XvMC->psp_bo); 882428d7b3dSmrg drm_intel_bo_unreference(pI915XvMC->psc_bo); 883428d7b3dSmrg} 884428d7b3dSmrg 885428d7b3dSmrg/* 886428d7b3dSmrg * Function: i915_release_resource 887428d7b3dSmrg */ 888428d7b3dSmrgstatic void i915_release_resource(Display * display, XvMCContext * context) 889428d7b3dSmrg{ 890428d7b3dSmrg i915XvMCContext *pI915XvMC; 891428d7b3dSmrg 892428d7b3dSmrg if (!(pI915XvMC = context->privData)) 893428d7b3dSmrg return; 894428d7b3dSmrg 895428d7b3dSmrg i915_xvmc_free_one_time_buffers(pI915XvMC); 896428d7b3dSmrg 897428d7b3dSmrg free(pI915XvMC); 898428d7b3dSmrg context->privData = NULL; 899428d7b3dSmrg} 900428d7b3dSmrg 901428d7b3dSmrgstatic Status i915_xvmc_mc_create_context(Display * display, 902428d7b3dSmrg XvMCContext * context, int priv_count, 903428d7b3dSmrg CARD32 * priv_data) 904428d7b3dSmrg{ 905428d7b3dSmrg i915XvMCContext *pI915XvMC = NULL; 906428d7b3dSmrg struct intel_xvmc_hw_context *tmpComm = NULL; 907428d7b3dSmrg 908428d7b3dSmrg if (priv_count != (sizeof(struct intel_xvmc_hw_context) >> 2)) { 909428d7b3dSmrg XVMC_ERR 910428d7b3dSmrg ("_xvmc_create_context() returned incorrect data size!"); 911428d7b3dSmrg XVMC_INFO("\tExpected %d, got %d", 912428d7b3dSmrg (int)(sizeof(struct intel_xvmc_hw_context) >> 2), 913428d7b3dSmrg priv_count); 914428d7b3dSmrg _xvmc_destroy_context(display, context); 915428d7b3dSmrg XFree(priv_data); 916428d7b3dSmrg context->privData = NULL; 917428d7b3dSmrg return BadValue; 918428d7b3dSmrg } 919428d7b3dSmrg 920428d7b3dSmrg context->privData = (void *)calloc(1, sizeof(i915XvMCContext)); 921428d7b3dSmrg if (!context->privData) { 922428d7b3dSmrg XVMC_ERR("Unable to allocate resources for XvMC context."); 923428d7b3dSmrg return BadAlloc; 924428d7b3dSmrg } 925428d7b3dSmrg pI915XvMC = (i915XvMCContext *) context->privData; 926428d7b3dSmrg 927428d7b3dSmrg tmpComm = (struct intel_xvmc_hw_context *) priv_data; 928428d7b3dSmrg pI915XvMC->use_phys_addr = tmpComm->i915.use_phys_addr; 929428d7b3dSmrg pI915XvMC->comm.surface_bo_size = SIZE_YUV420(context->width, 930428d7b3dSmrg context->height); 931428d7b3dSmrg 932428d7b3dSmrg /* Must free the private data we were passed from X */ 933428d7b3dSmrg XFree(priv_data); 934428d7b3dSmrg priv_data = NULL; 935428d7b3dSmrg 936428d7b3dSmrg if (!i915_xvmc_alloc_one_time_buffers(pI915XvMC)) 937428d7b3dSmrg goto free_one_time_buffers; 938428d7b3dSmrg 939428d7b3dSmrg /* Initialize private context values */ 940428d7b3dSmrg pI915XvMC->yStride = STRIDE(context->width); 941428d7b3dSmrg pI915XvMC->uvStride = STRIDE(context->width >> 1); 942428d7b3dSmrg 943428d7b3dSmrg /* pre-init state buffers */ 944428d7b3dSmrg i915_mc_one_time_context_init(context); 945428d7b3dSmrg 946428d7b3dSmrg return Success; 947428d7b3dSmrg 948428d7b3dSmrgfree_one_time_buffers: 949428d7b3dSmrg i915_xvmc_free_one_time_buffers(pI915XvMC); 950428d7b3dSmrg free(pI915XvMC); 951428d7b3dSmrg context->privData = NULL; 952428d7b3dSmrg return BadAlloc; 953428d7b3dSmrg} 954428d7b3dSmrg 955428d7b3dSmrgstatic int i915_xvmc_mc_destroy_context(Display * display, 956428d7b3dSmrg XvMCContext * context) 957428d7b3dSmrg{ 958428d7b3dSmrg i915XvMCContext *pI915XvMC; 959428d7b3dSmrg 960428d7b3dSmrg if (!(pI915XvMC = context->privData)) 961428d7b3dSmrg return XvMCBadContext; 962428d7b3dSmrg 963428d7b3dSmrg /* Pass Control to the X server to destroy the drm_context_t */ 964428d7b3dSmrg i915_release_resource(display, context); 965428d7b3dSmrg 966428d7b3dSmrg return Success; 967428d7b3dSmrg} 968428d7b3dSmrg 969428d7b3dSmrgstatic int i915_xvmc_alloc_render_state_buffers(i915XvMCContext *pI915XvMC) 970428d7b3dSmrg{ 971428d7b3dSmrg pI915XvMC->sis_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 972428d7b3dSmrg "sis", 973428d7b3dSmrg GTT_PAGE_SIZE, 974428d7b3dSmrg GTT_PAGE_SIZE); 975428d7b3dSmrg if (!pI915XvMC->sis_bo) 976428d7b3dSmrg return 0; 977428d7b3dSmrg 978428d7b3dSmrg pI915XvMC->msb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 979428d7b3dSmrg "msb", 980428d7b3dSmrg GTT_PAGE_SIZE, 981428d7b3dSmrg GTT_PAGE_SIZE); 982428d7b3dSmrg if (!pI915XvMC->msb_bo) 983428d7b3dSmrg return 0; 984428d7b3dSmrg 985428d7b3dSmrg pI915XvMC->corrdata_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 986428d7b3dSmrg "corrdata", 987428d7b3dSmrg CORRDATA_SIZE, 988428d7b3dSmrg GTT_PAGE_SIZE); 989428d7b3dSmrg if (!pI915XvMC->corrdata_bo) 990428d7b3dSmrg return 0; 991428d7b3dSmrg 992428d7b3dSmrg return 1; 993428d7b3dSmrg} 994428d7b3dSmrg 995428d7b3dSmrgstatic void i915_xvmc_free_render_state_buffers(i915XvMCContext *pI915XvMC) 996428d7b3dSmrg{ 997428d7b3dSmrg drm_intel_bo_unreference(pI915XvMC->sis_bo); 998428d7b3dSmrg drm_intel_bo_unreference(pI915XvMC->msb_bo); 999428d7b3dSmrg drm_intel_bo_unreference(pI915XvMC->corrdata_bo); 1000428d7b3dSmrg} 1001428d7b3dSmrg 1002428d7b3dSmrgstatic int i915_xvmc_mc_render_surface(Display * display, XvMCContext * context, 1003428d7b3dSmrg unsigned int picture_structure, 1004428d7b3dSmrg XvMCSurface * target_surface, 1005428d7b3dSmrg XvMCSurface * past_surface, 1006428d7b3dSmrg XvMCSurface * future_surface, 1007428d7b3dSmrg unsigned int flags, 1008428d7b3dSmrg unsigned int num_macroblocks, 1009428d7b3dSmrg unsigned int first_macroblock, 1010428d7b3dSmrg XvMCMacroBlockArray * macroblock_array, 1011428d7b3dSmrg XvMCBlockArray * blocks) 1012428d7b3dSmrg{ 1013428d7b3dSmrg int i; 1014428d7b3dSmrg int picture_coding_type = MPEG_I_PICTURE; 1015428d7b3dSmrg /* correction data buffer */ 1016428d7b3dSmrg char *corrdata_ptr; 1017428d7b3dSmrg int corrdata_size = 0; 1018428d7b3dSmrg 1019428d7b3dSmrg /* Block Pointer */ 1020428d7b3dSmrg short *block_ptr; 1021428d7b3dSmrg /* Current Macroblock Pointer */ 1022428d7b3dSmrg XvMCMacroBlock *mb; 1023428d7b3dSmrg 1024428d7b3dSmrg intel_xvmc_context_ptr intel_ctx; 1025428d7b3dSmrg 1026428d7b3dSmrg struct intel_xvmc_surface *privTarget = NULL; 1027428d7b3dSmrg struct intel_xvmc_surface *privFuture = NULL; 1028428d7b3dSmrg struct intel_xvmc_surface *privPast = NULL; 1029428d7b3dSmrg i915XvMCContext *pI915XvMC = NULL; 1030428d7b3dSmrg 1031428d7b3dSmrg /* Check Parameters for validity */ 1032428d7b3dSmrg if (!display || !context || !target_surface) { 1033428d7b3dSmrg XVMC_ERR("Invalid Display, Context or Target!"); 1034428d7b3dSmrg return BadValue; 1035428d7b3dSmrg } 1036428d7b3dSmrg 1037428d7b3dSmrg if (!num_macroblocks) 1038428d7b3dSmrg return Success; 1039428d7b3dSmrg 1040428d7b3dSmrg if (!macroblock_array || !blocks) { 1041428d7b3dSmrg XVMC_ERR("Invalid block data!"); 1042428d7b3dSmrg return BadValue; 1043428d7b3dSmrg } 1044428d7b3dSmrg 1045428d7b3dSmrg if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) { 1046428d7b3dSmrg XVMC_ERR("Too many macroblocks requested for MB array size."); 1047428d7b3dSmrg return BadValue; 1048428d7b3dSmrg } 1049428d7b3dSmrg 1050428d7b3dSmrg if (!(pI915XvMC = context->privData)) 1051428d7b3dSmrg return XvMCBadContext; 1052428d7b3dSmrg 1053428d7b3dSmrg if (!(privTarget = target_surface->privData)) 1054428d7b3dSmrg return XvMCBadSurface; 1055428d7b3dSmrg 1056428d7b3dSmrg if (!i915_xvmc_alloc_render_state_buffers(pI915XvMC)) 1057428d7b3dSmrg return BadAlloc; 1058428d7b3dSmrg 1059428d7b3dSmrg intel_ctx = context->privData; 1060428d7b3dSmrg if (!intel_ctx) { 1061428d7b3dSmrg XVMC_ERR("Can't find intel xvmc context\n"); 1062428d7b3dSmrg return BadValue; 1063428d7b3dSmrg } 1064428d7b3dSmrg 1065428d7b3dSmrg /* P Frame Test */ 1066428d7b3dSmrg if (!past_surface) { 1067428d7b3dSmrg /* Just to avoid some ifs later. */ 1068428d7b3dSmrg privPast = privTarget; 1069428d7b3dSmrg } else { 1070428d7b3dSmrg if (!(privPast = past_surface->privData)) { 1071428d7b3dSmrg return XvMCBadSurface; 1072428d7b3dSmrg } 1073428d7b3dSmrg picture_coding_type = MPEG_P_PICTURE; 1074428d7b3dSmrg } 1075428d7b3dSmrg 1076428d7b3dSmrg /* B Frame Test */ 1077428d7b3dSmrg if (!future_surface) { 1078428d7b3dSmrg privFuture = privPast; // privTarget; 1079428d7b3dSmrg } else { 1080428d7b3dSmrg if (!past_surface) { 1081428d7b3dSmrg XVMC_ERR("No Past Surface!"); 1082428d7b3dSmrg return BadValue; 1083428d7b3dSmrg } 1084428d7b3dSmrg 1085428d7b3dSmrg if (!(privFuture = future_surface->privData)) { 1086428d7b3dSmrg XVMC_ERR("Invalid Future Surface!"); 1087428d7b3dSmrg return XvMCBadSurface; 1088428d7b3dSmrg } 1089428d7b3dSmrg 1090428d7b3dSmrg picture_coding_type = MPEG_B_PICTURE; 1091428d7b3dSmrg } 1092428d7b3dSmrg 1093428d7b3dSmrg LOCK_HARDWARE(intel_ctx->hw_context); 1094428d7b3dSmrg drm_intel_gem_bo_map_gtt(pI915XvMC->corrdata_bo); 1095428d7b3dSmrg corrdata_ptr = pI915XvMC->corrdata_bo->virtual; 1096428d7b3dSmrg corrdata_size = 0; 1097428d7b3dSmrg 1098428d7b3dSmrg for (i = first_macroblock; i < (num_macroblocks + first_macroblock); 1099428d7b3dSmrg i++) { 1100428d7b3dSmrg int bspm = 0; 1101428d7b3dSmrg mb = ¯oblock_array->macro_blocks[i]; 1102428d7b3dSmrg block_ptr = &(blocks->blocks[mb->index << 6]); 1103428d7b3dSmrg 1104428d7b3dSmrg /* Lockup can happen if the coordinates are too far out of range */ 1105428d7b3dSmrg if (mb->x > (target_surface->width >> 4)) { 1106428d7b3dSmrg mb->x = 0; 1107428d7b3dSmrg XVMC_INFO("reset x"); 1108428d7b3dSmrg } 1109428d7b3dSmrg 1110428d7b3dSmrg if (mb->y > (target_surface->height >> 4)) { 1111428d7b3dSmrg mb->y = 0; 1112428d7b3dSmrg XVMC_INFO("reset y"); 1113428d7b3dSmrg } 1114428d7b3dSmrg 1115428d7b3dSmrg /* Catch no pattern case */ 1116428d7b3dSmrg if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) && 1117428d7b3dSmrg !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) && 1118428d7b3dSmrg mb->coded_block_pattern) { 1119428d7b3dSmrg mb->coded_block_pattern = 0; 1120428d7b3dSmrg XVMC_INFO("no coded blocks present!"); 1121428d7b3dSmrg } 1122428d7b3dSmrg 1123428d7b3dSmrg bspm = mb_bytes_420[mb->coded_block_pattern]; 1124428d7b3dSmrg 1125428d7b3dSmrg if (!bspm) 1126428d7b3dSmrg continue; 1127428d7b3dSmrg 1128428d7b3dSmrg corrdata_size += bspm; 1129428d7b3dSmrg 1130428d7b3dSmrg if (corrdata_size > CORRDATA_SIZE) { 1131428d7b3dSmrg XVMC_ERR("correction data buffer overflow."); 1132428d7b3dSmrg break; 1133428d7b3dSmrg } 1134428d7b3dSmrg memcpy(corrdata_ptr, block_ptr, bspm); 1135428d7b3dSmrg corrdata_ptr += bspm; 1136428d7b3dSmrg } 1137428d7b3dSmrg 1138428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(pI915XvMC->corrdata_bo); 1139428d7b3dSmrg 1140428d7b3dSmrg // i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB 1141428d7b3dSmrg // | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC); 1142428d7b3dSmrg 1143428d7b3dSmrg i915_mc_one_time_state_emit(context); 1144428d7b3dSmrg 1145428d7b3dSmrg i915_mc_static_indirect_state_set(context, target_surface, 1146428d7b3dSmrg picture_structure, flags, 1147428d7b3dSmrg picture_coding_type); 1148428d7b3dSmrg /* setup reference surfaces */ 1149428d7b3dSmrg i915_mc_map_state_set(context, privPast, privFuture); 1150428d7b3dSmrg 1151428d7b3dSmrg i915_mc_load_indirect_render_emit(context); 1152428d7b3dSmrg 1153428d7b3dSmrg i915_mc_mpeg_set_origin(context, 1154428d7b3dSmrg ¯oblock_array->macro_blocks 1155428d7b3dSmrg [first_macroblock]); 1156428d7b3dSmrg 1157428d7b3dSmrg for (i = first_macroblock; i < (num_macroblocks + first_macroblock); 1158428d7b3dSmrg i++) { 1159428d7b3dSmrg mb = ¯oblock_array->macro_blocks[i]; 1160428d7b3dSmrg 1161428d7b3dSmrg /* Intra Blocks */ 1162428d7b3dSmrg if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 1163428d7b3dSmrg i915_mc_mpeg_macroblock_ipicture(context, mb); 1164428d7b3dSmrg } else if ((picture_structure & XVMC_FRAME_PICTURE) == 1165428d7b3dSmrg XVMC_FRAME_PICTURE) { 1166428d7b3dSmrg /* Frame Picture */ 1167428d7b3dSmrg switch (mb->motion_type & 3) { 1168428d7b3dSmrg case XVMC_PREDICTION_FIELD: /* Field Based */ 1169428d7b3dSmrg i915_mc_mpeg_macroblock_2fbmv(context, mb, 1170428d7b3dSmrg picture_structure); 1171428d7b3dSmrg break; 1172428d7b3dSmrg 1173428d7b3dSmrg case XVMC_PREDICTION_FRAME: /* Frame Based */ 1174428d7b3dSmrg i915_mc_mpeg_macroblock_1fbmv(context, mb); 1175428d7b3dSmrg break; 1176428d7b3dSmrg 1177428d7b3dSmrg case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ 1178428d7b3dSmrg i915_mc_mpeg_macroblock_2fbmv(context, mb, 1179428d7b3dSmrg picture_structure); 1180428d7b3dSmrg break; 1181428d7b3dSmrg 1182428d7b3dSmrg default: /* No Motion Type */ 1183428d7b3dSmrg XVMC_ERR 1184428d7b3dSmrg ("Invalid Macroblock Parameters found."); 1185428d7b3dSmrg break; 1186428d7b3dSmrg } 1187428d7b3dSmrg } else { /* Field Picture */ 1188428d7b3dSmrg switch (mb->motion_type & 3) { 1189428d7b3dSmrg case XVMC_PREDICTION_FIELD: /* Field Based */ 1190428d7b3dSmrg i915_mc_mpeg_macroblock_1fbmv(context, mb); 1191428d7b3dSmrg break; 1192428d7b3dSmrg 1193428d7b3dSmrg case XVMC_PREDICTION_16x8: /* 16x8 MC */ 1194428d7b3dSmrg i915_mc_mpeg_macroblock_2fbmv(context, mb, 1195428d7b3dSmrg picture_structure); 1196428d7b3dSmrg break; 1197428d7b3dSmrg 1198428d7b3dSmrg case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ 1199428d7b3dSmrg i915_mc_mpeg_macroblock_1fbmv(context, mb); 1200428d7b3dSmrg break; 1201428d7b3dSmrg 1202428d7b3dSmrg default: /* No Motion Type */ 1203428d7b3dSmrg XVMC_ERR 1204428d7b3dSmrg ("Invalid Macroblock Parameters found."); 1205428d7b3dSmrg break; 1206428d7b3dSmrg } 1207428d7b3dSmrg } 1208428d7b3dSmrg } 1209428d7b3dSmrg 1210428d7b3dSmrg intelFlushBatch(); 1211428d7b3dSmrg 1212428d7b3dSmrg i915_xvmc_free_render_state_buffers(pI915XvMC); 1213428d7b3dSmrg 1214428d7b3dSmrg UNLOCK_HARDWARE(intel_ctx->hw_context); 1215428d7b3dSmrg return 0; 1216428d7b3dSmrg} 1217428d7b3dSmrg 1218428d7b3dSmrgstruct _intel_xvmc_driver i915_xvmc_mc_driver = { 1219428d7b3dSmrg .type = XVMC_I915_MPEG2_MC, 1220428d7b3dSmrg .num_ctx = 0, 1221428d7b3dSmrg .ctx_list = NULL, 1222428d7b3dSmrg .create_context = i915_xvmc_mc_create_context, 1223428d7b3dSmrg .destroy_context = i915_xvmc_mc_destroy_context, 1224428d7b3dSmrg .render_surface = i915_xvmc_mc_render_surface, 1225428d7b3dSmrg}; 1226