OSDN Git Service

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