1/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Author:
24 *    Zou Nan hai <nanhai.zou@intel.com>
25 *
26 */
27#include "intel_xvmc_private.h"
28#include "i830_reg.h"
29#include "i965_reg.h"
30#include "brw_defines.h"
31#include "brw_structs.h"
32#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0)
33#define URB_SIZE     256	/* XXX */
34
35#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
36
37enum interface {
38	INTRA_INTERFACE = 0,	/* non field intra */
39	NULL_INTERFACE,		/* fill with white, do nothing, for debug */
40	FORWARD_INTERFACE,	/* non field forward predict */
41	BACKWARD_INTERFACE,	/* non field backward predict */
42	F_B_INTERFACE,		/* non field forward and backward predict */
43	FIELD_FORWARD_INTERFACE,	/* field forward predict */
44	FIELD_BACKWARD_INTERFACE,	/* field backward predict */
45	FIELD_F_B_INTERFACE,	/* field forward and backward predict */
46	DUAL_PRIME_INTERFACE
47};
48
49static const uint32_t ipicture_kernel_static[][4] = {
50#include "shader/mc/ipicture.g4b"
51};
52
53static const uint32_t null_kernel_static[][4] = {
54#include "shader/mc/null.g4b"
55};
56
57static const uint32_t frame_forward_kernel_static[][4] = {
58#include "shader/mc/frame_forward.g4b"
59};
60
61static const uint32_t frame_backward_kernel_static[][4] = {
62#include "shader/mc/frame_backward.g4b"
63};
64
65static const uint32_t frame_f_b_kernel_static[][4] = {
66#include "shader/mc/frame_f_b.g4b"
67};
68
69static const uint32_t field_forward_kernel_static[][4] = {
70#include "shader/mc/field_forward.g4b"
71};
72
73static const uint32_t field_backward_kernel_static[][4] = {
74#include "shader/mc/field_backward.g4b"
75};
76
77static const uint32_t field_f_b_kernel_static[][4] = {
78#include "shader/mc/field_f_b.g4b"
79};
80
81static const uint32_t dual_prime_kernel_static[][4] = {
82#include "shader/mc/dual_prime.g4b"
83};
84
85static const uint32_t frame_forward_igd_kernel_static[][4] = {
86#include "shader/mc/frame_forward_igd.g4b"
87};
88
89static const uint32_t frame_backward_igd_kernel_static[][4] = {
90#include "shader/mc/frame_backward_igd.g4b"
91};
92
93static const uint32_t frame_f_b_igd_kernel_static[][4] = {
94#include "shader/mc/frame_f_b_igd.g4b"
95};
96
97static const uint32_t field_forward_igd_kernel_static[][4] = {
98#include "shader/mc/field_forward_igd.g4b"
99};
100
101static const uint32_t field_backward_igd_kernel_static[][4] = {
102#include "shader/mc/field_backward_igd.g4b"
103};
104
105static const uint32_t field_f_b_igd_kernel_static[][4] = {
106#include "shader/mc/field_f_b_igd.g4b"
107};
108
109static const uint32_t dual_prime_igd_kernel_static[][4] = {
110#include "shader/mc/dual_prime_igd.g4b"
111};
112
113struct kernel_struct {
114	const uint32_t(*bin)[4];
115	uint32_t size;
116};
117
118struct kernel_struct kernels_igd[] = {
119	{ipicture_kernel_static, sizeof(ipicture_kernel_static)}
120	,
121	{null_kernel_static, sizeof(null_kernel_static)}
122	,
123	{frame_forward_igd_kernel_static,
124	 sizeof(frame_forward_igd_kernel_static)}
125	,
126	{frame_backward_igd_kernel_static,
127	 sizeof(frame_backward_igd_kernel_static)}
128	,
129	{frame_f_b_igd_kernel_static, sizeof(frame_f_b_igd_kernel_static)}
130	,
131	{field_forward_igd_kernel_static,
132	 sizeof(field_forward_igd_kernel_static)}
133	,
134	{field_backward_igd_kernel_static,
135	 sizeof(field_backward_igd_kernel_static)}
136	,
137	{field_f_b_igd_kernel_static, sizeof(field_f_b_igd_kernel_static)}
138	,
139	{dual_prime_igd_kernel_static, sizeof(dual_prime_igd_kernel_static)}
140};
141
142struct kernel_struct kernels_965[] = {
143	{ipicture_kernel_static, sizeof(ipicture_kernel_static)}
144	,
145	{null_kernel_static, sizeof(null_kernel_static)}
146	,
147	{frame_forward_kernel_static, sizeof(frame_forward_kernel_static)}
148	,
149	{frame_backward_kernel_static, sizeof(frame_backward_kernel_static)}
150	,
151	{frame_f_b_kernel_static, sizeof(frame_f_b_kernel_static)}
152	,
153	{field_forward_kernel_static, sizeof(field_forward_kernel_static)}
154	,
155	{field_backward_kernel_static, sizeof(field_backward_kernel_static)}
156	,
157	{field_f_b_kernel_static, sizeof(field_f_b_kernel_static)}
158	,
159	{dual_prime_kernel_static, sizeof(dual_prime_kernel_static)}
160};
161
162#define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
163
164#define MAX_SURFACE_NUM	10
165#define DESCRIPTOR_NUM 12
166
167struct media_kernel_obj {
168	dri_bo *bo;
169};
170
171struct interface_descriptor_obj {
172	dri_bo *bo;
173	struct media_kernel_obj kernels[DESCRIPTOR_NUM];
174};
175
176struct vfe_state_obj {
177	dri_bo *bo;
178	struct interface_descriptor_obj interface;
179};
180
181struct surface_obj {
182	dri_bo *bo;
183};
184
185struct surface_state_obj {
186	struct surface_obj surface;
187	dri_bo *bo;
188};
189
190struct binding_table_obj {
191	dri_bo *bo;
192	struct surface_state_obj surface_states[MAX_SURFACE_NUM];
193};
194
195struct indirect_data_obj {
196	dri_bo *bo;
197};
198
199struct media_state {
200	unsigned int is_g4x:1;
201	unsigned int is_965_q:1;
202
203	struct vfe_state_obj vfe_state;
204	struct binding_table_obj binding_table;
205	struct indirect_data_obj indirect_data;
206};
207struct media_state media_state;
208
209static void free_object(struct media_state *s)
210{
211	int i;
212#define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo)
213	FREE_ONE_BO(s->vfe_state.bo);
214	FREE_ONE_BO(s->vfe_state.interface.bo);
215	for (i = 0; i < DESCRIPTOR_NUM; i++)
216		FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo);
217	FREE_ONE_BO(s->binding_table.bo);
218	for (i = 0; i < MAX_SURFACE_NUM; i++)
219		FREE_ONE_BO(s->binding_table.surface_states[i].bo);
220	FREE_ONE_BO(s->indirect_data.bo);
221}
222
223static int alloc_object(struct media_state *s)
224{
225	int i;
226
227	for (i = 0; i < MAX_SURFACE_NUM; i++) {
228		s->binding_table.surface_states[i].bo =
229		    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
230				       sizeof(struct brw_surface_state),
231				       0x1000);
232		if (!s->binding_table.surface_states[i].bo)
233			goto out;
234	}
235	return 0;
236out:
237	free_object(s);
238	return BadAlloc;
239}
240
241static Status destroy_context(Display * display, XvMCContext * context)
242{
243	struct intel_xvmc_context *intel_ctx;
244	intel_ctx = context->privData;
245	free(intel_ctx->hw);
246	free(intel_ctx);
247	return Success;
248}
249
250#define STRIDE(w)               (w)
251#define SIZE_YUV420(w, h)       (h * (STRIDE(w) + STRIDE(w >> 1)))
252
253static void flush()
254{
255	struct brw_mi_flush flush;
256	memset(&flush, 0, sizeof(flush));
257	flush.opcode = CMD_MI_FLUSH;
258	flush.flags = (1 << 1);
259	BATCH_STRUCT(flush);
260}
261
262static void clear_sf_state()
263{
264	struct brw_sf_unit_state sf;
265	memset(&sf, 0, sizeof(sf));
266	/* TODO */
267}
268
269/* urb fence must be aligned to cacheline */
270static void align_urb_fence()
271{
272	BATCH_LOCALS;
273	int i, offset_to_next_cacheline;
274	unsigned long batch_offset;
275	BEGIN_BATCH(3);
276	batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr;
277	offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset;
278	if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) {
279		for (i = 0; i < offset_to_next_cacheline / 4; i++)
280			OUT_BATCH(0);
281		ADVANCE_BATCH();
282	}
283}
284
285/* setup urb layout for media */
286static void urb_layout()
287{
288	BATCH_LOCALS;
289	align_urb_fence();
290	BEGIN_BATCH(3);
291	OUT_BATCH(BRW_URB_FENCE |
292		  UF0_VFE_REALLOC |
293		  UF0_CS_REALLOC |
294		  UF0_SF_REALLOC |
295		  UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1);
296	OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) |
297		  (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT));
298
299	OUT_BATCH(((URB_SIZE) << UF2_VFE_FENCE_SHIFT) |	/* VFE_SIZE */
300		  ((URB_SIZE) << UF2_CS_FENCE_SHIFT));	/* CS_SIZE is 0 */
301	ADVANCE_BATCH();
302}
303
304static void media_state_pointers(struct media_state *media_state)
305{
306	BATCH_LOCALS;
307	BEGIN_BATCH(3);
308	OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1);
309	OUT_BATCH(0);
310	OUT_RELOC(media_state->vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
311	ADVANCE_BATCH();
312}
313
314/* setup 2D surface for media_read or media_write
315 */
316static Status setup_media_surface(struct media_state *media_state,
317				  int surface_num, dri_bo * bo,
318				  unsigned long offset, int w, int h,
319				  Bool write)
320{
321	struct brw_surface_state s, *ss = &s;
322
323	memset(ss, 0, sizeof(struct brw_surface_state));
324	ss->ss0.surface_type = BRW_SURFACE_2D;
325	ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT;
326	ss->ss1.base_addr = offset + bo->offset;
327	ss->ss2.width = w - 1;
328	ss->ss2.height = h - 1;
329	ss->ss3.pitch = w - 1;
330
331	if (media_state->binding_table.surface_states[surface_num].bo)
332		drm_intel_bo_unreference(media_state->
333					 binding_table.surface_states
334					 [surface_num].bo);
335	media_state->binding_table.surface_states[surface_num].bo =
336	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
337			       sizeof(struct brw_surface_state), 0x1000);
338	if (!media_state->binding_table.surface_states[surface_num].bo)
339		return BadAlloc;
340
341	drm_intel_bo_subdata(media_state->
342			     binding_table.surface_states[surface_num].bo, 0,
343			     sizeof(*ss), ss);
344
345	drm_intel_bo_emit_reloc(media_state->
346				binding_table.surface_states[surface_num].bo,
347				offsetof(struct brw_surface_state, ss1), bo,
348				offset, I915_GEM_DOMAIN_RENDER,
349				write ? I915_GEM_DOMAIN_RENDER : 0);
350
351	return Success;
352}
353
354static Status setup_surfaces(struct media_state *media_state,
355			     dri_bo * dst_bo, dri_bo * past_bo,
356			     dri_bo * future_bo, int w, int h)
357{
358	Status ret;
359	ret = setup_media_surface(media_state, 0, dst_bo, 0, w, h, TRUE);
360	if (ret != Success)
361		return ret;
362	ret =
363	    setup_media_surface(media_state, 1, dst_bo, w * h, w / 2, h / 2,
364				TRUE);
365	if (ret != Success)
366		return ret;
367	ret =
368	    setup_media_surface(media_state, 2, dst_bo, w * h + w * h / 4,
369				w / 2, h / 2, TRUE);
370	if (ret != Success)
371		return ret;
372	if (past_bo) {
373		ret =
374		    setup_media_surface(media_state, 4, past_bo, 0, w, h,
375					FALSE);
376		if (ret != Success)
377			return ret;
378		ret =
379		    setup_media_surface(media_state, 5, past_bo, w * h, w / 2,
380					h / 2, FALSE);
381		if (ret != Success)
382			return ret;
383		ret =
384		    setup_media_surface(media_state, 6, past_bo,
385					w * h + w * h / 4, w / 2, h / 2, FALSE);
386		if (ret != Success)
387			return ret;
388	}
389	if (future_bo) {
390		ret =
391		    setup_media_surface(media_state, 7, future_bo, 0, w, h,
392					FALSE);
393		if (ret != Success)
394			return ret;
395		ret =
396		    setup_media_surface(media_state, 8, future_bo, w * h, w / 2,
397					h / 2, FALSE);
398		if (ret != Success)
399			return ret;
400		ret =
401		    setup_media_surface(media_state, 9, future_bo,
402					w * h + w * h / 4, w / 2, h / 2, FALSE);
403		if (ret != Success)
404			return ret;
405	}
406	return Success;
407}
408
409/* BUFFER SURFACE has a strange format
410 * the size of the surface is in part of w h and d component
411 */
412
413static Status setup_blocks(struct media_state *media_state,
414			   unsigned int block_size)
415{
416	union element {
417		struct {
418			unsigned int w:7;
419			unsigned int h:13;
420			unsigned int d:7;
421			unsigned int pad:7;
422		} whd;
423		unsigned int size;
424	} e;
425	struct brw_surface_state ss;
426	memset(&ss, 0, sizeof(struct brw_surface_state));
427	ss.ss0.surface_type = BRW_SURFACE_BUFFER;
428	ss.ss0.surface_format = BRW_SURFACEFORMAT_R8_UINT;
429	ss.ss1.base_addr = media_state->indirect_data.bo->offset;
430
431	e.size = block_size - 1;
432	ss.ss2.width = e.whd.w;
433	ss.ss2.height = e.whd.h;
434	ss.ss3.depth = e.whd.d;
435	ss.ss3.pitch = block_size - 1;
436
437	if (media_state->binding_table.surface_states[3].bo)
438		drm_intel_bo_unreference(media_state->
439					 binding_table.surface_states[3].bo);
440
441	media_state->binding_table.surface_states[3].bo =
442	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
443			       sizeof(struct brw_surface_state), 0x1000);
444	if (!media_state->binding_table.surface_states[3].bo)
445		return BadAlloc;
446
447	drm_intel_bo_subdata(media_state->binding_table.surface_states[3].bo, 0,
448			     sizeof(ss), &ss);
449
450	drm_intel_bo_emit_reloc(media_state->binding_table.surface_states[3].bo,
451				offsetof(struct brw_surface_state, ss1),
452				media_state->indirect_data.bo, 0,
453				I915_GEM_DOMAIN_SAMPLER, 0);
454	return Success;
455}
456
457/* setup state base address */
458static void state_base_address()
459{
460	BATCH_LOCALS;
461	BEGIN_BATCH(6);
462	OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
463	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
464	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
465	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
466	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
467	OUT_BATCH(0xFFFFF000 | BASE_ADDRESS_MODIFY);
468	ADVANCE_BATCH();
469}
470
471/* select media pipeline */
472static void pipeline_select(struct media_state *media_state)
473{
474	BATCH_LOCALS;
475	BEGIN_BATCH(1);
476	if (media_state->is_g4x)
477		OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
478	else
479		OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
480	ADVANCE_BATCH();
481}
482
483/* kick media object to gpu */
484static void send_media_object(XvMCMacroBlock * mb, int offset,
485			      enum interface interface)
486{
487	BATCH_LOCALS;
488	BEGIN_BATCH(13);
489	OUT_BATCH(BRW_MEDIA_OBJECT | 11);
490	OUT_BATCH(interface);
491	if (media_state.is_965_q) {
492		OUT_BATCH(0);
493		OUT_BATCH(0);
494	} else {
495		OUT_BATCH(6 * 128);
496		OUT_RELOC(media_state.indirect_data.bo,
497			  I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
498	}
499
500	OUT_BATCH(mb->x << 4);	//g1.0
501	OUT_BATCH(mb->y << 4);
502	OUT_RELOC(media_state.indirect_data.bo,	//g1.8
503		  I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
504	OUT_BATCH_SHORT(mb->coded_block_pattern);	//g1.12
505	OUT_BATCH_SHORT(mb->PMV[0][0][0]);	//g1.14
506	OUT_BATCH_SHORT(mb->PMV[0][0][1]);	//g1.16
507	OUT_BATCH_SHORT(mb->PMV[0][1][0]);	//g1.18
508	OUT_BATCH_SHORT(mb->PMV[0][1][1]);	//g1.20
509
510	OUT_BATCH_SHORT(mb->PMV[1][0][0]);	//g1.22
511	OUT_BATCH_SHORT(mb->PMV[1][0][1]);	//g1.24
512	OUT_BATCH_SHORT(mb->PMV[1][1][0]);	//g1.26
513	OUT_BATCH_SHORT(mb->PMV[1][1][1]);	//g1.28
514	OUT_BATCH_CHAR(mb->dct_type);	//g1.30
515	OUT_BATCH_CHAR(mb->motion_vertical_field_select);	//g1.31
516
517	if (media_state.is_965_q)
518		OUT_BATCH(0x0);
519	else
520		OUT_BATCH(0xffffffff);
521	ADVANCE_BATCH();
522}
523
524static Status binding_tables(struct media_state *media_state)
525{
526	unsigned int binding_table[MAX_SURFACE_NUM];
527	int i;
528
529	if (media_state->binding_table.bo)
530		drm_intel_bo_unreference(media_state->binding_table.bo);
531	media_state->binding_table.bo =
532	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table",
533			       MAX_SURFACE_NUM * 4, 0x1000);
534	if (!media_state->binding_table.bo)
535		return BadAlloc;
536
537	for (i = 0; i < MAX_SURFACE_NUM; i++)
538		binding_table[i] =
539		    media_state->binding_table.surface_states[i].bo->offset;
540	drm_intel_bo_subdata(media_state->binding_table.bo, 0,
541			     sizeof(binding_table), binding_table);
542
543	for (i = 0; i < MAX_SURFACE_NUM; i++)
544		drm_intel_bo_emit_reloc(media_state->binding_table.bo,
545					i * sizeof(unsigned int),
546					media_state->
547					binding_table.surface_states[i].bo, 0,
548					I915_GEM_DOMAIN_INSTRUCTION, 0);
549	return Success;
550}
551
552static int media_kernels(struct media_state *media_state)
553{
554	struct kernel_struct *kernels;
555	int kernel_array_size, i;
556
557	if (media_state->is_g4x) {
558		kernels = kernels_igd;
559		kernel_array_size = ARRAY_SIZE(kernels_igd);
560	} else {
561		kernels = kernels_965;
562		kernel_array_size = ARRAY_SIZE(kernels_965);
563	}
564
565	for (i = 0; i < kernel_array_size; i++) {
566		media_state->vfe_state.interface.kernels[i].bo =
567		    drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel",
568				       kernels[i].size, 0x1000);
569		if (!media_state->vfe_state.interface.kernels[i].bo)
570			goto out;
571	}
572
573	for (i = 0; i < kernel_array_size; i++) {
574		dri_bo *bo = media_state->vfe_state.interface.kernels[i].bo;
575		drm_intel_bo_subdata(bo, 0, kernels[i].size, kernels[i].bin);
576	}
577	return 0;
578out:
579	free_object(media_state);
580	return BadAlloc;
581}
582
583static void setup_interface(struct media_state *media_state, enum interface i)
584{
585	struct brw_interface_descriptor desc;
586	memset(&desc, 0, sizeof(desc));
587
588	desc.desc0.grf_reg_blocks = 15;
589	desc.desc0.kernel_start_pointer =
590	    media_state->vfe_state.interface.kernels[i].bo->offset >> 6;
591
592	desc.desc1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
593
594	/* use same binding table for all interface
595	 * may change this if it affect performance
596	 */
597	desc.desc3.binding_table_entry_count = MAX_SURFACE_NUM;
598	desc.desc3.binding_table_pointer =
599	    media_state->binding_table.bo->offset >> 5;
600
601	drm_intel_bo_subdata(media_state->vfe_state.interface.bo,
602			     i * sizeof(desc), sizeof(desc), &desc);
603
604	drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo,
605				i * sizeof(desc) +
606				offsetof(struct brw_interface_descriptor,
607					 desc0),
608				media_state->vfe_state.interface.kernels[i].bo,
609				desc.desc0.grf_reg_blocks,
610				I915_GEM_DOMAIN_INSTRUCTION, 0);
611
612	drm_intel_bo_emit_reloc(media_state->vfe_state.interface.bo,
613				i * sizeof(desc) +
614				offsetof(struct brw_interface_descriptor,
615					 desc3), media_state->binding_table.bo,
616				desc.desc3.binding_table_entry_count,
617				I915_GEM_DOMAIN_INSTRUCTION, 0);
618}
619
620static Status interface_descriptor(struct media_state *media_state)
621{
622	if (media_state->vfe_state.interface.bo)
623		drm_intel_bo_unreference(media_state->vfe_state.interface.bo);
624	media_state->vfe_state.interface.bo =
625	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces",
626			       DESCRIPTOR_NUM *
627			       sizeof(struct brw_interface_descriptor), 0x1000);
628	if (!media_state->vfe_state.interface.bo)
629		return BadAlloc;
630
631	setup_interface(media_state, INTRA_INTERFACE);
632	setup_interface(media_state, NULL_INTERFACE);
633	setup_interface(media_state, FORWARD_INTERFACE);
634	setup_interface(media_state, FIELD_FORWARD_INTERFACE);
635	setup_interface(media_state, BACKWARD_INTERFACE);
636	setup_interface(media_state, FIELD_BACKWARD_INTERFACE);
637	setup_interface(media_state, F_B_INTERFACE);
638	setup_interface(media_state, FIELD_F_B_INTERFACE);
639	setup_interface(media_state, DUAL_PRIME_INTERFACE);
640	return Success;
641}
642
643static Status vfe_state(struct media_state *media_state)
644{
645	struct brw_vfe_state state;
646	memset(&state, 0, sizeof(state));
647
648	/* no scratch space */
649	state.vfe1.vfe_mode = VFE_GENERIC_MODE;
650	state.vfe1.num_urb_entries = 1;
651	/* XXX TODO */
652	/* should carefully caculate those values for performance */
653	state.vfe1.urb_entry_alloc_size = 2;
654	state.vfe1.max_threads = 31;
655	state.vfe2.interface_descriptor_base =
656	    media_state->vfe_state.interface.bo->offset >> 4;
657
658	if (media_state->vfe_state.bo)
659		drm_intel_bo_unreference(media_state->vfe_state.bo);
660	media_state->vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
661						       "vfe state",
662						       sizeof(struct
663							      brw_vfe_state),
664						       0x1000);
665	if (!media_state->vfe_state.bo)
666		return BadAlloc;
667
668	drm_intel_bo_subdata(media_state->vfe_state.bo, 0, sizeof(state),
669			     &state);
670
671	drm_intel_bo_emit_reloc(media_state->vfe_state.bo,
672				offsetof(struct brw_vfe_state, vfe2),
673				media_state->vfe_state.interface.bo, 0,
674				I915_GEM_DOMAIN_INSTRUCTION, 0);
675	return Success;
676}
677
678static Status render_surface(Display * display,
679			     XvMCContext * context,
680			     unsigned int picture_structure,
681			     XvMCSurface * target_surface,
682			     XvMCSurface * past_surface,
683			     XvMCSurface * future_surface,
684			     unsigned int flags,
685			     unsigned int num_macroblocks,
686			     unsigned int first_macroblock,
687			     XvMCMacroBlockArray * macroblock_array,
688			     XvMCBlockArray * blocks)
689{
690
691	intel_xvmc_context_ptr intel_ctx;
692	int i, j;
693	struct i965_xvmc_context *i965_ctx;
694	XvMCMacroBlock *mb;
695	struct intel_xvmc_surface *priv_target_surface =
696	    target_surface->privData;
697	struct intel_xvmc_surface *priv_past_surface =
698	    past_surface ? past_surface->privData : 0;
699	struct intel_xvmc_surface *priv_future_surface =
700	    future_surface ? future_surface->privData : 0;
701	unsigned short *block_ptr;
702	intel_ctx = context->privData;
703	i965_ctx = context->privData;
704	if (!intel_ctx) {
705		XVMC_ERR("Can't find intel xvmc context\n");
706		return BadValue;
707	}
708
709	if (media_state.indirect_data.bo) {
710		drm_intel_gem_bo_unmap_gtt(media_state.
711					   indirect_data.bo);
712
713		drm_intel_bo_unreference(media_state.indirect_data.bo);
714	}
715	media_state.indirect_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
716							  "indirect data",
717							  128 * 6 *
718							  num_macroblocks, 64);
719	if (!media_state.indirect_data.bo)
720		return BadAlloc;
721	setup_surfaces(&media_state,
722		       priv_target_surface->bo,
723		       past_surface ? priv_past_surface->bo : NULL,
724		       future_surface ? priv_future_surface->bo : NULL,
725		       context->width, context->height);
726	setup_blocks(&media_state, 128 * 6 * num_macroblocks);
727	binding_tables(&media_state);
728	interface_descriptor(&media_state);
729	vfe_state(&media_state);
730
731	drm_intel_gem_bo_map_gtt(media_state.indirect_data.bo);
732
733	block_ptr = media_state.indirect_data.bo->virtual;
734	for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) {
735		unsigned short *mb_block_ptr;
736		mb = &macroblock_array->macro_blocks[i];
737		mb_block_ptr = &blocks->blocks[(mb->index << 6)];
738		if (mb->coded_block_pattern & 0x20) {
739			for (j = 0; j < 8; j++)
740				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
741				       16);
742			mb_block_ptr += 64;
743		}
744
745		if (mb->coded_block_pattern & 0x10) {
746			for (j = 0; j < 8; j++)
747				memcpy(block_ptr + 16 * j + 8,
748				       mb_block_ptr + 8 * j, 16);
749			mb_block_ptr += 64;
750		}
751		block_ptr += 2 * 64;
752		if (mb->coded_block_pattern & 0x08) {
753			for (j = 0; j < 8; j++)
754				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
755				       16);
756			mb_block_ptr += 64;
757		}
758
759		if (mb->coded_block_pattern & 0x04) {
760			for (j = 0; j < 8; j++)
761				memcpy(block_ptr + 16 * j + 8,
762				       mb_block_ptr + 8 * j, 16);
763			mb_block_ptr += 64;
764		}
765
766		block_ptr += 2 * 64;
767		if (mb->coded_block_pattern & 0x2) {
768			memcpy(block_ptr, mb_block_ptr, 128);
769			mb_block_ptr += 64;
770		}
771
772		block_ptr += 64;
773		if (mb->coded_block_pattern & 0x1)
774			memcpy(block_ptr, mb_block_ptr, 128);
775		block_ptr += 64;
776	}
777	{
778		int block_offset = 0;
779		LOCK_HARDWARE(intel_ctx->hw_context);
780		state_base_address();
781		flush();
782		clear_sf_state();
783		pipeline_select(&media_state);
784		urb_layout();
785		media_state_pointers(&media_state);
786		for (i = first_macroblock;
787		     i < num_macroblocks + first_macroblock;
788		     i++, block_offset += 128 * 6) {
789			mb = &macroblock_array->macro_blocks[i];
790
791			if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
792				send_media_object(mb, block_offset,
793						  INTRA_INTERFACE);
794			} else {
795				if (((mb->motion_type & 3) ==
796				     XVMC_PREDICTION_FRAME)) {
797					if ((mb->macroblock_type &
798					     XVMC_MB_TYPE_MOTION_FORWARD)) {
799						if (((mb->macroblock_type &
800						      XVMC_MB_TYPE_MOTION_BACKWARD)))
801							send_media_object(mb,
802									  block_offset,
803									  F_B_INTERFACE);
804						else
805							send_media_object(mb,
806									  block_offset,
807									  FORWARD_INTERFACE);
808					} else
809					    if ((mb->macroblock_type &
810						 XVMC_MB_TYPE_MOTION_BACKWARD))
811					{
812						send_media_object(mb,
813								  block_offset,
814								  BACKWARD_INTERFACE);
815					}
816				} else if ((mb->motion_type & 3) ==
817					   XVMC_PREDICTION_FIELD) {
818					if ((mb->macroblock_type &
819					     XVMC_MB_TYPE_MOTION_FORWARD)) {
820						if (((mb->macroblock_type &
821						      XVMC_MB_TYPE_MOTION_BACKWARD)))
822							send_media_object(mb,
823									  block_offset,
824									  FIELD_F_B_INTERFACE);
825						else
826
827							send_media_object(mb,
828									  block_offset,
829									  FIELD_FORWARD_INTERFACE);
830					} else
831					    if ((mb->macroblock_type &
832						 XVMC_MB_TYPE_MOTION_BACKWARD))
833					{
834						send_media_object(mb,
835								  block_offset,
836								  FIELD_BACKWARD_INTERFACE);
837					}
838				} else {
839					send_media_object(mb, block_offset,
840							  DUAL_PRIME_INTERFACE);
841				}
842			}
843		}
844		intelFlushBatch();
845		UNLOCK_HARDWARE(intel_ctx->hw_context);
846	}
847	return Success;
848}
849
850static Status create_context(Display * display, XvMCContext * context,
851			     int priv_count, CARD32 * priv_data)
852{
853	struct intel_xvmc_context *intel_ctx;
854	struct intel_xvmc_hw_context *hw_ctx;
855	hw_ctx = (struct intel_xvmc_hw_context *)priv_data;
856
857	intel_ctx = calloc(1, sizeof(struct intel_xvmc_context));
858	if (!intel_ctx)
859		return BadAlloc;
860	intel_ctx->hw = hw_ctx;
861	intel_ctx->surface_bo_size
862		= SIZE_YUV420(context->width, context->height);
863	context->privData = intel_ctx;
864
865	media_state.is_g4x = hw_ctx->i965.is_g4x;
866	media_state.is_965_q = hw_ctx->i965.is_965_q;
867
868	if (alloc_object(&media_state))
869		return BadAlloc;
870	if (media_kernels(&media_state))
871		return BadAlloc;
872	return Success;
873}
874
875struct _intel_xvmc_driver i965_xvmc_mc_driver = {
876	.type = XVMC_I965_MPEG2_MC,
877	.create_context = create_context,
878	.destroy_context = destroy_context,
879	.render_surface = render_surface,
880};
881