diff options
Diffstat (limited to 'xvmc/i965_xvmc.c')
-rw-r--r-- | xvmc/i965_xvmc.c | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/xvmc/i965_xvmc.c b/xvmc/i965_xvmc.c new file mode 100644 index 00000000..1850480c --- /dev/null +++ b/xvmc/i965_xvmc.c @@ -0,0 +1,880 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: + * Zou Nan hai <nanhai.zou@intel.com> + * + */ +#include "intel_xvmc_private.h" +#include "i830_reg.h" +#include "i965_reg.h" +#include "brw_defines.h" +#include "brw_structs.h" +#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0) +#define URB_SIZE 256 /* XXX */ + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +enum interface { + INTRA_INTERFACE = 0, /* non field intra */ + NULL_INTERFACE, /* fill with white, do nothing, for debug */ + FORWARD_INTERFACE, /* non field forward predict */ + BACKWARD_INTERFACE, /* non field backward predict */ + F_B_INTERFACE, /* non field forward and backward predict */ + FIELD_FORWARD_INTERFACE, /* field forward predict */ + FIELD_BACKWARD_INTERFACE, /* field backward predict */ + FIELD_F_B_INTERFACE, /* field forward and backward predict */ + DUAL_PRIME_INTERFACE +}; + +static const uint32_t ipicture_kernel_static[][4] = { +#include "shader/mc/ipicture.g4b" +}; + +static const uint32_t null_kernel_static[][4] = { +#include "shader/mc/null.g4b" +}; + +static const uint32_t frame_forward_kernel_static[][4] = { +#include "shader/mc/frame_forward.g4b" +}; + +static const uint32_t frame_backward_kernel_static[][4] = { +#include "shader/mc/frame_backward.g4b" +}; + +static const uint32_t frame_f_b_kernel_static[][4] = { +#include "shader/mc/frame_f_b.g4b" +}; + +static const uint32_t field_forward_kernel_static[][4] = { +#include "shader/mc/field_forward.g4b" +}; + +static const uint32_t field_backward_kernel_static[][4] = { +#include "shader/mc/field_backward.g4b" +}; + +static const uint32_t field_f_b_kernel_static[][4] = { +#include "shader/mc/field_f_b.g4b" +}; + +static const uint32_t dual_prime_kernel_static[][4] = { +#include "shader/mc/dual_prime.g4b" +}; + +static const uint32_t frame_forward_igd_kernel_static[][4] = { +#include "shader/mc/frame_forward_igd.g4b" +}; + +static const uint32_t frame_backward_igd_kernel_static[][4] = { +#include "shader/mc/frame_backward_igd.g4b" +}; + +static const uint32_t frame_f_b_igd_kernel_static[][4] = { +#include "shader/mc/frame_f_b_igd.g4b" +}; + +static const uint32_t field_forward_igd_kernel_static[][4] = { +#include "shader/mc/field_forward_igd.g4b" +}; + +static const uint32_t field_backward_igd_kernel_static[][4] = { +#include "shader/mc/field_backward_igd.g4b" +}; + +static const uint32_t field_f_b_igd_kernel_static[][4] = { +#include "shader/mc/field_f_b_igd.g4b" +}; + +static const uint32_t dual_prime_igd_kernel_static[][4] = { +#include "shader/mc/dual_prime_igd.g4b" +}; + +struct kernel_struct { + const uint32_t(*bin)[4]; + uint32_t size; +}; + +struct kernel_struct kernels_igd[] = { + {ipicture_kernel_static, sizeof(ipicture_kernel_static)} + , + {null_kernel_static, sizeof(null_kernel_static)} + , + {frame_forward_igd_kernel_static, + sizeof(frame_forward_igd_kernel_static)} + , + {frame_backward_igd_kernel_static, + sizeof(frame_backward_igd_kernel_static)} + , + {frame_f_b_igd_kernel_static, sizeof(frame_f_b_igd_kernel_static)} + , + {field_forward_igd_kernel_static, + sizeof(field_forward_igd_kernel_static)} + , + {field_backward_igd_kernel_static, + sizeof(field_backward_igd_kernel_static)} + , + {field_f_b_igd_kernel_static, sizeof(field_f_b_igd_kernel_static)} + , + {dual_prime_igd_kernel_static, sizeof(dual_prime_igd_kernel_static)} +}; + +struct kernel_struct kernels_965[] = { + {ipicture_kernel_static, sizeof(ipicture_kernel_static)} + , + {null_kernel_static, sizeof(null_kernel_static)} + , + {frame_forward_kernel_static, sizeof(frame_forward_kernel_static)} + , + {frame_backward_kernel_static, sizeof(frame_backward_kernel_static)} + , + {frame_f_b_kernel_static, sizeof(frame_f_b_kernel_static)} + , + {field_forward_kernel_static, sizeof(field_forward_kernel_static)} + , + {field_backward_kernel_static, sizeof(field_backward_kernel_static)} + , + {field_f_b_kernel_static, sizeof(field_f_b_kernel_static)} + , + {dual_prime_kernel_static, sizeof(dual_prime_kernel_static)} +}; + +#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) + +#define MAX_SURFACE_NUM 10 +#define DESCRIPTOR_NUM 12 + +struct media_kernel_obj { + dri_bo *bo; +}; + +struct interface_descriptor_obj { + dri_bo *bo; + struct media_kernel_obj kernels[DESCRIPTOR_NUM]; +}; + +struct vfe_state_obj { + dri_bo *bo; + struct interface_descriptor_obj interface; +}; + +struct surface_obj { + dri_bo *bo; +}; + +struct surface_state_obj { + struct surface_obj surface; + dri_bo *bo; +}; + +struct binding_table_obj { + dri_bo *bo; + struct surface_state_obj surface_states[MAX_SURFACE_NUM]; +}; + +struct indirect_data_obj { + dri_bo *bo; +}; + +struct media_state { + unsigned int is_g4x:1; + unsigned int is_965_q:1; + + struct vfe_state_obj vfe_state; + struct binding_table_obj binding_table; + struct indirect_data_obj indirect_data; +}; +struct media_state media_state; + +static void free_object(struct media_state *s) +{ + int i; +#define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo) + FREE_ONE_BO(s->vfe_state.bo); + FREE_ONE_BO(s->vfe_state.interface.bo); + for (i = 0; i < DESCRIPTOR_NUM; i++) + FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo); + FREE_ONE_BO(s->binding_table.bo); + for (i = 0; i < MAX_SURFACE_NUM; i++) + FREE_ONE_BO(s->binding_table.surface_states[i].bo); + FREE_ONE_BO(s->indirect_data.bo); +} + +static int alloc_object(struct media_state *s) +{ + int i; + + for (i = 0; i < MAX_SURFACE_NUM; i++) { + s->binding_table.surface_states[i].bo = + drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", + sizeof(struct brw_surface_state), + 0x1000); + if (!s->binding_table.surface_states[i].bo) + goto out; + } + return 0; +out: + free_object(s); + return BadAlloc; +} + +static Status destroy_context(Display * display, XvMCContext * context) +{ + struct intel_xvmc_context *intel_ctx; + intel_ctx = context->privData; + free(intel_ctx->hw); + free(intel_ctx); + return Success; +} + +#define STRIDE(w) (w) +#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1))) + +static void flush() +{ + struct brw_mi_flush flush; + memset(&flush, 0, sizeof(flush)); + flush.opcode = CMD_MI_FLUSH; + flush.flags = (1 << 1); + BATCH_STRUCT(flush); +} + +static void clear_sf_state() +{ + struct brw_sf_unit_state sf; + memset(&sf, 0, sizeof(sf)); + /* TODO */ +} + +/* urb fence must be aligned to cacheline */ +static void align_urb_fence() +{ + BATCH_LOCALS; + int i, offset_to_next_cacheline; + unsigned long batch_offset; + BEGIN_BATCH(3); + batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr; + offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset; + if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) { + for (i = 0; i < offset_to_next_cacheline / 4; i++) + OUT_BATCH(0); + ADVANCE_BATCH(); + } +} + +/* setup urb layout for media */ +static void urb_layout() +{ + BATCH_LOCALS; + align_urb_fence(); + BEGIN_BATCH(3); + OUT_BATCH(BRW_URB_FENCE | + UF0_VFE_REALLOC | + UF0_CS_REALLOC | + UF0_SF_REALLOC | + UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1); + OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) | + (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT)); + + OUT_BATCH(((URB_SIZE) << UF2_VFE_FENCE_SHIFT) | /* VFE_SIZE */ + ((URB_SIZE) << UF2_CS_FENCE_SHIFT)); /* CS_SIZE is 0 */ + ADVANCE_BATCH(); +} + +static void media_state_pointers(struct media_state *media_state) +{ + BATCH_LOCALS; + BEGIN_BATCH(3); + OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1); + OUT_BATCH(0); + OUT_RELOC(media_state->vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); + ADVANCE_BATCH(); +} + +/* setup 2D surface for media_read or media_write + */ +static Status setup_media_surface(struct media_state *media_state, + int surface_num, dri_bo * bo, + unsigned long offset, int w, int h, + Bool write) +{ + struct brw_surface_state s, *ss = &s; + + memset(ss, 0, sizeof(struct brw_surface_state)); + ss->ss0.surface_type = BRW_SURFACE_2D; + ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT; + ss->ss1.base_addr = offset + bo->offset; + ss->ss2.width = w - 1; + ss->ss2.height = h - 1; + ss->ss3.pitch = w - 1; + + if (media_state->binding_table.surface_states[surface_num].bo) + drm_intel_bo_unreference(media_state-> + binding_table.surface_states + [surface_num].bo); + media_state->binding_table.surface_states[surface_num].bo = + drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", + sizeof(struct brw_surface_state), 0x1000); + if (!media_state->binding_table.surface_states[surface_num].bo) + return BadAlloc; + + drm_intel_bo_subdata(media_state-> + binding_table.surface_states[surface_num].bo, 0, + sizeof(*ss), ss); + + drm_intel_bo_emit_reloc(media_state-> + binding_table.surface_states[surface_num].bo, + offsetof(struct brw_surface_state, ss1), bo, + offset, I915_GEM_DOMAIN_RENDER, + write ? I915_GEM_DOMAIN_RENDER : 0); + + return Success; +} + +static Status setup_surfaces(struct media_state *media_state, + dri_bo * dst_bo, dri_bo * past_bo, + dri_bo * future_bo, int w, int h) +{ + Status ret; + ret = setup_media_surface(media_state, 0, dst_bo, 0, w, h, TRUE); + if (ret != Success) + return ret; + ret = + setup_media_surface(media_state, 1, dst_bo, w * h, w / 2, h / 2, + TRUE); + if (ret != Success) + return ret; + ret = + setup_media_surface(media_state, 2, dst_bo, w * h + w * h / 4, + w / 2, h / 2, TRUE); + if (ret != Success) + return ret; + if (past_bo) { + ret = + setup_media_surface(media_state, 4, past_bo, 0, w, h, + FALSE); + if (ret != Success) + return ret; + ret = + setup_media_surface(media_state, 5, past_bo, w * h, w / 2, + h / 2, FALSE); + if (ret != Success) + return ret; + ret = + setup_media_surface(media_state, 6, past_bo, + w * h + w * h / 4, w / 2, h / 2, FALSE); + if (ret != Success) + return ret; + } + if (future_bo) { + ret = + setup_media_surface(media_state, 7, future_bo, 0, w, h, + FALSE); + if (ret != Success) + return ret; + ret = + setup_media_surface(media_state, 8, future_bo, w * h, w / 2, + h / 2, FALSE); + if (ret != Success) + return ret; + ret = + setup_media_surface(media_state, 9, future_bo, + w * h + w * h / 4, w / 2, h / 2, FALSE); + if (ret != Success) + return ret; + } + return Success; +} + +/* BUFFER SURFACE has a strange format + * the size of the surface is in part of w h and d component + */ + +static Status setup_blocks(struct media_state *media_state, + unsigned int block_size) +{ + union element { + struct { + unsigned int w:7; + unsigned int h:13; + unsigned int d:7; + unsigned int pad:7; + } whd; + unsigned int size; + } e; + struct brw_surface_state ss; + memset(&ss, 0, sizeof(struct brw_surface_state)); + ss.ss0.surface_type = BRW_SURFACE_BUFFER; + ss.ss0.surface_format = BRW_SURFACEFORMAT_R8_UINT; + ss.ss1.base_addr = media_state->indirect_data.bo->offset; + + e.size = block_size - 1; + ss.ss2.width = e.whd.w; + ss.ss2.height = e.whd.h; + ss.ss3.depth = e.whd.d; + ss.ss3.pitch = block_size - 1; + + if (media_state->binding_table.surface_states[3].bo) + drm_intel_bo_unreference(media_state-> + binding_table.surface_states[3].bo); + + media_state->binding_table.surface_states[3].bo = + drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state", + sizeof(struct brw_surface_state), 0x1000); + if (!media_state->binding_table.surface_states[3].bo) + return BadAlloc; + + drm_intel_bo_subdata(media_state->binding_table.surface_states[3].bo, 0, + sizeof(ss), &ss); + + drm_intel_bo_emit_reloc(media_state->binding_table.surface_states[3].bo, + offsetof(struct brw_surface_state, ss1), + media_state->indirect_data.bo, 0, + I915_GEM_DOMAIN_SAMPLER, 0); + return Success; +} + +/* setup state base address */ +static void state_base_address() +{ + BATCH_LOCALS; + BEGIN_BATCH(6); + OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4); + OUT_BATCH(0 | BASE_ADDRESS_MODIFY); + OUT_BATCH(0 | BASE_ADDRESS_MODIFY); + OUT_BATCH(0 | BASE_ADDRESS_MODIFY); + OUT_BATCH(0 | BASE_ADDRESS_MODIFY); + OUT_BATCH(0xFFFFF000 | BASE_ADDRESS_MODIFY); + ADVANCE_BATCH(); +} + +/* select media pipeline */ +static void pipeline_select(struct media_state *media_state) +{ + BATCH_LOCALS; + BEGIN_BATCH(1); + if (media_state->is_g4x) + OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); + else + OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA); + ADVANCE_BATCH(); +} + +/* kick media object to gpu */ +static void send_media_object(XvMCMacroBlock * mb, int offset, + enum interface interface) +{ + BATCH_LOCALS; + BEGIN_BATCH(13); + OUT_BATCH(BRW_MEDIA_OBJECT | 11); + OUT_BATCH(interface); + if (media_state.is_965_q) { + OUT_BATCH(0); + OUT_BATCH(0); + } else { + OUT_BATCH(6 * 128); + OUT_RELOC(media_state.indirect_data.bo, + I915_GEM_DOMAIN_INSTRUCTION, 0, offset); + } + + OUT_BATCH(mb->x << 4); //g1.0 + OUT_BATCH(mb->y << 4); + OUT_RELOC(media_state.indirect_data.bo, //g1.8 + I915_GEM_DOMAIN_INSTRUCTION, 0, offset); + OUT_BATCH_SHORT(mb->coded_block_pattern); //g1.12 + OUT_BATCH_SHORT(mb->PMV[0][0][0]); //g1.14 + OUT_BATCH_SHORT(mb->PMV[0][0][1]); //g1.16 + OUT_BATCH_SHORT(mb->PMV[0][1][0]); //g1.18 + OUT_BATCH_SHORT(mb->PMV[0][1][1]); //g1.20 + + OUT_BATCH_SHORT(mb->PMV[1][0][0]); //g1.22 + OUT_BATCH_SHORT(mb->PMV[1][0][1]); //g1.24 + OUT_BATCH_SHORT(mb->PMV[1][1][0]); //g1.26 + OUT_BATCH_SHORT(mb->PMV[1][1][1]); //g1.28 + OUT_BATCH_CHAR(mb->dct_type); //g1.30 + OUT_BATCH_CHAR(mb->motion_vertical_field_select); //g1.31 + + if (media_state.is_965_q) + OUT_BATCH(0x0); + else + OUT_BATCH(0xffffffff); + ADVANCE_BATCH(); +} + +static Status binding_tables(struct media_state *media_state) +{ + unsigned int binding_table[MAX_SURFACE_NUM]; + int i; + + if (media_state->binding_table.bo) + drm_intel_bo_unreference(media_state->binding_table.bo); + media_state->binding_table.bo = + drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table", + MAX_SURFACE_NUM * 4, 0x1000); + if (!media_state->binding_table.bo) + return BadAlloc; + + for (i = 0; i < MAX_SURFACE_NUM; i++) + binding_table[i] = + media_state->binding_table.surface_states[i].bo->offset; + drm_intel_bo_subdata(media_state->binding_table.bo, 0, + sizeof(binding_table), binding_table); + + for (i = 0; i < MAX_SURFACE_NUM; i++) + drm_intel_bo_emit_reloc(media_state->binding_table.bo, + i * sizeof(unsigned int), + media_state-> + binding_table.surface_states[i].bo, 0, + I915_GEM_DOMAIN_INSTRUCTION, 0); + return Success; +} + +static int media_kernels(struct media_state *media_state) +{ + struct kernel_struct *kernels; + int kernel_array_size, i; + + if (media_state->is_g4x) { + kernels = kernels_igd; + kernel_array_size = ARRAY_SIZE(kernels_igd); + } else { + kernels = kernels_965; + kernel_array_size = ARRAY_SIZE(kernels_965); + } + + for (i = 0; i < kernel_array_size; i++) { + media_state->vfe_state.interface.kernels[i].bo = + drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel", + kernels[i].size, 0x1000); + if (!media_state->vfe_state.interface.kernels[i].bo) + goto out; + } + + for (i = 0; i < kernel_array_size; i++) { + dri_bo *bo = media_state->vfe_state.interface.kernels[i].bo; + drm_intel_bo_subdata(bo, 0, kernels[i].size, kernels[i].bin); + } + return 0; +out: + free_object(media_state); + return BadAlloc; +} + +static void setup_interface(struct media_state *media_state, enum interface i) +{ + struct brw_interface_descriptor desc; + memset(&desc, 0, sizeof(desc)); + + desc.desc0.grf_reg_blocks = 15; + desc.desc0.kernel_start_pointer = + media_state->vfe_state.interface.kernels[i].bo->offset >> 6; + + desc.desc1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; + + /* use same binding table for all interface + * may change this if it affect performance + */ + desc.desc3.binding_table_entry_count = MAX_SURFACE_NUM; + desc.desc3.binding_table_pointer = + media_state->binding_table.bo->offset >> 5; + + drm_intel_bo_subdata(media_state->vfe_state.interface.bo, + i * sizeof(desc), sizeof(desc), &desc); + + drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo, + i * sizeof(desc) + + offsetof(struct brw_interface_descriptor, + desc0), + media_state->vfe_state.interface.kernels[i].bo, + desc.desc0.grf_reg_blocks, + I915_GEM_DOMAIN_INSTRUCTION, 0); + + drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo, + i * sizeof(desc) + + offsetof(struct brw_interface_descriptor, + desc3), media_state->binding_table.bo, + desc.desc3.binding_table_entry_count, + I915_GEM_DOMAIN_INSTRUCTION, 0); +} + +static Status interface_descriptor(struct media_state *media_state) +{ + if (media_state->vfe_state.interface.bo) + drm_intel_bo_unreference(media_state->vfe_state.interface.bo); + media_state->vfe_state.interface.bo = + drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces", + DESCRIPTOR_NUM * + sizeof(struct brw_interface_descriptor), 0x1000); + if (!media_state->vfe_state.interface.bo) + return BadAlloc; + + setup_interface(media_state, INTRA_INTERFACE); + setup_interface(media_state, NULL_INTERFACE); + setup_interface(media_state, FORWARD_INTERFACE); + setup_interface(media_state, FIELD_FORWARD_INTERFACE); + setup_interface(media_state, BACKWARD_INTERFACE); + setup_interface(media_state, FIELD_BACKWARD_INTERFACE); + setup_interface(media_state, F_B_INTERFACE); + setup_interface(media_state, FIELD_F_B_INTERFACE); + setup_interface(media_state, DUAL_PRIME_INTERFACE); + return Success; +} + +static Status vfe_state(struct media_state *media_state) +{ + struct brw_vfe_state state; + memset(&state, 0, sizeof(state)); + + /* no scratch space */ + state.vfe1.vfe_mode = VFE_GENERIC_MODE; + state.vfe1.num_urb_entries = 1; + /* XXX TODO */ + /* should carefully caculate those values for performance */ + state.vfe1.urb_entry_alloc_size = 2; + state.vfe1.max_threads = 31; + state.vfe2.interface_descriptor_base = + media_state->vfe_state.interface.bo->offset >> 4; + + if (media_state->vfe_state.bo) + drm_intel_bo_unreference(media_state->vfe_state.bo); + media_state->vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, + "vfe state", + sizeof(struct + brw_vfe_state), + 0x1000); + if (!media_state->vfe_state.bo) + return BadAlloc; + + drm_intel_bo_subdata(media_state->vfe_state.bo, 0, sizeof(state), + &state); + + drm_intel_bo_emit_reloc(media_state->vfe_state.bo, + offsetof(struct brw_vfe_state, vfe2), + media_state->vfe_state.interface.bo, 0, + I915_GEM_DOMAIN_INSTRUCTION, 0); + return Success; +} + +static Status render_surface(Display * display, + XvMCContext * context, + unsigned int picture_structure, + XvMCSurface * target_surface, + XvMCSurface * past_surface, + XvMCSurface * future_surface, + unsigned int flags, + unsigned int num_macroblocks, + unsigned int first_macroblock, + XvMCMacroBlockArray * macroblock_array, + XvMCBlockArray * blocks) +{ + + intel_xvmc_context_ptr intel_ctx; + int i, j; + struct i965_xvmc_context *i965_ctx; + XvMCMacroBlock *mb; + struct intel_xvmc_surface *priv_target_surface = + target_surface->privData; + struct intel_xvmc_surface *priv_past_surface = + past_surface ? past_surface->privData : 0; + struct intel_xvmc_surface *priv_future_surface = + future_surface ? future_surface->privData : 0; + unsigned short *block_ptr; + intel_ctx = context->privData; + i965_ctx = context->privData; + if (!intel_ctx) { + XVMC_ERR("Can't find intel xvmc context\n"); + return BadValue; + } + + if (media_state.indirect_data.bo) { + drm_intel_gem_bo_unmap_gtt(media_state. + indirect_data.bo); + + drm_intel_bo_unreference(media_state.indirect_data.bo); + } + media_state.indirect_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr, + "indirect data", + 128 * 6 * + num_macroblocks, 64); + if (!media_state.indirect_data.bo) + return BadAlloc; + setup_surfaces(&media_state, + priv_target_surface->bo, + past_surface ? priv_past_surface->bo : NULL, + future_surface ? priv_future_surface->bo : NULL, + context->width, context->height); + setup_blocks(&media_state, 128 * 6 * num_macroblocks); + binding_tables(&media_state); + interface_descriptor(&media_state); + vfe_state(&media_state); + + drm_intel_gem_bo_map_gtt(media_state.indirect_data.bo); + + block_ptr = media_state.indirect_data.bo->virtual; + for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) { + unsigned short *mb_block_ptr; + mb = ¯oblock_array->macro_blocks[i]; + mb_block_ptr = &blocks->blocks[(mb->index << 6)]; + if (mb->coded_block_pattern & 0x20) { + for (j = 0; j < 8; j++) + memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j, + 16); + mb_block_ptr += 64; + } + + if (mb->coded_block_pattern & 0x10) { + for (j = 0; j < 8; j++) + memcpy(block_ptr + 16 * j + 8, + mb_block_ptr + 8 * j, 16); + mb_block_ptr += 64; + } + block_ptr += 2 * 64; + if (mb->coded_block_pattern & 0x08) { + for (j = 0; j < 8; j++) + memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j, + 16); + mb_block_ptr += 64; + } + + if (mb->coded_block_pattern & 0x04) { + for (j = 0; j < 8; j++) + memcpy(block_ptr + 16 * j + 8, + mb_block_ptr + 8 * j, 16); + mb_block_ptr += 64; + } + + block_ptr += 2 * 64; + if (mb->coded_block_pattern & 0x2) { + memcpy(block_ptr, mb_block_ptr, 128); + mb_block_ptr += 64; + } + + block_ptr += 64; + if (mb->coded_block_pattern & 0x1) + memcpy(block_ptr, mb_block_ptr, 128); + block_ptr += 64; + } + { + int block_offset = 0; + LOCK_HARDWARE(intel_ctx->hw_context); + state_base_address(); + flush(); + clear_sf_state(); + pipeline_select(&media_state); + urb_layout(); + media_state_pointers(&media_state); + for (i = first_macroblock; + i < num_macroblocks + first_macroblock; + i++, block_offset += 128 * 6) { + mb = ¯oblock_array->macro_blocks[i]; + + if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) { + send_media_object(mb, block_offset, + INTRA_INTERFACE); + } else { + if (((mb->motion_type & 3) == + XVMC_PREDICTION_FRAME)) { + if ((mb->macroblock_type & + XVMC_MB_TYPE_MOTION_FORWARD)) { + if (((mb->macroblock_type & + XVMC_MB_TYPE_MOTION_BACKWARD))) + send_media_object(mb, + block_offset, + F_B_INTERFACE); + else + send_media_object(mb, + block_offset, + FORWARD_INTERFACE); + } else + if ((mb->macroblock_type & + XVMC_MB_TYPE_MOTION_BACKWARD)) + { + send_media_object(mb, + block_offset, + BACKWARD_INTERFACE); + } + } else if ((mb->motion_type & 3) == + XVMC_PREDICTION_FIELD) { + if ((mb->macroblock_type & + XVMC_MB_TYPE_MOTION_FORWARD)) { + if (((mb->macroblock_type & + XVMC_MB_TYPE_MOTION_BACKWARD))) + send_media_object(mb, + block_offset, + FIELD_F_B_INTERFACE); + else + + send_media_object(mb, + block_offset, + FIELD_FORWARD_INTERFACE); + } else + if ((mb->macroblock_type & + XVMC_MB_TYPE_MOTION_BACKWARD)) + { + send_media_object(mb, + block_offset, + FIELD_BACKWARD_INTERFACE); + } + } else { + send_media_object(mb, block_offset, + DUAL_PRIME_INTERFACE); + } + } + } + intelFlushBatch(TRUE); + UNLOCK_HARDWARE(intel_ctx->hw_context); + } + return Success; +} + +static Status create_context(Display * display, XvMCContext * context, + int priv_count, CARD32 * priv_data) +{ + struct intel_xvmc_context *intel_ctx; + struct intel_xvmc_hw_context *hw_ctx; + hw_ctx = (struct intel_xvmc_hw_context *)priv_data; + + intel_ctx = calloc(1, sizeof(struct intel_xvmc_context)); + if (!intel_ctx) + return BadAlloc; + intel_ctx->hw = hw_ctx; + intel_ctx->surface_bo_size + = SIZE_YUV420(context->width, context->height); + context->privData = intel_ctx; + + media_state.is_g4x = hw_ctx->i965.is_g4x; + media_state.is_965_q = hw_ctx->i965.is_965_q; + + if (alloc_object(&media_state)) + return BadAlloc; + if (media_kernels(&media_state)) + return BadAlloc; + return Success; +} + +struct _intel_xvmc_driver i965_xvmc_mc_driver = { + .type = XVMC_I965_MPEG2_MC, + .create_context = create_context, + .destroy_context = destroy_context, + .render_surface = render_surface, +}; |