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