OSDN Git Service

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