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