OSDN Git Service

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