OSDN Git Service

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