1/* 2 * Copyright © 2008 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 * Author: 24 * Zou Nan hai <nanhai.zou@intel.com> 25 * 26 */ 27#include "i965_xvmc.h" 28#include "i810_reg.h" 29#include "brw_defines.h" 30#include "brw_structs.h" 31#include "intel_batchbuffer.h" 32#include "i965_hwmc.h" 33#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0) 34#define URB_SIZE 256 /* XXX */ 35 36#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) 37 38enum interface { 39 INTRA_INTERFACE = 0, /* non field intra */ 40 NULL_INTERFACE, /* fill with white, do nothing, for debug */ 41 FORWARD_INTERFACE, /* non field forward predict */ 42 BACKWARD_INTERFACE, /* non field backward predict */ 43 F_B_INTERFACE, /* non field forward and backward predict */ 44 FIELD_FORWARD_INTERFACE, /* field forward predict */ 45 FIELD_BACKWARD_INTERFACE, /* field backward predict */ 46 FIELD_F_B_INTERFACE, /* field forward and backward predict */ 47 DUAL_PRIME_INTERFACE 48}; 49 50static const uint32_t ipicture_kernel_static[][4] = { 51 #include "shader/mc/ipicture.g4b" 52}; 53static const uint32_t null_kernel_static[][4] = { 54 #include "shader/mc/null.g4b" 55}; 56static const uint32_t frame_forward_kernel_static[][4] = { 57 #include "shader/mc/frame_forward.g4b" 58}; 59static const uint32_t frame_backward_kernel_static[][4] = { 60 #include "shader/mc/frame_backward.g4b" 61}; 62static const uint32_t frame_f_b_kernel_static[][4] = { 63 #include "shader/mc/frame_f_b.g4b" 64}; 65static const uint32_t field_forward_kernel_static[][4] = { 66 #include "shader/mc/field_forward.g4b" 67}; 68static const uint32_t field_backward_kernel_static[][4] = { 69 #include "shader/mc/field_backward.g4b" 70}; 71static const uint32_t field_f_b_kernel_static[][4] = { 72 #include "shader/mc/field_f_b.g4b" 73}; 74static const uint32_t dual_prime_kernel_static[][4]= { 75 #include "shader/mc/dual_prime.g4b" 76}; 77static const uint32_t frame_forward_igd_kernel_static[][4] = { 78 #include "shader/mc/frame_forward_igd.g4b" 79}; 80static const uint32_t frame_backward_igd_kernel_static[][4] = { 81 #include "shader/mc/frame_backward_igd.g4b" 82}; 83static const uint32_t frame_f_b_igd_kernel_static[][4] = { 84 #include "shader/mc/frame_f_b_igd.g4b" 85}; 86static const uint32_t field_forward_igd_kernel_static[][4] = { 87 #include "shader/mc/field_forward_igd.g4b" 88}; 89static const uint32_t field_backward_igd_kernel_static[][4] = { 90 #include "shader/mc/field_backward_igd.g4b" 91}; 92static const uint32_t field_f_b_igd_kernel_static[][4] = { 93 #include "shader/mc/field_f_b_igd.g4b" 94}; 95static const uint32_t dual_prime_igd_kernel_static[][4]= { 96 #include "shader/mc/dual_prime_igd.g4b" 97}; 98 99struct kernel_struct{ 100 const uint32_t (*bin)[4]; 101 uint32_t size; 102}; 103 104struct kernel_struct kernels_igd[] = { 105 {ipicture_kernel_static, sizeof(ipicture_kernel_static)}, 106 {null_kernel_static, sizeof(null_kernel_static)}, 107 {frame_forward_igd_kernel_static, sizeof(frame_forward_igd_kernel_static)}, 108 {frame_backward_igd_kernel_static, sizeof(frame_backward_igd_kernel_static)}, 109 {frame_f_b_igd_kernel_static, sizeof(frame_f_b_igd_kernel_static)}, 110 {field_forward_igd_kernel_static, sizeof(field_forward_igd_kernel_static)}, 111 {field_backward_igd_kernel_static, sizeof(field_backward_igd_kernel_static)}, 112 {field_f_b_igd_kernel_static, sizeof(field_f_b_igd_kernel_static)}, 113 {dual_prime_igd_kernel_static, sizeof(dual_prime_igd_kernel_static)} 114}; 115 116struct kernel_struct kernels_965[] = { 117 {ipicture_kernel_static, sizeof(ipicture_kernel_static)}, 118 {null_kernel_static, sizeof(null_kernel_static)}, 119 {frame_forward_kernel_static, sizeof(frame_forward_kernel_static)}, 120 {frame_backward_kernel_static, sizeof(frame_backward_kernel_static)}, 121 {frame_f_b_kernel_static, sizeof(frame_f_b_kernel_static)}, 122 {field_forward_kernel_static, sizeof(field_forward_kernel_static)}, 123 {field_backward_kernel_static, sizeof(field_backward_kernel_static)}, 124 {field_f_b_kernel_static, sizeof(field_f_b_kernel_static)}, 125 {dual_prime_kernel_static, sizeof(dual_prime_kernel_static)} 126}; 127 128#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) 129 130#define MAX_SURFACE_NUM 10 131#define DESCRIPTOR_NUM 12 132 133struct media_kernel_obj { 134 dri_bo *bo; 135}; 136 137struct interface_descriptor_obj { 138 dri_bo *bo; 139 struct media_kernel_obj kernels[DESCRIPTOR_NUM]; 140}; 141 142struct vfe_state_obj { 143 dri_bo *bo; 144 struct interface_descriptor_obj interface; 145}; 146 147struct surface_obj { 148 dri_bo *bo; 149}; 150 151struct surface_state_obj { 152 struct surface_obj surface; 153 dri_bo *bo; 154}; 155 156struct binding_table_obj { 157 dri_bo *bo; 158 struct surface_state_obj surface_states[MAX_SURFACE_NUM]; 159}; 160 161struct indirect_data_obj { 162 dri_bo *bo; 163}; 164 165struct media_state { 166 unsigned int is_g4x:1; 167 unsigned int is_965_q:1; 168 169 struct vfe_state_obj vfe_state; 170 struct binding_table_obj binding_table; 171 struct indirect_data_obj indirect_data; 172}; 173struct media_state media_state; 174 175static int free_object(struct media_state *s) 176{ 177 int i; 178#define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo) 179 FREE_ONE_BO(s->vfe_state.bo); 180 FREE_ONE_BO(s->vfe_state.interface.bo); 181 for (i = 0; i < DESCRIPTOR_NUM; i++) 182 FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo); 183 FREE_ONE_BO(s->binding_table.bo); 184 for (i = 0; i < MAX_SURFACE_NUM; i++) 185 FREE_ONE_BO(s->binding_table.surface_states[i].bo); 186 FREE_ONE_BO(s->indirect_data.bo); 187} 188 189static int alloc_object(struct media_state *s) 190{ 191 int i; 192 193 for (i = 0; i < MAX_SURFACE_NUM; i++) { 194 s->binding_table.surface_states[i].bo = 195 drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 196 sizeof(struct brw_surface_state), 0x1000); 197 if (!s->binding_table.surface_states[i].bo) 198 goto out; 199 } 200 return 0; 201out: 202 free_object(s); 203 return BadAlloc; 204} 205 206 207static Status destroy_context(Display *display, XvMCContext *context) 208{ 209 struct i965_xvmc_context *private_context; 210 private_context = context->privData; 211 212 free_object(&media_state); 213 Xfree(private_context); 214 return Success; 215} 216 217#define STRIDE(w) (w) 218#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1))) 219 220static Status create_surface(Display *display, 221 XvMCContext *context, XvMCSurface *surface, int priv_count, 222 CARD32 *priv_data) 223{ 224 struct i965_xvmc_surface *priv_surface = 225 (struct i965_xvmc_surface *)priv_data; 226 size_t size = SIZE_YUV420(priv_surface->w, priv_surface->h); 227 surface->privData = priv_data; 228 priv_surface->bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface", 229 size, 0x1000); 230 return Success; 231} 232 233static Status destroy_surface(Display *display, XvMCSurface *surface) 234{ 235 struct i965_xvmc_surface *priv_surface = 236 surface->privData; 237 XSync(display, False); 238 239 drm_intel_bo_unreference(priv_surface->bo); 240 return Success; 241} 242 243static void flush() 244{ 245 struct brw_mi_flush flush; 246 memset(&flush, 0, sizeof(flush)); 247 flush.opcode = CMD_MI_FLUSH; 248 flush.flags = (1<<1); 249 BATCH_STRUCT(flush); 250} 251 252static void clear_sf_state() 253{ 254 struct brw_sf_unit_state sf; 255 memset(&sf, 0, sizeof(sf)); 256 /* TODO */ 257} 258 259 260/* urb fence must be aligned to cacheline */ 261static void align_urb_fence() 262{ 263 BATCH_LOCALS; 264 int i, offset_to_next_cacheline; 265 unsigned long batch_offset; 266 BEGIN_BATCH(3); 267 batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr; 268 offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset; 269 if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) { 270 for (i = 0; i < offset_to_next_cacheline/4; i++) 271 OUT_BATCH(0); 272 ADVANCE_BATCH(); 273 } 274} 275 276/* setup urb layout for media */ 277static void urb_layout() 278{ 279 BATCH_LOCALS; 280 align_urb_fence(); 281 BEGIN_BATCH(3); 282 OUT_BATCH(BRW_URB_FENCE | 283 UF0_VFE_REALLOC | 284 UF0_CS_REALLOC | 285 UF0_SF_REALLOC | 286 UF0_CLIP_REALLOC | 287 UF0_GS_REALLOC | 288 UF0_VS_REALLOC | 289 1); 290 OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) | 291 (0 << UF1_GS_FENCE_SHIFT) | 292 (0 << UF1_VS_FENCE_SHIFT)); 293 294 OUT_BATCH(((URB_SIZE)<< UF2_VFE_FENCE_SHIFT) | /* VFE_SIZE */ 295 ((URB_SIZE)<< UF2_CS_FENCE_SHIFT)); /* CS_SIZE is 0 */ 296 ADVANCE_BATCH(); 297} 298 299static void media_state_pointers(struct media_state *media_state) 300{ 301 BATCH_LOCALS; 302 BEGIN_BATCH(3); 303 OUT_BATCH(BRW_MEDIA_STATE_POINTERS|1); 304 OUT_BATCH(0); 305 OUT_RELOC(media_state->vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); 306 ADVANCE_BATCH(); 307} 308 309/* setup 2D surface for media_read or media_write 310 */ 311static Status setup_media_surface(struct media_state *media_state, 312 int surface_num, dri_bo *bo, unsigned long offset, int w, int h, Bool write) 313{ 314 struct brw_surface_state s, *ss = &s; 315 316 memset(ss, 0, sizeof(struct brw_surface_state)); 317 ss->ss0.surface_type = BRW_SURFACE_2D; 318 ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT; 319 ss->ss1.base_addr = offset + bo->offset; 320 ss->ss2.width = w - 1; 321 ss->ss2.height = h - 1; 322 ss->ss3.pitch = w - 1; 323 324 if (media_state->binding_table.surface_states[surface_num].bo) 325 drm_intel_bo_unreference(media_state->binding_table.surface_states[surface_num].bo); 326 media_state->binding_table.surface_states[surface_num].bo = 327 drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 328 sizeof(struct brw_surface_state), 0x1000); 329 if (!media_state->binding_table.surface_states[surface_num].bo) 330 return BadAlloc; 331 332 drm_intel_bo_subdata( 333 media_state->binding_table.surface_states[surface_num].bo, 334 0, sizeof(*ss), ss); 335 336 drm_intel_bo_emit_reloc(media_state->binding_table.surface_states[surface_num].bo, 337 offsetof(struct brw_surface_state, ss1), 338 bo, 339 offset, 340 I915_GEM_DOMAIN_RENDER, write?I915_GEM_DOMAIN_RENDER:0); 341 342 return Success; 343} 344 345static Status setup_surfaces(struct media_state *media_state, 346 dri_bo *dst_bo, dri_bo *past_bo, dri_bo *future_bo, 347 int w, int h) 348{ 349 Status ret; 350 ret = setup_media_surface(media_state, 0, dst_bo, 0, w, h, TRUE); 351 if (ret != Success) 352 return ret; 353 ret = setup_media_surface(media_state, 1, dst_bo, w*h, w/2, h/2, TRUE); 354 if (ret != Success) 355 return ret; 356 ret = setup_media_surface(media_state, 2, dst_bo, w*h + w*h/4, w/2, h/2, TRUE); 357 if (ret != Success) 358 return ret; 359 if (past_bo) { 360 ret = setup_media_surface(media_state, 4, past_bo, 0, w, h, FALSE); 361 if (ret != Success) 362 return ret; 363 ret = setup_media_surface(media_state, 5, past_bo, w*h, w/2, h/2, FALSE); 364 if (ret != Success) 365 return ret; 366 ret = setup_media_surface(media_state, 6, past_bo, w*h + w*h/4, w/2, h/2, FALSE); 367 if (ret != Success) 368 return ret; 369 } 370 if (future_bo) { 371 ret = setup_media_surface(media_state, 7, future_bo, 0, w, h, FALSE); 372 if (ret != Success) 373 return ret; 374 ret = setup_media_surface(media_state, 8, future_bo, w*h, w/2, h/2, FALSE); 375 if (ret != Success) 376 return ret; 377 ret = setup_media_surface(media_state, 9, future_bo, w*h + w*h/4, w/2, h/2, FALSE); 378 if (ret != Success) 379 return ret; 380 } 381 return Success; 382} 383/* BUFFER SURFACE has a strange format 384 * the size of the surface is in part of w h and d component 385 */ 386 387static Status setup_blocks(struct media_state *media_state, unsigned int block_size) 388{ 389 union element{ 390 struct { 391 unsigned int w:7; 392 unsigned int h:13; 393 unsigned int d:7; 394 unsigned int pad:7; 395 }whd; 396 unsigned int size; 397 }e; 398 struct brw_surface_state ss; 399 memset(&ss, 0, sizeof(struct brw_surface_state)); 400 ss.ss0.surface_type = BRW_SURFACE_BUFFER; 401 ss.ss0.surface_format = BRW_SURFACEFORMAT_R8_UINT; 402 ss.ss1.base_addr = media_state->indirect_data.bo->offset; 403 404 e.size = block_size - 1; 405 ss.ss2.width = e.whd.w; 406 ss.ss2.height = e.whd.h; 407 ss.ss3.depth = e.whd.d; 408 ss.ss3.pitch = block_size - 1; 409 410 if (media_state->binding_table.surface_states[3].bo) 411 drm_intel_bo_unreference(media_state->binding_table.surface_states[3].bo); 412 413 media_state->binding_table.surface_states[3].bo = 414 drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 415 sizeof(struct brw_surface_state), 0x1000); 416 if (!media_state->binding_table.surface_states[3].bo) 417 return BadAlloc; 418 419 drm_intel_bo_subdata(media_state->binding_table.surface_states[3].bo, 0, 420 sizeof(ss), &ss); 421 422 drm_intel_bo_emit_reloc(media_state->binding_table.surface_states[3].bo, 423 offsetof(struct brw_surface_state, ss1), 424 media_state->indirect_data.bo, 0, 425 I915_GEM_DOMAIN_SAMPLER, 0); 426 return Success; 427} 428 429/* setup state base address */ 430static void state_base_address() 431{ 432 BATCH_LOCALS; 433 BEGIN_BATCH(6); 434 OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4); 435 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 436 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 437 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 438 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 439 OUT_BATCH(0xFFFFF000|BASE_ADDRESS_MODIFY); 440 ADVANCE_BATCH(); 441} 442 443/* select media pipeline */ 444static void pipeline_select(struct media_state *media_state) 445{ 446 BATCH_LOCALS; 447 BEGIN_BATCH(1); 448 if (media_state->is_g4x) 449 OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); 450 else 451 OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); 452 ADVANCE_BATCH(); 453} 454 455/* kick media object to gpu */ 456static void send_media_object(XvMCMacroBlock *mb, int offset, enum interface interface) 457{ 458 BATCH_LOCALS; 459 BEGIN_BATCH(13); 460 OUT_BATCH(BRW_MEDIA_OBJECT|11); 461 OUT_BATCH(interface); 462 if (media_state.is_965_q) { 463 OUT_BATCH(0); 464 OUT_BATCH(0); 465 }else { 466 OUT_BATCH(6*128); 467 OUT_RELOC(media_state.indirect_data.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset); 468 } 469 470 OUT_BATCH(mb->x<<4); //g1.0 471 OUT_BATCH(mb->y<<4); 472 OUT_RELOC(media_state.indirect_data.bo, //g1.8 473 I915_GEM_DOMAIN_INSTRUCTION, 0, offset); 474 OUT_BATCH_SHORT(mb->coded_block_pattern); //g1.12 475 OUT_BATCH_SHORT(mb->PMV[0][0][0]); //g1.14 476 OUT_BATCH_SHORT(mb->PMV[0][0][1]); //g1.16 477 OUT_BATCH_SHORT(mb->PMV[0][1][0]); //g1.18 478 OUT_BATCH_SHORT(mb->PMV[0][1][1]); //g1.20 479 480 OUT_BATCH_SHORT(mb->PMV[1][0][0]); //g1.22 481 OUT_BATCH_SHORT(mb->PMV[1][0][1]); //g1.24 482 OUT_BATCH_SHORT(mb->PMV[1][1][0]); //g1.26 483 OUT_BATCH_SHORT(mb->PMV[1][1][1]); //g1.28 484 OUT_BATCH_CHAR(mb->dct_type); //g1.30 485 OUT_BATCH_CHAR(mb->motion_vertical_field_select);//g1.31 486 487 if (media_state.is_965_q) 488 OUT_BATCH(0x0); 489 else 490 OUT_BATCH(0xffffffff); 491 ADVANCE_BATCH(); 492} 493 494static Status binding_tables(struct media_state *media_state) 495{ 496 unsigned int binding_table[MAX_SURFACE_NUM]; 497 int i; 498 499 if (media_state->binding_table.bo) 500 drm_intel_bo_unreference(media_state->binding_table.bo); 501 media_state->binding_table.bo = 502 drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table", 503 MAX_SURFACE_NUM*4, 0x1000); 504 if (!media_state->binding_table.bo) 505 return BadAlloc; 506 507 for (i = 0; i < MAX_SURFACE_NUM; i++) 508 binding_table[i] = media_state->binding_table.surface_states[i].bo->offset; 509 drm_intel_bo_subdata(media_state->binding_table.bo, 0, sizeof(binding_table), 510 binding_table); 511 512 for (i = 0; i < MAX_SURFACE_NUM; i++) 513 drm_intel_bo_emit_reloc(media_state->binding_table.bo, 514 i * sizeof(unsigned int), 515 media_state->binding_table.surface_states[i].bo, 0, 516 I915_GEM_DOMAIN_INSTRUCTION, 0); 517 return Success; 518} 519 520static int media_kernels(struct media_state *media_state) 521{ 522 struct kernel_struct *kernels; 523 int kernel_array_size, i; 524 525 if (media_state->is_g4x) { 526 kernels = kernels_igd; 527 kernel_array_size = ARRAY_SIZE(kernels_igd); 528 } else { 529 kernels = kernels_965; 530 kernel_array_size = ARRAY_SIZE(kernels_965); 531 } 532 533 for (i = 0; i < kernel_array_size; i++) { 534 media_state->vfe_state.interface.kernels[i].bo = 535 drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel", 536 kernels[i].size, 0x1000); 537 if (!media_state->vfe_state.interface.kernels[i].bo) 538 goto out; 539 } 540 541 for (i = 0; i < kernel_array_size; i++) { 542 dri_bo *bo = media_state->vfe_state.interface.kernels[i].bo; 543 drm_intel_bo_subdata(bo, 0, kernels[i].size, kernels[i].bin); 544 } 545 return 0; 546out: 547 free_object(media_state); 548 return BadAlloc; 549} 550 551static void setup_interface(struct media_state *media_state, 552 enum interface i) 553{ 554 struct brw_interface_descriptor desc; 555 memset(&desc, 0, sizeof(desc)); 556 557 desc.desc0.grf_reg_blocks = 15; 558 desc.desc0.kernel_start_pointer = 559 media_state->vfe_state.interface.kernels[i].bo->offset >> 6; 560 561 desc.desc1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; 562 563 /* use same binding table for all interface 564 * may change this if it affect performance 565 */ 566 desc.desc3.binding_table_entry_count = MAX_SURFACE_NUM; 567 desc.desc3.binding_table_pointer = media_state->binding_table.bo->offset >> 5; 568 569 drm_intel_bo_subdata(media_state->vfe_state.interface.bo, i*sizeof(desc), 570 sizeof(desc), &desc); 571 572 drm_intel_bo_emit_reloc( 573 media_state->vfe_state.interface.bo, 574 i * sizeof(desc) + 575 offsetof(struct brw_interface_descriptor, desc0), 576 media_state->vfe_state.interface.kernels[i].bo, 577 desc.desc0.grf_reg_blocks, 578 I915_GEM_DOMAIN_INSTRUCTION, 0); 579 580 drm_intel_bo_emit_reloc( 581 media_state->vfe_state.interface.bo, 582 i * sizeof(desc) + 583 offsetof(struct brw_interface_descriptor, desc3), 584 media_state->binding_table.bo, 585 desc.desc3.binding_table_entry_count, 586 I915_GEM_DOMAIN_INSTRUCTION, 0); 587} 588 589static Status interface_descriptor(struct media_state *media_state) 590{ 591 if (media_state->vfe_state.interface.bo) 592 drm_intel_bo_unreference(media_state->vfe_state.interface.bo); 593 media_state->vfe_state.interface.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 594 "interfaces", DESCRIPTOR_NUM*sizeof(struct brw_interface_descriptor), 595 0x1000); 596 if (!media_state->vfe_state.interface.bo) 597 return BadAlloc; 598 599 setup_interface(media_state, INTRA_INTERFACE); 600 setup_interface(media_state, NULL_INTERFACE); 601 setup_interface(media_state, FORWARD_INTERFACE); 602 setup_interface(media_state, FIELD_FORWARD_INTERFACE); 603 setup_interface(media_state, BACKWARD_INTERFACE); 604 setup_interface(media_state, FIELD_BACKWARD_INTERFACE); 605 setup_interface(media_state, F_B_INTERFACE); 606 setup_interface(media_state, FIELD_F_B_INTERFACE); 607 setup_interface(media_state, DUAL_PRIME_INTERFACE); 608 return Success; 609} 610 611static Status vfe_state(struct media_state *media_state) 612{ 613 struct brw_vfe_state state; 614 memset(&state, 0, sizeof(state)); 615 616 /* no scratch space */ 617 state.vfe1.vfe_mode = VFE_GENERIC_MODE; 618 state.vfe1.num_urb_entries = 1; 619 /* XXX TODO */ 620 /* should carefully caculate those values for performance */ 621 state.vfe1.urb_entry_alloc_size = 2; 622 state.vfe1.max_threads = 31; 623 state.vfe2.interface_descriptor_base = 624 media_state->vfe_state.interface.bo->offset >> 4; 625 626 if (media_state->vfe_state.bo) 627 drm_intel_bo_unreference(media_state->vfe_state.bo); 628 media_state->vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 629 "vfe state", sizeof(struct brw_vfe_state), 0x1000); 630 if (!media_state->vfe_state.bo) 631 return BadAlloc; 632 633 drm_intel_bo_subdata(media_state->vfe_state.bo, 0, sizeof(state), &state); 634 635 drm_intel_bo_emit_reloc(media_state->vfe_state.bo, 636 offsetof(struct brw_vfe_state, vfe2), 637 media_state->vfe_state.interface.bo, 0, 638 I915_GEM_DOMAIN_INSTRUCTION, 0); 639 return Success; 640} 641 642static Status render_surface(Display *display, 643 XvMCContext *context, 644 unsigned int picture_structure, 645 XvMCSurface *target_surface, 646 XvMCSurface *past_surface, 647 XvMCSurface *future_surface, 648 unsigned int flags, 649 unsigned int num_macroblocks, 650 unsigned int first_macroblock, 651 XvMCMacroBlockArray *macroblock_array, 652 XvMCBlockArray *blocks) 653{ 654 655 intel_xvmc_context_ptr intel_ctx; 656 int i, j; 657 struct i965_xvmc_context *i965_ctx; 658 XvMCMacroBlock *mb; 659 struct i965_xvmc_surface *priv_target_surface = 660 target_surface->privData; 661 struct i965_xvmc_surface *priv_past_surface = 662 past_surface?past_surface->privData:0; 663 struct i965_xvmc_surface *priv_future_surface = 664 future_surface?future_surface->privData:0; 665 unsigned short *block_ptr; 666 intel_ctx = intel_xvmc_find_context(context->context_id); 667 i965_ctx = context->privData; 668 if (!intel_ctx) { 669 XVMC_ERR("Can't find intel xvmc context\n"); 670 return BadValue; 671 } 672 673 if (media_state.indirect_data.bo) { 674 if (xvmc_driver->kernel_exec_fencing) 675 drm_intel_gem_bo_unmap_gtt(media_state.indirect_data.bo); 676 else 677 drm_intel_bo_unmap(media_state.indirect_data.bo); 678 679 drm_intel_bo_unreference(media_state.indirect_data.bo); 680 } 681 media_state.indirect_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 682 "indirect data", 128*6*num_macroblocks, 64); 683 if (!media_state.indirect_data.bo) 684 return BadAlloc; 685 setup_surfaces(&media_state, 686 priv_target_surface->bo, 687 past_surface? priv_past_surface->bo:NULL, 688 future_surface?priv_future_surface->bo:NULL, 689 context->width, context->height); 690 setup_blocks(&media_state, 128*6*num_macroblocks); 691 binding_tables(&media_state); 692 interface_descriptor(&media_state); 693 vfe_state(&media_state); 694 695 if (xvmc_driver->kernel_exec_fencing) 696 drm_intel_gem_bo_map_gtt(media_state.indirect_data.bo); 697 else 698 drm_intel_bo_map(media_state.indirect_data.bo, 1); 699 700 block_ptr = media_state.indirect_data.bo->virtual; 701 for (i = first_macroblock; 702 i < num_macroblocks + first_macroblock; i++) { 703 unsigned short *mb_block_ptr; 704 mb = ¯oblock_array->macro_blocks[i]; 705 mb_block_ptr = &blocks->blocks[(mb->index<<6)]; 706 if (mb->coded_block_pattern & 0x20) { 707 for (j = 0; j < 8; j++) 708 memcpy(block_ptr + 16*j, mb_block_ptr + 8*j, 16); 709 mb_block_ptr += 64; 710 } 711 712 if (mb->coded_block_pattern & 0x10) { 713 for (j = 0; j < 8; j++) 714 memcpy(block_ptr + 16*j + 8, mb_block_ptr + 8*j, 16); 715 mb_block_ptr += 64; 716 } 717 block_ptr += 2*64; 718 if (mb->coded_block_pattern & 0x08) { 719 for (j = 0; j < 8; j++) 720 memcpy(block_ptr + 16*j, mb_block_ptr + 8*j, 16); 721 mb_block_ptr += 64; 722 } 723 724 if (mb->coded_block_pattern & 0x04) { 725 for (j = 0; j < 8; j++) 726 memcpy(block_ptr + 16*j + 8, mb_block_ptr + 8*j, 16); 727 mb_block_ptr += 64; 728 } 729 730 block_ptr += 2*64; 731 if (mb->coded_block_pattern & 0x2) { 732 memcpy(block_ptr, mb_block_ptr, 128); 733 mb_block_ptr += 64; 734 } 735 736 block_ptr += 64; 737 if (mb->coded_block_pattern & 0x1) 738 memcpy(block_ptr, mb_block_ptr, 128); 739 block_ptr += 64; 740 } 741 { 742 int block_offset = 0; 743 LOCK_HARDWARE(intel_ctx->hw_context); 744 state_base_address(); 745 flush(); 746 clear_sf_state(); 747 pipeline_select(&media_state); 748 urb_layout(); 749 media_state_pointers(&media_state); 750 for (i = first_macroblock; 751 i < num_macroblocks + first_macroblock; 752 i++, block_offset += 128*6) { 753 mb = ¯oblock_array->macro_blocks[i]; 754 755 if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 756 send_media_object(mb, block_offset, INTRA_INTERFACE); 757 } else { 758 if (((mb->motion_type & 3) == XVMC_PREDICTION_FRAME)) { 759 if ((mb->macroblock_type&XVMC_MB_TYPE_MOTION_FORWARD)) 760 { 761 if (((mb->macroblock_type&XVMC_MB_TYPE_MOTION_BACKWARD))) 762 send_media_object(mb, block_offset, F_B_INTERFACE); 763 else 764 send_media_object(mb, block_offset, FORWARD_INTERFACE); 765 } else if ((mb->macroblock_type&XVMC_MB_TYPE_MOTION_BACKWARD)) 766 { 767 send_media_object(mb, block_offset, BACKWARD_INTERFACE); 768 } 769 } else if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) { 770 if ((mb->macroblock_type&XVMC_MB_TYPE_MOTION_FORWARD)) 771 { 772 if (((mb->macroblock_type&XVMC_MB_TYPE_MOTION_BACKWARD))) 773 send_media_object(mb, block_offset, FIELD_F_B_INTERFACE); 774 else 775 776 send_media_object(mb, block_offset, FIELD_FORWARD_INTERFACE); 777 } else if ((mb->macroblock_type&XVMC_MB_TYPE_MOTION_BACKWARD)) 778 { 779 send_media_object(mb, block_offset, FIELD_BACKWARD_INTERFACE); 780 } 781 }else { 782 send_media_object(mb, block_offset, DUAL_PRIME_INTERFACE); 783 } 784 } 785 } 786 intelFlushBatch(TRUE); 787 UNLOCK_HARDWARE(intel_ctx->hw_context); 788 } 789 return Success; 790} 791 792static Status put_surface(Display *display,XvMCSurface *surface, 793 Drawable draw, short srcx, short srcy, 794 unsigned short srcw, unsigned short srch, 795 short destx, short desty, 796 unsigned short destw, unsigned short desth, 797 int flags, struct intel_xvmc_command *data) 798{ 799 struct i965_xvmc_surface *private_surface = 800 surface->privData; 801 uint32_t handle = 0; 802 803 drm_intel_bo_flink(private_surface->bo, &handle); 804 data->handle = handle; 805 806 return Success; 807} 808 809static Status get_surface_status(Display *display, 810 XvMCSurface *surface, int *stats) 811{ 812 *stats = 0; 813 return 0; 814} 815 816static Status create_context(Display *display, XvMCContext *context, 817 int priv_count, CARD32 *priv_data) 818{ 819 struct i965_xvmc_context *i965_ctx; 820 i965_ctx = (struct i965_xvmc_context *)priv_data; 821 context->privData = i965_ctx; 822 823 media_state.is_g4x = i965_ctx->is_g4x; 824 media_state.is_965_q = i965_ctx->is_965_q; 825 826 if (alloc_object(&media_state)) 827 return BadAlloc; 828 if (media_kernels(&media_state)) 829 return BadAlloc; 830 return Success; 831} 832 833struct _intel_xvmc_driver i965_xvmc_mc_driver = { 834 .type = XVMC_I965_MPEG2_MC, 835 .create_context = create_context, 836 .destroy_context = destroy_context, 837 .create_surface = create_surface, 838 .destroy_surface = destroy_surface, 839 .render_surface = render_surface, 840 .put_surface = put_surface, 841 .get_surface_status = get_surface_status, 842}; 843 844