OSDN Git Service

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