OSDN Git Service

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