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