OSDN Git Service

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