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