OSDN Git Service

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