103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2009 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Author:
2403b705cfSriastradh *    Zou Nan hai <nanhai.zou@intel.com>
2503b705cfSriastradh */
2603b705cfSriastradh#include "intel_xvmc_private.h"
2703b705cfSriastradh#include "i830_reg.h"
2803b705cfSriastradh#include "i965_reg.h"
2903b705cfSriastradh#include "brw_defines.h"
3003b705cfSriastradh#include "brw_structs.h"
3103b705cfSriastradh
3203b705cfSriastradh#ifndef ALIGN
3303b705cfSriastradh#define ALIGN(m,n) (((m) + (n) - 1) & ~((n) - 1))
3403b705cfSriastradh#endif
3503b705cfSriastradh
3603b705cfSriastradh#define BATCH_STRUCT(x) intelBatchbufferData(&x, sizeof(x), 0)
3703b705cfSriastradh#define VLD_MAX_SLICE_SIZE (32 * 1024)
3803b705cfSriastradh#define CS_SIZE 	30
3903b705cfSriastradh#define URB_SIZE 	384
4003b705cfSriastradh/* idct table */
4103b705cfSriastradh#define C0 23170
4203b705cfSriastradh#define C1 22725
4303b705cfSriastradh#define C2 21407
4403b705cfSriastradh#define C3 19266
4503b705cfSriastradh#define C4 16383
4603b705cfSriastradh#define C5 12873
4703b705cfSriastradh#define C6 8867
4803b705cfSriastradh#define C7 4520
4903b705cfSriastradhconst uint32_t idct_table[] = {
5003b705cfSriastradh	C4, C1, C2, C3, C4, C5, C6, C7,	//g5
5103b705cfSriastradh	C4, C1, C2, C3, C4, C5, C6, C7,
5203b705cfSriastradh	C4, C3, C6, -C7, -C4, -C1, -C2, -C5,
5303b705cfSriastradh	C4, C3, C6, -C7, -C4, -C1, -C2, -C5,
5403b705cfSriastradh	C4, C5, -C6, -C1, -C4, C7, C2, C3,
5503b705cfSriastradh	C4, C5, -C6, -C1, -C4, C7, C2, C3,
5603b705cfSriastradh	C4, C7, -C2, -C5, C4, C3, -C6, -C1,
5703b705cfSriastradh	C4, C7, -C2, -C5, C4, C3, -C6, -C1,
5803b705cfSriastradh	C4, -C7, -C2, C5, C4, -C3, -C6, C1,
5903b705cfSriastradh	C4, -C7, -C2, C5, C4, -C3, -C6, C1,
6003b705cfSriastradh	C4, -C5, -C6, C1, -C4, -C7, C2, -C3,
6103b705cfSriastradh	C4, -C5, -C6, C1, -C4, -C7, C2, -C3,
6203b705cfSriastradh	C4, -C3, C6, C7, -C4, C1, -C2, C5,
6303b705cfSriastradh	C4, -C3, C6, C7, -C4, C1, -C2, C5,
6403b705cfSriastradh	C4, -C1, C2, -C3, C4, -C5, C6, -C7,
6503b705cfSriastradh	C4, -C1, C2, -C3, C4, -C5, C6, -C7	//g20
6603b705cfSriastradh};
6703b705cfSriastradh
6803b705cfSriastradh#undef C0
6903b705cfSriastradh#undef C1
7003b705cfSriastradh#undef C2
7103b705cfSriastradh#undef C3
7203b705cfSriastradh#undef C4
7303b705cfSriastradh#undef C5
7403b705cfSriastradh#undef C6
7503b705cfSriastradh#undef C7
7603b705cfSriastradh
7703b705cfSriastradh#define INTERFACE_NUM	8
7803b705cfSriastradhenum interface {
7903b705cfSriastradh	FRAME_INTRA = 0,
8003b705cfSriastradh	FRAME_FRAME_PRED_FORWARD,
8103b705cfSriastradh	FRAME_FRAME_PRED_BACKWARD,
8203b705cfSriastradh	FRAME_FRAME_PRED_BIDIRECT,
8303b705cfSriastradh	FRAME_FIELD_PRED_FORWARD,
8403b705cfSriastradh	FRAME_FIELD_PRED_BACKWARD,
8503b705cfSriastradh	FRAME_FIELD_PRED_BIDIRECT,
8603b705cfSriastradh	LIB_INTERFACE
8703b705cfSriastradh};
8803b705cfSriastradh
8903b705cfSriastradh/*kernels for vld mode*/
9003b705cfSriastradhstatic uint32_t lib_kernel[][4] = {
9103b705cfSriastradh#include "shader/vld/lib.g4b"
9203b705cfSriastradh};
9303b705cfSriastradh
9403b705cfSriastradhstatic uint32_t ipicture_kernel[][4] = {
9503b705cfSriastradh#include "shader/vld/ipicture.g4b"
9603b705cfSriastradh};
9703b705cfSriastradh
9803b705cfSriastradhstatic uint32_t frame_forward_kernel[][4] = {
9903b705cfSriastradh#include "shader/vld/frame_forward.g4b"
10003b705cfSriastradh};
10103b705cfSriastradh
10203b705cfSriastradhstatic uint32_t frame_backward_kernel[][4] = {
10303b705cfSriastradh#include "shader/vld/frame_backward.g4b"
10403b705cfSriastradh};
10503b705cfSriastradh
10603b705cfSriastradhstatic uint32_t frame_f_b_kernel[][4] = {
10703b705cfSriastradh#include "shader/vld/frame_f_b.g4b"
10803b705cfSriastradh};
10903b705cfSriastradh
11003b705cfSriastradhstatic uint32_t field_forward_kernel[][4] = {
11103b705cfSriastradh#include "shader/vld/field_forward.g4b"
11203b705cfSriastradh};
11303b705cfSriastradh
11403b705cfSriastradhstatic uint32_t field_backward_kernel[][4] = {
11503b705cfSriastradh#include "shader/vld/field_backward.g4b"
11603b705cfSriastradh};
11703b705cfSriastradh
11803b705cfSriastradhstatic uint32_t field_f_b_kernel[][4] = {
11903b705cfSriastradh#include "shader/vld/field_f_b.g4b"
12003b705cfSriastradh};
12103b705cfSriastradh
12203b705cfSriastradh/* on Ironlake */
12303b705cfSriastradhstatic uint32_t lib_kernel_gen5[][4] = {
12403b705cfSriastradh#include "shader/vld/lib.g4b.gen5"
12503b705cfSriastradh};
12603b705cfSriastradh
12703b705cfSriastradhstatic uint32_t ipicture_kernel_gen5[][4] = {
12803b705cfSriastradh#include "shader/vld/ipicture.g4b.gen5"
12903b705cfSriastradh};
13003b705cfSriastradh
13103b705cfSriastradhstatic uint32_t frame_forward_kernel_gen5[][4] = {
13203b705cfSriastradh#include "shader/vld/frame_forward.g4b.gen5"
13303b705cfSriastradh};
13403b705cfSriastradh
13503b705cfSriastradhstatic uint32_t frame_backward_kernel_gen5[][4] = {
13603b705cfSriastradh#include "shader/vld/frame_backward.g4b.gen5"
13703b705cfSriastradh};
13803b705cfSriastradh
13903b705cfSriastradhstatic uint32_t frame_f_b_kernel_gen5[][4] = {
14003b705cfSriastradh#include "shader/vld/frame_f_b.g4b.gen5"
14103b705cfSriastradh};
14203b705cfSriastradh
14303b705cfSriastradhstatic uint32_t field_forward_kernel_gen5[][4] = {
14403b705cfSriastradh#include "shader/vld/field_forward.g4b.gen5"
14503b705cfSriastradh};
14603b705cfSriastradh
14703b705cfSriastradhstatic uint32_t field_backward_kernel_gen5[][4] = {
14803b705cfSriastradh#include "shader/vld/field_backward.g4b.gen5"
14903b705cfSriastradh};
15003b705cfSriastradh
15103b705cfSriastradhstatic uint32_t field_f_b_kernel_gen5[][4] = {
15203b705cfSriastradh#include "shader/vld/field_f_b.g4b.gen5"
15303b705cfSriastradh};
15403b705cfSriastradh
15503b705cfSriastradh/*kernels for mc mode*/
15603b705cfSriastradhstatic uint32_t lib_kernel_idct[][4] = {
15703b705cfSriastradh#include "shader/mc/lib_igd.g4b"
15803b705cfSriastradh};
15903b705cfSriastradh
16003b705cfSriastradhstatic uint32_t ipicture_kernel_idct[][4] = {
16103b705cfSriastradh#include "shader/mc/ipicture_igd.g4b"
16203b705cfSriastradh};
16303b705cfSriastradh
16403b705cfSriastradhstatic uint32_t frame_forward_kernel_idct[][4] = {
16503b705cfSriastradh#include "shader/mc/frame_forward_igd.g4b"
16603b705cfSriastradh};
16703b705cfSriastradh
16803b705cfSriastradhstatic uint32_t frame_backward_kernel_idct[][4] = {
16903b705cfSriastradh#include "shader/mc/frame_backward_igd.g4b"
17003b705cfSriastradh};
17103b705cfSriastradh
17203b705cfSriastradhstatic uint32_t frame_f_b_kernel_idct[][4] = {
17303b705cfSriastradh#include "shader/mc/frame_f_b_igd.g4b"
17403b705cfSriastradh};
17503b705cfSriastradh
17603b705cfSriastradhstatic uint32_t field_forward_kernel_idct[][4] = {
17703b705cfSriastradh#include "shader/mc/field_forward_igd.g4b"
17803b705cfSriastradh};
17903b705cfSriastradh
18003b705cfSriastradhstatic uint32_t field_backward_kernel_idct[][4] = {
18103b705cfSriastradh#include "shader/mc/field_backward_igd.g4b"
18203b705cfSriastradh};
18303b705cfSriastradh
18403b705cfSriastradhstatic uint32_t field_f_b_kernel_idct[][4] = {
18503b705cfSriastradh#include "shader/mc/field_f_b_igd.g4b"
18603b705cfSriastradh};
18703b705cfSriastradh
18803b705cfSriastradh/* on Ironlake */
18903b705cfSriastradhstatic uint32_t lib_kernel_idct_gen5[][4] = {
19003b705cfSriastradh#include "shader/mc/lib_igd.g4b.gen5"
19103b705cfSriastradh};
19203b705cfSriastradh
19303b705cfSriastradhstatic uint32_t ipicture_kernel_idct_gen5[][4] = {
19403b705cfSriastradh#include "shader/mc/ipicture_igd.g4b.gen5"
19503b705cfSriastradh};
19603b705cfSriastradh
19703b705cfSriastradhstatic uint32_t frame_forward_kernel_idct_gen5[][4] = {
19803b705cfSriastradh#include "shader/mc/frame_forward_igd.g4b.gen5"
19903b705cfSriastradh};
20003b705cfSriastradh
20103b705cfSriastradhstatic uint32_t frame_backward_kernel_idct_gen5[][4] = {
20203b705cfSriastradh#include "shader/mc/frame_backward_igd.g4b.gen5"
20303b705cfSriastradh};
20403b705cfSriastradh
20503b705cfSriastradhstatic uint32_t frame_f_b_kernel_idct_gen5[][4] = {
20603b705cfSriastradh#include "shader/mc/frame_f_b_igd.g4b.gen5"
20703b705cfSriastradh};
20803b705cfSriastradh
20903b705cfSriastradhstatic uint32_t field_forward_kernel_idct_gen5[][4] = {
21003b705cfSriastradh#include "shader/mc/field_forward_igd.g4b.gen5"
21103b705cfSriastradh};
21203b705cfSriastradh
21303b705cfSriastradhstatic uint32_t field_backward_kernel_idct_gen5[][4] = {
21403b705cfSriastradh#include "shader/mc/field_backward_igd.g4b.gen5"
21503b705cfSriastradh};
21603b705cfSriastradh
21703b705cfSriastradhstatic uint32_t field_f_b_kernel_idct_gen5[][4] = {
21803b705cfSriastradh#include "shader/mc/field_f_b_igd.g4b.gen5"
21903b705cfSriastradh};
22003b705cfSriastradh
22103b705cfSriastradhstruct media_kernel {
22203b705cfSriastradh	uint32_t(*bin)[4];
22303b705cfSriastradh	int size;
22403b705cfSriastradh};
22503b705cfSriastradhstatic struct media_kernel media_kernels[] = {
22603b705cfSriastradh	/*kernels for vld mode */
22703b705cfSriastradh	{ipicture_kernel, sizeof(ipicture_kernel)}
22803b705cfSriastradh	,
22903b705cfSriastradh	{frame_forward_kernel, sizeof(frame_forward_kernel)}
23003b705cfSriastradh	,
23103b705cfSriastradh	{frame_backward_kernel, sizeof(frame_backward_kernel)}
23203b705cfSriastradh	,
23303b705cfSriastradh	{frame_f_b_kernel, sizeof(frame_f_b_kernel)}
23403b705cfSriastradh	,
23503b705cfSriastradh	{field_forward_kernel, sizeof(field_forward_kernel)}
23603b705cfSriastradh	,
23703b705cfSriastradh	{field_backward_kernel, sizeof(field_backward_kernel)}
23803b705cfSriastradh	,
23903b705cfSriastradh	{field_f_b_kernel, sizeof(field_f_b_kernel)}
24003b705cfSriastradh	,
24103b705cfSriastradh	{lib_kernel, sizeof(lib_kernel)}
24203b705cfSriastradh	,
24303b705cfSriastradh	/*kernels for mc mode */
24403b705cfSriastradh	{ipicture_kernel_idct, sizeof(ipicture_kernel_idct)}
24503b705cfSriastradh	,
24603b705cfSriastradh	{frame_forward_kernel_idct, sizeof(frame_forward_kernel_idct)}
24703b705cfSriastradh	,
24803b705cfSriastradh	{frame_backward_kernel_idct, sizeof(frame_backward_kernel_idct)}
24903b705cfSriastradh	,
25003b705cfSriastradh	{frame_f_b_kernel_idct, sizeof(frame_f_b_kernel_idct)}
25103b705cfSriastradh	,
25203b705cfSriastradh	{field_forward_kernel_idct, sizeof(field_forward_kernel_idct)}
25303b705cfSriastradh	,
25403b705cfSriastradh	{field_backward_kernel_idct, sizeof(field_backward_kernel_idct)}
25503b705cfSriastradh	,
25603b705cfSriastradh	{field_f_b_kernel_idct, sizeof(field_f_b_kernel_idct)}
25703b705cfSriastradh	,
25803b705cfSriastradh	{lib_kernel_idct, sizeof(lib_kernel_idct)}
25903b705cfSriastradh};
26003b705cfSriastradh
26103b705cfSriastradhstatic struct media_kernel media_gen5_kernels[] = {
26203b705cfSriastradh	/*kernels for vld mode */
26303b705cfSriastradh	{ipicture_kernel_gen5, sizeof(ipicture_kernel_gen5)}
26403b705cfSriastradh	,
26503b705cfSriastradh	{frame_forward_kernel_gen5, sizeof(frame_forward_kernel_gen5)}
26603b705cfSriastradh	,
26703b705cfSriastradh	{frame_backward_kernel_gen5, sizeof(frame_backward_kernel_gen5)}
26803b705cfSriastradh	,
26903b705cfSriastradh	{frame_f_b_kernel_gen5, sizeof(frame_f_b_kernel_gen5)}
27003b705cfSriastradh	,
27103b705cfSriastradh	{field_forward_kernel_gen5, sizeof(field_forward_kernel_gen5)}
27203b705cfSriastradh	,
27303b705cfSriastradh	{field_backward_kernel_gen5, sizeof(field_backward_kernel_gen5)}
27403b705cfSriastradh	,
27503b705cfSriastradh	{field_f_b_kernel_gen5, sizeof(field_f_b_kernel_gen5)}
27603b705cfSriastradh	,
27703b705cfSriastradh	{lib_kernel_gen5, sizeof(lib_kernel_gen5)}
27803b705cfSriastradh	,
27903b705cfSriastradh	/*kernels for mc mode */
28003b705cfSriastradh	{ipicture_kernel_idct_gen5, sizeof(ipicture_kernel_idct_gen5)}
28103b705cfSriastradh	,
28203b705cfSriastradh	{frame_forward_kernel_idct_gen5, sizeof(frame_forward_kernel_idct_gen5)}
28303b705cfSriastradh	,
28403b705cfSriastradh	{frame_backward_kernel_idct_gen5,
28503b705cfSriastradh	 sizeof(frame_backward_kernel_idct_gen5)}
28603b705cfSriastradh	,
28703b705cfSriastradh	{frame_f_b_kernel_idct_gen5, sizeof(frame_f_b_kernel_idct_gen5)}
28803b705cfSriastradh	,
28903b705cfSriastradh	{field_forward_kernel_idct_gen5, sizeof(field_forward_kernel_idct_gen5)}
29003b705cfSriastradh	,
29103b705cfSriastradh	{field_backward_kernel_idct_gen5,
29203b705cfSriastradh	 sizeof(field_backward_kernel_idct_gen5)}
29303b705cfSriastradh	,
29403b705cfSriastradh	{field_f_b_kernel_idct_gen5, sizeof(field_f_b_kernel_idct_gen5)}
29503b705cfSriastradh	,
29603b705cfSriastradh	{lib_kernel_idct_gen5, sizeof(lib_kernel_idct_gen5)}
29703b705cfSriastradh};
29803b705cfSriastradh
29903b705cfSriastradh#define MEDIA_KERNEL_NUM (sizeof(media_kernels)/sizeof(media_kernels[0]))
30003b705cfSriastradh
30103b705cfSriastradhstruct media_kernel_obj {
30203b705cfSriastradh	dri_bo *bo;
30303b705cfSriastradh};
30403b705cfSriastradh
30503b705cfSriastradhstruct interface_descriptor_obj {
30603b705cfSriastradh	dri_bo *bo;
30703b705cfSriastradh	struct media_kernel_obj kernels[MEDIA_KERNEL_NUM];
30803b705cfSriastradh};
30903b705cfSriastradh
31003b705cfSriastradhstruct vfe_state_obj {
31103b705cfSriastradh	dri_bo *bo;
31203b705cfSriastradh	struct interface_descriptor_obj interface;
31303b705cfSriastradh};
31403b705cfSriastradh
31503b705cfSriastradhstruct vld_state_obj {
31603b705cfSriastradh	dri_bo *bo;
31703b705cfSriastradh};
31803b705cfSriastradh
31903b705cfSriastradhstruct surface_obj {
32003b705cfSriastradh	dri_bo *bo;
32103b705cfSriastradh};
32203b705cfSriastradh
32303b705cfSriastradhstruct surface_state_obj {
32403b705cfSriastradh	struct surface_obj surface;
32503b705cfSriastradh	dri_bo *bo;
32603b705cfSriastradh};
32703b705cfSriastradh
32803b705cfSriastradh#define MAX_SURFACES 12
32903b705cfSriastradhstruct binding_table_obj {
33003b705cfSriastradh	dri_bo *bo;
33103b705cfSriastradh	struct surface_state_obj surface_states[MAX_SURFACES];
33203b705cfSriastradh};
33303b705cfSriastradh
33403b705cfSriastradhstruct slice_data_obj {
33503b705cfSriastradh	dri_bo *bo;
33603b705cfSriastradh};
33703b705cfSriastradh
33803b705cfSriastradhstruct mb_data_obj {
33903b705cfSriastradh	dri_bo *bo;
34003b705cfSriastradh};
34103b705cfSriastradh
34203b705cfSriastradhstruct cs_state_obj {
34303b705cfSriastradh	dri_bo *bo;
34403b705cfSriastradh};
34503b705cfSriastradh
34603b705cfSriastradhstatic struct media_state {
34703b705cfSriastradh	struct vfe_state_obj vfe_state;
34803b705cfSriastradh	struct vld_state_obj vld_state;
34903b705cfSriastradh	struct binding_table_obj binding_table;
35003b705cfSriastradh	struct cs_state_obj cs_object;
35103b705cfSriastradh	struct slice_data_obj slice_data;
35203b705cfSriastradh	struct mb_data_obj mb_data;
35303b705cfSriastradh} media_state;
35403b705cfSriastradh
35503b705cfSriastradh/* XvMCQMatrix * 2 + idct_table + 8 * kernel offset pointer */
35603b705cfSriastradh#define CS_OBJECT_SIZE (32*20 + sizeof(unsigned int) * 8)
35703b705cfSriastradhstatic void free_object(struct media_state *s)
35803b705cfSriastradh{
35903b705cfSriastradh	int i;
36003b705cfSriastradh#define FREE_ONE_BO(bo) \
36103b705cfSriastradh    if (bo) \
36203b705cfSriastradh        drm_intel_bo_unreference(bo)
36303b705cfSriastradh	FREE_ONE_BO(s->vfe_state.bo);
36403b705cfSriastradh	FREE_ONE_BO(s->vfe_state.interface.bo);
36503b705cfSriastradh	for (i = 0; i < MEDIA_KERNEL_NUM; i++)
36603b705cfSriastradh		FREE_ONE_BO(s->vfe_state.interface.kernels[i].bo);
36703b705cfSriastradh	FREE_ONE_BO(s->binding_table.bo);
36803b705cfSriastradh	for (i = 0; i < MAX_SURFACES; i++)
36903b705cfSriastradh		FREE_ONE_BO(s->binding_table.surface_states[i].bo);
37003b705cfSriastradh	FREE_ONE_BO(s->slice_data.bo);
37103b705cfSriastradh	FREE_ONE_BO(s->mb_data.bo);
37203b705cfSriastradh	FREE_ONE_BO(s->cs_object.bo);
37303b705cfSriastradh	FREE_ONE_BO(s->vld_state.bo);
37403b705cfSriastradh}
37503b705cfSriastradh
37603b705cfSriastradhstatic int alloc_object(struct media_state *s)
37703b705cfSriastradh{
37803b705cfSriastradh	int i;
37903b705cfSriastradh
38003b705cfSriastradh	for (i = 0; i < MAX_SURFACES; i++) {
38103b705cfSriastradh		s->binding_table.surface_states[i].bo =
38203b705cfSriastradh		    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
38303b705cfSriastradh				       sizeof(struct brw_surface_state),
38403b705cfSriastradh				       0x1000);
38503b705cfSriastradh		if (!s->binding_table.surface_states[i].bo)
38603b705cfSriastradh			goto out;
38703b705cfSriastradh	}
38803b705cfSriastradh	return 0;
38903b705cfSriastradhout:
39003b705cfSriastradh	free_object(s);
39103b705cfSriastradh	return BadAlloc;
39203b705cfSriastradh}
39303b705cfSriastradh
39403b705cfSriastradhstatic void flush()
39503b705cfSriastradh{
39603b705cfSriastradh#define FLUSH_STATE_CACHE  	1
39703b705cfSriastradh	struct brw_mi_flush f;
39803b705cfSriastradh	memset(&f, 0, sizeof(f));
39903b705cfSriastradh	f.opcode = CMD_MI_FLUSH;
40003b705cfSriastradh	f.flags = (1 << FLUSH_STATE_CACHE);
40103b705cfSriastradh	BATCH_STRUCT(f);
40203b705cfSriastradh}
40303b705cfSriastradh
40403b705cfSriastradhstatic Status vfe_state(int vfe_mode)
40503b705cfSriastradh{
40603b705cfSriastradh	struct brw_vfe_state tmp, *vfe_state = &tmp;
40703b705cfSriastradh	memset(vfe_state, 0, sizeof(*vfe_state));
40803b705cfSriastradh	if (vfe_mode == VFE_VLD_MODE) {
40903b705cfSriastradh		vfe_state->vfe0.extend_vfe_state_present = 1;
41003b705cfSriastradh	} else {
41103b705cfSriastradh		vfe_state->vfe0.extend_vfe_state_present = 0;
41203b705cfSriastradh	}
41303b705cfSriastradh	vfe_state->vfe1.vfe_mode = vfe_mode;
41403b705cfSriastradh	vfe_state->vfe1.num_urb_entries = 1;
41503b705cfSriastradh	vfe_state->vfe1.children_present = 0;
41603b705cfSriastradh	vfe_state->vfe1.urb_entry_alloc_size = 2;
41703b705cfSriastradh	vfe_state->vfe1.max_threads = 31;
41803b705cfSriastradh	vfe_state->vfe2.interface_descriptor_base =
41903b705cfSriastradh	    media_state.vfe_state.interface.bo->offset >> 4;
42003b705cfSriastradh
42103b705cfSriastradh	if (media_state.vfe_state.bo)
42203b705cfSriastradh		drm_intel_bo_unreference(media_state.vfe_state.bo);
42303b705cfSriastradh
42403b705cfSriastradh	media_state.vfe_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
42503b705cfSriastradh						      "vfe state",
42603b705cfSriastradh						      sizeof(struct
42703b705cfSriastradh							     brw_vfe_state),
42803b705cfSriastradh						      0x1000);
42903b705cfSriastradh	if (!media_state.vfe_state.bo)
43003b705cfSriastradh		return BadAlloc;
43103b705cfSriastradh
43203b705cfSriastradh	drm_intel_bo_subdata(media_state.vfe_state.bo, 0, sizeof(tmp), &tmp);
43303b705cfSriastradh
43403b705cfSriastradh	drm_intel_bo_emit_reloc(media_state.vfe_state.bo,
43503b705cfSriastradh				offsetof(struct brw_vfe_state, vfe2),
43603b705cfSriastradh				media_state.vfe_state.interface.bo, 0,
43703b705cfSriastradh				I915_GEM_DOMAIN_INSTRUCTION, 0);
43803b705cfSriastradh	return Success;
43903b705cfSriastradh}
44003b705cfSriastradh
44103b705cfSriastradhstatic Status interface_descriptor()
44203b705cfSriastradh{
44303b705cfSriastradh	int i;
44403b705cfSriastradh	struct brw_interface_descriptor tmp, *desc = &tmp;
44503b705cfSriastradh
44603b705cfSriastradh	if (media_state.vfe_state.interface.bo)
44703b705cfSriastradh		drm_intel_bo_unreference(media_state.vfe_state.interface.bo);
44803b705cfSriastradh
44903b705cfSriastradh	media_state.vfe_state.interface.bo =
45003b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "interfaces",
45103b705cfSriastradh			       MEDIA_KERNEL_NUM *
45203b705cfSriastradh			       sizeof(struct brw_interface_descriptor), 0x1000);
45303b705cfSriastradh	if (!media_state.vfe_state.interface.bo)
45403b705cfSriastradh		return BadAlloc;
45503b705cfSriastradh
45603b705cfSriastradh	for (i = 0; i < MEDIA_KERNEL_NUM; i++) {
45703b705cfSriastradh		memset(desc, 0, sizeof(*desc));
45803b705cfSriastradh		desc->desc0.grf_reg_blocks = 15;
45903b705cfSriastradh		desc->desc0.kernel_start_pointer =
46003b705cfSriastradh		    media_state.vfe_state.interface.kernels[i].bo->offset >> 6;
46103b705cfSriastradh
46203b705cfSriastradh		desc->desc1.const_urb_entry_read_offset = 0;
46303b705cfSriastradh		desc->desc1.const_urb_entry_read_len = 30;
46403b705cfSriastradh
46503b705cfSriastradh		desc->desc3.binding_table_entry_count = MAX_SURFACES - 1;
46603b705cfSriastradh		desc->desc3.binding_table_pointer =
46703b705cfSriastradh		    media_state.binding_table.bo->offset >> 5;
46803b705cfSriastradh
46903b705cfSriastradh		drm_intel_bo_subdata(media_state.vfe_state.interface.bo,
47003b705cfSriastradh				     i * sizeof(tmp), sizeof(tmp), desc);
47103b705cfSriastradh
47203b705cfSriastradh		drm_intel_bo_emit_reloc(media_state.vfe_state.interface.bo,
47303b705cfSriastradh					i * sizeof(*desc) + offsetof(struct
47403b705cfSriastradh								     brw_interface_descriptor,
47503b705cfSriastradh								     desc0),
47603b705cfSriastradh					media_state.vfe_state.
47703b705cfSriastradh					interface.kernels[i].bo,
47803b705cfSriastradh					desc->desc0.grf_reg_blocks,
47903b705cfSriastradh					I915_GEM_DOMAIN_INSTRUCTION, 0);
48003b705cfSriastradh
48103b705cfSriastradh		drm_intel_bo_emit_reloc(media_state.vfe_state.interface.bo,
48203b705cfSriastradh					i * sizeof(*desc) + offsetof(struct
48303b705cfSriastradh								     brw_interface_descriptor,
48403b705cfSriastradh								     desc3),
48503b705cfSriastradh					media_state.binding_table.bo,
48603b705cfSriastradh					desc->desc3.binding_table_entry_count,
48703b705cfSriastradh					I915_GEM_DOMAIN_INSTRUCTION, 0);
48803b705cfSriastradh	}
48903b705cfSriastradh	return Success;
49003b705cfSriastradh}
49103b705cfSriastradh
49203b705cfSriastradhstatic int setup_media_kernels(struct intel_xvmc_hw_context *ctx)
49303b705cfSriastradh{
49403b705cfSriastradh	int i;
49503b705cfSriastradh
49603b705cfSriastradh	assert(MEDIA_KERNEL_NUM ==
49703b705cfSriastradh	       sizeof(media_gen5_kernels) / sizeof(media_gen5_kernels[0]));
49803b705cfSriastradh
49903b705cfSriastradh	for (i = 0; i < MEDIA_KERNEL_NUM; i++) {
50003b705cfSriastradh		if (ctx->i965.is_igdng)
50103b705cfSriastradh			media_state.vfe_state.interface.kernels[i].bo =
50203b705cfSriastradh			    drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernel",
50303b705cfSriastradh					       media_gen5_kernels[i].size,
50403b705cfSriastradh					       0x1000);
50503b705cfSriastradh		else
50603b705cfSriastradh			media_state.vfe_state.interface.kernels[i].bo =
50703b705cfSriastradh			    drm_intel_bo_alloc(xvmc_driver->bufmgr, "kernels",
50803b705cfSriastradh					       media_kernels[i].size, 0x1000);
50903b705cfSriastradh
51003b705cfSriastradh		if (!media_state.vfe_state.interface.kernels[i].bo)
51103b705cfSriastradh			goto out;
51203b705cfSriastradh	}
51303b705cfSriastradh
51403b705cfSriastradh	for (i = 0; i < MEDIA_KERNEL_NUM; i++) {
51503b705cfSriastradh		dri_bo *bo = media_state.vfe_state.interface.kernels[i].bo;
51603b705cfSriastradh
51703b705cfSriastradh		if (ctx->i965.is_igdng)
51803b705cfSriastradh			drm_intel_bo_subdata(bo, 0, media_gen5_kernels[i].size,
51903b705cfSriastradh					     media_gen5_kernels[i].bin);
52003b705cfSriastradh		else
52103b705cfSriastradh			drm_intel_bo_subdata(bo, 0, media_kernels[i].size,
52203b705cfSriastradh					     media_kernels[i].bin);
52303b705cfSriastradh	}
52403b705cfSriastradh	return 0;
52503b705cfSriastradhout:
52603b705cfSriastradh	free_object(&media_state);
52703b705cfSriastradh	return BadAlloc;
52803b705cfSriastradh}
52903b705cfSriastradh
53003b705cfSriastradhstatic Status binding_tables()
53103b705cfSriastradh{
53203b705cfSriastradh	unsigned int table[MAX_SURFACES];
53303b705cfSriastradh	int i;
53403b705cfSriastradh
53503b705cfSriastradh	if (media_state.binding_table.bo)
53603b705cfSriastradh		drm_intel_bo_unreference(media_state.binding_table.bo);
53703b705cfSriastradh	media_state.binding_table.bo =
53803b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "binding_table",
53903b705cfSriastradh			       MAX_SURFACES * 4, 0x1000);
54003b705cfSriastradh	if (!media_state.binding_table.bo)
54103b705cfSriastradh		return BadAlloc;
54203b705cfSriastradh
54303b705cfSriastradh	for (i = 0; i < MAX_SURFACES; i++) {
54403b705cfSriastradh		table[i] =
54503b705cfSriastradh		    media_state.binding_table.surface_states[i].bo->offset;
54603b705cfSriastradh		drm_intel_bo_emit_reloc(media_state.binding_table.bo,
54703b705cfSriastradh					i * sizeof(unsigned int),
54803b705cfSriastradh					media_state.
54903b705cfSriastradh					binding_table.surface_states[i].bo, 0,
55003b705cfSriastradh					I915_GEM_DOMAIN_INSTRUCTION, 0);
55103b705cfSriastradh	}
55203b705cfSriastradh
55303b705cfSriastradh	drm_intel_bo_subdata(media_state.binding_table.bo, 0, sizeof(table),
55403b705cfSriastradh			     table);
55503b705cfSriastradh	return Success;
55603b705cfSriastradh}
55703b705cfSriastradh
55803b705cfSriastradhstatic Status cs_init(int interface_offset)
55903b705cfSriastradh{
56003b705cfSriastradh	char buf[CS_OBJECT_SIZE];
56103b705cfSriastradh	unsigned int *lib_reloc;
56203b705cfSriastradh	int i;
56303b705cfSriastradh
56403b705cfSriastradh	if (media_state.cs_object.bo)
56503b705cfSriastradh		drm_intel_bo_unreference(media_state.cs_object.bo);
56603b705cfSriastradh
56703b705cfSriastradh	media_state.cs_object.bo =
56803b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "cs object", CS_OBJECT_SIZE,
56903b705cfSriastradh			       64);
57003b705cfSriastradh	if (!media_state.cs_object.bo)
57103b705cfSriastradh		return BadAlloc;
57203b705cfSriastradh
57303b705cfSriastradh	memcpy(buf + 32 * 4, idct_table, sizeof(idct_table));
57403b705cfSriastradh	/* idct lib reloction */
57503b705cfSriastradh	lib_reloc = (unsigned int *)(buf + 32 * 20);
57603b705cfSriastradh	for (i = 0; i < 8; i++)
57703b705cfSriastradh		lib_reloc[i] =
57803b705cfSriastradh		    media_state.vfe_state.interface.kernels[LIB_INTERFACE +
57903b705cfSriastradh							    interface_offset].bo->
58003b705cfSriastradh		    offset;
58103b705cfSriastradh	drm_intel_bo_subdata(media_state.cs_object.bo, 32 * 4,
58203b705cfSriastradh			     32 * 16 + 8 * sizeof(unsigned int), buf + 32 * 4);
58303b705cfSriastradh
58403b705cfSriastradh	for (i = 0; i < 8; i++)
58503b705cfSriastradh		drm_intel_bo_emit_reloc(media_state.cs_object.bo,
58603b705cfSriastradh					32 * 20 + sizeof(unsigned int) * i,
58703b705cfSriastradh					media_state.vfe_state.
58803b705cfSriastradh					interface.kernels[LIB_INTERFACE +
58903b705cfSriastradh							  interface_offset].bo,
59003b705cfSriastradh					0, I915_GEM_DOMAIN_INSTRUCTION, 0);
59103b705cfSriastradh
59203b705cfSriastradh	return Success;
59303b705cfSriastradh}
59403b705cfSriastradh
59503b705cfSriastradh#define STRIDE(w)               (w)
59603b705cfSriastradh#define SIZE_YUV420(w, h)       (h * (STRIDE(w) + STRIDE(w >> 1)))
59703b705cfSriastradhstatic Status create_context(Display * display, XvMCContext * context,
59803b705cfSriastradh			     int priv_count, CARD32 * priv_data)
59903b705cfSriastradh{
60003b705cfSriastradh	struct intel_xvmc_context *intel_ctx;
60103b705cfSriastradh	struct intel_xvmc_hw_context *hw_ctx;
60203b705cfSriastradh	hw_ctx = (struct intel_xvmc_hw_context *)priv_data;
60303b705cfSriastradh
60403b705cfSriastradh	intel_ctx = calloc(1, sizeof(struct intel_xvmc_context));
60503b705cfSriastradh	if (!intel_ctx)
60603b705cfSriastradh		return BadAlloc;
60703b705cfSriastradh	intel_ctx->hw = hw_ctx;
60803b705cfSriastradh	context->privData = intel_ctx;
60903b705cfSriastradh	intel_ctx->surface_bo_size
61003b705cfSriastradh		= SIZE_YUV420(context->width, context->height);
61103b705cfSriastradh
61203b705cfSriastradh	if (alloc_object(&media_state))
61303b705cfSriastradh		return BadAlloc;
61403b705cfSriastradh
61503b705cfSriastradh	if (setup_media_kernels(hw_ctx))
61603b705cfSriastradh		return BadAlloc;
61703b705cfSriastradh	return Success;
61803b705cfSriastradh}
61903b705cfSriastradh
62003b705cfSriastradhstatic Status destroy_context(Display * display, XvMCContext * context)
62103b705cfSriastradh{
62203b705cfSriastradh	struct intel_xvmc_context *intel_ctx;
62303b705cfSriastradh	intel_ctx = context->privData;
62403b705cfSriastradh	free(intel_ctx->hw);
62503b705cfSriastradh	free(intel_ctx);
62603b705cfSriastradh	return Success;
62703b705cfSriastradh}
62803b705cfSriastradh
62903b705cfSriastradhstatic Status load_qmatrix(Display * display, XvMCContext * context,
63003b705cfSriastradh			   const XvMCQMatrix * qmx)
63103b705cfSriastradh{
63203b705cfSriastradh	Status ret;
63303b705cfSriastradh	ret = cs_init(0);
63403b705cfSriastradh	if (ret != Success)
63503b705cfSriastradh		return ret;
63603b705cfSriastradh	drm_intel_bo_subdata(media_state.cs_object.bo, 0, 64,
63703b705cfSriastradh			     qmx->intra_quantiser_matrix);
63803b705cfSriastradh	drm_intel_bo_subdata(media_state.cs_object.bo, 64, 64,
63903b705cfSriastradh			     qmx->non_intra_quantiser_matrix);
64003b705cfSriastradh
64103b705cfSriastradh	return Success;
64203b705cfSriastradh}
64303b705cfSriastradh
64403b705cfSriastradhstatic Status vld_state(const XvMCMpegControl * control)
64503b705cfSriastradh{
64603b705cfSriastradh	struct brw_vld_state tmp, *vld = &tmp;
64703b705cfSriastradh
64803b705cfSriastradh	if (media_state.vld_state.bo)
64903b705cfSriastradh		drm_intel_bo_unreference(media_state.vld_state.bo);
65003b705cfSriastradh	media_state.vld_state.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
65103b705cfSriastradh						      "vld state",
65203b705cfSriastradh						      sizeof(struct
65303b705cfSriastradh							     brw_vld_state),
65403b705cfSriastradh						      64);
65503b705cfSriastradh	if (!media_state.vld_state.bo)
65603b705cfSriastradh		return BadAlloc;
65703b705cfSriastradh
65803b705cfSriastradh	memset(vld, 0, sizeof(*vld));
65903b705cfSriastradh	vld->vld0.f_code_0_0 = control->FHMV_range + 1;
66003b705cfSriastradh	vld->vld0.f_code_0_1 = control->FVMV_range + 1;
66103b705cfSriastradh	vld->vld0.f_code_1_0 = control->BHMV_range + 1;
66203b705cfSriastradh	vld->vld0.f_code_1_1 = control->BVMV_range + 1;
66303b705cfSriastradh	vld->vld0.intra_dc_precision = control->intra_dc_precision;
66403b705cfSriastradh	vld->vld0.picture_structure = control->picture_structure;
66503b705cfSriastradh	vld->vld0.top_field_first = !!(control->flags & XVMC_TOP_FIELD_FIRST);
66603b705cfSriastradh	vld->vld0.frame_predict_frame_dct =
66703b705cfSriastradh	    !!(control->flags & XVMC_PRED_DCT_FRAME);
66803b705cfSriastradh	vld->vld0.concealment_motion_vector =
66903b705cfSriastradh	    !!(control->flags & XVMC_CONCEALMENT_MOTION_VECTORS);
67003b705cfSriastradh	vld->vld0.quantizer_scale_type = !!(control->flags & XVMC_Q_SCALE_TYPE);
67103b705cfSriastradh	vld->vld0.intra_vlc_format = !!(control->flags & XVMC_INTRA_VLC_FORMAT);
67203b705cfSriastradh	vld->vld0.scan_order = !!(control->flags & XVMC_ALTERNATE_SCAN);
67303b705cfSriastradh
67403b705cfSriastradh	vld->vld1.picture_coding_type = control->picture_coding_type;
67503b705cfSriastradh
67603b705cfSriastradh	vld->desc_remap_table0.index_0 = FRAME_INTRA;
67703b705cfSriastradh	vld->desc_remap_table0.index_1 = FRAME_FRAME_PRED_FORWARD;
67803b705cfSriastradh	vld->desc_remap_table0.index_2 = FRAME_FIELD_PRED_FORWARD;
67903b705cfSriastradh	vld->desc_remap_table0.index_3 = FRAME_FIELD_PRED_BIDIRECT;	/* dual prime */
68003b705cfSriastradh	vld->desc_remap_table0.index_4 = FRAME_FRAME_PRED_BACKWARD;
68103b705cfSriastradh	vld->desc_remap_table0.index_5 = FRAME_FIELD_PRED_BACKWARD;
68203b705cfSriastradh	vld->desc_remap_table0.index_6 = FRAME_FRAME_PRED_BIDIRECT;
68303b705cfSriastradh	vld->desc_remap_table0.index_7 = FRAME_FIELD_PRED_BIDIRECT;
68403b705cfSriastradh
68503b705cfSriastradh	vld->desc_remap_table1.index_8 = FRAME_INTRA;
68603b705cfSriastradh	vld->desc_remap_table1.index_9 = FRAME_FRAME_PRED_FORWARD;
68703b705cfSriastradh	vld->desc_remap_table1.index_10 = FRAME_FIELD_PRED_FORWARD;
68803b705cfSriastradh	vld->desc_remap_table1.index_11 = FRAME_FIELD_PRED_BIDIRECT;
68903b705cfSriastradh	vld->desc_remap_table1.index_12 = FRAME_FRAME_PRED_BACKWARD;
69003b705cfSriastradh	vld->desc_remap_table1.index_13 = FRAME_FIELD_PRED_BACKWARD;
69103b705cfSriastradh	vld->desc_remap_table1.index_14 = FRAME_FRAME_PRED_BIDIRECT;
69203b705cfSriastradh	vld->desc_remap_table1.index_15 = FRAME_FIELD_PRED_BIDIRECT;
69303b705cfSriastradh
69403b705cfSriastradh	drm_intel_bo_subdata(media_state.vld_state.bo, 0, sizeof(tmp), vld);
69503b705cfSriastradh	return Success;
69603b705cfSriastradh}
69703b705cfSriastradh
69803b705cfSriastradhstatic Status setup_media_surface(int index, dri_bo * bo,
69903b705cfSriastradh				  unsigned long offset, int w, int h,
70003b705cfSriastradh				  Bool write)
70103b705cfSriastradh{
70203b705cfSriastradh	struct brw_surface_state tmp, *ss = &tmp;
70303b705cfSriastradh	memset(ss, 0, sizeof(*ss));
70403b705cfSriastradh	ss->ss0.surface_type = BRW_SURFACE_2D;
70503b705cfSriastradh	ss->ss0.surface_format = BRW_SURFACEFORMAT_R8_SINT;
70603b705cfSriastradh	ss->ss1.base_addr = offset + bo->offset;
70703b705cfSriastradh	ss->ss2.width = w - 1;
70803b705cfSriastradh	ss->ss2.height = h - 1;
70903b705cfSriastradh	ss->ss3.pitch = w - 1;
71003b705cfSriastradh
71103b705cfSriastradh	if (media_state.binding_table.surface_states[index].bo)
71203b705cfSriastradh		drm_intel_bo_unreference(media_state.
71303b705cfSriastradh					 binding_table.surface_states[index].
71403b705cfSriastradh					 bo);
71503b705cfSriastradh
71603b705cfSriastradh	media_state.binding_table.surface_states[index].bo =
71703b705cfSriastradh	    drm_intel_bo_alloc(xvmc_driver->bufmgr, "surface_state",
71803b705cfSriastradh			       sizeof(struct brw_surface_state), 0x1000);
71903b705cfSriastradh	if (!media_state.binding_table.surface_states[index].bo)
72003b705cfSriastradh		return BadAlloc;
72103b705cfSriastradh
72203b705cfSriastradh	drm_intel_bo_subdata(media_state.binding_table.surface_states[index].bo,
72303b705cfSriastradh			     0, sizeof(*ss), ss);
72403b705cfSriastradh	drm_intel_bo_emit_reloc(media_state.binding_table.
72503b705cfSriastradh				surface_states[index].bo,
72603b705cfSriastradh				offsetof(struct brw_surface_state, ss1), bo,
72703b705cfSriastradh				offset, I915_GEM_DOMAIN_RENDER,
72803b705cfSriastradh				write ? I915_GEM_DOMAIN_RENDER : 0);
72903b705cfSriastradh	return Success;
73003b705cfSriastradh}
73103b705cfSriastradh
73203b705cfSriastradhstatic Status setup_surface(struct intel_xvmc_surface *target,
73303b705cfSriastradh			    struct intel_xvmc_surface *past,
73403b705cfSriastradh			    struct intel_xvmc_surface *future, int w, int h)
73503b705cfSriastradh{
73603b705cfSriastradh	Status ret;
73703b705cfSriastradh	ret = setup_media_surface(0, target->bo, 0, w, h, TRUE);
73803b705cfSriastradh	if (ret != Success)
73903b705cfSriastradh		return ret;
74003b705cfSriastradh	ret = setup_media_surface(1, target->bo, w * h, w / 2, h / 2, TRUE);
74103b705cfSriastradh	if (ret != Success)
74203b705cfSriastradh		return ret;
74303b705cfSriastradh	ret =
74403b705cfSriastradh	    setup_media_surface(2, target->bo, w * h + w * h / 4, w / 2, h / 2,
74503b705cfSriastradh				TRUE);
74603b705cfSriastradh	if (ret != Success)
74703b705cfSriastradh		return ret;
74803b705cfSriastradh	if (past) {
74903b705cfSriastradh		ret = setup_media_surface(4, past->bo, 0, w, h, FALSE);
75003b705cfSriastradh		if (ret != Success)
75103b705cfSriastradh			return ret;
75203b705cfSriastradh		ret =
75303b705cfSriastradh		    setup_media_surface(5, past->bo, w * h, w / 2, h / 2,
75403b705cfSriastradh					FALSE);
75503b705cfSriastradh		if (ret != Success)
75603b705cfSriastradh			return ret;
75703b705cfSriastradh		ret =
75803b705cfSriastradh		    setup_media_surface(6, past->bo, w * h + w * h / 4, w / 2,
75903b705cfSriastradh					h / 2, FALSE);
76003b705cfSriastradh		if (ret != Success)
76103b705cfSriastradh			return ret;
76203b705cfSriastradh	}
76303b705cfSriastradh	if (future) {
76403b705cfSriastradh		ret = setup_media_surface(7, future->bo, 0, w, h, FALSE);
76503b705cfSriastradh		if (ret != Success)
76603b705cfSriastradh			return ret;
76703b705cfSriastradh		ret =
76803b705cfSriastradh		    setup_media_surface(8, future->bo, w * h, w / 2, h / 2,
76903b705cfSriastradh					FALSE);
77003b705cfSriastradh		if (ret != Success)
77103b705cfSriastradh			return ret;
77203b705cfSriastradh		ret =
77303b705cfSriastradh		    setup_media_surface(9, future->bo, w * h + w * h / 4, w / 2,
77403b705cfSriastradh					h / 2, FALSE);
77503b705cfSriastradh		if (ret != Success)
77603b705cfSriastradh			return ret;
77703b705cfSriastradh	}
77803b705cfSriastradh	return Success;
77903b705cfSriastradh}
78003b705cfSriastradh
78103b705cfSriastradhstatic Status begin_surface(Display * display, XvMCContext * context,
78203b705cfSriastradh			    XvMCSurface * target,
78303b705cfSriastradh			    XvMCSurface * past,
78403b705cfSriastradh			    XvMCSurface * future,
78503b705cfSriastradh			    const XvMCMpegControl * control)
78603b705cfSriastradh{
78703b705cfSriastradh	struct intel_xvmc_surface *priv_target, *priv_past, *priv_future;
78803b705cfSriastradh	intel_xvmc_context_ptr intel_ctx = context->privData;
78903b705cfSriastradh	Status ret;
79003b705cfSriastradh
79103b705cfSriastradh	priv_target = target->privData;
79203b705cfSriastradh	priv_past = past ? past->privData : NULL;
79303b705cfSriastradh	priv_future = future ? future->privData : NULL;
79403b705cfSriastradh
79503b705cfSriastradh	ret = vld_state(control);
79603b705cfSriastradh	if (ret != Success)
79703b705cfSriastradh		return ret;
79803b705cfSriastradh	ret = setup_surface(priv_target, priv_past, priv_future,
79903b705cfSriastradh			    context->width, context->height);
80003b705cfSriastradh	if (ret != Success)
80103b705cfSriastradh		return ret;
80203b705cfSriastradh	ret = binding_tables();
80303b705cfSriastradh	if (ret != Success)
80403b705cfSriastradh		return ret;
80503b705cfSriastradh	ret = interface_descriptor();
80603b705cfSriastradh	if (ret != Success)
80703b705cfSriastradh		return ret;
80803b705cfSriastradh	ret = vfe_state(VFE_VLD_MODE);
80903b705cfSriastradh	if (ret != Success)
81003b705cfSriastradh		return ret;
81103b705cfSriastradh
81203b705cfSriastradh	LOCK_HARDWARE(intel_ctx->hw_context);
81303b705cfSriastradh	flush();
81403b705cfSriastradh	UNLOCK_HARDWARE(intel_ctx->hw_context);
81503b705cfSriastradh	return Success;
81603b705cfSriastradh}
81703b705cfSriastradh
81803b705cfSriastradhstatic Status put_slice(Display * display, XvMCContext * context,
81903b705cfSriastradh			unsigned char *slice, int nbytes)
82003b705cfSriastradh{
82103b705cfSriastradh	return Success;
82203b705cfSriastradh}
82303b705cfSriastradh
82403b705cfSriastradhstatic void state_base_address(struct intel_xvmc_hw_context *ctx)
82503b705cfSriastradh{
82603b705cfSriastradh	BATCH_LOCALS;
82703b705cfSriastradh
82803b705cfSriastradh	if (ctx->i965.is_igdng) {
82903b705cfSriastradh		BEGIN_BATCH(8);
83003b705cfSriastradh		OUT_BATCH(BRW_STATE_BASE_ADDRESS | 6);
83103b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83203b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83303b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83403b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83503b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83603b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83703b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
83803b705cfSriastradh		ADVANCE_BATCH();
83903b705cfSriastradh	} else {
84003b705cfSriastradh		BEGIN_BATCH(6);
84103b705cfSriastradh		OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
84203b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
84303b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
84403b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
84503b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
84603b705cfSriastradh		OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
84703b705cfSriastradh		ADVANCE_BATCH();
84803b705cfSriastradh	}
84903b705cfSriastradh}
85003b705cfSriastradh
85103b705cfSriastradhstatic void pipeline_select()
85203b705cfSriastradh{
85303b705cfSriastradh	BATCH_LOCALS;
85403b705cfSriastradh	BEGIN_BATCH(1);
85503b705cfSriastradh	OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
85603b705cfSriastradh	ADVANCE_BATCH();
85703b705cfSriastradh}
85803b705cfSriastradh
85903b705cfSriastradhstatic void media_state_pointers(int vfe_mode)
86003b705cfSriastradh{
86103b705cfSriastradh	BATCH_LOCALS;
86203b705cfSriastradh	BEGIN_BATCH(3);
86303b705cfSriastradh	OUT_BATCH(BRW_MEDIA_STATE_POINTERS | 1);
86403b705cfSriastradh	if (vfe_mode == VFE_VLD_MODE)
86503b705cfSriastradh		OUT_RELOC(media_state.vld_state.bo, I915_GEM_DOMAIN_INSTRUCTION,
86603b705cfSriastradh			  0, 1);
86703b705cfSriastradh	else
86803b705cfSriastradh		OUT_BATCH(0);
86903b705cfSriastradh	OUT_RELOC(media_state.vfe_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
87003b705cfSriastradh	ADVANCE_BATCH();
87103b705cfSriastradh}
87203b705cfSriastradh
87303b705cfSriastradhstatic void align_urb_fence()
87403b705cfSriastradh{
87503b705cfSriastradh	BATCH_LOCALS;
87603b705cfSriastradh	int i, offset_to_next_cacheline;
87703b705cfSriastradh	unsigned long batch_offset;
87803b705cfSriastradh	BEGIN_BATCH(3);
87903b705cfSriastradh	batch_offset = (void *)batch_ptr - xvmc_driver->alloc.ptr;
88003b705cfSriastradh	offset_to_next_cacheline = ALIGN(batch_offset, 64) - batch_offset;
88103b705cfSriastradh	if (offset_to_next_cacheline <= 12 && offset_to_next_cacheline != 0) {
88203b705cfSriastradh		for (i = 0; i < offset_to_next_cacheline / 4; i++)
88303b705cfSriastradh			OUT_BATCH(0);
88403b705cfSriastradh		ADVANCE_BATCH();
88503b705cfSriastradh	}
88603b705cfSriastradh}
88703b705cfSriastradh
88803b705cfSriastradhstatic void urb_layout()
88903b705cfSriastradh{
89003b705cfSriastradh	BATCH_LOCALS;
89103b705cfSriastradh	align_urb_fence();
89203b705cfSriastradh	BEGIN_BATCH(3);
89303b705cfSriastradh	OUT_BATCH(BRW_URB_FENCE |
89403b705cfSriastradh		  UF0_VFE_REALLOC |
89503b705cfSriastradh		  UF0_CS_REALLOC |
89603b705cfSriastradh		  UF0_SF_REALLOC |
89703b705cfSriastradh		  UF0_CLIP_REALLOC | UF0_GS_REALLOC | UF0_VS_REALLOC | 1);
89803b705cfSriastradh
89903b705cfSriastradh	OUT_BATCH((0 << UF1_CLIP_FENCE_SHIFT) |
90003b705cfSriastradh		  (0 << UF1_GS_FENCE_SHIFT) | (0 << UF1_VS_FENCE_SHIFT));
90103b705cfSriastradh
90203b705cfSriastradh	OUT_BATCH((0 << UF2_CS_FENCE_SHIFT) | (0 << UF2_SF_FENCE_SHIFT) | ((URB_SIZE - CS_SIZE - 1) << UF2_VFE_FENCE_SHIFT) |	/* VFE_SIZE */
90303b705cfSriastradh		  ((URB_SIZE) << UF2_CS_FENCE_SHIFT));	/* CS_SIZE */
90403b705cfSriastradh	ADVANCE_BATCH();
90503b705cfSriastradh}
90603b705cfSriastradh
90703b705cfSriastradhstatic void cs_urb_layout()
90803b705cfSriastradh{
90903b705cfSriastradh	BATCH_LOCALS;
91003b705cfSriastradh	BEGIN_BATCH(2);
91103b705cfSriastradh	OUT_BATCH(BRW_CS_URB_STATE | 0);
91203b705cfSriastradh	OUT_BATCH((CS_SIZE << 4) |	/* URB Entry Allocation Size */
91303b705cfSriastradh		  (1 << 0));	/* Number of URB Entries */
91403b705cfSriastradh	ADVANCE_BATCH();
91503b705cfSriastradh}
91603b705cfSriastradh
91703b705cfSriastradhstatic void cs_buffer()
91803b705cfSriastradh{
91903b705cfSriastradh	BATCH_LOCALS;
92003b705cfSriastradh	BEGIN_BATCH(2);
92103b705cfSriastradh	OUT_BATCH(BRW_CONSTANT_BUFFER | 0 | (1 << 8));
92203b705cfSriastradh	OUT_RELOC(media_state.cs_object.bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
92303b705cfSriastradh		  CS_SIZE);
92403b705cfSriastradh	ADVANCE_BATCH();
92503b705cfSriastradh}
92603b705cfSriastradh
92703b705cfSriastradh/* kick media object to gpu in idct mode*/
92803b705cfSriastradhstatic void send_media_object(XvMCMacroBlock * mb, dri_bo * bo,
92903b705cfSriastradh			      uint32_t offset, enum interface interface)
93003b705cfSriastradh{
93103b705cfSriastradh	BATCH_LOCALS;
93203b705cfSriastradh	BEGIN_BATCH(13);
93303b705cfSriastradh	OUT_BATCH(BRW_MEDIA_OBJECT | 11);
93403b705cfSriastradh	OUT_BATCH(interface);
93503b705cfSriastradh	OUT_BATCH(6 * 128);
93603b705cfSriastradh	OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
93703b705cfSriastradh
93803b705cfSriastradh	OUT_BATCH(mb->x << 4);
93903b705cfSriastradh	OUT_BATCH(mb->y << 4);
94003b705cfSriastradh	OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, offset);
94103b705cfSriastradh	OUT_BATCH_SHORT(mb->coded_block_pattern);
94203b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][0][0]);
94303b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][0][1]);
94403b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][1][0]);
94503b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[0][1][1]);
94603b705cfSriastradh
94703b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][0][0]);
94803b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][0][1]);
94903b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][1][0]);
95003b705cfSriastradh	OUT_BATCH_SHORT(mb->PMV[1][1][1]);
95103b705cfSriastradh	OUT_BATCH_CHAR(mb->dct_type);
95203b705cfSriastradh	OUT_BATCH_CHAR(mb->motion_vertical_field_select);
95303b705cfSriastradh
95403b705cfSriastradh	OUT_BATCH(0xffffffff);
95503b705cfSriastradh	ADVANCE_BATCH();
95603b705cfSriastradh}
95703b705cfSriastradh
95803b705cfSriastradh/* kick media object to gpu in vld mode*/
95903b705cfSriastradhstatic void vld_send_media_object(dri_bo * bo,
96003b705cfSriastradh				  int slice_len, int mb_h_pos, int mb_v_pos,
96103b705cfSriastradh				  int mb_bit_offset, int mb_count,
96203b705cfSriastradh				  int q_scale_code)
96303b705cfSriastradh{
96403b705cfSriastradh	BATCH_LOCALS;
96503b705cfSriastradh	BEGIN_BATCH(6);
96603b705cfSriastradh	OUT_BATCH(BRW_MEDIA_OBJECT | 4);
96703b705cfSriastradh	OUT_BATCH(0);
96803b705cfSriastradh	OUT_BATCH(slice_len);
96903b705cfSriastradh	OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
97003b705cfSriastradh	OUT_BATCH((mb_h_pos << 24) | (mb_v_pos << 16) | (mb_count << 8) |
97103b705cfSriastradh		  (mb_bit_offset));
97203b705cfSriastradh	OUT_BATCH(q_scale_code << 24);
97303b705cfSriastradh	ADVANCE_BATCH();
97403b705cfSriastradh}
97503b705cfSriastradh
97603b705cfSriastradhstatic Status put_slice2(Display * display, XvMCContext * context,
97703b705cfSriastradh			 unsigned char *slice, int nbytes, int sliceCode)
97803b705cfSriastradh{
97903b705cfSriastradh	unsigned int bit_buf;
98003b705cfSriastradh	intel_xvmc_context_ptr intel_ctx = context->privData;
98103b705cfSriastradh	struct intel_xvmc_hw_context *hw_ctx = intel_ctx->hw;
98203b705cfSriastradh	int q_scale_code, mb_row;
98303b705cfSriastradh
98403b705cfSriastradh	mb_row = *(slice - 1) - 1;
98503b705cfSriastradh	bit_buf =
98603b705cfSriastradh	    (slice[0] << 24) | (slice[1] << 16) | (slice[2] << 8) | (slice[3]);
98703b705cfSriastradh
98803b705cfSriastradh	q_scale_code = bit_buf >> 27;
98903b705cfSriastradh
99003b705cfSriastradh	if (media_state.slice_data.bo) {
99103b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(media_state.slice_data.bo);
99203b705cfSriastradh
99303b705cfSriastradh		drm_intel_bo_unreference(media_state.slice_data.bo);
99403b705cfSriastradh	}
99503b705cfSriastradh	media_state.slice_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
99603b705cfSriastradh						       "slice data",
99703b705cfSriastradh						       VLD_MAX_SLICE_SIZE, 64);
99803b705cfSriastradh	if (!media_state.slice_data.bo)
99903b705cfSriastradh		return BadAlloc;
100003b705cfSriastradh	drm_intel_gem_bo_map_gtt(media_state.slice_data.bo);
100103b705cfSriastradh
100203b705cfSriastradh	memcpy(media_state.slice_data.bo->virtual, slice, nbytes);
100303b705cfSriastradh
100403b705cfSriastradh	LOCK_HARDWARE(intel_ctx->hw_context);
100503b705cfSriastradh	state_base_address(hw_ctx);
100603b705cfSriastradh	pipeline_select();
100703b705cfSriastradh	media_state_pointers(VFE_VLD_MODE);
100803b705cfSriastradh	urb_layout();
100903b705cfSriastradh	cs_urb_layout();
101003b705cfSriastradh	cs_buffer();
101103b705cfSriastradh	vld_send_media_object(media_state.slice_data.bo,
101203b705cfSriastradh			      nbytes, 0, mb_row, 6, 127, q_scale_code);
101342542f5fSchristos	intelFlushBatch();
101403b705cfSriastradh	UNLOCK_HARDWARE(intel_ctx->hw_context);
101503b705cfSriastradh
101603b705cfSriastradh	return Success;
101703b705cfSriastradh}
101803b705cfSriastradh
101903b705cfSriastradhstatic Status render_surface(Display * display,
102003b705cfSriastradh			     XvMCContext * context,
102103b705cfSriastradh			     unsigned int picture_structure,
102203b705cfSriastradh			     XvMCSurface * target_surface,
102303b705cfSriastradh			     XvMCSurface * past_surface,
102403b705cfSriastradh			     XvMCSurface * future_surface,
102503b705cfSriastradh			     unsigned int flags,
102603b705cfSriastradh			     unsigned int num_macroblocks,
102703b705cfSriastradh			     unsigned int first_macroblock,
102803b705cfSriastradh			     XvMCMacroBlockArray * macroblock_array,
102903b705cfSriastradh			     XvMCBlockArray * blocks)
103003b705cfSriastradh{
103103b705cfSriastradh	struct intel_xvmc_surface *priv_target, *priv_past, *priv_future;
103203b705cfSriastradh	intel_xvmc_context_ptr intel_ctx;
103303b705cfSriastradh	XvMCMacroBlock *mb;
103403b705cfSriastradh	Status ret;
103503b705cfSriastradh	unsigned short *block_ptr;
103603b705cfSriastradh	int i, j;
103703b705cfSriastradh	int block_offset = 0;
103803b705cfSriastradh	struct intel_xvmc_hw_context *hw_ctx;
103903b705cfSriastradh
104003b705cfSriastradh	intel_ctx = context->privData;
104103b705cfSriastradh
104203b705cfSriastradh	hw_ctx = (struct intel_xvmc_hw_context *)context->privData;
104303b705cfSriastradh	priv_target = target_surface->privData;
104403b705cfSriastradh	priv_past = past_surface ? past_surface->privData : NULL;
104503b705cfSriastradh	priv_future = future_surface ? future_surface->privData : NULL;
104603b705cfSriastradh
104703b705cfSriastradh	ret = setup_surface(priv_target, priv_past, priv_future,
104803b705cfSriastradh			    context->width, context->height);
104903b705cfSriastradh	if (ret != Success)
105003b705cfSriastradh		return ret;
105103b705cfSriastradh	ret = binding_tables();
105203b705cfSriastradh	if (ret != Success)
105303b705cfSriastradh		return ret;
105403b705cfSriastradh	ret = interface_descriptor();
105503b705cfSriastradh	if (ret != Success)
105603b705cfSriastradh		return ret;
105703b705cfSriastradh	ret = cs_init(INTERFACE_NUM);
105803b705cfSriastradh	if (ret != Success)
105903b705cfSriastradh		return ret;
106003b705cfSriastradh	ret = vfe_state(VFE_GENERIC_MODE);
106103b705cfSriastradh	if (ret != Success)
106203b705cfSriastradh		return ret;
106303b705cfSriastradh
106403b705cfSriastradh	if (media_state.mb_data.bo) {
106503b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(media_state.mb_data.bo);
106603b705cfSriastradh
106703b705cfSriastradh		drm_intel_bo_unreference(media_state.mb_data.bo);
106803b705cfSriastradh	}
106903b705cfSriastradh	unsigned int block_num =
107003b705cfSriastradh	    (((context->width + 15) >> 4) * ((context->height + 15) >> 4));
107103b705cfSriastradh	unsigned int surface_size = (64 * sizeof(short) * 6 * block_num);
107203b705cfSriastradh	media_state.mb_data.bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
107303b705cfSriastradh						    "macroblock data",
107403b705cfSriastradh						    surface_size, 64);
107503b705cfSriastradh	if (!media_state.mb_data.bo)
107603b705cfSriastradh		return BadAlloc;
107703b705cfSriastradh	drm_intel_gem_bo_map_gtt(media_state.mb_data.bo);
107803b705cfSriastradh
107903b705cfSriastradh	block_ptr = media_state.mb_data.bo->virtual;
108003b705cfSriastradh	unsigned short *mb_block_ptr;
108103b705cfSriastradh	for (i = first_macroblock; i < num_macroblocks + first_macroblock; i++) {
108203b705cfSriastradh		mb = &macroblock_array->macro_blocks[i];
108303b705cfSriastradh		mb_block_ptr = &blocks->blocks[(mb->index << 6)];
108403b705cfSriastradh
108503b705cfSriastradh		if (mb->coded_block_pattern & 0x20) {
108603b705cfSriastradh			for (j = 0; j < 8; j++)
108703b705cfSriastradh				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
108803b705cfSriastradh				       16);
108903b705cfSriastradh			mb_block_ptr += 64;
109003b705cfSriastradh		}
109103b705cfSriastradh		if (mb->coded_block_pattern & 0x10) {
109203b705cfSriastradh			for (j = 0; j < 8; j++)
109303b705cfSriastradh				memcpy(block_ptr + 16 * j + 8,
109403b705cfSriastradh				       mb_block_ptr + 8 * j, 16);
109503b705cfSriastradh			mb_block_ptr += 64;
109603b705cfSriastradh		}
109703b705cfSriastradh
109803b705cfSriastradh		block_ptr += 2 * 64;
109903b705cfSriastradh		if (mb->coded_block_pattern & 0x08) {
110003b705cfSriastradh			for (j = 0; j < 8; j++)
110103b705cfSriastradh				memcpy(block_ptr + 16 * j, mb_block_ptr + 8 * j,
110203b705cfSriastradh				       16);
110303b705cfSriastradh			mb_block_ptr += 64;
110403b705cfSriastradh		}
110503b705cfSriastradh		if (mb->coded_block_pattern & 0x04) {
110603b705cfSriastradh			for (j = 0; j < 8; j++)
110703b705cfSriastradh				memcpy(block_ptr + 16 * j + 8,
110803b705cfSriastradh				       mb_block_ptr + 8 * j, 16);
110903b705cfSriastradh			mb_block_ptr += 64;
111003b705cfSriastradh		}
111103b705cfSriastradh
111203b705cfSriastradh		block_ptr += 2 * 64;
111303b705cfSriastradh		if (mb->coded_block_pattern & 0x2) {
111403b705cfSriastradh			memcpy(block_ptr, mb_block_ptr, 128);
111503b705cfSriastradh			mb_block_ptr += 64;
111603b705cfSriastradh		}
111703b705cfSriastradh
111803b705cfSriastradh		block_ptr += 64;
111903b705cfSriastradh		if (mb->coded_block_pattern & 0x1)
112003b705cfSriastradh			memcpy(block_ptr, mb_block_ptr, 128);
112103b705cfSriastradh		block_ptr += 64;
112203b705cfSriastradh	}
112303b705cfSriastradh
112403b705cfSriastradh	LOCK_HARDWARE(intel_ctx->hw_context);
112503b705cfSriastradh	state_base_address(hw_ctx);
112603b705cfSriastradh	flush();
112703b705cfSriastradh	pipeline_select();
112803b705cfSriastradh	urb_layout();
112903b705cfSriastradh	media_state_pointers(VFE_GENERIC_MODE);
113003b705cfSriastradh	cs_urb_layout();
113103b705cfSriastradh	cs_buffer();
113203b705cfSriastradh	for (i = first_macroblock;
113303b705cfSriastradh	     i < num_macroblocks + first_macroblock;
113403b705cfSriastradh	     i++, block_offset += 128 * 6) {
113503b705cfSriastradh		mb = &macroblock_array->macro_blocks[i];
113603b705cfSriastradh
113703b705cfSriastradh		if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
113803b705cfSriastradh			send_media_object(mb, media_state.mb_data.bo,
113903b705cfSriastradh					  block_offset,
114003b705cfSriastradh					  FRAME_INTRA + INTERFACE_NUM);
114103b705cfSriastradh		} else {
114203b705cfSriastradh			if (((mb->motion_type & 3) == XVMC_PREDICTION_FRAME)) {
114303b705cfSriastradh				if ((mb->macroblock_type &
114403b705cfSriastradh				     XVMC_MB_TYPE_MOTION_FORWARD)) {
114503b705cfSriastradh					if ((mb->macroblock_type &
114603b705cfSriastradh					     XVMC_MB_TYPE_MOTION_BACKWARD)) {
114703b705cfSriastradh						send_media_object(mb,
114803b705cfSriastradh								  media_state.mb_data.
114903b705cfSriastradh								  bo,
115003b705cfSriastradh								  block_offset,
115103b705cfSriastradh								  FRAME_FRAME_PRED_BIDIRECT
115203b705cfSriastradh								  +
115303b705cfSriastradh								  INTERFACE_NUM);
115403b705cfSriastradh					} else {
115503b705cfSriastradh						send_media_object(mb,
115603b705cfSriastradh								  media_state.mb_data.
115703b705cfSriastradh								  bo,
115803b705cfSriastradh								  block_offset,
115903b705cfSriastradh								  FRAME_FRAME_PRED_FORWARD
116003b705cfSriastradh								  +
116103b705cfSriastradh								  INTERFACE_NUM);
116203b705cfSriastradh					}
116303b705cfSriastradh				} else
116403b705cfSriastradh				    if ((mb->macroblock_type &
116503b705cfSriastradh					 XVMC_MB_TYPE_MOTION_BACKWARD)) {
116603b705cfSriastradh					send_media_object(mb,
116703b705cfSriastradh							  media_state.
116803b705cfSriastradh							  mb_data.bo,
116903b705cfSriastradh							  block_offset,
117003b705cfSriastradh							  FRAME_FRAME_PRED_BACKWARD
117103b705cfSriastradh							  + INTERFACE_NUM);
117203b705cfSriastradh				}
117303b705cfSriastradh			} else if ((mb->motion_type & 3) ==
117403b705cfSriastradh				   XVMC_PREDICTION_FIELD) {
117503b705cfSriastradh				if ((mb->macroblock_type &
117603b705cfSriastradh				     XVMC_MB_TYPE_MOTION_FORWARD)) {
117703b705cfSriastradh					if (((mb->macroblock_type &
117803b705cfSriastradh					      XVMC_MB_TYPE_MOTION_BACKWARD))) {
117903b705cfSriastradh						send_media_object(mb,
118003b705cfSriastradh								  media_state.mb_data.
118103b705cfSriastradh								  bo,
118203b705cfSriastradh								  block_offset,
118303b705cfSriastradh								  FRAME_FIELD_PRED_BIDIRECT
118403b705cfSriastradh								  +
118503b705cfSriastradh								  INTERFACE_NUM);
118603b705cfSriastradh					} else {
118703b705cfSriastradh						send_media_object(mb,
118803b705cfSriastradh								  media_state.mb_data.
118903b705cfSriastradh								  bo,
119003b705cfSriastradh								  block_offset,
119103b705cfSriastradh								  FRAME_FIELD_PRED_FORWARD
119203b705cfSriastradh								  +
119303b705cfSriastradh								  INTERFACE_NUM);
119403b705cfSriastradh					}
119503b705cfSriastradh				} else
119603b705cfSriastradh				    if ((mb->macroblock_type &
119703b705cfSriastradh					 XVMC_MB_TYPE_MOTION_BACKWARD)) {
119803b705cfSriastradh					send_media_object(mb,
119903b705cfSriastradh							  media_state.
120003b705cfSriastradh							  mb_data.bo,
120103b705cfSriastradh							  block_offset,
120203b705cfSriastradh							  FRAME_FIELD_PRED_BACKWARD
120303b705cfSriastradh							  + INTERFACE_NUM);
120403b705cfSriastradh				}
120503b705cfSriastradh			} else {
120603b705cfSriastradh				send_media_object(mb, media_state.mb_data.bo, block_offset, FRAME_FIELD_PRED_BIDIRECT + INTERFACE_NUM);	/*dual prime */
120703b705cfSriastradh			}
120803b705cfSriastradh		}
120903b705cfSriastradh	}
121042542f5fSchristos	intelFlushBatch();
121103b705cfSriastradh	UNLOCK_HARDWARE(intel_ctx->hw_context);
121203b705cfSriastradh	return Success;
121303b705cfSriastradh}
121403b705cfSriastradh
121503b705cfSriastradhstruct _intel_xvmc_driver xvmc_vld_driver = {
121603b705cfSriastradh	.type = XVMC_I965_MPEG2_VLD,
121703b705cfSriastradh	.create_context = create_context,
121803b705cfSriastradh	.destroy_context = destroy_context,
121903b705cfSriastradh	.load_qmatrix = load_qmatrix,
122003b705cfSriastradh	.begin_surface = begin_surface,
122103b705cfSriastradh	.render_surface = render_surface,
122203b705cfSriastradh	.put_slice = put_slice,
122303b705cfSriastradh	.put_slice2 = put_slice2
122403b705cfSriastradh};
1225