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