OSDN Git Service

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