1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 2008 Intel Corporation 3428d7b3dSmrg * 4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"), 6428d7b3dSmrg * to deal in the Software without restriction, including without limitation 7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions: 10428d7b3dSmrg * 11428d7b3dSmrg * The above copyright notice and this permission notice (including the next 12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the 13428d7b3dSmrg * Software. 14428d7b3dSmrg * 15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21428d7b3dSmrg * SOFTWARE. 22428d7b3dSmrg * 23428d7b3dSmrg * Author: 24428d7b3dSmrg * Zou Nan hai <nanhai.zou@intel.com> 25428d7b3dSmrg * 26428d7b3dSmrg */ 27428d7b3dSmrg#include "intel_xvmc_private.h" 28428d7b3dSmrg#include "i830_reg.h" 29428d7b3dSmrg#include "i965_reg.h" 30428d7b3dSmrg#include "brw_defines.h" 31428d7b3dSmrg#include "brw_structs.h" 32428d7b3dSmrg#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0) 33428d7b3dSmrg#define URB_SIZE 256 /* XXX */ 34428d7b3dSmrg 35428d7b3dSmrg#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) 36428d7b3dSmrg 37428d7b3dSmrgenum interface { 38428d7b3dSmrg INTRA_INTERFACE = 0, /* non field intra */ 39428d7b3dSmrg NULL_INTERFACE, /* fill with white, do nothing, for debug */ 40428d7b3dSmrg FORWARD_INTERFACE, /* non field forward predict */ 41428d7b3dSmrg BACKWARD_INTERFACE, /* non field backward predict */ 42428d7b3dSmrg F_B_INTERFACE, /* non field forward and backward predict */ 43428d7b3dSmrg FIELD_FORWARD_INTERFACE, /* field forward predict */ 44428d7b3dSmrg FIELD_BACKWARD_INTERFACE, /* field backward predict */ 45428d7b3dSmrg FIELD_F_B_INTERFACE, /* field forward and backward predict */ 46428d7b3dSmrg DUAL_PRIME_INTERFACE 47428d7b3dSmrg}; 48428d7b3dSmrg 49428d7b3dSmrgstatic const uint32_t ipicture_kernel_static[][4] = { 50428d7b3dSmrg#include "shader/mc/ipicture.g4b" 51428d7b3dSmrg}; 52428d7b3dSmrg 53428d7b3dSmrgstatic const uint32_t null_kernel_static[][4] = { 54428d7b3dSmrg#include "shader/mc/null.g4b" 55428d7b3dSmrg}; 56428d7b3dSmrg 57428d7b3dSmrgstatic const uint32_t frame_forward_kernel_static[][4] = { 58428d7b3dSmrg#include "shader/mc/frame_forward.g4b" 59428d7b3dSmrg}; 60428d7b3dSmrg 61428d7b3dSmrgstatic const uint32_t frame_backward_kernel_static[][4] = { 62428d7b3dSmrg#include "shader/mc/frame_backward.g4b" 63428d7b3dSmrg}; 64428d7b3dSmrg 65428d7b3dSmrgstatic const uint32_t frame_f_b_kernel_static[][4] = { 66428d7b3dSmrg#include "shader/mc/frame_f_b.g4b" 67428d7b3dSmrg}; 68428d7b3dSmrg 69428d7b3dSmrgstatic const uint32_t field_forward_kernel_static[][4] = { 70428d7b3dSmrg#include "shader/mc/field_forward.g4b" 71428d7b3dSmrg}; 72428d7b3dSmrg 73428d7b3dSmrgstatic const uint32_t field_backward_kernel_static[][4] = { 74428d7b3dSmrg#include "shader/mc/field_backward.g4b" 75428d7b3dSmrg}; 76428d7b3dSmrg 77428d7b3dSmrgstatic const uint32_t field_f_b_kernel_static[][4] = { 78428d7b3dSmrg#include "shader/mc/field_f_b.g4b" 79428d7b3dSmrg}; 80428d7b3dSmrg 81428d7b3dSmrgstatic const uint32_t dual_prime_kernel_static[][4] = { 82428d7b3dSmrg#include "shader/mc/dual_prime.g4b" 83428d7b3dSmrg}; 84428d7b3dSmrg 85428d7b3dSmrgstatic const uint32_t frame_forward_igd_kernel_static[][4] = { 86428d7b3dSmrg#include "shader/mc/frame_forward_igd.g4b" 87428d7b3dSmrg}; 88428d7b3dSmrg 89428d7b3dSmrgstatic const uint32_t frame_backward_igd_kernel_static[][4] = { 90428d7b3dSmrg#include "shader/mc/frame_backward_igd.g4b" 91428d7b3dSmrg}; 92428d7b3dSmrg 93428d7b3dSmrgstatic const uint32_t frame_f_b_igd_kernel_static[][4] = { 94428d7b3dSmrg#include "shader/mc/frame_f_b_igd.g4b" 95428d7b3dSmrg}; 96428d7b3dSmrg 97428d7b3dSmrgstatic const uint32_t field_forward_igd_kernel_static[][4] = { 98428d7b3dSmrg#include "shader/mc/field_forward_igd.g4b" 99428d7b3dSmrg}; 100428d7b3dSmrg 101428d7b3dSmrgstatic const uint32_t field_backward_igd_kernel_static[][4] = { 102428d7b3dSmrg#include "shader/mc/field_backward_igd.g4b" 103428d7b3dSmrg}; 104428d7b3dSmrg 105428d7b3dSmrgstatic const uint32_t field_f_b_igd_kernel_static[][4] = { 106428d7b3dSmrg#include "shader/mc/field_f_b_igd.g4b" 107428d7b3dSmrg}; 108428d7b3dSmrg 109428d7b3dSmrgstatic const uint32_t dual_prime_igd_kernel_static[][4] = { 110428d7b3dSmrg#include "shader/mc/dual_prime_igd.g4b" 111428d7b3dSmrg}; 112428d7b3dSmrg 113428d7b3dSmrgstruct kernel_struct { 114428d7b3dSmrg const uint32_t(*bin)[4]; 115428d7b3dSmrg uint32_t size; 116428d7b3dSmrg}; 117428d7b3dSmrg 118428d7b3dSmrgstruct kernel_struct kernels_igd[] = { 119428d7b3dSmrg {ipicture_kernel_static, sizeof(ipicture_kernel_static)} 120428d7b3dSmrg , 121428d7b3dSmrg {null_kernel_static, sizeof(null_kernel_static)} 122428d7b3dSmrg , 123428d7b3dSmrg {frame_forward_igd_kernel_static, 124428d7b3dSmrg sizeof(frame_forward_igd_kernel_static)} 125428d7b3dSmrg , 126428d7b3dSmrg {frame_backward_igd_kernel_static, 127428d7b3dSmrg sizeof(frame_backward_igd_kernel_static)} 128428d7b3dSmrg , 129428d7b3dSmrg {frame_f_b_igd_kernel_static, sizeof(frame_f_b_igd_kernel_static)} 130428d7b3dSmrg , 131428d7b3dSmrg {field_forward_igd_kernel_static, 132428d7b3dSmrg sizeof(field_forward_igd_kernel_static)} 133428d7b3dSmrg , 134428d7b3dSmrg {field_backward_igd_kernel_static, 135428d7b3dSmrg sizeof(field_backward_igd_kernel_static)} 136428d7b3dSmrg , 137428d7b3dSmrg {field_f_b_igd_kernel_static, sizeof(field_f_b_igd_kernel_static)} 138428d7b3dSmrg , 139428d7b3dSmrg {dual_prime_igd_kernel_static, sizeof(dual_prime_igd_kernel_static)} 140428d7b3dSmrg}; 141428d7b3dSmrg 142428d7b3dSmrgstruct kernel_struct kernels_965[] = { 143428d7b3dSmrg {ipicture_kernel_static, sizeof(ipicture_kernel_static)} 144428d7b3dSmrg , 145428d7b3dSmrg {null_kernel_static, sizeof(null_kernel_static)} 146428d7b3dSmrg , 147428d7b3dSmrg {frame_forward_kernel_static, sizeof(frame_forward_kernel_static)} 148428d7b3dSmrg , 149428d7b3dSmrg {frame_backward_kernel_static, sizeof(frame_backward_kernel_static)} 150428d7b3dSmrg , 151428d7b3dSmrg {frame_f_b_kernel_static, sizeof(frame_f_b_kernel_static)} 152428d7b3dSmrg , 153428d7b3dSmrg {field_forward_kernel_static, sizeof(field_forward_kernel_static)} 154428d7b3dSmrg , 155428d7b3dSmrg {field_backward_kernel_static, sizeof(field_backward_kernel_static)} 156428d7b3dSmrg , 157428d7b3dSmrg {field_f_b_kernel_static, sizeof(field_f_b_kernel_static)} 158428d7b3dSmrg , 159428d7b3dSmrg {dual_prime_kernel_static, sizeof(dual_prime_kernel_static)} 160428d7b3dSmrg}; 161428d7b3dSmrg 162428d7b3dSmrg#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) 163428d7b3dSmrg 164428d7b3dSmrg#define MAX_SURFACE_NUM 10 165428d7b3dSmrg#define DESCRIPTOR_NUM 12 166428d7b3dSmrg 167428d7b3dSmrgstruct media_kernel_obj { 168428d7b3dSmrg dri_bo *bo; 169428d7b3dSmrg}; 170428d7b3dSmrg 171428d7b3dSmrgstruct interface_descriptor_obj { 172428d7b3dSmrg dri_bo *bo; 173428d7b3dSmrg struct media_kernel_obj kernels[DESCRIPTOR_NUM]; 174428d7b3dSmrg}; 175428d7b3dSmrg 176428d7b3dSmrgstruct vfe_state_obj { 177428d7b3dSmrg dri_bo *bo; 178428d7b3dSmrg struct interface_descriptor_obj interface; 179428d7b3dSmrg}; 180428d7b3dSmrg 181428d7b3dSmrgstruct surface_obj { 182428d7b3dSmrg dri_bo *bo; 183428d7b3dSmrg}; 184428d7b3dSmrg 185428d7b3dSmrgstruct surface_state_obj { 186428d7b3dSmrg struct surface_obj surface; 187428d7b3dSmrg dri_bo *bo; 188428d7b3dSmrg}; 189428d7b3dSmrg 190428d7b3dSmrgstruct binding_table_obj { 191428d7b3dSmrg dri_bo *bo; 192428d7b3dSmrg struct surface_state_obj surface_states[MAX_SURFACE_NUM]; 193428d7b3dSmrg}; 194428d7b3dSmrg 195428d7b3dSmrgstruct indirect_data_obj { 196428d7b3dSmrg dri_bo *bo; 197428d7b3dSmrg}; 198428d7b3dSmrg 199428d7b3dSmrgstruct media_state { 200428d7b3dSmrg unsigned int is_g4x:1; 201428d7b3dSmrg unsigned int is_965_q:1; 202428d7b3dSmrg 203428d7b3dSmrg struct vfe_state_obj vfe_state; 204428d7b3dSmrg struct binding_table_obj binding_table; 205428d7b3dSmrg struct indirect_data_obj indirect_data; 206428d7b3dSmrg}; 207428d7b3dSmrgstruct media_state media_state; 208428d7b3dSmrg 209428d7b3dSmrgstatic void free_object(struct media_state *s) 210428d7b3dSmrg{ 211428d7b3dSmrg int i; 212428d7b3dSmrg#define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo) 213428d7b3dSmrg FREE_ONE_BO(s->vfe_state.bo); 214428d7b3dSmrg FREE_ONE_BO(s->vfe_state.interface.bo); 215428d7b3dSmrg for (i = 0; i < DESCRIPTOR_NUM; i++) 216428d7b3dSmrg FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo); 217428d7b3dSmrg FREE_ONE_BO(s->binding_table.bo); 218428d7b3dSmrg for (i = 0; i < MAX_SURFACE_NUM; i++) 219428d7b3dSmrg FREE_ONE_BO(s->binding_table.surface_states[i].bo); 220428d7b3dSmrg FREE_ONE_BO(s->indirect_data.bo); 221428d7b3dSmrg} 222428d7b3dSmrg 223428d7b3dSmrgstatic int alloc_object(struct media_state *s) 224428d7b3dSmrg{ 225428d7b3dSmrg int i; 226428d7b3dSmrg 227428d7b3dSmrg for (i = 0; i < MAX_SURFACE_NUM; i++) { 228428d7b3dSmrg s->binding_table.surface_states[i].bo = 229428d7b3dSmrg drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 230428d7b3dSmrg sizeof(struct brw_surface_state), 231428d7b3dSmrg 0x1000); 232428d7b3dSmrg if (!s->binding_table.surface_states[i].bo) 233428d7b3dSmrg goto out; 234428d7b3dSmrg } 235428d7b3dSmrg return 0; 236428d7b3dSmrgout: 237428d7b3dSmrg free_object(s); 238428d7b3dSmrg return BadAlloc; 239428d7b3dSmrg} 240428d7b3dSmrg 241428d7b3dSmrgstatic Status destroy_context(Display * display, XvMCContext * context) 242428d7b3dSmrg{ 243428d7b3dSmrg struct intel_xvmc_context *intel_ctx; 244428d7b3dSmrg intel_ctx = context->privData; 245428d7b3dSmrg free(intel_ctx->hw); 246428d7b3dSmrg free(intel_ctx); 247428d7b3dSmrg return Success; 248428d7b3dSmrg} 249428d7b3dSmrg 250428d7b3dSmrg#define STRIDE(w) (w) 251428d7b3dSmrg#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1))) 252428d7b3dSmrg 253428d7b3dSmrgstatic void flush() 254428d7b3dSmrg{ 255428d7b3dSmrg struct brw_mi_flush flush; 256428d7b3dSmrg memset(&flush, 0, sizeof(flush)); 257428d7b3dSmrg flush.opcode = CMD_MI_FLUSH; 258428d7b3dSmrg flush.flags = (1 << 1); 259428d7b3dSmrg BATCH_STRUCT(flush); 260428d7b3dSmrg} 261428d7b3dSmrg 262428d7b3dSmrgstatic void clear_sf_state() 263428d7b3dSmrg{ 264428d7b3dSmrg struct brw_sf_unit_state sf; 265428d7b3dSmrg memset(&sf, 0, sizeof(sf)); 266428d7b3dSmrg /* TODO */ 267428d7b3dSmrg} 268428d7b3dSmrg 269428d7b3dSmrg/* urb fence must be aligned to cacheline */ 270428d7b3dSmrgstatic void align_urb_fence() 271428d7b3dSmrg{ 272428d7b3dSmrg BATCH_LOCALS; 273428d7b3dSmrg int i, offset_to_next_cacheline; 274428d7b3dSmrg unsigned long batch_offset; 275428d7b3dSmrg BEGIN_BATCH(3); 276428d7b3dSmrg batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr; 277428d7b3dSmrg offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset; 278428d7b3dSmrg if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) { 279428d7b3dSmrg for (i = 0; i < offset_to_next_cacheline / 4; i++) 280428d7b3dSmrg OUT_BATCH(0); 281428d7b3dSmrg ADVANCE_BATCH(); 282428d7b3dSmrg } 283428d7b3dSmrg} 284428d7b3dSmrg 285428d7b3dSmrg/* setup urb layout for media */ 286428d7b3dSmrgstatic void urb_layout() 287428d7b3dSmrg{ 288428d7b3dSmrg BATCH_LOCALS; 289428d7b3dSmrg align_urb_fence(); 290428d7b3dSmrg BEGIN_BATCH(3); 291428d7b3dSmrg OUT_BATCH(BRW_URB_FENCE | 292428d7b3dSmrg UF0_VFE_REALLOC | 293428d7b3dSmrg UF0_CS_REALLOC | 294428d7b3dSmrg UF0_SF_REALLOC | 295428d7b3dSmrg UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1); 296428d7b3dSmrg OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) | 297428d7b3dSmrg (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT)); 298428d7b3dSmrg 299428d7b3dSmrg OUT_BATCH(((URB_SIZE) << UF2_VFE_FENCE_SHIFT) | /* VFE_SIZE */ 300428d7b3dSmrg ((URB_SIZE) << UF2_CS_FENCE_SHIFT)); /* CS_SIZE is 0 */ 301428d7b3dSmrg ADVANCE_BATCH(); 302428d7b3dSmrg} 303428d7b3dSmrg 304428d7b3dSmrgstatic void media_state_pointers(struct media_state *media_state) 305428d7b3dSmrg{ 306428d7b3dSmrg BATCH_LOCALS; 307428d7b3dSmrg BEGIN_BATCH(3); 308428d7b3dSmrg OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1); 309428d7b3dSmrg OUT_BATCH(0); 310428d7b3dSmrg OUT_RELOC(media_state->vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); 311428d7b3dSmrg ADVANCE_BATCH(); 312428d7b3dSmrg} 313428d7b3dSmrg 314428d7b3dSmrg/* setup 2D surface for media_read or media_write 315428d7b3dSmrg */ 316428d7b3dSmrgstatic Status setup_media_surface(struct media_state *media_state, 317428d7b3dSmrg int surface_num, dri_bo * bo, 318428d7b3dSmrg unsigned long offset, int w, int h, 319428d7b3dSmrg Bool write) 320428d7b3dSmrg{ 321428d7b3dSmrg struct brw_surface_state s, *ss = &s; 322428d7b3dSmrg 323428d7b3dSmrg memset(ss, 0, sizeof(struct brw_surface_state)); 324428d7b3dSmrg ss->ss0.surface_type = BRW_SURFACE_2D; 325428d7b3dSmrg ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT; 326428d7b3dSmrg ss->ss1.base_addr = offset + bo->offset; 327428d7b3dSmrg ss->ss2.width = w - 1; 328428d7b3dSmrg ss->ss2.height = h - 1; 329428d7b3dSmrg ss->ss3.pitch = w - 1; 330428d7b3dSmrg 331428d7b3dSmrg if (media_state->binding_table.surface_states[surface_num].bo) 332428d7b3dSmrg drm_intel_bo_unreference(media_state-> 333428d7b3dSmrg binding_table.surface_states 334428d7b3dSmrg [surface_num].bo); 335428d7b3dSmrg media_state->binding_table.surface_states[surface_num].bo = 336428d7b3dSmrg drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 337428d7b3dSmrg sizeof(struct brw_surface_state), 0x1000); 338428d7b3dSmrg if (!media_state->binding_table.surface_states[surface_num].bo) 339428d7b3dSmrg return BadAlloc; 340428d7b3dSmrg 341428d7b3dSmrg drm_intel_bo_subdata(media_state-> 342428d7b3dSmrg binding_table.surface_states[surface_num].bo, 0, 343428d7b3dSmrg sizeof(*ss), ss); 344428d7b3dSmrg 345428d7b3dSmrg drm_intel_bo_emit_reloc(media_state-> 346428d7b3dSmrg binding_table.surface_states[surface_num].bo, 347428d7b3dSmrg offsetof(struct brw_surface_state, ss1), bo, 348428d7b3dSmrg offset, I915_GEM_DOMAIN_RENDER, 349428d7b3dSmrg write ? I915_GEM_DOMAIN_RENDER : 0); 350428d7b3dSmrg 351428d7b3dSmrg return Success; 352428d7b3dSmrg} 353428d7b3dSmrg 354428d7b3dSmrgstatic Status setup_surfaces(struct media_state *media_state, 355428d7b3dSmrg dri_bo * dst_bo, dri_bo * past_bo, 356428d7b3dSmrg dri_bo * future_bo, int w, int h) 357428d7b3dSmrg{ 358428d7b3dSmrg Status ret; 359428d7b3dSmrg ret = setup_media_surface(media_state, 0, dst_bo, 0, w, h, TRUE); 360428d7b3dSmrg if (ret != Success) 361428d7b3dSmrg return ret; 362428d7b3dSmrg ret = 363428d7b3dSmrg setup_media_surface(media_state, 1, dst_bo, w * h, w / 2, h / 2, 364428d7b3dSmrg TRUE); 365428d7b3dSmrg if (ret != Success) 366428d7b3dSmrg return ret; 367428d7b3dSmrg ret = 368428d7b3dSmrg setup_media_surface(media_state, 2, dst_bo, w * h + w * h / 4, 369428d7b3dSmrg w / 2, h / 2, TRUE); 370428d7b3dSmrg if (ret != Success) 371428d7b3dSmrg return ret; 372428d7b3dSmrg if (past_bo) { 373428d7b3dSmrg ret = 374428d7b3dSmrg setup_media_surface(media_state, 4, past_bo, 0, w, h, 375428d7b3dSmrg FALSE); 376428d7b3dSmrg if (ret != Success) 377428d7b3dSmrg return ret; 378428d7b3dSmrg ret = 379428d7b3dSmrg setup_media_surface(media_state, 5, past_bo, w * h, w / 2, 380428d7b3dSmrg h / 2, FALSE); 381428d7b3dSmrg if (ret != Success) 382428d7b3dSmrg return ret; 383428d7b3dSmrg ret = 384428d7b3dSmrg setup_media_surface(media_state, 6, past_bo, 385428d7b3dSmrg w * h + w * h / 4, w / 2, h / 2, FALSE); 386428d7b3dSmrg if (ret != Success) 387428d7b3dSmrg return ret; 388428d7b3dSmrg } 389428d7b3dSmrg if (future_bo) { 390428d7b3dSmrg ret = 391428d7b3dSmrg setup_media_surface(media_state, 7, future_bo, 0, w, h, 392428d7b3dSmrg FALSE); 393428d7b3dSmrg if (ret != Success) 394428d7b3dSmrg return ret; 395428d7b3dSmrg ret = 396428d7b3dSmrg setup_media_surface(media_state, 8, future_bo, w * h, w / 2, 397428d7b3dSmrg h / 2, FALSE); 398428d7b3dSmrg if (ret != Success) 399428d7b3dSmrg return ret; 400428d7b3dSmrg ret = 401428d7b3dSmrg setup_media_surface(media_state, 9, future_bo, 402428d7b3dSmrg w * h + w * h / 4, w / 2, h / 2, FALSE); 403428d7b3dSmrg if (ret != Success) 404428d7b3dSmrg return ret; 405428d7b3dSmrg } 406428d7b3dSmrg return Success; 407428d7b3dSmrg} 408428d7b3dSmrg 409428d7b3dSmrg/* BUFFER SURFACE has a strange format 410428d7b3dSmrg * the size of the surface is in part of w h and d component 411428d7b3dSmrg */ 412428d7b3dSmrg 413428d7b3dSmrgstatic Status setup_blocks(struct media_state *media_state, 414428d7b3dSmrg unsigned int block_size) 415428d7b3dSmrg{ 416428d7b3dSmrg union element { 417428d7b3dSmrg struct { 418428d7b3dSmrg unsigned int w:7; 419428d7b3dSmrg unsigned int h:13; 420428d7b3dSmrg unsigned int d:7; 421428d7b3dSmrg unsigned int pad:7; 422428d7b3dSmrg } whd; 423428d7b3dSmrg unsigned int size; 424428d7b3dSmrg } e; 425428d7b3dSmrg struct brw_surface_state ss; 426428d7b3dSmrg memset(&ss, 0, sizeof(struct brw_surface_state)); 427428d7b3dSmrg ss.ss0.surface_type = BRW_SURFACE_BUFFER; 428428d7b3dSmrg ss.ss0.surface_format = BRW_SURFACEFORMAT_R8_UINT; 429428d7b3dSmrg ss.ss1.base_addr = media_state->indirect_data.bo->offset; 430428d7b3dSmrg 431428d7b3dSmrg e.size = block_size - 1; 432428d7b3dSmrg ss.ss2.width = e.whd.w; 433428d7b3dSmrg ss.ss2.height = e.whd.h; 434428d7b3dSmrg ss.ss3.depth = e.whd.d; 435428d7b3dSmrg ss.ss3.pitch = block_size - 1; 436428d7b3dSmrg 437428d7b3dSmrg if (media_state->binding_table.surface_states[3].bo) 438428d7b3dSmrg drm_intel_bo_unreference(media_state-> 439428d7b3dSmrg binding_table.surface_states[3].bo); 440428d7b3dSmrg 441428d7b3dSmrg media_state->binding_table.surface_states[3].bo = 442428d7b3dSmrg drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", 443428d7b3dSmrg sizeof(struct brw_surface_state), 0x1000); 444428d7b3dSmrg if (!media_state->binding_table.surface_states[3].bo) 445428d7b3dSmrg return BadAlloc; 446428d7b3dSmrg 447428d7b3dSmrg drm_intel_bo_subdata(media_state->binding_table.surface_states[3].bo, 0, 448428d7b3dSmrg sizeof(ss), &ss); 449428d7b3dSmrg 450428d7b3dSmrg drm_intel_bo_emit_reloc(media_state->binding_table.surface_states[3].bo, 451428d7b3dSmrg offsetof(struct brw_surface_state, ss1), 452428d7b3dSmrg media_state->indirect_data.bo, 0, 453428d7b3dSmrg I915_GEM_DOMAIN_SAMPLER, 0); 454428d7b3dSmrg return Success; 455428d7b3dSmrg} 456428d7b3dSmrg 457428d7b3dSmrg/* setup state base address */ 458428d7b3dSmrgstatic void state_base_address() 459428d7b3dSmrg{ 460428d7b3dSmrg BATCH_LOCALS; 461428d7b3dSmrg BEGIN_BATCH(6); 462428d7b3dSmrg OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4); 463428d7b3dSmrg OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 464428d7b3dSmrg OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 465428d7b3dSmrg OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 466428d7b3dSmrg OUT_BATCH(0 | BASE_ADDRESS_MODIFY); 467428d7b3dSmrg OUT_BATCH(0xFFFFF000 | BASE_ADDRESS_MODIFY); 468428d7b3dSmrg ADVANCE_BATCH(); 469428d7b3dSmrg} 470428d7b3dSmrg 471428d7b3dSmrg/* select media pipeline */ 472428d7b3dSmrgstatic void pipeline_select(struct media_state *media_state) 473428d7b3dSmrg{ 474428d7b3dSmrg BATCH_LOCALS; 475428d7b3dSmrg BEGIN_BATCH(1); 476428d7b3dSmrg if (media_state->is_g4x) 477428d7b3dSmrg OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); 478428d7b3dSmrg else 479428d7b3dSmrg OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); 480428d7b3dSmrg ADVANCE_BATCH(); 481428d7b3dSmrg} 482428d7b3dSmrg 483428d7b3dSmrg/* kick media object to gpu */ 484428d7b3dSmrgstatic void send_media_object(XvMCMacroBlock * mb, int offset, 485428d7b3dSmrg enum interface interface) 486428d7b3dSmrg{ 487428d7b3dSmrg BATCH_LOCALS; 488428d7b3dSmrg BEGIN_BATCH(13); 489428d7b3dSmrg OUT_BATCH(BRW_MEDIA_OBJECT | 11); 490428d7b3dSmrg OUT_BATCH(interface); 491428d7b3dSmrg if (media_state.is_965_q) { 492428d7b3dSmrg OUT_BATCH(0); 493428d7b3dSmrg OUT_BATCH(0); 494428d7b3dSmrg } else { 495428d7b3dSmrg OUT_BATCH(6 * 128); 496428d7b3dSmrg OUT_RELOC(media_state.indirect_data.bo, 497428d7b3dSmrg I915_GEM_DOMAIN_INSTRUCTION, 0, offset); 498428d7b3dSmrg } 499428d7b3dSmrg 500428d7b3dSmrg OUT_BATCH(mb->x << 4); //g1.0 501428d7b3dSmrg OUT_BATCH(mb->y << 4); 502428d7b3dSmrg OUT_RELOC(media_state.indirect_data.bo, //g1.8 503428d7b3dSmrg I915_GEM_DOMAIN_INSTRUCTION, 0, offset); 504428d7b3dSmrg OUT_BATCH_SHORT(mb->coded_block_pattern); //g1.12 505428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[0][0][0]); //g1.14 506428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[0][0][1]); //g1.16 507428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[0][1][0]); //g1.18 508428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[0][1][1]); //g1.20 509428d7b3dSmrg 510428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[1][0][0]); //g1.22 511428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[1][0][1]); //g1.24 512428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[1][1][0]); //g1.26 513428d7b3dSmrg OUT_BATCH_SHORT(mb->PMV[1][1][1]); //g1.28 514428d7b3dSmrg OUT_BATCH_CHAR(mb->dct_type); //g1.30 515428d7b3dSmrg OUT_BATCH_CHAR(mb->motion_vertical_field_select); //g1.31 516428d7b3dSmrg 517428d7b3dSmrg if (media_state.is_965_q) 518428d7b3dSmrg OUT_BATCH(0x0); 519428d7b3dSmrg else 520428d7b3dSmrg OUT_BATCH(0xffffffff); 521428d7b3dSmrg ADVANCE_BATCH(); 522428d7b3dSmrg} 523428d7b3dSmrg 524428d7b3dSmrgstatic Status binding_tables(struct media_state *media_state) 525428d7b3dSmrg{ 526428d7b3dSmrg unsigned int binding_table[MAX_SURFACE_NUM]; 527428d7b3dSmrg int i; 528428d7b3dSmrg 529428d7b3dSmrg if (media_state->binding_table.bo) 530428d7b3dSmrg drm_intel_bo_unreference(media_state->binding_table.bo); 531428d7b3dSmrg media_state->binding_table.bo = 532428d7b3dSmrg drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table", 533428d7b3dSmrg MAX_SURFACE_NUM * 4, 0x1000); 534428d7b3dSmrg if (!media_state->binding_table.bo) 535428d7b3dSmrg return BadAlloc; 536428d7b3dSmrg 537428d7b3dSmrg for (i = 0; i < MAX_SURFACE_NUM; i++) 538428d7b3dSmrg binding_table[i] = 539428d7b3dSmrg media_state->binding_table.surface_states[i].bo->offset; 540428d7b3dSmrg drm_intel_bo_subdata(media_state->binding_table.bo, 0, 541428d7b3dSmrg sizeof(binding_table), binding_table); 542428d7b3dSmrg 543428d7b3dSmrg for (i = 0; i < MAX_SURFACE_NUM; i++) 544428d7b3dSmrg drm_intel_bo_emit_reloc(media_state->binding_table.bo, 545428d7b3dSmrg i * sizeof(unsigned int), 546428d7b3dSmrg media_state-> 547428d7b3dSmrg binding_table.surface_states[i].bo, 0, 548428d7b3dSmrg I915_GEM_DOMAIN_INSTRUCTION, 0); 549428d7b3dSmrg return Success; 550428d7b3dSmrg} 551428d7b3dSmrg 552428d7b3dSmrgstatic int media_kernels(struct media_state *media_state) 553428d7b3dSmrg{ 554428d7b3dSmrg struct kernel_struct *kernels; 555428d7b3dSmrg int kernel_array_size, i; 556428d7b3dSmrg 557428d7b3dSmrg if (media_state->is_g4x) { 558428d7b3dSmrg kernels = kernels_igd; 559428d7b3dSmrg kernel_array_size = ARRAY_SIZE(kernels_igd); 560428d7b3dSmrg } else { 561428d7b3dSmrg kernels = kernels_965; 562428d7b3dSmrg kernel_array_size = ARRAY_SIZE(kernels_965); 563428d7b3dSmrg } 564428d7b3dSmrg 565428d7b3dSmrg for (i = 0; i < kernel_array_size; i++) { 566428d7b3dSmrg media_state->vfe_state.interface.kernels[i].bo = 567428d7b3dSmrg drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel", 568428d7b3dSmrg kernels[i].size, 0x1000); 569428d7b3dSmrg if (!media_state->vfe_state.interface.kernels[i].bo) 570428d7b3dSmrg goto out; 571428d7b3dSmrg } 572428d7b3dSmrg 573428d7b3dSmrg for (i = 0; i < kernel_array_size; i++) { 574428d7b3dSmrg dri_bo *bo = media_state->vfe_state.interface.kernels[i].bo; 575428d7b3dSmrg drm_intel_bo_subdata(bo, 0, kernels[i].size, kernels[i].bin); 576428d7b3dSmrg } 577428d7b3dSmrg return 0; 578428d7b3dSmrgout: 579428d7b3dSmrg free_object(media_state); 580428d7b3dSmrg return BadAlloc; 581428d7b3dSmrg} 582428d7b3dSmrg 583428d7b3dSmrgstatic void setup_interface(struct media_state *media_state, enum interface i) 584428d7b3dSmrg{ 585428d7b3dSmrg struct brw_interface_descriptor desc; 586428d7b3dSmrg memset(&desc, 0, sizeof(desc)); 587428d7b3dSmrg 588428d7b3dSmrg desc.desc0.grf_reg_blocks = 15; 589428d7b3dSmrg desc.desc0.kernel_start_pointer = 590428d7b3dSmrg media_state->vfe_state.interface.kernels[i].bo->offset >> 6; 591428d7b3dSmrg 592428d7b3dSmrg desc.desc1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; 593428d7b3dSmrg 594428d7b3dSmrg /* use same binding table for all interface 595428d7b3dSmrg * may change this if it affect performance 596428d7b3dSmrg */ 597428d7b3dSmrg desc.desc3.binding_table_entry_count = MAX_SURFACE_NUM; 598428d7b3dSmrg desc.desc3.binding_table_pointer = 599428d7b3dSmrg media_state->binding_table.bo->offset >> 5; 600428d7b3dSmrg 601428d7b3dSmrg drm_intel_bo_subdata(media_state->vfe_state.interface.bo, 602428d7b3dSmrg i * sizeof(desc), sizeof(desc), &desc); 603428d7b3dSmrg 604428d7b3dSmrg drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo, 605428d7b3dSmrg i * sizeof(desc) + 606428d7b3dSmrg offsetof(struct brw_interface_descriptor, 607428d7b3dSmrg desc0), 608428d7b3dSmrg media_state->vfe_state.interface.kernels[i].bo, 609428d7b3dSmrg desc.desc0.grf_reg_blocks, 610428d7b3dSmrg I915_GEM_DOMAIN_INSTRUCTION, 0); 611428d7b3dSmrg 612428d7b3dSmrg drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo, 613428d7b3dSmrg i * sizeof(desc) + 614428d7b3dSmrg offsetof(struct brw_interface_descriptor, 615428d7b3dSmrg desc3), media_state->binding_table.bo, 616428d7b3dSmrg desc.desc3.binding_table_entry_count, 617428d7b3dSmrg I915_GEM_DOMAIN_INSTRUCTION, 0); 618428d7b3dSmrg} 619428d7b3dSmrg 620428d7b3dSmrgstatic Status interface_descriptor(struct media_state *media_state) 621428d7b3dSmrg{ 622428d7b3dSmrg if (media_state->vfe_state.interface.bo) 623428d7b3dSmrg drm_intel_bo_unreference(media_state->vfe_state.interface.bo); 624428d7b3dSmrg media_state->vfe_state.interface.bo = 625428d7b3dSmrg drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces", 626428d7b3dSmrg DESCRIPTOR_NUM * 627428d7b3dSmrg sizeof(struct brw_interface_descriptor), 0x1000); 628428d7b3dSmrg if (!media_state->vfe_state.interface.bo) 629428d7b3dSmrg return BadAlloc; 630428d7b3dSmrg 631428d7b3dSmrg setup_interface(media_state, INTRA_INTERFACE); 632428d7b3dSmrg setup_interface(media_state, NULL_INTERFACE); 633428d7b3dSmrg setup_interface(media_state, FORWARD_INTERFACE); 634428d7b3dSmrg setup_interface(media_state, FIELD_FORWARD_INTERFACE); 635428d7b3dSmrg setup_interface(media_state, BACKWARD_INTERFACE); 636428d7b3dSmrg setup_interface(media_state, FIELD_BACKWARD_INTERFACE); 637428d7b3dSmrg setup_interface(media_state, F_B_INTERFACE); 638428d7b3dSmrg setup_interface(media_state, FIELD_F_B_INTERFACE); 639428d7b3dSmrg setup_interface(media_state, DUAL_PRIME_INTERFACE); 640428d7b3dSmrg return Success; 641428d7b3dSmrg} 642428d7b3dSmrg 643428d7b3dSmrgstatic Status vfe_state(struct media_state *media_state) 644428d7b3dSmrg{ 645428d7b3dSmrg struct brw_vfe_state state; 646428d7b3dSmrg memset(&state, 0, sizeof(state)); 647428d7b3dSmrg 648428d7b3dSmrg /* no scratch space */ 649428d7b3dSmrg state.vfe1.vfe_mode = VFE_GENERIC_MODE; 650428d7b3dSmrg state.vfe1.num_urb_entries = 1; 651428d7b3dSmrg /* XXX TODO */ 652428d7b3dSmrg /* should carefully caculate those values for performance */ 653428d7b3dSmrg state.vfe1.urb_entry_alloc_size = 2; 654428d7b3dSmrg state.vfe1.max_threads = 31; 655428d7b3dSmrg state.vfe2.interface_descriptor_base = 656428d7b3dSmrg media_state->vfe_state.interface.bo->offset >> 4; 657428d7b3dSmrg 658428d7b3dSmrg if (media_state->vfe_state.bo) 659428d7b3dSmrg drm_intel_bo_unreference(media_state->vfe_state.bo); 660428d7b3dSmrg media_state->vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 661428d7b3dSmrg "vfe state", 662428d7b3dSmrg sizeof(struct 663428d7b3dSmrg brw_vfe_state), 664428d7b3dSmrg 0x1000); 665428d7b3dSmrg if (!media_state->vfe_state.bo) 666428d7b3dSmrg return BadAlloc; 667428d7b3dSmrg 668428d7b3dSmrg drm_intel_bo_subdata(media_state->vfe_state.bo, 0, sizeof(state), 669428d7b3dSmrg &state); 670428d7b3dSmrg 671428d7b3dSmrg drm_intel_bo_emit_reloc(media_state->vfe_state.bo, 672428d7b3dSmrg offsetof(struct brw_vfe_state, vfe2), 673428d7b3dSmrg media_state->vfe_state.interface.bo, 0, 674428d7b3dSmrg I915_GEM_DOMAIN_INSTRUCTION, 0); 675428d7b3dSmrg return Success; 676428d7b3dSmrg} 677428d7b3dSmrg 678428d7b3dSmrgstatic Status render_surface(Display * display, 679428d7b3dSmrg XvMCContext * context, 680428d7b3dSmrg unsigned int picture_structure, 681428d7b3dSmrg XvMCSurface * target_surface, 682428d7b3dSmrg XvMCSurface * past_surface, 683428d7b3dSmrg XvMCSurface * future_surface, 684428d7b3dSmrg unsigned int flags, 685428d7b3dSmrg unsigned int num_macroblocks, 686428d7b3dSmrg unsigned int first_macroblock, 687428d7b3dSmrg XvMCMacroBlockArray * macroblock_array, 688428d7b3dSmrg XvMCBlockArray * blocks) 689428d7b3dSmrg{ 690428d7b3dSmrg 691428d7b3dSmrg intel_xvmc_context_ptr intel_ctx; 692428d7b3dSmrg int i, j; 693428d7b3dSmrg struct i965_xvmc_context *i965_ctx; 694428d7b3dSmrg XvMCMacroBlock *mb; 695428d7b3dSmrg struct intel_xvmc_surface *priv_target_surface = 696428d7b3dSmrg target_surface->privData; 697428d7b3dSmrg struct intel_xvmc_surface *priv_past_surface = 698428d7b3dSmrg past_surface ? past_surface->privData : 0; 699428d7b3dSmrg struct intel_xvmc_surface *priv_future_surface = 700428d7b3dSmrg future_surface ? future_surface->privData : 0; 701428d7b3dSmrg unsigned short *block_ptr; 702428d7b3dSmrg intel_ctx = context->privData; 703428d7b3dSmrg i965_ctx = context->privData; 704428d7b3dSmrg if (!intel_ctx) { 705428d7b3dSmrg XVMC_ERR("Can't find intel xvmc context\n"); 706428d7b3dSmrg return BadValue; 707428d7b3dSmrg } 708428d7b3dSmrg 709428d7b3dSmrg if (media_state.indirect_data.bo) { 710428d7b3dSmrg drm_intel_gem_bo_unmap_gtt(media_state. 711428d7b3dSmrg indirect_data.bo); 712428d7b3dSmrg 713428d7b3dSmrg drm_intel_bo_unreference(media_state.indirect_data.bo); 714428d7b3dSmrg } 715428d7b3dSmrg media_state.indirect_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, 716428d7b3dSmrg "indirect data", 717428d7b3dSmrg 128 * 6 * 718428d7b3dSmrg num_macroblocks, 64); 719428d7b3dSmrg if (!media_state.indirect_data.bo) 720428d7b3dSmrg return BadAlloc; 721428d7b3dSmrg setup_surfaces(&media_state, 722428d7b3dSmrg priv_target_surface->bo, 723428d7b3dSmrg past_surface ? priv_past_surface->bo : NULL, 724428d7b3dSmrg future_surface ? priv_future_surface->bo : NULL, 725428d7b3dSmrg context->width, context->height); 726428d7b3dSmrg setup_blocks(&media_state, 128 * 6 * num_macroblocks); 727428d7b3dSmrg binding_tables(&media_state); 728428d7b3dSmrg interface_descriptor(&media_state); 729428d7b3dSmrg vfe_state(&media_state); 730428d7b3dSmrg 731428d7b3dSmrg drm_intel_gem_bo_map_gtt(media_state.indirect_data.bo); 732428d7b3dSmrg 733428d7b3dSmrg block_ptr = media_state.indirect_data.bo->virtual; 734428d7b3dSmrg for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) { 735428d7b3dSmrg unsigned short *mb_block_ptr; 736428d7b3dSmrg mb = ¯oblock_array->macro_blocks[i]; 737428d7b3dSmrg mb_block_ptr = &blocks->blocks[(mb->index << 6)]; 738428d7b3dSmrg if (mb->coded_block_pattern & 0x20) { 739428d7b3dSmrg for (j = 0; j < 8; j++) 740428d7b3dSmrg memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j, 741428d7b3dSmrg 16); 742428d7b3dSmrg mb_block_ptr += 64; 743428d7b3dSmrg } 744428d7b3dSmrg 745428d7b3dSmrg if (mb->coded_block_pattern & 0x10) { 746428d7b3dSmrg for (j = 0; j < 8; j++) 747428d7b3dSmrg memcpy(block_ptr + 16 * j + 8, 748428d7b3dSmrg mb_block_ptr + 8 * j, 16); 749428d7b3dSmrg mb_block_ptr += 64; 750428d7b3dSmrg } 751428d7b3dSmrg block_ptr += 2 * 64; 752428d7b3dSmrg if (mb->coded_block_pattern & 0x08) { 753428d7b3dSmrg for (j = 0; j < 8; j++) 754428d7b3dSmrg memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j, 755428d7b3dSmrg 16); 756428d7b3dSmrg mb_block_ptr += 64; 757428d7b3dSmrg } 758428d7b3dSmrg 759428d7b3dSmrg if (mb->coded_block_pattern & 0x04) { 760428d7b3dSmrg for (j = 0; j < 8; j++) 761428d7b3dSmrg memcpy(block_ptr + 16 * j + 8, 762428d7b3dSmrg mb_block_ptr + 8 * j, 16); 763428d7b3dSmrg mb_block_ptr += 64; 764428d7b3dSmrg } 765428d7b3dSmrg 766428d7b3dSmrg block_ptr += 2 * 64; 767428d7b3dSmrg if (mb->coded_block_pattern & 0x2) { 768428d7b3dSmrg memcpy(block_ptr, mb_block_ptr, 128); 769428d7b3dSmrg mb_block_ptr += 64; 770428d7b3dSmrg } 771428d7b3dSmrg 772428d7b3dSmrg block_ptr += 64; 773428d7b3dSmrg if (mb->coded_block_pattern & 0x1) 774428d7b3dSmrg memcpy(block_ptr, mb_block_ptr, 128); 775428d7b3dSmrg block_ptr += 64; 776428d7b3dSmrg } 777428d7b3dSmrg { 778428d7b3dSmrg int block_offset = 0; 779428d7b3dSmrg LOCK_HARDWARE(intel_ctx->hw_context); 780428d7b3dSmrg state_base_address(); 781428d7b3dSmrg flush(); 782428d7b3dSmrg clear_sf_state(); 783428d7b3dSmrg pipeline_select(&media_state); 784428d7b3dSmrg urb_layout(); 785428d7b3dSmrg media_state_pointers(&media_state); 786428d7b3dSmrg for (i = first_macroblock; 787428d7b3dSmrg i < num_macroblocks + first_macroblock; 788428d7b3dSmrg i++, block_offset += 128 * 6) { 789428d7b3dSmrg mb = ¯oblock_array->macro_blocks[i]; 790428d7b3dSmrg 791428d7b3dSmrg if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) { 792428d7b3dSmrg send_media_object(mb, block_offset, 793428d7b3dSmrg INTRA_INTERFACE); 794428d7b3dSmrg } else { 795428d7b3dSmrg if (((mb->motion_type & 3) == 796428d7b3dSmrg XVMC_PREDICTION_FRAME)) { 797428d7b3dSmrg if ((mb->macroblock_type & 798428d7b3dSmrg XVMC_MB_TYPE_MOTION_FORWARD)) { 799428d7b3dSmrg if (((mb->macroblock_type & 800428d7b3dSmrg XVMC_MB_TYPE_MOTION_BACKWARD))) 801428d7b3dSmrg send_media_object(mb, 802428d7b3dSmrg block_offset, 803428d7b3dSmrg F_B_INTERFACE); 804428d7b3dSmrg else 805428d7b3dSmrg send_media_object(mb, 806428d7b3dSmrg block_offset, 807428d7b3dSmrg FORWARD_INTERFACE); 808428d7b3dSmrg } else 809428d7b3dSmrg if ((mb->macroblock_type & 810428d7b3dSmrg XVMC_MB_TYPE_MOTION_BACKWARD)) 811428d7b3dSmrg { 812428d7b3dSmrg send_media_object(mb, 813428d7b3dSmrg block_offset, 814428d7b3dSmrg BACKWARD_INTERFACE); 815428d7b3dSmrg } 816428d7b3dSmrg } else if ((mb->motion_type & 3) == 817428d7b3dSmrg XVMC_PREDICTION_FIELD) { 818428d7b3dSmrg if ((mb->macroblock_type & 819428d7b3dSmrg XVMC_MB_TYPE_MOTION_FORWARD)) { 820428d7b3dSmrg if (((mb->macroblock_type & 821428d7b3dSmrg XVMC_MB_TYPE_MOTION_BACKWARD))) 822428d7b3dSmrg send_media_object(mb, 823428d7b3dSmrg block_offset, 824428d7b3dSmrg FIELD_F_B_INTERFACE); 825428d7b3dSmrg else 826428d7b3dSmrg 827428d7b3dSmrg send_media_object(mb, 828428d7b3dSmrg block_offset, 829428d7b3dSmrg FIELD_FORWARD_INTERFACE); 830428d7b3dSmrg } else 831428d7b3dSmrg if ((mb->macroblock_type & 832428d7b3dSmrg XVMC_MB_TYPE_MOTION_BACKWARD)) 833428d7b3dSmrg { 834428d7b3dSmrg send_media_object(mb, 835428d7b3dSmrg block_offset, 836428d7b3dSmrg FIELD_BACKWARD_INTERFACE); 837428d7b3dSmrg } 838428d7b3dSmrg } else { 839428d7b3dSmrg send_media_object(mb, block_offset, 840428d7b3dSmrg DUAL_PRIME_INTERFACE); 841428d7b3dSmrg } 842428d7b3dSmrg } 843428d7b3dSmrg } 844428d7b3dSmrg intelFlushBatch(); 845428d7b3dSmrg UNLOCK_HARDWARE(intel_ctx->hw_context); 846428d7b3dSmrg } 847428d7b3dSmrg return Success; 848428d7b3dSmrg} 849428d7b3dSmrg 850428d7b3dSmrgstatic Status create_context(Display * display, XvMCContext * context, 851428d7b3dSmrg int priv_count, CARD32 * priv_data) 852428d7b3dSmrg{ 853428d7b3dSmrg struct intel_xvmc_context *intel_ctx; 854428d7b3dSmrg struct intel_xvmc_hw_context *hw_ctx; 855428d7b3dSmrg hw_ctx = (struct intel_xvmc_hw_context *)priv_data; 856428d7b3dSmrg 857428d7b3dSmrg intel_ctx = calloc(1, sizeof(struct intel_xvmc_context)); 858428d7b3dSmrg if (!intel_ctx) 859428d7b3dSmrg return BadAlloc; 860428d7b3dSmrg intel_ctx->hw = hw_ctx; 861428d7b3dSmrg intel_ctx->surface_bo_size 862428d7b3dSmrg = SIZE_YUV420(context->width, context->height); 863428d7b3dSmrg context->privData = intel_ctx; 864428d7b3dSmrg 865428d7b3dSmrg media_state.is_g4x = hw_ctx->i965.is_g4x; 866428d7b3dSmrg media_state.is_965_q = hw_ctx->i965.is_965_q; 867428d7b3dSmrg 868428d7b3dSmrg if (alloc_object(&media_state)) 869428d7b3dSmrg return BadAlloc; 870428d7b3dSmrg if (media_kernels(&media_state)) 871428d7b3dSmrg return BadAlloc; 872428d7b3dSmrg return Success; 873428d7b3dSmrg} 874428d7b3dSmrg 875428d7b3dSmrgstruct _intel_xvmc_driver i965_xvmc_mc_driver = { 876428d7b3dSmrg .type = XVMC_I965_MPEG2_MC, 877428d7b3dSmrg .create_context = create_context, 878428d7b3dSmrg .destroy_context = destroy_context, 879428d7b3dSmrg .render_surface = render_surface, 880428d7b3dSmrg}; 881