OSDN Git Service

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