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