1/*
2 * Copyright © 2009 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#include "intel_xvmc_private.h"
27#include "i830_reg.h"
28#include "i965_reg.h"
29#include "brw_defines.h"
30#include "brw_structs.h"
31
32#ifndef ALIGN
33#define ALIGN(m,n) (((m) + (n) - 1) & ~((n) - 1))
34#endif
35
36#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0)
37#define VLD_MAX_SLICE_SIZE (32 * 1024)
38#define CS_SIZE 	30
39#define URB_SIZE 	384
40/* idct table */
41#define C0 23170
42#define C1 22725
43#define C2 21407
44#define C3 19266
45#define C4 16383
46#define C5 12873
47#define C6 8867
48#define C7 4520
49const uint32_t idct_table[] = {
50	C4, C1, C2, C3, C4, C5, C6, C7,	//g5
51	C4, C1, C2, C3, C4, C5, C6, C7,
52	C4, C3, C6, -C7, -C4, -C1, -C2, -C5,
53	C4, C3, C6, -C7, -C4, -C1, -C2, -C5,
54	C4, C5, -C6, -C1, -C4, C7, C2, C3,
55	C4, C5, -C6, -C1, -C4, C7, C2, C3,
56	C4, C7, -C2, -C5, C4, C3, -C6, -C1,
57	C4, C7, -C2, -C5, C4, C3, -C6, -C1,
58	C4, -C7, -C2, C5, C4, -C3, -C6, C1,
59	C4, -C7, -C2, C5, C4, -C3, -C6, C1,
60	C4, -C5, -C6, C1, -C4, -C7, C2, -C3,
61	C4, -C5, -C6, C1, -C4, -C7, C2, -C3,
62	C4, -C3, C6, C7, -C4, C1, -C2, C5,
63	C4, -C3, C6, C7, -C4, C1, -C2, C5,
64	C4, -C1, C2, -C3, C4, -C5, C6, -C7,
65	C4, -C1, C2, -C3, C4, -C5, C6, -C7	//g20
66};
67
68#undef C0
69#undef C1
70#undef C2
71#undef C3
72#undef C4
73#undef C5
74#undef C6
75#undef C7
76
77#define INTERFACE_NUM	8
78enum interface {
79	FRAME_INTRA = 0,
80	FRAME_FRAME_PRED_FORWARD,
81	FRAME_FRAME_PRED_BACKWARD,
82	FRAME_FRAME_PRED_BIDIRECT,
83	FRAME_FIELD_PRED_FORWARD,
84	FRAME_FIELD_PRED_BACKWARD,
85	FRAME_FIELD_PRED_BIDIRECT,
86	LIB_INTERFACE
87};
88
89/*kernels for vld mode*/
90static uint32_t lib_kernel[][4] = {
91#include "shader/vld/lib.g4b"
92};
93
94static uint32_t ipicture_kernel[][4] = {
95#include "shader/vld/ipicture.g4b"
96};
97
98static uint32_t frame_forward_kernel[][4] = {
99#include "shader/vld/frame_forward.g4b"
100};
101
102static uint32_t frame_backward_kernel[][4] = {
103#include "shader/vld/frame_backward.g4b"
104};
105
106static uint32_t frame_f_b_kernel[][4] = {
107#include "shader/vld/frame_f_b.g4b"
108};
109
110static uint32_t field_forward_kernel[][4] = {
111#include "shader/vld/field_forward.g4b"
112};
113
114static uint32_t field_backward_kernel[][4] = {
115#include "shader/vld/field_backward.g4b"
116};
117
118static uint32_t field_f_b_kernel[][4] = {
119#include "shader/vld/field_f_b.g4b"
120};
121
122/* on Ironlake */
123static uint32_t lib_kernel_gen5[][4] = {
124#include "shader/vld/lib.g4b.gen5"
125};
126
127static uint32_t ipicture_kernel_gen5[][4] = {
128#include "shader/vld/ipicture.g4b.gen5"
129};
130
131static uint32_t frame_forward_kernel_gen5[][4] = {
132#include "shader/vld/frame_forward.g4b.gen5"
133};
134
135static uint32_t frame_backward_kernel_gen5[][4] = {
136#include "shader/vld/frame_backward.g4b.gen5"
137};
138
139static uint32_t frame_f_b_kernel_gen5[][4] = {
140#include "shader/vld/frame_f_b.g4b.gen5"
141};
142
143static uint32_t field_forward_kernel_gen5[][4] = {
144#include "shader/vld/field_forward.g4b.gen5"
145};
146
147static uint32_t field_backward_kernel_gen5[][4] = {
148#include "shader/vld/field_backward.g4b.gen5"
149};
150
151static uint32_t field_f_b_kernel_gen5[][4] = {
152#include "shader/vld/field_f_b.g4b.gen5"
153};
154
155/*kernels for mc mode*/
156static uint32_t lib_kernel_idct[][4] = {
157#include "shader/mc/lib_igd.g4b"
158};
159
160static uint32_t ipicture_kernel_idct[][4] = {
161#include "shader/mc/ipicture_igd.g4b"
162};
163
164static uint32_t frame_forward_kernel_idct[][4] = {
165#include "shader/mc/frame_forward_igd.g4b"
166};
167
168static uint32_t frame_backward_kernel_idct[][4] = {
169#include "shader/mc/frame_backward_igd.g4b"
170};
171
172static uint32_t frame_f_b_kernel_idct[][4] = {
173#include "shader/mc/frame_f_b_igd.g4b"
174};
175
176static uint32_t field_forward_kernel_idct[][4] = {
177#include "shader/mc/field_forward_igd.g4b"
178};
179
180static uint32_t field_backward_kernel_idct[][4] = {
181#include "shader/mc/field_backward_igd.g4b"
182};
183
184static uint32_t field_f_b_kernel_idct[][4] = {
185#include "shader/mc/field_f_b_igd.g4b"
186};
187
188/* on Ironlake */
189static uint32_t lib_kernel_idct_gen5[][4] = {
190#include "shader/mc/lib_igd.g4b.gen5"
191};
192
193static uint32_t ipicture_kernel_idct_gen5[][4] = {
194#include "shader/mc/ipicture_igd.g4b.gen5"
195};
196
197static uint32_t frame_forward_kernel_idct_gen5[][4] = {
198#include "shader/mc/frame_forward_igd.g4b.gen5"
199};
200
201static uint32_t frame_backward_kernel_idct_gen5[][4] = {
202#include "shader/mc/frame_backward_igd.g4b.gen5"
203};
204
205static uint32_t frame_f_b_kernel_idct_gen5[][4] = {
206#include "shader/mc/frame_f_b_igd.g4b.gen5"
207};
208
209static uint32_t field_forward_kernel_idct_gen5[][4] = {
210#include "shader/mc/field_forward_igd.g4b.gen5"
211};
212
213static uint32_t field_backward_kernel_idct_gen5[][4] = {
214#include "shader/mc/field_backward_igd.g4b.gen5"
215};
216
217static uint32_t field_f_b_kernel_idct_gen5[][4] = {
218#include "shader/mc/field_f_b_igd.g4b.gen5"
219};
220
221struct media_kernel {
222	uint32_t(*bin)[4];
223	int size;
224};
225static struct media_kernel media_kernels[] = {
226	/*kernels for vld mode */
227	{ipicture_kernel, sizeof(ipicture_kernel)}
228	,
229	{frame_forward_kernel, sizeof(frame_forward_kernel)}
230	,
231	{frame_backward_kernel, sizeof(frame_backward_kernel)}
232	,
233	{frame_f_b_kernel, sizeof(frame_f_b_kernel)}
234	,
235	{field_forward_kernel, sizeof(field_forward_kernel)}
236	,
237	{field_backward_kernel, sizeof(field_backward_kernel)}
238	,
239	{field_f_b_kernel, sizeof(field_f_b_kernel)}
240	,
241	{lib_kernel, sizeof(lib_kernel)}
242	,
243	/*kernels for mc mode */
244	{ipicture_kernel_idct, sizeof(ipicture_kernel_idct)}
245	,
246	{frame_forward_kernel_idct, sizeof(frame_forward_kernel_idct)}
247	,
248	{frame_backward_kernel_idct, sizeof(frame_backward_kernel_idct)}
249	,
250	{frame_f_b_kernel_idct, sizeof(frame_f_b_kernel_idct)}
251	,
252	{field_forward_kernel_idct, sizeof(field_forward_kernel_idct)}
253	,
254	{field_backward_kernel_idct, sizeof(field_backward_kernel_idct)}
255	,
256	{field_f_b_kernel_idct, sizeof(field_f_b_kernel_idct)}
257	,
258	{lib_kernel_idct, sizeof(lib_kernel_idct)}
259};
260
261static struct media_kernel media_gen5_kernels[] = {
262	/*kernels for vld mode */
263	{ipicture_kernel_gen5, sizeof(ipicture_kernel_gen5)}
264	,
265	{frame_forward_kernel_gen5, sizeof(frame_forward_kernel_gen5)}
266	,
267	{frame_backward_kernel_gen5, sizeof(frame_backward_kernel_gen5)}
268	,
269	{frame_f_b_kernel_gen5, sizeof(frame_f_b_kernel_gen5)}
270	,
271	{field_forward_kernel_gen5, sizeof(field_forward_kernel_gen5)}
272	,
273	{field_backward_kernel_gen5, sizeof(field_backward_kernel_gen5)}
274	,
275	{field_f_b_kernel_gen5, sizeof(field_f_b_kernel_gen5)}
276	,
277	{lib_kernel_gen5, sizeof(lib_kernel_gen5)}
278	,
279	/*kernels for mc mode */
280	{ipicture_kernel_idct_gen5, sizeof(ipicture_kernel_idct_gen5)}
281	,
282	{frame_forward_kernel_idct_gen5, sizeof(frame_forward_kernel_idct_gen5)}
283	,
284	{frame_backward_kernel_idct_gen5,
285	 sizeof(frame_backward_kernel_idct_gen5)}
286	,
287	{frame_f_b_kernel_idct_gen5, sizeof(frame_f_b_kernel_idct_gen5)}
288	,
289	{field_forward_kernel_idct_gen5, sizeof(field_forward_kernel_idct_gen5)}
290	,
291	{field_backward_kernel_idct_gen5,
292	 sizeof(field_backward_kernel_idct_gen5)}
293	,
294	{field_f_b_kernel_idct_gen5, sizeof(field_f_b_kernel_idct_gen5)}
295	,
296	{lib_kernel_idct_gen5, sizeof(lib_kernel_idct_gen5)}
297};
298
299#define MEDIA_KERNEL_NUM (sizeof(media_kernels)/sizeof(media_kernels[0]))
300
301struct media_kernel_obj {
302	dri_bo *bo;
303};
304
305struct interface_descriptor_obj {
306	dri_bo *bo;
307	struct media_kernel_obj kernels[MEDIA_KERNEL_NUM];
308};
309
310struct vfe_state_obj {
311	dri_bo *bo;
312	struct interface_descriptor_obj interface;
313};
314
315struct vld_state_obj {
316	dri_bo *bo;
317};
318
319struct surface_obj {
320	dri_bo *bo;
321};
322
323struct surface_state_obj {
324	struct surface_obj surface;
325	dri_bo *bo;
326};
327
328#define MAX_SURFACES 12
329struct binding_table_obj {
330	dri_bo *bo;
331	struct surface_state_obj surface_states[MAX_SURFACES];
332};
333
334struct slice_data_obj {
335	dri_bo *bo;
336};
337
338struct mb_data_obj {
339	dri_bo *bo;
340};
341
342struct cs_state_obj {
343	dri_bo *bo;
344};
345
346static struct media_state {
347	struct vfe_state_obj vfe_state;
348	struct vld_state_obj vld_state;
349	struct binding_table_obj binding_table;
350	struct cs_state_obj cs_object;
351	struct slice_data_obj slice_data;
352	struct mb_data_obj mb_data;
353} media_state;
354
355/* XvMCQMatrix * 2 + idct_table + 8 * kernel offset pointer */
356#define CS_OBJECT_SIZE (32*20 + sizeof(unsigned int) * 8)
357static void free_object(struct media_state *s)
358{
359	int i;
360#define FREE_ONE_BO(bo) \
361    if (bo) \
362        drm_intel_bo_unreference(bo)
363	FREE_ONE_BO(s->vfe_state.bo);
364	FREE_ONE_BO(s->vfe_state.interface.bo);
365	for (i = 0; i < MEDIA_KERNEL_NUM; i++)
366		FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo);
367	FREE_ONE_BO(s->binding_table.bo);
368	for (i = 0; i < MAX_SURFACES; i++)
369		FREE_ONE_BO(s->binding_table.surface_states[i].bo);
370	FREE_ONE_BO(s->slice_data.bo);
371	FREE_ONE_BO(s->mb_data.bo);
372	FREE_ONE_BO(s->cs_object.bo);
373	FREE_ONE_BO(s->vld_state.bo);
374}
375
376static int alloc_object(struct media_state *s)
377{
378	int i;
379
380	for (i = 0; i < MAX_SURFACES; i++) {
381		s->binding_table.surface_states[i].bo =
382		    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
383				       sizeof(struct brw_surface_state),
384				       0x1000);
385		if (!s->binding_table.surface_states[i].bo)
386			goto out;
387	}
388	return 0;
389out:
390	free_object(s);
391	return BadAlloc;
392}
393
394static void flush()
395{
396#define FLUSH_STATE_CACHE  	1
397	struct brw_mi_flush f;
398	memset(&f, 0, sizeof(f));
399	f.opcode = CMD_MI_FLUSH;
400	f.flags = (1 << FLUSH_STATE_CACHE);
401	BATCH_STRUCT(f);
402}
403
404static Status vfe_state(int vfe_mode)
405{
406	struct brw_vfe_state tmp, *vfe_state = &tmp;
407	memset(vfe_state, 0, sizeof(*vfe_state));
408	if (vfe_mode == VFE_VLD_MODE) {
409		vfe_state->vfe0.extend_vfe_state_present = 1;
410	} else {
411		vfe_state->vfe0.extend_vfe_state_present = 0;
412	}
413	vfe_state->vfe1.vfe_mode = vfe_mode;
414	vfe_state->vfe1.num_urb_entries = 1;
415	vfe_state->vfe1.children_present = 0;
416	vfe_state->vfe1.urb_entry_alloc_size = 2;
417	vfe_state->vfe1.max_threads = 31;
418	vfe_state->vfe2.interface_descriptor_base =
419	    media_state.vfe_state.interface.bo->offset >> 4;
420
421	if (media_state.vfe_state.bo)
422		drm_intel_bo_unreference(media_state.vfe_state.bo);
423
424	media_state.vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
425						      "vfe state",
426						      sizeof(struct
427							     brw_vfe_state),
428						      0x1000);
429	if (!media_state.vfe_state.bo)
430		return BadAlloc;
431
432	drm_intel_bo_subdata(media_state.vfe_state.bo, 0, sizeof(tmp), &tmp);
433
434	drm_intel_bo_emit_reloc(media_state.vfe_state.bo,
435				offsetof(struct brw_vfe_state, vfe2),
436				media_state.vfe_state.interface.bo, 0,
437				I915_GEM_DOMAIN_INSTRUCTION, 0);
438	return Success;
439}
440
441static Status interface_descriptor()
442{
443	int i;
444	struct brw_interface_descriptor tmp, *desc = &tmp;
445
446	if (media_state.vfe_state.interface.bo)
447		drm_intel_bo_unreference(media_state.vfe_state.interface.bo);
448
449	media_state.vfe_state.interface.bo =
450	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces",
451			       MEDIA_KERNEL_NUM *
452			       sizeof(struct brw_interface_descriptor), 0x1000);
453	if (!media_state.vfe_state.interface.bo)
454		return BadAlloc;
455
456	for (i = 0; i < MEDIA_KERNEL_NUM; i++) {
457		memset(desc, 0, sizeof(*desc));
458		desc->desc0.grf_reg_blocks = 15;
459		desc->desc0.kernel_start_pointer =
460		    media_state.vfe_state.interface.kernels[i].bo->offset >> 6;
461
462		desc->desc1.const_urb_entry_read_offset = 0;
463		desc->desc1.const_urb_entry_read_len = 30;
464
465		desc->desc3.binding_table_entry_count = MAX_SURFACES - 1;
466		desc->desc3.binding_table_pointer =
467		    media_state.binding_table.bo->offset >> 5;
468
469		drm_intel_bo_subdata(media_state.vfe_state.interface.bo,
470				     i * sizeof(tmp), sizeof(tmp), desc);
471
472		drm_intel_bo_emit_reloc(media_state.vfe_state.interface.bo,
473					i * sizeof(*desc) + offsetof(struct
474								     brw_interface_descriptor,
475								     desc0),
476					media_state.vfe_state.
477					interface.kernels[i].bo,
478					desc->desc0.grf_reg_blocks,
479					I915_GEM_DOMAIN_INSTRUCTION, 0);
480
481		drm_intel_bo_emit_reloc(media_state.vfe_state.interface.bo,
482					i * sizeof(*desc) + offsetof(struct
483								     brw_interface_descriptor,
484								     desc3),
485					media_state.binding_table.bo,
486					desc->desc3.binding_table_entry_count,
487					I915_GEM_DOMAIN_INSTRUCTION, 0);
488	}
489	return Success;
490}
491
492static int setup_media_kernels(struct intel_xvmc_hw_context *ctx)
493{
494	int i;
495
496	assert(MEDIA_KERNEL_NUM ==
497	       sizeof(media_gen5_kernels) / sizeof(media_gen5_kernels[0]));
498
499	for (i = 0; i < MEDIA_KERNEL_NUM; i++) {
500		if (ctx->i965.is_igdng)
501			media_state.vfe_state.interface.kernels[i].bo =
502			    drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel",
503					       media_gen5_kernels[i].size,
504					       0x1000);
505		else
506			media_state.vfe_state.interface.kernels[i].bo =
507			    drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernels",
508					       media_kernels[i].size, 0x1000);
509
510		if (!media_state.vfe_state.interface.kernels[i].bo)
511			goto out;
512	}
513
514	for (i = 0; i < MEDIA_KERNEL_NUM; i++) {
515		dri_bo *bo = media_state.vfe_state.interface.kernels[i].bo;
516
517		if (ctx->i965.is_igdng)
518			drm_intel_bo_subdata(bo, 0, media_gen5_kernels[i].size,
519					     media_gen5_kernels[i].bin);
520		else
521			drm_intel_bo_subdata(bo, 0, media_kernels[i].size,
522					     media_kernels[i].bin);
523	}
524	return 0;
525out:
526	free_object(&media_state);
527	return BadAlloc;
528}
529
530static Status binding_tables()
531{
532	unsigned int table[MAX_SURFACES];
533	int i;
534
535	if (media_state.binding_table.bo)
536		drm_intel_bo_unreference(media_state.binding_table.bo);
537	media_state.binding_table.bo =
538	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table",
539			       MAX_SURFACES * 4, 0x1000);
540	if (!media_state.binding_table.bo)
541		return BadAlloc;
542
543	for (i = 0; i < MAX_SURFACES; i++) {
544		table[i] =
545		    media_state.binding_table.surface_states[i].bo->offset;
546		drm_intel_bo_emit_reloc(media_state.binding_table.bo,
547					i * sizeof(unsigned int),
548					media_state.
549					binding_table.surface_states[i].bo, 0,
550					I915_GEM_DOMAIN_INSTRUCTION, 0);
551	}
552
553	drm_intel_bo_subdata(media_state.binding_table.bo, 0, sizeof(table),
554			     table);
555	return Success;
556}
557
558static Status cs_init(int interface_offset)
559{
560	char buf[CS_OBJECT_SIZE];
561	unsigned int *lib_reloc;
562	int i;
563
564	if (media_state.cs_object.bo)
565		drm_intel_bo_unreference(media_state.cs_object.bo);
566
567	media_state.cs_object.bo =
568	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "cs object", CS_OBJECT_SIZE,
569			       64);
570	if (!media_state.cs_object.bo)
571		return BadAlloc;
572
573	memcpy(buf + 32 * 4, idct_table, sizeof(idct_table));
574	/* idct lib reloction */
575	lib_reloc = (unsigned int *)(buf + 32 * 20);
576	for (i = 0; i < 8; i++)
577		lib_reloc[i] =
578		    media_state.vfe_state.interface.kernels[LIB_INTERFACE +
579							    interface_offset].bo->
580		    offset;
581	drm_intel_bo_subdata(media_state.cs_object.bo, 32 * 4,
582			     32 * 16 + 8 * sizeof(unsigned int), buf + 32 * 4);
583
584	for (i = 0; i < 8; i++)
585		drm_intel_bo_emit_reloc(media_state.cs_object.bo,
586					32 * 20 + sizeof(unsigned int) * i,
587					media_state.vfe_state.
588					interface.kernels[LIB_INTERFACE +
589							  interface_offset].bo,
590					0, I915_GEM_DOMAIN_INSTRUCTION, 0);
591
592	return Success;
593}
594
595#define STRIDE(w)               (w)
596#define SIZE_YUV420(w, h)       (h * (STRIDE(w) + STRIDE(w >> 1)))
597static Status create_context(Display * display, XvMCContext * context,
598			     int priv_count, CARD32 * priv_data)
599{
600	struct intel_xvmc_context *intel_ctx;
601	struct intel_xvmc_hw_context *hw_ctx;
602	hw_ctx = (struct intel_xvmc_hw_context *)priv_data;
603
604	intel_ctx = calloc(1, sizeof(struct intel_xvmc_context));
605	if (!intel_ctx)
606		return BadAlloc;
607	intel_ctx->hw = hw_ctx;
608	context->privData = intel_ctx;
609	intel_ctx->surface_bo_size
610		= SIZE_YUV420(context->width, context->height);
611
612	if (alloc_object(&media_state))
613		return BadAlloc;
614
615	if (setup_media_kernels(hw_ctx))
616		return BadAlloc;
617	return Success;
618}
619
620static Status destroy_context(Display * display, XvMCContext * context)
621{
622	struct intel_xvmc_context *intel_ctx;
623	intel_ctx = context->privData;
624	free(intel_ctx->hw);
625	free(intel_ctx);
626	return Success;
627}
628
629static Status load_qmatrix(Display * display, XvMCContext * context,
630			   const XvMCQMatrix * qmx)
631{
632	Status ret;
633	ret = cs_init(0);
634	if (ret != Success)
635		return ret;
636	drm_intel_bo_subdata(media_state.cs_object.bo, 0, 64,
637			     qmx->intra_quantiser_matrix);
638	drm_intel_bo_subdata(media_state.cs_object.bo, 64, 64,
639			     qmx->non_intra_quantiser_matrix);
640
641	return Success;
642}
643
644static Status vld_state(const XvMCMpegControl * control)
645{
646	struct brw_vld_state tmp, *vld = &tmp;
647
648	if (media_state.vld_state.bo)
649		drm_intel_bo_unreference(media_state.vld_state.bo);
650	media_state.vld_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
651						      "vld state",
652						      sizeof(struct
653							     brw_vld_state),
654						      64);
655	if (!media_state.vld_state.bo)
656		return BadAlloc;
657
658	memset(vld, 0, sizeof(*vld));
659	vld->vld0.f_code_0_0 = control->FHMV_range + 1;
660	vld->vld0.f_code_0_1 = control->FVMV_range + 1;
661	vld->vld0.f_code_1_0 = control->BHMV_range + 1;
662	vld->vld0.f_code_1_1 = control->BVMV_range + 1;
663	vld->vld0.intra_dc_precision = control->intra_dc_precision;
664	vld->vld0.picture_structure = control->picture_structure;
665	vld->vld0.top_field_first = !!(control->flags & XVMC_TOP_FIELD_FIRST);
666	vld->vld0.frame_predict_frame_dct =
667	    !!(control->flags & XVMC_PRED_DCT_FRAME);
668	vld->vld0.concealment_motion_vector =
669	    !!(control->flags & XVMC_CONCEALMENT_MOTION_VECTORS);
670	vld->vld0.quantizer_scale_type = !!(control->flags & XVMC_Q_SCALE_TYPE);
671	vld->vld0.intra_vlc_format = !!(control->flags & XVMC_INTRA_VLC_FORMAT);
672	vld->vld0.scan_order = !!(control->flags & XVMC_ALTERNATE_SCAN);
673
674	vld->vld1.picture_coding_type = control->picture_coding_type;
675
676	vld->desc_remap_table0.index_0 = FRAME_INTRA;
677	vld->desc_remap_table0.index_1 = FRAME_FRAME_PRED_FORWARD;
678	vld->desc_remap_table0.index_2 = FRAME_FIELD_PRED_FORWARD;
679	vld->desc_remap_table0.index_3 = FRAME_FIELD_PRED_BIDIRECT;	/* dual prime */
680	vld->desc_remap_table0.index_4 = FRAME_FRAME_PRED_BACKWARD;
681	vld->desc_remap_table0.index_5 = FRAME_FIELD_PRED_BACKWARD;
682	vld->desc_remap_table0.index_6 = FRAME_FRAME_PRED_BIDIRECT;
683	vld->desc_remap_table0.index_7 = FRAME_FIELD_PRED_BIDIRECT;
684
685	vld->desc_remap_table1.index_8 = FRAME_INTRA;
686	vld->desc_remap_table1.index_9 = FRAME_FRAME_PRED_FORWARD;
687	vld->desc_remap_table1.index_10 = FRAME_FIELD_PRED_FORWARD;
688	vld->desc_remap_table1.index_11 = FRAME_FIELD_PRED_BIDIRECT;
689	vld->desc_remap_table1.index_12 = FRAME_FRAME_PRED_BACKWARD;
690	vld->desc_remap_table1.index_13 = FRAME_FIELD_PRED_BACKWARD;
691	vld->desc_remap_table1.index_14 = FRAME_FRAME_PRED_BIDIRECT;
692	vld->desc_remap_table1.index_15 = FRAME_FIELD_PRED_BIDIRECT;
693
694	drm_intel_bo_subdata(media_state.vld_state.bo, 0, sizeof(tmp), vld);
695	return Success;
696}
697
698static Status setup_media_surface(int index, dri_bo * bo,
699				  unsigned long offset, int w, int h,
700				  Bool write)
701{
702	struct brw_surface_state tmp, *ss = &tmp;
703	memset(ss, 0, sizeof(*ss));
704	ss->ss0.surface_type = BRW_SURFACE_2D;
705	ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT;
706	ss->ss1.base_addr = offset + bo->offset;
707	ss->ss2.width = w - 1;
708	ss->ss2.height = h - 1;
709	ss->ss3.pitch = w - 1;
710
711	if (media_state.binding_table.surface_states[index].bo)
712		drm_intel_bo_unreference(media_state.
713					 binding_table.surface_states[index].
714					 bo);
715
716	media_state.binding_table.surface_states[index].bo =
717	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
718			       sizeof(struct brw_surface_state), 0x1000);
719	if (!media_state.binding_table.surface_states[index].bo)
720		return BadAlloc;
721
722	drm_intel_bo_subdata(media_state.binding_table.surface_states[index].bo,
723			     0, sizeof(*ss), ss);
724	drm_intel_bo_emit_reloc(media_state.binding_table.
725				surface_states[index].bo,
726				offsetof(struct brw_surface_state, ss1), bo,
727				offset, I915_GEM_DOMAIN_RENDER,
728				write ? I915_GEM_DOMAIN_RENDER : 0);
729	return Success;
730}
731
732static Status setup_surface(struct intel_xvmc_surface *target,
733			    struct intel_xvmc_surface *past,
734			    struct intel_xvmc_surface *future, int w, int h)
735{
736	Status ret;
737	ret = setup_media_surface(0, target->bo, 0, w, h, TRUE);
738	if (ret != Success)
739		return ret;
740	ret = setup_media_surface(1, target->bo, w * h, w / 2, h / 2, TRUE);
741	if (ret != Success)
742		return ret;
743	ret =
744	    setup_media_surface(2, target->bo, w * h + w * h / 4, w / 2, h / 2,
745				TRUE);
746	if (ret != Success)
747		return ret;
748	if (past) {
749		ret = setup_media_surface(4, past->bo, 0, w, h, FALSE);
750		if (ret != Success)
751			return ret;
752		ret =
753		    setup_media_surface(5, past->bo, w * h, w / 2, h / 2,
754					FALSE);
755		if (ret != Success)
756			return ret;
757		ret =
758		    setup_media_surface(6, past->bo, w * h + w * h / 4, w / 2,
759					h / 2, FALSE);
760		if (ret != Success)
761			return ret;
762	}
763	if (future) {
764		ret = setup_media_surface(7, future->bo, 0, w, h, FALSE);
765		if (ret != Success)
766			return ret;
767		ret =
768		    setup_media_surface(8, future->bo, w * h, w / 2, h / 2,
769					FALSE);
770		if (ret != Success)
771			return ret;
772		ret =
773		    setup_media_surface(9, future->bo, w * h + w * h / 4, w / 2,
774					h / 2, FALSE);
775		if (ret != Success)
776			return ret;
777	}
778	return Success;
779}
780
781static Status begin_surface(Display * display, XvMCContext * context,
782			    XvMCSurface * target,
783			    XvMCSurface * past,
784			    XvMCSurface * future,
785			    const XvMCMpegControl * control)
786{
787	struct intel_xvmc_surface *priv_target, *priv_past, *priv_future;
788	intel_xvmc_context_ptr intel_ctx = context->privData;
789	Status ret;
790
791	priv_target = target->privData;
792	priv_past = past ? past->privData : NULL;
793	priv_future = future ? future->privData : NULL;
794
795	ret = vld_state(control);
796	if (ret != Success)
797		return ret;
798	ret = setup_surface(priv_target, priv_past, priv_future,
799			    context->width, context->height);
800	if (ret != Success)
801		return ret;
802	ret = binding_tables();
803	if (ret != Success)
804		return ret;
805	ret = interface_descriptor();
806	if (ret != Success)
807		return ret;
808	ret = vfe_state(VFE_VLD_MODE);
809	if (ret != Success)
810		return ret;
811
812	LOCK_HARDWARE(intel_ctx->hw_context);
813	flush();
814	UNLOCK_HARDWARE(intel_ctx->hw_context);
815	return Success;
816}
817
818static Status put_slice(Display * display, XvMCContext * context,
819			unsigned char *slice, int nbytes)
820{
821	return Success;
822}
823
824static void state_base_address(struct intel_xvmc_hw_context *ctx)
825{
826	BATCH_LOCALS;
827
828	if (ctx->i965.is_igdng) {
829		BEGIN_BATCH(8);
830		OUT_BATCH(BRW_STATE_BASE_ADDRESS | 6);
831		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
832		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
833		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
834		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
835		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
836		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
837		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
838		ADVANCE_BATCH();
839	} else {
840		BEGIN_BATCH(6);
841		OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
842		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
843		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
844		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
845		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
846		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
847		ADVANCE_BATCH();
848	}
849}
850
851static void pipeline_select()
852{
853	BATCH_LOCALS;
854	BEGIN_BATCH(1);
855	OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
856	ADVANCE_BATCH();
857}
858
859static void media_state_pointers(int vfe_mode)
860{
861	BATCH_LOCALS;
862	BEGIN_BATCH(3);
863	OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1);
864	if (vfe_mode == VFE_VLD_MODE)
865		OUT_RELOC(media_state.vld_state.bo, I915_GEM_DOMAIN_INSTRUCTION,
866			  0, 1);
867	else
868		OUT_BATCH(0);
869	OUT_RELOC(media_state.vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
870	ADVANCE_BATCH();
871}
872
873static void align_urb_fence()
874{
875	BATCH_LOCALS;
876	int i, offset_to_next_cacheline;
877	unsigned long batch_offset;
878	BEGIN_BATCH(3);
879	batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr;
880	offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset;
881	if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) {
882		for (i = 0; i < offset_to_next_cacheline / 4; i++)
883			OUT_BATCH(0);
884		ADVANCE_BATCH();
885	}
886}
887
888static void urb_layout()
889{
890	BATCH_LOCALS;
891	align_urb_fence();
892	BEGIN_BATCH(3);
893	OUT_BATCH(BRW_URB_FENCE |
894		  UF0_VFE_REALLOC |
895		  UF0_CS_REALLOC |
896		  UF0_SF_REALLOC |
897		  UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1);
898
899	OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) |
900		  (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT));
901
902	OUT_BATCH((0 << UF2_CS_FENCE_SHIFT) | (0 << UF2_SF_FENCE_SHIFT) | ((URB_SIZE - CS_SIZE - 1) << UF2_VFE_FENCE_SHIFT) |	/* VFE_SIZE */
903		  ((URB_SIZE) << UF2_CS_FENCE_SHIFT));	/* CS_SIZE */
904	ADVANCE_BATCH();
905}
906
907static void cs_urb_layout()
908{
909	BATCH_LOCALS;
910	BEGIN_BATCH(2);
911	OUT_BATCH(BRW_CS_URB_STATE | 0);
912	OUT_BATCH((CS_SIZE << 4) |	/* URB Entry Allocation Size */
913		  (1 << 0));	/* Number of URB Entries */
914	ADVANCE_BATCH();
915}
916
917static void cs_buffer()
918{
919	BATCH_LOCALS;
920	BEGIN_BATCH(2);
921	OUT_BATCH(BRW_CONSTANT_BUFFER | 0 | (1 << 8));
922	OUT_RELOC(media_state.cs_object.bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
923		  CS_SIZE);
924	ADVANCE_BATCH();
925}
926
927/* kick media object to gpu in idct mode*/
928static void send_media_object(XvMCMacroBlock * mb, dri_bo * bo,
929			      uint32_t offset, enum interface interface)
930{
931	BATCH_LOCALS;
932	BEGIN_BATCH(13);
933	OUT_BATCH(BRW_MEDIA_OBJECT | 11);
934	OUT_BATCH(interface);
935	OUT_BATCH(6 * 128);
936	OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
937
938	OUT_BATCH(mb->x << 4);
939	OUT_BATCH(mb->y << 4);
940	OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
941	OUT_BATCH_SHORT(mb->coded_block_pattern);
942	OUT_BATCH_SHORT(mb->PMV[0][0][0]);
943	OUT_BATCH_SHORT(mb->PMV[0][0][1]);
944	OUT_BATCH_SHORT(mb->PMV[0][1][0]);
945	OUT_BATCH_SHORT(mb->PMV[0][1][1]);
946
947	OUT_BATCH_SHORT(mb->PMV[1][0][0]);
948	OUT_BATCH_SHORT(mb->PMV[1][0][1]);
949	OUT_BATCH_SHORT(mb->PMV[1][1][0]);
950	OUT_BATCH_SHORT(mb->PMV[1][1][1]);
951	OUT_BATCH_CHAR(mb->dct_type);
952	OUT_BATCH_CHAR(mb->motion_vertical_field_select);
953
954	OUT_BATCH(0xffffffff);
955	ADVANCE_BATCH();
956}
957
958/* kick media object to gpu in vld mode*/
959static void vld_send_media_object(dri_bo * bo,
960				  int slice_len, int mb_h_pos, int mb_v_pos,
961				  int mb_bit_offset, int mb_count,
962				  int q_scale_code)
963{
964	BATCH_LOCALS;
965	BEGIN_BATCH(6);
966	OUT_BATCH(BRW_MEDIA_OBJECT | 4);
967	OUT_BATCH(0);
968	OUT_BATCH(slice_len);
969	OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
970	OUT_BATCH((mb_h_pos << 24) | (mb_v_pos << 16) | (mb_count << 8) |
971		  (mb_bit_offset));
972	OUT_BATCH(q_scale_code << 24);
973	ADVANCE_BATCH();
974}
975
976static Status put_slice2(Display * display, XvMCContext * context,
977			 unsigned char *slice, int nbytes, int sliceCode)
978{
979	unsigned int bit_buf;
980	intel_xvmc_context_ptr intel_ctx = context->privData;
981	struct intel_xvmc_hw_context *hw_ctx = intel_ctx->hw;
982	int q_scale_code, mb_row;
983
984	mb_row = *(slice - 1) - 1;
985	bit_buf =
986	    (slice[0] << 24) | (slice[1] << 16) | (slice[2] << 8) | (slice[3]);
987
988	q_scale_code = bit_buf >> 27;
989
990	if (media_state.slice_data.bo) {
991		drm_intel_gem_bo_unmap_gtt(media_state.slice_data.bo);
992
993		drm_intel_bo_unreference(media_state.slice_data.bo);
994	}
995	media_state.slice_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
996						       "slice data",
997						       VLD_MAX_SLICE_SIZE, 64);
998	if (!media_state.slice_data.bo)
999		return BadAlloc;
1000	drm_intel_gem_bo_map_gtt(media_state.slice_data.bo);
1001
1002	memcpy(media_state.slice_data.bo->virtual, slice, nbytes);
1003
1004	LOCK_HARDWARE(intel_ctx->hw_context);
1005	state_base_address(hw_ctx);
1006	pipeline_select();
1007	media_state_pointers(VFE_VLD_MODE);
1008	urb_layout();
1009	cs_urb_layout();
1010	cs_buffer();
1011	vld_send_media_object(media_state.slice_data.bo,
1012			      nbytes, 0, mb_row, 6, 127, q_scale_code);
1013	intelFlushBatch();
1014	UNLOCK_HARDWARE(intel_ctx->hw_context);
1015
1016	return Success;
1017}
1018
1019static Status render_surface(Display * display,
1020			     XvMCContext * context,
1021			     unsigned int picture_structure,
1022			     XvMCSurface * target_surface,
1023			     XvMCSurface * past_surface,
1024			     XvMCSurface * future_surface,
1025			     unsigned int flags,
1026			     unsigned int num_macroblocks,
1027			     unsigned int first_macroblock,
1028			     XvMCMacroBlockArray * macroblock_array,
1029			     XvMCBlockArray * blocks)
1030{
1031	struct intel_xvmc_surface *priv_target, *priv_past, *priv_future;
1032	intel_xvmc_context_ptr intel_ctx;
1033	XvMCMacroBlock *mb;
1034	Status ret;
1035	unsigned short *block_ptr;
1036	int i, j;
1037	int block_offset = 0;
1038	struct intel_xvmc_hw_context *hw_ctx;
1039
1040	intel_ctx = context->privData;
1041
1042	hw_ctx = (struct intel_xvmc_hw_context *)context->privData;
1043	priv_target = target_surface->privData;
1044	priv_past = past_surface ? past_surface->privData : NULL;
1045	priv_future = future_surface ? future_surface->privData : NULL;
1046
1047	ret = setup_surface(priv_target, priv_past, priv_future,
1048			    context->width, context->height);
1049	if (ret != Success)
1050		return ret;
1051	ret = binding_tables();
1052	if (ret != Success)
1053		return ret;
1054	ret = interface_descriptor();
1055	if (ret != Success)
1056		return ret;
1057	ret = cs_init(INTERFACE_NUM);
1058	if (ret != Success)
1059		return ret;
1060	ret = vfe_state(VFE_GENERIC_MODE);
1061	if (ret != Success)
1062		return ret;
1063
1064	if (media_state.mb_data.bo) {
1065		drm_intel_gem_bo_unmap_gtt(media_state.mb_data.bo);
1066
1067		drm_intel_bo_unreference(media_state.mb_data.bo);
1068	}
1069	unsigned int block_num =
1070	    (((context->width + 15) >> 4) * ((context->height + 15) >> 4));
1071	unsigned int surface_size = (64 * sizeof(short) * 6 * block_num);
1072	media_state.mb_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
1073						    "macroblock data",
1074						    surface_size, 64);
1075	if (!media_state.mb_data.bo)
1076		return BadAlloc;
1077	drm_intel_gem_bo_map_gtt(media_state.mb_data.bo);
1078
1079	block_ptr = media_state.mb_data.bo->virtual;
1080	unsigned short *mb_block_ptr;
1081	for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) {
1082		mb = &macroblock_array->macro_blocks[i];
1083		mb_block_ptr = &blocks->blocks[(mb->index << 6)];
1084
1085		if (mb->coded_block_pattern & 0x20) {
1086			for (j = 0; j < 8; j++)
1087				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
1088				       16);
1089			mb_block_ptr += 64;
1090		}
1091		if (mb->coded_block_pattern & 0x10) {
1092			for (j = 0; j < 8; j++)
1093				memcpy(block_ptr + 16 * j + 8,
1094				       mb_block_ptr + 8 * j, 16);
1095			mb_block_ptr += 64;
1096		}
1097
1098		block_ptr += 2 * 64;
1099		if (mb->coded_block_pattern & 0x08) {
1100			for (j = 0; j < 8; j++)
1101				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
1102				       16);
1103			mb_block_ptr += 64;
1104		}
1105		if (mb->coded_block_pattern & 0x04) {
1106			for (j = 0; j < 8; j++)
1107				memcpy(block_ptr + 16 * j + 8,
1108				       mb_block_ptr + 8 * j, 16);
1109			mb_block_ptr += 64;
1110		}
1111
1112		block_ptr += 2 * 64;
1113		if (mb->coded_block_pattern & 0x2) {
1114			memcpy(block_ptr, mb_block_ptr, 128);
1115			mb_block_ptr += 64;
1116		}
1117
1118		block_ptr += 64;
1119		if (mb->coded_block_pattern & 0x1)
1120			memcpy(block_ptr, mb_block_ptr, 128);
1121		block_ptr += 64;
1122	}
1123
1124	LOCK_HARDWARE(intel_ctx->hw_context);
1125	state_base_address(hw_ctx);
1126	flush();
1127	pipeline_select();
1128	urb_layout();
1129	media_state_pointers(VFE_GENERIC_MODE);
1130	cs_urb_layout();
1131	cs_buffer();
1132	for (i = first_macroblock;
1133	     i < num_macroblocks + first_macroblock;
1134	     i++, block_offset += 128 * 6) {
1135		mb = &macroblock_array->macro_blocks[i];
1136
1137		if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
1138			send_media_object(mb, media_state.mb_data.bo,
1139					  block_offset,
1140					  FRAME_INTRA + INTERFACE_NUM);
1141		} else {
1142			if (((mb->motion_type & 3) == XVMC_PREDICTION_FRAME)) {
1143				if ((mb->macroblock_type &
1144				     XVMC_MB_TYPE_MOTION_FORWARD)) {
1145					if ((mb->macroblock_type &
1146					     XVMC_MB_TYPE_MOTION_BACKWARD)) {
1147						send_media_object(mb,
1148								  media_state.mb_data.
1149								  bo,
1150								  block_offset,
1151								  FRAME_FRAME_PRED_BIDIRECT
1152								  +
1153								  INTERFACE_NUM);
1154					} else {
1155						send_media_object(mb,
1156								  media_state.mb_data.
1157								  bo,
1158								  block_offset,
1159								  FRAME_FRAME_PRED_FORWARD
1160								  +
1161								  INTERFACE_NUM);
1162					}
1163				} else
1164				    if ((mb->macroblock_type &
1165					 XVMC_MB_TYPE_MOTION_BACKWARD)) {
1166					send_media_object(mb,
1167							  media_state.
1168							  mb_data.bo,
1169							  block_offset,
1170							  FRAME_FRAME_PRED_BACKWARD
1171							  + INTERFACE_NUM);
1172				}
1173			} else if ((mb->motion_type & 3) ==
1174				   XVMC_PREDICTION_FIELD) {
1175				if ((mb->macroblock_type &
1176				     XVMC_MB_TYPE_MOTION_FORWARD)) {
1177					if (((mb->macroblock_type &
1178					      XVMC_MB_TYPE_MOTION_BACKWARD))) {
1179						send_media_object(mb,
1180								  media_state.mb_data.
1181								  bo,
1182								  block_offset,
1183								  FRAME_FIELD_PRED_BIDIRECT
1184								  +
1185								  INTERFACE_NUM);
1186					} else {
1187						send_media_object(mb,
1188								  media_state.mb_data.
1189								  bo,
1190								  block_offset,
1191								  FRAME_FIELD_PRED_FORWARD
1192								  +
1193								  INTERFACE_NUM);
1194					}
1195				} else
1196				    if ((mb->macroblock_type &
1197					 XVMC_MB_TYPE_MOTION_BACKWARD)) {
1198					send_media_object(mb,
1199							  media_state.
1200							  mb_data.bo,
1201							  block_offset,
1202							  FRAME_FIELD_PRED_BACKWARD
1203							  + INTERFACE_NUM);
1204				}
1205			} else {
1206				send_media_object(mb, media_state.mb_data.bo, block_offset, FRAME_FIELD_PRED_BIDIRECT + INTERFACE_NUM);	/*dual prime */
1207			}
1208		}
1209	}
1210	intelFlushBatch();
1211	UNLOCK_HARDWARE(intel_ctx->hw_context);
1212	return Success;
1213}
1214
1215struct _intel_xvmc_driver xvmc_vld_driver = {
1216	.type = XVMC_I965_MPEG2_VLD,
1217	.create_context = create_context,
1218	.destroy_context = destroy_context,
1219	.load_qmatrix = load_qmatrix,
1220	.begin_surface = begin_surface,
1221	.render_surface = render_surface,
1222	.put_slice = put_slice,
1223	.put_slice2 = put_slice2
1224};
1225