OSDN Git Service

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