OSDN Git Service

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