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 
37 enum 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 
49 static const uint32_t ipicture_kernel_static[][4] = {
50 #include "shader/mc/ipicture.g4b"
51 };
52 
53 static const uint32_t null_kernel_static[][4] = {
54 #include "shader/mc/null.g4b"
55 };
56 
57 static const uint32_t frame_forward_kernel_static[][4] = {
58 #include "shader/mc/frame_forward.g4b"
59 };
60 
61 static const uint32_t frame_backward_kernel_static[][4] = {
62 #include "shader/mc/frame_backward.g4b"
63 };
64 
65 static const uint32_t frame_f_b_kernel_static[][4] = {
66 #include "shader/mc/frame_f_b.g4b"
67 };
68 
69 static const uint32_t field_forward_kernel_static[][4] = {
70 #include "shader/mc/field_forward.g4b"
71 };
72 
73 static const uint32_t field_backward_kernel_static[][4] = {
74 #include "shader/mc/field_backward.g4b"
75 };
76 
77 static const uint32_t field_f_b_kernel_static[][4] = {
78 #include "shader/mc/field_f_b.g4b"
79 };
80 
81 static const uint32_t dual_prime_kernel_static[][4] = {
82 #include "shader/mc/dual_prime.g4b"
83 };
84 
85 static const uint32_t frame_forward_igd_kernel_static[][4] = {
86 #include "shader/mc/frame_forward_igd.g4b"
87 };
88 
89 static const uint32_t frame_backward_igd_kernel_static[][4] = {
90 #include "shader/mc/frame_backward_igd.g4b"
91 };
92 
93 static const uint32_t frame_f_b_igd_kernel_static[][4] = {
94 #include "shader/mc/frame_f_b_igd.g4b"
95 };
96 
97 static const uint32_t field_forward_igd_kernel_static[][4] = {
98 #include "shader/mc/field_forward_igd.g4b"
99 };
100 
101 static const uint32_t field_backward_igd_kernel_static[][4] = {
102 #include "shader/mc/field_backward_igd.g4b"
103 };
104 
105 static const uint32_t field_f_b_igd_kernel_static[][4] = {
106 #include "shader/mc/field_f_b_igd.g4b"
107 };
108 
109 static const uint32_t dual_prime_igd_kernel_static[][4] = {
110 #include "shader/mc/dual_prime_igd.g4b"
111 };
112 
113 struct kernel_struct {
114 	const uint32_t(*bin)[4];
115 	uint32_t size;
116 };
117 
118 struct 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 
142 struct 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 
167 struct media_kernel_obj {
168 	dri_bo *bo;
169 };
170 
171 struct interface_descriptor_obj {
172 	dri_bo *bo;
173 	struct media_kernel_obj kernels[DESCRIPTOR_NUM];
174 };
175 
176 struct vfe_state_obj {
177 	dri_bo *bo;
178 	struct interface_descriptor_obj interface;
179 };
180 
181 struct surface_obj {
182 	dri_bo *bo;
183 };
184 
185 struct surface_state_obj {
186 	struct surface_obj surface;
187 	dri_bo *bo;
188 };
189 
190 struct binding_table_obj {
191 	dri_bo *bo;
192 	struct surface_state_obj surface_states[MAX_SURFACE_NUM];
193 };
194 
195 struct indirect_data_obj {
196 	dri_bo *bo;
197 };
198 
199 struct 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 };
207 struct media_state media_state;
208 
free_object(struct media_state * s)209 static 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 
alloc_object(struct media_state * s)223 static 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;
236 out:
237 	free_object(s);
238 	return BadAlloc;
239 }
240 
destroy_context(Display * display,XvMCContext * context)241 static 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 
flush()253 static 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 
clear_sf_state()262 static 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 */
align_urb_fence()270 static 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 */
urb_layout()286 static 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 
media_state_pointers(struct media_state * media_state)304 static 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  */
setup_media_surface(struct media_state * media_state,int surface_num,dri_bo * bo,unsigned long offset,int w,int h,Bool write)316 static 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 
setup_surfaces(struct media_state * media_state,dri_bo * dst_bo,dri_bo * past_bo,dri_bo * future_bo,int w,int h)354 static 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 
setup_blocks(struct media_state * media_state,unsigned int block_size)413 static 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 */
state_base_address()458 static 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 */
pipeline_select(struct media_state * media_state)472 static 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 */
send_media_object(XvMCMacroBlock * mb,int offset,enum interface interface)484 static 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 
binding_tables(struct media_state * media_state)524 static 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 
media_kernels(struct media_state * media_state)552 static 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;
578 out:
579 	free_object(media_state);
580 	return BadAlloc;
581 }
582 
setup_interface(struct media_state * media_state,enum interface i)583 static 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 
interface_descriptor(struct media_state * media_state)620 static 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 
vfe_state(struct media_state * media_state)643 static 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 
render_surface(Display * display,XvMCContext * context,unsigned int picture_structure,XvMCSurface * target_surface,XvMCSurface * past_surface,XvMCSurface * future_surface,unsigned int flags,unsigned int num_macroblocks,unsigned int first_macroblock,XvMCMacroBlockArray * macroblock_array,XvMCBlockArray * blocks)678 static 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 
create_context(Display * display,XvMCContext * context,int priv_count,CARD32 * priv_data)850 static 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 
875 struct _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