OSDN Git Service

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