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