100ed9b5ff4b781f6e03bce201864bc7f7b3ab92
[platform/upstream/libva-intel-driver.git] / src / i965_drv_video.c
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
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Xiang Haihao <haihao.xiang@intel.com>
26  *    Zou Nan hai <nanhai.zou@intel.com>
27  *
28  */
29
30 #include "sysdeps.h"
31
32 #ifdef HAVE_VA_X11
33 # include "i965_output_dri.h"
34 #endif
35
36 #ifdef HAVE_VA_WAYLAND
37 # include "i965_output_wayland.h"
38 #endif
39
40 #include "intel_driver.h"
41 #include "intel_memman.h"
42 #include "intel_batchbuffer.h"
43 #include "i965_defines.h"
44 #include "i965_drv_video.h"
45 #include "i965_decoder.h"
46 #include "i965_encoder.h"
47
48 #define CONFIG_ID_OFFSET                0x01000000
49 #define CONTEXT_ID_OFFSET               0x02000000
50 #define SURFACE_ID_OFFSET               0x04000000
51 #define BUFFER_ID_OFFSET                0x08000000
52 #define IMAGE_ID_OFFSET                 0x0a000000
53 #define SUBPIC_ID_OFFSET                0x10000000
54
55 #define HAS_MPEG2_DECODING(ctx)  ((ctx)->codec_info->has_mpeg2_decoding && \
56                                   (ctx)->intel.has_bsd)
57
58 #define HAS_MPEG2_ENCODING(ctx)  ((ctx)->codec_info->has_mpeg2_encoding && \
59                                   (ctx)->intel.has_bsd)
60
61 #define HAS_H264_DECODING(ctx)  ((ctx)->codec_info->has_h264_decoding && \
62                                  (ctx)->intel.has_bsd)
63
64 #define HAS_H264_ENCODING(ctx)  ((ctx)->codec_info->has_h264_encoding && \
65                                  (ctx)->intel.has_bsd)
66
67 #define HAS_VC1_DECODING(ctx)   ((ctx)->codec_info->has_vc1_decoding && \
68                                  (ctx)->intel.has_bsd)
69
70 #define HAS_JPEG_DECODING(ctx)  ((ctx)->codec_info->has_jpeg_decoding && \
71                                  (ctx)->intel.has_bsd)
72
73 #define HAS_VPP(ctx)    ((ctx)->codec_info->has_vpp)
74
75 #define HAS_ACCELERATED_GETIMAGE(ctx)   ((ctx)->codec_info->has_accelerated_getimage)
76
77 #define HAS_ACCELERATED_PUTIMAGE(ctx)   ((ctx)->codec_info->has_accelerated_putimage)
78
79 #define HAS_TILED_SURFACE(ctx) ((ctx)->codec_info->has_tiled_surface)
80
81 #define HAS_VP8_DECODING(ctx)   ((ctx)->codec_info->has_vp8_decoding && \
82                                  (ctx)->intel.has_bsd)
83
84 #define HAS_VP8_ENCODING(ctx)   ((ctx)->codec_info->has_vp8_encoding && \
85                                  (ctx)->intel.has_bsd)
86
87 #define HAS_H264_MVC_DECODING(ctx) \
88     (HAS_H264_DECODING(ctx) && (ctx)->codec_info->h264_mvc_dec_profiles)
89
90 #define HAS_H264_MVC_DECODING_PROFILE(ctx, profile)                     \
91     (HAS_H264_MVC_DECODING(ctx) &&                                      \
92      ((ctx)->codec_info->h264_mvc_dec_profiles & (1U << profile)))
93
94 #define HAS_H264_MVC_ENCODING(ctx)  ((ctx)->codec_info->has_h264_mvc_encoding && \
95                                      (ctx)->intel.has_bsd)
96
97 static int get_sampling_from_fourcc(unsigned int fourcc);
98
99 /* Check whether we are rendering to X11 (VA/X11 or VA/GLX API) */
100 #define IS_VA_X11(ctx) \
101     (((ctx)->display_type & VA_DISPLAY_MAJOR_MASK) == VA_DISPLAY_X11)
102
103 /* Check whether we are rendering to Wayland */
104 #define IS_VA_WAYLAND(ctx) \
105     (((ctx)->display_type & VA_DISPLAY_MAJOR_MASK) == VA_DISPLAY_WAYLAND)
106
107 #define I965_BIT        1
108 #define I965_2BITS      (I965_BIT << 1)
109 #define I965_4BITS      (I965_BIT << 2)
110 #define I965_8BITS      (I965_BIT << 3)
111 #define I965_16BITS     (I965_BIT << 4)
112 #define I965_32BITS     (I965_BIT << 5)
113
114 #define PLANE_0         0
115 #define PLANE_1         1
116 #define PLANE_2         2
117
118 #define OFFSET_0        0
119 #define OFFSET_4        4
120 #define OFFSET_8        8
121 #define OFFSET_16       16
122 #define OFFSET_24       24
123
124 /* hfactor, vfactor, num_planes, bpp[], num_components, components[] */
125 #define I_NV12  2, 2, 2, {I965_8BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_1, OFFSET_8} }
126 #define I_I420  2, 2, 3, {I965_8BITS, I965_2BITS, I965_2BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
127 #define I_IYUV  I_I420
128 #define I_IMC3  I_I420
129 #define I_YV12  2, 2, 3, {I965_8BITS, I965_2BITS, I965_2BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_2, OFFSET_0}, {PLANE_1, OFFSET_0} }
130 #define I_IMC1  I_YV12
131
132 #define I_422H  2, 1, 3, {I965_8BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
133 #define I_422V  1, 2, 3, {I965_8BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
134 #define I_YV16  2, 1, 3, {I965_8BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_2, OFFSET_0}, {PLANE_1, OFFSET_0} }
135 #define I_YUY2  2, 1, 1, {I965_32BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_24} }
136 #define I_UYVY  2, 1, 1, {I965_32BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_16} }
137
138 #define I_444P  1, 1, 3, {I965_8BITS, I965_8BITS, I965_8BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
139
140 #define I_411P  4, 1, 3, {I965_8BITS, I965_2BITS, I965_2BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
141
142 #define I_Y800  1, 1, 1, {I965_8BITS}, 1, { {PLANE_0, OFFSET_0} }
143
144 #define I_RGBA  1, 1, 1, {I965_32BITS}, 4, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_16}, {PLANE_0, OFFSET_24} }
145 #define I_RGBX  1, 1, 1, {I965_32BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_16} }
146 #define I_BGRA  1, 1, 1, {I965_32BITS}, 4, { {PLANE_0, OFFSET_16}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_24} }
147 #define I_BGRX  1, 1, 1, {I965_32BITS}, 3, { {PLANE_0, OFFSET_16}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_0} }
148
149 #define I_ARGB  1, 1, 1, {I965_32BITS}, 4, { {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_16}, {PLANE_0, OFFSET_24}, {PLANE_0, OFFSET_0} }
150 #define I_ABGR  1, 1, 1, {I965_32BITS}, 4, { {PLANE_0, OFFSET_24}, {PLANE_0, OFFSET_16}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_0} }
151
152 #define I_IA88  1, 1, 1, {I965_16BITS}, 2, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8} }
153 #define I_AI88  1, 1, 1, {I965_16BITS}, 2, { {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_0} }
154
155 #define I_IA44  1, 1, 1, {I965_8BITS}, 2, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_4} }
156 #define I_AI44  1, 1, 1, {I965_8BITS}, 2, { {PLANE_0, OFFSET_4}, {PLANE_0, OFFSET_0} }
157
158 /* flag */
159 #define I_S             1
160 #define I_I             2
161 #define I_SI            (I_S | I_I)
162
163 #define DEF_FOUCC_INFO(FOURCC, FORMAT, SUB, FLAG)       { VA_FOURCC_##FOURCC, I965_COLOR_##FORMAT, SUBSAMPLE_##SUB, FLAG, I_##FOURCC }
164 #define DEF_YUV(FOURCC, SUB, FLAG)                      DEF_FOUCC_INFO(FOURCC, YUV, SUB, FLAG)
165 #define DEF_RGB(FOURCC, SUB, FLAG)                      DEF_FOUCC_INFO(FOURCC, RGB, SUB, FLAG)
166 #define DEF_INDEX(FOURCC, SUB, FLAG)                    DEF_FOUCC_INFO(FOURCC, INDEX, SUB, FLAG)
167
168 static const i965_fourcc_info i965_fourcc_infos[] = {
169     DEF_YUV(NV12, YUV420, I_SI),
170     DEF_YUV(I420, YUV420, I_SI),
171     DEF_YUV(IYUV, YUV420, I_S),
172     DEF_YUV(IMC3, YUV420, I_S),
173     DEF_YUV(YV12, YUV420, I_SI),
174     DEF_YUV(IMC1, YUV420, I_S),
175
176     DEF_YUV(422H, YUV422H, I_SI),
177     DEF_YUV(422V, YUV422V, I_S),
178     DEF_YUV(YV16, YUV422H, I_S),
179     DEF_YUV(YUY2, YUV422H, I_SI),
180     DEF_YUV(UYVY, YUV422H, I_SI),
181
182     DEF_YUV(444P, YUV444, I_S),
183
184     DEF_YUV(411P, YUV411, I_S),
185
186     DEF_YUV(Y800, YUV400, I_S),
187
188     DEF_RGB(RGBA, RGBX, I_SI),
189     DEF_RGB(RGBX, RGBX, I_SI),
190     DEF_RGB(BGRA, RGBX, I_SI),
191     DEF_RGB(BGRX, RGBX, I_SI),
192
193     DEF_RGB(ARGB, RGBX, I_I),
194     DEF_RGB(ABGR, RGBX, I_I),
195
196     DEF_INDEX(IA88, RGBX, I_I),
197     DEF_INDEX(AI88, RGBX, I_I),
198
199     DEF_INDEX(IA44, RGBX, I_I),
200     DEF_INDEX(AI44, RGBX, I_I)
201 };
202
203 const i965_fourcc_info *
204 get_fourcc_info(unsigned int fourcc)
205 {
206     unsigned int i;
207
208     for (i = 0; ARRAY_ELEMS(i965_fourcc_infos); i++) {
209         const i965_fourcc_info * const info = &i965_fourcc_infos[i];
210
211         if (info->fourcc == fourcc)
212             return info;
213     }
214
215     return NULL;
216 }
217
218 enum {
219     I965_SURFACETYPE_RGBA = 1,
220     I965_SURFACETYPE_YUV,
221     I965_SURFACETYPE_INDEXED
222 };
223
224 /* List of supported display attributes */
225 static const VADisplayAttribute i965_display_attributes[] = {
226     {
227         VADisplayAttribBrightness,
228         -100, 100, DEFAULT_BRIGHTNESS,
229         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
230     },
231
232     {
233         VADisplayAttribContrast,
234         0, 100, DEFAULT_CONTRAST,
235         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
236     },
237
238     {
239         VADisplayAttribHue,
240         -180, 180, DEFAULT_HUE,
241         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
242     },
243
244     {
245         VADisplayAttribSaturation,
246         0, 100, DEFAULT_SATURATION,
247         VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
248     },
249
250     {
251         VADisplayAttribRotation,
252         0, 3, VA_ROTATION_NONE,
253         VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE
254     },
255 };
256
257 /* List of supported image formats */
258 typedef struct {
259     unsigned int        type;
260     VAImageFormat       va_format;
261 } i965_image_format_map_t;
262
263 static const i965_image_format_map_t
264 i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
265     { I965_SURFACETYPE_YUV,
266       { VA_FOURCC_YV12, VA_LSB_FIRST, 12, } },
267     { I965_SURFACETYPE_YUV,
268       { VA_FOURCC_I420, VA_LSB_FIRST, 12, } },
269     { I965_SURFACETYPE_YUV,
270       { VA_FOURCC_NV12, VA_LSB_FIRST, 12, } },
271     { I965_SURFACETYPE_YUV,
272       { VA_FOURCC_YUY2, VA_LSB_FIRST, 16, } },
273     { I965_SURFACETYPE_YUV,
274       { VA_FOURCC_UYVY, VA_LSB_FIRST, 16, } },
275     { I965_SURFACETYPE_YUV,
276       { VA_FOURCC_422H, VA_LSB_FIRST, 16, } },
277     { I965_SURFACETYPE_RGBA,
278       { VA_FOURCC_RGBX, VA_LSB_FIRST, 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000 } },
279     { I965_SURFACETYPE_RGBA,
280       { VA_FOURCC_BGRX, VA_LSB_FIRST, 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff } },
281 };
282
283 /* List of supported subpicture formats */
284 typedef struct {
285     unsigned int        type;
286     unsigned int        format;
287     VAImageFormat       va_format;
288     unsigned int        va_flags;
289 } i965_subpic_format_map_t;
290
291 #define COMMON_SUBPICTURE_FLAGS                 \
292     (VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD| \
293      VA_SUBPICTURE_GLOBAL_ALPHA)
294
295 static const i965_subpic_format_map_t
296 i965_subpic_formats_map[I965_MAX_SUBPIC_FORMATS + 1] = {
297     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P4A4_UNORM,
298       { VA_FOURCC_IA44, VA_MSB_FIRST, 8, },
299       COMMON_SUBPICTURE_FLAGS },
300     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM,
301       { VA_FOURCC_AI44, VA_MSB_FIRST, 8, },
302       COMMON_SUBPICTURE_FLAGS },
303     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P8A8_UNORM,
304       { VA_FOURCC_IA88, VA_MSB_FIRST, 16, },
305       COMMON_SUBPICTURE_FLAGS },
306     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A8P8_UNORM,
307       { VA_FOURCC_AI88, VA_MSB_FIRST, 16, },
308       COMMON_SUBPICTURE_FLAGS },
309      { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM,
310       { VA_FOURCC_BGRA, VA_LSB_FIRST, 32,
311         32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
312       COMMON_SUBPICTURE_FLAGS },
313     { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM,
314       { VA_FOURCC_RGBA, VA_LSB_FIRST, 32,
315         32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
316       COMMON_SUBPICTURE_FLAGS },
317 };
318
319 static const i965_subpic_format_map_t *
320 get_subpic_format(const VAImageFormat *va_format)
321 {
322     unsigned int i;
323     for (i = 0; i965_subpic_formats_map[i].type != 0; i++) {
324         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[i];
325         if (m->va_format.fourcc == va_format->fourcc &&
326             (m->type == I965_SURFACETYPE_RGBA ?
327              (m->va_format.byte_order == va_format->byte_order &&
328               m->va_format.red_mask   == va_format->red_mask   &&
329               m->va_format.green_mask == va_format->green_mask &&
330               m->va_format.blue_mask  == va_format->blue_mask  &&
331               m->va_format.alpha_mask == va_format->alpha_mask) : 1))
332             return m;
333     }
334     return NULL;
335 }
336
337 #define I965_PACKED_HEADER_BASE         0
338 #define I965_PACKED_MISC_HEADER_BASE    3
339
340 int
341 va_enc_packed_type_to_idx(int packed_type)
342 {
343     int idx = 0;
344
345     if (packed_type & VAEncPackedHeaderMiscMask) {
346         idx = I965_PACKED_MISC_HEADER_BASE;
347         packed_type = (~VAEncPackedHeaderMiscMask & packed_type);
348         ASSERT_RET(packed_type > 0, 0);
349         idx += (packed_type - 1);
350     } else {
351         idx = I965_PACKED_HEADER_BASE;
352
353         switch (packed_type) {
354         case VAEncPackedHeaderSequence:
355             idx = I965_PACKED_HEADER_BASE + 0;
356             break;
357
358         case VAEncPackedHeaderPicture:
359             idx = I965_PACKED_HEADER_BASE + 1;
360             break;
361
362         case VAEncPackedHeaderSlice:
363             idx = I965_PACKED_HEADER_BASE + 2;
364             break;
365
366         default:
367             /* Should not get here */
368             ASSERT_RET(0, 0);
369             break;
370         }
371     }
372
373     ASSERT_RET(idx < 4, 0);
374     return idx;
375 }
376
377 VAStatus 
378 i965_QueryConfigProfiles(VADriverContextP ctx,
379                          VAProfile *profile_list,       /* out */
380                          int *num_profiles)             /* out */
381 {
382     struct i965_driver_data * const i965 = i965_driver_data(ctx);
383     int i = 0;
384
385     if (HAS_MPEG2_DECODING(i965) ||
386         HAS_MPEG2_ENCODING(i965)) {
387         profile_list[i++] = VAProfileMPEG2Simple;
388         profile_list[i++] = VAProfileMPEG2Main;
389     }
390
391     if (HAS_H264_DECODING(i965) ||
392         HAS_H264_ENCODING(i965)) {
393         profile_list[i++] = VAProfileH264ConstrainedBaseline;
394         profile_list[i++] = VAProfileH264Main;
395         profile_list[i++] = VAProfileH264High;
396     }
397     if (HAS_H264_MVC_DECODING_PROFILE(i965, VAProfileH264MultiviewHigh))
398         profile_list[i++] = VAProfileH264MultiviewHigh;
399     if (HAS_H264_MVC_DECODING_PROFILE(i965, VAProfileH264StereoHigh))
400         profile_list[i++] = VAProfileH264StereoHigh;
401
402     if (HAS_VC1_DECODING(i965)) {
403         profile_list[i++] = VAProfileVC1Simple;
404         profile_list[i++] = VAProfileVC1Main;
405         profile_list[i++] = VAProfileVC1Advanced;
406     }
407
408     if (HAS_VPP(i965)) {
409         profile_list[i++] = VAProfileNone;
410     }
411
412     if (HAS_JPEG_DECODING(i965)) {
413         profile_list[i++] = VAProfileJPEGBaseline;
414     }
415
416     if (HAS_VP8_DECODING(i965) ||
417         HAS_VP8_ENCODING(i965)) {
418         profile_list[i++] = VAProfileVP8Version0_3;
419     }
420
421     if (HAS_H264_MVC_ENCODING(i965)) {
422         profile_list[i++] = VAProfileH264MultiviewHigh;
423         profile_list[i++] = VAProfileH264StereoHigh;
424     }
425
426     /* If the assert fails then I965_MAX_PROFILES needs to be bigger */
427     ASSERT_RET(i <= I965_MAX_PROFILES, VA_STATUS_ERROR_OPERATION_FAILED);
428     *num_profiles = i;
429
430     return VA_STATUS_SUCCESS;
431 }
432
433 VAStatus 
434 i965_QueryConfigEntrypoints(VADriverContextP ctx,
435                             VAProfile profile,
436                             VAEntrypoint *entrypoint_list,      /* out */
437                             int *num_entrypoints)               /* out */
438 {
439     struct i965_driver_data * const i965 = i965_driver_data(ctx);
440     int n = 0;
441
442     switch (profile) {
443     case VAProfileMPEG2Simple:
444     case VAProfileMPEG2Main:
445         if (HAS_MPEG2_DECODING(i965))
446             entrypoint_list[n++] = VAEntrypointVLD;
447
448         if (HAS_MPEG2_ENCODING(i965))
449             entrypoint_list[n++] = VAEntrypointEncSlice;
450
451         break;
452
453     case VAProfileH264ConstrainedBaseline:
454     case VAProfileH264Main:
455     case VAProfileH264High:
456         if (HAS_H264_DECODING(i965))
457             entrypoint_list[n++] = VAEntrypointVLD;
458
459         if (HAS_H264_ENCODING(i965))
460             entrypoint_list[n++] = VAEntrypointEncSlice;
461
462         break;
463    case VAProfileH264MultiviewHigh:
464    case VAProfileH264StereoHigh:
465        if (HAS_H264_MVC_DECODING_PROFILE(i965, profile))
466             entrypoint_list[n++] = VAEntrypointVLD;
467
468        if (HAS_H264_MVC_ENCODING(i965))
469             entrypoint_list[n++] = VAEntrypointEncSlice;
470         break;
471
472     case VAProfileVC1Simple:
473     case VAProfileVC1Main:
474     case VAProfileVC1Advanced:
475         if (HAS_VC1_DECODING(i965))
476             entrypoint_list[n++] = VAEntrypointVLD;
477         break;
478
479     case VAProfileNone:
480         if (HAS_VPP(i965))
481             entrypoint_list[n++] = VAEntrypointVideoProc;
482         break;
483
484     case VAProfileJPEGBaseline:
485         if (HAS_JPEG_DECODING(i965))
486             entrypoint_list[n++] = VAEntrypointVLD;
487         break;
488
489     case VAProfileVP8Version0_3:
490         if (HAS_VP8_DECODING(i965))
491             entrypoint_list[n++] = VAEntrypointVLD;
492         
493         if (HAS_VP8_ENCODING(i965))
494             entrypoint_list[n++] = VAEntrypointEncSlice;
495
496     default:
497         break;
498     }
499
500     /* If the assert fails then I965_MAX_ENTRYPOINTS needs to be bigger */
501     ASSERT_RET(n <= I965_MAX_ENTRYPOINTS, VA_STATUS_ERROR_OPERATION_FAILED);
502     *num_entrypoints = n;
503     return n > 0 ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
504 }
505
506 static VAStatus
507 i965_validate_config(VADriverContextP ctx, VAProfile profile,
508     VAEntrypoint entrypoint)
509 {
510     struct i965_driver_data * const i965 = i965_driver_data(ctx);
511     VAStatus va_status;
512
513     /* Validate profile & entrypoint */
514     switch (profile) {
515     case VAProfileMPEG2Simple:
516     case VAProfileMPEG2Main:
517         if ((HAS_MPEG2_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
518             (HAS_MPEG2_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
519             va_status = VA_STATUS_SUCCESS;
520         } else {
521             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
522         }
523         break;
524
525     case VAProfileH264ConstrainedBaseline:
526     case VAProfileH264Main:
527     case VAProfileH264High:
528         if ((HAS_H264_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
529             (HAS_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
530             va_status = VA_STATUS_SUCCESS;
531         } else {
532             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
533         }
534         break;
535
536     case VAProfileVC1Simple:
537     case VAProfileVC1Main:
538     case VAProfileVC1Advanced:
539         if (HAS_VC1_DECODING(i965) && entrypoint == VAEntrypointVLD) {
540             va_status = VA_STATUS_SUCCESS;
541         } else {
542             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
543         }
544         break;
545
546     case VAProfileNone:
547         if (HAS_VPP(i965) && VAEntrypointVideoProc == entrypoint) {
548             va_status = VA_STATUS_SUCCESS;
549         } else {
550             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
551         }
552         break;
553
554     case VAProfileJPEGBaseline:
555         if (HAS_JPEG_DECODING(i965) && entrypoint == VAEntrypointVLD) {
556             va_status = VA_STATUS_SUCCESS;
557         } else {
558             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
559         }
560         break;
561
562     case VAProfileVP8Version0_3:
563         if ((HAS_VP8_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
564             (HAS_VP8_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
565             va_status = VA_STATUS_SUCCESS;
566         } else {
567             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
568         }
569         break;
570
571     case VAProfileH264MultiviewHigh:
572     case VAProfileH264StereoHigh:
573         if ((HAS_H264_MVC_DECODING_PROFILE(i965, profile) &&
574              entrypoint == VAEntrypointVLD) ||
575             (HAS_H264_MVC_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
576             va_status = VA_STATUS_SUCCESS;
577         } else {
578             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
579         }
580
581         break;
582
583     default:
584         va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
585         break;
586     }
587     return va_status;
588 }
589
590 static uint32_t
591 i965_get_default_chroma_formats(VADriverContextP ctx, VAProfile profile,
592     VAEntrypoint entrypoint)
593 {
594     struct i965_driver_data * const i965 = i965_driver_data(ctx);
595     uint32_t chroma_formats = VA_RT_FORMAT_YUV420;
596
597     switch (profile) {
598     case VAProfileH264ConstrainedBaseline:
599     case VAProfileH264Main:
600     case VAProfileH264High:
601         if (HAS_H264_DECODING(i965) && entrypoint == VAEntrypointVLD)
602             chroma_formats |= i965->codec_info->h264_dec_chroma_formats;
603         break;
604
605     case VAProfileH264MultiviewHigh:
606     case VAProfileH264StereoHigh:
607         if (HAS_H264_MVC_DECODING(i965) && entrypoint == VAEntrypointVLD)
608             chroma_formats |= i965->codec_info->h264_dec_chroma_formats;
609         break;
610
611     case VAProfileJPEGBaseline:
612         if (HAS_JPEG_DECODING(i965) && entrypoint == VAEntrypointVLD)
613             chroma_formats |= i965->codec_info->jpeg_dec_chroma_formats;
614         break;
615
616     default:
617         break;
618     }
619     return chroma_formats;
620 }
621
622 VAStatus 
623 i965_GetConfigAttributes(VADriverContextP ctx,
624                          VAProfile profile,
625                          VAEntrypoint entrypoint,
626                          VAConfigAttrib *attrib_list,  /* in/out */
627                          int num_attribs)
628 {
629     VAStatus va_status;
630     struct i965_driver_data *i965 = i965_driver_data(ctx);
631     int i;
632
633     va_status = i965_validate_config(ctx, profile, entrypoint);
634     if (va_status != VA_STATUS_SUCCESS)
635         return va_status;
636
637     /* Other attributes don't seem to be defined */
638     /* What to do if we don't know the attribute? */
639     for (i = 0; i < num_attribs; i++) {
640         switch (attrib_list[i].type) {
641         case VAConfigAttribRTFormat:
642             attrib_list[i].value = i965_get_default_chroma_formats(ctx,
643                 profile, entrypoint);
644             break;
645
646         case VAConfigAttribRateControl:
647             if (entrypoint == VAEntrypointEncSlice) {
648                 attrib_list[i].value = VA_RC_CQP;
649
650                 if (profile != VAProfileMPEG2Main &&
651                     profile != VAProfileMPEG2Simple)
652                     attrib_list[i].value |= VA_RC_CBR;
653                 break;
654             }
655
656         case VAConfigAttribEncPackedHeaders:
657             if (entrypoint == VAEntrypointEncSlice) {
658                 attrib_list[i].value = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
659                 if (profile == VAProfileH264ConstrainedBaseline ||
660                     profile == VAProfileH264Main ||
661                     profile == VAProfileH264High ||
662                     profile == VAProfileH264StereoHigh ||
663                     profile == VAProfileH264MultiviewHigh) {
664                     attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
665                                              VA_ENC_PACKED_HEADER_SLICE);
666                 }
667                 break;
668             }
669
670         case VAConfigAttribEncMaxRefFrames:
671             if (entrypoint == VAEntrypointEncSlice) {
672                 attrib_list[i].value = (1 << 16) | (1 << 0);
673                 break;
674             }
675
676         case VAConfigAttribEncQualityRange:
677             if (entrypoint == VAEntrypointEncSlice) {
678                 attrib_list[i].value = 1;
679                 if (profile == VAProfileH264ConstrainedBaseline ||
680                     profile == VAProfileH264Main ||
681                     profile == VAProfileH264High )
682                     attrib_list[i].value = ENCODER_QUALITY_RANGE;
683                 break;
684             }
685
686         default:
687             /* Do nothing */
688             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
689             break;
690         }
691     }
692
693     return VA_STATUS_SUCCESS;
694 }
695
696 static void 
697 i965_destroy_config(struct object_heap *heap, struct object_base *obj)
698 {
699     object_heap_free(heap, obj);
700 }
701
702 static VAConfigAttrib *
703 i965_lookup_config_attribute(struct object_config *obj_config,
704     VAConfigAttribType type)
705 {
706     int i;
707
708     for (i = 0; i < obj_config->num_attribs; i++) {
709         VAConfigAttrib * const attrib = &obj_config->attrib_list[i];
710         if (attrib->type == type)
711             return attrib;
712     }
713     return NULL;
714 }
715
716 static VAStatus
717 i965_append_config_attribute(struct object_config *obj_config,
718     const VAConfigAttrib *new_attrib)
719 {
720     VAConfigAttrib *attrib;
721
722     if (obj_config->num_attribs >= I965_MAX_CONFIG_ATTRIBUTES)
723         return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
724
725     attrib = &obj_config->attrib_list[obj_config->num_attribs++];
726     attrib->type = new_attrib->type;
727     attrib->value = new_attrib->value;
728     return VA_STATUS_SUCCESS;
729 }
730
731 static VAStatus
732 i965_ensure_config_attribute(struct object_config *obj_config,
733     const VAConfigAttrib *new_attrib)
734 {
735     VAConfigAttrib *attrib;
736
737     /* Check for existing attributes */
738     attrib = i965_lookup_config_attribute(obj_config, new_attrib->type);
739     if (attrib) {
740         /* Update existing attribute */
741         attrib->value = new_attrib->value;
742         return VA_STATUS_SUCCESS;
743     }
744     return i965_append_config_attribute(obj_config, new_attrib);
745 }
746
747 VAStatus 
748 i965_CreateConfig(VADriverContextP ctx,
749                   VAProfile profile,
750                   VAEntrypoint entrypoint,
751                   VAConfigAttrib *attrib_list,
752                   int num_attribs,
753                   VAConfigID *config_id)        /* out */
754 {
755     struct i965_driver_data * const i965 = i965_driver_data(ctx);
756     struct object_config *obj_config;
757     int configID;
758     int i;
759     VAStatus vaStatus;
760
761     vaStatus = i965_validate_config(ctx, profile, entrypoint);
762
763     if (VA_STATUS_SUCCESS != vaStatus) {
764         return vaStatus;
765     }
766
767     configID = NEW_CONFIG_ID();
768     obj_config = CONFIG(configID);
769
770     if (NULL == obj_config) {
771         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
772         return vaStatus;
773     }
774
775     obj_config->profile = profile;
776     obj_config->entrypoint = entrypoint;
777     obj_config->num_attribs = 0;
778
779     for (i = 0; i < num_attribs; i++) {
780         vaStatus = i965_ensure_config_attribute(obj_config, &attrib_list[i]);
781         if (vaStatus != VA_STATUS_SUCCESS)
782             break;
783     }
784
785     if (vaStatus == VA_STATUS_SUCCESS) {
786         VAConfigAttrib attrib, *attrib_found;
787         attrib.type = VAConfigAttribRTFormat;
788         attrib.value = i965_get_default_chroma_formats(ctx, profile, entrypoint);
789         attrib_found = i965_lookup_config_attribute(obj_config, attrib.type);
790         if (!attrib_found || !attrib_found->value)
791             vaStatus = i965_append_config_attribute(obj_config, &attrib);
792         else if (!(attrib_found->value & attrib.value))
793             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
794     }
795
796     /* Error recovery */
797     if (VA_STATUS_SUCCESS != vaStatus) {
798         i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
799     } else {
800         *config_id = configID;
801     }
802
803     return vaStatus;
804 }
805
806 VAStatus 
807 i965_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
808 {
809     struct i965_driver_data *i965 = i965_driver_data(ctx);
810     struct object_config *obj_config = CONFIG(config_id);
811     VAStatus vaStatus;
812
813     if (NULL == obj_config) {
814         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
815         return vaStatus;
816     }
817
818     i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
819     return VA_STATUS_SUCCESS;
820 }
821
822 VAStatus i965_QueryConfigAttributes(VADriverContextP ctx,
823                                     VAConfigID config_id,
824                                     VAProfile *profile,                 /* out */
825                                     VAEntrypoint *entrypoint,           /* out */
826                                     VAConfigAttrib *attrib_list,        /* out */
827                                     int *num_attribs)                   /* out */
828 {
829     struct i965_driver_data *i965 = i965_driver_data(ctx);
830     struct object_config *obj_config = CONFIG(config_id);
831     VAStatus vaStatus = VA_STATUS_SUCCESS;
832     int i;
833
834     ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
835     *profile = obj_config->profile;
836     *entrypoint = obj_config->entrypoint;
837     *num_attribs = obj_config->num_attribs;
838
839     for(i = 0; i < obj_config->num_attribs; i++) {
840         attrib_list[i] = obj_config->attrib_list[i];
841     }
842
843     return vaStatus;
844 }
845
846 void
847 i965_destroy_surface_storage(struct object_surface *obj_surface)
848 {
849     if (!obj_surface)
850         return;
851
852     dri_bo_unreference(obj_surface->bo);
853     obj_surface->bo = NULL;
854
855     if (obj_surface->free_private_data != NULL) {
856         obj_surface->free_private_data(&obj_surface->private_data);
857         obj_surface->private_data = NULL;
858     }
859 }
860
861 static void 
862 i965_destroy_surface(struct object_heap *heap, struct object_base *obj)
863 {
864     struct object_surface *obj_surface = (struct object_surface *)obj;
865
866     i965_destroy_surface_storage(obj_surface);
867     object_heap_free(heap, obj);
868 }
869
870 static VAStatus
871 i965_surface_native_memory(VADriverContextP ctx,
872                            struct object_surface *obj_surface,
873                            int format,
874                            int expected_fourcc)
875 {
876     struct i965_driver_data *i965 = i965_driver_data(ctx);
877     int tiling = HAS_TILED_SURFACE(i965);
878
879     if (!expected_fourcc)
880         return VA_STATUS_SUCCESS;
881
882     // todo, should we disable tiling for 422 format?
883     if (expected_fourcc == VA_FOURCC_I420 ||
884         expected_fourcc == VA_FOURCC_IYUV ||
885         expected_fourcc == VA_FOURCC_YV12 ||
886         expected_fourcc == VA_FOURCC_YV16)
887         tiling = 0;
888                 
889     i965_check_alloc_surface_bo(ctx, obj_surface, tiling, expected_fourcc, get_sampling_from_fourcc(expected_fourcc));
890
891     return VA_STATUS_SUCCESS;
892 }
893     
894 static VAStatus
895 i965_suface_external_memory(VADriverContextP ctx,
896                             struct object_surface *obj_surface,
897                             int external_memory_type,
898                             VASurfaceAttribExternalBuffers *memory_attibute,
899                             int index)
900 {
901     struct i965_driver_data *i965 = i965_driver_data(ctx);
902
903     if (!memory_attibute ||
904         !memory_attibute->buffers ||
905         index > memory_attibute->num_buffers)
906         return VA_STATUS_ERROR_INVALID_PARAMETER;
907
908     ASSERT_RET(obj_surface->orig_width == memory_attibute->width, VA_STATUS_ERROR_INVALID_PARAMETER);
909     ASSERT_RET(obj_surface->orig_height == memory_attibute->height, VA_STATUS_ERROR_INVALID_PARAMETER);
910     ASSERT_RET(memory_attibute->num_planes >= 1, VA_STATUS_ERROR_INVALID_PARAMETER);
911
912     obj_surface->fourcc = memory_attibute->pixel_format;
913     obj_surface->width = memory_attibute->pitches[0];
914     obj_surface->size = memory_attibute->data_size;
915
916     if (memory_attibute->num_planes == 1)
917         obj_surface->height = memory_attibute->data_size / obj_surface->width;
918     else 
919         obj_surface->height = memory_attibute->offsets[1] / obj_surface->width;
920
921     obj_surface->x_cb_offset = 0; /* X offset is always 0 */
922     obj_surface->x_cr_offset = 0;
923
924     switch (obj_surface->fourcc) {
925     case VA_FOURCC_NV12:
926         ASSERT_RET(memory_attibute->num_planes == 2, VA_STATUS_ERROR_INVALID_PARAMETER);
927         ASSERT_RET(memory_attibute->pitches[0] == memory_attibute->pitches[1], VA_STATUS_ERROR_INVALID_PARAMETER);
928
929         obj_surface->subsampling = SUBSAMPLE_YUV420;
930         obj_surface->y_cb_offset = obj_surface->height;
931         obj_surface->y_cr_offset = obj_surface->height;
932         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
933         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
934         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
935
936         break;
937
938     case VA_FOURCC_YV12:
939     case VA_FOURCC_IMC1:
940         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
941         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
942
943         obj_surface->subsampling = SUBSAMPLE_YUV420;
944         obj_surface->y_cr_offset = obj_surface->height;
945         obj_surface->y_cb_offset = memory_attibute->offsets[2] / obj_surface->width;
946         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
947         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
948         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
949         
950         break;
951
952     case VA_FOURCC_I420:
953     case VA_FOURCC_IYUV:
954     case VA_FOURCC_IMC3:
955         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
956         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
957
958         obj_surface->subsampling = SUBSAMPLE_YUV420;
959         obj_surface->y_cb_offset = obj_surface->height;
960         obj_surface->y_cr_offset = memory_attibute->offsets[2] / obj_surface->width;
961         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
962         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
963         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
964
965         break;
966
967     case VA_FOURCC_YUY2:
968     case VA_FOURCC_UYVY:
969         ASSERT_RET(memory_attibute->num_planes == 1, VA_STATUS_ERROR_INVALID_PARAMETER);
970
971         obj_surface->subsampling = SUBSAMPLE_YUV422H;
972         obj_surface->y_cb_offset = 0;
973         obj_surface->y_cr_offset = 0;
974         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
975         obj_surface->cb_cr_height = obj_surface->orig_height;
976         obj_surface->cb_cr_pitch = memory_attibute->pitches[0];
977
978         break;
979
980     case VA_FOURCC_RGBA:
981     case VA_FOURCC_RGBX:
982     case VA_FOURCC_BGRA:
983     case VA_FOURCC_BGRX:
984         ASSERT_RET(memory_attibute->num_planes == 1, VA_STATUS_ERROR_INVALID_PARAMETER);
985
986         obj_surface->subsampling = SUBSAMPLE_RGBX;
987         obj_surface->y_cb_offset = 0;
988         obj_surface->y_cr_offset = 0;
989         obj_surface->cb_cr_width = 0;
990         obj_surface->cb_cr_height = 0;
991         obj_surface->cb_cr_pitch = 0;
992
993         break;
994
995     case VA_FOURCC_Y800: /* monochrome surface */
996         ASSERT_RET(memory_attibute->num_planes == 1, VA_STATUS_ERROR_INVALID_PARAMETER);
997         
998         obj_surface->subsampling = SUBSAMPLE_YUV400;
999         obj_surface->y_cb_offset = 0;
1000         obj_surface->y_cr_offset = 0;
1001         obj_surface->cb_cr_width = 0;
1002         obj_surface->cb_cr_height = 0;
1003         obj_surface->cb_cr_pitch = 0;
1004
1005         break;
1006
1007     case VA_FOURCC_411P:
1008         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
1009         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
1010
1011         obj_surface->subsampling = SUBSAMPLE_YUV411;
1012         obj_surface->y_cb_offset = 0;
1013         obj_surface->y_cr_offset = 0;
1014         obj_surface->cb_cr_width = obj_surface->orig_width / 4;
1015         obj_surface->cb_cr_height = obj_surface->orig_height;
1016         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
1017
1018         break;
1019
1020     case VA_FOURCC_422H:
1021         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
1022         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
1023
1024         obj_surface->subsampling = SUBSAMPLE_YUV422H;
1025         obj_surface->y_cb_offset = obj_surface->height;
1026         obj_surface->y_cr_offset = memory_attibute->offsets[2] / obj_surface->width;
1027         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
1028         obj_surface->cb_cr_height = obj_surface->orig_height;
1029         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
1030
1031         break;
1032
1033     case VA_FOURCC_YV16:
1034         assert(memory_attibute->num_planes == 3);
1035         assert(memory_attibute->pitches[1] == memory_attibute->pitches[2]);
1036
1037         obj_surface->subsampling = SUBSAMPLE_YUV422H;
1038         obj_surface->y_cr_offset = memory_attibute->offsets[1] / obj_surface->width;
1039         obj_surface->y_cb_offset = memory_attibute->offsets[2] / obj_surface->width;
1040         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
1041         obj_surface->cb_cr_height = obj_surface->orig_height;
1042         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
1043
1044         break;
1045
1046     case VA_FOURCC_422V:
1047         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
1048         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
1049
1050         obj_surface->subsampling = SUBSAMPLE_YUV422H;
1051         obj_surface->y_cb_offset = obj_surface->height;
1052         obj_surface->y_cr_offset = memory_attibute->offsets[2] / obj_surface->width;
1053         obj_surface->cb_cr_width = obj_surface->orig_width;
1054         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
1055         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
1056
1057         break;
1058
1059     case VA_FOURCC_444P:
1060         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
1061         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
1062
1063         obj_surface->subsampling = SUBSAMPLE_YUV444;
1064         obj_surface->y_cb_offset = obj_surface->height;
1065         obj_surface->y_cr_offset = memory_attibute->offsets[2] / obj_surface->width;
1066         obj_surface->cb_cr_width = obj_surface->orig_width;
1067         obj_surface->cb_cr_height = obj_surface->orig_height;
1068         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
1069
1070         break;
1071
1072     default:
1073
1074         return VA_STATUS_ERROR_INVALID_PARAMETER;
1075     }
1076
1077     if (external_memory_type == I965_SURFACE_MEM_GEM_FLINK)
1078         obj_surface->bo = drm_intel_bo_gem_create_from_name(i965->intel.bufmgr,
1079                                                             "gem flinked vaapi surface",
1080                                                             memory_attibute->buffers[index]);
1081     else if (external_memory_type == I965_SURFACE_MEM_DRM_PRIME)
1082         obj_surface->bo = drm_intel_bo_gem_create_from_prime(i965->intel.bufmgr,
1083                                                              memory_attibute->buffers[index],
1084                                                              obj_surface->size);
1085
1086     if (!obj_surface->bo)
1087         return VA_STATUS_ERROR_INVALID_PARAMETER;
1088
1089     return VA_STATUS_SUCCESS;
1090 }
1091
1092 /* byte-per-pixel of the first plane */
1093 static int
1094 bpp_1stplane_by_fourcc(unsigned int fourcc)
1095 {
1096     const i965_fourcc_info *info = get_fourcc_info(fourcc);
1097
1098     if (info && (info->flag & I_S))
1099         return info->bpp[0] / 8;
1100     else
1101         return 0;
1102 }
1103
1104 static VAStatus
1105 i965_CreateSurfaces2(
1106     VADriverContextP    ctx,
1107     unsigned int        format,
1108     unsigned int        width,
1109     unsigned int        height,
1110     VASurfaceID        *surfaces,
1111     unsigned int        num_surfaces,
1112     VASurfaceAttrib    *attrib_list,
1113     unsigned int        num_attribs
1114     )
1115 {
1116     struct i965_driver_data *i965 = i965_driver_data(ctx);
1117     int i,j;
1118     VAStatus vaStatus = VA_STATUS_SUCCESS;
1119     int expected_fourcc = 0;
1120     int memory_type = I965_SURFACE_MEM_NATIVE; /* native */
1121     VASurfaceAttribExternalBuffers *memory_attibute = NULL;
1122
1123     for (i = 0; i < num_attribs && attrib_list; i++) {
1124         if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
1125             (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
1126             ASSERT_RET(attrib_list[i].value.type == VAGenericValueTypeInteger, VA_STATUS_ERROR_INVALID_PARAMETER);
1127             expected_fourcc = attrib_list[i].value.value.i;
1128         }
1129
1130         if ((attrib_list[i].type == VASurfaceAttribMemoryType) &&
1131             (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
1132             
1133             ASSERT_RET(attrib_list[i].value.type == VAGenericValueTypeInteger, VA_STATUS_ERROR_INVALID_PARAMETER);
1134
1135             if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM)
1136                 memory_type = I965_SURFACE_MEM_GEM_FLINK; /* flinked GEM handle */
1137             else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME)
1138                 memory_type = I965_SURFACE_MEM_DRM_PRIME; /* drm prime fd */
1139             else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
1140                 memory_type = I965_SURFACE_MEM_NATIVE; /* va native memory, to be allocated */
1141         }
1142
1143         if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) &&
1144             (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) {
1145             ASSERT_RET(attrib_list[i].value.type == VAGenericValueTypePointer, VA_STATUS_ERROR_INVALID_PARAMETER);
1146             memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
1147         }
1148     }
1149
1150     /* support 420 & 422 & RGB32 format, 422 and RGB32 are only used
1151      * for post-processing (including color conversion) */
1152     if (VA_RT_FORMAT_YUV420 != format &&
1153         VA_RT_FORMAT_YUV422 != format &&
1154         VA_RT_FORMAT_YUV444 != format &&
1155         VA_RT_FORMAT_YUV411 != format &&
1156         VA_RT_FORMAT_YUV400 != format &&
1157         VA_RT_FORMAT_RGB32  != format) {
1158         return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
1159     }
1160
1161     for (i = 0; i < num_surfaces; i++) {
1162         int surfaceID = NEW_SURFACE_ID();
1163         struct object_surface *obj_surface = SURFACE(surfaceID);
1164
1165         if (NULL == obj_surface) {
1166             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1167             break;
1168         }
1169
1170         surfaces[i] = surfaceID;
1171         obj_surface->status = VASurfaceReady;
1172         obj_surface->orig_width = width;
1173         obj_surface->orig_height = height;
1174         obj_surface->user_disable_tiling = false;
1175         obj_surface->user_h_stride_set = false;
1176         obj_surface->user_v_stride_set = false;
1177
1178         obj_surface->subpic_render_idx = 0;
1179         for(j = 0; j < I965_MAX_SUBPIC_SUM; j++){
1180            obj_surface->subpic[j] = VA_INVALID_ID;
1181            obj_surface->obj_subpic[j] = NULL;
1182         }
1183
1184         assert(i965->codec_info->min_linear_wpitch);
1185         assert(i965->codec_info->min_linear_hpitch);
1186         obj_surface->width = ALIGN(width, i965->codec_info->min_linear_wpitch);
1187         obj_surface->height = ALIGN(height, i965->codec_info->min_linear_hpitch);
1188         obj_surface->flags = SURFACE_REFERENCED;
1189         obj_surface->fourcc = 0;
1190         obj_surface->bo = NULL;
1191         obj_surface->locked_image_id = VA_INVALID_ID;
1192         obj_surface->private_data = NULL;
1193         obj_surface->free_private_data = NULL;
1194         obj_surface->subsampling = SUBSAMPLE_YUV420;
1195
1196         switch (memory_type) {
1197         case I965_SURFACE_MEM_NATIVE:
1198             if (memory_attibute) {
1199                 if (!(memory_attibute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING))
1200                     obj_surface->user_disable_tiling = true;
1201
1202                 if (memory_attibute->pixel_format) {
1203                     if (expected_fourcc)
1204                         ASSERT_RET(memory_attibute->pixel_format == expected_fourcc, VA_STATUS_ERROR_INVALID_PARAMETER);
1205                     else
1206                         expected_fourcc = memory_attibute->pixel_format;
1207                 }
1208                 ASSERT_RET(expected_fourcc, VA_STATUS_ERROR_INVALID_PARAMETER);
1209                 if (memory_attibute->pitches[0]) {
1210                     int bpp_1stplane = bpp_1stplane_by_fourcc(expected_fourcc);
1211                     ASSERT_RET(bpp_1stplane, VA_STATUS_ERROR_INVALID_PARAMETER);
1212                     obj_surface->width = memory_attibute->pitches[0]/bpp_1stplane;
1213                     obj_surface->user_h_stride_set = true;
1214                     ASSERT_RET(IS_ALIGNED(obj_surface->width, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
1215                     ASSERT_RET(obj_surface->width >= width, VA_STATUS_ERROR_INVALID_PARAMETER);
1216
1217                     if (memory_attibute->offsets[1]) {
1218                         ASSERT_RET(!memory_attibute->offsets[0], VA_STATUS_ERROR_INVALID_PARAMETER);
1219                         obj_surface->height = memory_attibute->offsets[1]/memory_attibute->pitches[0];
1220                         obj_surface->user_v_stride_set = true;
1221                         ASSERT_RET(IS_ALIGNED(obj_surface->height, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
1222                         ASSERT_RET(obj_surface->height >= height, VA_STATUS_ERROR_INVALID_PARAMETER);
1223                     }
1224                 }
1225             }
1226             i965_surface_native_memory(ctx,
1227                                        obj_surface,
1228                                        format,
1229                                        expected_fourcc);
1230             break;
1231
1232         case I965_SURFACE_MEM_GEM_FLINK:
1233         case I965_SURFACE_MEM_DRM_PRIME:
1234             i965_suface_external_memory(ctx,
1235                                         obj_surface,
1236                                         memory_type,
1237                                         memory_attibute,
1238                                         i);
1239             break;
1240         }
1241     }
1242
1243     /* Error recovery */
1244     if (VA_STATUS_SUCCESS != vaStatus) {
1245         /* surfaces[i-1] was the last successful allocation */
1246         for (; i--; ) {
1247             struct object_surface *obj_surface = SURFACE(surfaces[i]);
1248
1249             surfaces[i] = VA_INVALID_SURFACE;
1250             assert(obj_surface);
1251             i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
1252         }
1253     }
1254
1255     return vaStatus;
1256 }
1257
1258 VAStatus 
1259 i965_CreateSurfaces(VADriverContextP ctx,
1260                     int width,
1261                     int height,
1262                     int format,
1263                     int num_surfaces,
1264                     VASurfaceID *surfaces)      /* out */
1265 {
1266     return i965_CreateSurfaces2(ctx,
1267                                 format,
1268                                 width,
1269                                 height,
1270                                 surfaces,
1271                                 num_surfaces,
1272                                 NULL,
1273                                 0);
1274 }
1275
1276 VAStatus 
1277 i965_DestroySurfaces(VADriverContextP ctx,
1278                      VASurfaceID *surface_list,
1279                      int num_surfaces)
1280 {
1281     struct i965_driver_data *i965 = i965_driver_data(ctx);
1282     int i;
1283
1284     for (i = num_surfaces; i--; ) {
1285         struct object_surface *obj_surface = SURFACE(surface_list[i]);
1286
1287         ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
1288         i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
1289     }
1290
1291     return VA_STATUS_SUCCESS;
1292 }
1293
1294 VAStatus 
1295 i965_QueryImageFormats(VADriverContextP ctx,
1296                        VAImageFormat *format_list,      /* out */
1297                        int *num_formats)                /* out */
1298 {
1299     int n;
1300
1301     for (n = 0; i965_image_formats_map[n].va_format.fourcc != 0; n++) {
1302         const i965_image_format_map_t * const m = &i965_image_formats_map[n];
1303         if (format_list)
1304             format_list[n] = m->va_format;
1305     }
1306
1307     if (num_formats)
1308         *num_formats = n;
1309
1310     return VA_STATUS_SUCCESS;
1311 }
1312
1313 /*
1314  * Guess the format when the usage of a VA surface is unknown
1315  * 1. Without a valid context: YV12
1316  * 2. The current context is valid:
1317  *    a) always NV12 on GEN6 and later
1318  *    b) I420 for MPEG-2 and NV12 for other codec on GEN4 & GEN5
1319  */
1320 static void
1321 i965_guess_surface_format(VADriverContextP ctx,
1322                           VASurfaceID surface,
1323                           unsigned int *fourcc,
1324                           unsigned int *is_tiled)
1325 {
1326     struct i965_driver_data *i965 = i965_driver_data(ctx);
1327     struct object_context *obj_context = NULL;
1328     struct object_config *obj_config = NULL;
1329
1330     *fourcc = VA_FOURCC_YV12;
1331     *is_tiled = 0;
1332
1333     if (i965->current_context_id == VA_INVALID_ID)
1334         return;
1335
1336     obj_context = CONTEXT(i965->current_context_id);
1337
1338     if (!obj_context)
1339         return;
1340
1341     obj_config = obj_context->obj_config;
1342     assert(obj_config);
1343
1344     if (!obj_config)
1345         return;
1346
1347     if (IS_GEN6(i965->intel.device_info) ||
1348         IS_GEN7(i965->intel.device_info) ||
1349         IS_GEN8(i965->intel.device_info)) {
1350         *fourcc = VA_FOURCC_NV12;
1351         *is_tiled = 1;
1352         return;
1353     }
1354
1355     switch (obj_config->profile) {
1356     case VAProfileMPEG2Simple:
1357     case VAProfileMPEG2Main:
1358         *fourcc = VA_FOURCC_I420;
1359         *is_tiled = 0;
1360         break;
1361
1362     default:
1363         *fourcc = VA_FOURCC_NV12;
1364         *is_tiled = 0;
1365         break;
1366     }
1367 }
1368
1369 VAStatus 
1370 i965_QuerySubpictureFormats(VADriverContextP ctx,
1371                             VAImageFormat *format_list,         /* out */
1372                             unsigned int *flags,                /* out */
1373                             unsigned int *num_formats)          /* out */
1374 {
1375     int n;
1376
1377     for (n = 0; i965_subpic_formats_map[n].va_format.fourcc != 0; n++) {
1378         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[n];
1379         if (format_list)
1380             format_list[n] = m->va_format;
1381         if (flags)
1382             flags[n] = m->va_flags;
1383     }
1384
1385     if (num_formats)
1386         *num_formats = n;
1387
1388     return VA_STATUS_SUCCESS;
1389 }
1390
1391 static void 
1392 i965_destroy_subpic(struct object_heap *heap, struct object_base *obj)
1393 {
1394     //    struct object_subpic *obj_subpic = (struct object_subpic *)obj;
1395
1396     object_heap_free(heap, obj);
1397 }
1398
1399 VAStatus 
1400 i965_CreateSubpicture(VADriverContextP ctx,
1401                       VAImageID image,
1402                       VASubpictureID *subpicture)         /* out */
1403 {
1404     struct i965_driver_data *i965 = i965_driver_data(ctx);
1405     VASubpictureID subpicID = NEW_SUBPIC_ID()
1406     struct object_subpic *obj_subpic = SUBPIC(subpicID);
1407
1408     if (!obj_subpic)
1409         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1410
1411     struct object_image *obj_image = IMAGE(image);
1412     if (!obj_image)
1413         return VA_STATUS_ERROR_INVALID_IMAGE;
1414
1415     const i965_subpic_format_map_t * const m = get_subpic_format(&obj_image->image.format);
1416     if (!m)
1417         return VA_STATUS_ERROR_UNKNOWN; /* XXX: VA_STATUS_ERROR_UNSUPPORTED_FORMAT? */
1418
1419     *subpicture = subpicID;
1420     obj_subpic->image  = image;
1421     obj_subpic->obj_image = obj_image;
1422     obj_subpic->format = m->format;
1423     obj_subpic->width  = obj_image->image.width;
1424     obj_subpic->height = obj_image->image.height;
1425     obj_subpic->pitch  = obj_image->image.pitches[0];
1426     obj_subpic->bo     = obj_image->bo;
1427     obj_subpic->global_alpha = 1.0;
1428  
1429     return VA_STATUS_SUCCESS;
1430 }
1431
1432 VAStatus 
1433 i965_DestroySubpicture(VADriverContextP ctx,
1434                        VASubpictureID subpicture)
1435 {
1436     struct i965_driver_data *i965 = i965_driver_data(ctx);
1437     struct object_subpic *obj_subpic = SUBPIC(subpicture);
1438
1439     if (!obj_subpic)
1440         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1441
1442     ASSERT_RET(obj_subpic->obj_image, VA_STATUS_ERROR_INVALID_SUBPICTURE);
1443     i965_destroy_subpic(&i965->subpic_heap, (struct object_base *)obj_subpic);
1444     return VA_STATUS_SUCCESS;
1445 }
1446
1447 VAStatus 
1448 i965_SetSubpictureImage(VADriverContextP ctx,
1449                         VASubpictureID subpicture,
1450                         VAImageID image)
1451 {
1452     /* TODO */
1453     return VA_STATUS_ERROR_UNIMPLEMENTED;
1454 }
1455
1456 VAStatus 
1457 i965_SetSubpictureChromakey(VADriverContextP ctx,
1458                             VASubpictureID subpicture,
1459                             unsigned int chromakey_min,
1460                             unsigned int chromakey_max,
1461                             unsigned int chromakey_mask)
1462 {
1463     /* TODO */
1464     return VA_STATUS_ERROR_UNIMPLEMENTED;
1465 }
1466
1467 VAStatus 
1468 i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
1469                               VASubpictureID subpicture,
1470                               float global_alpha)
1471 {
1472     struct i965_driver_data *i965 = i965_driver_data(ctx);
1473     struct object_subpic *obj_subpic = SUBPIC(subpicture);
1474
1475     if(global_alpha > 1.0 || global_alpha < 0.0){
1476        return VA_STATUS_ERROR_INVALID_PARAMETER;
1477     }
1478
1479     if (!obj_subpic)
1480         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1481
1482     obj_subpic->global_alpha  = global_alpha;
1483
1484     return VA_STATUS_SUCCESS;
1485 }
1486
1487 VAStatus 
1488 i965_AssociateSubpicture(VADriverContextP ctx,
1489                          VASubpictureID subpicture,
1490                          VASurfaceID *target_surfaces,
1491                          int num_surfaces,
1492                          short src_x, /* upper left offset in subpicture */
1493                          short src_y,
1494                          unsigned short src_width,
1495                          unsigned short src_height,
1496                          short dest_x, /* upper left offset in surface */
1497                          short dest_y,
1498                          unsigned short dest_width,
1499                          unsigned short dest_height,
1500                          /*
1501                           * whether to enable chroma-keying or global-alpha
1502                           * see VA_SUBPICTURE_XXX values
1503                           */
1504                          unsigned int flags)
1505 {
1506     struct i965_driver_data *i965 = i965_driver_data(ctx);
1507     struct object_subpic *obj_subpic = SUBPIC(subpicture);
1508     int i, j;
1509
1510     if (!obj_subpic)
1511         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1512     
1513     ASSERT_RET(obj_subpic->obj_image, VA_STATUS_ERROR_INVALID_SUBPICTURE);
1514
1515     obj_subpic->src_rect.x      = src_x;
1516     obj_subpic->src_rect.y      = src_y;
1517     obj_subpic->src_rect.width  = src_width;
1518     obj_subpic->src_rect.height = src_height;
1519     obj_subpic->dst_rect.x      = dest_x;
1520     obj_subpic->dst_rect.y      = dest_y;
1521     obj_subpic->dst_rect.width  = dest_width;
1522     obj_subpic->dst_rect.height = dest_height;
1523     obj_subpic->flags           = flags;
1524
1525     for (i = 0; i < num_surfaces; i++) {
1526         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
1527         if (!obj_surface)
1528             return VA_STATUS_ERROR_INVALID_SURFACE;
1529
1530         for(j = 0; j < I965_MAX_SUBPIC_SUM; j ++){
1531             if(obj_surface->subpic[j] == VA_INVALID_ID){
1532                 assert(obj_surface->obj_subpic[j] == NULL);
1533                 obj_surface->subpic[j] = subpicture;
1534                 obj_surface->obj_subpic[j] = obj_subpic;
1535                 break;
1536             }
1537         }
1538         
1539         if(j == I965_MAX_SUBPIC_SUM){
1540             return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1541         }
1542
1543     }
1544     return VA_STATUS_SUCCESS;
1545 }
1546
1547
1548 VAStatus 
1549 i965_DeassociateSubpicture(VADriverContextP ctx,
1550                            VASubpictureID subpicture,
1551                            VASurfaceID *target_surfaces,
1552                            int num_surfaces)
1553 {
1554     struct i965_driver_data *i965 = i965_driver_data(ctx);
1555     struct object_subpic *obj_subpic = SUBPIC(subpicture);
1556     int i, j;
1557
1558     if (!obj_subpic)
1559         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1560
1561     for (i = 0; i < num_surfaces; i++) {
1562         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
1563         if (!obj_surface)
1564             return VA_STATUS_ERROR_INVALID_SURFACE;
1565
1566         for(j = 0; j < I965_MAX_SUBPIC_SUM; j ++){
1567             if (obj_surface->subpic[j] == subpicture) {
1568                 assert(obj_surface->obj_subpic[j] == obj_subpic);
1569                 obj_surface->subpic[j] = VA_INVALID_ID;
1570                 obj_surface->obj_subpic[j] = NULL;
1571                 break;
1572             }
1573         }
1574         
1575         if(j == I965_MAX_SUBPIC_SUM){
1576             return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1577         }
1578     }
1579     return VA_STATUS_SUCCESS;
1580 }
1581
1582 void
1583 i965_reference_buffer_store(struct buffer_store **ptr, 
1584                             struct buffer_store *buffer_store)
1585 {
1586     assert(*ptr == NULL);
1587
1588     if (buffer_store) {
1589         buffer_store->ref_count++;
1590         *ptr = buffer_store;
1591     }
1592 }
1593
1594 void 
1595 i965_release_buffer_store(struct buffer_store **ptr)
1596 {
1597     struct buffer_store *buffer_store = *ptr;
1598
1599     if (buffer_store == NULL)
1600         return;
1601
1602     assert(buffer_store->bo || buffer_store->buffer);
1603     assert(!(buffer_store->bo && buffer_store->buffer));
1604     buffer_store->ref_count--;
1605     
1606     if (buffer_store->ref_count == 0) {
1607         dri_bo_unreference(buffer_store->bo);
1608         free(buffer_store->buffer);
1609         buffer_store->bo = NULL;
1610         buffer_store->buffer = NULL;
1611         free(buffer_store);
1612     }
1613
1614     *ptr = NULL;
1615 }
1616
1617 static void 
1618 i965_destroy_context(struct object_heap *heap, struct object_base *obj)
1619 {
1620     struct object_context *obj_context = (struct object_context *)obj;
1621     int i;
1622
1623     if (obj_context->hw_context) {
1624         obj_context->hw_context->destroy(obj_context->hw_context);
1625         obj_context->hw_context = NULL;
1626     }
1627
1628     if (obj_context->codec_type == CODEC_PROC) {
1629         i965_release_buffer_store(&obj_context->codec_state.proc.pipeline_param);
1630
1631     } else if (obj_context->codec_type == CODEC_ENC) {
1632         assert(obj_context->codec_state.encode.num_slice_params <= obj_context->codec_state.encode.max_slice_params);
1633         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
1634         i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
1635
1636         for (i = 0; i < obj_context->codec_state.encode.num_slice_params; i++)
1637             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
1638
1639         free(obj_context->codec_state.encode.slice_params);
1640
1641         assert(obj_context->codec_state.encode.num_slice_params_ext <= obj_context->codec_state.encode.max_slice_params_ext);
1642         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param_ext);
1643         i965_release_buffer_store(&obj_context->codec_state.encode.seq_param_ext);
1644
1645         for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_param); i++)
1646             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_param[i]);
1647
1648         for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_data); i++)
1649             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data[i]);
1650
1651         for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param); i++)
1652             i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i]);
1653
1654         for (i = 0; i < obj_context->codec_state.encode.num_slice_params_ext; i++)
1655             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params_ext[i]);
1656
1657         free(obj_context->codec_state.encode.slice_params_ext);
1658         if (obj_context->codec_state.encode.slice_rawdata_index) {
1659             free(obj_context->codec_state.encode.slice_rawdata_index);
1660             obj_context->codec_state.encode.slice_rawdata_index = NULL;
1661         }
1662         if (obj_context->codec_state.encode.slice_rawdata_count) {
1663             free(obj_context->codec_state.encode.slice_rawdata_count);
1664             obj_context->codec_state.encode.slice_rawdata_count = NULL;
1665         }
1666
1667         if (obj_context->codec_state.encode.slice_header_index) {
1668             free(obj_context->codec_state.encode.slice_header_index);
1669             obj_context->codec_state.encode.slice_header_index = NULL;
1670         }
1671
1672         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_params_ext; i++)
1673             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_params_ext[i]);
1674         free(obj_context->codec_state.encode.packed_header_params_ext);
1675
1676         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_data_ext; i++)
1677             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data_ext[i]);
1678         free(obj_context->codec_state.encode.packed_header_data_ext);
1679
1680     } else {
1681         assert(obj_context->codec_state.decode.num_slice_params <= obj_context->codec_state.decode.max_slice_params);
1682         assert(obj_context->codec_state.decode.num_slice_datas <= obj_context->codec_state.decode.max_slice_datas);
1683
1684         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
1685         i965_release_buffer_store(&obj_context->codec_state.decode.iq_matrix);
1686         i965_release_buffer_store(&obj_context->codec_state.decode.bit_plane);
1687
1688         for (i = 0; i < obj_context->codec_state.decode.num_slice_params; i++)
1689             i965_release_buffer_store(&obj_context->codec_state.decode.slice_params[i]);
1690
1691         for (i = 0; i < obj_context->codec_state.decode.num_slice_datas; i++)
1692             i965_release_buffer_store(&obj_context->codec_state.decode.slice_datas[i]);
1693
1694         free(obj_context->codec_state.decode.slice_params);
1695         free(obj_context->codec_state.decode.slice_datas);
1696     }
1697
1698     free(obj_context->render_targets);
1699     object_heap_free(heap, obj);
1700 }
1701
1702 VAStatus
1703 i965_CreateContext(VADriverContextP ctx,
1704                    VAConfigID config_id,
1705                    int picture_width,
1706                    int picture_height,
1707                    int flag,
1708                    VASurfaceID *render_targets,
1709                    int num_render_targets,
1710                    VAContextID *context)                /* out */
1711 {
1712     struct i965_driver_data *i965 = i965_driver_data(ctx);
1713     struct i965_render_state *render_state = &i965->render_state;
1714     struct object_config *obj_config = CONFIG(config_id);
1715     struct object_context *obj_context = NULL;
1716     VAConfigAttrib *attrib;
1717     VAStatus vaStatus = VA_STATUS_SUCCESS;
1718     int contextID;
1719     int i;
1720
1721     if (NULL == obj_config) {
1722         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1723         return vaStatus;
1724     }
1725
1726     if (picture_width > i965->codec_info->max_width ||
1727         picture_height > i965->codec_info->max_height) {
1728         vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1729         return vaStatus;
1730     }
1731
1732     /* Validate flag */
1733     /* Validate picture dimensions */
1734     contextID = NEW_CONTEXT_ID();
1735     obj_context = CONTEXT(contextID);
1736
1737     if (NULL == obj_context) {
1738         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1739         return vaStatus;
1740     }
1741
1742     render_state->inited = 1;
1743
1744     switch (obj_config->profile) {
1745     case VAProfileH264ConstrainedBaseline:
1746     case VAProfileH264Main:
1747     case VAProfileH264High:
1748         if (!HAS_H264_DECODING(i965) &&
1749             !HAS_H264_ENCODING(i965))
1750             return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1751         render_state->interleaved_uv = 1;
1752         break;
1753     case VAProfileH264MultiviewHigh:
1754     case VAProfileH264StereoHigh:
1755         if (!HAS_H264_MVC_DECODING(i965))
1756             return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1757         render_state->interleaved_uv = 1;
1758         break;
1759     default:
1760         render_state->interleaved_uv = !!(IS_GEN6(i965->intel.device_info) || IS_GEN7(i965->intel.device_info) || IS_GEN8(i965->intel.device_info));
1761         break;
1762     }
1763
1764     *context = contextID;
1765     obj_context->flags = flag;
1766     obj_context->context_id = contextID;
1767     obj_context->obj_config = obj_config;
1768     obj_context->picture_width = picture_width;
1769     obj_context->picture_height = picture_height;
1770     obj_context->num_render_targets = num_render_targets;
1771     obj_context->render_targets = 
1772         (VASurfaceID *)calloc(num_render_targets, sizeof(VASurfaceID));
1773     obj_context->hw_context = NULL;
1774
1775     for(i = 0; i < num_render_targets; i++) {
1776         if (NULL == SURFACE(render_targets[i])) {
1777             vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1778             break;
1779         }
1780
1781         obj_context->render_targets[i] = render_targets[i];
1782     }
1783
1784     if (VA_STATUS_SUCCESS == vaStatus) {
1785         if (VAEntrypointVideoProc == obj_config->entrypoint) {
1786             obj_context->codec_type = CODEC_PROC;
1787             memset(&obj_context->codec_state.proc, 0, sizeof(obj_context->codec_state.proc));
1788             obj_context->codec_state.proc.current_render_target = VA_INVALID_ID;
1789             assert(i965->codec_info->proc_hw_context_init);
1790             obj_context->hw_context = i965->codec_info->proc_hw_context_init(ctx, obj_config);
1791         } else if (VAEntrypointEncSlice == obj_config->entrypoint) { /*encode routin only*/
1792             VAConfigAttrib *packed_attrib;
1793             obj_context->codec_type = CODEC_ENC;
1794             memset(&obj_context->codec_state.encode, 0, sizeof(obj_context->codec_state.encode));
1795             obj_context->codec_state.encode.current_render_target = VA_INVALID_ID;
1796             obj_context->codec_state.encode.max_slice_params = NUM_SLICES;
1797             obj_context->codec_state.encode.slice_params = calloc(obj_context->codec_state.encode.max_slice_params,
1798                                                                sizeof(*obj_context->codec_state.encode.slice_params));
1799             obj_context->codec_state.encode.max_packed_header_params_ext = NUM_SLICES;
1800             obj_context->codec_state.encode.packed_header_params_ext =
1801                 calloc(obj_context->codec_state.encode.max_packed_header_params_ext,
1802                        sizeof(struct buffer_store *));
1803
1804             obj_context->codec_state.encode.max_packed_header_data_ext = NUM_SLICES;
1805             obj_context->codec_state.encode.packed_header_data_ext =
1806                 calloc(obj_context->codec_state.encode.max_packed_header_data_ext,
1807                        sizeof(struct buffer_store *));
1808
1809             obj_context->codec_state.encode.max_slice_num = NUM_SLICES;
1810             obj_context->codec_state.encode.slice_rawdata_index =
1811                 calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
1812             obj_context->codec_state.encode.slice_rawdata_count =
1813                 calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
1814
1815             obj_context->codec_state.encode.slice_header_index =
1816                 calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
1817
1818             obj_context->codec_state.encode.slice_index = 0;
1819             packed_attrib = i965_lookup_config_attribute(obj_config, VAConfigAttribEncPackedHeaders);
1820             if (packed_attrib)
1821                 obj_context->codec_state.encode.packed_header_flag = packed_attrib->value;
1822             else {
1823                 /* use the default value. SPS/PPS/RAWDATA is passed from user
1824                  * while Slice_header data is generated by driver.
1825                  */
1826                 obj_context->codec_state.encode.packed_header_flag =
1827                                VA_ENC_PACKED_HEADER_SEQUENCE |
1828                                VA_ENC_PACKED_HEADER_PICTURE |
1829                                VA_ENC_PACKED_HEADER_RAW_DATA;
1830             }
1831             assert(i965->codec_info->enc_hw_context_init);
1832             obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
1833         } else {
1834             obj_context->codec_type = CODEC_DEC;
1835             memset(&obj_context->codec_state.decode, 0, sizeof(obj_context->codec_state.decode));
1836             obj_context->codec_state.decode.current_render_target = -1;
1837             obj_context->codec_state.decode.max_slice_params = NUM_SLICES;
1838             obj_context->codec_state.decode.max_slice_datas = NUM_SLICES;
1839             obj_context->codec_state.decode.slice_params = calloc(obj_context->codec_state.decode.max_slice_params,
1840                                                                sizeof(*obj_context->codec_state.decode.slice_params));
1841             obj_context->codec_state.decode.slice_datas = calloc(obj_context->codec_state.decode.max_slice_datas,
1842                                                               sizeof(*obj_context->codec_state.decode.slice_datas));
1843
1844             assert(i965->codec_info->dec_hw_context_init);
1845             obj_context->hw_context = i965->codec_info->dec_hw_context_init(ctx, obj_config);
1846         }
1847     }
1848
1849     attrib = i965_lookup_config_attribute(obj_config, VAConfigAttribRTFormat);
1850     if (!attrib)
1851         return VA_STATUS_ERROR_INVALID_CONFIG;
1852     obj_context->codec_state.base.chroma_formats = attrib->value;
1853
1854     /* Error recovery */
1855     if (VA_STATUS_SUCCESS != vaStatus) {
1856         i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
1857     }
1858
1859     i965->current_context_id = contextID;
1860
1861     return vaStatus;
1862 }
1863
1864 VAStatus 
1865 i965_DestroyContext(VADriverContextP ctx, VAContextID context)
1866 {
1867     struct i965_driver_data *i965 = i965_driver_data(ctx);
1868     struct object_context *obj_context = CONTEXT(context);
1869
1870     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
1871
1872     if (i965->current_context_id == context)
1873         i965->current_context_id = VA_INVALID_ID;
1874
1875     i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
1876
1877     return VA_STATUS_SUCCESS;
1878 }
1879
1880 static void 
1881 i965_destroy_buffer(struct object_heap *heap, struct object_base *obj)
1882 {
1883     struct object_buffer *obj_buffer = (struct object_buffer *)obj;
1884
1885     assert(obj_buffer->buffer_store);
1886     i965_release_buffer_store(&obj_buffer->buffer_store);
1887     object_heap_free(heap, obj);
1888 }
1889
1890 static VAStatus
1891 i965_create_buffer_internal(VADriverContextP ctx,
1892                             VAContextID context,
1893                             VABufferType type,
1894                             unsigned int size,
1895                             unsigned int num_elements,
1896                             void *data,
1897                             dri_bo *store_bo,
1898                             VABufferID *buf_id)
1899 {
1900     struct i965_driver_data *i965 = i965_driver_data(ctx);
1901     struct object_buffer *obj_buffer = NULL;
1902     struct buffer_store *buffer_store = NULL;
1903     int bufferID;
1904
1905     /* Validate type */
1906     switch (type) {
1907     case VAPictureParameterBufferType:
1908     case VAIQMatrixBufferType:
1909     case VAQMatrixBufferType:
1910     case VABitPlaneBufferType:
1911     case VASliceGroupMapBufferType:
1912     case VASliceParameterBufferType:
1913     case VASliceDataBufferType:
1914     case VAMacroblockParameterBufferType:
1915     case VAResidualDataBufferType:
1916     case VADeblockingParameterBufferType:
1917     case VAImageBufferType:
1918     case VAEncCodedBufferType:
1919     case VAEncSequenceParameterBufferType:
1920     case VAEncPictureParameterBufferType:
1921     case VAEncSliceParameterBufferType:
1922     case VAEncPackedHeaderParameterBufferType:
1923     case VAEncPackedHeaderDataBufferType:
1924     case VAEncMiscParameterBufferType:
1925     case VAProcPipelineParameterBufferType:
1926     case VAProcFilterParameterBufferType:
1927     case VAHuffmanTableBufferType:
1928     case VAProbabilityBufferType:
1929         /* Ok */
1930         break;
1931
1932     default:
1933         return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1934     }
1935
1936     bufferID = NEW_BUFFER_ID();
1937     obj_buffer = BUFFER(bufferID);
1938
1939     if (NULL == obj_buffer) {
1940         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1941     }
1942
1943     if (type == VAEncCodedBufferType) {
1944         size += I965_CODEDBUFFER_HEADER_SIZE;
1945         size += 0x1000; /* for upper bound check */
1946     }
1947
1948     obj_buffer->max_num_elements = num_elements;
1949     obj_buffer->num_elements = num_elements;
1950     obj_buffer->size_element = size;
1951     obj_buffer->type = type;
1952     obj_buffer->buffer_store = NULL;
1953     buffer_store = calloc(1, sizeof(struct buffer_store));
1954     assert(buffer_store);
1955     buffer_store->ref_count = 1;
1956
1957     if (store_bo != NULL) {
1958         buffer_store->bo = store_bo;
1959         dri_bo_reference(buffer_store->bo);
1960         
1961         if (data)
1962             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
1963     } else if (type == VASliceDataBufferType || 
1964                type == VAImageBufferType || 
1965                type == VAEncCodedBufferType ||
1966                type == VAProbabilityBufferType) {
1967         buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, 
1968                                         "Buffer", 
1969                                         size * num_elements, 64);
1970         assert(buffer_store->bo);
1971
1972         if (type == VAEncCodedBufferType) {
1973             struct i965_coded_buffer_segment *coded_buffer_segment;
1974
1975             dri_bo_map(buffer_store->bo, 1);
1976             coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer_store->bo->virtual;
1977             coded_buffer_segment->base.size = size - I965_CODEDBUFFER_HEADER_SIZE;
1978             coded_buffer_segment->base.bit_offset = 0;
1979             coded_buffer_segment->base.status = 0;
1980             coded_buffer_segment->base.buf = NULL;
1981             coded_buffer_segment->base.next = NULL;
1982             coded_buffer_segment->mapped = 0;
1983             coded_buffer_segment->codec = 0;
1984             dri_bo_unmap(buffer_store->bo);
1985         } else if (data) {
1986             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
1987         }
1988
1989     } else {
1990         int msize = size;
1991         
1992         if (type == VAEncPackedHeaderDataBufferType) {
1993             msize = ALIGN(size, 4);
1994         }
1995
1996         buffer_store->buffer = malloc(msize * num_elements);
1997         assert(buffer_store->buffer);
1998
1999         if (data)
2000             memcpy(buffer_store->buffer, data, size * num_elements);
2001     }
2002
2003     buffer_store->num_elements = obj_buffer->num_elements;
2004     i965_reference_buffer_store(&obj_buffer->buffer_store, buffer_store);
2005     i965_release_buffer_store(&buffer_store);
2006     *buf_id = bufferID;
2007
2008     return VA_STATUS_SUCCESS;
2009 }
2010
2011 VAStatus 
2012 i965_CreateBuffer(VADriverContextP ctx,
2013                   VAContextID context,          /* in */
2014                   VABufferType type,            /* in */
2015                   unsigned int size,            /* in */
2016                   unsigned int num_elements,    /* in */
2017                   void *data,                   /* in */
2018                   VABufferID *buf_id)           /* out */
2019 {
2020     return i965_create_buffer_internal(ctx, context, type, size, num_elements, data, NULL, buf_id);
2021 }
2022
2023
2024 VAStatus 
2025 i965_BufferSetNumElements(VADriverContextP ctx,
2026                           VABufferID buf_id,           /* in */
2027                           unsigned int num_elements)   /* in */
2028 {
2029     struct i965_driver_data *i965 = i965_driver_data(ctx);
2030     struct object_buffer *obj_buffer = BUFFER(buf_id);
2031     VAStatus vaStatus = VA_STATUS_SUCCESS;
2032
2033     ASSERT_RET(obj_buffer, VA_STATUS_ERROR_INVALID_BUFFER);
2034
2035     if ((num_elements < 0) || 
2036         (num_elements > obj_buffer->max_num_elements)) {
2037         vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
2038     } else {
2039         obj_buffer->num_elements = num_elements;
2040         if (obj_buffer->buffer_store != NULL) {
2041             obj_buffer->buffer_store->num_elements = num_elements;
2042         }
2043     }
2044
2045     return vaStatus;
2046 }
2047
2048 VAStatus 
2049 i965_MapBuffer(VADriverContextP ctx,
2050                VABufferID buf_id,       /* in */
2051                void **pbuf)             /* out */
2052 {
2053     struct i965_driver_data *i965 = i965_driver_data(ctx);
2054     struct object_buffer *obj_buffer = BUFFER(buf_id);
2055     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
2056
2057     ASSERT_RET(obj_buffer && obj_buffer->buffer_store, VA_STATUS_ERROR_INVALID_BUFFER);
2058     ASSERT_RET(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
2059     ASSERT_RET(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer), VA_STATUS_ERROR_INVALID_BUFFER);
2060
2061     if (NULL != obj_buffer->buffer_store->bo) {
2062         unsigned int tiling, swizzle;
2063
2064         dri_bo_get_tiling(obj_buffer->buffer_store->bo, &tiling, &swizzle);
2065
2066         if (tiling != I915_TILING_NONE)
2067             drm_intel_gem_bo_map_gtt(obj_buffer->buffer_store->bo);
2068         else
2069             dri_bo_map(obj_buffer->buffer_store->bo, 1);
2070
2071         ASSERT_RET(obj_buffer->buffer_store->bo->virtual, VA_STATUS_ERROR_OPERATION_FAILED);
2072         *pbuf = obj_buffer->buffer_store->bo->virtual;
2073
2074         if (obj_buffer->type == VAEncCodedBufferType) {
2075             int i;
2076             unsigned char *buffer = NULL;
2077             struct i965_coded_buffer_segment *coded_buffer_segment = (struct i965_coded_buffer_segment *)(obj_buffer->buffer_store->bo->virtual);
2078
2079             if (!coded_buffer_segment->mapped) {
2080                 unsigned char delimiter0, delimiter1, delimiter2, delimiter3, delimiter4;
2081
2082                 coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + I965_CODEDBUFFER_HEADER_SIZE;
2083
2084                 if (coded_buffer_segment->codec == CODEC_H264 ||
2085                     coded_buffer_segment->codec == CODEC_H264_MVC) {
2086                     delimiter0 = H264_DELIMITER0;
2087                     delimiter1 = H264_DELIMITER1;
2088                     delimiter2 = H264_DELIMITER2;
2089                     delimiter3 = H264_DELIMITER3;
2090                     delimiter4 = H264_DELIMITER4;
2091                 } else if (coded_buffer_segment->codec == CODEC_MPEG2) {
2092                     delimiter0 = MPEG2_DELIMITER0;
2093                     delimiter1 = MPEG2_DELIMITER1;
2094                     delimiter2 = MPEG2_DELIMITER2;
2095                     delimiter3 = MPEG2_DELIMITER3;
2096                     delimiter4 = MPEG2_DELIMITER4;
2097                 } else {
2098                     ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
2099                 }
2100
2101                 for (i = 0; i < obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000; i++) {
2102                     if ((buffer[i] == delimiter0) &&
2103                         (buffer[i + 1] == delimiter1) &&
2104                         (buffer[i + 2] == delimiter2) &&
2105                         (buffer[i + 3] == delimiter3) &&
2106                         (buffer[i + 4] == delimiter4))
2107                         break;
2108                 }
2109
2110                 if (i == obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000) {
2111                     coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
2112                 }
2113
2114                 coded_buffer_segment->base.size = i;
2115                 coded_buffer_segment->mapped = 1;
2116             } else {
2117                 assert(coded_buffer_segment->base.buf);
2118             }
2119         }
2120
2121         vaStatus = VA_STATUS_SUCCESS;
2122     } else if (NULL != obj_buffer->buffer_store->buffer) {
2123         *pbuf = obj_buffer->buffer_store->buffer;
2124         vaStatus = VA_STATUS_SUCCESS;
2125     }
2126
2127     return vaStatus;
2128 }
2129
2130 VAStatus 
2131 i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
2132 {
2133     struct i965_driver_data *i965 = i965_driver_data(ctx);
2134     struct object_buffer *obj_buffer = BUFFER(buf_id);
2135     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
2136
2137     if ((buf_id & OBJECT_HEAP_OFFSET_MASK) != BUFFER_ID_OFFSET)
2138         return VA_STATUS_ERROR_INVALID_BUFFER;
2139
2140     ASSERT_RET(obj_buffer && obj_buffer->buffer_store, VA_STATUS_ERROR_INVALID_BUFFER);
2141     ASSERT_RET(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_OPERATION_FAILED);
2142     ASSERT_RET(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer), VA_STATUS_ERROR_OPERATION_FAILED);
2143
2144     if (NULL != obj_buffer->buffer_store->bo) {
2145         unsigned int tiling, swizzle;
2146
2147         dri_bo_get_tiling(obj_buffer->buffer_store->bo, &tiling, &swizzle);
2148
2149         if (tiling != I915_TILING_NONE)
2150             drm_intel_gem_bo_unmap_gtt(obj_buffer->buffer_store->bo);
2151         else
2152             dri_bo_unmap(obj_buffer->buffer_store->bo);
2153
2154         vaStatus = VA_STATUS_SUCCESS;
2155     } else if (NULL != obj_buffer->buffer_store->buffer) {
2156         /* Do nothing */
2157         vaStatus = VA_STATUS_SUCCESS;
2158     }
2159
2160     return vaStatus;    
2161 }
2162
2163 VAStatus 
2164 i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
2165 {
2166     struct i965_driver_data *i965 = i965_driver_data(ctx);
2167     struct object_buffer *obj_buffer = BUFFER(buffer_id);
2168
2169     ASSERT_RET(obj_buffer, VA_STATUS_ERROR_INVALID_BUFFER);
2170
2171     i965_destroy_buffer(&i965->buffer_heap, (struct object_base *)obj_buffer);
2172
2173     return VA_STATUS_SUCCESS;
2174 }
2175
2176 VAStatus 
2177 i965_BeginPicture(VADriverContextP ctx,
2178                   VAContextID context,
2179                   VASurfaceID render_target)
2180 {
2181     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2182     struct object_context *obj_context = CONTEXT(context);
2183     struct object_surface *obj_surface = SURFACE(render_target);
2184     struct object_config *obj_config;
2185     VAStatus vaStatus;
2186     int i;
2187
2188     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
2189     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
2190     obj_config = obj_context->obj_config;
2191     ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
2192
2193     switch (obj_config->profile) {
2194     case VAProfileMPEG2Simple:
2195     case VAProfileMPEG2Main:
2196         vaStatus = VA_STATUS_SUCCESS;
2197         break;
2198
2199     case VAProfileH264ConstrainedBaseline:
2200     case VAProfileH264Main:
2201     case VAProfileH264High:
2202         vaStatus = VA_STATUS_SUCCESS;
2203         break;
2204
2205     case VAProfileH264MultiviewHigh:
2206     case VAProfileH264StereoHigh:
2207         if (HAS_H264_MVC_DECODING_PROFILE(i965, obj_config->profile) ||
2208             HAS_H264_MVC_ENCODING(i965)) {
2209             vaStatus = VA_STATUS_SUCCESS;
2210         } else {
2211             ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
2212         }
2213         break;
2214
2215     case VAProfileVC1Simple:
2216     case VAProfileVC1Main:
2217     case VAProfileVC1Advanced:
2218         vaStatus = VA_STATUS_SUCCESS;
2219         break;
2220
2221     case VAProfileJPEGBaseline:
2222         vaStatus = VA_STATUS_SUCCESS;
2223         break;
2224
2225     case VAProfileNone:
2226         vaStatus = VA_STATUS_SUCCESS;
2227         break;
2228
2229     case VAProfileVP8Version0_3:
2230         vaStatus = VA_STATUS_SUCCESS;
2231         break;
2232
2233     default:
2234         ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
2235         break;
2236     }
2237
2238     if (obj_context->codec_type == CODEC_PROC) {
2239         obj_context->codec_state.proc.current_render_target = render_target;
2240     } else if (obj_context->codec_type == CODEC_ENC) {
2241         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
2242
2243         for (i = 0; i < obj_context->codec_state.encode.num_slice_params; i++) {
2244             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
2245         }
2246
2247         obj_context->codec_state.encode.num_slice_params = 0;
2248
2249         /* ext */
2250         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param_ext);
2251
2252         for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_param); i++)
2253             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_param[i]);
2254
2255         for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_data); i++)
2256             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data[i]);
2257
2258         for (i = 0; i < obj_context->codec_state.encode.num_slice_params_ext; i++)
2259             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params_ext[i]);
2260
2261         obj_context->codec_state.encode.num_slice_params_ext = 0;
2262         obj_context->codec_state.encode.current_render_target = render_target;     /*This is input new frame*/
2263         obj_context->codec_state.encode.last_packed_header_type = 0;
2264         memset(obj_context->codec_state.encode.slice_rawdata_index, 0,
2265                sizeof(int) * obj_context->codec_state.encode.max_slice_num);
2266         memset(obj_context->codec_state.encode.slice_rawdata_count, 0,
2267                sizeof(int) * obj_context->codec_state.encode.max_slice_num);
2268         memset(obj_context->codec_state.encode.slice_header_index, 0,
2269                sizeof(int) * obj_context->codec_state.encode.max_slice_num);
2270
2271         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_params_ext; i++)
2272             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_params_ext[i]);
2273         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_data_ext; i++)
2274             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data_ext[i]);
2275         obj_context->codec_state.encode.num_packed_header_params_ext = 0;
2276         obj_context->codec_state.encode.num_packed_header_data_ext = 0;
2277         obj_context->codec_state.encode.slice_index = 0;
2278     } else {
2279         obj_context->codec_state.decode.current_render_target = render_target;
2280         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
2281         i965_release_buffer_store(&obj_context->codec_state.decode.iq_matrix);
2282         i965_release_buffer_store(&obj_context->codec_state.decode.bit_plane);
2283         i965_release_buffer_store(&obj_context->codec_state.decode.huffman_table);
2284
2285         for (i = 0; i < obj_context->codec_state.decode.num_slice_params; i++) {
2286             i965_release_buffer_store(&obj_context->codec_state.decode.slice_params[i]);
2287             i965_release_buffer_store(&obj_context->codec_state.decode.slice_datas[i]);
2288         }
2289
2290         obj_context->codec_state.decode.num_slice_params = 0;
2291         obj_context->codec_state.decode.num_slice_datas = 0;
2292     }
2293
2294     return vaStatus;
2295 }
2296
2297 #define I965_RENDER_BUFFER(category, name) i965_render_##category##_##name##_buffer(ctx, obj_context, obj_buffer)
2298
2299 #define DEF_RENDER_SINGLE_BUFFER_FUNC(category, name, member)           \
2300     static VAStatus                                                     \
2301     i965_render_##category##_##name##_buffer(VADriverContextP ctx,      \
2302                                              struct object_context *obj_context, \
2303                                              struct object_buffer *obj_buffer) \
2304     {                                                                   \
2305         struct category##_state *category = &obj_context->codec_state.category; \
2306         i965_release_buffer_store(&category->member);                   \
2307         i965_reference_buffer_store(&category->member, obj_buffer->buffer_store); \
2308         return VA_STATUS_SUCCESS;                                       \
2309     }
2310
2311 #define DEF_RENDER_MULTI_BUFFER_FUNC(category, name, member)            \
2312     static VAStatus                                                     \
2313     i965_render_##category##_##name##_buffer(VADriverContextP ctx,      \
2314                                              struct object_context *obj_context, \
2315                                              struct object_buffer *obj_buffer) \
2316     {                                                                   \
2317         struct category##_state *category = &obj_context->codec_state.category; \
2318         if (category->num_##member == category->max_##member) {         \
2319             category->member = realloc(category->member, (category->max_##member + NUM_SLICES) * sizeof(*category->member)); \
2320             memset(category->member + category->max_##member, 0, NUM_SLICES * sizeof(*category->member)); \
2321             category->max_##member += NUM_SLICES;                       \
2322         }                                                               \
2323         i965_release_buffer_store(&category->member[category->num_##member]); \
2324         i965_reference_buffer_store(&category->member[category->num_##member], obj_buffer->buffer_store); \
2325         category->num_##member++;                                       \
2326         return VA_STATUS_SUCCESS;                                       \
2327     }
2328
2329 #define I965_RENDER_DECODE_BUFFER(name) I965_RENDER_BUFFER(decode, name)
2330
2331 #define DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(decode, name, member)
2332 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
2333 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(iq_matrix, iq_matrix)
2334 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(bit_plane, bit_plane)
2335 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(huffman_table, huffman_table)
2336 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(probability_data, probability_data)
2337
2338 #define DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(name, member) DEF_RENDER_MULTI_BUFFER_FUNC(decode, name, member)
2339 DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
2340 DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_data, slice_datas)
2341
2342 static VAStatus 
2343 i965_decoder_render_picture(VADriverContextP ctx,
2344                             VAContextID context,
2345                             VABufferID *buffers,
2346                             int num_buffers)
2347 {
2348     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2349     struct object_context *obj_context = CONTEXT(context);
2350     VAStatus vaStatus = VA_STATUS_SUCCESS;
2351     int i;
2352     
2353     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
2354
2355     for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
2356         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
2357
2358         if (!obj_buffer)
2359             return VA_STATUS_ERROR_INVALID_BUFFER;
2360
2361         switch (obj_buffer->type) {
2362         case VAPictureParameterBufferType:
2363             vaStatus = I965_RENDER_DECODE_BUFFER(picture_parameter);
2364             break;
2365             
2366         case VAIQMatrixBufferType:
2367             vaStatus = I965_RENDER_DECODE_BUFFER(iq_matrix);
2368             break;
2369
2370         case VABitPlaneBufferType:
2371             vaStatus = I965_RENDER_DECODE_BUFFER(bit_plane);
2372             break;
2373
2374         case VASliceParameterBufferType:
2375             vaStatus = I965_RENDER_DECODE_BUFFER(slice_parameter);
2376             break;
2377
2378         case VASliceDataBufferType:
2379             vaStatus = I965_RENDER_DECODE_BUFFER(slice_data);
2380             break;
2381
2382         case VAHuffmanTableBufferType:
2383             vaStatus = I965_RENDER_DECODE_BUFFER(huffman_table);
2384             break;
2385
2386         case VAProbabilityBufferType:
2387             vaStatus = I965_RENDER_DECODE_BUFFER(probability_data);
2388             break;
2389
2390         default:
2391             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
2392             break;
2393         }
2394     }
2395
2396     return vaStatus;
2397 }
2398
2399 #define I965_RENDER_ENCODE_BUFFER(name) I965_RENDER_BUFFER(encode, name)
2400
2401 #define DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(encode, name, member)
2402 // DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter, seq_param)    
2403 // DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
2404 // DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_control, pic_control)
2405 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(qmatrix, q_matrix)
2406 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(iqmatrix, iq_matrix)
2407 /* extended buffer */
2408 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter_ext, seq_param_ext)
2409 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter_ext, pic_param_ext)
2410
2411 #define DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(name, member) DEF_RENDER_MULTI_BUFFER_FUNC(encode, name, member)
2412 // DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
2413 DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter_ext, slice_params_ext)
2414
2415 DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(packed_header_params_ext, packed_header_params_ext)
2416 DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(packed_header_data_ext, packed_header_data_ext)
2417
2418 static VAStatus
2419 i965_encoder_render_packed_header_parameter_buffer(VADriverContextP ctx,
2420                                                    struct object_context *obj_context,
2421                                                    struct object_buffer *obj_buffer,
2422                                                    int type_index)
2423 {
2424     struct encode_state *encode = &obj_context->codec_state.encode;
2425
2426     ASSERT_RET(obj_buffer->buffer_store->bo == NULL, VA_STATUS_ERROR_INVALID_BUFFER);
2427     ASSERT_RET(obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
2428     i965_release_buffer_store(&encode->packed_header_param[type_index]);
2429     i965_reference_buffer_store(&encode->packed_header_param[type_index], obj_buffer->buffer_store);
2430
2431     return VA_STATUS_SUCCESS;
2432 }
2433
2434 static VAStatus
2435 i965_encoder_render_packed_header_data_buffer(VADriverContextP ctx,
2436                                               struct object_context *obj_context,
2437                                               struct object_buffer *obj_buffer,
2438                                               int type_index)
2439 {
2440     struct encode_state *encode = &obj_context->codec_state.encode;
2441
2442     ASSERT_RET(obj_buffer->buffer_store->bo == NULL, VA_STATUS_ERROR_INVALID_BUFFER);
2443     ASSERT_RET(obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
2444     i965_release_buffer_store(&encode->packed_header_data[type_index]);
2445     i965_reference_buffer_store(&encode->packed_header_data[type_index], obj_buffer->buffer_store);
2446
2447     return VA_STATUS_SUCCESS;
2448 }
2449
2450 static VAStatus
2451 i965_encoder_render_misc_parameter_buffer(VADriverContextP ctx,
2452                                           struct object_context *obj_context,
2453                                           struct object_buffer *obj_buffer)
2454 {
2455     struct encode_state *encode = &obj_context->codec_state.encode;
2456     VAEncMiscParameterBuffer *param = NULL;
2457
2458     ASSERT_RET(obj_buffer->buffer_store->bo == NULL, VA_STATUS_ERROR_INVALID_BUFFER);
2459     ASSERT_RET(obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
2460
2461     param = (VAEncMiscParameterBuffer *)obj_buffer->buffer_store->buffer;
2462
2463     if (param->type >= ARRAY_ELEMS(encode->misc_param))
2464         return VA_STATUS_ERROR_INVALID_PARAMETER;
2465
2466     i965_release_buffer_store(&encode->misc_param[param->type]);
2467     i965_reference_buffer_store(&encode->misc_param[param->type], obj_buffer->buffer_store);
2468
2469     return VA_STATUS_SUCCESS;
2470 }
2471
2472 static VAStatus 
2473 i965_encoder_render_picture(VADriverContextP ctx,
2474                             VAContextID context,
2475                             VABufferID *buffers,
2476                             int num_buffers)
2477 {
2478     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2479     struct object_context *obj_context = CONTEXT(context);
2480     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
2481     struct encode_state *encode;
2482     int i;
2483
2484     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
2485
2486     encode = &obj_context->codec_state.encode;
2487     for (i = 0; i < num_buffers; i++) {  
2488         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
2489
2490         if (!obj_buffer)
2491             return VA_STATUS_ERROR_INVALID_BUFFER;
2492
2493         switch (obj_buffer->type) {
2494         case VAQMatrixBufferType:
2495             vaStatus = I965_RENDER_ENCODE_BUFFER(qmatrix);
2496             break;
2497
2498         case VAIQMatrixBufferType:
2499             vaStatus = I965_RENDER_ENCODE_BUFFER(iqmatrix);
2500             break;
2501
2502         case VAEncSequenceParameterBufferType:
2503             vaStatus = I965_RENDER_ENCODE_BUFFER(sequence_parameter_ext);
2504             break;
2505
2506         case VAEncPictureParameterBufferType:
2507             vaStatus = I965_RENDER_ENCODE_BUFFER(picture_parameter_ext);
2508             break;
2509
2510         case VAEncSliceParameterBufferType:
2511             vaStatus = I965_RENDER_ENCODE_BUFFER(slice_parameter_ext);
2512             if (vaStatus == VA_STATUS_SUCCESS) {
2513                 /* When the max number of slices is updated, it also needs
2514                  * to reallocate the arrays that is used to store
2515                  * the packed data index/count for the slice
2516                  */
2517                 if (!(encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE)) {
2518                    encode->slice_index++;
2519                 }
2520                 if (encode->slice_index == encode->max_slice_num) {
2521                     int slice_num = encode->max_slice_num;
2522                     encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
2523                                                           (slice_num + NUM_SLICES) * sizeof(int));
2524                     encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
2525                                                           (slice_num + NUM_SLICES) * sizeof(int));
2526                     encode->slice_header_index = realloc(encode->slice_header_index,
2527                                                           (slice_num + NUM_SLICES) * sizeof(int));
2528                     memset(encode->slice_rawdata_index + slice_num, 0,
2529                         sizeof(int) * NUM_SLICES);
2530                     memset(encode->slice_rawdata_count + slice_num, 0,
2531                         sizeof(int) * NUM_SLICES);
2532                     memset(encode->slice_header_index + slice_num, 0,
2533                         sizeof(int) * NUM_SLICES);
2534
2535                     encode->max_slice_num += NUM_SLICES;
2536                     if ((encode->slice_rawdata_index == NULL) ||
2537                         (encode->slice_header_index == NULL)  ||
2538                         (encode->slice_rawdata_count == NULL)) {
2539                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2540                         return vaStatus;
2541                     }
2542                 }
2543             }
2544             break;
2545
2546         case VAEncPackedHeaderParameterBufferType:
2547         {
2548             VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)obj_buffer->buffer_store->buffer;
2549             encode->last_packed_header_type = param->type;
2550
2551             if ((param->type == VAEncPackedHeaderRawData) ||
2552                 (param->type == VAEncPackedHeaderSlice)) {
2553                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_params_ext);
2554             } else {
2555                 vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
2556                                                                           obj_context,
2557                                                                           obj_buffer,
2558                                                                           va_enc_packed_type_to_idx(encode->last_packed_header_type));
2559             }
2560             break;
2561         }
2562
2563         case VAEncPackedHeaderDataBufferType:
2564         {
2565             if (encode->last_packed_header_type == 0) {
2566                 WARN_ONCE("the packed header data is passed without type!\n");
2567                 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2568                 return vaStatus;
2569             }
2570             if (encode->last_packed_header_type == VAEncPackedHeaderRawData ||
2571                 encode->last_packed_header_type == VAEncPackedHeaderSlice) {
2572                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_data_ext);
2573
2574                 /* When the PACKED_SLICE_HEADER flag is passed, it will use
2575                  * the packed_slice_header as the delimeter to decide how
2576                  * the packed rawdata is inserted for the given slice.
2577                  * Otherwise it will use the VAEncSequenceParameterBuffer
2578                  * as the delimeter
2579                  */
2580                 if (encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE) {
2581                     /* store the first index of the packed header data for current slice */
2582                     if (encode->slice_rawdata_index[encode->slice_index] == 0) {
2583                         encode->slice_rawdata_index[encode->slice_index] =
2584                             SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
2585                     }
2586                     encode->slice_rawdata_count[encode->slice_index]++;
2587                     if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
2588                         /* find one packed slice_header delimeter. And the following
2589                          * packed data is for the next slice
2590                          */
2591                         encode->slice_header_index[encode->slice_index] =
2592                             SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
2593                         encode->slice_index++;
2594                         /* Reallocate the buffer to record the index/count of
2595                          * packed_data for one slice.
2596                          */
2597                         if (encode->slice_index == encode->max_slice_num) {
2598                             int slice_num = encode->max_slice_num;
2599
2600                             encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
2601                                                           (slice_num + NUM_SLICES) * sizeof(int));
2602                             encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
2603                                                           (slice_num + NUM_SLICES) * sizeof(int));
2604                             encode->slice_header_index = realloc(encode->slice_header_index,
2605                                                           (slice_num + NUM_SLICES) * sizeof(int));
2606                             memset(encode->slice_rawdata_index + slice_num, 0,
2607                                    sizeof(int) * NUM_SLICES);
2608                             memset(encode->slice_rawdata_count + slice_num, 0,
2609                                    sizeof(int) * NUM_SLICES);
2610                             memset(encode->slice_header_index + slice_num, 0,
2611                                    sizeof(int) * NUM_SLICES);
2612                             encode->max_slice_num += NUM_SLICES;
2613                         }
2614                     }
2615                 } else {
2616                     if (vaStatus == VA_STATUS_SUCCESS) {
2617                         /* store the first index of the packed header data for current slice */
2618                         if (encode->slice_rawdata_index[encode->slice_index] == 0) {
2619                             encode->slice_rawdata_index[encode->slice_index] =
2620                                 SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
2621                         }
2622                         encode->slice_rawdata_count[encode->slice_index]++;
2623                         if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
2624                             if (encode->slice_header_index[encode->slice_index] == 0) {
2625                                 encode->slice_header_index[encode->slice_index] =
2626                                     SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
2627                             } else {
2628                                 WARN_ONCE("Multi slice header data is passed for"
2629                                       " slice %d!\n", encode->slice_index);
2630                             }
2631                         }
2632                     }
2633                 }
2634             } else {
2635                 ASSERT_RET(encode->last_packed_header_type == VAEncPackedHeaderSequence ||
2636                     encode->last_packed_header_type == VAEncPackedHeaderPicture ||
2637                     encode->last_packed_header_type == VAEncPackedHeaderSlice ||
2638                    (((encode->last_packed_header_type & VAEncPackedHeaderMiscMask) == VAEncPackedHeaderMiscMask) &&
2639                     ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)),
2640                     VA_STATUS_ERROR_ENCODING_ERROR);
2641                 vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
2642                                                                      obj_context,
2643                                                                      obj_buffer,
2644                                                                      va_enc_packed_type_to_idx(encode->last_packed_header_type));
2645             }
2646             encode->last_packed_header_type = 0;
2647             break;       
2648         }
2649
2650         case VAEncMiscParameterBufferType:
2651             vaStatus = i965_encoder_render_misc_parameter_buffer(ctx,
2652                                                                  obj_context,
2653                                                                  obj_buffer);
2654             break;
2655             
2656         default:
2657             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
2658             break;
2659         }
2660     }   
2661
2662     return vaStatus;
2663 }
2664
2665 #define I965_RENDER_PROC_BUFFER(name) I965_RENDER_BUFFER(proc, name)
2666
2667 #define DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(proc, name, member)
2668 DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(pipeline_parameter, pipeline_param)    
2669
2670 static VAStatus 
2671 i965_proc_render_picture(VADriverContextP ctx,
2672                          VAContextID context,
2673                          VABufferID *buffers,
2674                          int num_buffers)
2675 {
2676     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2677     struct object_context *obj_context = CONTEXT(context);
2678     VAStatus vaStatus = VA_STATUS_SUCCESS;
2679     int i;
2680
2681     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
2682
2683     for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
2684         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
2685
2686         if (!obj_buffer)
2687             return VA_STATUS_ERROR_INVALID_BUFFER;
2688
2689         switch (obj_buffer->type) {
2690         case VAProcPipelineParameterBufferType:
2691             vaStatus = I965_RENDER_PROC_BUFFER(pipeline_parameter);
2692             break;
2693
2694         default:
2695             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
2696             break;
2697         }
2698     }
2699
2700     return vaStatus;
2701 }
2702
2703 VAStatus 
2704 i965_RenderPicture(VADriverContextP ctx,
2705                    VAContextID context,
2706                    VABufferID *buffers,
2707                    int num_buffers)
2708 {
2709     struct i965_driver_data *i965 = i965_driver_data(ctx);
2710     struct object_context *obj_context;
2711     struct object_config *obj_config;
2712     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
2713
2714     obj_context = CONTEXT(context);
2715     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
2716
2717     if (num_buffers <= 0)
2718         return VA_STATUS_ERROR_INVALID_PARAMETER;
2719
2720     obj_config = obj_context->obj_config;
2721     ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
2722
2723     if (VAEntrypointVideoProc == obj_config->entrypoint) {
2724         vaStatus = i965_proc_render_picture(ctx, context, buffers, num_buffers);
2725     } else if (VAEntrypointEncSlice == obj_config->entrypoint ) {
2726         vaStatus = i965_encoder_render_picture(ctx, context, buffers, num_buffers);
2727     } else {
2728         vaStatus = i965_decoder_render_picture(ctx, context, buffers, num_buffers);
2729     }
2730
2731     return vaStatus;
2732 }
2733
2734 VAStatus 
2735 i965_EndPicture(VADriverContextP ctx, VAContextID context)
2736 {
2737     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2738     struct object_context *obj_context = CONTEXT(context);
2739     struct object_config *obj_config;
2740
2741     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
2742     obj_config = obj_context->obj_config;
2743     ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
2744
2745     if (obj_context->codec_type == CODEC_PROC) {
2746         ASSERT_RET(VAEntrypointVideoProc == obj_config->entrypoint, VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT);
2747     } else if (obj_context->codec_type == CODEC_ENC) {
2748         ASSERT_RET(VAEntrypointEncSlice == obj_config->entrypoint, VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT);
2749
2750         if (obj_context->codec_state.encode.num_packed_header_params_ext !=
2751                obj_context->codec_state.encode.num_packed_header_data_ext) {
2752             WARN_ONCE("the packed header/data is not paired for encoding!\n");
2753             return VA_STATUS_ERROR_INVALID_PARAMETER;
2754         }
2755         if (!(obj_context->codec_state.encode.pic_param ||
2756                 obj_context->codec_state.encode.pic_param_ext)) {
2757             return VA_STATUS_ERROR_INVALID_PARAMETER;
2758         }
2759         if (!(obj_context->codec_state.encode.seq_param ||
2760                 obj_context->codec_state.encode.seq_param_ext)) {
2761             return VA_STATUS_ERROR_INVALID_PARAMETER;
2762         }
2763         if ((obj_context->codec_state.encode.num_slice_params <=0) &&
2764                 (obj_context->codec_state.encode.num_slice_params_ext <=0)) {
2765             return VA_STATUS_ERROR_INVALID_PARAMETER;
2766         }
2767
2768         if ((obj_context->codec_state.encode.packed_header_flag & VA_ENC_PACKED_HEADER_SLICE) &&
2769             (obj_context->codec_state.encode.num_slice_params_ext !=
2770              obj_context->codec_state.encode.slice_index)) {
2771             WARN_ONCE("packed slice_header data is missing for some slice"
2772                       " under packed SLICE_HEADER mode\n");
2773             return VA_STATUS_ERROR_INVALID_PARAMETER;
2774         }
2775     } else {
2776         if (obj_context->codec_state.decode.pic_param == NULL) {
2777             return VA_STATUS_ERROR_INVALID_PARAMETER;
2778         }
2779         if (obj_context->codec_state.decode.num_slice_params <=0) {
2780             return VA_STATUS_ERROR_INVALID_PARAMETER;
2781         }
2782         if (obj_context->codec_state.decode.num_slice_datas <=0) {
2783             return VA_STATUS_ERROR_INVALID_PARAMETER;
2784         }
2785
2786         if (obj_context->codec_state.decode.num_slice_params !=
2787                 obj_context->codec_state.decode.num_slice_datas) {
2788             return VA_STATUS_ERROR_INVALID_PARAMETER;
2789         }
2790     }
2791
2792     ASSERT_RET(obj_context->hw_context->run, VA_STATUS_ERROR_OPERATION_FAILED);
2793     return obj_context->hw_context->run(ctx, obj_config->profile, &obj_context->codec_state, obj_context->hw_context);
2794 }
2795
2796 VAStatus 
2797 i965_SyncSurface(VADriverContextP ctx,
2798                  VASurfaceID render_target)
2799 {
2800     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2801     struct object_surface *obj_surface = SURFACE(render_target);
2802
2803     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
2804
2805     if(obj_surface->bo)
2806         drm_intel_bo_wait_rendering(obj_surface->bo);
2807
2808     return VA_STATUS_SUCCESS;
2809 }
2810
2811 VAStatus 
2812 i965_QuerySurfaceStatus(VADriverContextP ctx,
2813                         VASurfaceID render_target,
2814                         VASurfaceStatus *status)        /* out */
2815 {
2816     struct i965_driver_data *i965 = i965_driver_data(ctx); 
2817     struct object_surface *obj_surface = SURFACE(render_target);
2818
2819     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
2820
2821     if (obj_surface->bo) {
2822         if (drm_intel_bo_busy(obj_surface->bo)){
2823             *status = VASurfaceRendering;
2824         }
2825         else {
2826             *status = VASurfaceReady;
2827         }
2828     } else {
2829         *status = VASurfaceReady;
2830     }
2831
2832     return VA_STATUS_SUCCESS;
2833 }
2834
2835 static VADisplayAttribute *
2836 get_display_attribute(VADriverContextP ctx, VADisplayAttribType type)
2837 {
2838     struct i965_driver_data * const i965 = i965_driver_data(ctx);
2839     unsigned int i;
2840
2841     if (!i965->display_attributes)
2842         return NULL;
2843
2844     for (i = 0; i < i965->num_display_attributes; i++) {
2845         if (i965->display_attributes[i].type == type)
2846             return &i965->display_attributes[i];
2847     }
2848     return NULL;
2849 }
2850
2851 static void
2852 i965_display_attributes_terminate(VADriverContextP ctx)
2853 {
2854     struct i965_driver_data * const i965 = i965_driver_data(ctx);
2855
2856     if (i965->display_attributes) {
2857         free(i965->display_attributes);
2858         i965->display_attributes = NULL;
2859         i965->num_display_attributes = 0;
2860     }
2861 }
2862
2863 static bool
2864 i965_display_attributes_init(VADriverContextP ctx)
2865 {
2866     struct i965_driver_data * const i965 = i965_driver_data(ctx);
2867
2868     i965->num_display_attributes = ARRAY_ELEMS(i965_display_attributes);
2869     i965->display_attributes = malloc(
2870         i965->num_display_attributes * sizeof(i965->display_attributes[0]));
2871     if (!i965->display_attributes)
2872         goto error;
2873
2874     memcpy(
2875         i965->display_attributes,
2876         i965_display_attributes,
2877         sizeof(i965_display_attributes)
2878     );
2879
2880     i965->rotation_attrib = get_display_attribute(ctx, VADisplayAttribRotation);
2881     i965->brightness_attrib = get_display_attribute(ctx, VADisplayAttribBrightness);
2882     i965->contrast_attrib = get_display_attribute(ctx, VADisplayAttribContrast);
2883     i965->hue_attrib = get_display_attribute(ctx, VADisplayAttribHue);
2884     i965->saturation_attrib = get_display_attribute(ctx, VADisplayAttribSaturation);
2885
2886     if (!i965->rotation_attrib ||
2887         !i965->brightness_attrib ||
2888         !i965->contrast_attrib ||
2889         !i965->hue_attrib ||
2890         !i965->saturation_attrib) {
2891         goto error;
2892     }
2893     return true;
2894
2895 error:
2896     i965_display_attributes_terminate(ctx);
2897     return false;
2898 }
2899
2900 /* 
2901  * Query display attributes 
2902  * The caller must provide a "attr_list" array that can hold at
2903  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
2904  * returned in "attr_list" is returned in "num_attributes".
2905  */
2906 VAStatus 
2907 i965_QueryDisplayAttributes(
2908     VADriverContextP    ctx,
2909     VADisplayAttribute *attribs,        /* out */
2910     int                *num_attribs_ptr /* out */
2911 )
2912 {
2913     const int num_attribs = ARRAY_ELEMS(i965_display_attributes);
2914
2915     if (attribs && num_attribs > 0)
2916         memcpy(attribs, i965_display_attributes, sizeof(i965_display_attributes));
2917
2918     if (num_attribs_ptr)
2919         *num_attribs_ptr = num_attribs;
2920
2921     return VA_STATUS_SUCCESS;
2922 }
2923
2924 /* 
2925  * Get display attributes 
2926  * This function returns the current attribute values in "attr_list".
2927  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
2928  * from vaQueryDisplayAttributes() can have their values retrieved.  
2929  */
2930 VAStatus 
2931 i965_GetDisplayAttributes(
2932     VADriverContextP    ctx,
2933     VADisplayAttribute *attribs,        /* inout */
2934     int                 num_attribs     /* in */
2935 )
2936 {
2937     int i;
2938
2939     for (i = 0; i < num_attribs; i++) {
2940         VADisplayAttribute *src_attrib, * const dst_attrib = &attribs[i];
2941
2942         src_attrib = get_display_attribute(ctx, dst_attrib->type);
2943         if (src_attrib && (src_attrib->flags & VA_DISPLAY_ATTRIB_GETTABLE)) {
2944             dst_attrib->min_value = src_attrib->min_value;
2945             dst_attrib->max_value = src_attrib->max_value;
2946             dst_attrib->value     = src_attrib->value;
2947         }
2948         else
2949             dst_attrib->flags = VA_DISPLAY_ATTRIB_NOT_SUPPORTED;
2950     }
2951     return VA_STATUS_SUCCESS;
2952 }
2953
2954 /* 
2955  * Set display attributes 
2956  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
2957  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or 
2958  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
2959  */
2960 VAStatus 
2961 i965_SetDisplayAttributes(
2962     VADriverContextP    ctx,
2963     VADisplayAttribute *attribs,        /* in */
2964     int                 num_attribs     /* in */
2965 )
2966 {
2967     int i;
2968
2969     for (i = 0; i < num_attribs; i++) {
2970         VADisplayAttribute *dst_attrib, * const src_attrib = &attribs[i];
2971
2972         dst_attrib = get_display_attribute(ctx, src_attrib->type);
2973         if (!dst_attrib)
2974             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
2975
2976         if (!(dst_attrib->flags & VA_DISPLAY_ATTRIB_SETTABLE))
2977             continue;
2978
2979         if (src_attrib->value < dst_attrib->min_value ||
2980             src_attrib->value > dst_attrib->max_value)
2981             return VA_STATUS_ERROR_INVALID_PARAMETER;
2982
2983         dst_attrib->value = src_attrib->value;
2984         /* XXX: track modified attributes through timestamps */
2985     }
2986     return VA_STATUS_SUCCESS;
2987 }
2988
2989 VAStatus 
2990 i965_DbgCopySurfaceToBuffer(VADriverContextP ctx,
2991                             VASurfaceID surface,
2992                             void **buffer,              /* out */
2993                             unsigned int *stride)       /* out */
2994 {
2995     /* TODO */
2996     return VA_STATUS_ERROR_UNIMPLEMENTED;
2997 }
2998
2999 static void
3000 i965_destroy_heap(struct object_heap *heap, 
3001                   void (*func)(struct object_heap *heap, struct object_base *object))
3002 {
3003     struct object_base *object;
3004     object_heap_iterator iter;    
3005
3006     object = object_heap_first(heap, &iter);
3007
3008     while (object) {
3009         if (func)
3010             func(heap, object);
3011
3012         object = object_heap_next(heap, &iter);
3013     }
3014
3015     object_heap_destroy(heap);
3016 }
3017
3018
3019 VAStatus 
3020 i965_DestroyImage(VADriverContextP ctx, VAImageID image);
3021
3022 VAStatus 
3023 i965_CreateImage(VADriverContextP ctx,
3024                  VAImageFormat *format,
3025                  int width,
3026                  int height,
3027                  VAImage *out_image)        /* out */
3028 {
3029     struct i965_driver_data *i965 = i965_driver_data(ctx);
3030     struct object_image *obj_image;
3031     VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED;
3032     VAImageID image_id;
3033     unsigned int size2, size, awidth, aheight;
3034
3035     out_image->image_id = VA_INVALID_ID;
3036     out_image->buf      = VA_INVALID_ID;
3037
3038     image_id = NEW_IMAGE_ID();
3039     if (image_id == VA_INVALID_ID)
3040         return VA_STATUS_ERROR_ALLOCATION_FAILED;
3041
3042     obj_image = IMAGE(image_id);
3043     if (!obj_image)
3044         return VA_STATUS_ERROR_ALLOCATION_FAILED;
3045     obj_image->bo         = NULL;
3046     obj_image->palette    = NULL;
3047     obj_image->derived_surface = VA_INVALID_ID;
3048
3049     VAImage * const image = &obj_image->image;
3050     image->image_id       = image_id;
3051     image->buf            = VA_INVALID_ID;
3052
3053     awidth = ALIGN(width, i965->codec_info->min_linear_wpitch);
3054
3055     if ((format->fourcc == VA_FOURCC_YV12) ||
3056                 (format->fourcc == VA_FOURCC_I420)) {
3057         if (awidth % 128 != 0) {
3058                 awidth = ALIGN(width, 128);     
3059         }
3060     }
3061
3062     aheight = ALIGN(height, i965->codec_info->min_linear_hpitch);
3063     size    = awidth * aheight;
3064     size2    = (awidth / 2) * (aheight / 2);
3065
3066     image->num_palette_entries = 0;
3067     image->entry_bytes         = 0;
3068     memset(image->component_order, 0, sizeof(image->component_order));
3069
3070     switch (format->fourcc) {
3071     case VA_FOURCC_IA44:
3072     case VA_FOURCC_AI44:
3073         image->num_planes = 1;
3074         image->pitches[0] = awidth;
3075         image->offsets[0] = 0;
3076         image->data_size  = image->offsets[0] + image->pitches[0] * aheight;
3077         image->num_palette_entries = 16;
3078         image->entry_bytes         = 3;
3079         image->component_order[0]  = 'R';
3080         image->component_order[1]  = 'G';
3081         image->component_order[2]  = 'B';
3082         break;
3083     case VA_FOURCC_IA88:
3084     case VA_FOURCC_AI88:
3085         image->num_planes = 1;
3086         image->pitches[0] = awidth * 2;
3087         image->offsets[0] = 0;
3088         image->data_size  = image->offsets[0] + image->pitches[0] * aheight;
3089         image->num_palette_entries = 256;
3090         image->entry_bytes         = 3;
3091         image->component_order[0]  = 'R';
3092         image->component_order[1]  = 'G';
3093         image->component_order[2]  = 'B';
3094         break;
3095     case VA_FOURCC_ARGB:
3096     case VA_FOURCC_ABGR:
3097     case VA_FOURCC_BGRA:
3098     case VA_FOURCC_RGBA:
3099     case VA_FOURCC_BGRX:
3100     case VA_FOURCC_RGBX:
3101         image->num_planes = 1;
3102         image->pitches[0] = awidth * 4;
3103         image->offsets[0] = 0;
3104         image->data_size  = image->offsets[0] + image->pitches[0] * aheight;
3105         break;
3106     case VA_FOURCC_YV12:
3107         image->num_planes = 3;
3108         image->pitches[0] = awidth;
3109         image->offsets[0] = 0;
3110         image->pitches[1] = awidth / 2;
3111         image->offsets[1] = size;
3112         image->pitches[2] = awidth / 2;
3113         image->offsets[2] = size + size2;
3114         image->data_size  = size + 2 * size2;
3115         break;
3116     case VA_FOURCC_I420:
3117         image->num_planes = 3;
3118         image->pitches[0] = awidth;
3119         image->offsets[0] = 0;
3120         image->pitches[1] = awidth / 2;
3121         image->offsets[1] = size;
3122         image->pitches[2] = awidth / 2;
3123         image->offsets[2] = size + size2;
3124         image->data_size  = size + 2 * size2;
3125         break;
3126     case VA_FOURCC_422H:
3127         image->num_planes = 3;
3128         image->pitches[0] = awidth;
3129         image->offsets[0] = 0;
3130         image->pitches[1] = awidth / 2;
3131         image->offsets[1] = size;
3132         image->pitches[2] = awidth / 2;
3133         image->offsets[2] = size + (awidth / 2) * aheight;
3134         image->data_size  = size + 2 * ((awidth / 2) * aheight);
3135         break;
3136     case VA_FOURCC_NV12:
3137         image->num_planes = 2;
3138         image->pitches[0] = awidth;
3139         image->offsets[0] = 0;
3140         image->pitches[1] = awidth;
3141         image->offsets[1] = size;
3142         image->data_size  = size + 2 * size2;
3143         break;
3144     case VA_FOURCC_YUY2:
3145     case VA_FOURCC_UYVY:
3146         image->num_planes = 1;
3147         image->pitches[0] = awidth * 2;
3148         image->offsets[0] = 0;
3149         image->data_size  = size * 2;
3150         break;
3151     default:
3152         goto error;
3153     }
3154
3155     va_status = i965_CreateBuffer(ctx, 0, VAImageBufferType,
3156                                   image->data_size, 1, NULL, &image->buf);
3157     if (va_status != VA_STATUS_SUCCESS)
3158         goto error;
3159
3160     struct object_buffer *obj_buffer = BUFFER(image->buf);
3161
3162     if (!obj_buffer ||
3163         !obj_buffer->buffer_store ||
3164         !obj_buffer->buffer_store->bo)
3165         return VA_STATUS_ERROR_ALLOCATION_FAILED;
3166
3167     obj_image->bo = obj_buffer->buffer_store->bo;
3168     dri_bo_reference(obj_image->bo);
3169
3170     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
3171         obj_image->palette = malloc(image->num_palette_entries * sizeof(*obj_image->palette));
3172         if (!obj_image->palette)
3173             goto error;
3174     }
3175
3176     image->image_id             = image_id;
3177     image->format               = *format;
3178     image->width                = width;
3179     image->height               = height;
3180
3181     *out_image                  = *image;
3182     return VA_STATUS_SUCCESS;
3183
3184  error:
3185     i965_DestroyImage(ctx, image_id);
3186     return va_status;
3187 }
3188
3189 VAStatus
3190 i965_check_alloc_surface_bo(VADriverContextP ctx,
3191                             struct object_surface *obj_surface,
3192                             int tiled,
3193                             unsigned int fourcc,
3194                             unsigned int subsampling)
3195 {
3196     struct i965_driver_data *i965 = i965_driver_data(ctx);
3197     int region_width, region_height;
3198
3199     if (obj_surface->bo) {
3200         ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
3201         ASSERT_RET(obj_surface->fourcc == fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
3202         ASSERT_RET(obj_surface->subsampling == subsampling, VA_STATUS_ERROR_INVALID_SURFACE);
3203         return VA_STATUS_SUCCESS;
3204     }
3205
3206     obj_surface->x_cb_offset = 0; /* X offset is always 0 */
3207     obj_surface->x_cr_offset = 0;
3208
3209     if ((tiled && !obj_surface->user_disable_tiling)) {
3210         ASSERT_RET(fourcc != VA_FOURCC_I420 &&
3211                fourcc != VA_FOURCC_IYUV &&
3212                fourcc != VA_FOURCC_YV12,
3213                VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT);
3214         if (obj_surface->user_h_stride_set) {
3215             ASSERT_RET(IS_ALIGNED(obj_surface->width, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
3216         } else
3217             obj_surface->width = ALIGN(obj_surface->orig_width, 128);
3218
3219         if (obj_surface->user_v_stride_set) {
3220             ASSERT_RET(IS_ALIGNED(obj_surface->height, 32), VA_STATUS_ERROR_INVALID_PARAMETER);
3221         } else
3222             obj_surface->height = ALIGN(obj_surface->orig_height, 32);
3223
3224         region_height = obj_surface->height;
3225
3226         switch (fourcc) {
3227         case VA_FOURCC_NV12:
3228             assert(subsampling == SUBSAMPLE_YUV420);
3229             obj_surface->cb_cr_pitch = obj_surface->width;
3230             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3231             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3232             obj_surface->y_cb_offset = obj_surface->height;
3233             obj_surface->y_cr_offset = obj_surface->height;
3234             region_width = obj_surface->width;
3235             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
3236             
3237             break;
3238
3239         case VA_FOURCC_IMC1:
3240             assert(subsampling == SUBSAMPLE_YUV420);
3241             obj_surface->cb_cr_pitch = obj_surface->width;
3242             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3243             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3244             obj_surface->y_cr_offset = obj_surface->height;
3245             obj_surface->y_cb_offset = obj_surface->y_cr_offset + ALIGN(obj_surface->cb_cr_height, 32);
3246             region_width = obj_surface->width;
3247             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
3248
3249             break;
3250
3251         case VA_FOURCC_IMC3:
3252             assert(subsampling == SUBSAMPLE_YUV420);
3253             obj_surface->cb_cr_pitch = obj_surface->width;
3254             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3255             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3256             obj_surface->y_cb_offset = obj_surface->height;
3257             obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
3258             region_width = obj_surface->width;
3259             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
3260             
3261             break;
3262
3263         case VA_FOURCC_422H:
3264             assert(subsampling == SUBSAMPLE_YUV422H);
3265             obj_surface->cb_cr_pitch = obj_surface->width;
3266             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3267             obj_surface->cb_cr_height = obj_surface->orig_height;
3268             obj_surface->y_cb_offset = obj_surface->height;
3269             obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
3270             region_width = obj_surface->width;
3271             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
3272
3273             break;
3274
3275         case VA_FOURCC_422V:
3276             assert(subsampling == SUBSAMPLE_YUV422V);
3277             obj_surface->cb_cr_pitch = obj_surface->width;
3278             obj_surface->cb_cr_width = obj_surface->orig_width;
3279             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3280             obj_surface->y_cb_offset = obj_surface->height;
3281             obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
3282             region_width = obj_surface->width;
3283             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
3284
3285             break;
3286
3287         case VA_FOURCC_411P:
3288             assert(subsampling == SUBSAMPLE_YUV411);
3289             obj_surface->cb_cr_pitch = obj_surface->width;
3290             obj_surface->cb_cr_width = obj_surface->orig_width / 4;
3291             obj_surface->cb_cr_height = obj_surface->orig_height;
3292             obj_surface->y_cb_offset = obj_surface->height;
3293             obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
3294             region_width = obj_surface->width;
3295             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
3296
3297             break;
3298
3299         case VA_FOURCC_444P:
3300             assert(subsampling == SUBSAMPLE_YUV444);
3301             obj_surface->cb_cr_pitch = obj_surface->width;
3302             obj_surface->cb_cr_width = obj_surface->orig_width;
3303             obj_surface->cb_cr_height = obj_surface->orig_height;
3304             obj_surface->y_cb_offset = obj_surface->height;
3305             obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
3306             region_width = obj_surface->width;
3307             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
3308
3309             break;
3310
3311         case VA_FOURCC_Y800:
3312             assert(subsampling == SUBSAMPLE_YUV400);
3313             obj_surface->cb_cr_pitch = 0;
3314             obj_surface->cb_cr_width = 0;
3315             obj_surface->cb_cr_height = 0;
3316             obj_surface->y_cb_offset = 0;
3317             obj_surface->y_cr_offset = 0;
3318             region_width = obj_surface->width;
3319             region_height = obj_surface->height;
3320
3321             break;
3322
3323         case VA_FOURCC_YUY2:
3324         case VA_FOURCC_UYVY:
3325             assert(subsampling == SUBSAMPLE_YUV422H);
3326             obj_surface->width = ALIGN(obj_surface->orig_width * 2, 128);
3327             obj_surface->cb_cr_pitch = obj_surface->width;
3328             obj_surface->y_cb_offset = 0; 
3329             obj_surface->y_cr_offset = 0; 
3330             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3331             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3332             region_width = obj_surface->width;
3333             region_height = obj_surface->height;
3334             
3335             break;
3336
3337         case VA_FOURCC_RGBA:
3338         case VA_FOURCC_RGBX:
3339         case VA_FOURCC_BGRA:
3340         case VA_FOURCC_BGRX:
3341             assert(subsampling == SUBSAMPLE_RGBX);
3342
3343             obj_surface->width = ALIGN(obj_surface->orig_width * 4, 128);
3344             region_width = obj_surface->width;
3345             region_height = obj_surface->height;
3346             break;
3347
3348         default:
3349             /* Never get here */
3350             ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT);
3351             break;
3352         }
3353     } else {
3354         assert(subsampling == SUBSAMPLE_YUV420 || 
3355                subsampling == SUBSAMPLE_YUV422H || 
3356                subsampling == SUBSAMPLE_YUV422V ||
3357                subsampling == SUBSAMPLE_RGBX);
3358
3359         region_width = obj_surface->width;
3360         region_height = obj_surface->height;
3361
3362         switch (fourcc) {
3363         case VA_FOURCC_NV12:
3364             obj_surface->y_cb_offset = obj_surface->height;
3365             obj_surface->y_cr_offset = obj_surface->height;
3366             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3367             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3368             obj_surface->cb_cr_pitch = obj_surface->width;
3369             region_height = obj_surface->height + obj_surface->height / 2;
3370             break;
3371
3372         case VA_FOURCC_YV16:
3373             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3374             obj_surface->cb_cr_height = obj_surface->orig_height;
3375             obj_surface->y_cr_offset = obj_surface->height;
3376             obj_surface->y_cb_offset = obj_surface->y_cr_offset + ALIGN(obj_surface->cb_cr_height, 32) / 2;
3377             obj_surface->cb_cr_pitch = obj_surface->width / 2;
3378             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
3379             break;
3380
3381         case VA_FOURCC_YV12:
3382         case VA_FOURCC_I420:
3383             if (fourcc == VA_FOURCC_YV12) {
3384                 obj_surface->y_cr_offset = obj_surface->height;
3385                 obj_surface->y_cb_offset = obj_surface->height + obj_surface->height / 4;
3386             } else {
3387                 obj_surface->y_cb_offset = obj_surface->height;
3388                 obj_surface->y_cr_offset = obj_surface->height + obj_surface->height / 4;
3389             }
3390
3391             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3392             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
3393             obj_surface->cb_cr_pitch = obj_surface->width / 2;
3394             region_height = obj_surface->height + obj_surface->height / 2;
3395             break;
3396
3397         case VA_FOURCC_YUY2:
3398         case VA_FOURCC_UYVY:
3399             obj_surface->width = ALIGN(obj_surface->orig_width * 2, i965->codec_info->min_linear_wpitch);
3400             obj_surface->y_cb_offset = 0;
3401             obj_surface->y_cr_offset = 0;
3402             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
3403             obj_surface->cb_cr_height = obj_surface->orig_height;
3404             obj_surface->cb_cr_pitch = obj_surface->width;
3405             region_width = obj_surface->width;
3406             region_height = obj_surface->height;
3407             break;
3408         case VA_FOURCC_RGBA:
3409         case VA_FOURCC_RGBX:
3410         case VA_FOURCC_BGRA:
3411         case VA_FOURCC_BGRX:
3412             obj_surface->width = ALIGN(obj_surface->orig_width * 4, i965->codec_info->min_linear_wpitch);
3413             region_width = obj_surface->width;
3414             region_height = obj_surface->height;
3415             break;
3416
3417         default:
3418             /* Never get here */
3419             ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT);
3420             break;
3421         }
3422     }
3423
3424     obj_surface->size = ALIGN(region_width * region_height, 0x1000);
3425
3426     if ((tiled && !obj_surface->user_disable_tiling)) {
3427         uint32_t tiling_mode = I915_TILING_Y; /* always uses Y-tiled format */
3428         unsigned long pitch;
3429
3430         obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr, 
3431                                                    "vaapi surface",
3432                                                    region_width,
3433                                                    region_height,
3434                                                    1,
3435                                                    &tiling_mode,
3436                                                    &pitch,
3437                                                    0);
3438         assert(tiling_mode == I915_TILING_Y);
3439         assert(pitch == obj_surface->width);
3440     } else {
3441         obj_surface->bo = dri_bo_alloc(i965->intel.bufmgr,
3442                                        "vaapi surface",
3443                                        obj_surface->size,
3444                                        0x1000);
3445     }
3446
3447     obj_surface->fourcc = fourcc;
3448     obj_surface->subsampling = subsampling;
3449     assert(obj_surface->bo);
3450     return VA_STATUS_SUCCESS;
3451 }
3452
3453 VAStatus i965_DeriveImage(VADriverContextP ctx,
3454                           VASurfaceID surface,
3455                           VAImage *out_image)        /* out */
3456 {
3457     struct i965_driver_data *i965 = i965_driver_data(ctx);
3458     struct object_image *obj_image;
3459     struct object_surface *obj_surface; 
3460     VAImageID image_id;
3461     unsigned int w_pitch;
3462     VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED;
3463
3464     out_image->image_id = VA_INVALID_ID;
3465     obj_surface = SURFACE(surface);
3466
3467     if (!obj_surface)
3468         return VA_STATUS_ERROR_INVALID_SURFACE;
3469
3470     if (!obj_surface->bo) {
3471         unsigned int is_tiled = 0;
3472         unsigned int fourcc = VA_FOURCC_YV12;
3473         i965_guess_surface_format(ctx, surface, &fourcc, &is_tiled);
3474         int sampling = get_sampling_from_fourcc(fourcc);
3475         va_status = i965_check_alloc_surface_bo(ctx, obj_surface, is_tiled, fourcc, sampling);
3476         if (va_status != VA_STATUS_SUCCESS)
3477             return va_status;
3478     }
3479
3480     ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
3481
3482     w_pitch = obj_surface->width;
3483
3484     image_id = NEW_IMAGE_ID();
3485
3486     if (image_id == VA_INVALID_ID)
3487         return VA_STATUS_ERROR_ALLOCATION_FAILED;
3488
3489     obj_image = IMAGE(image_id);
3490     
3491     if (!obj_image)
3492         return VA_STATUS_ERROR_ALLOCATION_FAILED;
3493
3494     obj_image->bo = NULL;
3495     obj_image->palette = NULL;
3496     obj_image->derived_surface = VA_INVALID_ID;
3497
3498     VAImage * const image = &obj_image->image;
3499     
3500     memset(image, 0, sizeof(*image));
3501     image->image_id = image_id;
3502     image->buf = VA_INVALID_ID;
3503     image->num_palette_entries = 0;
3504     image->entry_bytes = 0;
3505     image->width = obj_surface->orig_width;
3506     image->height = obj_surface->orig_height;
3507     image->data_size = obj_surface->size;
3508
3509     image->format.fourcc = obj_surface->fourcc;
3510     image->format.byte_order = VA_LSB_FIRST;
3511     image->format.bits_per_pixel = 12;
3512
3513     switch (image->format.fourcc) {
3514     case VA_FOURCC_YV12:
3515         image->num_planes = 3;
3516         image->pitches[0] = w_pitch; /* Y */
3517         image->offsets[0] = 0;
3518         image->pitches[1] = obj_surface->cb_cr_pitch; /* V */
3519         image->offsets[1] = w_pitch * obj_surface->y_cr_offset;
3520         image->pitches[2] = obj_surface->cb_cr_pitch; /* U */
3521         image->offsets[2] = w_pitch * obj_surface->y_cb_offset;
3522         break;
3523
3524     case VA_FOURCC_YV16:
3525         image->num_planes = 3;
3526         image->pitches[0] = w_pitch; /* Y */
3527         image->offsets[0] = 0;
3528         image->pitches[1] = obj_surface->cb_cr_pitch; /* V */
3529         image->offsets[1] = w_pitch * obj_surface->y_cr_offset;
3530         image->pitches[2] = obj_surface->cb_cr_pitch; /* U */
3531         image->offsets[2] = w_pitch * obj_surface->y_cb_offset;
3532         break;
3533
3534     case VA_FOURCC_NV12:
3535         image->num_planes = 2;
3536         image->pitches[0] = w_pitch; /* Y */
3537         image->offsets[0] = 0;
3538         image->pitches[1] = obj_surface->cb_cr_pitch; /* UV */
3539         image->offsets[1] = w_pitch * obj_surface->y_cb_offset;
3540         break;
3541
3542     case VA_FOURCC_I420:
3543     case VA_FOURCC_422H:
3544     case VA_FOURCC_IMC3:
3545     case VA_FOURCC_444P:
3546     case VA_FOURCC_422V:
3547     case VA_FOURCC_411P:
3548         image->num_planes = 3;
3549         image->pitches[0] = w_pitch; /* Y */
3550         image->offsets[0] = 0;
3551         image->pitches[1] = obj_surface->cb_cr_pitch; /* U */
3552         image->offsets[1] = w_pitch * obj_surface->y_cb_offset;
3553         image->pitches[2] = obj_surface->cb_cr_pitch; /* V */
3554         image->offsets[2] = w_pitch * obj_surface->y_cr_offset;
3555         break;
3556
3557     case VA_FOURCC_YUY2:
3558     case VA_FOURCC_UYVY:
3559     case VA_FOURCC_Y800:
3560         image->num_planes = 1;
3561         image->pitches[0] = obj_surface->width; /* Y, width is aligned already */
3562         image->offsets[0] = 0;
3563         break;
3564     case VA_FOURCC_RGBA:
3565     case VA_FOURCC_RGBX:
3566     case VA_FOURCC_BGRA:
3567     case VA_FOURCC_BGRX:
3568         image->num_planes = 1;
3569         image->pitches[0] = obj_surface->width;
3570         break;
3571     default:
3572         goto error;
3573     }
3574
3575     va_status = i965_create_buffer_internal(ctx, 0, VAImageBufferType,
3576                                             obj_surface->size, 1, NULL, obj_surface->bo, &image->buf);
3577     if (va_status != VA_STATUS_SUCCESS)
3578         goto error;
3579
3580     struct object_buffer *obj_buffer = BUFFER(image->buf);
3581
3582     if (!obj_buffer ||
3583         !obj_buffer->buffer_store ||
3584         !obj_buffer->buffer_store->bo)
3585         return VA_STATUS_ERROR_ALLOCATION_FAILED;
3586
3587     obj_image->bo = obj_buffer->buffer_store->bo;
3588     dri_bo_reference(obj_image->bo);
3589
3590     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
3591         obj_image->palette = malloc(image->num_palette_entries * sizeof(*obj_image->palette));
3592         if (!obj_image->palette) {
3593             va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
3594             goto error;
3595         }
3596     }
3597
3598     *out_image = *image;
3599     obj_surface->flags |= SURFACE_DERIVED;
3600     obj_image->derived_surface = surface;
3601
3602     return VA_STATUS_SUCCESS;
3603
3604  error:
3605     i965_DestroyImage(ctx, image_id);
3606     return va_status;
3607 }
3608
3609 static void 
3610 i965_destroy_image(struct object_heap *heap, struct object_base *obj)
3611 {
3612     object_heap_free(heap, obj);
3613 }
3614
3615
3616 VAStatus 
3617 i965_DestroyImage(VADriverContextP ctx, VAImageID image)
3618 {
3619     struct i965_driver_data *i965 = i965_driver_data(ctx);
3620     struct object_image *obj_image = IMAGE(image); 
3621     struct object_surface *obj_surface; 
3622
3623     if (!obj_image)
3624         return VA_STATUS_SUCCESS;
3625
3626     dri_bo_unreference(obj_image->bo);
3627     obj_image->bo = NULL;
3628
3629     if (obj_image->image.buf != VA_INVALID_ID) {
3630         i965_DestroyBuffer(ctx, obj_image->image.buf);
3631         obj_image->image.buf = VA_INVALID_ID;
3632     }
3633
3634     if (obj_image->palette) {
3635         free(obj_image->palette);
3636         obj_image->palette = NULL;
3637     }
3638
3639     obj_surface = SURFACE(obj_image->derived_surface);
3640
3641     if (obj_surface) {
3642         obj_surface->flags &= ~SURFACE_DERIVED;
3643     }
3644
3645     i965_destroy_image(&i965->image_heap, (struct object_base *)obj_image);
3646
3647     return VA_STATUS_SUCCESS;
3648 }
3649
3650 /*
3651  * pointer to an array holding the palette data.  The size of the array is
3652  * num_palette_entries * entry_bytes in size.  The order of the components
3653  * in the palette is described by the component_order in VASubpicture struct
3654  */
3655 VAStatus 
3656 i965_SetImagePalette(VADriverContextP ctx,
3657                      VAImageID image,
3658                      unsigned char *palette)
3659 {
3660     struct i965_driver_data *i965 = i965_driver_data(ctx);
3661     unsigned int i;
3662
3663     struct object_image *obj_image = IMAGE(image);
3664     if (!obj_image)
3665         return VA_STATUS_ERROR_INVALID_IMAGE;
3666
3667     if (!obj_image->palette)
3668         return VA_STATUS_ERROR_ALLOCATION_FAILED; /* XXX: unpaletted/error */
3669
3670     for (i = 0; i < obj_image->image.num_palette_entries; i++)
3671         obj_image->palette[i] = (((unsigned int)palette[3*i + 0] << 16) |
3672                                  ((unsigned int)palette[3*i + 1] <<  8) |
3673                                  (unsigned int)palette[3*i + 2]);
3674     return VA_STATUS_SUCCESS;
3675 }
3676
3677 static int 
3678 get_sampling_from_fourcc(unsigned int fourcc)
3679 {
3680     const i965_fourcc_info *info = get_fourcc_info(fourcc);
3681
3682     if (info && (info->flag & I_S))
3683         return info->subsampling;
3684     else
3685         return -1;
3686 }
3687
3688 static inline void
3689 memcpy_pic(uint8_t *dst, unsigned int dst_stride,
3690            const uint8_t *src, unsigned int src_stride,
3691            unsigned int len, unsigned int height)
3692 {
3693     unsigned int i;
3694
3695     for (i = 0; i < height; i++) {
3696         memcpy(dst, src, len);
3697         dst += dst_stride;
3698         src += src_stride;
3699     }
3700 }
3701
3702 static VAStatus
3703 get_image_i420(struct object_image *obj_image, uint8_t *image_data,
3704                struct object_surface *obj_surface,
3705                const VARectangle *rect)
3706 {
3707     uint8_t *dst[3], *src[3];
3708     const int Y = 0;
3709     const int U = obj_image->image.format.fourcc == obj_surface->fourcc ? 1 : 2;
3710     const int V = obj_image->image.format.fourcc == obj_surface->fourcc ? 2 : 1;
3711     unsigned int tiling, swizzle;
3712     VAStatus va_status = VA_STATUS_SUCCESS;
3713
3714     if (!obj_surface->bo)
3715         return VA_STATUS_ERROR_INVALID_SURFACE;
3716
3717     ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
3718     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
3719
3720     if (tiling != I915_TILING_NONE)
3721         drm_intel_gem_bo_map_gtt(obj_surface->bo);
3722     else
3723         dri_bo_map(obj_surface->bo, 0);
3724
3725     if (!obj_surface->bo->virtual)
3726         return VA_STATUS_ERROR_INVALID_SURFACE;
3727
3728     /* Dest VA image has either I420 or YV12 format.
3729        Source VA surface alway has I420 format */
3730     dst[Y] = image_data + obj_image->image.offsets[Y];
3731     src[0] = (uint8_t *)obj_surface->bo->virtual;
3732     dst[U] = image_data + obj_image->image.offsets[U];
3733     src[1] = src[0] + obj_surface->width * obj_surface->height;
3734     dst[V] = image_data + obj_image->image.offsets[V];
3735     src[2] = src[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
3736
3737     /* Y plane */
3738     dst[Y] += rect->y * obj_image->image.pitches[Y] + rect->x;
3739     src[0] += rect->y * obj_surface->width + rect->x;
3740     memcpy_pic(dst[Y], obj_image->image.pitches[Y],
3741                src[0], obj_surface->width,
3742                rect->width, rect->height);
3743
3744     /* U plane */
3745     dst[U] += (rect->y / 2) * obj_image->image.pitches[U] + rect->x / 2;
3746     src[1] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2;
3747     memcpy_pic(dst[U], obj_image->image.pitches[U],
3748                src[1], obj_surface->width / 2,
3749                rect->width / 2, rect->height / 2);
3750
3751     /* V plane */
3752     dst[V] += (rect->y / 2) * obj_image->image.pitches[V] + rect->x / 2;
3753     src[2] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2;
3754     memcpy_pic(dst[V], obj_image->image.pitches[V],
3755                src[2], obj_surface->width / 2,
3756                rect->width / 2, rect->height / 2);
3757
3758     if (tiling != I915_TILING_NONE)
3759         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
3760     else
3761         dri_bo_unmap(obj_surface->bo);
3762
3763     return va_status;
3764 }
3765
3766 static VAStatus
3767 get_image_nv12(struct object_image *obj_image, uint8_t *image_data,
3768                struct object_surface *obj_surface,
3769                const VARectangle *rect)
3770 {
3771     uint8_t *dst[2], *src[2];
3772     unsigned int tiling, swizzle;
3773     VAStatus va_status = VA_STATUS_SUCCESS;
3774
3775     if (!obj_surface->bo)
3776         return VA_STATUS_ERROR_INVALID_SURFACE;
3777
3778     assert(obj_surface->fourcc);
3779     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
3780
3781     if (tiling != I915_TILING_NONE)
3782         drm_intel_gem_bo_map_gtt(obj_surface->bo);
3783     else
3784         dri_bo_map(obj_surface->bo, 0);
3785
3786     if (!obj_surface->bo->virtual)
3787         return VA_STATUS_ERROR_INVALID_SURFACE;
3788
3789     /* Both dest VA image and source surface have NV12 format */
3790     dst[0] = image_data + obj_image->image.offsets[0];
3791     src[0] = (uint8_t *)obj_surface->bo->virtual;
3792     dst[1] = image_data + obj_image->image.offsets[1];
3793     src[1] = src[0] + obj_surface->width * obj_surface->height;
3794
3795     /* Y plane */
3796     dst[0] += rect->y * obj_image->image.pitches[0] + rect->x;
3797     src[0] += rect->y * obj_surface->width + rect->x;
3798     memcpy_pic(dst[0], obj_image->image.pitches[0],
3799                src[0], obj_surface->width,
3800                rect->width, rect->height);
3801
3802     /* UV plane */
3803     dst[1] += (rect->y / 2) * obj_image->image.pitches[1] + (rect->x & -2);
3804     src[1] += (rect->y / 2) * obj_surface->width + (rect->x & -2);
3805     memcpy_pic(dst[1], obj_image->image.pitches[1],
3806                src[1], obj_surface->width,
3807                rect->width, rect->height / 2);
3808
3809     if (tiling != I915_TILING_NONE)
3810         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
3811     else
3812         dri_bo_unmap(obj_surface->bo);
3813
3814     return va_status;
3815 }
3816
3817 static VAStatus
3818 get_image_yuy2(struct object_image *obj_image, uint8_t *image_data,
3819                struct object_surface *obj_surface,
3820                const VARectangle *rect)
3821 {
3822     uint8_t *dst, *src;
3823     unsigned int tiling, swizzle;
3824     VAStatus va_status = VA_STATUS_SUCCESS;
3825
3826     if (!obj_surface->bo)
3827         return VA_STATUS_ERROR_INVALID_SURFACE;
3828
3829     assert(obj_surface->fourcc);
3830     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
3831
3832     if (tiling != I915_TILING_NONE)
3833         drm_intel_gem_bo_map_gtt(obj_surface->bo);
3834     else
3835         dri_bo_map(obj_surface->bo, 0);
3836
3837     if (!obj_surface->bo->virtual)
3838         return VA_STATUS_ERROR_INVALID_SURFACE;
3839
3840     /* Both dest VA image and source surface have YUYV format */
3841     dst = image_data + obj_image->image.offsets[0];
3842     src = (uint8_t *)obj_surface->bo->virtual;
3843
3844     /* Y plane */
3845     dst += rect->y * obj_image->image.pitches[0] + rect->x*2;
3846     src += rect->y * obj_surface->width + rect->x*2;
3847     memcpy_pic(dst, obj_image->image.pitches[0],
3848                src, obj_surface->width*2,
3849                rect->width*2, rect->height);
3850
3851     if (tiling != I915_TILING_NONE)
3852         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
3853     else
3854         dri_bo_unmap(obj_surface->bo);
3855
3856     return va_status;
3857 }
3858
3859 static VAStatus 
3860 i965_sw_getimage(VADriverContextP ctx,
3861                  VASurfaceID surface,
3862                  int x,   /* coordinates of the upper left source pixel */
3863                  int y,
3864                  unsigned int width,      /* width and height of the region */
3865                  unsigned int height,
3866                  VAImageID image)
3867 {
3868     struct i965_driver_data *i965 = i965_driver_data(ctx);
3869     struct i965_render_state *render_state = &i965->render_state;
3870     VAStatus va_status = VA_STATUS_SUCCESS;
3871
3872     struct object_surface *obj_surface = SURFACE(surface);
3873     if (!obj_surface)
3874         return VA_STATUS_ERROR_INVALID_SURFACE;
3875
3876     struct object_image *obj_image = IMAGE(image);
3877     if (!obj_image)
3878         return VA_STATUS_ERROR_INVALID_IMAGE;
3879
3880     if (x < 0 || y < 0)
3881         return VA_STATUS_ERROR_INVALID_PARAMETER;
3882     if (x + width > obj_surface->orig_width ||
3883         y + height > obj_surface->orig_height)
3884         return VA_STATUS_ERROR_INVALID_PARAMETER;
3885     if (x + width > obj_image->image.width ||
3886         y + height > obj_image->image.height)
3887         return VA_STATUS_ERROR_INVALID_PARAMETER;
3888
3889     if (obj_surface->fourcc != obj_image->image.format.fourcc)
3890         return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
3891
3892     void *image_data = NULL;
3893
3894     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
3895     if (va_status != VA_STATUS_SUCCESS)
3896         return va_status;
3897
3898     VARectangle rect;
3899     rect.x = x;
3900     rect.y = y;
3901     rect.width = width;
3902     rect.height = height;
3903
3904     switch (obj_image->image.format.fourcc) {
3905     case VA_FOURCC_YV12:
3906     case VA_FOURCC_I420:
3907         /* I420 is native format for MPEG-2 decoded surfaces */
3908         if (render_state->interleaved_uv)
3909             goto operation_failed;
3910         get_image_i420(obj_image, image_data, obj_surface, &rect);
3911         break;
3912     case VA_FOURCC_NV12:
3913         /* NV12 is native format for H.264 decoded surfaces */
3914         if (!render_state->interleaved_uv)
3915             goto operation_failed;
3916         get_image_nv12(obj_image, image_data, obj_surface, &rect);
3917         break;
3918     case VA_FOURCC_YUY2:
3919         /* YUY2 is the format supported by overlay plane */
3920         get_image_yuy2(obj_image, image_data, obj_surface, &rect);
3921         break;
3922     default:
3923     operation_failed:
3924         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
3925         break;
3926     }
3927
3928     if (va_status != VA_STATUS_SUCCESS)
3929         return va_status;
3930
3931     va_status = i965_UnmapBuffer(ctx, obj_image->image.buf);
3932     return va_status;
3933 }
3934
3935 static VAStatus 
3936 i965_hw_getimage(VADriverContextP ctx,
3937                  VASurfaceID surface,
3938                  int x,   /* coordinates of the upper left source pixel */
3939                  int y,
3940                  unsigned int width,      /* width and height of the region */
3941                  unsigned int height,
3942                  VAImageID image)
3943 {
3944     struct i965_driver_data *i965 = i965_driver_data(ctx);
3945     struct i965_surface src_surface;
3946     struct i965_surface dst_surface;
3947     VAStatus va_status = VA_STATUS_SUCCESS;
3948     VARectangle rect;
3949     struct object_surface *obj_surface = SURFACE(surface);
3950     struct object_image *obj_image = IMAGE(image);
3951
3952     if (!obj_surface)
3953         return VA_STATUS_ERROR_INVALID_SURFACE;
3954
3955     if (!obj_image)
3956         return VA_STATUS_ERROR_INVALID_IMAGE;
3957
3958     if (x < 0 || y < 0)
3959         return VA_STATUS_ERROR_INVALID_PARAMETER;
3960     if (x + width > obj_surface->orig_width ||
3961         y + height > obj_surface->orig_height)
3962         return VA_STATUS_ERROR_INVALID_PARAMETER;
3963     if (x + width > obj_image->image.width ||
3964         y + height > obj_image->image.height)
3965         return VA_STATUS_ERROR_INVALID_PARAMETER;
3966
3967     if (!obj_surface->bo)
3968         return VA_STATUS_SUCCESS;
3969     assert(obj_image->bo); // image bo is always created, see i965_CreateImage()
3970
3971     rect.x = x;
3972     rect.y = y;
3973     rect.width = width;
3974     rect.height = height;
3975
3976     src_surface.base = (struct object_base *)obj_surface;
3977     src_surface.type = I965_SURFACE_TYPE_SURFACE;
3978     src_surface.flags = I965_SURFACE_FLAG_FRAME;
3979
3980     dst_surface.base = (struct object_base *)obj_image;
3981     dst_surface.type = I965_SURFACE_TYPE_IMAGE;
3982     dst_surface.flags = I965_SURFACE_FLAG_FRAME;
3983
3984     va_status = i965_image_processing(ctx,
3985                                       &src_surface,
3986                                       &rect,
3987                                       &dst_surface,
3988                                       &rect);
3989
3990
3991     return va_status;
3992 }
3993
3994 VAStatus 
3995 i965_GetImage(VADriverContextP ctx,
3996               VASurfaceID surface,
3997               int x,   /* coordinates of the upper left source pixel */
3998               int y,
3999               unsigned int width,      /* width and height of the region */
4000               unsigned int height,
4001               VAImageID image)
4002 {
4003     struct i965_driver_data * const i965 = i965_driver_data(ctx);
4004     VAStatus va_status = VA_STATUS_SUCCESS;
4005
4006     if (HAS_ACCELERATED_GETIMAGE(i965))
4007         va_status = i965_hw_getimage(ctx,
4008                                      surface,
4009                                      x, y,
4010                                      width, height,
4011                                      image);
4012     else
4013         va_status = i965_sw_getimage(ctx,
4014                                      surface,
4015                                      x, y,
4016                                      width, height,
4017                                      image);
4018
4019     return va_status;
4020 }
4021
4022 static VAStatus
4023 put_image_i420(struct object_surface *obj_surface,
4024                const VARectangle *dst_rect,
4025                struct object_image *obj_image, uint8_t *image_data,
4026                const VARectangle *src_rect)
4027 {
4028     uint8_t *dst[3], *src[3];
4029     const int Y = 0;
4030     const int U = obj_image->image.format.fourcc == obj_surface->fourcc ? 1 : 2;
4031     const int V = obj_image->image.format.fourcc == obj_surface->fourcc ? 2 : 1;
4032     unsigned int tiling, swizzle;
4033     VAStatus va_status = VA_STATUS_SUCCESS;
4034
4035     ASSERT_RET(obj_surface->bo, VA_STATUS_ERROR_INVALID_SURFACE);
4036
4037     ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
4038     ASSERT_RET(dst_rect->width == src_rect->width, VA_STATUS_ERROR_UNIMPLEMENTED);
4039     ASSERT_RET(dst_rect->height == src_rect->height, VA_STATUS_ERROR_UNIMPLEMENTED);
4040     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
4041
4042     if (tiling != I915_TILING_NONE)
4043         drm_intel_gem_bo_map_gtt(obj_surface->bo);
4044     else
4045         dri_bo_map(obj_surface->bo, 0);
4046
4047     if (!obj_surface->bo->virtual)
4048         return VA_STATUS_ERROR_INVALID_SURFACE;
4049
4050     /* Dest VA image has either I420 or YV12 format.
4051        Source VA surface alway has I420 format */
4052     dst[0] = (uint8_t *)obj_surface->bo->virtual;
4053     src[Y] = image_data + obj_image->image.offsets[Y];
4054     dst[1] = dst[0] + obj_surface->width * obj_surface->height;
4055     src[U] = image_data + obj_image->image.offsets[U];
4056     dst[2] = dst[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
4057     src[V] = image_data + obj_image->image.offsets[V];
4058
4059     /* Y plane */
4060     dst[0] += dst_rect->y * obj_surface->width + dst_rect->x;
4061     src[Y] += src_rect->y * obj_image->image.pitches[Y] + src_rect->x;
4062     memcpy_pic(dst[0], obj_surface->width,
4063                src[Y], obj_image->image.pitches[Y],
4064                src_rect->width, src_rect->height);
4065
4066     /* U plane */
4067     dst[1] += (dst_rect->y / 2) * obj_surface->width / 2 + dst_rect->x / 2;
4068     src[U] += (src_rect->y / 2) * obj_image->image.pitches[U] + src_rect->x / 2;
4069     memcpy_pic(dst[1], obj_surface->width / 2,
4070                src[U], obj_image->image.pitches[U],
4071                src_rect->width / 2, src_rect->height / 2);
4072
4073     /* V plane */
4074     dst[2] += (dst_rect->y / 2) * obj_surface->width / 2 + dst_rect->x / 2;
4075     src[V] += (src_rect->y / 2) * obj_image->image.pitches[V] + src_rect->x / 2;
4076     memcpy_pic(dst[2], obj_surface->width / 2,
4077                src[V], obj_image->image.pitches[V],
4078                src_rect->width / 2, src_rect->height / 2);
4079
4080     if (tiling != I915_TILING_NONE)
4081         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
4082     else
4083         dri_bo_unmap(obj_surface->bo);
4084
4085     return va_status;
4086 }
4087
4088 static VAStatus
4089 put_image_nv12(struct object_surface *obj_surface,
4090                const VARectangle *dst_rect,
4091                struct object_image *obj_image, uint8_t *image_data,
4092                const VARectangle *src_rect)
4093 {
4094     uint8_t *dst[2], *src[2];
4095     unsigned int tiling, swizzle;
4096     VAStatus va_status = VA_STATUS_SUCCESS;
4097
4098     if (!obj_surface->bo)
4099         return VA_STATUS_ERROR_INVALID_SURFACE;
4100
4101     ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
4102     ASSERT_RET(dst_rect->width == src_rect->width, VA_STATUS_ERROR_UNIMPLEMENTED);
4103     ASSERT_RET(dst_rect->height == src_rect->height, VA_STATUS_ERROR_UNIMPLEMENTED);
4104     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
4105
4106     if (tiling != I915_TILING_NONE)
4107         drm_intel_gem_bo_map_gtt(obj_surface->bo);
4108     else
4109         dri_bo_map(obj_surface->bo, 0);
4110
4111     if (!obj_surface->bo->virtual)
4112         return VA_STATUS_ERROR_INVALID_SURFACE;
4113
4114     /* Both dest VA image and source surface have NV12 format */
4115     dst[0] = (uint8_t *)obj_surface->bo->virtual;
4116     src[0] = image_data + obj_image->image.offsets[0];
4117     dst[1] = dst[0] + obj_surface->width * obj_surface->height;
4118     src[1] = image_data + obj_image->image.offsets[1];
4119
4120     /* Y plane */
4121     dst[0] += dst_rect->y * obj_surface->width + dst_rect->x;
4122     src[0] += src_rect->y * obj_image->image.pitches[0] + src_rect->x;
4123     memcpy_pic(dst[0], obj_surface->width,
4124                src[0], obj_image->image.pitches[0],
4125                src_rect->width, src_rect->height);
4126
4127     /* UV plane */
4128     dst[1] += (dst_rect->y / 2) * obj_surface->width + (dst_rect->x & -2);
4129     src[1] += (src_rect->y / 2) * obj_image->image.pitches[1] + (src_rect->x & -2);
4130     memcpy_pic(dst[1], obj_surface->width,
4131                src[1], obj_image->image.pitches[1],
4132                src_rect->width, src_rect->height / 2);
4133
4134     if (tiling != I915_TILING_NONE)
4135         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
4136     else
4137         dri_bo_unmap(obj_surface->bo);
4138
4139     return va_status;
4140 }
4141
4142 static VAStatus
4143 put_image_yuy2(struct object_surface *obj_surface,
4144                const VARectangle *dst_rect,
4145                struct object_image *obj_image, uint8_t *image_data,
4146                const VARectangle *src_rect)
4147 {
4148     uint8_t *dst, *src;
4149     unsigned int tiling, swizzle;
4150     VAStatus va_status = VA_STATUS_SUCCESS;
4151
4152     ASSERT_RET(obj_surface->bo, VA_STATUS_ERROR_INVALID_SURFACE);
4153     ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
4154     ASSERT_RET(dst_rect->width == src_rect->width, VA_STATUS_ERROR_UNIMPLEMENTED);
4155     ASSERT_RET(dst_rect->height == src_rect->height, VA_STATUS_ERROR_UNIMPLEMENTED);
4156     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
4157
4158     if (tiling != I915_TILING_NONE)
4159         drm_intel_gem_bo_map_gtt(obj_surface->bo);
4160     else
4161         dri_bo_map(obj_surface->bo, 0);
4162
4163     if (!obj_surface->bo->virtual)
4164         return VA_STATUS_ERROR_INVALID_SURFACE;
4165
4166     /* Both dest VA image and source surface have YUY2 format */
4167     dst = (uint8_t *)obj_surface->bo->virtual;
4168     src = image_data + obj_image->image.offsets[0];
4169
4170     /* YUYV packed plane */
4171     dst += dst_rect->y * obj_surface->width + dst_rect->x*2;
4172     src += src_rect->y * obj_image->image.pitches[0] + src_rect->x*2;
4173     memcpy_pic(dst, obj_surface->width*2,
4174                src, obj_image->image.pitches[0],
4175                src_rect->width*2, src_rect->height);
4176
4177     if (tiling != I915_TILING_NONE)
4178         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
4179     else
4180         dri_bo_unmap(obj_surface->bo);
4181
4182     return va_status;
4183 }
4184
4185
4186 static VAStatus
4187 i965_sw_putimage(VADriverContextP ctx,
4188                  VASurfaceID surface,
4189                  VAImageID image,
4190                  int src_x,
4191                  int src_y,
4192                  unsigned int src_width,
4193                  unsigned int src_height,
4194                  int dest_x,
4195                  int dest_y,
4196                  unsigned int dest_width,
4197                  unsigned int dest_height)
4198 {
4199     struct i965_driver_data *i965 = i965_driver_data(ctx);
4200     struct object_surface *obj_surface = SURFACE(surface);
4201     struct object_image *obj_image = IMAGE(image);
4202     VAStatus va_status = VA_STATUS_SUCCESS;
4203     void *image_data = NULL;
4204
4205     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
4206     ASSERT_RET(obj_image, VA_STATUS_ERROR_INVALID_IMAGE);
4207
4208     if (src_x < 0 || src_y < 0)
4209         return VA_STATUS_ERROR_INVALID_PARAMETER;
4210     if (src_x + src_width > obj_image->image.width ||
4211         src_y + src_height > obj_image->image.height)
4212         return VA_STATUS_ERROR_INVALID_PARAMETER;
4213     if (dest_x < 0 || dest_y < 0)
4214         return VA_STATUS_ERROR_INVALID_PARAMETER;
4215     if (dest_x + dest_width > obj_surface->orig_width ||
4216         dest_y + dest_height > obj_surface->orig_height)
4217         return VA_STATUS_ERROR_INVALID_PARAMETER;
4218
4219     /* XXX: don't allow scaling */
4220     if (src_width != dest_width || src_height != dest_height)
4221         return VA_STATUS_ERROR_INVALID_PARAMETER;
4222
4223     if (obj_surface->fourcc) {
4224         /* Don't allow format mismatch */
4225         if (obj_surface->fourcc != obj_image->image.format.fourcc)
4226             return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
4227     }
4228
4229     else {
4230         /* VA is surface not used for decoding, use same VA image format */
4231         va_status = i965_check_alloc_surface_bo(
4232             ctx,
4233             obj_surface,
4234             0, /* XXX: don't use tiled surface */
4235             obj_image->image.format.fourcc,
4236             get_sampling_from_fourcc (obj_image->image.format.fourcc));
4237     }
4238
4239     if (va_status != VA_STATUS_SUCCESS)
4240         return va_status;
4241
4242     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
4243     if (va_status != VA_STATUS_SUCCESS)
4244         return va_status;
4245
4246     VARectangle src_rect, dest_rect;
4247     src_rect.x       = src_x;
4248     src_rect.y       = src_y;
4249     src_rect.width   = src_width;
4250     src_rect.height  = src_height;
4251     dest_rect.x      = dest_x;
4252     dest_rect.y      = dest_y;
4253     dest_rect.width  = dest_width;
4254     dest_rect.height = dest_height;
4255      
4256     switch (obj_image->image.format.fourcc) {
4257     case VA_FOURCC_YV12:
4258     case VA_FOURCC_I420:
4259         va_status = put_image_i420(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
4260         break;
4261     case VA_FOURCC_NV12:
4262         va_status = put_image_nv12(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
4263         break;
4264     case VA_FOURCC_YUY2:
4265         va_status = put_image_yuy2(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
4266         break;
4267     default:
4268         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
4269         break;
4270     }
4271     if (va_status != VA_STATUS_SUCCESS)
4272         return va_status;
4273
4274     va_status = i965_UnmapBuffer(ctx, obj_image->image.buf);
4275     return va_status;
4276 }
4277
4278 static VAStatus 
4279 i965_hw_putimage(VADriverContextP ctx,
4280                  VASurfaceID surface,
4281                  VAImageID image,
4282                  int src_x,
4283                  int src_y,
4284                  unsigned int src_width,
4285                  unsigned int src_height,
4286                  int dest_x,
4287                  int dest_y,
4288                  unsigned int dest_width,
4289                  unsigned int dest_height)
4290 {
4291     struct i965_driver_data *i965 = i965_driver_data(ctx);
4292     struct object_surface *obj_surface = SURFACE(surface);
4293     struct object_image *obj_image = IMAGE(image);
4294     struct i965_surface src_surface, dst_surface;
4295     VAStatus va_status = VA_STATUS_SUCCESS;
4296     VARectangle src_rect, dst_rect;
4297
4298     ASSERT_RET(obj_surface,VA_STATUS_ERROR_INVALID_SURFACE);
4299     ASSERT_RET(obj_image && obj_image->bo, VA_STATUS_ERROR_INVALID_IMAGE);
4300
4301     if (src_x < 0 ||
4302         src_y < 0 ||
4303         src_x + src_width > obj_image->image.width ||
4304         src_y + src_height > obj_image->image.height)
4305         return VA_STATUS_ERROR_INVALID_PARAMETER;
4306
4307     if (dest_x < 0 ||
4308         dest_y < 0 ||
4309         dest_x + dest_width > obj_surface->orig_width ||
4310         dest_y + dest_height > obj_surface->orig_height)
4311         return VA_STATUS_ERROR_INVALID_PARAMETER;
4312
4313     if (!obj_surface->bo) {
4314         unsigned int tiling, swizzle;
4315         int surface_sampling = get_sampling_from_fourcc (obj_image->image.format.fourcc);;
4316         dri_bo_get_tiling(obj_image->bo, &tiling, &swizzle);
4317
4318         i965_check_alloc_surface_bo(ctx,
4319                                     obj_surface,
4320                                     !!tiling,
4321                                     obj_image->image.format.fourcc,
4322                                     surface_sampling);
4323     }
4324
4325     ASSERT_RET(obj_surface->fourcc, VA_STATUS_ERROR_INVALID_SURFACE);
4326
4327     src_surface.base = (struct object_base *)obj_image;
4328     src_surface.type = I965_SURFACE_TYPE_IMAGE;
4329     src_surface.flags = I965_SURFACE_FLAG_FRAME;
4330     src_rect.x = src_x;
4331     src_rect.y = src_y;
4332     src_rect.width = src_width;
4333     src_rect.height = src_height;
4334
4335     dst_surface.base = (struct object_base *)obj_surface;
4336     dst_surface.type = I965_SURFACE_TYPE_SURFACE;
4337     dst_surface.flags = I965_SURFACE_FLAG_FRAME;
4338     dst_rect.x = dest_x;
4339     dst_rect.y = dest_y;
4340     dst_rect.width = dest_width;
4341     dst_rect.height = dest_height;
4342
4343     va_status = i965_image_processing(ctx,
4344                                       &src_surface,
4345                                       &src_rect,
4346                                       &dst_surface,
4347                                       &dst_rect);
4348
4349     return  va_status;
4350 }
4351
4352 static VAStatus 
4353 i965_PutImage(VADriverContextP ctx,
4354               VASurfaceID surface,
4355               VAImageID image,
4356               int src_x,
4357               int src_y,
4358               unsigned int src_width,
4359               unsigned int src_height,
4360               int dest_x,
4361               int dest_y,
4362               unsigned int dest_width,
4363               unsigned int dest_height)
4364 {
4365     struct i965_driver_data *i965 = i965_driver_data(ctx);
4366     VAStatus va_status = VA_STATUS_SUCCESS;
4367
4368     if (HAS_ACCELERATED_PUTIMAGE(i965))
4369         va_status = i965_hw_putimage(ctx,
4370                                      surface,
4371                                      image,
4372                                      src_x,
4373                                      src_y,
4374                                      src_width,
4375                                      src_height,
4376                                      dest_x,
4377                                      dest_y,
4378                                      dest_width,
4379                                      dest_height);
4380     else 
4381         va_status = i965_sw_putimage(ctx,
4382                                      surface,
4383                                      image,
4384                                      src_x,
4385                                      src_y,
4386                                      src_width,
4387                                      src_height,
4388                                      dest_x,
4389                                      dest_y,
4390                                      dest_width,
4391                                      dest_height);
4392
4393     return va_status;
4394 }
4395
4396 VAStatus 
4397 i965_PutSurface(VADriverContextP ctx,
4398                 VASurfaceID surface,
4399                 void *draw, /* X Drawable */
4400                 short srcx,
4401                 short srcy,
4402                 unsigned short srcw,
4403                 unsigned short srch,
4404                 short destx,
4405                 short desty,
4406                 unsigned short destw,
4407                 unsigned short desth,
4408                 VARectangle *cliprects, /* client supplied clip list */
4409                 unsigned int number_cliprects, /* number of clip rects in the clip list */
4410                 unsigned int flags) /* de-interlacing flags */
4411 {
4412 #ifdef HAVE_VA_X11
4413     if (IS_VA_X11(ctx)) {
4414         VARectangle src_rect, dst_rect;
4415
4416         src_rect.x      = srcx;
4417         src_rect.y      = srcy;
4418         src_rect.width  = srcw;
4419         src_rect.height = srch;
4420
4421         dst_rect.x      = destx;
4422         dst_rect.y      = desty;
4423         dst_rect.width  = destw;
4424         dst_rect.height = desth;
4425
4426         return i965_put_surface_dri(ctx, surface, draw, &src_rect, &dst_rect,
4427                                     cliprects, number_cliprects, flags);
4428     }
4429 #endif
4430     return VA_STATUS_ERROR_UNIMPLEMENTED;
4431 }
4432
4433 static VAStatus
4434 i965_BufferInfo(
4435     VADriverContextP ctx,       /* in */
4436     VABufferID buf_id,          /* in */
4437     VABufferType *type,         /* out */
4438     unsigned int *size,         /* out */
4439     unsigned int *num_elements  /* out */
4440 )
4441 {
4442     struct i965_driver_data *i965 = NULL;
4443     struct object_buffer *obj_buffer = NULL;
4444
4445     i965 = i965_driver_data(ctx);
4446     obj_buffer = BUFFER(buf_id);
4447
4448     ASSERT_RET(obj_buffer, VA_STATUS_ERROR_INVALID_BUFFER);
4449
4450     *type = obj_buffer->type;
4451     *size = obj_buffer->size_element;
4452     *num_elements = obj_buffer->num_elements;
4453
4454     return VA_STATUS_SUCCESS;
4455 }
4456
4457 static VAStatus
4458 i965_LockSurface(
4459     VADriverContextP ctx,           /* in */
4460     VASurfaceID surface,            /* in */
4461     unsigned int *fourcc,           /* out */
4462     unsigned int *luma_stride,      /* out */
4463     unsigned int *chroma_u_stride,  /* out */
4464     unsigned int *chroma_v_stride,  /* out */
4465     unsigned int *luma_offset,      /* out */
4466     unsigned int *chroma_u_offset,  /* out */
4467     unsigned int *chroma_v_offset,  /* out */
4468     unsigned int *buffer_name,      /* out */
4469     void **buffer                   /* out */
4470 )
4471 {
4472     VAStatus vaStatus = VA_STATUS_SUCCESS;
4473     struct i965_driver_data *i965 = i965_driver_data(ctx);
4474     struct object_surface *obj_surface = NULL;
4475     VAImage tmpImage;
4476
4477     ASSERT_RET(fourcc, VA_STATUS_ERROR_INVALID_PARAMETER);
4478     ASSERT_RET(luma_stride, VA_STATUS_ERROR_INVALID_PARAMETER);
4479     ASSERT_RET(chroma_u_stride, VA_STATUS_ERROR_INVALID_PARAMETER);
4480     ASSERT_RET(chroma_v_stride, VA_STATUS_ERROR_INVALID_PARAMETER);
4481     ASSERT_RET(luma_offset, VA_STATUS_ERROR_INVALID_PARAMETER);
4482     ASSERT_RET(chroma_u_offset, VA_STATUS_ERROR_INVALID_PARAMETER);
4483     ASSERT_RET(chroma_v_offset, VA_STATUS_ERROR_INVALID_PARAMETER);
4484     ASSERT_RET(buffer_name, VA_STATUS_ERROR_INVALID_PARAMETER);
4485     ASSERT_RET(buffer, VA_STATUS_ERROR_INVALID_PARAMETER);
4486
4487     tmpImage.image_id = VA_INVALID_ID;
4488
4489     obj_surface = SURFACE(surface);
4490     if (obj_surface == NULL) {
4491         // Surface is absent.
4492         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
4493         goto error;
4494     }
4495
4496     // Lock functionality is absent now.
4497     if (obj_surface->locked_image_id != VA_INVALID_ID) {
4498         // Surface is locked already.
4499         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
4500         goto error;
4501     }
4502
4503     vaStatus = i965_DeriveImage(
4504         ctx,
4505         surface,
4506         &tmpImage);
4507     if (vaStatus != VA_STATUS_SUCCESS) {
4508         goto error;
4509     }
4510
4511     obj_surface->locked_image_id = tmpImage.image_id;
4512
4513     vaStatus = i965_MapBuffer(
4514         ctx,
4515         tmpImage.buf,
4516         buffer);
4517     if (vaStatus != VA_STATUS_SUCCESS) {
4518         goto error;
4519     }
4520
4521     *fourcc = tmpImage.format.fourcc;
4522     *luma_offset = tmpImage.offsets[0];
4523     *luma_stride = tmpImage.pitches[0];
4524     *chroma_u_offset = tmpImage.offsets[1];
4525     *chroma_u_stride = tmpImage.pitches[1];
4526     *chroma_v_offset = tmpImage.offsets[2];
4527     *chroma_v_stride = tmpImage.pitches[2];
4528     *buffer_name = tmpImage.buf;
4529
4530 error:
4531     if (vaStatus != VA_STATUS_SUCCESS) {
4532         buffer = NULL;
4533     }
4534
4535     return vaStatus;
4536 }
4537
4538 static VAStatus
4539 i965_UnlockSurface(
4540     VADriverContextP ctx,   /* in */
4541     VASurfaceID surface     /* in */
4542 )
4543 {
4544     VAStatus vaStatus = VA_STATUS_SUCCESS;
4545     struct i965_driver_data *i965 = i965_driver_data(ctx);
4546     struct object_image *locked_img = NULL;
4547     struct object_surface *obj_surface = NULL;
4548
4549     obj_surface = SURFACE(surface);
4550
4551     if (obj_surface == NULL) {
4552         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;   // Surface is absent
4553         return vaStatus;
4554     }
4555     if (obj_surface->locked_image_id == VA_INVALID_ID) {
4556         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;   // Surface is not locked
4557         return vaStatus;
4558     }
4559
4560     locked_img = IMAGE(obj_surface->locked_image_id);
4561     if (locked_img == NULL || (locked_img->image.image_id == VA_INVALID_ID)) {
4562         // Work image was deallocated before i965_UnlockSurface()
4563         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
4564         goto error;
4565     }
4566
4567     vaStatus = i965_UnmapBuffer(
4568         ctx,
4569         locked_img->image.buf);
4570     if (vaStatus != VA_STATUS_SUCCESS) {
4571         goto error;
4572     }
4573
4574     vaStatus = i965_DestroyImage(
4575         ctx,
4576         locked_img->image.image_id);
4577     if (vaStatus != VA_STATUS_SUCCESS) {
4578         goto error;
4579     }
4580
4581     locked_img->image.image_id = VA_INVALID_ID;
4582
4583  error:
4584     obj_surface->locked_image_id = VA_INVALID_ID;
4585
4586     return vaStatus;
4587 }
4588
4589 static VAStatus
4590 i965_GetSurfaceAttributes(
4591     VADriverContextP ctx,
4592     VAConfigID config,
4593     VASurfaceAttrib *attrib_list,
4594     unsigned int num_attribs
4595     )
4596 {
4597     VAStatus vaStatus = VA_STATUS_SUCCESS;
4598     struct i965_driver_data *i965 = i965_driver_data(ctx);
4599     struct object_config *obj_config;
4600     int i;
4601
4602     if (config == VA_INVALID_ID)
4603         return VA_STATUS_ERROR_INVALID_CONFIG;
4604
4605     obj_config = CONFIG(config);
4606
4607     if (obj_config == NULL)
4608         return VA_STATUS_ERROR_INVALID_CONFIG;
4609     
4610     if (attrib_list == NULL || num_attribs == 0)
4611         return VA_STATUS_ERROR_INVALID_PARAMETER;
4612
4613     for (i = 0; i < num_attribs; i++) {
4614         switch (attrib_list[i].type) {
4615         case VASurfaceAttribPixelFormat:
4616             attrib_list[i].value.type = VAGenericValueTypeInteger;
4617             attrib_list[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4618
4619             if (attrib_list[i].value.value.i == 0) {
4620                 if (IS_G4X(i965->intel.device_info)) {
4621                     if (obj_config->profile == VAProfileMPEG2Simple ||
4622                         obj_config->profile == VAProfileMPEG2Main) {
4623                         attrib_list[i].value.value.i = VA_FOURCC_I420;
4624                     } else {
4625                         assert(0);
4626                         attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4627                     }
4628                 } else if (IS_IRONLAKE(i965->intel.device_info)) {
4629                     if (obj_config->profile == VAProfileMPEG2Simple ||
4630                         obj_config->profile == VAProfileMPEG2Main) {
4631                         attrib_list[i].value.value.i = VA_FOURCC_I420;
4632                     } else if (obj_config->profile == VAProfileH264ConstrainedBaseline ||
4633                                obj_config->profile == VAProfileH264Main ||
4634                                obj_config->profile == VAProfileH264High) {
4635                         attrib_list[i].value.value.i = VA_FOURCC_NV12;
4636                     } else if (obj_config->profile == VAProfileNone) {
4637                         attrib_list[i].value.value.i = VA_FOURCC_NV12;
4638                     } else {
4639                         assert(0);
4640                         attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4641                     }
4642                 } else if (IS_GEN6(i965->intel.device_info)) {
4643                     attrib_list[i].value.value.i = VA_FOURCC_NV12;
4644                 } else if (IS_GEN7(i965->intel.device_info) ||
4645                            IS_GEN8(i965->intel.device_info)) {
4646                     if (obj_config->profile == VAProfileJPEGBaseline)
4647                         attrib_list[i].value.value.i = 0; /* internal format */
4648                     else
4649                         attrib_list[i].value.value.i = VA_FOURCC_NV12;
4650                 }
4651             } else {
4652                 if (IS_G4X(i965->intel.device_info)) {
4653                     if (obj_config->profile == VAProfileMPEG2Simple ||
4654                         obj_config->profile == VAProfileMPEG2Main) {
4655                         if (attrib_list[i].value.value.i != VA_FOURCC_I420) {
4656                             attrib_list[i].value.value.i = 0;
4657                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4658                         }
4659                     } else {
4660                         assert(0);
4661                         attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4662                     }
4663                 } else if (IS_IRONLAKE(i965->intel.device_info)) {
4664                     if (obj_config->profile == VAProfileMPEG2Simple ||
4665                         obj_config->profile == VAProfileMPEG2Main) {
4666                         if (attrib_list[i].value.value.i != VA_FOURCC_I420) {
4667                             attrib_list[i].value.value.i = 0;                            
4668                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4669                         }
4670                     } else if (obj_config->profile == VAProfileH264ConstrainedBaseline ||
4671                                obj_config->profile == VAProfileH264Main ||
4672                                obj_config->profile == VAProfileH264High) {
4673                         if (attrib_list[i].value.value.i != VA_FOURCC_NV12) {
4674                             attrib_list[i].value.value.i = 0;
4675                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4676                         }
4677                     } else if (obj_config->profile == VAProfileNone) {
4678                         switch (attrib_list[i].value.value.i) {
4679                         case VA_FOURCC_NV12:
4680                         case VA_FOURCC_I420:
4681                         case VA_FOURCC_YV12:
4682                         case VA_FOURCC_YUY2:
4683                         case VA_FOURCC_BGRA:
4684                         case VA_FOURCC_BGRX:
4685                         case VA_FOURCC_RGBX:
4686                         case VA_FOURCC_RGBA:
4687                             break;
4688                         default:
4689                             attrib_list[i].value.value.i = 0;                            
4690                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4691                             break;
4692                         }
4693                     } else {
4694                         assert(0);
4695                         attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4696                     }
4697                 } else if (IS_GEN6(i965->intel.device_info)) {
4698                     if (obj_config->entrypoint == VAEntrypointEncSlice ||
4699                         obj_config->entrypoint == VAEntrypointVideoProc) {
4700                         switch (attrib_list[i].value.value.i) {
4701                         case VA_FOURCC_NV12:
4702                         case VA_FOURCC_I420:
4703                         case VA_FOURCC_YV12:
4704                         case VA_FOURCC_YUY2:
4705                         case VA_FOURCC_BGRA:
4706                         case VA_FOURCC_BGRX:
4707                         case VA_FOURCC_RGBX:
4708                         case VA_FOURCC_RGBA:
4709                             break;
4710                         default:
4711                             attrib_list[i].value.value.i = 0;                            
4712                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4713                             break;
4714                         }
4715                     } else {
4716                         if (attrib_list[i].value.value.i != VA_FOURCC_NV12) {
4717                             attrib_list[i].value.value.i = 0;
4718                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4719                         }
4720                     }
4721                 } else if (IS_GEN7(i965->intel.device_info) ||
4722                            IS_GEN8(i965->intel.device_info)) {
4723                     if (obj_config->entrypoint == VAEntrypointEncSlice ||
4724                         obj_config->entrypoint == VAEntrypointVideoProc) {
4725                         switch (attrib_list[i].value.value.i) {
4726                         case VA_FOURCC_NV12:
4727                         case VA_FOURCC_I420:
4728                         case VA_FOURCC_YV12:
4729                             break;
4730                         default:
4731                             attrib_list[i].value.value.i = 0;                            
4732                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4733                             break;
4734                         }
4735                     } else {
4736                         if (obj_config->profile == VAProfileJPEGBaseline) {
4737                             attrib_list[i].value.value.i = 0;   /* JPEG decoding always uses an internal format */
4738                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4739                         } else {
4740                             if (attrib_list[i].value.value.i != VA_FOURCC_NV12) {
4741                                 attrib_list[i].value.value.i = 0;
4742                                 attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
4743                             }
4744                         }
4745                     }
4746                 }
4747             }
4748
4749             break;
4750         case VASurfaceAttribMinWidth:
4751             /* FIXME: add support for it later */
4752             attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4753             break;
4754         case VASurfaceAttribMaxWidth:
4755             attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4756             break;
4757         case VASurfaceAttribMinHeight:
4758             attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4759             break;
4760         case VASurfaceAttribMaxHeight:
4761             attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4762             break;
4763         default:
4764             attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
4765             break;
4766         }
4767     }
4768
4769     return vaStatus;
4770 }
4771
4772 static VAStatus
4773 i965_QuerySurfaceAttributes(VADriverContextP ctx,
4774                             VAConfigID config,
4775                             VASurfaceAttrib *attrib_list,
4776                             unsigned int *num_attribs)
4777 {
4778     VAStatus vaStatus = VA_STATUS_SUCCESS;
4779     struct i965_driver_data *i965 = i965_driver_data(ctx);
4780     struct object_config *obj_config;
4781     int i = 0;
4782     VASurfaceAttrib *attribs = NULL;
4783     
4784     if (config == VA_INVALID_ID)
4785         return VA_STATUS_ERROR_INVALID_CONFIG;
4786
4787     obj_config = CONFIG(config);
4788
4789     if (obj_config == NULL)
4790         return VA_STATUS_ERROR_INVALID_CONFIG;
4791     
4792     if (!attrib_list && !num_attribs)
4793         return VA_STATUS_ERROR_INVALID_PARAMETER;
4794
4795     if (attrib_list == NULL) {
4796         *num_attribs = I965_MAX_SURFACE_ATTRIBUTES;
4797         return VA_STATUS_SUCCESS;
4798     }
4799
4800     attribs = malloc(I965_MAX_SURFACE_ATTRIBUTES *sizeof(*attribs));
4801     
4802     if (attribs == NULL)
4803         return VA_STATUS_ERROR_ALLOCATION_FAILED;
4804
4805     if (IS_G4X(i965->intel.device_info)) {
4806         if (obj_config->profile == VAProfileMPEG2Simple ||
4807             obj_config->profile == VAProfileMPEG2Main) {
4808             attribs[i].type = VASurfaceAttribPixelFormat;
4809             attribs[i].value.type = VAGenericValueTypeInteger;
4810             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4811             attribs[i].value.value.i = VA_FOURCC_I420;
4812             i++;
4813         }
4814     } else if (IS_IRONLAKE(i965->intel.device_info)) {
4815         switch (obj_config->profile) {
4816         case VAProfileMPEG2Simple:
4817         case VAProfileMPEG2Main:
4818             attribs[i].type = VASurfaceAttribPixelFormat;
4819             attribs[i].value.type = VAGenericValueTypeInteger;
4820             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4821             attribs[i].value.value.i = VA_FOURCC_I420;
4822             i++;
4823             
4824             break;
4825
4826         case VAProfileH264ConstrainedBaseline:
4827         case VAProfileH264Main:
4828         case VAProfileH264High:
4829             attribs[i].type = VASurfaceAttribPixelFormat;
4830             attribs[i].value.type = VAGenericValueTypeInteger;
4831             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4832             attribs[i].value.value.i = VA_FOURCC_NV12;
4833             i++;
4834
4835         case VAProfileNone:
4836             attribs[i].type = VASurfaceAttribPixelFormat;
4837             attribs[i].value.type = VAGenericValueTypeInteger;
4838             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4839             attribs[i].value.value.i = VA_FOURCC_NV12;
4840             i++;
4841
4842             attribs[i].type = VASurfaceAttribPixelFormat;
4843             attribs[i].value.type = VAGenericValueTypeInteger;
4844             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4845             attribs[i].value.value.i = VA_FOURCC_I420;
4846             i++;
4847
4848             break;
4849             
4850         default:
4851             break;
4852         }
4853     } else if (IS_GEN6(i965->intel.device_info)) {
4854         if (obj_config->entrypoint == VAEntrypointVLD) { /* decode */
4855             attribs[i].type = VASurfaceAttribPixelFormat;
4856             attribs[i].value.type = VAGenericValueTypeInteger;
4857             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4858             attribs[i].value.value.i = VA_FOURCC_NV12;
4859             i++;
4860         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
4861                    obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */ 
4862             attribs[i].type = VASurfaceAttribPixelFormat;
4863             attribs[i].value.type = VAGenericValueTypeInteger;
4864             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4865             attribs[i].value.value.i = VA_FOURCC_NV12;
4866             i++;
4867
4868             attribs[i].type = VASurfaceAttribPixelFormat;
4869             attribs[i].value.type = VAGenericValueTypeInteger;
4870             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4871             attribs[i].value.value.i = VA_FOURCC_I420;
4872             i++;
4873
4874             attribs[i].type = VASurfaceAttribPixelFormat;
4875             attribs[i].value.type = VAGenericValueTypeInteger;
4876             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4877             attribs[i].value.value.i = VA_FOURCC_YV12;
4878             i++;
4879
4880             if (obj_config->entrypoint == VAEntrypointVideoProc) {
4881                 attribs[i].type = VASurfaceAttribPixelFormat;
4882                 attribs[i].value.type = VAGenericValueTypeInteger;
4883                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4884                 attribs[i].value.value.i = VA_FOURCC_YUY2;
4885                 i++;
4886
4887                 attribs[i].type = VASurfaceAttribPixelFormat;
4888                 attribs[i].value.type = VAGenericValueTypeInteger;
4889                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4890                 attribs[i].value.value.i = VA_FOURCC_RGBA;
4891                 i++;
4892
4893                 attribs[i].type = VASurfaceAttribPixelFormat;
4894                 attribs[i].value.type = VAGenericValueTypeInteger;
4895                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4896                 attribs[i].value.value.i = VA_FOURCC_RGBX;
4897                 i++;
4898             }
4899         }
4900     } else if (IS_GEN7(i965->intel.device_info)) {
4901         if (obj_config->entrypoint == VAEntrypointVLD) { /* decode */
4902             if (obj_config->profile == VAProfileJPEGBaseline) {
4903                 attribs[i].type = VASurfaceAttribPixelFormat;
4904                 attribs[i].value.type = VAGenericValueTypeInteger;
4905                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4906                 attribs[i].value.value.i = VA_FOURCC_IMC3;
4907                 i++;
4908
4909                 attribs[i].type = VASurfaceAttribPixelFormat;
4910                 attribs[i].value.type = VAGenericValueTypeInteger;
4911                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4912                 attribs[i].value.value.i = VA_FOURCC_IMC1;
4913                 i++;
4914
4915                 attribs[i].type = VASurfaceAttribPixelFormat;
4916                 attribs[i].value.type = VAGenericValueTypeInteger;
4917                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4918                 attribs[i].value.value.i = VA_FOURCC_Y800;
4919                 i++;
4920
4921                 attribs[i].type = VASurfaceAttribPixelFormat;
4922                 attribs[i].value.type = VAGenericValueTypeInteger;
4923                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4924                 attribs[i].value.value.i = VA_FOURCC_411P;
4925                 i++;
4926
4927                 attribs[i].type = VASurfaceAttribPixelFormat;
4928                 attribs[i].value.type = VAGenericValueTypeInteger;
4929                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4930                 attribs[i].value.value.i = VA_FOURCC_422H;
4931                 i++;
4932
4933                 attribs[i].type = VASurfaceAttribPixelFormat;
4934                 attribs[i].value.type = VAGenericValueTypeInteger;
4935                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4936                 attribs[i].value.value.i = VA_FOURCC_422V;
4937                 i++;
4938
4939                 attribs[i].type = VASurfaceAttribPixelFormat;
4940                 attribs[i].value.type = VAGenericValueTypeInteger;
4941                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4942                 attribs[i].value.value.i = VA_FOURCC_444P;
4943                 i++;
4944             } else {
4945                 attribs[i].type = VASurfaceAttribPixelFormat;
4946                 attribs[i].value.type = VAGenericValueTypeInteger;
4947                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4948                 attribs[i].value.value.i = VA_FOURCC_NV12;
4949                 i++;
4950             }
4951         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
4952                    obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */ 
4953             attribs[i].type = VASurfaceAttribPixelFormat;
4954             attribs[i].value.type = VAGenericValueTypeInteger;
4955             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4956             attribs[i].value.value.i = VA_FOURCC_NV12;
4957             i++;
4958
4959             attribs[i].type = VASurfaceAttribPixelFormat;
4960             attribs[i].value.type = VAGenericValueTypeInteger;
4961             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4962             attribs[i].value.value.i = VA_FOURCC_I420;
4963             i++;
4964
4965             attribs[i].type = VASurfaceAttribPixelFormat;
4966             attribs[i].value.type = VAGenericValueTypeInteger;
4967             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4968             attribs[i].value.value.i = VA_FOURCC_YV12;
4969             i++;
4970
4971             attribs[i].type = VASurfaceAttribPixelFormat;
4972             attribs[i].value.type = VAGenericValueTypeInteger;
4973             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4974             attribs[i].value.value.i = VA_FOURCC_IMC3;
4975             i++;
4976
4977             if (obj_config->entrypoint == VAEntrypointVideoProc) {
4978                 attribs[i].type = VASurfaceAttribPixelFormat;
4979                 attribs[i].value.type = VAGenericValueTypeInteger;
4980                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4981                 attribs[i].value.value.i = VA_FOURCC_YUY2;
4982                 i++;
4983
4984                 attribs[i].type = VASurfaceAttribPixelFormat;
4985                 attribs[i].value.type = VAGenericValueTypeInteger;
4986                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4987                 attribs[i].value.value.i = VA_FOURCC_RGBA;
4988                 i++;
4989
4990                 attribs[i].type = VASurfaceAttribPixelFormat;
4991                 attribs[i].value.type = VAGenericValueTypeInteger;
4992                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4993                 attribs[i].value.value.i = VA_FOURCC_RGBX;
4994                 i++;
4995
4996                 attribs[i].type = VASurfaceAttribPixelFormat;
4997                 attribs[i].value.type = VAGenericValueTypeInteger;
4998                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
4999                 attribs[i].value.value.i = VA_FOURCC_YV16;
5000                 i++;
5001             }
5002         }
5003     } else if (IS_GEN8(i965->intel.device_info)) {
5004         if (obj_config->entrypoint == VAEntrypointVLD) { /* decode */
5005             if (obj_config->profile == VAProfileJPEGBaseline) {
5006                 attribs[i].type = VASurfaceAttribPixelFormat;
5007                 attribs[i].value.type = VAGenericValueTypeInteger;
5008                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5009                 attribs[i].value.value.i = VA_FOURCC_IMC3;
5010                 i++;
5011
5012                 attribs[i].type = VASurfaceAttribPixelFormat;
5013                 attribs[i].value.type = VAGenericValueTypeInteger;
5014                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5015                 attribs[i].value.value.i = VA_FOURCC_IMC1;
5016                 i++;
5017
5018                 attribs[i].type = VASurfaceAttribPixelFormat;
5019                 attribs[i].value.type = VAGenericValueTypeInteger;
5020                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5021                 attribs[i].value.value.i = VA_FOURCC_Y800;
5022                 i++;
5023
5024                 attribs[i].type = VASurfaceAttribPixelFormat;
5025                 attribs[i].value.type = VAGenericValueTypeInteger;
5026                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5027                 attribs[i].value.value.i = VA_FOURCC_411P;
5028                 i++;
5029
5030                 attribs[i].type = VASurfaceAttribPixelFormat;
5031                 attribs[i].value.type = VAGenericValueTypeInteger;
5032                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5033                 attribs[i].value.value.i = VA_FOURCC_422H;
5034                 i++;
5035
5036                 attribs[i].type = VASurfaceAttribPixelFormat;
5037                 attribs[i].value.type = VAGenericValueTypeInteger;
5038                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5039                 attribs[i].value.value.i = VA_FOURCC_422V;
5040                 i++;
5041
5042                 attribs[i].type = VASurfaceAttribPixelFormat;
5043                 attribs[i].value.type = VAGenericValueTypeInteger;
5044                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5045                 attribs[i].value.value.i = VA_FOURCC_444P;
5046                 i++;
5047             } else {
5048                 attribs[i].type = VASurfaceAttribPixelFormat;
5049                 attribs[i].value.type = VAGenericValueTypeInteger;
5050                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5051                 attribs[i].value.value.i = VA_FOURCC_NV12;
5052                 i++;
5053             }
5054         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
5055                    obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */
5056
5057             attribs[i].type = VASurfaceAttribPixelFormat;
5058             attribs[i].value.type = VAGenericValueTypeInteger;
5059             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5060             attribs[i].value.value.i = VA_FOURCC_NV12;
5061             i++;
5062
5063             attribs[i].type = VASurfaceAttribPixelFormat;
5064             attribs[i].value.type = VAGenericValueTypeInteger;
5065             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5066             attribs[i].value.value.i = VA_FOURCC_I420;
5067             i++;
5068
5069             attribs[i].type = VASurfaceAttribPixelFormat;
5070             attribs[i].value.type = VAGenericValueTypeInteger;
5071             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5072             attribs[i].value.value.i = VA_FOURCC_YV12;
5073             i++;
5074
5075             attribs[i].type = VASurfaceAttribPixelFormat;
5076             attribs[i].value.type = VAGenericValueTypeInteger;
5077             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5078             attribs[i].value.value.i = VA_FOURCC_IMC3;
5079             i++;
5080
5081             if (obj_config->entrypoint == VAEntrypointVideoProc) {
5082                 attribs[i].type = VASurfaceAttribPixelFormat;
5083                 attribs[i].value.type = VAGenericValueTypeInteger;
5084                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5085                 attribs[i].value.value.i = VA_FOURCC_YUY2;
5086                 i++;
5087
5088                 attribs[i].type = VASurfaceAttribPixelFormat;
5089                 attribs[i].value.type = VAGenericValueTypeInteger;
5090                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5091                 attribs[i].value.value.i = VA_FOURCC_RGBA;
5092                 i++;
5093
5094                 attribs[i].type = VASurfaceAttribPixelFormat;
5095                 attribs[i].value.type = VAGenericValueTypeInteger;
5096                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5097                 attribs[i].value.value.i = VA_FOURCC_RGBX;
5098                 i++;
5099
5100                 attribs[i].type = VASurfaceAttribPixelFormat;
5101                 attribs[i].value.type = VAGenericValueTypeInteger;
5102                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5103                 attribs[i].value.value.i = VA_FOURCC_BGRA;
5104                 i++;
5105
5106                 attribs[i].type = VASurfaceAttribPixelFormat;
5107                 attribs[i].value.type = VAGenericValueTypeInteger;
5108                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5109                 attribs[i].value.value.i = VA_FOURCC_BGRX;
5110                 i++;
5111
5112                 attribs[i].type = VASurfaceAttribPixelFormat;
5113                 attribs[i].value.type = VAGenericValueTypeInteger;
5114                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5115                 attribs[i].value.value.i = VA_FOURCC_YV16;
5116                 i++;
5117             }
5118         }
5119     }
5120
5121     attribs[i].type = VASurfaceAttribMemoryType;
5122     attribs[i].value.type = VAGenericValueTypeInteger;
5123     attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
5124     attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
5125         VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM |
5126         VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
5127     i++;
5128
5129     attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
5130     attribs[i].value.type = VAGenericValueTypePointer;
5131     attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
5132     attribs[i].value.value.p = NULL; /* ignore */
5133     i++;
5134
5135     if (i > *num_attribs) {
5136         *num_attribs = i;
5137         free(attribs);
5138         return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
5139     }
5140
5141     *num_attribs = i;
5142     memcpy(attrib_list, attribs, i * sizeof(*attribs));
5143     free(attribs);
5144
5145     return vaStatus;
5146 }
5147
5148 static int
5149 i965_os_has_ring_support(VADriverContextP ctx,
5150                          int ring)
5151 {
5152     struct i965_driver_data *const i965 = i965_driver_data(ctx);
5153
5154     switch (ring) {
5155     case I965_RING_BSD:
5156         return i965->intel.has_bsd;
5157         
5158     case I965_RING_BLT:
5159         return i965->intel.has_blt;
5160         
5161     case I965_RING_VEBOX:
5162         return i965->intel.has_vebox;
5163
5164     case I965_RING_NULL:
5165         return 1; /* Always support */
5166
5167     default:
5168         /* should never get here */
5169         assert(0);
5170         break;
5171     }
5172
5173     return 0;
5174 }
5175                                 
5176 /* 
5177  * Query video processing pipeline 
5178  */
5179 VAStatus i965_QueryVideoProcFilters(
5180     VADriverContextP    ctx,
5181     VAContextID         context,
5182     VAProcFilterType   *filters,
5183     unsigned int       *num_filters
5184     )
5185 {
5186     struct i965_driver_data *const i965 = i965_driver_data(ctx);
5187     unsigned int i = 0, num = 0;
5188
5189     if (!num_filters  || !filters)
5190         return VA_STATUS_ERROR_INVALID_PARAMETER;
5191
5192     for (i = 0; i < i965->codec_info->num_filters; i++) {
5193         if (i965_os_has_ring_support(ctx, i965->codec_info->filters[i].ring)) {
5194             if (num == *num_filters) {
5195                 *num_filters = i965->codec_info->num_filters;
5196
5197                 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
5198             }
5199          
5200             filters[num++] = i965->codec_info->filters[i].type;
5201         }
5202     }
5203
5204     *num_filters = num;
5205
5206     return VA_STATUS_SUCCESS;
5207 }
5208
5209 VAStatus i965_QueryVideoProcFilterCaps(
5210     VADriverContextP    ctx,
5211     VAContextID         context,
5212     VAProcFilterType    type,
5213     void               *filter_caps,
5214     unsigned int       *num_filter_caps
5215     )
5216 {
5217     unsigned int i = 0;
5218     struct i965_driver_data *const i965 = i965_driver_data(ctx);
5219
5220     if (!filter_caps || !num_filter_caps)
5221         return VA_STATUS_ERROR_INVALID_PARAMETER;
5222
5223     for (i = 0; i < i965->codec_info->num_filters; i++) {
5224         if (type == i965->codec_info->filters[i].type &&
5225             i965_os_has_ring_support(ctx, i965->codec_info->filters[i].ring))
5226             break;
5227     }
5228
5229     if (i == i965->codec_info->num_filters)
5230         return VA_STATUS_ERROR_UNSUPPORTED_FILTER;
5231
5232     i = 0;
5233
5234     switch (type) {
5235     case VAProcFilterNoiseReduction:
5236     case VAProcFilterSharpening:
5237         {
5238             VAProcFilterCap *cap = filter_caps;
5239
5240             if (*num_filter_caps < 1) {
5241                 *num_filter_caps = 1;
5242                 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
5243             }
5244             
5245             cap->range.min_value = 0.0;
5246             cap->range.max_value = 1.0;
5247             cap->range.default_value = 0.5;
5248             cap->range.step = 0.03125; /* 1.0 / 32 */
5249             i++;
5250         }
5251
5252         break;
5253
5254     case VAProcFilterDeinterlacing:
5255         {
5256             VAProcFilterCapDeinterlacing *cap = filter_caps;
5257
5258             if (*num_filter_caps < VAProcDeinterlacingCount) {
5259                 *num_filter_caps = VAProcDeinterlacingCount;
5260                 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
5261             }
5262         
5263             cap->type = VAProcDeinterlacingBob;
5264             i++;
5265             cap++;
5266
5267
5268             if (i965->codec_info->has_di_motion_adptive) {
5269                 cap->type = VAProcDeinterlacingMotionAdaptive;
5270                 i++;
5271                 cap++;
5272             }
5273
5274             if (i965->codec_info->has_di_motion_compensated) {
5275                 cap->type = VAProcDeinterlacingMotionCompensated;
5276                 i++;
5277                 cap++;
5278             }
5279        }
5280
5281         break;
5282
5283     case VAProcFilterColorBalance:
5284         {
5285             VAProcFilterCapColorBalance *cap = filter_caps;
5286
5287             if (*num_filter_caps < VAProcColorBalanceCount) {
5288                 *num_filter_caps = VAProcColorBalanceCount;
5289                 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
5290             }
5291
5292             cap->type = VAProcColorBalanceHue;
5293             cap->range.min_value = -180.0;
5294             cap->range.max_value = 180.0;
5295             cap->range.default_value = 0.0;
5296             cap->range.step = 1.0; 
5297             i++;
5298             cap++; 
5299  
5300             cap->type = VAProcColorBalanceSaturation;
5301             cap->range.min_value = 0.0;
5302             cap->range.max_value = 10.0;
5303             cap->range.default_value = 1.0;
5304             cap->range.step = 0.1; 
5305             i++;
5306             cap++; 
5307  
5308             cap->type = VAProcColorBalanceBrightness;
5309             cap->range.min_value = -100.0;
5310             cap->range.max_value = 100.0;
5311             cap->range.default_value = 0.0;
5312             cap->range.step = 1.0; 
5313             i++;
5314             cap++; 
5315  
5316             cap->type = VAProcColorBalanceContrast;
5317             cap->range.min_value = 0.0;
5318             cap->range.max_value = 10.0;
5319             cap->range.default_value = 1.0;
5320             cap->range.step = 0.1; 
5321             i++;
5322             cap++; 
5323         }
5324
5325         break;
5326
5327     default:
5328         
5329         break;
5330     }
5331
5332     *num_filter_caps = i;
5333
5334     return VA_STATUS_SUCCESS;
5335 }
5336
5337 static VAProcColorStandardType vpp_input_color_standards[VAProcColorStandardCount] = {
5338     VAProcColorStandardBT601,
5339 };
5340
5341 static VAProcColorStandardType vpp_output_color_standards[VAProcColorStandardCount] = {
5342     VAProcColorStandardBT601,
5343 };
5344
5345 VAStatus i965_QueryVideoProcPipelineCaps(
5346     VADriverContextP ctx,
5347     VAContextID context,
5348     VABufferID *filters,
5349     unsigned int num_filters,
5350     VAProcPipelineCaps *pipeline_cap     /* out */
5351     )
5352 {
5353     struct i965_driver_data * const i965 = i965_driver_data(ctx);
5354     unsigned int i = 0;
5355
5356     pipeline_cap->pipeline_flags = 0;
5357     pipeline_cap->filter_flags = 0;
5358     pipeline_cap->num_forward_references = 0;
5359     pipeline_cap->num_backward_references = 0;
5360     pipeline_cap->num_input_color_standards = 1;
5361     pipeline_cap->input_color_standards = vpp_input_color_standards;
5362     pipeline_cap->num_output_color_standards = 1;
5363     pipeline_cap->output_color_standards = vpp_output_color_standards;
5364
5365     for (i = 0; i < num_filters; i++) {
5366         struct object_buffer *obj_buffer = BUFFER(filters[i]);
5367
5368         if (!obj_buffer ||
5369             !obj_buffer->buffer_store ||
5370             !obj_buffer->buffer_store->buffer)
5371             return VA_STATUS_ERROR_INVALID_BUFFER;
5372
5373         VAProcFilterParameterBufferBase *base = (VAProcFilterParameterBufferBase *)obj_buffer->buffer_store->buffer;
5374
5375         if (base->type == VAProcFilterNoiseReduction) {
5376             VAProcFilterParameterBuffer *denoise = (VAProcFilterParameterBuffer *)base;
5377             (void)denoise;
5378         } else if (base->type == VAProcFilterDeinterlacing) {
5379             VAProcFilterParameterBufferDeinterlacing *deint = (VAProcFilterParameterBufferDeinterlacing *)base;
5380
5381             ASSERT_RET(deint->algorithm == VAProcDeinterlacingBob ||
5382                    deint->algorithm == VAProcDeinterlacingMotionAdaptive ||
5383                    deint->algorithm == VAProcDeinterlacingMotionCompensated,
5384                    VA_STATUS_ERROR_INVALID_PARAMETER);
5385             
5386             if (deint->algorithm == VAProcDeinterlacingMotionAdaptive ||
5387                 deint->algorithm == VAProcDeinterlacingMotionCompensated);
5388                 pipeline_cap->num_forward_references++;
5389         } else if (base->type == VAProcFilterSkinToneEnhancement) {
5390                 VAProcFilterParameterBuffer *stde = (VAProcFilterParameterBuffer *)base;
5391                 (void)stde;
5392         }
5393     }
5394
5395     return VA_STATUS_SUCCESS;
5396 }
5397
5398 extern const struct hw_codec_info *i965_get_codec_info(int devid);
5399
5400 static bool
5401 i965_driver_data_init(VADriverContextP ctx)
5402 {
5403     struct i965_driver_data *i965 = i965_driver_data(ctx); 
5404
5405     i965->codec_info = i965_get_codec_info(i965->intel.device_id);
5406
5407     if (!i965->codec_info)
5408         return false;
5409
5410     if (object_heap_init(&i965->config_heap,
5411                          sizeof(struct object_config),
5412                          CONFIG_ID_OFFSET))
5413         goto err_config_heap;
5414     if (object_heap_init(&i965->context_heap,
5415                          sizeof(struct object_context),
5416                          CONTEXT_ID_OFFSET))
5417         goto err_context_heap;
5418     
5419     if (object_heap_init(&i965->surface_heap,
5420                          sizeof(struct object_surface),
5421                          SURFACE_ID_OFFSET))
5422         goto err_surface_heap;
5423     if (object_heap_init(&i965->buffer_heap,
5424                          sizeof(struct object_buffer),
5425                          BUFFER_ID_OFFSET))
5426         goto err_buffer_heap;
5427     if (object_heap_init(&i965->image_heap,
5428                          sizeof(struct object_image),
5429                          IMAGE_ID_OFFSET))
5430         goto err_image_heap;
5431     if (object_heap_init(&i965->subpic_heap,
5432                          sizeof(struct object_subpic),
5433                          SUBPIC_ID_OFFSET))
5434         goto err_subpic_heap;
5435
5436     i965->batch = intel_batchbuffer_new(&i965->intel, I915_EXEC_RENDER, 0);
5437     i965->pp_batch = intel_batchbuffer_new(&i965->intel, I915_EXEC_RENDER, 0);
5438     _i965InitMutex(&i965->render_mutex);
5439     _i965InitMutex(&i965->pp_mutex);
5440
5441     return true;
5442
5443 err_subpic_heap:    
5444     object_heap_destroy(&i965->image_heap);
5445 err_image_heap:
5446     object_heap_destroy(&i965->buffer_heap);
5447 err_buffer_heap:
5448     object_heap_destroy(&i965->surface_heap);
5449 err_surface_heap:
5450     object_heap_destroy(&i965->context_heap);
5451 err_context_heap:
5452     object_heap_destroy(&i965->config_heap);
5453 err_config_heap:
5454
5455     return false;
5456 }
5457
5458 static void
5459 i965_driver_data_terminate(VADriverContextP ctx)
5460 {
5461     struct i965_driver_data *i965 = i965_driver_data(ctx); 
5462
5463     _i965DestroyMutex(&i965->pp_mutex);
5464     _i965DestroyMutex(&i965->render_mutex);
5465
5466     if (i965->batch)
5467         intel_batchbuffer_free(i965->batch);
5468
5469     if (i965->pp_batch)
5470         intel_batchbuffer_free(i965->pp_batch);
5471
5472     i965_destroy_heap(&i965->subpic_heap, i965_destroy_subpic);
5473     i965_destroy_heap(&i965->image_heap, i965_destroy_image);
5474     i965_destroy_heap(&i965->buffer_heap, i965_destroy_buffer);
5475     i965_destroy_heap(&i965->surface_heap, i965_destroy_surface);
5476     i965_destroy_heap(&i965->context_heap, i965_destroy_context);
5477     i965_destroy_heap(&i965->config_heap, i965_destroy_config);
5478 }
5479
5480 struct {
5481     bool (*init)(VADriverContextP ctx);
5482     void (*terminate)(VADriverContextP ctx);
5483     int display_type;
5484 } i965_sub_ops[] =  {
5485     {   
5486         intel_driver_init,
5487         intel_driver_terminate,
5488         0,
5489     },
5490
5491     {
5492         i965_driver_data_init,
5493         i965_driver_data_terminate,
5494         0,
5495     },
5496
5497     {
5498         i965_display_attributes_init,
5499         i965_display_attributes_terminate,
5500         0,
5501     },
5502
5503     {
5504         i965_post_processing_init,
5505         i965_post_processing_terminate,
5506         0,
5507     },
5508
5509     {
5510         i965_render_init,
5511         i965_render_terminate,
5512         0,
5513     },
5514
5515 #ifdef HAVE_VA_WAYLAND
5516     {
5517         i965_output_wayland_init,
5518         i965_output_wayland_terminate,
5519         VA_DISPLAY_WAYLAND,
5520     },
5521 #endif
5522
5523 #ifdef HAVE_VA_X11
5524     {
5525         i965_output_dri_init,
5526         i965_output_dri_terminate,
5527         VA_DISPLAY_X11,
5528     },
5529 #endif
5530 };
5531
5532 static VAStatus 
5533 i965_Init(VADriverContextP ctx)
5534 {
5535     struct i965_driver_data *i965 = i965_driver_data(ctx); 
5536     int i;
5537     const char *chipset;
5538
5539     for (i = 0; i < ARRAY_ELEMS(i965_sub_ops); i++) {
5540         if ((i965_sub_ops[i].display_type == 0 ||
5541              i965_sub_ops[i].display_type == (ctx->display_type & VA_DISPLAY_MAJOR_MASK)) &&
5542             !i965_sub_ops[i].init(ctx))
5543             break;
5544     }
5545
5546     if (i == ARRAY_ELEMS(i965_sub_ops)) {
5547         switch (i965->intel.device_id) {
5548 #undef CHIPSET
5549 #define CHIPSET(id, family, dev, str) case id: chipset = str; break;
5550 #include "i965_pciids.h"
5551         default:
5552             chipset = "Unknown Intel Chipset";
5553             break;
5554         }
5555
5556         sprintf(i965->va_vendor, "%s %s driver for %s - %d.%d.%d",
5557                 INTEL_STR_DRIVER_VENDOR,
5558                 INTEL_STR_DRIVER_NAME,
5559                 chipset,
5560                 INTEL_DRIVER_MAJOR_VERSION,
5561                 INTEL_DRIVER_MINOR_VERSION,
5562                 INTEL_DRIVER_MICRO_VERSION);
5563
5564         if (INTEL_DRIVER_PRE_VERSION > 0) {
5565             const int len = strlen(i965->va_vendor);
5566             sprintf(&i965->va_vendor[len], ".pre%d", INTEL_DRIVER_PRE_VERSION);
5567         }
5568
5569         i965->current_context_id = VA_INVALID_ID;
5570
5571         return VA_STATUS_SUCCESS;
5572     } else {
5573         i--;
5574
5575         for (; i >= 0; i--) {
5576             if (i965_sub_ops[i].display_type == 0 ||
5577                 i965_sub_ops[i].display_type == (ctx->display_type & VA_DISPLAY_MAJOR_MASK)) {
5578                 i965_sub_ops[i].terminate(ctx);
5579             }
5580         }
5581
5582         return VA_STATUS_ERROR_UNKNOWN;
5583     }
5584 }
5585
5586 VAStatus 
5587 i965_Terminate(VADriverContextP ctx)
5588 {
5589     struct i965_driver_data *i965 = i965_driver_data(ctx);
5590     int i;
5591
5592     if (i965) {
5593         for (i = ARRAY_ELEMS(i965_sub_ops); i > 0; i--)
5594             if (i965_sub_ops[i - 1].display_type == 0 ||
5595                 i965_sub_ops[i - 1].display_type == (ctx->display_type & VA_DISPLAY_MAJOR_MASK)) {
5596                 i965_sub_ops[i - 1].terminate(ctx);
5597             }
5598
5599         free(i965);
5600         ctx->pDriverData = NULL;        
5601     }
5602
5603     return VA_STATUS_SUCCESS;
5604 }
5605
5606 VAStatus DLL_EXPORT
5607 VA_DRIVER_INIT_FUNC(VADriverContextP ctx);
5608
5609 VAStatus 
5610 VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
5611 {
5612     struct VADriverVTable * const vtable = ctx->vtable;
5613     struct VADriverVTableVPP * const vtable_vpp = ctx->vtable_vpp;
5614
5615     struct i965_driver_data *i965;
5616     VAStatus ret = VA_STATUS_ERROR_UNKNOWN;
5617
5618     ctx->version_major = VA_MAJOR_VERSION;
5619     ctx->version_minor = VA_MINOR_VERSION;
5620     ctx->max_profiles = I965_MAX_PROFILES;
5621     ctx->max_entrypoints = I965_MAX_ENTRYPOINTS;
5622     ctx->max_attributes = I965_MAX_CONFIG_ATTRIBUTES;
5623     ctx->max_image_formats = I965_MAX_IMAGE_FORMATS;
5624     ctx->max_subpic_formats = I965_MAX_SUBPIC_FORMATS;
5625     ctx->max_display_attributes = 1 + ARRAY_ELEMS(i965_display_attributes);
5626
5627     vtable->vaTerminate = i965_Terminate;
5628     vtable->vaQueryConfigEntrypoints = i965_QueryConfigEntrypoints;
5629     vtable->vaQueryConfigProfiles = i965_QueryConfigProfiles;
5630     vtable->vaQueryConfigAttributes = i965_QueryConfigAttributes;
5631     vtable->vaCreateConfig = i965_CreateConfig;
5632     vtable->vaDestroyConfig = i965_DestroyConfig;
5633     vtable->vaGetConfigAttributes = i965_GetConfigAttributes;
5634     vtable->vaCreateSurfaces = i965_CreateSurfaces;
5635     vtable->vaDestroySurfaces = i965_DestroySurfaces;
5636     vtable->vaCreateContext = i965_CreateContext;
5637     vtable->vaDestroyContext = i965_DestroyContext;
5638     vtable->vaCreateBuffer = i965_CreateBuffer;
5639     vtable->vaBufferSetNumElements = i965_BufferSetNumElements;
5640     vtable->vaMapBuffer = i965_MapBuffer;
5641     vtable->vaUnmapBuffer = i965_UnmapBuffer;
5642     vtable->vaDestroyBuffer = i965_DestroyBuffer;
5643     vtable->vaBeginPicture = i965_BeginPicture;
5644     vtable->vaRenderPicture = i965_RenderPicture;
5645     vtable->vaEndPicture = i965_EndPicture;
5646     vtable->vaSyncSurface = i965_SyncSurface;
5647     vtable->vaQuerySurfaceStatus = i965_QuerySurfaceStatus;
5648     vtable->vaPutSurface = i965_PutSurface;
5649     vtable->vaQueryImageFormats = i965_QueryImageFormats;
5650     vtable->vaCreateImage = i965_CreateImage;
5651     vtable->vaDeriveImage = i965_DeriveImage;
5652     vtable->vaDestroyImage = i965_DestroyImage;
5653     vtable->vaSetImagePalette = i965_SetImagePalette;
5654     vtable->vaGetImage = i965_GetImage;
5655     vtable->vaPutImage = i965_PutImage;
5656     vtable->vaQuerySubpictureFormats = i965_QuerySubpictureFormats;
5657     vtable->vaCreateSubpicture = i965_CreateSubpicture;
5658     vtable->vaDestroySubpicture = i965_DestroySubpicture;
5659     vtable->vaSetSubpictureImage = i965_SetSubpictureImage;
5660     vtable->vaSetSubpictureChromakey = i965_SetSubpictureChromakey;
5661     vtable->vaSetSubpictureGlobalAlpha = i965_SetSubpictureGlobalAlpha;
5662     vtable->vaAssociateSubpicture = i965_AssociateSubpicture;
5663     vtable->vaDeassociateSubpicture = i965_DeassociateSubpicture;
5664     vtable->vaQueryDisplayAttributes = i965_QueryDisplayAttributes;
5665     vtable->vaGetDisplayAttributes = i965_GetDisplayAttributes;
5666     vtable->vaSetDisplayAttributes = i965_SetDisplayAttributes;
5667     vtable->vaBufferInfo = i965_BufferInfo;
5668     vtable->vaLockSurface = i965_LockSurface;
5669     vtable->vaUnlockSurface = i965_UnlockSurface;
5670     vtable->vaGetSurfaceAttributes = i965_GetSurfaceAttributes;
5671     vtable->vaQuerySurfaceAttributes = i965_QuerySurfaceAttributes;
5672     vtable->vaCreateSurfaces2 = i965_CreateSurfaces2;
5673
5674     vtable_vpp->vaQueryVideoProcFilters = i965_QueryVideoProcFilters;
5675     vtable_vpp->vaQueryVideoProcFilterCaps = i965_QueryVideoProcFilterCaps;
5676     vtable_vpp->vaQueryVideoProcPipelineCaps = i965_QueryVideoProcPipelineCaps;
5677
5678     i965 = (struct i965_driver_data *)calloc(1, sizeof(*i965));
5679
5680     if (i965 == NULL) {
5681         ctx->pDriverData = NULL;
5682
5683         return VA_STATUS_ERROR_ALLOCATION_FAILED;
5684     }
5685
5686     ctx->pDriverData = (void *)i965;
5687     ret = i965_Init(ctx);
5688
5689     if (ret == VA_STATUS_SUCCESS) {
5690         ctx->str_vendor = i965->va_vendor;
5691     } else {
5692         free(i965);
5693         ctx->pDriverData = NULL;
5694     }
5695
5696     return ret;
5697 }