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