OSDN Git Service

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