OSDN Git Service

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