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 = ¯oblock_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 = ¯oblock_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