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 = &macroblock_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 = &macroblock_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