1/* 2 * Copyright © 2009 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#include "intel_xvmc_private.h" 27#include "i830_reg.h" 28#include "i965_reg.h" 29#include "brw_defines.h" 30#include "brw_structs.h" 31 32#ifndef ALIGN 33#define ALIGN(m,n) (((m) + (n) - 1) & ~((n) - 1)) 34#endif 35 36#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0) 37#define VLD_MAX_SLICE_SIZE (32 * 1024) 38#define CS_SIZE 30 39#define URB_SIZE 384 40/* idct table */ 41#define C0 23170 42#define C1 22725 43#define C2 21407 44#define C3 19266 45#define C4 16383 46#define C5 12873 47#define C6 8867 48#define C7 4520 49const uint32_t idct_table[] = { 50 C4, C1, C2, C3, C4, C5, C6, C7, //g5 51 C4, C1, C2, C3, C4, C5, C6, C7, 52 C4, C3, C6, -C7, -C4, -C1, -C2, -C5, 53 C4, C3, C6, -C7, -C4, -C1, -C2, -C5, 54 C4, C5, -C6, -C1, -C4, C7, C2, C3, 55 C4, C5, -C6, -C1, -C4, C7, C2, C3, 56 C4, C7, -C2, -C5, C4, C3, -C6, -C1, 57 C4, C7, -C2, -C5, C4, C3, -C6, -C1, 58 C4, -C7, -C2, C5, C4, -C3, -C6, C1, 59 C4, -C7, -C2, C5, C4, -C3, -C6, C1, 60 C4, -C5, -C6, C1, -C4, -C7, C2, -C3, 61 C4, -C5, -C6, C1, -C4, -C7, C2, -C3, 62 C4, -C3, C6, C7, -C4, C1, -C2, C5, 63 C4, -C3, C6, C7, -C4, C1, -C2, C5, 64 C4, -C1, C2, -C3, C4, -C5, C6, -C7, 65 C4, -C1, C2, -C3, C4, -C5, C6, -C7 //g20 66}; 67 68#undef C0 69#undef C1 70#undef C2 71#undef C3 72#undef C4 73#undef C5 74#undef C6 75#undef C7 76 77#define INTERFACE_NUM 8 78enum interface { 79 FRAME_INTRA = 0, 80 FRAME_FRAME_PRED_FORWARD, 81 FRAME_FRAME_PRED_BACKWARD, 82 FRAME_FRAME_PRED_BIDIRECT, 83 FRAME_FIELD_PRED_FORWARD, 84 FRAME_FIELD_PRED_BACKWARD, 85 FRAME_FIELD_PRED_BIDIRECT, 86 LIB_INTERFACE 87}; 88 89/*kernels for vld mode*/ 90static uint32_t lib_kernel[][4] = { 91#include "shader/vld/lib.g4b" 92}; 93 94static uint32_t ipicture_kernel[][4] = { 95#include "shader/vld/ipicture.g4b" 96}; 97 98static uint32_t frame_forward_kernel[][4] = { 99#include "shader/vld/frame_forward.g4b" 100}; 101 102static uint32_t frame_backward_kernel[][4] = { 103#include "shader/vld/frame_backward.g4b" 104}; 105 106static uint32_t frame_f_b_kernel[][4] = { 107#include "shader/vld/frame_f_b.g4b" 108}; 109 110static uint32_t field_forward_kernel[][4] = { 111#include "shader/vld/field_forward.g4b" 112}; 113 114static uint32_t field_backward_kernel[][4] = { 115#include "shader/vld/field_backward.g4b" 116}; 117 118static uint32_t field_f_b_kernel[][4] = { 119#include "shader/vld/field_f_b.g4b" 120}; 121 122/* on Ironlake */ 123static uint32_t lib_kernel_gen5[][4] = { 124#include "shader/vld/lib.g4b.gen5" 125}; 126 127static uint32_t ipicture_kernel_gen5[][4] = { 128#include "shader/vld/ipicture.g4b.gen5" 129}; 130 131static uint32_t frame_forward_kernel_gen5[][4] = { 132#include "shader/vld/frame_forward.g4b.gen5" 133}; 134 135static uint32_t frame_backward_kernel_gen5[][4] = { 136#include "shader/vld/frame_backward.g4b.gen5" 137}; 138 139static uint32_t frame_f_b_kernel_gen5[][4] = { 140#include "shader/vld/frame_f_b.g4b.gen5" 141}; 142 143static uint32_t field_forward_kernel_gen5[][4] = { 144#include "shader/vld/field_forward.g4b.gen5" 145}; 146 147static uint32_t field_backward_kernel_gen5[][4] = { 148#include "shader/vld/field_backward.g4b.gen5" 149}; 150 151static uint32_t field_f_b_kernel_gen5[][4] = { 152#include "shader/vld/field_f_b.g4b.gen5" 153}; 154 155/*kernels for mc mode*/ 156static uint32_t lib_kernel_idct[][4] = { 157#include "shader/mc/lib_igd.g4b" 158}; 159 160static uint32_t ipicture_kernel_idct[][4] = { 161#include "shader/mc/ipicture_igd.g4b" 162}; 163 164static uint32_t frame_forward_kernel_idct[][4] = { 165#include "shader/mc/frame_forward_igd.g4b" 166}; 167 168static uint32_t frame_backward_kernel_idct[][4] = { 169#include "shader/mc/frame_backward_igd.g4b" 170}; 171 172static uint32_t frame_f_b_kernel_idct[][4] = { 173#include "shader/mc/frame_f_b_igd.g4b" 174}; 175 176static uint32_t field_forward_kernel_idct[][4] = { 177#include "shader/mc/field_forward_igd.g4b" 178}; 179 180static uint32_t field_backward_kernel_idct[][4] = { 181#include "shader/mc/field_backward_igd.g4b" 182}; 183 184static uint32_t field_f_b_kernel_idct[][4] = { 185#include "shader/mc/field_f_b_igd.g4b" 186}; 187 188/* on Ironlake */ 189static uint32_t lib_kernel_idct_gen5[][4] = { 190#include "shader/mc/lib_igd.g4b.gen5" 191}; 192 193static uint32_t ipicture_kernel_idct_gen5[][4] = { 194#include "shader/mc/ipicture_igd.g4b.gen5" 195}; 196 197static uint32_t frame_forward_kernel_idct_gen5[][4] = { 198#include "shader/mc/frame_forward_igd.g4b.gen5" 199}; 200 201static uint32_t frame_backward_kernel_idct_gen5[][4] = { 202#include "shader/mc/frame_backward_igd.g4b.gen5" 203}; 204 205static uint32_t frame_f_b_kernel_idct_gen5[][4] = { 206#include "shader/mc/frame_f_b_igd.g4b.gen5" 207}; 208 209static uint32_t field_forward_kernel_idct_gen5[][4] = { 210#include "shader/mc/field_forward_igd.g4b.gen5" 211}; 212 213static uint32_t field_backward_kernel_idct_gen5[][4] = { 214#include "shader/mc/field_backward_igd.g4b.gen5" 215}; 216 217static uint32_t field_f_b_kernel_idct_gen5[][4] = { 218#include "shader/mc/field_f_b_igd.g4b.gen5" 219}; 220 221struct media_kernel { 222 uint32_t(*bin)[4]; 223 int size; 224}; 225static struct media_kernel media_kernels[] = { 226 /*kernels for vld mode */ 227 {ipicture_kernel, sizeof(ipicture_kernel)} 228 , 229 {frame_forward_kernel, sizeof(frame_forward_kernel)} 230 , 231 {frame_backward_kernel, sizeof(frame_backward_kernel)} 232 , 233 {frame_f_b_kernel, sizeof(frame_f_b_kernel)} 234 , 235 {field_forward_kernel, sizeof(field_forward_kernel)} 236 , 237 {field_backward_kernel, sizeof(field_backward_kernel)} 238 , 239 {field_f_b_kernel, sizeof(field_f_b_kernel)} 240 , 241 {lib_kernel, sizeof(lib_kernel)} 242 , 243 /*kernels for mc mode */ 244 {ipicture_kernel_idct, sizeof(ipicture_kernel_idct)} 245 , 246 {frame_forward_kernel_idct, sizeof(frame_forward_kernel_idct)} 247 , 248 {frame_backward_kernel_idct, sizeof(frame_backward_kernel_idct)} 249 , 250 {frame_f_b_kernel_idct, sizeof(frame_f_b_kernel_idct)} 251 , 252 {field_forward_kernel_idct, sizeof(field_forward_kernel_idct)} 253 , 254 {field_backward_kernel_idct, sizeof(field_backward_kernel_idct)} 255 , 256 {field_f_b_kernel_idct, sizeof(field_f_b_kernel_idct)} 257 , 258 {lib_kernel_idct, sizeof(lib_kernel_idct)} 259}; 260 261static struct media_kernel media_gen5_kernels[] = { 262 /*kernels for vld mode */ 263 {ipicture_kernel_gen5, sizeof(ipicture_kernel_gen5)} 264 , 265 {frame_forward_kernel_gen5, sizeof(frame_forward_kernel_gen5)} 266 , 267 {frame_backward_kernel_gen5, sizeof(frame_backward_kernel_gen5)} 268 , 269 {frame_f_b_kernel_gen5, sizeof(frame_f_b_kernel_gen5)} 270 , 271 {field_forward_kernel_gen5, sizeof(field_forward_kernel_gen5)} 272 , 273 {field_backward_kernel_gen5, sizeof(field_backward_kernel_gen5)} 274 , 275 {field_f_b_kernel_gen5, sizeof(field_f_b_kernel_gen5)} 276 , 277 {lib_kernel_gen5, sizeof(lib_kernel_gen5)} 278 , 279 /*kernels for mc mode */ 280 {ipicture_kernel_idct_gen5, sizeof(ipicture_kernel_idct_gen5)} 281 , 282 {frame_forward_kernel_idct_gen5, sizeof(frame_forward_kernel_idct_gen5)} 283 , 284 {frame_backward_kernel_idct_gen5, 285 sizeof(frame_backward_kernel_idct_gen5)} 286 , 287 {frame_f_b_kernel_idct_gen5, sizeof(frame_f_b_kernel_idct_gen5)} 288 , 289 {field_forward_kernel_idct_gen5, sizeof(field_forward_kernel_idct_gen5)} 290 , 291 {field_backward_kernel_idct_gen5, 292 sizeof(field_backward_kernel_idct_gen5)} 293 , 294 {field_f_b_kernel_idct_gen5, sizeof(field_f_b_kernel_idct_gen5)} 295 , 296 {lib_kernel_idct_gen5, sizeof(lib_kernel_idct_gen5)} 297}; 298 299#define MEDIA_KERNEL_NUM (sizeof(media_kernels)/sizeof(media_kernels[0])) 300 301struct media_kernel_obj { 302 dri_bo *bo; 303}; 304 305struct interface_descriptor_obj { 306 dri_bo *bo; 307 struct media_kernel_obj kernels[MEDIA_KERNEL_NUM]; 308}; 309 310struct vfe_state_obj { 311 dri_bo *bo; 312 struct interface_descriptor_obj interface; 313}; 314 315struct vld_state_obj { 316 dri_bo *bo; 317}; 318 319struct surface_obj { 320 dri_bo *bo; 321}; 322 323struct surface_state_obj { 324 struct surface_obj surface; 325 dri_bo *bo; 326}; 327 328#define MAX_SURFACES 12 329struct binding_table_obj { 330 dri_bo *bo; 331 struct surface_state_obj surface_states[MAX_SURFACES]; 332}; 333 334struct slice_data_obj { 335 dri_bo *bo; 336}; 337 338struct mb_data_obj { 339 dri_bo *bo; 340}; 341 342struct cs_state_obj { 343 dri_bo *bo; 344}; 345 346static struct media_state { 347 struct vfe_state_obj vfe_state; 348 struct vld_state_obj vld_state; 349 struct binding_table_obj binding_table; 350 struct cs_state_obj cs_object; 351 struct slice_data_obj slice_data; 352 struct mb_data_obj mb_data; 353} media_state; 354 355/* XvMCQMatrix * 2 + idct_table + 8 * kernel offset pointer */ 356#define CS_OBJECT_SIZE (32*20 + sizeof(unsigned int) * 8) 357static void free_object(struct media_state *s) 358{ 359 int i; 360#define FREE_ONE_BO(bo) \ 361 if (bo) \ 362 drm_intel_bo_unreference(bo) 363 FREE_ONE_BO(s->vfe_state.bo); 364 FREE_ONE_BO(s->vfe_state.interface.bo); 365 for (i = 0; i < MEDIA_KERNEL_NUM; i++) 366 FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo); 367 FREE_ONE_BO(s->binding_table.bo); 368 for (i = 0; i < MAX_SURFACES; i++) 369 FREE_ONE_BO(s->binding_table.surface_states[i].bo); 370 FREE_ONE_BO(s->slice_data.bo); 371 FREE_ONE_BO(s->mb_data.bo); 372 FREE_ONE_BO(s->cs_object.bo); 373 FREE_ONE_BO(s->vld_state.bo); 374} 375 376static int alloc_object(struct media_state *s) 377{ 378 int i; 379 380 for (i = 0; i < MAX_SURFACES; i++) { 381 s->binding_table.surface_states[i].bo = 382 drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 383 sizeof(struct brw_surface_state), 384 0x1000); 385 if (!s->binding_table.surface_states[i].bo) 386 goto out; 387 } 388 return 0; 389out: 390 free_object(s); 391 return BadAlloc; 392} 393 394static void flush() 395{ 396#define FLUSH_STATE_CACHE 1 397 struct brw_mi_flush f; 398 memset(&f, 0, sizeof(f)); 399 f.opcode = CMD_MI_FLUSH; 400 f.flags = (1 << FLUSH_STATE_CACHE); 401 BATCH_STRUCT(f); 402} 403 404static Status vfe_state(int vfe_mode) 405{ 406 struct brw_vfe_state tmp, *vfe_state = &tmp; 407 memset(vfe_state, 0, sizeof(*vfe_state)); 408 if (vfe_mode == VFE_VLD_MODE) { 409 vfe_state->vfe0.extend_vfe_state_present = 1; 410 } else { 411 vfe_state->vfe0.extend_vfe_state_present = 0; 412 } 413 vfe_state->vfe1.vfe_mode = vfe_mode; 414 vfe_state->vfe1.num_urb_entries = 1; 415 vfe_state->vfe1.children_present = 0; 416 vfe_state->vfe1.urb_entry_alloc_size = 2; 417 vfe_state->vfe1.max_threads = 31; 418 vfe_state->vfe2.interface_descriptor_base = 419 media_state.vfe_state.interface.bo->offset >> 4; 420 421 if (media_state.vfe_state.bo) 422 drm_intel_bo_unreference(media_state.vfe_state.bo); 423 424 media_state.vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 425 "vfe state", 426 sizeof(struct 427 brw_vfe_state), 428 0x1000); 429 if (!media_state.vfe_state.bo) 430 return BadAlloc; 431 432 drm_intel_bo_subdata(media_state.vfe_state.bo, 0, sizeof(tmp), &tmp); 433 434 drm_intel_bo_emit_reloc(media_state.vfe_state.bo, 435 offsetof(struct brw_vfe_state, vfe2), 436 media_state.vfe_state.interface.bo, 0, 437 I915_GEM_DOMAIN_INSTRUCTION, 0); 438 return Success; 439} 440 441static Status interface_descriptor() 442{ 443 int i; 444 struct brw_interface_descriptor tmp, *desc = &tmp; 445 446 if (media_state.vfe_state.interface.bo) 447 drm_intel_bo_unreference(media_state.vfe_state.interface.bo); 448 449 media_state.vfe_state.interface.bo = 450 drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces", 451 MEDIA_KERNEL_NUM * 452 sizeof(struct brw_interface_descriptor), 0x1000); 453 if (!media_state.vfe_state.interface.bo) 454 return BadAlloc; 455 456 for (i = 0; i < MEDIA_KERNEL_NUM; i++) { 457 memset(desc, 0, sizeof(*desc)); 458 desc->desc0.grf_reg_blocks = 15; 459 desc->desc0.kernel_start_pointer = 460 media_state.vfe_state.interface.kernels[i].bo->offset >> 6; 461 462 desc->desc1.const_urb_entry_read_offset = 0; 463 desc->desc1.const_urb_entry_read_len = 30; 464 465 desc->desc3.binding_table_entry_count = MAX_SURFACES - 1; 466 desc->desc3.binding_table_pointer = 467 media_state.binding_table.bo->offset >> 5; 468 469 drm_intel_bo_subdata(media_state.vfe_state.interface.bo, 470 i * sizeof(tmp), sizeof(tmp), desc); 471 472 drm_intel_bo_emit_reloc(media_state.vfe_state.interface.bo, 473 i * sizeof(*desc) + offsetof(struct 474 brw_interface_descriptor, 475 desc0), 476 media_state.vfe_state. 477 interface.kernels[i].bo, 478 desc->desc0.grf_reg_blocks, 479 I915_GEM_DOMAIN_INSTRUCTION, 0); 480 481 drm_intel_bo_emit_reloc(media_state.vfe_state.interface.bo, 482 i * sizeof(*desc) + offsetof(struct 483 brw_interface_descriptor, 484 desc3), 485 media_state.binding_table.bo, 486 desc->desc3.binding_table_entry_count, 487 I915_GEM_DOMAIN_INSTRUCTION, 0); 488 } 489 return Success; 490} 491 492static int setup_media_kernels(struct intel_xvmc_hw_context *ctx) 493{ 494 int i; 495 496 assert(MEDIA_KERNEL_NUM == 497 sizeof(media_gen5_kernels) / sizeof(media_gen5_kernels[0])); 498 499 for (i = 0; i < MEDIA_KERNEL_NUM; i++) { 500 if (ctx->i965.is_igdng) 501 media_state.vfe_state.interface.kernels[i].bo = 502 drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel", 503 media_gen5_kernels[i].size, 504 0x1000); 505 else 506 media_state.vfe_state.interface.kernels[i].bo = 507 drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernels", 508 media_kernels[i].size, 0x1000); 509 510 if (!media_state.vfe_state.interface.kernels[i].bo) 511 goto out; 512 } 513 514 for (i = 0; i < MEDIA_KERNEL_NUM; i++) { 515 dri_bo *bo = media_state.vfe_state.interface.kernels[i].bo; 516 517 if (ctx->i965.is_igdng) 518 drm_intel_bo_subdata(bo, 0, media_gen5_kernels[i].size, 519 media_gen5_kernels[i].bin); 520 else 521 drm_intel_bo_subdata(bo, 0, media_kernels[i].size, 522 media_kernels[i].bin); 523 } 524 return 0; 525out: 526 free_object(&media_state); 527 return BadAlloc; 528} 529 530static Status binding_tables() 531{ 532 unsigned int table[MAX_SURFACES]; 533 int i; 534 535 if (media_state.binding_table.bo) 536 drm_intel_bo_unreference(media_state.binding_table.bo); 537 media_state.binding_table.bo = 538 drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table", 539 MAX_SURFACES * 4, 0x1000); 540 if (!media_state.binding_table.bo) 541 return BadAlloc; 542 543 for (i = 0; i < MAX_SURFACES; i++) { 544 table[i] = 545 media_state.binding_table.surface_states[i].bo->offset; 546 drm_intel_bo_emit_reloc(media_state.binding_table.bo, 547 i * sizeof(unsigned int), 548 media_state. 549 binding_table.surface_states[i].bo, 0, 550 I915_GEM_DOMAIN_INSTRUCTION, 0); 551 } 552 553 drm_intel_bo_subdata(media_state.binding_table.bo, 0, sizeof(table), 554 table); 555 return Success; 556} 557 558static Status cs_init(int interface_offset) 559{ 560 char buf[CS_OBJECT_SIZE]; 561 unsigned int *lib_reloc; 562 int i; 563 564 if (media_state.cs_object.bo) 565 drm_intel_bo_unreference(media_state.cs_object.bo); 566 567 media_state.cs_object.bo = 568 drm_intel_bo_alloc(xvmc_driver->bufmgr, "cs object", CS_OBJECT_SIZE, 569 64); 570 if (!media_state.cs_object.bo) 571 return BadAlloc; 572 573 memcpy(buf + 32 * 4, idct_table, sizeof(idct_table)); 574 /* idct lib reloction */ 575 lib_reloc = (unsigned int *)(buf + 32 * 20); 576 for (i = 0; i < 8; i++) 577 lib_reloc[i] = 578 media_state.vfe_state.interface.kernels[LIB_INTERFACE + 579 interface_offset].bo-> 580 offset; 581 drm_intel_bo_subdata(media_state.cs_object.bo, 32 * 4, 582 32 * 16 + 8 * sizeof(unsigned int), buf + 32 * 4); 583 584 for (i = 0; i < 8; i++) 585 drm_intel_bo_emit_reloc(media_state.cs_object.bo, 586 32 * 20 + sizeof(unsigned int) * i, 587 media_state.vfe_state. 588 interface.kernels[LIB_INTERFACE + 589 interface_offset].bo, 590 0, I915_GEM_DOMAIN_INSTRUCTION, 0); 591 592 return Success; 593} 594 595#define STRIDE(w) (w) 596#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1))) 597static Status create_context(Display * display, XvMCContext * context, 598 int priv_count, CARD32 * priv_data) 599{ 600 struct intel_xvmc_context *intel_ctx; 601 struct intel_xvmc_hw_context *hw_ctx; 602 hw_ctx = (struct intel_xvmc_hw_context *)priv_data; 603 604 intel_ctx = calloc(1, sizeof(struct intel_xvmc_context)); 605 if (!intel_ctx) 606 return BadAlloc; 607 intel_ctx->hw = hw_ctx; 608 context->privData = intel_ctx; 609 intel_ctx->surface_bo_size 610 = SIZE_YUV420(context->width, context->height); 611 612 if (alloc_object(&media_state)) 613 return BadAlloc; 614 615 if (setup_media_kernels(hw_ctx)) 616 return BadAlloc; 617 return Success; 618} 619 620static Status destroy_context(Display * display, XvMCContext * context) 621{ 622 struct intel_xvmc_context *intel_ctx; 623 intel_ctx = context->privData; 624 free(intel_ctx->hw); 625 free(intel_ctx); 626 return Success; 627} 628 629static Status load_qmatrix(Display * display, XvMCContext * context, 630 const XvMCQMatrix * qmx) 631{ 632 Status ret; 633 ret = cs_init(0); 634 if (ret != Success) 635 return ret; 636 drm_intel_bo_subdata(media_state.cs_object.bo, 0, 64, 637 qmx->intra_quantiser_matrix); 638 drm_intel_bo_subdata(media_state.cs_object.bo, 64, 64, 639 qmx->non_intra_quantiser_matrix); 640 641 return Success; 642} 643 644static Status vld_state(const XvMCMpegControl * control) 645{ 646 struct brw_vld_state tmp, *vld = &tmp; 647 648 if (media_state.vld_state.bo) 649 drm_intel_bo_unreference(media_state.vld_state.bo); 650 media_state.vld_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 651 "vld state", 652 sizeof(struct 653 brw_vld_state), 654 64); 655 if (!media_state.vld_state.bo) 656 return BadAlloc; 657 658 memset(vld, 0, sizeof(*vld)); 659 vld->vld0.f_code_0_0 = control->FHMV_range + 1; 660 vld->vld0.f_code_0_1 = control->FVMV_range + 1; 661 vld->vld0.f_code_1_0 = control->BHMV_range + 1; 662 vld->vld0.f_code_1_1 = control->BVMV_range + 1; 663 vld->vld0.intra_dc_precision = control->intra_dc_precision; 664 vld->vld0.picture_structure = control->picture_structure; 665 vld->vld0.top_field_first = !!(control->flags & XVMC_TOP_FIELD_FIRST); 666 vld->vld0.frame_predict_frame_dct = 667 !!(control->flags & XVMC_PRED_DCT_FRAME); 668 vld->vld0.concealment_motion_vector = 669 !!(control->flags & XVMC_CONCEALMENT_MOTION_VECTORS); 670 vld->vld0.quantizer_scale_type = !!(control->flags & XVMC_Q_SCALE_TYPE); 671 vld->vld0.intra_vlc_format = !!(control->flags & XVMC_INTRA_VLC_FORMAT); 672 vld->vld0.scan_order = !!(control->flags & XVMC_ALTERNATE_SCAN); 673 674 vld->vld1.picture_coding_type = control->picture_coding_type; 675 676 vld->desc_remap_table0.index_0 = FRAME_INTRA; 677 vld->desc_remap_table0.index_1 = FRAME_FRAME_PRED_FORWARD; 678 vld->desc_remap_table0.index_2 = FRAME_FIELD_PRED_FORWARD; 679 vld->desc_remap_table0.index_3 = FRAME_FIELD_PRED_BIDIRECT; /* dual prime */ 680 vld->desc_remap_table0.index_4 = FRAME_FRAME_PRED_BACKWARD; 681 vld->desc_remap_table0.index_5 = FRAME_FIELD_PRED_BACKWARD; 682 vld->desc_remap_table0.index_6 = FRAME_FRAME_PRED_BIDIRECT; 683 vld->desc_remap_table0.index_7 = FRAME_FIELD_PRED_BIDIRECT; 684 685 vld->desc_remap_table1.index_8 = FRAME_INTRA; 686 vld->desc_remap_table1.index_9 = FRAME_FRAME_PRED_FORWARD; 687 vld->desc_remap_table1.index_10 = FRAME_FIELD_PRED_FORWARD; 688 vld->desc_remap_table1.index_11 = FRAME_FIELD_PRED_BIDIRECT; 689 vld->desc_remap_table1.index_12 = FRAME_FRAME_PRED_BACKWARD; 690 vld->desc_remap_table1.index_13 = FRAME_FIELD_PRED_BACKWARD; 691 vld->desc_remap_table1.index_14 = FRAME_FRAME_PRED_BIDIRECT; 692 vld->desc_remap_table1.index_15 = FRAME_FIELD_PRED_BIDIRECT; 693 694 drm_intel_bo_subdata(media_state.vld_state.bo, 0, sizeof(tmp), vld); 695 return Success; 696} 697 698static Status setup_media_surface(int index, dri_bo * bo, 699 unsigned long offset, int w, int h, 700 Bool write) 701{ 702 struct brw_surface_state tmp, *ss = &tmp; 703 memset(ss, 0, sizeof(*ss)); 704 ss->ss0.surface_type = BRW_SURFACE_2D; 705 ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT; 706 ss->ss1.base_addr = offset + bo->offset; 707 ss->ss2.width = w - 1; 708 ss->ss2.height = h - 1; 709 ss->ss3.pitch = w - 1; 710 711 if (media_state.binding_table.surface_states[index].bo) 712 drm_intel_bo_unreference(media_state. 713 binding_table.surface_states[index]. 714 bo); 715 716 media_state.binding_table.surface_states[index].bo = 717 drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 718 sizeof(struct brw_surface_state), 0x1000); 719 if (!media_state.binding_table.surface_states[index].bo) 720 return BadAlloc; 721 722 drm_intel_bo_subdata(media_state.binding_table.surface_states[index].bo, 723 0, sizeof(*ss), ss); 724 drm_intel_bo_emit_reloc(media_state.binding_table. 725 surface_states[index].bo, 726 offsetof(struct brw_surface_state, ss1), bo, 727 offset, I915_GEM_DOMAIN_RENDER, 728 write ? I915_GEM_DOMAIN_RENDER : 0); 729 return Success; 730} 731 732static Status setup_surface(struct intel_xvmc_surface *target, 733 struct intel_xvmc_surface *past, 734 struct intel_xvmc_surface *future, int w, int h) 735{ 736 Status ret; 737 ret = setup_media_surface(0, target->bo, 0, w, h, TRUE); 738 if (ret != Success) 739 return ret; 740 ret = setup_media_surface(1, target->bo, w * h, w / 2, h / 2, TRUE); 741 if (ret != Success) 742 return ret; 743 ret = 744 setup_media_surface(2, target->bo, w * h + w * h / 4, w / 2, h / 2, 745 TRUE); 746 if (ret != Success) 747 return ret; 748 if (past) { 749 ret = setup_media_surface(4, past->bo, 0, w, h, FALSE); 750 if (ret != Success) 751 return ret; 752 ret = 753 setup_media_surface(5, past->bo, w * h, w / 2, h / 2, 754 FALSE); 755 if (ret != Success) 756 return ret; 757 ret = 758 setup_media_surface(6, past->bo, w * h + w * h / 4, w / 2, 759 h / 2, FALSE); 760 if (ret != Success) 761 return ret; 762 } 763 if (future) { 764 ret = setup_media_surface(7, future->bo, 0, w, h, FALSE); 765 if (ret != Success) 766 return ret; 767 ret = 768 setup_media_surface(8, future->bo, w * h, w / 2, h / 2, 769 FALSE); 770 if (ret != Success) 771 return ret; 772 ret = 773 setup_media_surface(9, future->bo, w * h + w * h / 4, w / 2, 774 h / 2, FALSE); 775 if (ret != Success) 776 return ret; 777 } 778 return Success; 779} 780 781static Status begin_surface(Display * display, XvMCContext * context, 782 XvMCSurface * target, 783 XvMCSurface * past, 784 XvMCSurface * future, 785 const XvMCMpegControl * control) 786{ 787 struct intel_xvmc_surface *priv_target, *priv_past, *priv_future; 788 intel_xvmc_context_ptr intel_ctx = context->privData; 789 Status ret; 790 791 priv_target = target->privData; 792 priv_past = past ? past->privData : NULL; 793 priv_future = future ? future->privData : NULL; 794 795 ret = vld_state(control); 796 if (ret != Success) 797 return ret; 798 ret = setup_surface(priv_target, priv_past, priv_future, 799 context->width, context->height); 800 if (ret != Success) 801 return ret; 802 ret = binding_tables(); 803 if (ret != Success) 804 return ret; 805 ret = interface_descriptor(); 806 if (ret != Success) 807 return ret; 808 ret = vfe_state(VFE_VLD_MODE); 809 if (ret != Success) 810 return ret; 811 812 LOCK_HARDWARE(intel_ctx->hw_context); 813 flush(); 814 UNLOCK_HARDWARE(intel_ctx->hw_context); 815 return Success; 816} 817 818static Status put_slice(Display * display, XvMCContext * context, 819 unsigned char *slice, int nbytes) 820{ 821 return Success; 822} 823 824static void state_base_address(struct intel_xvmc_hw_context *ctx) 825{ 826 BATCH_LOCALS; 827 828 if (ctx->i965.is_igdng) { 829 BEGIN_BATCH(8); 830 OUT_BATCH(BRW_STATE_BASE_ADDRESS | 6); 831 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 832 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 833 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 834 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 835 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 836 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 837 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 838 ADVANCE_BATCH(); 839 } else { 840 BEGIN_BATCH(6); 841 OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4); 842 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 843 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 844 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 845 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 846 OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 847 ADVANCE_BATCH(); 848 } 849} 850 851static void pipeline_select() 852{ 853 BATCH_LOCALS; 854 BEGIN_BATCH(1); 855 OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); 856 ADVANCE_BATCH(); 857} 858 859static void media_state_pointers(int vfe_mode) 860{ 861 BATCH_LOCALS; 862 BEGIN_BATCH(3); 863 OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1); 864 if (vfe_mode == VFE_VLD_MODE) 865 OUT_RELOC(media_state.vld_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 866 0, 1); 867 else 868 OUT_BATCH(0); 869 OUT_RELOC(media_state.vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); 870 ADVANCE_BATCH(); 871} 872 873static void align_urb_fence() 874{ 875 BATCH_LOCALS; 876 int i, offset_to_next_cacheline; 877 unsigned long batch_offset; 878 BEGIN_BATCH(3); 879 batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr; 880 offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset; 881 if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) { 882 for (i = 0; i < offset_to_next_cacheline / 4; i++) 883 OUT_BATCH(0); 884 ADVANCE_BATCH(); 885 } 886} 887 888static void urb_layout() 889{ 890 BATCH_LOCALS; 891 align_urb_fence(); 892 BEGIN_BATCH(3); 893 OUT_BATCH(BRW_URB_FENCE | 894 UF0_VFE_REALLOC | 895 UF0_CS_REALLOC | 896 UF0_SF_REALLOC | 897 UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1); 898 899 OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) | 900 (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT)); 901 902 OUT_BATCH((0 << UF2_CS_FENCE_SHIFT) | (0 << UF2_SF_FENCE_SHIFT) | ((URB_SIZE - CS_SIZE - 1) << UF2_VFE_FENCE_SHIFT) | /* VFE_SIZE */ 903 ((URB_SIZE) << UF2_CS_FENCE_SHIFT)); /* CS_SIZE */ 904 ADVANCE_BATCH(); 905} 906 907static void cs_urb_layout() 908{ 909 BATCH_LOCALS; 910 BEGIN_BATCH(2); 911 OUT_BATCH(BRW_CS_URB_STATE | 0); 912 OUT_BATCH((CS_SIZE << 4) | /* URB Entry Allocation Size */ 913 (1 << 0)); /* Number of URB Entries */ 914 ADVANCE_BATCH(); 915} 916 917static void cs_buffer() 918{ 919 BATCH_LOCALS; 920 BEGIN_BATCH(2); 921 OUT_BATCH(BRW_CONSTANT_BUFFER | 0 | (1 << 8)); 922 OUT_RELOC(media_state.cs_object.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 923 CS_SIZE); 924 ADVANCE_BATCH(); 925} 926 927/* kick media object to gpu in idct mode*/ 928static void send_media_object(XvMCMacroBlock * mb, dri_bo * bo, 929 uint32_t offset, enum interface interface) 930{ 931 BATCH_LOCALS; 932 BEGIN_BATCH(13); 933 OUT_BATCH(BRW_MEDIA_OBJECT | 11); 934 OUT_BATCH(interface); 935 OUT_BATCH(6 * 128); 936 OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset); 937 938 OUT_BATCH(mb->x << 4); 939 OUT_BATCH(mb->y << 4); 940 OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset); 941 OUT_BATCH_SHORT(mb->coded_block_pattern); 942 OUT_BATCH_SHORT(mb->PMV[0][0][0]); 943 OUT_BATCH_SHORT(mb->PMV[0][0][1]); 944 OUT_BATCH_SHORT(mb->PMV[0][1][0]); 945 OUT_BATCH_SHORT(mb->PMV[0][1][1]); 946 947 OUT_BATCH_SHORT(mb->PMV[1][0][0]); 948 OUT_BATCH_SHORT(mb->PMV[1][0][1]); 949 OUT_BATCH_SHORT(mb->PMV[1][1][0]); 950 OUT_BATCH_SHORT(mb->PMV[1][1][1]); 951 OUT_BATCH_CHAR(mb->dct_type); 952 OUT_BATCH_CHAR(mb->motion_vertical_field_select); 953 954 OUT_BATCH(0xffffffff); 955 ADVANCE_BATCH(); 956} 957 958/* kick media object to gpu in vld mode*/ 959static void vld_send_media_object(dri_bo * bo, 960 int slice_len, int mb_h_pos, int mb_v_pos, 961 int mb_bit_offset, int mb_count, 962 int q_scale_code) 963{ 964 BATCH_LOCALS; 965 BEGIN_BATCH(6); 966 OUT_BATCH(BRW_MEDIA_OBJECT | 4); 967 OUT_BATCH(0); 968 OUT_BATCH(slice_len); 969 OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); 970 OUT_BATCH((mb_h_pos << 24) | (mb_v_pos << 16) | (mb_count << 8) | 971 (mb_bit_offset)); 972 OUT_BATCH(q_scale_code << 24); 973 ADVANCE_BATCH(); 974} 975 976static Status put_slice2(Display * display, XvMCContext * context, 977 unsigned char *slice, int nbytes, int sliceCode) 978{ 979 unsigned int bit_buf; 980 intel_xvmc_context_ptr intel_ctx = context->privData; 981 struct intel_xvmc_hw_context *hw_ctx = intel_ctx->hw; 982 int q_scale_code, mb_row; 983 984 mb_row = *(slice - 1) - 1; 985 bit_buf = 986 (slice[0] << 24) | (slice[1] << 16) | (slice[2] << 8) | (slice[3]); 987 988 q_scale_code = bit_buf >> 27; 989 990 if (media_state.slice_data.bo) { 991 drm_intel_gem_bo_unmap_gtt(media_state.slice_data.bo); 992 993 drm_intel_bo_unreference(media_state.slice_data.bo); 994 } 995 media_state.slice_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 996 "slice data", 997 VLD_MAX_SLICE_SIZE, 64); 998 if (!media_state.slice_data.bo) 999 return BadAlloc; 1000 drm_intel_gem_bo_map_gtt(media_state.slice_data.bo); 1001 1002 memcpy(media_state.slice_data.bo->virtual, slice, nbytes); 1003 1004 LOCK_HARDWARE(intel_ctx->hw_context); 1005 state_base_address(hw_ctx); 1006 pipeline_select(); 1007 media_state_pointers(VFE_VLD_MODE); 1008 urb_layout(); 1009 cs_urb_layout(); 1010 cs_buffer(); 1011 vld_send_media_object(media_state.slice_data.bo, 1012 nbytes, 0, mb_row, 6, 127, q_scale_code); 1013 intelFlushBatch(); 1014 UNLOCK_HARDWARE(intel_ctx->hw_context); 1015 1016 return Success; 1017} 1018 1019static Status render_surface(Display * display, 1020 XvMCContext * context, 1021 unsigned int picture_structure, 1022 XvMCSurface * target_surface, 1023 XvMCSurface * past_surface, 1024 XvMCSurface * future_surface, 1025 unsigned int flags, 1026 unsigned int num_macroblocks, 1027 unsigned int first_macroblock, 1028 XvMCMacroBlockArray * macroblock_array, 1029 XvMCBlockArray * blocks) 1030{ 1031 struct intel_xvmc_surface *priv_target, *priv_past, *priv_future; 1032 intel_xvmc_context_ptr intel_ctx; 1033 XvMCMacroBlock *mb; 1034 Status ret; 1035 unsigned short *block_ptr; 1036 int i, j; 1037 int block_offset = 0; 1038 struct intel_xvmc_hw_context *hw_ctx; 1039 1040 intel_ctx = context->privData; 1041 1042 hw_ctx = (struct intel_xvmc_hw_context *)context->privData; 1043 priv_target = target_surface->privData; 1044 priv_past = past_surface ? past_surface->privData : NULL; 1045 priv_future = future_surface ? future_surface->privData : NULL; 1046 1047 ret = setup_surface(priv_target, priv_past, priv_future, 1048 context->width, context->height); 1049 if (ret != Success) 1050 return ret; 1051 ret = binding_tables(); 1052 if (ret != Success) 1053 return ret; 1054 ret = interface_descriptor(); 1055 if (ret != Success) 1056 return ret; 1057 ret = cs_init(INTERFACE_NUM); 1058 if (ret != Success) 1059 return ret; 1060 ret = vfe_state(VFE_GENERIC_MODE); 1061 if (ret != Success) 1062 return ret; 1063 1064 if (media_state.mb_data.bo) { 1065 drm_intel_gem_bo_unmap_gtt(media_state.mb_data.bo); 1066 1067 drm_intel_bo_unreference(media_state.mb_data.bo); 1068 } 1069 unsigned int block_num = 1070 (((context->width + 15) >> 4) * ((context->height + 15) >> 4)); 1071 unsigned int surface_size = (64 * sizeof(short) * 6 * block_num); 1072 media_state.mb_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 1073 "macroblock data", 1074 surface_size, 64); 1075 if (!media_state.mb_data.bo) 1076 return BadAlloc; 1077 drm_intel_gem_bo_map_gtt(media_state.mb_data.bo); 1078 1079 block_ptr = media_state.mb_data.bo->virtual; 1080 unsigned short *mb_block_ptr; 1081 for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) { 1082 mb = ¯oblock_array->macro_blocks[i]; 1083 mb_block_ptr = &blocks->blocks[(mb->index << 6)]; 1084 1085 if (mb->coded_block_pattern & 0x20) { 1086 for (j = 0; j < 8; j++) 1087 memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j, 1088 16); 1089 mb_block_ptr += 64; 1090 } 1091 if (mb->coded_block_pattern & 0x10) { 1092 for (j = 0; j < 8; j++) 1093 memcpy(block_ptr + 16 * j + 8, 1094 mb_block_ptr + 8 * j, 16); 1095 mb_block_ptr += 64; 1096 } 1097 1098 block_ptr += 2 * 64; 1099 if (mb->coded_block_pattern & 0x08) { 1100 for (j = 0; j < 8; j++) 1101 memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j, 1102 16); 1103 mb_block_ptr += 64; 1104 } 1105 if (mb->coded_block_pattern & 0x04) { 1106 for (j = 0; j < 8; j++) 1107 memcpy(block_ptr + 16 * j + 8, 1108 mb_block_ptr + 8 * j, 16); 1109 mb_block_ptr += 64; 1110 } 1111 1112 block_ptr += 2 * 64; 1113 if (mb->coded_block_pattern & 0x2) { 1114 memcpy(block_ptr, mb_block_ptr, 128); 1115 mb_block_ptr += 64; 1116 } 1117 1118 block_ptr += 64; 1119 if (mb->coded_block_pattern & 0x1) 1120 memcpy(block_ptr, mb_block_ptr, 128); 1121 block_ptr += 64; 1122 } 1123 1124 LOCK_HARDWARE(intel_ctx->hw_context); 1125 state_base_address(hw_ctx); 1126 flush(); 1127 pipeline_select(); 1128 urb_layout(); 1129 media_state_pointers(VFE_GENERIC_MODE); 1130 cs_urb_layout(); 1131 cs_buffer(); 1132 for (i = first_macroblock; 1133 i < num_macroblocks + first_macroblock; 1134 i++, block_offset += 128 * 6) { 1135 mb = ¯oblock_array->macro_blocks[i]; 1136 1137 if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 1138 send_media_object(mb, media_state.mb_data.bo, 1139 block_offset, 1140 FRAME_INTRA + INTERFACE_NUM); 1141 } else { 1142 if (((mb->motion_type & 3) == XVMC_PREDICTION_FRAME)) { 1143 if ((mb->macroblock_type & 1144 XVMC_MB_TYPE_MOTION_FORWARD)) { 1145 if ((mb->macroblock_type & 1146 XVMC_MB_TYPE_MOTION_BACKWARD)) { 1147 send_media_object(mb, 1148 media_state.mb_data. 1149 bo, 1150 block_offset, 1151 FRAME_FRAME_PRED_BIDIRECT 1152 + 1153 INTERFACE_NUM); 1154 } else { 1155 send_media_object(mb, 1156 media_state.mb_data. 1157 bo, 1158 block_offset, 1159 FRAME_FRAME_PRED_FORWARD 1160 + 1161 INTERFACE_NUM); 1162 } 1163 } else 1164 if ((mb->macroblock_type & 1165 XVMC_MB_TYPE_MOTION_BACKWARD)) { 1166 send_media_object(mb, 1167 media_state. 1168 mb_data.bo, 1169 block_offset, 1170 FRAME_FRAME_PRED_BACKWARD 1171 + INTERFACE_NUM); 1172 } 1173 } else if ((mb->motion_type & 3) == 1174 XVMC_PREDICTION_FIELD) { 1175 if ((mb->macroblock_type & 1176 XVMC_MB_TYPE_MOTION_FORWARD)) { 1177 if (((mb->macroblock_type & 1178 XVMC_MB_TYPE_MOTION_BACKWARD))) { 1179 send_media_object(mb, 1180 media_state.mb_data. 1181 bo, 1182 block_offset, 1183 FRAME_FIELD_PRED_BIDIRECT 1184 + 1185 INTERFACE_NUM); 1186 } else { 1187 send_media_object(mb, 1188 media_state.mb_data. 1189 bo, 1190 block_offset, 1191 FRAME_FIELD_PRED_FORWARD 1192 + 1193 INTERFACE_NUM); 1194 } 1195 } else 1196 if ((mb->macroblock_type & 1197 XVMC_MB_TYPE_MOTION_BACKWARD)) { 1198 send_media_object(mb, 1199 media_state. 1200 mb_data.bo, 1201 block_offset, 1202 FRAME_FIELD_PRED_BACKWARD 1203 + INTERFACE_NUM); 1204 } 1205 } else { 1206 send_media_object(mb, media_state.mb_data.bo, block_offset, FRAME_FIELD_PRED_BIDIRECT + INTERFACE_NUM); /*dual prime */ 1207 } 1208 } 1209 } 1210 intelFlushBatch(); 1211 UNLOCK_HARDWARE(intel_ctx->hw_context); 1212 return Success; 1213} 1214 1215struct _intel_xvmc_driver xvmc_vld_driver = { 1216 .type = XVMC_I965_MPEG2_VLD, 1217 .create_context = create_context, 1218 .destroy_context = destroy_context, 1219 .load_qmatrix = load_qmatrix, 1220 .begin_surface = begin_surface, 1221 .render_surface = render_surface, 1222 .put_slice = put_slice, 1223 .put_slice2 = put_slice2 1224}; 1225