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