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