i915_xvmc.c revision 42542f5f
1/* 2 * Copyright © 2006 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Xiang Haihao <haihao.xiang@intel.com> 25 * 26 */ 27 28#include <sys/ioctl.h> 29 30#include "i915_xvmc.h" 31#include "i915_structs.h" 32#include "i915_program.h" 33 34#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) 35 36#define STRIDE(w) (ALIGN((w), 1024)) 37#define SIZE_Y420(w, h) (h * STRIDE(w)) 38#define SIZE_UV420(w, h) ((h >> 1) * STRIDE(w >> 1)) 39#define SIZE_YUV420(w, h) (SIZE_Y420(w,h) + SIZE_UV420(w,h) * 2) 40#define UOFFSET(context) (SIZE_Y420(context->width, context->height)) 41#define VOFFSET(context) (SIZE_Y420(context->width, context->height) + \ 42 SIZE_UV420(context->width, context->height)) 43 44typedef union { 45 int16_t component[2]; 46 int32_t v; 47} vector_t; 48 49static void i915_inst_arith(unsigned int *inst, 50 unsigned int op, 51 unsigned int dest, 52 unsigned int mask, 53 unsigned int saturate, 54 unsigned int src0, unsigned int src1, 55 unsigned int src2) 56{ 57 dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); 58 *inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); 59 inst++; 60 *inst = (A1_SRC0(src0) | A1_SRC1(src1)); 61 inst++; 62 *inst = (A2_SRC1(src1) | A2_SRC2(src2)); 63} 64 65static void i915_inst_decl(unsigned int *inst, 66 unsigned int type, 67 unsigned int nr, unsigned int d0_flags) 68{ 69 unsigned int reg = UREG(type, nr); 70 71 *inst = (D0_DCL | D0_DEST(reg) | d0_flags); 72 inst++; 73 *inst = D1_MBZ; 74 inst++; 75 *inst = D2_MBZ; 76} 77 78static void i915_inst_texld(unsigned int *inst, 79 unsigned int op, 80 unsigned int dest, 81 unsigned int coord, unsigned int sampler) 82{ 83 dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); 84 *inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler)); 85 inst++; 86 *inst = T1_ADDRESS_REG(coord); 87 inst++; 88 *inst = T2_MBZ; 89} 90 91static void i915_mc_one_time_context_init(XvMCContext * context) 92{ 93 unsigned int dest, src0, src1, src2; 94 i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 95 int i; 96 struct i915_3dstate_sampler_state *sampler_state; 97 struct i915_3dstate_pixel_shader_program *pixel_shader_program; 98 struct i915_3dstate_pixel_shader_constants *pixel_shader_constants; 99 100 /* sampler static state */ 101 drm_intel_gem_bo_map_gtt(pI915XvMC->ssb_bo); 102 sampler_state = pI915XvMC->ssb_bo->virtual; 103 104 memset(sampler_state, 0, sizeof(*sampler_state)); 105 sampler_state->dw0.type = CMD_3D; 106 sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE; 107 sampler_state->dw0.length = 6; 108 sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1; 109 110 sampler_state->sampler0.ts0.reverse_gamma = 0; 111 sampler_state->sampler0.ts0.planar2packet = 0; 112 sampler_state->sampler0.ts0.color_conversion = 0; 113 sampler_state->sampler0.ts0.chromakey_index = 0; 114 sampler_state->sampler0.ts0.base_level = 0; 115 sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE; /* NONE */ 116 sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ 117 sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ 118 sampler_state->sampler0.ts0.lod_bias = 0; /* 0.0 */ 119 sampler_state->sampler0.ts0.shadow_enable = 0; 120 sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2; 121 sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS; 122 sampler_state->sampler0.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ 123 sampler_state->sampler0.ts1.kill_pixel = 0; 124 sampler_state->sampler0.ts1.keyed_texture_filter = 0; 125 sampler_state->sampler0.ts1.chromakey_enable = 0; 126 sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP; 127 sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP; 128 sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP; 129 sampler_state->sampler0.ts1.normalized_coor = 0; 130 sampler_state->sampler0.ts1.map_index = 0; 131 sampler_state->sampler0.ts1.east_deinterlacer = 0; 132 sampler_state->sampler0.ts2.default_color = 0; 133 134 sampler_state->sampler1.ts0.reverse_gamma = 0; 135 sampler_state->sampler1.ts0.planar2packet = 0; 136 sampler_state->sampler1.ts0.color_conversion = 0; 137 sampler_state->sampler1.ts0.chromakey_index = 0; 138 sampler_state->sampler1.ts0.base_level = 0; 139 sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE; /* NONE */ 140 sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ 141 sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ 142 sampler_state->sampler1.ts0.lod_bias = 0; /* 0.0 */ 143 sampler_state->sampler1.ts0.shadow_enable = 0; 144 sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2; 145 sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS; 146 sampler_state->sampler1.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ 147 sampler_state->sampler1.ts1.kill_pixel = 0; 148 sampler_state->sampler1.ts1.keyed_texture_filter = 0; 149 sampler_state->sampler1.ts1.chromakey_enable = 0; 150 sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP; 151 sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP; 152 sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP; 153 sampler_state->sampler1.ts1.normalized_coor = 0; 154 sampler_state->sampler1.ts1.map_index = 1; 155 sampler_state->sampler1.ts1.east_deinterlacer = 0; 156 sampler_state->sampler1.ts2.default_color = 0; 157 158 drm_intel_gem_bo_unmap_gtt(pI915XvMC->ssb_bo); 159 160 /* pixel shader static state */ 161 drm_intel_gem_bo_map_gtt(pI915XvMC->psp_bo); 162 pixel_shader_program = pI915XvMC->psp_bo->virtual; 163 164 memset(pixel_shader_program, 0, sizeof(*pixel_shader_program)); 165 pixel_shader_program->shader0.type = CMD_3D; 166 pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 167 pixel_shader_program->shader0.retain = 1; 168 pixel_shader_program->shader0.length = 2; /* 1 inst */ 169 i = 0; 170 171 dest = UREG(REG_TYPE_OC, 0); 172 src0 = UREG(REG_TYPE_CONST, 0); 173 src1 = 0; 174 src2 = 0; 175 i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV, 176 dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 177 src2); 178 179 pixel_shader_program->shader1.type = CMD_3D; 180 pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 181 pixel_shader_program->shader1.retain = 1; 182 pixel_shader_program->shader1.length = 14; /* 5 inst */ 183 i = 0; 184 /* dcl t0.xy */ 185 i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0, 186 D0_CHANNEL_XY); 187 i += 3; 188 /* dcl t1.xy */ 189 i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1, 190 D0_CHANNEL_XY); 191 /* dcl_2D s0 */ 192 i += 3; 193 i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0, 194 D0_SAMPLE_TYPE_2D); 195 /* texld r0, t0, s0 */ 196 i += 3; 197 dest = UREG(REG_TYPE_R, 0); 198 src0 = UREG(REG_TYPE_T, 0); /* COORD */ 199 src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ 200 i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0, 201 src1); 202 /* mov oC, r0 */ 203 i += 3; 204 dest = UREG(REG_TYPE_OC, 0); 205 src0 = UREG(REG_TYPE_R, 0); 206 src1 = src2 = 0; 207 i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest, 208 A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 209 src2); 210 211 pixel_shader_program->shader2.type = CMD_3D; 212 pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 213 pixel_shader_program->shader2.retain = 1; 214 pixel_shader_program->shader2.length = 14; /* 5 inst */ 215 i = 0; 216 /* dcl t2.xy */ 217 i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2, 218 D0_CHANNEL_XY); 219 /* dcl t3.xy */ 220 i += 3; 221 i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3, 222 D0_CHANNEL_XY); 223 /* dcl_2D s1 */ 224 i += 3; 225 i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1, 226 D0_SAMPLE_TYPE_2D); 227 /* texld r0, t2, s1 */ 228 i += 3; 229 dest = UREG(REG_TYPE_R, 0); 230 src0 = UREG(REG_TYPE_T, 2); /* COORD */ 231 src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ 232 i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0, 233 src1); 234 /* mov oC, r0 */ 235 i += 3; 236 dest = UREG(REG_TYPE_OC, 0); 237 src0 = UREG(REG_TYPE_R, 0); 238 src1 = src2 = 0; 239 i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest, 240 A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 241 src2); 242 243 /* Shader 3 */ 244 pixel_shader_program->shader3.type = CMD_3D; 245 pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; 246 pixel_shader_program->shader3.retain = 1; 247 pixel_shader_program->shader3.length = 29; /* 10 inst */ 248 i = 0; 249 /* dcl t0.xy */ 250 i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0, 251 D0_CHANNEL_XY); 252 /* dcl t1.xy */ 253 i += 3; 254 i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1, 255 D0_CHANNEL_XY); 256 /* dcl t2.xy */ 257 i += 3; 258 i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2, 259 D0_CHANNEL_XY); 260 /* dcl t3.xy */ 261 i += 3; 262 i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3, 263 D0_CHANNEL_XY); 264 /* dcl_2D s0 */ 265 i += 3; 266 i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0, 267 D0_SAMPLE_TYPE_2D); 268 /* dcl_2D s1 */ 269 i += 3; 270 i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1, 271 D0_SAMPLE_TYPE_2D); 272 /* texld r0, t0, s0 */ 273 i += 3; 274 dest = UREG(REG_TYPE_R, 0); 275 src0 = UREG(REG_TYPE_T, 0); /* COORD */ 276 src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ 277 i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0, 278 src1); 279 /* texld r1, t2, s1 */ 280 i += 3; 281 dest = UREG(REG_TYPE_R, 1); 282 src0 = UREG(REG_TYPE_T, 2); /* COORD */ 283 src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ 284 i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0, 285 src1); 286 /* add r0, r0, r1 */ 287 i += 3; 288 dest = UREG(REG_TYPE_R, 0); 289 src0 = UREG(REG_TYPE_R, 0); 290 src1 = UREG(REG_TYPE_R, 1); 291 src2 = 0; 292 i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest, 293 A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */ , src0, 294 src1, src2); 295 /* mul oC, r0, c0 */ 296 i += 3; 297 dest = UREG(REG_TYPE_OC, 0); 298 src0 = UREG(REG_TYPE_R, 0); 299 src1 = UREG(REG_TYPE_CONST, 0); 300 src2 = 0; 301 i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest, 302 A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, 303 src2); 304 305 drm_intel_gem_bo_unmap_gtt(pI915XvMC->psp_bo); 306 307 /* pixel shader contant static state */ 308 drm_intel_gem_bo_map_gtt(pI915XvMC->psc_bo); 309 pixel_shader_constants = pI915XvMC->psc_bo->virtual; 310 311 memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants)); 312 pixel_shader_constants->dw0.type = CMD_3D; 313 pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS; 314 pixel_shader_constants->dw0.length = 4; 315 pixel_shader_constants->dw1.reg_mask = REG_CR0; 316 pixel_shader_constants->value.x = 0.5; 317 pixel_shader_constants->value.y = 0.5; 318 pixel_shader_constants->value.z = 0.5; 319 pixel_shader_constants->value.w = 0.5; 320 321 drm_intel_gem_bo_unmap_gtt(pI915XvMC->psc_bo); 322} 323 324static void i915_mc_one_time_state_emit(XvMCContext * context) 325{ 326 i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 327 uint32_t load_state_immediate_1, load_indirect, s3_dword, s6_dword; 328 int mem_select; 329 BATCH_LOCALS; 330 331 /* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */ 332 BEGIN_BATCH(3 + 8); 333 load_state_immediate_1 = OP_3D_LOAD_STATE_IMMEDIATE_1; 334 load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S3; 335 load_state_immediate_1 |= OP_3D_LOAD_STATE_IMM_LOAD_S6; 336 load_state_immediate_1 |= 3 - 2; /* length */ 337 OUT_BATCH(load_state_immediate_1); 338 339 s3_dword = S3_SET0_PCD | S3_SET1_PCD | 340 S3_SET2_PCD | S3_SET3_PCD | 341 S3_SET4_PCD | S3_SET5_PCD | 342 S3_SET6_PCD | S3_SET7_PCD; 343 OUT_BATCH(s3_dword); 344 345 s6_dword = S6_COLOR_BUFFER_WRITE | S6_DEPTH_TEST_ENABLE; 346 s6_dword |= 1 << S6_SRC_BLEND_FACTOR_SHIFT; 347 s6_dword |= 1 << S6_DST_BLEND_FACTOR_SHIFT; 348 OUT_BATCH(s6_dword); 349 350 /* 3DSTATE_LOAD_INDIRECT */ 351 load_indirect = OP_3D_LOAD_INDIRECT; 352 load_indirect |= (BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC) 353 << BLOCK_MASK_SHIFT; 354 load_indirect |= 8 - 2; /* length */ 355 356 if (pI915XvMC->use_phys_addr) 357 mem_select = 0; /* use physical address */ 358 else { 359 load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR; 360 mem_select = 1; /* use gfx address */ 361 } 362 363 OUT_BATCH(load_indirect); 364 365 /* Dynamic indirect state buffer */ 366 OUT_BATCH(0); /* no dynamic indirect state */ 367 368 /* Sample state buffer */ 369 OUT_RELOC(pI915XvMC->ssb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 370 STATE_VALID | STATE_FORCE); 371 OUT_BATCH(7); /* 8 - 1 */ 372 373 /* Pixel shader program buffer */ 374 OUT_RELOC(pI915XvMC->psp_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 375 STATE_VALID | STATE_FORCE); 376 OUT_BATCH(66); /* 4 + 16 + 16 + 31 - 1 */ 377 378 /* Pixel shader constant buffer */ 379 OUT_RELOC(pI915XvMC->psc_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 380 STATE_VALID | STATE_FORCE); 381 OUT_BATCH(5); /* 6 - 1 */ 382 ADVANCE_BATCH(); 383} 384 385static void i915_mc_static_indirect_state_set(XvMCContext * context, 386 XvMCSurface * dest, 387 unsigned int picture_structure, 388 unsigned int flags, 389 unsigned int picture_coding_type) 390{ 391 i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 392 struct intel_xvmc_surface *intel_surf = dest->privData; 393 struct i915_mc_static_indirect_state_buffer *buffer_info; 394 395 drm_intel_gem_bo_map_gtt(pI915XvMC->sis_bo); 396 buffer_info = pI915XvMC->sis_bo->virtual; 397 398 memset(buffer_info, 0, sizeof(*buffer_info)); 399 400 /* dest Y */ 401 buffer_info->dest_y.dw0.type = CMD_3D; 402 buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 403 buffer_info->dest_y.dw0.length = 1; 404 buffer_info->dest_y.dw1.aux_id = 0; 405 buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK; 406 buffer_info->dest_y.dw1.fence_regs = 0; /* disabled *//* FIXME: tiled y for performance */ 407 buffer_info->dest_y.dw1.tiled_surface = 0; /* linear */ 408 buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR; 409 buffer_info->dest_y.dw1.pitch = (pI915XvMC->yStride >> 2); /* in DWords */ 410 buffer_info->dest_y.dw2.base_address = intel_surf->bo->offset >> 2; /* starting DWORD address */ 411 drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 412 offsetof(typeof(*buffer_info),dest_y.dw2), 413 intel_surf->bo, 0, 414 I915_GEM_DOMAIN_RENDER, 415 I915_GEM_DOMAIN_RENDER); 416 417 /* dest U */ 418 buffer_info->dest_u.dw0.type = CMD_3D; 419 buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 420 buffer_info->dest_u.dw0.length = 1; 421 buffer_info->dest_u.dw1.aux_id = 0; 422 buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX; 423 buffer_info->dest_u.dw1.fence_regs = 0; 424 buffer_info->dest_u.dw1.tiled_surface = 0; 425 buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR; 426 buffer_info->dest_u.dw1.pitch = (pI915XvMC->uvStride >> 2); /* in DWords */ 427 buffer_info->dest_u.dw2.base_address = 428 (intel_surf->bo->offset + UOFFSET(context)) >> 2; 429 drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 430 offsetof(typeof(*buffer_info),dest_u.dw2), 431 intel_surf->bo, UOFFSET(context), 432 I915_GEM_DOMAIN_RENDER, 433 I915_GEM_DOMAIN_RENDER); 434 435 /* dest V */ 436 buffer_info->dest_v.dw0.type = CMD_3D; 437 buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 438 buffer_info->dest_v.dw0.length = 1; 439 buffer_info->dest_v.dw1.aux_id = 1; 440 buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX; 441 buffer_info->dest_v.dw1.fence_regs = 0; 442 buffer_info->dest_v.dw1.tiled_surface = 0; 443 buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR; 444 buffer_info->dest_v.dw1.pitch = (pI915XvMC->uvStride >> 2); /* in Dwords */ 445 buffer_info->dest_v.dw2.base_address = 446 (intel_surf->bo->offset + VOFFSET(context)) >> 2; 447 drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 448 offsetof(typeof(*buffer_info),dest_v.dw2), 449 intel_surf->bo, VOFFSET(context), 450 I915_GEM_DOMAIN_RENDER, 451 I915_GEM_DOMAIN_RENDER); 452 453 /* Dest buffer parameters */ 454 buffer_info->dest_buf.dw0.type = CMD_3D; 455 buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES; 456 buffer_info->dest_buf.dw0.length = 0; 457 buffer_info->dest_buf.dw1.dest_v_bias = 8; /* 0.5 */ 458 buffer_info->dest_buf.dw1.dest_h_bias = 8; /* 0.5 */ 459 buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT; 460 buffer_info->dest_buf.dw1.v_ls = 0; /* fill later */ 461 buffer_info->dest_buf.dw1.v_ls_offset = 0; /* fill later */ 462 if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { 463 ; 464 } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) { 465 buffer_info->dest_buf.dw1.v_ls = 1; 466 } else if ((picture_structure & XVMC_FRAME_PICTURE) == 467 XVMC_BOTTOM_FIELD) { 468 buffer_info->dest_buf.dw1.v_ls = 1; 469 buffer_info->dest_buf.dw1.v_ls_offset = 1; 470 } 471 472 /* MPEG buffer parameters */ 473 buffer_info->dest_buf_mpeg.dw0.type = CMD_3D; 474 buffer_info->dest_buf_mpeg.dw0.opcode = 475 OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG; 476 buffer_info->dest_buf_mpeg.dw0.length = 1; 477 buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC; 478 buffer_info->dest_buf_mpeg.dw1.rcontrol = 0; /* for MPEG-1/MPEG-2 */ 479 buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0; /* for MPEG-1/MPEG-2/MPEG-4 */ 480 buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1; 481 buffer_info->dest_buf_mpeg.dw1.intra8 = 0; /* 16-bit formatted correction data */ 482 buffer_info->dest_buf_mpeg.dw1.tff = 1; /* fill later */ 483 484 buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V; 485 buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H; 486 487 if (picture_structure & XVMC_FRAME_PICTURE) { 488 ; 489 } else if (picture_structure & XVMC_TOP_FIELD) { 490 if (flags & XVMC_SECOND_FIELD) 491 buffer_info->dest_buf_mpeg.dw1.tff = 0; 492 else 493 buffer_info->dest_buf_mpeg.dw1.tff = 1; 494 } else if (picture_structure & XVMC_BOTTOM_FIELD) { 495 if (flags & XVMC_SECOND_FIELD) 496 buffer_info->dest_buf_mpeg.dw1.tff = 1; 497 else 498 buffer_info->dest_buf_mpeg.dw1.tff = 0; 499 } 500 501 buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4); /* in macroblocks */ 502 buffer_info->dest_buf_mpeg.dw2.picture_coding_type = 503 picture_coding_type; 504 505 buffer_info->corr.dw0.type = CMD_3D; 506 buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; 507 buffer_info->corr.dw0.length = 1; 508 buffer_info->corr.dw1.aux_id = 0; 509 buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR; 510 buffer_info->corr.dw1.aux_id = 0; 511 buffer_info->corr.dw1.fence_regs = 0; 512 buffer_info->corr.dw1.tiled_surface = 0; 513 buffer_info->corr.dw1.walk = 0; 514 buffer_info->corr.dw1.pitch = 0; 515 buffer_info->corr.dw2.base_address = pI915XvMC->corrdata_bo->offset >> 2; /* starting DWORD address */ 516 drm_intel_bo_emit_reloc(pI915XvMC->sis_bo, 517 offsetof(typeof(*buffer_info),corr.dw2), 518 pI915XvMC->corrdata_bo, 0, 519 I915_GEM_DOMAIN_RENDER, 0); 520 521 drm_intel_gem_bo_unmap_gtt(pI915XvMC->sis_bo); 522} 523 524static void i915_mc_map_state_set(XvMCContext * context, 525 struct intel_xvmc_surface * privPast, 526 struct intel_xvmc_surface * privFuture) 527{ 528 i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 529 struct i915_mc_map_state *map_state; 530 unsigned int w = context->width; 531 unsigned int h = context->height; 532 533 drm_intel_gem_bo_map_gtt(pI915XvMC->msb_bo); 534 map_state = pI915XvMC->msb_bo->virtual; 535 536 memset(map_state, 0, sizeof(*map_state)); 537 538 /* 3DSATE_MAP_STATE: Y */ 539 map_state->y_map.dw0.type = CMD_3D; 540 map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; 541 map_state->y_map.dw0.retain = 1; 542 map_state->y_map.dw0.length = 6; 543 map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; 544 545 /* Y Forward (Past) */ 546 map_state->y_forward.tm0.v_ls_offset = 0; 547 map_state->y_forward.tm0.v_ls = 0; 548 map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR; 549 map_state->y_forward.tm1.tiled_surface = 0; 550 map_state->y_forward.tm1.utilize_fence_regs = 0; 551 map_state->y_forward.tm1.texel_fmt = 0; /* 8bit */ 552 map_state->y_forward.tm1.surface_fmt = 1; /* 8bit */ 553 map_state->y_forward.tm1.width = w - 1; 554 map_state->y_forward.tm1.height = h - 1; 555 map_state->y_forward.tm2.depth = 0; 556 map_state->y_forward.tm2.max_lod = 0; 557 map_state->y_forward.tm2.cube_face = 0; 558 map_state->y_forward.tm0.base_address = privPast->bo->offset >> 2; 559 drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 560 offsetof(typeof(*map_state),y_forward.tm0), 561 privPast->bo, 0, 562 I915_GEM_DOMAIN_SAMPLER, 0); 563 map_state->y_forward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1; /* in DWords - 1 */ 564 565 /* Y Backward (Future) */ 566 map_state->y_backward.tm0.v_ls_offset = 0; 567 map_state->y_backward.tm0.v_ls = 0; 568 map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR; 569 map_state->y_backward.tm1.tiled_surface = 0; 570 map_state->y_backward.tm1.utilize_fence_regs = 0; 571 map_state->y_backward.tm1.texel_fmt = 0; /* 8bit */ 572 map_state->y_backward.tm1.surface_fmt = 1; /* 8bit */ 573 map_state->y_backward.tm1.width = w - 1; 574 map_state->y_backward.tm1.height = h - 1; 575 map_state->y_backward.tm2.depth = 0; 576 map_state->y_backward.tm2.max_lod = 0; 577 map_state->y_backward.tm2.cube_face = 0; 578 map_state->y_backward.tm0.base_address = privFuture->bo->offset >> 2; 579 drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 580 offsetof(typeof(*map_state),y_backward.tm0), 581 privFuture->bo, 0, 582 I915_GEM_DOMAIN_SAMPLER, 0); 583 map_state->y_backward.tm2.pitch = (pI915XvMC->yStride >> 2) - 1; 584 585 /* 3DSATE_MAP_STATE: U */ 586 map_state->u_map.dw0.type = CMD_3D; 587 map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; 588 map_state->u_map.dw0.retain = 1; 589 map_state->u_map.dw0.length = 6; 590 map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; 591 592 /* U Forward */ 593 map_state->u_forward.tm0.v_ls_offset = 0; 594 map_state->u_forward.tm0.v_ls = 0; 595 map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR; 596 map_state->u_forward.tm1.tiled_surface = 0; 597 map_state->u_forward.tm1.utilize_fence_regs = 0; 598 map_state->u_forward.tm1.texel_fmt = 0; /* 8bit */ 599 map_state->u_forward.tm1.surface_fmt = 1; /* 8bit */ 600 map_state->u_forward.tm1.width = (w >> 1) - 1; 601 map_state->u_forward.tm1.height = (h >> 1) - 1; 602 map_state->u_forward.tm2.depth = 0; 603 map_state->u_forward.tm2.max_lod = 0; 604 map_state->u_forward.tm2.cube_face = 0; 605 map_state->u_forward.tm0.base_address = 606 (privPast->bo->offset + UOFFSET(context)) >> 2; 607 drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 608 offsetof(typeof(*map_state),u_forward.tm0), 609 privPast->bo, UOFFSET(context), 610 I915_GEM_DOMAIN_SAMPLER, 0); 611 map_state->u_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; /* in DWords - 1 */ 612 613 /* U Backward */ 614 map_state->u_backward.tm0.v_ls_offset = 0; 615 map_state->u_backward.tm0.v_ls = 0; 616 map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR; 617 map_state->u_backward.tm1.tiled_surface = 0; 618 map_state->u_backward.tm1.utilize_fence_regs = 0; 619 map_state->u_backward.tm1.texel_fmt = 0; 620 map_state->u_backward.tm1.surface_fmt = 1; 621 map_state->u_backward.tm1.width = (w >> 1) - 1; 622 map_state->u_backward.tm1.height = (h >> 1) - 1; 623 map_state->u_backward.tm2.depth = 0; 624 map_state->u_backward.tm2.max_lod = 0; 625 map_state->u_backward.tm2.cube_face = 0; 626 map_state->u_backward.tm0.base_address = 627 (privFuture->bo->offset + UOFFSET(context)) >> 2; 628 drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 629 offsetof(typeof(*map_state),u_backward.tm0), 630 privFuture->bo, UOFFSET(context), 631 I915_GEM_DOMAIN_SAMPLER, 0); 632 map_state->u_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; 633 634 /* 3DSATE_MAP_STATE: V */ 635 map_state->v_map.dw0.type = CMD_3D; 636 map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; 637 map_state->v_map.dw0.retain = 1; 638 map_state->v_map.dw0.length = 6; 639 map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; 640 641 /* V Forward */ 642 map_state->v_forward.tm0.v_ls_offset = 0; 643 map_state->v_forward.tm0.v_ls = 0; 644 map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR; 645 map_state->v_forward.tm1.tiled_surface = 0; 646 map_state->v_forward.tm1.utilize_fence_regs = 0; 647 map_state->v_forward.tm1.texel_fmt = 0; 648 map_state->v_forward.tm1.surface_fmt = 1; 649 map_state->v_forward.tm1.width = (w >> 1) - 1; 650 map_state->v_forward.tm1.height = (h >> 1) - 1; 651 map_state->v_forward.tm2.depth = 0; 652 map_state->v_forward.tm2.max_lod = 0; 653 map_state->v_forward.tm2.cube_face = 0; 654 map_state->v_forward.tm0.base_address = 655 (privPast->bo->offset + VOFFSET(context)) >> 2; 656 drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 657 offsetof(typeof(*map_state),v_forward.tm0), 658 privPast->bo, VOFFSET(context), 659 I915_GEM_DOMAIN_SAMPLER, 0); 660 map_state->v_forward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; /* in DWords - 1 */ 661 662 /* V Backward */ 663 map_state->v_backward.tm0.v_ls_offset = 0; 664 map_state->v_backward.tm0.v_ls = 0; 665 map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR; 666 map_state->v_backward.tm1.tiled_surface = 0; 667 map_state->v_backward.tm1.utilize_fence_regs = 0; 668 map_state->v_backward.tm1.texel_fmt = 0; 669 map_state->v_backward.tm1.surface_fmt = 1; 670 map_state->v_backward.tm1.width = (w >> 1) - 1; 671 map_state->v_backward.tm1.height = (h >> 1) - 1; 672 map_state->v_backward.tm2.depth = 0; 673 map_state->v_backward.tm2.max_lod = 0; 674 map_state->v_backward.tm2.cube_face = 0; 675 map_state->v_backward.tm0.base_address = 676 (privFuture->bo->offset + VOFFSET(context)) >> 2; 677 drm_intel_bo_emit_reloc(pI915XvMC->msb_bo, 678 offsetof(typeof(*map_state),v_backward.tm0), 679 privFuture->bo, VOFFSET(context), 680 I915_GEM_DOMAIN_SAMPLER, 0); 681 map_state->v_backward.tm2.pitch = (pI915XvMC->uvStride >> 2) - 1; 682 683 drm_intel_gem_bo_unmap_gtt(pI915XvMC->msb_bo); 684} 685 686static void i915_mc_load_indirect_render_emit(XvMCContext * context) 687{ 688 i915XvMCContext *pI915XvMC = (i915XvMCContext *) context->privData; 689 int mem_select; 690 uint32_t load_indirect; 691 BATCH_LOCALS; 692 693 BEGIN_BATCH(5); 694 load_indirect = OP_3D_LOAD_INDIRECT; 695 load_indirect |= (BLOCK_SIS | BLOCK_MSB) << BLOCK_MASK_SHIFT; 696 load_indirect |= 5 - 2; /* length */ 697 698 if (pI915XvMC->use_phys_addr) 699 mem_select = 0; /* use physical address */ 700 else { 701 load_indirect |= OP_3D_LOAD_INDIRECT_GFX_ADDR; 702 mem_select = 1; /* use gfx address */ 703 } 704 OUT_BATCH(load_indirect); 705 706 /* Static Indirect state buffer (dest buffer info) */ 707 OUT_RELOC(pI915XvMC->sis_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 708 STATE_VALID | STATE_FORCE); 709 OUT_BATCH(16); /* 4 * 3 + 2 + 3 - 1 */ 710 711 /* Map state buffer (reference buffer info) */ 712 OUT_RELOC(pI915XvMC->msb_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 713 STATE_VALID | STATE_FORCE); 714 OUT_BATCH(23); /* 3 * 8 - 1 */ 715 ADVANCE_BATCH(); 716} 717 718static void i915_mc_mpeg_set_origin(XvMCContext * context, XvMCMacroBlock * mb) 719{ 720 struct i915_3dmpeg_set_origin set_origin; 721 722 /* 3DMPEG_SET_ORIGIN */ 723 memset(&set_origin, 0, sizeof(set_origin)); 724 set_origin.dw0.type = CMD_3D; 725 set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN; 726 set_origin.dw0.length = 0; 727 set_origin.dw1.h_origin = mb->x; 728 set_origin.dw1.v_origin = mb->y; 729 730 intelBatchbufferData(&set_origin, sizeof(set_origin), 0); 731} 732 733static void i915_mc_mpeg_macroblock_ipicture(XvMCContext * context, 734 XvMCMacroBlock * mb) 735{ 736 struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture; 737 738 /* 3DMPEG_MACROBLOCK_IPICTURE */ 739 memset(¯oblock_ipicture, 0, sizeof(macroblock_ipicture)); 740 macroblock_ipicture.dw0.type = CMD_3D; 741 macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE; 742 macroblock_ipicture.dw0.dct_type = 743 (mb->dct_type == XVMC_DCT_TYPE_FIELD); 744 745 intelBatchbufferData(¯oblock_ipicture, sizeof(macroblock_ipicture), 746 0); 747} 748 749static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext * context, 750 XvMCMacroBlock * mb) 751{ 752 struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv; 753 vector_t mv0[2]; 754 755 /* 3DMPEG_MACROBLOCK(1fbmv) */ 756 memset(¯oblock_1fbmv, 0, sizeof(macroblock_1fbmv)); 757 macroblock_1fbmv.header.dw0.type = CMD_3D; 758 macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; 759 macroblock_1fbmv.header.dw0.length = 2; 760 macroblock_1fbmv.header.dw1.mb_intra = 0; /* should be 0 */ 761 macroblock_1fbmv.header.dw1.forward = 762 ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); 763 macroblock_1fbmv.header.dw1.backward = 764 ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); 765 macroblock_1fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ 766 macroblock_1fbmv.header.dw1.dct_type = 767 (mb->dct_type == XVMC_DCT_TYPE_FIELD); 768 769 if (!(mb->coded_block_pattern & 0x3f)) 770 macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; 771 772 macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); 773 macroblock_1fbmv.header.dw1.vertical_field_select = 774 (mb->motion_vertical_field_select & 0x0f); 775 macroblock_1fbmv.header.dw1.coded_block_pattern = 776 mb->coded_block_pattern; 777 macroblock_1fbmv.header.dw1.skipped_macroblocks = 0; 778 779 mv0[0].component[0] = mb->PMV[0][0][0]; 780 mv0[0].component[1] = mb->PMV[0][0][1]; 781 mv0[1].component[0] = mb->PMV[0][1][0]; 782 mv0[1].component[1] = mb->PMV[0][1][1]; 783 784 macroblock_1fbmv.dw2 = mv0[0].v; 785 macroblock_1fbmv.dw3 = mv0[1].v; 786 787 intelBatchbufferData(¯oblock_1fbmv, sizeof(macroblock_1fbmv), 0); 788} 789 790static void i915_mc_mpeg_macroblock_2fbmv(XvMCContext * context, 791 XvMCMacroBlock * mb, unsigned int ps) 792{ 793 struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv; 794 vector_t mv0[2]; 795 vector_t mv1[2]; 796 797 /* 3DMPEG_MACROBLOCK(2fbmv) */ 798 memset(¯oblock_2fbmv, 0, sizeof(macroblock_2fbmv)); 799 macroblock_2fbmv.header.dw0.type = CMD_3D; 800 macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; 801 macroblock_2fbmv.header.dw0.length = 4; 802 macroblock_2fbmv.header.dw1.mb_intra = 0; /* should be 0 */ 803 macroblock_2fbmv.header.dw1.forward = 804 ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); 805 macroblock_2fbmv.header.dw1.backward = 806 ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); 807 macroblock_2fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ 808 macroblock_2fbmv.header.dw1.dct_type = 809 (mb->dct_type == XVMC_DCT_TYPE_FIELD); 810 811 if (!(mb->coded_block_pattern & 0x3f)) 812 macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; 813 814 macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); 815 macroblock_2fbmv.header.dw1.vertical_field_select = 816 (mb->motion_vertical_field_select & 0x0f); 817 macroblock_2fbmv.header.dw1.coded_block_pattern = 818 mb->coded_block_pattern; 819 macroblock_2fbmv.header.dw1.skipped_macroblocks = 0; 820 821 mv0[0].component[0] = mb->PMV[0][0][0]; 822 mv0[0].component[1] = mb->PMV[0][0][1]; 823 mv0[1].component[0] = mb->PMV[0][1][0]; 824 mv0[1].component[1] = mb->PMV[0][1][1]; 825 mv1[0].component[0] = mb->PMV[1][0][0]; 826 mv1[0].component[1] = mb->PMV[1][0][1]; 827 mv1[1].component[0] = mb->PMV[1][1][0]; 828 mv1[1].component[1] = mb->PMV[1][1][1]; 829 830 if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { 831 if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) { 832 mv0[0].component[1] = mb->PMV[0][0][1] >> 1; 833 mv0[1].component[1] = mb->PMV[0][1][1] >> 1; 834 mv1[0].component[1] = mb->PMV[1][0][1] >> 1; 835 mv1[1].component[1] = mb->PMV[1][1][1] >> 1; 836 } else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) { 837 mv0[0].component[1] = mb->PMV[0][0][1] >> 1; 838 mv0[1].component[1] = mb->PMV[0][1][1] >> 1; // MPEG2 MV[0][1] isn't used 839 mv1[0].component[1] = mb->PMV[1][0][1] >> 1; 840 mv1[1].component[1] = mb->PMV[1][1][1] >> 1; 841 } 842 } 843 844 macroblock_2fbmv.dw2 = mv0[0].v; 845 macroblock_2fbmv.dw3 = mv0[1].v; 846 macroblock_2fbmv.dw4 = mv1[0].v; 847 macroblock_2fbmv.dw5 = mv1[1].v; 848 849 intelBatchbufferData(¯oblock_2fbmv, sizeof(macroblock_2fbmv), 0); 850} 851 852static int i915_xvmc_alloc_one_time_buffers(i915XvMCContext *pI915XvMC) 853{ 854 pI915XvMC->ssb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 855 "ssb", 856 GTT_PAGE_SIZE, 857 GTT_PAGE_SIZE); 858 if (!pI915XvMC->ssb_bo) 859 return 0; 860 861 pI915XvMC->psp_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 862 "psp", 863 GTT_PAGE_SIZE, 864 GTT_PAGE_SIZE); 865 if (!pI915XvMC->psp_bo) 866 return 0; 867 868 pI915XvMC->psc_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 869 "psc", 870 GTT_PAGE_SIZE, 871 GTT_PAGE_SIZE); 872 if (!pI915XvMC->psc_bo) 873 return 0; 874 875 return 1; 876} 877 878static void i915_xvmc_free_one_time_buffers(i915XvMCContext *pI915XvMC) 879{ 880 drm_intel_bo_unreference(pI915XvMC->ssb_bo); 881 drm_intel_bo_unreference(pI915XvMC->psp_bo); 882 drm_intel_bo_unreference(pI915XvMC->psc_bo); 883} 884 885/* 886 * Function: i915_release_resource 887 */ 888static void i915_release_resource(Display * display, XvMCContext * context) 889{ 890 i915XvMCContext *pI915XvMC; 891 892 if (!(pI915XvMC = context->privData)) 893 return; 894 895 i915_xvmc_free_one_time_buffers(pI915XvMC); 896 897 free(pI915XvMC); 898 context->privData = NULL; 899} 900 901static Status i915_xvmc_mc_create_context(Display * display, 902 XvMCContext * context, int priv_count, 903 CARD32 * priv_data) 904{ 905 i915XvMCContext *pI915XvMC = NULL; 906 struct intel_xvmc_hw_context *tmpComm = NULL; 907 908 if (priv_count != (sizeof(struct intel_xvmc_hw_context) >> 2)) { 909 XVMC_ERR 910 ("_xvmc_create_context() returned incorrect data size!"); 911 XVMC_INFO("\tExpected %d, got %d", 912 (int)(sizeof(struct intel_xvmc_hw_context) >> 2), 913 priv_count); 914 _xvmc_destroy_context(display, context); 915 XFree(priv_data); 916 context->privData = NULL; 917 return BadValue; 918 } 919 920 context->privData = (void *)calloc(1, sizeof(i915XvMCContext)); 921 if (!context->privData) { 922 XVMC_ERR("Unable to allocate resources for XvMC context."); 923 return BadAlloc; 924 } 925 pI915XvMC = (i915XvMCContext *) context->privData; 926 927 tmpComm = (struct intel_xvmc_hw_context *) priv_data; 928 pI915XvMC->use_phys_addr = tmpComm->i915.use_phys_addr; 929 pI915XvMC->comm.surface_bo_size = SIZE_YUV420(context->width, 930 context->height); 931 932 /* Must free the private data we were passed from X */ 933 XFree(priv_data); 934 priv_data = NULL; 935 936 if (!i915_xvmc_alloc_one_time_buffers(pI915XvMC)) 937 goto free_one_time_buffers; 938 939 /* Initialize private context values */ 940 pI915XvMC->yStride = STRIDE(context->width); 941 pI915XvMC->uvStride = STRIDE(context->width >> 1); 942 943 /* pre-init state buffers */ 944 i915_mc_one_time_context_init(context); 945 946 return Success; 947 948free_one_time_buffers: 949 i915_xvmc_free_one_time_buffers(pI915XvMC); 950 free(pI915XvMC); 951 context->privData = NULL; 952 return BadAlloc; 953} 954 955static int i915_xvmc_mc_destroy_context(Display * display, 956 XvMCContext * context) 957{ 958 i915XvMCContext *pI915XvMC; 959 960 if (!(pI915XvMC = context->privData)) 961 return XvMCBadContext; 962 963 /* Pass Control to the X server to destroy the drm_context_t */ 964 i915_release_resource(display, context); 965 966 return Success; 967} 968 969static int i915_xvmc_alloc_render_state_buffers(i915XvMCContext *pI915XvMC) 970{ 971 pI915XvMC->sis_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 972 "sis", 973 GTT_PAGE_SIZE, 974 GTT_PAGE_SIZE); 975 if (!pI915XvMC->sis_bo) 976 return 0; 977 978 pI915XvMC->msb_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 979 "msb", 980 GTT_PAGE_SIZE, 981 GTT_PAGE_SIZE); 982 if (!pI915XvMC->msb_bo) 983 return 0; 984 985 pI915XvMC->corrdata_bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 986 "corrdata", 987 CORRDATA_SIZE, 988 GTT_PAGE_SIZE); 989 if (!pI915XvMC->corrdata_bo) 990 return 0; 991 992 return 1; 993} 994 995static void i915_xvmc_free_render_state_buffers(i915XvMCContext *pI915XvMC) 996{ 997 drm_intel_bo_unreference(pI915XvMC->sis_bo); 998 drm_intel_bo_unreference(pI915XvMC->msb_bo); 999 drm_intel_bo_unreference(pI915XvMC->corrdata_bo); 1000} 1001 1002static int i915_xvmc_mc_render_surface(Display * display, XvMCContext * context, 1003 unsigned int picture_structure, 1004 XvMCSurface * target_surface, 1005 XvMCSurface * past_surface, 1006 XvMCSurface * future_surface, 1007 unsigned int flags, 1008 unsigned int num_macroblocks, 1009 unsigned int first_macroblock, 1010 XvMCMacroBlockArray * macroblock_array, 1011 XvMCBlockArray * blocks) 1012{ 1013 int i; 1014 int picture_coding_type = MPEG_I_PICTURE; 1015 /* correction data buffer */ 1016 char *corrdata_ptr; 1017 int corrdata_size = 0; 1018 1019 /* Block Pointer */ 1020 short *block_ptr; 1021 /* Current Macroblock Pointer */ 1022 XvMCMacroBlock *mb; 1023 1024 intel_xvmc_context_ptr intel_ctx; 1025 1026 struct intel_xvmc_surface *privTarget = NULL; 1027 struct intel_xvmc_surface *privFuture = NULL; 1028 struct intel_xvmc_surface *privPast = NULL; 1029 i915XvMCContext *pI915XvMC = NULL; 1030 1031 /* Check Parameters for validity */ 1032 if (!display || !context || !target_surface) { 1033 XVMC_ERR("Invalid Display, Context or Target!"); 1034 return BadValue; 1035 } 1036 1037 if (!num_macroblocks) 1038 return Success; 1039 1040 if (!macroblock_array || !blocks) { 1041 XVMC_ERR("Invalid block data!"); 1042 return BadValue; 1043 } 1044 1045 if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) { 1046 XVMC_ERR("Too many macroblocks requested for MB array size."); 1047 return BadValue; 1048 } 1049 1050 if (!(pI915XvMC = context->privData)) 1051 return XvMCBadContext; 1052 1053 if (!(privTarget = target_surface->privData)) 1054 return XvMCBadSurface; 1055 1056 if (!i915_xvmc_alloc_render_state_buffers(pI915XvMC)) 1057 return BadAlloc; 1058 1059 intel_ctx = context->privData; 1060 if (!intel_ctx) { 1061 XVMC_ERR("Can't find intel xvmc context\n"); 1062 return BadValue; 1063 } 1064 1065 /* P Frame Test */ 1066 if (!past_surface) { 1067 /* Just to avoid some ifs later. */ 1068 privPast = privTarget; 1069 } else { 1070 if (!(privPast = past_surface->privData)) { 1071 return XvMCBadSurface; 1072 } 1073 picture_coding_type = MPEG_P_PICTURE; 1074 } 1075 1076 /* B Frame Test */ 1077 if (!future_surface) { 1078 privFuture = privPast; // privTarget; 1079 } else { 1080 if (!past_surface) { 1081 XVMC_ERR("No Past Surface!"); 1082 return BadValue; 1083 } 1084 1085 if (!(privFuture = future_surface->privData)) { 1086 XVMC_ERR("Invalid Future Surface!"); 1087 return XvMCBadSurface; 1088 } 1089 1090 picture_coding_type = MPEG_B_PICTURE; 1091 } 1092 1093 LOCK_HARDWARE(intel_ctx->hw_context); 1094 drm_intel_gem_bo_map_gtt(pI915XvMC->corrdata_bo); 1095 corrdata_ptr = pI915XvMC->corrdata_bo->virtual; 1096 corrdata_size = 0; 1097 1098 for (i = first_macroblock; i < (num_macroblocks + first_macroblock); 1099 i++) { 1100 int bspm = 0; 1101 mb = ¯oblock_array->macro_blocks[i]; 1102 block_ptr = &(blocks->blocks[mb->index << 6]); 1103 1104 /* Lockup can happen if the coordinates are too far out of range */ 1105 if (mb->x > (target_surface->width >> 4)) { 1106 mb->x = 0; 1107 XVMC_INFO("reset x"); 1108 } 1109 1110 if (mb->y > (target_surface->height >> 4)) { 1111 mb->y = 0; 1112 XVMC_INFO("reset y"); 1113 } 1114 1115 /* Catch no pattern case */ 1116 if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) && 1117 !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) && 1118 mb->coded_block_pattern) { 1119 mb->coded_block_pattern = 0; 1120 XVMC_INFO("no coded blocks present!"); 1121 } 1122 1123 bspm = mb_bytes_420[mb->coded_block_pattern]; 1124 1125 if (!bspm) 1126 continue; 1127 1128 corrdata_size += bspm; 1129 1130 if (corrdata_size > CORRDATA_SIZE) { 1131 XVMC_ERR("correction data buffer overflow."); 1132 break; 1133 } 1134 memcpy(corrdata_ptr, block_ptr, bspm); 1135 corrdata_ptr += bspm; 1136 } 1137 1138 drm_intel_gem_bo_unmap_gtt(pI915XvMC->corrdata_bo); 1139 1140 // i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB 1141 // | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC); 1142 1143 i915_mc_one_time_state_emit(context); 1144 1145 i915_mc_static_indirect_state_set(context, target_surface, 1146 picture_structure, flags, 1147 picture_coding_type); 1148 /* setup reference surfaces */ 1149 i915_mc_map_state_set(context, privPast, privFuture); 1150 1151 i915_mc_load_indirect_render_emit(context); 1152 1153 i915_mc_mpeg_set_origin(context, 1154 ¯oblock_array->macro_blocks 1155 [first_macroblock]); 1156 1157 for (i = first_macroblock; i < (num_macroblocks + first_macroblock); 1158 i++) { 1159 mb = ¯oblock_array->macro_blocks[i]; 1160 1161 /* Intra Blocks */ 1162 if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 1163 i915_mc_mpeg_macroblock_ipicture(context, mb); 1164 } else if ((picture_structure & XVMC_FRAME_PICTURE) == 1165 XVMC_FRAME_PICTURE) { 1166 /* Frame Picture */ 1167 switch (mb->motion_type & 3) { 1168 case XVMC_PREDICTION_FIELD: /* Field Based */ 1169 i915_mc_mpeg_macroblock_2fbmv(context, mb, 1170 picture_structure); 1171 break; 1172 1173 case XVMC_PREDICTION_FRAME: /* Frame Based */ 1174 i915_mc_mpeg_macroblock_1fbmv(context, mb); 1175 break; 1176 1177 case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ 1178 i915_mc_mpeg_macroblock_2fbmv(context, mb, 1179 picture_structure); 1180 break; 1181 1182 default: /* No Motion Type */ 1183 XVMC_ERR 1184 ("Invalid Macroblock Parameters found."); 1185 break; 1186 } 1187 } else { /* Field Picture */ 1188 switch (mb->motion_type & 3) { 1189 case XVMC_PREDICTION_FIELD: /* Field Based */ 1190 i915_mc_mpeg_macroblock_1fbmv(context, mb); 1191 break; 1192 1193 case XVMC_PREDICTION_16x8: /* 16x8 MC */ 1194 i915_mc_mpeg_macroblock_2fbmv(context, mb, 1195 picture_structure); 1196 break; 1197 1198 case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ 1199 i915_mc_mpeg_macroblock_1fbmv(context, mb); 1200 break; 1201 1202 default: /* No Motion Type */ 1203 XVMC_ERR 1204 ("Invalid Macroblock Parameters found."); 1205 break; 1206 } 1207 } 1208 } 1209 1210 intelFlushBatch(); 1211 1212 i915_xvmc_free_render_state_buffers(pI915XvMC); 1213 1214 UNLOCK_HARDWARE(intel_ctx->hw_context); 1215 return 0; 1216} 1217 1218struct _intel_xvmc_driver i915_xvmc_mc_driver = { 1219 .type = XVMC_I915_MPEG2_MC, 1220 .num_ctx = 0, 1221 .ctx_list = NULL, 1222 .create_context = i915_xvmc_mc_create_context, 1223 .destroy_context = i915_xvmc_mc_destroy_context, 1224 .render_surface = i915_xvmc_mc_render_surface, 1225}; 1226