OSDN Git Service

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