OSDN Git Service

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