OSDN Git Service

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