OSDN Git Service

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