OSDN Git Service

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