103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2008 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Author:
2403b705cfSriastradh *    Zou Nan hai <nanhai.zou@intel.com>
2503b705cfSriastradh *
2603b705cfSriastradh */
2703b705cfSriastradh#include "intel_xvmc_private.h"
2803b705cfSriastradh#include "i830_reg.h"
2903b705cfSriastradh#include "i965_reg.h"
3003b705cfSriastradh#include "brw_defines.h"
3103b705cfSriastradh#include "brw_structs.h"
3203b705cfSriastradh#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0)
3303b705cfSriastradh#define URB_SIZE     256	/* XXX */
3403b705cfSriastradh
3503b705cfSriastradh#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
3603b705cfSriastradh
3703b705cfSriastradhenum interface {
3803b705cfSriastradh	INTRA_INTERFACE = 0,	/* non field intra */
3903b705cfSriastradh	NULL_INTERFACE,		/* fill with white, do nothing, for debug */
4003b705cfSriastradh	FORWARD_INTERFACE,	/* non field forward predict */
4103b705cfSriastradh	BACKWARD_INTERFACE,	/* non field backward predict */
4203b705cfSriastradh	F_B_INTERFACE,		/* non field forward and backward predict */
4303b705cfSriastradh	FIELD_FORWARD_INTERFACE,	/* field forward predict */
4403b705cfSriastradh	FIELD_BACKWARD_INTERFACE,	/* field backward predict */
4503b705cfSriastradh	FIELD_F_B_INTERFACE,	/* field forward and backward predict */
4603b705cfSriastradh	DUAL_PRIME_INTERFACE
4703b705cfSriastradh};
4803b705cfSriastradh
4903b705cfSriastradhstatic const uint32_t ipicture_kernel_static[][4] = {
5003b705cfSriastradh#include "shader/mc/ipicture.g4b"
5103b705cfSriastradh};
5203b705cfSriastradh
5303b705cfSriastradhstatic const uint32_t null_kernel_static[][4] = {
5403b705cfSriastradh#include "shader/mc/null.g4b"
5503b705cfSriastradh};
5603b705cfSriastradh
5703b705cfSriastradhstatic const uint32_t frame_forward_kernel_static[][4] = {
5803b705cfSriastradh#include "shader/mc/frame_forward.g4b"
5903b705cfSriastradh};
6003b705cfSriastradh
6103b705cfSriastradhstatic const uint32_t frame_backward_kernel_static[][4] = {
6203b705cfSriastradh#include "shader/mc/frame_backward.g4b"
6303b705cfSriastradh};
6403b705cfSriastradh
6503b705cfSriastradhstatic const uint32_t frame_f_b_kernel_static[][4] = {
6603b705cfSriastradh#include "shader/mc/frame_f_b.g4b"
6703b705cfSriastradh};
6803b705cfSriastradh
6903b705cfSriastradhstatic const uint32_t field_forward_kernel_static[][4] = {
7003b705cfSriastradh#include "shader/mc/field_forward.g4b"
7103b705cfSriastradh};
7203b705cfSriastradh
7303b705cfSriastradhstatic const uint32_t field_backward_kernel_static[][4] = {
7403b705cfSriastradh#include "shader/mc/field_backward.g4b"
7503b705cfSriastradh};
7603b705cfSriastradh
7703b705cfSriastradhstatic const uint32_t field_f_b_kernel_static[][4] = {
7803b705cfSriastradh#include "shader/mc/field_f_b.g4b"
7903b705cfSriastradh};
8003b705cfSriastradh
8103b705cfSriastradhstatic const uint32_t dual_prime_kernel_static[][4] = {
8203b705cfSriastradh#include "shader/mc/dual_prime.g4b"
8303b705cfSriastradh};
8403b705cfSriastradh
8503b705cfSriastradhstatic const uint32_t frame_forward_igd_kernel_static[][4] = {
8603b705cfSriastradh#include "shader/mc/frame_forward_igd.g4b"
8703b705cfSriastradh};
8803b705cfSriastradh
8903b705cfSriastradhstatic const uint32_t frame_backward_igd_kernel_static[][4] = {
9003b705cfSriastradh#include "shader/mc/frame_backward_igd.g4b"
9103b705cfSriastradh};
9203b705cfSriastradh
9303b705cfSriastradhstatic const uint32_t frame_f_b_igd_kernel_static[][4] = {
9403b705cfSriastradh#include "shader/mc/frame_f_b_igd.g4b"
9503b705cfSriastradh};
9603b705cfSriastradh
9703b705cfSriastradhstatic const uint32_t field_forward_igd_kernel_static[][4] = {
9803b705cfSriastradh#include "shader/mc/field_forward_igd.g4b"
9903b705cfSriastradh};
10003b705cfSriastradh
10103b705cfSriastradhstatic const uint32_t field_backward_igd_kernel_static[][4] = {
10203b705cfSriastradh#include "shader/mc/field_backward_igd.g4b"
10303b705cfSriastradh};
10403b705cfSriastradh
10503b705cfSriastradhstatic const uint32_t field_f_b_igd_kernel_static[][4] = {
10603b705cfSriastradh#include "shader/mc/field_f_b_igd.g4b"
10703b705cfSriastradh};
10803b705cfSriastradh
10903b705cfSriastradhstatic const uint32_t dual_prime_igd_kernel_static[][4] = {
11003b705cfSriastradh#include "shader/mc/dual_prime_igd.g4b"
11103b705cfSriastradh};
11203b705cfSriastradh
11303b705cfSriastradhstruct kernel_struct {
11403b705cfSriastradh	const uint32_t(*bin)[4];
11503b705cfSriastradh	uint32_t size;
11603b705cfSriastradh};
11703b705cfSriastradh
11803b705cfSriastradhstruct kernel_struct kernels_igd[] = {
11903b705cfSriastradh	{ipicture_kernel_static, sizeof(ipicture_kernel_static)}
12003b705cfSriastradh	,
12103b705cfSriastradh	{null_kernel_static, sizeof(null_kernel_static)}
12203b705cfSriastradh	,
12303b705cfSriastradh	{frame_forward_igd_kernel_static,
12403b705cfSriastradh	 sizeof(frame_forward_igd_kernel_static)}
12503b705cfSriastradh	,
12603b705cfSriastradh	{frame_backward_igd_kernel_static,
12703b705cfSriastradh	 sizeof(frame_backward_igd_kernel_static)}
12803b705cfSriastradh	,
12903b705cfSriastradh	{frame_f_b_igd_kernel_static, sizeof(frame_f_b_igd_kernel_static)}
13003b705cfSriastradh	,
13103b705cfSriastradh	{field_forward_igd_kernel_static,
13203b705cfSriastradh	 sizeof(field_forward_igd_kernel_static)}
13303b705cfSriastradh	,
13403b705cfSriastradh	{field_backward_igd_kernel_static,
13503b705cfSriastradh	 sizeof(field_backward_igd_kernel_static)}
13603b705cfSriastradh	,
13703b705cfSriastradh	{field_f_b_igd_kernel_static, sizeof(field_f_b_igd_kernel_static)}
13803b705cfSriastradh	,
13903b705cfSriastradh	{dual_prime_igd_kernel_static, sizeof(dual_prime_igd_kernel_static)}
14003b705cfSriastradh};
14103b705cfSriastradh
14203b705cfSriastradhstruct kernel_struct kernels_965[] = {
14303b705cfSriastradh	{ipicture_kernel_static, sizeof(ipicture_kernel_static)}
14403b705cfSriastradh	,
14503b705cfSriastradh	{null_kernel_static, sizeof(null_kernel_static)}
14603b705cfSriastradh	,
14703b705cfSriastradh	{frame_forward_kernel_static, sizeof(frame_forward_kernel_static)}
14803b705cfSriastradh	,
14903b705cfSriastradh	{frame_backward_kernel_static, sizeof(frame_backward_kernel_static)}
15003b705cfSriastradh	,
15103b705cfSriastradh	{frame_f_b_kernel_static, sizeof(frame_f_b_kernel_static)}
15203b705cfSriastradh	,
15303b705cfSriastradh	{field_forward_kernel_static, sizeof(field_forward_kernel_static)}
15403b705cfSriastradh	,
15503b705cfSriastradh	{field_backward_kernel_static, sizeof(field_backward_kernel_static)}
15603b705cfSriastradh	,
15703b705cfSriastradh	{field_f_b_kernel_static, sizeof(field_f_b_kernel_static)}
15803b705cfSriastradh	,
15903b705cfSriastradh	{dual_prime_kernel_static, sizeof(dual_prime_kernel_static)}
16003b705cfSriastradh};
16103b705cfSriastradh
16203b705cfSriastradh#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
16303b705cfSriastradh
16403b705cfSriastradh#define MAX_SURFACE_NUM	10
16503b705cfSriastradh#define DESCRIPTOR_NUM 12
16603b705cfSriastradh
16703b705cfSriastradhstruct media_kernel_obj {
16803b705cfSriastradh	dri_bo *bo;
16903b705cfSriastradh};
17003b705cfSriastradh
17103b705cfSriastradhstruct interface_descriptor_obj {
17203b705cfSriastradh	dri_bo *bo;
17303b705cfSriastradh	struct media_kernel_obj kernels[DESCRIPTOR_NUM];
17403b705cfSriastradh};
17503b705cfSriastradh
17603b705cfSriastradhstruct vfe_state_obj {
17703b705cfSriastradh	dri_bo *bo;
17803b705cfSriastradh	struct interface_descriptor_obj interface;
17903b705cfSriastradh};
18003b705cfSriastradh
18103b705cfSriastradhstruct surface_obj {
18203b705cfSriastradh	dri_bo *bo;
18303b705cfSriastradh};
18403b705cfSriastradh
18503b705cfSriastradhstruct surface_state_obj {
18603b705cfSriastradh	struct surface_obj surface;
18703b705cfSriastradh	dri_bo *bo;
18803b705cfSriastradh};
18903b705cfSriastradh
19003b705cfSriastradhstruct binding_table_obj {
19103b705cfSriastradh	dri_bo *bo;
19203b705cfSriastradh	struct surface_state_obj surface_states[MAX_SURFACE_NUM];
19303b705cfSriastradh};
19403b705cfSriastradh
19503b705cfSriastradhstruct indirect_data_obj {
19603b705cfSriastradh	dri_bo *bo;
19703b705cfSriastradh};
19803b705cfSriastradh
19903b705cfSriastradhstruct media_state {
20003b705cfSriastradh	unsigned int is_g4x:1;
20103b705cfSriastradh	unsigned int is_965_q:1;
20203b705cfSriastradh
20303b705cfSriastradh	struct vfe_state_obj vfe_state;
20403b705cfSriastradh	struct binding_table_obj binding_table;
20503b705cfSriastradh	struct indirect_data_obj indirect_data;
20603b705cfSriastradh};
20703b705cfSriastradhstruct media_state media_state;
20803b705cfSriastradh
20903b705cfSriastradhstatic void free_object(struct media_state *s)
21003b705cfSriastradh{
21103b705cfSriastradh	int i;
21203b705cfSriastradh#define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo)
21303b705cfSriastradh	FREE_ONE_BO(s->vfe_state.bo);
21403b705cfSriastradh	FREE_ONE_BO(s->vfe_state.interface.bo);
21503b705cfSriastradh	for (i = 0; i < DESCRIPTOR_NUM; i++)
21603b705cfSriastradh		FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo);
21703b705cfSriastradh	FREE_ONE_BO(s->binding_table.bo);
21803b705cfSriastradh	for (i = 0; i < MAX_SURFACE_NUM; i++)
21903b705cfSriastradh		FREE_ONE_BO(s->binding_table.surface_states[i].bo);
22003b705cfSriastradh	FREE_ONE_BO(s->indirect_data.bo);
22103b705cfSriastradh}
22203b705cfSriastradh
22303b705cfSriastradhstatic int alloc_object(struct media_state *s)
22403b705cfSriastradh{
22503b705cfSriastradh	int i;
22603b705cfSriastradh
22703b705cfSriastradh	for (i = 0; i < MAX_SURFACE_NUM; i++) {
22803b705cfSriastradh		s->binding_table.surface_states[i].bo =
22903b705cfSriastradh		    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
23003b705cfSriastradh				       sizeof(struct brw_surface_state),
23103b705cfSriastradh				       0x1000);
23203b705cfSriastradh		if (!s->binding_table.surface_states[i].bo)
23303b705cfSriastradh			goto out;
23403b705cfSriastradh	}
23503b705cfSriastradh	return 0;
23603b705cfSriastradhout:
23703b705cfSriastradh	free_object(s);
23803b705cfSriastradh	return BadAlloc;
23903b705cfSriastradh}
24003b705cfSriastradh
24103b705cfSriastradhstatic Status destroy_context(Display * display, XvMCContext * context)
24203b705cfSriastradh{
24303b705cfSriastradh	struct intel_xvmc_context *intel_ctx;
24403b705cfSriastradh	intel_ctx = context->privData;
24503b705cfSriastradh	free(intel_ctx->hw);
24603b705cfSriastradh	free(intel_ctx);
24703b705cfSriastradh	return Success;
24803b705cfSriastradh}
24903b705cfSriastradh
25003b705cfSriastradh#define STRIDE(w)               (w)
25103b705cfSriastradh#define SIZE_YUV420(w, h)       (h * (STRIDE(w) + STRIDE(w >> 1)))
25203b705cfSriastradh
25303b705cfSriastradhstatic void flush()
25403b705cfSriastradh{
25503b705cfSriastradh	struct brw_mi_flush flush;
25603b705cfSriastradh	memset(&flush, 0, sizeof(flush));
25703b705cfSriastradh	flush.opcode = CMD_MI_FLUSH;
25803b705cfSriastradh	flush.flags = (1 << 1);
25903b705cfSriastradh	BATCH_STRUCT(flush);
26003b705cfSriastradh}
26103b705cfSriastradh
26203b705cfSriastradhstatic void clear_sf_state()
26303b705cfSriastradh{
26403b705cfSriastradh	struct brw_sf_unit_state sf;
26503b705cfSriastradh	memset(&sf, 0, sizeof(sf));
26603b705cfSriastradh	/* TODO */
26703b705cfSriastradh}
26803b705cfSriastradh
26903b705cfSriastradh/* urb fence must be aligned to cacheline */
27003b705cfSriastradhstatic void align_urb_fence()
27103b705cfSriastradh{
27203b705cfSriastradh	BATCH_LOCALS;
27303b705cfSriastradh	int i, offset_to_next_cacheline;
27403b705cfSriastradh	unsigned long batch_offset;
27503b705cfSriastradh	BEGIN_BATCH(3);
27603b705cfSriastradh	batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr;
27703b705cfSriastradh	offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset;
27803b705cfSriastradh	if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) {
27903b705cfSriastradh		for (i = 0; i < offset_to_next_cacheline / 4; i++)
28003b705cfSriastradh			OUT_BATCH(0);
28103b705cfSriastradh		ADVANCE_BATCH();
28203b705cfSriastradh	}
28303b705cfSriastradh}
28403b705cfSriastradh
28503b705cfSriastradh/* setup urb layout for media */
28603b705cfSriastradhstatic void urb_layout()
28703b705cfSriastradh{
28803b705cfSriastradh	BATCH_LOCALS;
28903b705cfSriastradh	align_urb_fence();
29003b705cfSriastradh	BEGIN_BATCH(3);
29103b705cfSriastradh	OUT_BATCH(BRW_URB_FENCE |
29203b705cfSriastradh		  UF0_VFE_REALLOC |
29303b705cfSriastradh		  UF0_CS_REALLOC |
29403b705cfSriastradh		  UF0_SF_REALLOC |
29503b705cfSriastradh		  UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1);
29603b705cfSriastradh	OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) |
29703b705cfSriastradh		  (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT));
29803b705cfSriastradh
29903b705cfSriastradh	OUT_BATCH(((URB_SIZE) << UF2_VFE_FENCE_SHIFT) |	/* VFE_SIZE */
30003b705cfSriastradh		  ((URB_SIZE) << UF2_CS_FENCE_SHIFT));	/* CS_SIZE is 0 */
30103b705cfSriastradh	ADVANCE_BATCH();
30203b705cfSriastradh}
30303b705cfSriastradh
30403b705cfSriastradhstatic void media_state_pointers(struct media_state *media_state)
30503b705cfSriastradh{
30603b705cfSriastradh	BATCH_LOCALS;
30703b705cfSriastradh	BEGIN_BATCH(3);
30803b705cfSriastradh	OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1);
30903b705cfSriastradh	OUT_BATCH(0);
31003b705cfSriastradh	OUT_RELOC(media_state->vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
31103b705cfSriastradh	ADVANCE_BATCH();
31203b705cfSriastradh}
31303b705cfSriastradh
31403b705cfSriastradh/* setup 2D surface for media_read or media_write
31503b705cfSriastradh */
31603b705cfSriastradhstatic Status setup_media_surface(struct media_state *media_state,
31703b705cfSriastradh				  int surface_num, dri_bo * bo,
31803b705cfSriastradh				  unsigned long offset, int w, int h,
31903b705cfSriastradh				  Bool write)
32003b705cfSriastradh{
32103b705cfSriastradh	struct brw_surface_state s, *ss = &s;
32203b705cfSriastradh
32303b705cfSriastradh	memset(ss, 0, sizeof(struct brw_surface_state));
32403b705cfSriastradh	ss->ss0.surface_type = BRW_SURFACE_2D;
32503b705cfSriastradh	ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT;
32603b705cfSriastradh	ss->ss1.base_addr = offset + bo->offset;
32703b705cfSriastradh	ss->ss2.width = w - 1;
32803b705cfSriastradh	ss->ss2.height = h - 1;
32903b705cfSriastradh	ss->ss3.pitch = w - 1;
33003b705cfSriastradh
33103b705cfSriastradh	if (media_state->binding_table.surface_states[surface_num].bo)
33203b705cfSriastradh		drm_intel_bo_unreference(media_state->
33303b705cfSriastradh					 binding_table.surface_states
33403b705cfSriastradh					 [surface_num].bo);
33503b705cfSriastradh	media_state->binding_table.surface_states[surface_num].bo =
33603b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
33703b705cfSriastradh			       sizeof(struct brw_surface_state), 0x1000);
33803b705cfSriastradh	if (!media_state->binding_table.surface_states[surface_num].bo)
33903b705cfSriastradh		return BadAlloc;
34003b705cfSriastradh
34103b705cfSriastradh	drm_intel_bo_subdata(media_state->
34203b705cfSriastradh			     binding_table.surface_states[surface_num].bo, 0,
34303b705cfSriastradh			     sizeof(*ss), ss);
34403b705cfSriastradh
34503b705cfSriastradh	drm_intel_bo_emit_reloc(media_state->
34603b705cfSriastradh				binding_table.surface_states[surface_num].bo,
34703b705cfSriastradh				offsetof(struct brw_surface_state, ss1), bo,
34803b705cfSriastradh				offset, I915_GEM_DOMAIN_RENDER,
34903b705cfSriastradh				write ? I915_GEM_DOMAIN_RENDER : 0);
35003b705cfSriastradh
35103b705cfSriastradh	return Success;
35203b705cfSriastradh}
35303b705cfSriastradh
35403b705cfSriastradhstatic Status setup_surfaces(struct media_state *media_state,
35503b705cfSriastradh			     dri_bo * dst_bo, dri_bo * past_bo,
35603b705cfSriastradh			     dri_bo * future_bo, int w, int h)
35703b705cfSriastradh{
35803b705cfSriastradh	Status ret;
35903b705cfSriastradh	ret = setup_media_surface(media_state, 0, dst_bo, 0, w, h, TRUE);
36003b705cfSriastradh	if (ret != Success)
36103b705cfSriastradh		return ret;
36203b705cfSriastradh	ret =
36303b705cfSriastradh	    setup_media_surface(media_state, 1, dst_bo, w * h, w / 2, h / 2,
36403b705cfSriastradh				TRUE);
36503b705cfSriastradh	if (ret != Success)
36603b705cfSriastradh		return ret;
36703b705cfSriastradh	ret =
36803b705cfSriastradh	    setup_media_surface(media_state, 2, dst_bo, w * h + w * h / 4,
36903b705cfSriastradh				w / 2, h / 2, TRUE);
37003b705cfSriastradh	if (ret != Success)
37103b705cfSriastradh		return ret;
37203b705cfSriastradh	if (past_bo) {
37303b705cfSriastradh		ret =
37403b705cfSriastradh		    setup_media_surface(media_state, 4, past_bo, 0, w, h,
37503b705cfSriastradh					FALSE);
37603b705cfSriastradh		if (ret != Success)
37703b705cfSriastradh			return ret;
37803b705cfSriastradh		ret =
37903b705cfSriastradh		    setup_media_surface(media_state, 5, past_bo, w * h, w / 2,
38003b705cfSriastradh					h / 2, FALSE);
38103b705cfSriastradh		if (ret != Success)
38203b705cfSriastradh			return ret;
38303b705cfSriastradh		ret =
38403b705cfSriastradh		    setup_media_surface(media_state, 6, past_bo,
38503b705cfSriastradh					w * h + w * h / 4, w / 2, h / 2, FALSE);
38603b705cfSriastradh		if (ret != Success)
38703b705cfSriastradh			return ret;
38803b705cfSriastradh	}
38903b705cfSriastradh	if (future_bo) {
39003b705cfSriastradh		ret =
39103b705cfSriastradh		    setup_media_surface(media_state, 7, future_bo, 0, w, h,
39203b705cfSriastradh					FALSE);
39303b705cfSriastradh		if (ret != Success)
39403b705cfSriastradh			return ret;
39503b705cfSriastradh		ret =
39603b705cfSriastradh		    setup_media_surface(media_state, 8, future_bo, w * h, w / 2,
39703b705cfSriastradh					h / 2, FALSE);
39803b705cfSriastradh		if (ret != Success)
39903b705cfSriastradh			return ret;
40003b705cfSriastradh		ret =
40103b705cfSriastradh		    setup_media_surface(media_state, 9, future_bo,
40203b705cfSriastradh					w * h + w * h / 4, w / 2, h / 2, FALSE);
40303b705cfSriastradh		if (ret != Success)
40403b705cfSriastradh			return ret;
40503b705cfSriastradh	}
40603b705cfSriastradh	return Success;
40703b705cfSriastradh}
40803b705cfSriastradh
40903b705cfSriastradh/* BUFFER SURFACE has a strange format
41003b705cfSriastradh * the size of the surface is in part of w h and d component
41103b705cfSriastradh */
41203b705cfSriastradh
41303b705cfSriastradhstatic Status setup_blocks(struct media_state *media_state,
41403b705cfSriastradh			   unsigned int block_size)
41503b705cfSriastradh{
41603b705cfSriastradh	union element {
41703b705cfSriastradh		struct {
41803b705cfSriastradh			unsigned int w:7;
41903b705cfSriastradh			unsigned int h:13;
42003b705cfSriastradh			unsigned int d:7;
42103b705cfSriastradh			unsigned int pad:7;
42203b705cfSriastradh		} whd;
42303b705cfSriastradh		unsigned int size;
42403b705cfSriastradh	} e;
42503b705cfSriastradh	struct brw_surface_state ss;
42603b705cfSriastradh	memset(&ss, 0, sizeof(struct brw_surface_state));
42703b705cfSriastradh	ss.ss0.surface_type = BRW_SURFACE_BUFFER;
42803b705cfSriastradh	ss.ss0.surface_format = BRW_SURFACEFORMAT_R8_UINT;
42903b705cfSriastradh	ss.ss1.base_addr = media_state->indirect_data.bo->offset;
43003b705cfSriastradh
43103b705cfSriastradh	e.size = block_size - 1;
43203b705cfSriastradh	ss.ss2.width = e.whd.w;
43303b705cfSriastradh	ss.ss2.height = e.whd.h;
43403b705cfSriastradh	ss.ss3.depth = e.whd.d;
43503b705cfSriastradh	ss.ss3.pitch = block_size - 1;
43603b705cfSriastradh
43703b705cfSriastradh	if (media_state->binding_table.surface_states[3].bo)
43803b705cfSriastradh		drm_intel_bo_unreference(media_state->
43903b705cfSriastradh					 binding_table.surface_states[3].bo);
44003b705cfSriastradh
44103b705cfSriastradh	media_state->binding_table.surface_states[3].bo =
44203b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
44303b705cfSriastradh			       sizeof(struct brw_surface_state), 0x1000);
44403b705cfSriastradh	if (!media_state->binding_table.surface_states[3].bo)
44503b705cfSriastradh		return BadAlloc;
44603b705cfSriastradh
44703b705cfSriastradh	drm_intel_bo_subdata(media_state->binding_table.surface_states[3].bo, 0,
44803b705cfSriastradh			     sizeof(ss), &ss);
44903b705cfSriastradh
45003b705cfSriastradh	drm_intel_bo_emit_reloc(media_state->binding_table.surface_states[3].bo,
45103b705cfSriastradh				offsetof(struct brw_surface_state, ss1),
45203b705cfSriastradh				media_state->indirect_data.bo, 0,
45303b705cfSriastradh				I915_GEM_DOMAIN_SAMPLER, 0);
45403b705cfSriastradh	return Success;
45503b705cfSriastradh}
45603b705cfSriastradh
45703b705cfSriastradh/* setup state base address */
45803b705cfSriastradhstatic void state_base_address()
45903b705cfSriastradh{
46003b705cfSriastradh	BATCH_LOCALS;
46103b705cfSriastradh	BEGIN_BATCH(6);
46203b705cfSriastradh	OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
46303b705cfSriastradh	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
46403b705cfSriastradh	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
46503b705cfSriastradh	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
46603b705cfSriastradh	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
46703b705cfSriastradh	OUT_BATCH(0xFFFFF000 | BASE_ADDRESS_MODIFY);
46803b705cfSriastradh	ADVANCE_BATCH();
46903b705cfSriastradh}
47003b705cfSriastradh
47103b705cfSriastradh/* select media pipeline */
47203b705cfSriastradhstatic void pipeline_select(struct media_state *media_state)
47303b705cfSriastradh{
47403b705cfSriastradh	BATCH_LOCALS;
47503b705cfSriastradh	BEGIN_BATCH(1);
47603b705cfSriastradh	if (media_state->is_g4x)
47703b705cfSriastradh		OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
47803b705cfSriastradh	else
47903b705cfSriastradh		OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
48003b705cfSriastradh	ADVANCE_BATCH();
48103b705cfSriastradh}
48203b705cfSriastradh
48303b705cfSriastradh/* kick media object to gpu */
48403b705cfSriastradhstatic void send_media_object(XvMCMacroBlock * mb, int offset,
48503b705cfSriastradh			      enum interface interface)
48603b705cfSriastradh{
48703b705cfSriastradh	BATCH_LOCALS;
48803b705cfSriastradh	BEGIN_BATCH(13);
48903b705cfSriastradh	OUT_BATCH(BRW_MEDIA_OBJECT | 11);
49003b705cfSriastradh	OUT_BATCH(interface);
49103b705cfSriastradh	if (media_state.is_965_q) {
49203b705cfSriastradh		OUT_BATCH(0);
49303b705cfSriastradh		OUT_BATCH(0);
49403b705cfSriastradh	} else {
49503b705cfSriastradh		OUT_BATCH(6 * 128);
49603b705cfSriastradh		OUT_RELOC(media_state.indirect_data.bo,
49703b705cfSriastradh			  I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
49803b705cfSriastradh	}
49903b705cfSriastradh
50003b705cfSriastradh	OUT_BATCH(mb->x << 4);	//g1.0
50103b705cfSriastradh	OUT_BATCH(mb->y << 4);
50203b705cfSriastradh	OUT_RELOC(media_state.indirect_data.bo,	//g1.8
50303b705cfSriastradh		  I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
50403b705cfSriastradh	OUT_BATCH_SHORT(mb->coded_block_pattern);	//g1.12
50503b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][0][0]);	//g1.14
50603b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][0][1]);	//g1.16
50703b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][1][0]);	//g1.18
50803b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][1][1]);	//g1.20
50903b705cfSriastradh
51003b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][0][0]);	//g1.22
51103b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][0][1]);	//g1.24
51203b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][1][0]);	//g1.26
51303b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][1][1]);	//g1.28
51403b705cfSriastradh	OUT_BATCH_CHAR(mb->dct_type);	//g1.30
51503b705cfSriastradh	OUT_BATCH_CHAR(mb->motion_vertical_field_select);	//g1.31
51603b705cfSriastradh
51703b705cfSriastradh	if (media_state.is_965_q)
51803b705cfSriastradh		OUT_BATCH(0x0);
51903b705cfSriastradh	else
52003b705cfSriastradh		OUT_BATCH(0xffffffff);
52103b705cfSriastradh	ADVANCE_BATCH();
52203b705cfSriastradh}
52303b705cfSriastradh
52403b705cfSriastradhstatic Status binding_tables(struct media_state *media_state)
52503b705cfSriastradh{
52603b705cfSriastradh	unsigned int binding_table[MAX_SURFACE_NUM];
52703b705cfSriastradh	int i;
52803b705cfSriastradh
52903b705cfSriastradh	if (media_state->binding_table.bo)
53003b705cfSriastradh		drm_intel_bo_unreference(media_state->binding_table.bo);
53103b705cfSriastradh	media_state->binding_table.bo =
53203b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table",
53303b705cfSriastradh			       MAX_SURFACE_NUM * 4, 0x1000);
53403b705cfSriastradh	if (!media_state->binding_table.bo)
53503b705cfSriastradh		return BadAlloc;
53603b705cfSriastradh
53703b705cfSriastradh	for (i = 0; i < MAX_SURFACE_NUM; i++)
53803b705cfSriastradh		binding_table[i] =
53903b705cfSriastradh		    media_state->binding_table.surface_states[i].bo->offset;
54003b705cfSriastradh	drm_intel_bo_subdata(media_state->binding_table.bo, 0,
54103b705cfSriastradh			     sizeof(binding_table), binding_table);
54203b705cfSriastradh
54303b705cfSriastradh	for (i = 0; i < MAX_SURFACE_NUM; i++)
54403b705cfSriastradh		drm_intel_bo_emit_reloc(media_state->binding_table.bo,
54503b705cfSriastradh					i * sizeof(unsigned int),
54603b705cfSriastradh					media_state->
54703b705cfSriastradh					binding_table.surface_states[i].bo, 0,
54803b705cfSriastradh					I915_GEM_DOMAIN_INSTRUCTION, 0);
54903b705cfSriastradh	return Success;
55003b705cfSriastradh}
55103b705cfSriastradh
55203b705cfSriastradhstatic int media_kernels(struct media_state *media_state)
55303b705cfSriastradh{
55403b705cfSriastradh	struct kernel_struct *kernels;
55503b705cfSriastradh	int kernel_array_size, i;
55603b705cfSriastradh
55703b705cfSriastradh	if (media_state->is_g4x) {
55803b705cfSriastradh		kernels = kernels_igd;
55903b705cfSriastradh		kernel_array_size = ARRAY_SIZE(kernels_igd);
56003b705cfSriastradh	} else {
56103b705cfSriastradh		kernels = kernels_965;
56203b705cfSriastradh		kernel_array_size = ARRAY_SIZE(kernels_965);
56303b705cfSriastradh	}
56403b705cfSriastradh
56503b705cfSriastradh	for (i = 0; i < kernel_array_size; i++) {
56603b705cfSriastradh		media_state->vfe_state.interface.kernels[i].bo =
56703b705cfSriastradh		    drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel",
56803b705cfSriastradh				       kernels[i].size, 0x1000);
56903b705cfSriastradh		if (!media_state->vfe_state.interface.kernels[i].bo)
57003b705cfSriastradh			goto out;
57103b705cfSriastradh	}
57203b705cfSriastradh
57303b705cfSriastradh	for (i = 0; i < kernel_array_size; i++) {
57403b705cfSriastradh		dri_bo *bo = media_state->vfe_state.interface.kernels[i].bo;
57503b705cfSriastradh		drm_intel_bo_subdata(bo, 0, kernels[i].size, kernels[i].bin);
57603b705cfSriastradh	}
57703b705cfSriastradh	return 0;
57803b705cfSriastradhout:
57903b705cfSriastradh	free_object(media_state);
58003b705cfSriastradh	return BadAlloc;
58103b705cfSriastradh}
58203b705cfSriastradh
58303b705cfSriastradhstatic void setup_interface(struct media_state *media_state, enum interface i)
58403b705cfSriastradh{
58503b705cfSriastradh	struct brw_interface_descriptor desc;
58603b705cfSriastradh	memset(&desc, 0, sizeof(desc));
58703b705cfSriastradh
58803b705cfSriastradh	desc.desc0.grf_reg_blocks = 15;
58903b705cfSriastradh	desc.desc0.kernel_start_pointer =
59003b705cfSriastradh	    media_state->vfe_state.interface.kernels[i].bo->offset >> 6;
59103b705cfSriastradh
59203b705cfSriastradh	desc.desc1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
59303b705cfSriastradh
59403b705cfSriastradh	/* use same binding table for all interface
59503b705cfSriastradh	 * may change this if it affect performance
59603b705cfSriastradh	 */
59703b705cfSriastradh	desc.desc3.binding_table_entry_count = MAX_SURFACE_NUM;
59803b705cfSriastradh	desc.desc3.binding_table_pointer =
59903b705cfSriastradh	    media_state->binding_table.bo->offset >> 5;
60003b705cfSriastradh
60103b705cfSriastradh	drm_intel_bo_subdata(media_state->vfe_state.interface.bo,
60203b705cfSriastradh			     i * sizeof(desc), sizeof(desc), &desc);
60303b705cfSriastradh
60403b705cfSriastradh	drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo,
60503b705cfSriastradh				i * sizeof(desc) +
60603b705cfSriastradh				offsetof(struct brw_interface_descriptor,
60703b705cfSriastradh					 desc0),
60803b705cfSriastradh				media_state->vfe_state.interface.kernels[i].bo,
60903b705cfSriastradh				desc.desc0.grf_reg_blocks,
61003b705cfSriastradh				I915_GEM_DOMAIN_INSTRUCTION, 0);
61103b705cfSriastradh
61203b705cfSriastradh	drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo,
61303b705cfSriastradh				i * sizeof(desc) +
61403b705cfSriastradh				offsetof(struct brw_interface_descriptor,
61503b705cfSriastradh					 desc3), media_state->binding_table.bo,
61603b705cfSriastradh				desc.desc3.binding_table_entry_count,
61703b705cfSriastradh				I915_GEM_DOMAIN_INSTRUCTION, 0);
61803b705cfSriastradh}
61903b705cfSriastradh
62003b705cfSriastradhstatic Status interface_descriptor(struct media_state *media_state)
62103b705cfSriastradh{
62203b705cfSriastradh	if (media_state->vfe_state.interface.bo)
62303b705cfSriastradh		drm_intel_bo_unreference(media_state->vfe_state.interface.bo);
62403b705cfSriastradh	media_state->vfe_state.interface.bo =
62503b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces",
62603b705cfSriastradh			       DESCRIPTOR_NUM *
62703b705cfSriastradh			       sizeof(struct brw_interface_descriptor), 0x1000);
62803b705cfSriastradh	if (!media_state->vfe_state.interface.bo)
62903b705cfSriastradh		return BadAlloc;
63003b705cfSriastradh
63103b705cfSriastradh	setup_interface(media_state, INTRA_INTERFACE);
63203b705cfSriastradh	setup_interface(media_state, NULL_INTERFACE);
63303b705cfSriastradh	setup_interface(media_state, FORWARD_INTERFACE);
63403b705cfSriastradh	setup_interface(media_state, FIELD_FORWARD_INTERFACE);
63503b705cfSriastradh	setup_interface(media_state, BACKWARD_INTERFACE);
63603b705cfSriastradh	setup_interface(media_state, FIELD_BACKWARD_INTERFACE);
63703b705cfSriastradh	setup_interface(media_state, F_B_INTERFACE);
63803b705cfSriastradh	setup_interface(media_state, FIELD_F_B_INTERFACE);
63903b705cfSriastradh	setup_interface(media_state, DUAL_PRIME_INTERFACE);
64003b705cfSriastradh	return Success;
64103b705cfSriastradh}
64203b705cfSriastradh
64303b705cfSriastradhstatic Status vfe_state(struct media_state *media_state)
64403b705cfSriastradh{
64503b705cfSriastradh	struct brw_vfe_state state;
64603b705cfSriastradh	memset(&state, 0, sizeof(state));
64703b705cfSriastradh
64803b705cfSriastradh	/* no scratch space */
64903b705cfSriastradh	state.vfe1.vfe_mode = VFE_GENERIC_MODE;
65003b705cfSriastradh	state.vfe1.num_urb_entries = 1;
65103b705cfSriastradh	/* XXX TODO */
65203b705cfSriastradh	/* should carefully caculate those values for performance */
65303b705cfSriastradh	state.vfe1.urb_entry_alloc_size = 2;
65403b705cfSriastradh	state.vfe1.max_threads = 31;
65503b705cfSriastradh	state.vfe2.interface_descriptor_base =
65603b705cfSriastradh	    media_state->vfe_state.interface.bo->offset >> 4;
65703b705cfSriastradh
65803b705cfSriastradh	if (media_state->vfe_state.bo)
65903b705cfSriastradh		drm_intel_bo_unreference(media_state->vfe_state.bo);
66003b705cfSriastradh	media_state->vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
66103b705cfSriastradh						       "vfe state",
66203b705cfSriastradh						       sizeof(struct
66303b705cfSriastradh							      brw_vfe_state),
66403b705cfSriastradh						       0x1000);
66503b705cfSriastradh	if (!media_state->vfe_state.bo)
66603b705cfSriastradh		return BadAlloc;
66703b705cfSriastradh
66803b705cfSriastradh	drm_intel_bo_subdata(media_state->vfe_state.bo, 0, sizeof(state),
66903b705cfSriastradh			     &state);
67003b705cfSriastradh
67103b705cfSriastradh	drm_intel_bo_emit_reloc(media_state->vfe_state.bo,
67203b705cfSriastradh				offsetof(struct brw_vfe_state, vfe2),
67303b705cfSriastradh				media_state->vfe_state.interface.bo, 0,
67403b705cfSriastradh				I915_GEM_DOMAIN_INSTRUCTION, 0);
67503b705cfSriastradh	return Success;
67603b705cfSriastradh}
67703b705cfSriastradh
67803b705cfSriastradhstatic Status render_surface(Display * display,
67903b705cfSriastradh			     XvMCContext * context,
68003b705cfSriastradh			     unsigned int picture_structure,
68103b705cfSriastradh			     XvMCSurface * target_surface,
68203b705cfSriastradh			     XvMCSurface * past_surface,
68303b705cfSriastradh			     XvMCSurface * future_surface,
68403b705cfSriastradh			     unsigned int flags,
68503b705cfSriastradh			     unsigned int num_macroblocks,
68603b705cfSriastradh			     unsigned int first_macroblock,
68703b705cfSriastradh			     XvMCMacroBlockArray * macroblock_array,
68803b705cfSriastradh			     XvMCBlockArray * blocks)
68903b705cfSriastradh{
69003b705cfSriastradh
69103b705cfSriastradh	intel_xvmc_context_ptr intel_ctx;
69203b705cfSriastradh	int i, j;
69303b705cfSriastradh	struct i965_xvmc_context *i965_ctx;
69403b705cfSriastradh	XvMCMacroBlock *mb;
69503b705cfSriastradh	struct intel_xvmc_surface *priv_target_surface =
69603b705cfSriastradh	    target_surface->privData;
69703b705cfSriastradh	struct intel_xvmc_surface *priv_past_surface =
69803b705cfSriastradh	    past_surface ? past_surface->privData : 0;
69903b705cfSriastradh	struct intel_xvmc_surface *priv_future_surface =
70003b705cfSriastradh	    future_surface ? future_surface->privData : 0;
70103b705cfSriastradh	unsigned short *block_ptr;
70203b705cfSriastradh	intel_ctx = context->privData;
70303b705cfSriastradh	i965_ctx = context->privData;
70403b705cfSriastradh	if (!intel_ctx) {
70503b705cfSriastradh		XVMC_ERR("Can't find intel xvmc context\n");
70603b705cfSriastradh		return BadValue;
70703b705cfSriastradh	}
70803b705cfSriastradh
70903b705cfSriastradh	if (media_state.indirect_data.bo) {
71003b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(media_state.
71103b705cfSriastradh					   indirect_data.bo);
71203b705cfSriastradh
71303b705cfSriastradh		drm_intel_bo_unreference(media_state.indirect_data.bo);
71403b705cfSriastradh	}
71503b705cfSriastradh	media_state.indirect_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
71603b705cfSriastradh							  "indirect data",
71703b705cfSriastradh							  128 * 6 *
71803b705cfSriastradh							  num_macroblocks, 64);
71903b705cfSriastradh	if (!media_state.indirect_data.bo)
72003b705cfSriastradh		return BadAlloc;
72103b705cfSriastradh	setup_surfaces(&media_state,
72203b705cfSriastradh		       priv_target_surface->bo,
72303b705cfSriastradh		       past_surface ? priv_past_surface->bo : NULL,
72403b705cfSriastradh		       future_surface ? priv_future_surface->bo : NULL,
72503b705cfSriastradh		       context->width, context->height);
72603b705cfSriastradh	setup_blocks(&media_state, 128 * 6 * num_macroblocks);
72703b705cfSriastradh	binding_tables(&media_state);
72803b705cfSriastradh	interface_descriptor(&media_state);
72903b705cfSriastradh	vfe_state(&media_state);
73003b705cfSriastradh
73103b705cfSriastradh	drm_intel_gem_bo_map_gtt(media_state.indirect_data.bo);
73203b705cfSriastradh
73303b705cfSriastradh	block_ptr = media_state.indirect_data.bo->virtual;
73403b705cfSriastradh	for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) {
73503b705cfSriastradh		unsigned short *mb_block_ptr;
73603b705cfSriastradh		mb = &macroblock_array->macro_blocks[i];
73703b705cfSriastradh		mb_block_ptr = &blocks->blocks[(mb->index << 6)];
73803b705cfSriastradh		if (mb->coded_block_pattern & 0x20) {
73903b705cfSriastradh			for (j = 0; j < 8; j++)
74003b705cfSriastradh				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
74103b705cfSriastradh				       16);
74203b705cfSriastradh			mb_block_ptr += 64;
74303b705cfSriastradh		}
74403b705cfSriastradh
74503b705cfSriastradh		if (mb->coded_block_pattern & 0x10) {
74603b705cfSriastradh			for (j = 0; j < 8; j++)
74703b705cfSriastradh				memcpy(block_ptr + 16 * j + 8,
74803b705cfSriastradh				       mb_block_ptr + 8 * j, 16);
74903b705cfSriastradh			mb_block_ptr += 64;
75003b705cfSriastradh		}
75103b705cfSriastradh		block_ptr += 2 * 64;
75203b705cfSriastradh		if (mb->coded_block_pattern & 0x08) {
75303b705cfSriastradh			for (j = 0; j < 8; j++)
75403b705cfSriastradh				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
75503b705cfSriastradh				       16);
75603b705cfSriastradh			mb_block_ptr += 64;
75703b705cfSriastradh		}
75803b705cfSriastradh
75903b705cfSriastradh		if (mb->coded_block_pattern & 0x04) {
76003b705cfSriastradh			for (j = 0; j < 8; j++)
76103b705cfSriastradh				memcpy(block_ptr + 16 * j + 8,
76203b705cfSriastradh				       mb_block_ptr + 8 * j, 16);
76303b705cfSriastradh			mb_block_ptr += 64;
76403b705cfSriastradh		}
76503b705cfSriastradh
76603b705cfSriastradh		block_ptr += 2 * 64;
76703b705cfSriastradh		if (mb->coded_block_pattern & 0x2) {
76803b705cfSriastradh			memcpy(block_ptr, mb_block_ptr, 128);
76903b705cfSriastradh			mb_block_ptr += 64;
77003b705cfSriastradh		}
77103b705cfSriastradh
77203b705cfSriastradh		block_ptr += 64;
77303b705cfSriastradh		if (mb->coded_block_pattern & 0x1)
77403b705cfSriastradh			memcpy(block_ptr, mb_block_ptr, 128);
77503b705cfSriastradh		block_ptr += 64;
77603b705cfSriastradh	}
77703b705cfSriastradh	{
77803b705cfSriastradh		int block_offset = 0;
77903b705cfSriastradh		LOCK_HARDWARE(intel_ctx->hw_context);
78003b705cfSriastradh		state_base_address();
78103b705cfSriastradh		flush();
78203b705cfSriastradh		clear_sf_state();
78303b705cfSriastradh		pipeline_select(&media_state);
78403b705cfSriastradh		urb_layout();
78503b705cfSriastradh		media_state_pointers(&media_state);
78603b705cfSriastradh		for (i = first_macroblock;
78703b705cfSriastradh		     i < num_macroblocks + first_macroblock;
78803b705cfSriastradh		     i++, block_offset += 128 * 6) {
78903b705cfSriastradh			mb = &macroblock_array->macro_blocks[i];
79003b705cfSriastradh
79103b705cfSriastradh			if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
79203b705cfSriastradh				send_media_object(mb, block_offset,
79303b705cfSriastradh						  INTRA_INTERFACE);
79403b705cfSriastradh			} else {
79503b705cfSriastradh				if (((mb->motion_type & 3) ==
79603b705cfSriastradh				     XVMC_PREDICTION_FRAME)) {
79703b705cfSriastradh					if ((mb->macroblock_type &
79803b705cfSriastradh					     XVMC_MB_TYPE_MOTION_FORWARD)) {
79903b705cfSriastradh						if (((mb->macroblock_type &
80003b705cfSriastradh						      XVMC_MB_TYPE_MOTION_BACKWARD)))
80103b705cfSriastradh							send_media_object(mb,
80203b705cfSriastradh									  block_offset,
80303b705cfSriastradh									  F_B_INTERFACE);
80403b705cfSriastradh						else
80503b705cfSriastradh							send_media_object(mb,
80603b705cfSriastradh									  block_offset,
80703b705cfSriastradh									  FORWARD_INTERFACE);
80803b705cfSriastradh					} else
80903b705cfSriastradh					    if ((mb->macroblock_type &
81003b705cfSriastradh						 XVMC_MB_TYPE_MOTION_BACKWARD))
81103b705cfSriastradh					{
81203b705cfSriastradh						send_media_object(mb,
81303b705cfSriastradh								  block_offset,
81403b705cfSriastradh								  BACKWARD_INTERFACE);
81503b705cfSriastradh					}
81603b705cfSriastradh				} else if ((mb->motion_type & 3) ==
81703b705cfSriastradh					   XVMC_PREDICTION_FIELD) {
81803b705cfSriastradh					if ((mb->macroblock_type &
81903b705cfSriastradh					     XVMC_MB_TYPE_MOTION_FORWARD)) {
82003b705cfSriastradh						if (((mb->macroblock_type &
82103b705cfSriastradh						      XVMC_MB_TYPE_MOTION_BACKWARD)))
82203b705cfSriastradh							send_media_object(mb,
82303b705cfSriastradh									  block_offset,
82403b705cfSriastradh									  FIELD_F_B_INTERFACE);
82503b705cfSriastradh						else
82603b705cfSriastradh
82703b705cfSriastradh							send_media_object(mb,
82803b705cfSriastradh									  block_offset,
82903b705cfSriastradh									  FIELD_FORWARD_INTERFACE);
83003b705cfSriastradh					} else
83103b705cfSriastradh					    if ((mb->macroblock_type &
83203b705cfSriastradh						 XVMC_MB_TYPE_MOTION_BACKWARD))
83303b705cfSriastradh					{
83403b705cfSriastradh						send_media_object(mb,
83503b705cfSriastradh								  block_offset,
83603b705cfSriastradh								  FIELD_BACKWARD_INTERFACE);
83703b705cfSriastradh					}
83803b705cfSriastradh				} else {
83903b705cfSriastradh					send_media_object(mb, block_offset,
84003b705cfSriastradh							  DUAL_PRIME_INTERFACE);
84103b705cfSriastradh				}
84203b705cfSriastradh			}
84303b705cfSriastradh		}
84442542f5fSchristos		intelFlushBatch();
84503b705cfSriastradh		UNLOCK_HARDWARE(intel_ctx->hw_context);
84603b705cfSriastradh	}
84703b705cfSriastradh	return Success;
84803b705cfSriastradh}
84903b705cfSriastradh
85003b705cfSriastradhstatic Status create_context(Display * display, XvMCContext * context,
85103b705cfSriastradh			     int priv_count, CARD32 * priv_data)
85203b705cfSriastradh{
85303b705cfSriastradh	struct intel_xvmc_context *intel_ctx;
85403b705cfSriastradh	struct intel_xvmc_hw_context *hw_ctx;
85503b705cfSriastradh	hw_ctx = (struct intel_xvmc_hw_context *)priv_data;
85603b705cfSriastradh
85703b705cfSriastradh	intel_ctx = calloc(1, sizeof(struct intel_xvmc_context));
85803b705cfSriastradh	if (!intel_ctx)
85903b705cfSriastradh		return BadAlloc;
86003b705cfSriastradh	intel_ctx->hw = hw_ctx;
86103b705cfSriastradh	intel_ctx->surface_bo_size
86203b705cfSriastradh		= SIZE_YUV420(context->width, context->height);
86303b705cfSriastradh	context->privData = intel_ctx;
86403b705cfSriastradh
86503b705cfSriastradh	media_state.is_g4x = hw_ctx->i965.is_g4x;
86603b705cfSriastradh	media_state.is_965_q = hw_ctx->i965.is_965_q;
86703b705cfSriastradh
86803b705cfSriastradh	if (alloc_object(&media_state))
86903b705cfSriastradh		return BadAlloc;
87003b705cfSriastradh	if (media_kernels(&media_state))
87103b705cfSriastradh		return BadAlloc;
87203b705cfSriastradh	return Success;
87303b705cfSriastradh}
87403b705cfSriastradh
87503b705cfSriastradhstruct _intel_xvmc_driver i965_xvmc_mc_driver = {
87603b705cfSriastradh	.type = XVMC_I965_MPEG2_MC,
87703b705cfSriastradh	.create_context = create_context,
87803b705cfSriastradh	.destroy_context = destroy_context,
87903b705cfSriastradh	.render_surface = render_surface,
88003b705cfSriastradh};
881