OSDN Git Service

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