Fix the issue in i965_UnlockSurface to lock it next time
[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(ctx)  (IS_G4X((ctx)->intel.device_id) ||      \
56                          IS_IRONLAKE((ctx)->intel.device_id) || \
57                          ((IS_GEN6((ctx)->intel.device_id) ||   \
58                            IS_GEN7((ctx)->intel.device_id)) &&  \
59                           (ctx)->intel.has_bsd))
60
61 #define HAS_H264(ctx)   ((IS_GEN7((ctx)->intel.device_id) ||            \
62                           IS_GEN6((ctx)->intel.device_id) ||            \
63                           IS_IRONLAKE((ctx)->intel.device_id)) &&       \
64                          (ctx)->intel.has_bsd)
65
66 #define HAS_VC1(ctx)    ((IS_GEN7((ctx)->intel.device_id) ||    \
67                           IS_GEN6((ctx)->intel.device_id)) &&   \
68                          (ctx)->intel.has_bsd)
69
70 #define HAS_TILED_SURFACE(ctx) ((IS_GEN7((ctx)->intel.device_id) ||     \
71                                  IS_GEN6((ctx)->intel.device_id)) &&    \
72                                 (ctx)->render_state.interleaved_uv)
73
74 #define HAS_ENCODER(ctx)        ((IS_GEN7((ctx)->intel.device_id) ||    \
75                                   IS_GEN6((ctx)->intel.device_id)) &&   \
76                                  (ctx)->intel.has_bsd)
77
78 #define HAS_JPEG(ctx)   (IS_GEN7((ctx)->intel.device_id) &&     \
79                          (ctx)->intel.has_bsd)
80
81 #define HAS_ACCELERATED_GETIMAGE(ctx)   (IS_GEN6((ctx)->intel.device_id) ||     \
82                                          IS_GEN7((ctx)->intel.device_id))
83
84 #define HAS_ACCELERATED_PUTIMAGE(ctx)   HAS_VPP(ctx)
85 static int get_sampling_from_fourcc(unsigned int fourcc);
86
87 #if VA_CHECK_VERSION(0,33,0)
88 /* Check whether we are rendering to X11 (VA/X11 or VA/GLX API) */
89 #define IS_VA_X11(ctx) \
90     (((ctx)->display_type & VA_DISPLAY_MAJOR_MASK) == VA_DISPLAY_X11)
91
92 /* Check whether we are rendering to Wayland */
93 #define IS_VA_WAYLAND(ctx) \
94     (((ctx)->display_type & VA_DISPLAY_MAJOR_MASK) == VA_DISPLAY_WAYLAND)
95 #else
96 /* Previous VA-API versions only supported VA/X11 (and VA/GLX) API */
97 #define IS_VA_X11(ctx)          1
98 #define IS_VA_WAYLAND(ctx)      0
99 #endif
100
101 enum {
102     I965_SURFACETYPE_RGBA = 1,
103     I965_SURFACETYPE_YUV,
104     I965_SURFACETYPE_INDEXED
105 };
106
107 /* List of supported display attributes */
108 static const VADisplayAttribute i965_display_attributes[] = {
109     {
110         VADisplayAttribRotation,
111         0, 3, VA_ROTATION_NONE,
112         VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE
113     },
114 };
115
116 /* List of supported image formats */
117 typedef struct {
118     unsigned int        type;
119     VAImageFormat       va_format;
120 } i965_image_format_map_t;
121
122 static const i965_image_format_map_t
123 i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
124     { I965_SURFACETYPE_YUV,
125       { VA_FOURCC('Y','V','1','2'), VA_LSB_FIRST, 12, } },
126     { I965_SURFACETYPE_YUV,
127       { VA_FOURCC('I','4','2','0'), VA_LSB_FIRST, 12, } },
128     { I965_SURFACETYPE_YUV,
129       { VA_FOURCC('N','V','1','2'), VA_LSB_FIRST, 12, } },
130 };
131
132 /* List of supported subpicture formats */
133 typedef struct {
134     unsigned int        type;
135     unsigned int        format;
136     VAImageFormat       va_format;
137     unsigned int        va_flags;
138 } i965_subpic_format_map_t;
139
140 static const i965_subpic_format_map_t
141 i965_subpic_formats_map[I965_MAX_SUBPIC_FORMATS + 1] = {
142     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P4A4_UNORM,
143       { VA_FOURCC('I','A','4','4'), VA_MSB_FIRST, 8, },
144       VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD },
145     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM,
146       { VA_FOURCC('A','I','4','4'), VA_MSB_FIRST, 8, },
147       VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD },
148     { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM,
149       { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32,
150         32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
151       VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD },
152     { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM,
153       { VA_FOURCC('R','G','B','A'), VA_LSB_FIRST, 32,
154         32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
155       VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD },
156 };
157
158 static const i965_subpic_format_map_t *
159 get_subpic_format(const VAImageFormat *va_format)
160 {
161     unsigned int i;
162     for (i = 0; i965_subpic_formats_map[i].type != 0; i++) {
163         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[i];
164         if (m->va_format.fourcc == va_format->fourcc &&
165             (m->type == I965_SURFACETYPE_RGBA ?
166              (m->va_format.byte_order == va_format->byte_order &&
167               m->va_format.red_mask   == va_format->red_mask   &&
168               m->va_format.green_mask == va_format->green_mask &&
169               m->va_format.blue_mask  == va_format->blue_mask  &&
170               m->va_format.alpha_mask == va_format->alpha_mask) : 1))
171             return m;
172     }
173     return NULL;
174 }
175
176 extern struct hw_context *g4x_dec_hw_context_init(VADriverContextP, VAProfile);
177 static struct hw_codec_info g4x_hw_codec_info = {
178     .dec_hw_context_init = g4x_dec_hw_context_init,
179     .enc_hw_context_init = NULL,
180     .max_width = 2048,
181     .max_height = 2048,
182 };
183
184 extern struct hw_context *ironlake_dec_hw_context_init(VADriverContextP, VAProfile);
185 static struct hw_codec_info ironlake_hw_codec_info = {
186     .dec_hw_context_init = ironlake_dec_hw_context_init,
187     .enc_hw_context_init = NULL,
188     .max_width = 2048,
189     .max_height = 2048,
190 };
191
192 extern struct hw_context *gen6_dec_hw_context_init(VADriverContextP, VAProfile);
193 extern struct hw_context *gen6_enc_hw_context_init(VADriverContextP, VAProfile);
194 static struct hw_codec_info gen6_hw_codec_info = {
195     .dec_hw_context_init = gen6_dec_hw_context_init,
196     .enc_hw_context_init = gen6_enc_hw_context_init,
197     .max_width = 2048,
198     .max_height = 2048,
199 };
200
201 extern struct hw_context *gen7_dec_hw_context_init(VADriverContextP, VAProfile);
202 static struct hw_codec_info gen7_hw_codec_info = {
203     .dec_hw_context_init = gen7_dec_hw_context_init,
204     .enc_hw_context_init = gen6_enc_hw_context_init,
205     .max_width = 4096,
206     .max_height = 4096,
207 };
208
209 static struct hw_codec_info gen75_hw_codec_info = {
210     .dec_hw_context_init = gen75_dec_hw_context_init,
211     .enc_hw_context_init = gen75_enc_hw_context_init,
212     .max_width = 4096,
213     .max_height = 4096,
214 };
215
216 VAStatus 
217 i965_QueryConfigProfiles(VADriverContextP ctx,
218                          VAProfile *profile_list,       /* out */
219                          int *num_profiles)             /* out */
220 {
221     struct i965_driver_data * const i965 = i965_driver_data(ctx);
222     int i = 0;
223
224     if (HAS_MPEG2(i965)) {
225         profile_list[i++] = VAProfileMPEG2Simple;
226         profile_list[i++] = VAProfileMPEG2Main;
227     }
228
229     if (HAS_H264(i965)) {
230         profile_list[i++] = VAProfileH264Baseline;
231         profile_list[i++] = VAProfileH264Main;
232         profile_list[i++] = VAProfileH264High;
233     }
234
235     if (HAS_VC1(i965)) {
236         profile_list[i++] = VAProfileVC1Simple;
237         profile_list[i++] = VAProfileVC1Main;
238         profile_list[i++] = VAProfileVC1Advanced;
239     }
240
241 #ifdef HAVE_VA_JPEG_DECODE
242     if (HAS_JPEG(i965)) {
243         profile_list[i++] = VAProfileJPEGBaseline;
244     }
245 #endif
246
247     /* If the assert fails then I965_MAX_PROFILES needs to be bigger */
248     assert(i <= I965_MAX_PROFILES);
249     *num_profiles = i;
250
251     return VA_STATUS_SUCCESS;
252 }
253
254 VAStatus 
255 i965_QueryConfigEntrypoints(VADriverContextP ctx,
256                             VAProfile profile,
257                             VAEntrypoint *entrypoint_list,      /* out */
258                             int *num_entrypoints)               /* out */
259 {
260     struct i965_driver_data * const i965 = i965_driver_data(ctx);
261     int n = 0;
262
263     switch (profile) {
264     case VAProfileMPEG2Simple:
265     case VAProfileMPEG2Main:
266         if (HAS_MPEG2(i965))
267             entrypoint_list[n++] = VAEntrypointVLD;
268         break;
269
270     case VAProfileH264Baseline:
271     case VAProfileH264Main:
272     case VAProfileH264High:
273         if (HAS_H264(i965))
274             entrypoint_list[n++] = VAEntrypointVLD;
275         
276         if (HAS_ENCODER(i965))
277             entrypoint_list[n++] = VAEntrypointEncSlice;
278
279         break;
280
281     case VAProfileVC1Simple:
282     case VAProfileVC1Main:
283     case VAProfileVC1Advanced:
284         if (HAS_VC1(i965))
285             entrypoint_list[n++] = VAEntrypointVLD;
286         break;
287
288     case VAProfileJPEGBaseline:
289         if (HAS_JPEG(i965))
290             entrypoint_list[n++] = VAEntrypointVLD;
291         break;
292
293     default:
294         break;
295     }
296
297     /* If the assert fails then I965_MAX_ENTRYPOINTS needs to be bigger */
298     assert(n <= I965_MAX_ENTRYPOINTS);
299     *num_entrypoints = n;
300     return n > 0 ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
301 }
302
303 VAStatus 
304 i965_GetConfigAttributes(VADriverContextP ctx,
305                          VAProfile profile,
306                          VAEntrypoint entrypoint,
307                          VAConfigAttrib *attrib_list,  /* in/out */
308                          int num_attribs)
309 {
310     int i;
311
312     /* Other attributes don't seem to be defined */
313     /* What to do if we don't know the attribute? */
314     for (i = 0; i < num_attribs; i++) {
315         switch (attrib_list[i].type) {
316         case VAConfigAttribRTFormat:
317             attrib_list[i].value = VA_RT_FORMAT_YUV420;
318             break;
319
320         case VAConfigAttribRateControl:
321             attrib_list[i].value = VA_RC_VBR;
322             break;
323
324         default:
325             /* Do nothing */
326             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
327             break;
328         }
329     }
330
331     return VA_STATUS_SUCCESS;
332 }
333
334 static void 
335 i965_destroy_config(struct object_heap *heap, struct object_base *obj)
336 {
337     object_heap_free(heap, obj);
338 }
339
340 static VAStatus 
341 i965_update_attribute(struct object_config *obj_config, VAConfigAttrib *attrib)
342 {
343     int i;
344
345     /* Check existing attrbiutes */
346     for (i = 0; obj_config->num_attribs < i; i++) {
347         if (obj_config->attrib_list[i].type == attrib->type) {
348             /* Update existing attribute */
349             obj_config->attrib_list[i].value = attrib->value;
350             return VA_STATUS_SUCCESS;
351         }
352     }
353
354     if (obj_config->num_attribs < I965_MAX_CONFIG_ATTRIBUTES) {
355         i = obj_config->num_attribs;
356         obj_config->attrib_list[i].type = attrib->type;
357         obj_config->attrib_list[i].value = attrib->value;
358         obj_config->num_attribs++;
359         return VA_STATUS_SUCCESS;
360     }
361
362     return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
363 }
364
365 VAStatus 
366 i965_CreateConfig(VADriverContextP ctx,
367                   VAProfile profile,
368                   VAEntrypoint entrypoint,
369                   VAConfigAttrib *attrib_list,
370                   int num_attribs,
371                   VAConfigID *config_id)        /* out */
372 {
373     struct i965_driver_data * const i965 = i965_driver_data(ctx);
374     struct object_config *obj_config;
375     int configID;
376     int i;
377     VAStatus vaStatus;
378
379     /* Validate profile & entrypoint */
380     switch (profile) {
381     case VAProfileMPEG2Simple:
382     case VAProfileMPEG2Main:
383         if (HAS_MPEG2(i965) && VAEntrypointVLD == entrypoint) {
384             vaStatus = VA_STATUS_SUCCESS;
385         } else {
386             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
387         }
388         break;
389
390     case VAProfileH264Baseline:
391     case VAProfileH264Main:
392     case VAProfileH264High:
393         if ((HAS_H264(i965) && VAEntrypointVLD == entrypoint) ||
394             (HAS_ENCODER(i965) && VAEntrypointEncSlice == entrypoint)) {
395             vaStatus = VA_STATUS_SUCCESS;
396         } else {
397             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
398         }
399
400         break;
401
402     case VAProfileVC1Simple:
403     case VAProfileVC1Main:
404     case VAProfileVC1Advanced:
405         if (HAS_VC1(i965) && VAEntrypointVLD == entrypoint) {
406             vaStatus = VA_STATUS_SUCCESS;
407         } else {
408             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
409         }
410
411         break;
412
413     case VAProfileJPEGBaseline:
414         if (HAS_JPEG(i965) && VAEntrypointVLD == entrypoint) {
415             vaStatus = VA_STATUS_SUCCESS;
416         } else {
417             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
418         }
419
420         break;
421
422     default:
423         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
424         break;
425     }
426
427     if (VA_STATUS_SUCCESS != vaStatus) {
428         return vaStatus;
429     }
430
431     configID = NEW_CONFIG_ID();
432     obj_config = CONFIG(configID);
433
434     if (NULL == obj_config) {
435         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
436         return vaStatus;
437     }
438
439     obj_config->profile = profile;
440     obj_config->entrypoint = entrypoint;
441     obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
442     obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
443     obj_config->num_attribs = 1;
444
445     for(i = 0; i < num_attribs; i++) {
446         vaStatus = i965_update_attribute(obj_config, &(attrib_list[i]));
447
448         if (VA_STATUS_SUCCESS != vaStatus) {
449             break;
450         }
451     }
452
453     /* Error recovery */
454     if (VA_STATUS_SUCCESS != vaStatus) {
455         i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
456     } else {
457         *config_id = configID;
458     }
459
460     return vaStatus;
461 }
462
463 VAStatus 
464 i965_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
465 {
466     struct i965_driver_data *i965 = i965_driver_data(ctx);
467     struct object_config *obj_config = CONFIG(config_id);
468     VAStatus vaStatus;
469
470     if (NULL == obj_config) {
471         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
472         return vaStatus;
473     }
474
475     i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
476     return VA_STATUS_SUCCESS;
477 }
478
479 VAStatus i965_QueryConfigAttributes(VADriverContextP ctx,
480                                     VAConfigID config_id,
481                                     VAProfile *profile,                 /* out */
482                                     VAEntrypoint *entrypoint,           /* out */
483                                     VAConfigAttrib *attrib_list,        /* out */
484                                     int *num_attribs)                   /* out */
485 {
486     struct i965_driver_data *i965 = i965_driver_data(ctx);
487     struct object_config *obj_config = CONFIG(config_id);
488     VAStatus vaStatus = VA_STATUS_SUCCESS;
489     int i;
490
491     assert(obj_config);
492     *profile = obj_config->profile;
493     *entrypoint = obj_config->entrypoint;
494     *num_attribs = obj_config->num_attribs;
495
496     for(i = 0; i < obj_config->num_attribs; i++) {
497         attrib_list[i] = obj_config->attrib_list[i];
498     }
499
500     return vaStatus;
501 }
502
503 static void 
504 i965_destroy_surface(struct object_heap *heap, struct object_base *obj)
505 {
506     struct object_surface *obj_surface = (struct object_surface *)obj;
507
508     dri_bo_unreference(obj_surface->bo);
509     obj_surface->bo = NULL;
510
511     if (obj_surface->free_private_data != NULL) {
512         obj_surface->free_private_data(&obj_surface->private_data);
513         obj_surface->private_data = NULL;
514     }
515
516     object_heap_free(heap, obj);
517 }
518
519 VAStatus 
520 i965_CreateSurfaces(VADriverContextP ctx,
521                     int width,
522                     int height,
523                     int format,
524                     int num_surfaces,
525                     VASurfaceID *surfaces)      /* out */
526 {
527     struct i965_driver_data *i965 = i965_driver_data(ctx);
528     int i;
529     VAStatus vaStatus = VA_STATUS_SUCCESS;
530
531     /* We only support one format */
532     if (VA_RT_FORMAT_YUV420 != format) {
533         return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
534     }
535
536     for (i = 0; i < num_surfaces; i++) {
537         int surfaceID = NEW_SURFACE_ID();
538         struct object_surface *obj_surface = SURFACE(surfaceID);
539
540         if (NULL == obj_surface) {
541             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
542             break;
543         }
544
545         surfaces[i] = surfaceID;
546         obj_surface->status = VASurfaceReady;
547         obj_surface->subpic = VA_INVALID_ID;
548         obj_surface->orig_width = width;
549         obj_surface->orig_height = height;
550
551         if (IS_G4X(i965->intel.device_id) || IS_IRONLAKE(i965->intel.device_id)) {
552                 obj_surface->width = ALIGN(width, 16);
553                 obj_surface->height = ALIGN(height, 16);
554         } else {
555                 obj_surface->width = ALIGN(width, 128);
556                 obj_surface->height = ALIGN(height, 32);
557         }
558
559         obj_surface->flags = SURFACE_REFERENCED;
560         obj_surface->fourcc = 0;
561         obj_surface->bo = NULL;
562         obj_surface->locked_image_id = VA_INVALID_ID;
563         obj_surface->private_data = NULL;
564         obj_surface->free_private_data = NULL;
565         obj_surface->subsampling = SUBSAMPLE_YUV420;
566     }
567
568     /* Error recovery */
569     if (VA_STATUS_SUCCESS != vaStatus) {
570         /* surfaces[i-1] was the last successful allocation */
571         for (; i--; ) {
572             struct object_surface *obj_surface = SURFACE(surfaces[i]);
573
574             surfaces[i] = VA_INVALID_SURFACE;
575             assert(obj_surface);
576             i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
577         }
578     }
579
580     return vaStatus;
581 }
582
583 VAStatus 
584 i965_DestroySurfaces(VADriverContextP ctx,
585                      VASurfaceID *surface_list,
586                      int num_surfaces)
587 {
588     struct i965_driver_data *i965 = i965_driver_data(ctx);
589     int i;
590
591     for (i = num_surfaces; i--; ) {
592         struct object_surface *obj_surface = SURFACE(surface_list[i]);
593
594         assert(obj_surface);
595         i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
596     }
597
598     return VA_STATUS_SUCCESS;
599 }
600
601 VAStatus 
602 i965_QueryImageFormats(VADriverContextP ctx,
603                        VAImageFormat *format_list,      /* out */
604                        int *num_formats)                /* out */
605 {
606     int n;
607
608     for (n = 0; i965_image_formats_map[n].va_format.fourcc != 0; n++) {
609         const i965_image_format_map_t * const m = &i965_image_formats_map[n];
610         if (format_list)
611             format_list[n] = m->va_format;
612     }
613
614     if (num_formats)
615         *num_formats = n;
616
617     return VA_STATUS_SUCCESS;
618 }
619
620 VAStatus 
621 i965_PutImage(VADriverContextP ctx,
622               VASurfaceID surface,
623               VAImageID image,
624               int src_x,
625               int src_y,
626               unsigned int src_width,
627               unsigned int src_height,
628               int dest_x,
629               int dest_y,
630               unsigned int dest_width,
631               unsigned int dest_height)
632 {
633     return VA_STATUS_SUCCESS;
634 }
635
636 VAStatus 
637 i965_QuerySubpictureFormats(VADriverContextP ctx,
638                             VAImageFormat *format_list,         /* out */
639                             unsigned int *flags,                /* out */
640                             unsigned int *num_formats)          /* out */
641 {
642     int n;
643
644     for (n = 0; i965_subpic_formats_map[n].va_format.fourcc != 0; n++) {
645         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[n];
646         if (format_list)
647             format_list[n] = m->va_format;
648         if (flags)
649             flags[n] = m->va_flags;
650     }
651
652     if (num_formats)
653         *num_formats = n;
654
655     return VA_STATUS_SUCCESS;
656 }
657
658 static void 
659 i965_destroy_subpic(struct object_heap *heap, struct object_base *obj)
660 {
661     //    struct object_subpic *obj_subpic = (struct object_subpic *)obj;
662
663     object_heap_free(heap, obj);
664 }
665
666 VAStatus 
667 i965_CreateSubpicture(VADriverContextP ctx,
668                       VAImageID image,
669                       VASubpictureID *subpicture)         /* out */
670 {
671     struct i965_driver_data *i965 = i965_driver_data(ctx);
672     VASubpictureID subpicID = NEW_SUBPIC_ID()
673     struct object_subpic *obj_subpic = SUBPIC(subpicID);
674
675     if (!obj_subpic)
676         return VA_STATUS_ERROR_ALLOCATION_FAILED;
677
678     struct object_image *obj_image = IMAGE(image);
679     if (!obj_image)
680         return VA_STATUS_ERROR_INVALID_IMAGE;
681
682     const i965_subpic_format_map_t * const m = get_subpic_format(&obj_image->image.format);
683     if (!m)
684         return VA_STATUS_ERROR_UNKNOWN; /* XXX: VA_STATUS_ERROR_UNSUPPORTED_FORMAT? */
685
686     *subpicture = subpicID;
687     obj_subpic->image  = image;
688     obj_subpic->format = m->format;
689     obj_subpic->width  = obj_image->image.width;
690     obj_subpic->height = obj_image->image.height;
691     obj_subpic->pitch  = obj_image->image.pitches[0];
692     obj_subpic->bo     = obj_image->bo;
693     return VA_STATUS_SUCCESS;
694 }
695
696 VAStatus 
697 i965_DestroySubpicture(VADriverContextP ctx,
698                        VASubpictureID subpicture)
699 {
700     struct i965_driver_data *i965 = i965_driver_data(ctx);
701     struct object_subpic *obj_subpic = SUBPIC(subpicture);
702     i965_destroy_subpic(&i965->subpic_heap, (struct object_base *)obj_subpic);
703     return VA_STATUS_SUCCESS;
704 }
705
706 VAStatus 
707 i965_SetSubpictureImage(VADriverContextP ctx,
708                         VASubpictureID subpicture,
709                         VAImageID image)
710 {
711     /* TODO */
712     return VA_STATUS_ERROR_UNIMPLEMENTED;
713 }
714
715 VAStatus 
716 i965_SetSubpictureChromakey(VADriverContextP ctx,
717                             VASubpictureID subpicture,
718                             unsigned int chromakey_min,
719                             unsigned int chromakey_max,
720                             unsigned int chromakey_mask)
721 {
722     /* TODO */
723     return VA_STATUS_ERROR_UNIMPLEMENTED;
724 }
725
726 VAStatus 
727 i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
728                               VASubpictureID subpicture,
729                               float global_alpha)
730 {
731     /* TODO */
732     return VA_STATUS_ERROR_UNIMPLEMENTED;
733 }
734
735 VAStatus 
736 i965_AssociateSubpicture(VADriverContextP ctx,
737                          VASubpictureID subpicture,
738                          VASurfaceID *target_surfaces,
739                          int num_surfaces,
740                          short src_x, /* upper left offset in subpicture */
741                          short src_y,
742                          unsigned short src_width,
743                          unsigned short src_height,
744                          short dest_x, /* upper left offset in surface */
745                          short dest_y,
746                          unsigned short dest_width,
747                          unsigned short dest_height,
748                          /*
749                           * whether to enable chroma-keying or global-alpha
750                           * see VA_SUBPICTURE_XXX values
751                           */
752                          unsigned int flags)
753 {
754     struct i965_driver_data *i965 = i965_driver_data(ctx);
755     struct object_subpic *obj_subpic = SUBPIC(subpicture);
756     int i;
757
758     obj_subpic->src_rect.x      = src_x;
759     obj_subpic->src_rect.y      = src_y;
760     obj_subpic->src_rect.width  = src_width;
761     obj_subpic->src_rect.height = src_height;
762     obj_subpic->dst_rect.x      = dest_x;
763     obj_subpic->dst_rect.y      = dest_y;
764     obj_subpic->dst_rect.width  = dest_width;
765     obj_subpic->dst_rect.height = dest_height;
766     obj_subpic->flags           = flags;
767
768     for (i = 0; i < num_surfaces; i++) {
769         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
770         if (!obj_surface)
771             return VA_STATUS_ERROR_INVALID_SURFACE;
772         obj_surface->subpic = subpicture;
773     }
774     return VA_STATUS_SUCCESS;
775 }
776
777
778 VAStatus 
779 i965_DeassociateSubpicture(VADriverContextP ctx,
780                            VASubpictureID subpicture,
781                            VASurfaceID *target_surfaces,
782                            int num_surfaces)
783 {
784     struct i965_driver_data *i965 = i965_driver_data(ctx);
785     int i;
786
787     for (i = 0; i < num_surfaces; i++) {
788         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
789         if (!obj_surface)
790             return VA_STATUS_ERROR_INVALID_SURFACE;
791         if (obj_surface->subpic == subpicture)
792             obj_surface->subpic = VA_INVALID_ID;
793     }
794     return VA_STATUS_SUCCESS;
795 }
796
797 void
798 i965_reference_buffer_store(struct buffer_store **ptr, 
799                             struct buffer_store *buffer_store)
800 {
801     assert(*ptr == NULL);
802
803     if (buffer_store) {
804         buffer_store->ref_count++;
805         *ptr = buffer_store;
806     }
807 }
808
809 void 
810 i965_release_buffer_store(struct buffer_store **ptr)
811 {
812     struct buffer_store *buffer_store = *ptr;
813
814     if (buffer_store == NULL)
815         return;
816
817     assert(buffer_store->bo || buffer_store->buffer);
818     assert(!(buffer_store->bo && buffer_store->buffer));
819     buffer_store->ref_count--;
820     
821     if (buffer_store->ref_count == 0) {
822         dri_bo_unreference(buffer_store->bo);
823         free(buffer_store->buffer);
824         buffer_store->bo = NULL;
825         buffer_store->buffer = NULL;
826         free(buffer_store);
827     }
828
829     *ptr = NULL;
830 }
831
832 static void 
833 i965_destroy_context(struct object_heap *heap, struct object_base *obj)
834 {
835     struct object_context *obj_context = (struct object_context *)obj;
836     int i;
837
838     if (obj_context->hw_context) {
839         obj_context->hw_context->destroy(obj_context->hw_context);
840         obj_context->hw_context = NULL;
841     }
842
843     if (obj_context->codec_type == CODEC_ENC) {
844         assert(obj_context->codec_state.encode.num_slice_params <= obj_context->codec_state.encode.max_slice_params);
845         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
846         i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
847
848         for (i = 0; i < obj_context->codec_state.encode.num_slice_params; i++)
849             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
850
851         free(obj_context->codec_state.encode.slice_params);
852     } else {
853         assert(obj_context->codec_state.decode.num_slice_params <= obj_context->codec_state.decode.max_slice_params);
854         assert(obj_context->codec_state.decode.num_slice_datas <= obj_context->codec_state.decode.max_slice_datas);
855
856         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
857         i965_release_buffer_store(&obj_context->codec_state.decode.iq_matrix);
858         i965_release_buffer_store(&obj_context->codec_state.decode.bit_plane);
859
860         for (i = 0; i < obj_context->codec_state.decode.num_slice_params; i++)
861             i965_release_buffer_store(&obj_context->codec_state.decode.slice_params[i]);
862
863         for (i = 0; i < obj_context->codec_state.decode.num_slice_datas; i++)
864             i965_release_buffer_store(&obj_context->codec_state.decode.slice_datas[i]);
865
866         free(obj_context->codec_state.decode.slice_params);
867         free(obj_context->codec_state.decode.slice_datas);
868     }
869
870     free(obj_context->render_targets);
871     object_heap_free(heap, obj);
872 }
873
874 VAStatus
875 i965_CreateContext(VADriverContextP ctx,
876                    VAConfigID config_id,
877                    int picture_width,
878                    int picture_height,
879                    int flag,
880                    VASurfaceID *render_targets,
881                    int num_render_targets,
882                    VAContextID *context)                /* out */
883 {
884     struct i965_driver_data *i965 = i965_driver_data(ctx);
885     struct i965_render_state *render_state = &i965->render_state;
886     struct object_config *obj_config = CONFIG(config_id);
887     struct object_context *obj_context = NULL;
888     VAStatus vaStatus = VA_STATUS_SUCCESS;
889     int contextID;
890     int i;
891
892     if (NULL == obj_config) {
893         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
894         return vaStatus;
895     }
896
897     if (picture_width > i965->codec_info->max_width ||
898         picture_height > i965->codec_info->max_height) {
899         vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
900         return vaStatus;
901     }
902
903     /* Validate flag */
904     /* Validate picture dimensions */
905     contextID = NEW_CONTEXT_ID();
906     obj_context = CONTEXT(contextID);
907
908     if (NULL == obj_context) {
909         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
910         return vaStatus;
911     }
912
913     render_state->inited = 1;
914
915     switch (obj_config->profile) {
916     case VAProfileH264Baseline:
917     case VAProfileH264Main:
918     case VAProfileH264High:
919         if (!HAS_H264(i965))
920             return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
921         render_state->interleaved_uv = 1;
922         break;
923     default:
924         render_state->interleaved_uv = !!(IS_GEN6(i965->intel.device_id) || IS_GEN7(i965->intel.device_id));
925         break;
926     }
927
928     *context = contextID;
929     obj_context->flags = flag;
930     obj_context->context_id = contextID;
931     obj_context->config_id = config_id;
932     obj_context->picture_width = picture_width;
933     obj_context->picture_height = picture_height;
934     obj_context->num_render_targets = num_render_targets;
935     obj_context->render_targets = 
936         (VASurfaceID *)calloc(num_render_targets, sizeof(VASurfaceID));
937     obj_context->hw_context = NULL;
938
939     for(i = 0; i < num_render_targets; i++) {
940         if (NULL == SURFACE(render_targets[i])) {
941             vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
942             break;
943         }
944
945         obj_context->render_targets[i] = render_targets[i];
946     }
947
948     if (VA_STATUS_SUCCESS == vaStatus) {
949         if (VAEntrypointEncSlice == obj_config->entrypoint ) { /*encode routin only*/
950             obj_context->codec_type = CODEC_ENC;
951             memset(&obj_context->codec_state.encode, 0, sizeof(obj_context->codec_state.encode));
952             obj_context->codec_state.encode.current_render_target = VA_INVALID_ID;
953             obj_context->codec_state.encode.max_slice_params = NUM_SLICES;
954             obj_context->codec_state.encode.slice_params = calloc(obj_context->codec_state.encode.max_slice_params,
955                                                                sizeof(*obj_context->codec_state.encode.slice_params));
956             assert(i965->codec_info->enc_hw_context_init);
957             obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config->profile);
958         } else {
959             obj_context->codec_type = CODEC_DEC;
960             memset(&obj_context->codec_state.decode, 0, sizeof(obj_context->codec_state.decode));
961             obj_context->codec_state.decode.current_render_target = -1;
962             obj_context->codec_state.decode.max_slice_params = NUM_SLICES;
963             obj_context->codec_state.decode.max_slice_datas = NUM_SLICES;
964             obj_context->codec_state.decode.slice_params = calloc(obj_context->codec_state.decode.max_slice_params,
965                                                                sizeof(*obj_context->codec_state.decode.slice_params));
966             obj_context->codec_state.decode.slice_datas = calloc(obj_context->codec_state.decode.max_slice_datas,
967                                                               sizeof(*obj_context->codec_state.decode.slice_datas));
968
969             assert(i965->codec_info->dec_hw_context_init);
970             obj_context->hw_context = i965->codec_info->dec_hw_context_init(ctx, obj_config->profile);
971         }
972     }
973
974     /* Error recovery */
975     if (VA_STATUS_SUCCESS != vaStatus) {
976         i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
977     }
978
979     return vaStatus;
980 }
981
982 VAStatus 
983 i965_DestroyContext(VADriverContextP ctx, VAContextID context)
984 {
985     struct i965_driver_data *i965 = i965_driver_data(ctx);
986     struct object_context *obj_context = CONTEXT(context);
987
988     assert(obj_context);
989     i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
990
991     return VA_STATUS_SUCCESS;
992 }
993
994 static void 
995 i965_destroy_buffer(struct object_heap *heap, struct object_base *obj)
996 {
997     struct object_buffer *obj_buffer = (struct object_buffer *)obj;
998
999     assert(obj_buffer->buffer_store);
1000     i965_release_buffer_store(&obj_buffer->buffer_store);
1001     object_heap_free(heap, obj);
1002 }
1003
1004 static VAStatus
1005 i965_create_buffer_internal(VADriverContextP ctx,
1006                             VAContextID context,
1007                             VABufferType type,
1008                             unsigned int size,
1009                             unsigned int num_elements,
1010                             void *data,
1011                             dri_bo *store_bo,
1012                             VABufferID *buf_id)
1013 {
1014     struct i965_driver_data *i965 = i965_driver_data(ctx);
1015     struct object_buffer *obj_buffer = NULL;
1016     struct buffer_store *buffer_store = NULL;
1017     int bufferID;
1018
1019     /* Validate type */
1020     switch (type) {
1021     case VAPictureParameterBufferType:
1022     case VAIQMatrixBufferType:
1023     case VABitPlaneBufferType:
1024     case VASliceGroupMapBufferType:
1025     case VASliceParameterBufferType:
1026     case VASliceDataBufferType:
1027     case VAMacroblockParameterBufferType:
1028     case VAResidualDataBufferType:
1029     case VADeblockingParameterBufferType:
1030     case VAImageBufferType:
1031     case VAEncCodedBufferType:
1032     case VAEncSequenceParameterBufferType:
1033     case VAEncPictureParameterBufferType:
1034     case VAEncSliceParameterBufferType:
1035 #ifdef HAVE_VA_JPEG_DECODE
1036      case VAHuffmanTableBufferType:
1037 #endif
1038         /* Ok */
1039         break;
1040
1041     default:
1042         return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1043     }
1044
1045     bufferID = NEW_BUFFER_ID();
1046     obj_buffer = BUFFER(bufferID);
1047
1048     if (NULL == obj_buffer) {
1049         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1050     }
1051
1052     if (type == VAEncCodedBufferType) {
1053         size += ALIGN(sizeof(VACodedBufferSegment), 64);
1054     }
1055
1056     obj_buffer->max_num_elements = num_elements;
1057     obj_buffer->num_elements = num_elements;
1058     obj_buffer->size_element = size;
1059     obj_buffer->type = type;
1060     obj_buffer->buffer_store = NULL;
1061     buffer_store = calloc(1, sizeof(struct buffer_store));
1062     assert(buffer_store);
1063     buffer_store->ref_count = 1;
1064
1065     if (store_bo != NULL) {
1066         buffer_store->bo = store_bo;
1067         dri_bo_reference(buffer_store->bo);
1068         
1069         if (data)
1070             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
1071     } else if (type == VASliceDataBufferType || type == VAImageBufferType || type == VAEncCodedBufferType) {
1072         buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, 
1073                                         "Buffer", 
1074                                         size * num_elements, 64);
1075         assert(buffer_store->bo);
1076
1077         if (type == VAEncCodedBufferType) {
1078             VACodedBufferSegment *coded_buffer_segment;
1079             dri_bo_map(buffer_store->bo, 1);
1080             coded_buffer_segment = (VACodedBufferSegment *)buffer_store->bo->virtual;
1081             coded_buffer_segment->size = size - ALIGN(sizeof(VACodedBufferSegment), 64);
1082             coded_buffer_segment->bit_offset = 0;
1083             coded_buffer_segment->status = 0;
1084             coded_buffer_segment->buf = NULL;
1085             coded_buffer_segment->next = NULL;
1086             dri_bo_unmap(buffer_store->bo);
1087         } else if (data) {
1088             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
1089         }
1090
1091     } else {
1092         buffer_store->buffer = malloc(size * num_elements);
1093         assert(buffer_store->buffer);
1094
1095         if (data)
1096             memcpy(buffer_store->buffer, data, size * num_elements);
1097     }
1098
1099     buffer_store->num_elements = obj_buffer->num_elements;
1100     i965_reference_buffer_store(&obj_buffer->buffer_store, buffer_store);
1101     i965_release_buffer_store(&buffer_store);
1102     *buf_id = bufferID;
1103
1104     return VA_STATUS_SUCCESS;
1105 }
1106
1107 VAStatus 
1108 i965_CreateBuffer(VADriverContextP ctx,
1109                   VAContextID context,          /* in */
1110                   VABufferType type,            /* in */
1111                   unsigned int size,            /* in */
1112                   unsigned int num_elements,    /* in */
1113                   void *data,                   /* in */
1114                   VABufferID *buf_id)           /* out */
1115 {
1116     return i965_create_buffer_internal(ctx, context, type, size, num_elements, data, NULL, buf_id);
1117 }
1118
1119
1120 VAStatus 
1121 i965_BufferSetNumElements(VADriverContextP ctx,
1122                           VABufferID buf_id,           /* in */
1123                           unsigned int num_elements)   /* in */
1124 {
1125     struct i965_driver_data *i965 = i965_driver_data(ctx);
1126     struct object_buffer *obj_buffer = BUFFER(buf_id);
1127     VAStatus vaStatus = VA_STATUS_SUCCESS;
1128
1129     assert(obj_buffer);
1130
1131     if ((num_elements < 0) || 
1132         (num_elements > obj_buffer->max_num_elements)) {
1133         vaStatus = VA_STATUS_ERROR_UNKNOWN;
1134     } else {
1135         obj_buffer->num_elements = num_elements;
1136         if (obj_buffer->buffer_store != NULL) {
1137             obj_buffer->buffer_store->num_elements = num_elements;
1138         }
1139     }
1140
1141     return vaStatus;
1142 }
1143
1144 VAStatus 
1145 i965_MapBuffer(VADriverContextP ctx,
1146                VABufferID buf_id,       /* in */
1147                void **pbuf)             /* out */
1148 {
1149     struct i965_driver_data *i965 = i965_driver_data(ctx);
1150     struct object_buffer *obj_buffer = BUFFER(buf_id);
1151     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1152
1153     assert(obj_buffer && obj_buffer->buffer_store);
1154     assert(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer);
1155     assert(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer));
1156
1157     if (NULL != obj_buffer->buffer_store->bo) {
1158         unsigned int tiling, swizzle;
1159
1160         dri_bo_get_tiling(obj_buffer->buffer_store->bo, &tiling, &swizzle);
1161
1162         if (tiling != I915_TILING_NONE)
1163             drm_intel_gem_bo_map_gtt(obj_buffer->buffer_store->bo);
1164         else
1165             dri_bo_map(obj_buffer->buffer_store->bo, 1);
1166
1167         assert(obj_buffer->buffer_store->bo->virtual);
1168         *pbuf = obj_buffer->buffer_store->bo->virtual;
1169
1170         if (obj_buffer->type == VAEncCodedBufferType) {
1171             VACodedBufferSegment *coded_buffer_segment = (VACodedBufferSegment *)(obj_buffer->buffer_store->bo->virtual);
1172             coded_buffer_segment->buf = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + ALIGN(sizeof(VACodedBufferSegment), 64);
1173         }
1174
1175         vaStatus = VA_STATUS_SUCCESS;
1176     } else if (NULL != obj_buffer->buffer_store->buffer) {
1177         *pbuf = obj_buffer->buffer_store->buffer;
1178         vaStatus = VA_STATUS_SUCCESS;
1179     }
1180
1181     return vaStatus;
1182 }
1183
1184 VAStatus 
1185 i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
1186 {
1187     struct i965_driver_data *i965 = i965_driver_data(ctx);
1188     struct object_buffer *obj_buffer = BUFFER(buf_id);
1189     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1190
1191     assert(obj_buffer && obj_buffer->buffer_store);
1192     assert(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer);
1193     assert(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer));
1194
1195     if (NULL != obj_buffer->buffer_store->bo) {
1196         unsigned int tiling, swizzle;
1197
1198         dri_bo_get_tiling(obj_buffer->buffer_store->bo, &tiling, &swizzle);
1199
1200         if (tiling != I915_TILING_NONE)
1201             drm_intel_gem_bo_unmap_gtt(obj_buffer->buffer_store->bo);
1202         else
1203             dri_bo_unmap(obj_buffer->buffer_store->bo);
1204
1205         vaStatus = VA_STATUS_SUCCESS;
1206     } else if (NULL != obj_buffer->buffer_store->buffer) {
1207         /* Do nothing */
1208         vaStatus = VA_STATUS_SUCCESS;
1209     }
1210
1211     return vaStatus;    
1212 }
1213
1214 VAStatus 
1215 i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
1216 {
1217     struct i965_driver_data *i965 = i965_driver_data(ctx);
1218     struct object_buffer *obj_buffer = BUFFER(buffer_id);
1219
1220     assert(obj_buffer);
1221     i965_destroy_buffer(&i965->buffer_heap, (struct object_base *)obj_buffer);
1222
1223     return VA_STATUS_SUCCESS;
1224 }
1225
1226 VAStatus 
1227 i965_BeginPicture(VADriverContextP ctx,
1228                   VAContextID context,
1229                   VASurfaceID render_target)
1230 {
1231     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1232     struct object_context *obj_context = CONTEXT(context);
1233     struct object_surface *obj_surface = SURFACE(render_target);
1234     struct object_config *obj_config;
1235     VAContextID config;
1236     VAStatus vaStatus;
1237     int i;
1238
1239     assert(obj_context);
1240     assert(obj_surface);
1241
1242     config = obj_context->config_id;
1243     obj_config = CONFIG(config);
1244     assert(obj_config);
1245
1246     switch (obj_config->profile) {
1247     case VAProfileMPEG2Simple:
1248     case VAProfileMPEG2Main:
1249         vaStatus = VA_STATUS_SUCCESS;
1250         break;
1251
1252     case VAProfileH264Baseline:
1253     case VAProfileH264Main:
1254     case VAProfileH264High:
1255         vaStatus = VA_STATUS_SUCCESS;
1256         break;
1257
1258     case VAProfileVC1Simple:
1259     case VAProfileVC1Main:
1260     case VAProfileVC1Advanced:
1261         vaStatus = VA_STATUS_SUCCESS;
1262         break;
1263
1264     case VAProfileJPEGBaseline:
1265         vaStatus = VA_STATUS_SUCCESS;
1266         break;
1267
1268     default:
1269         assert(0);
1270         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1271         break;
1272     }
1273
1274     if (obj_context->codec_type == CODEC_ENC) {
1275         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
1276         i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
1277
1278         for (i = 0; i < obj_context->codec_state.encode.num_slice_params; i++) {
1279             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
1280         }
1281
1282         obj_context->codec_state.encode.num_slice_params = 0;
1283         obj_context->codec_state.encode.current_render_target = render_target;     /*This is input new frame*/
1284     } else {
1285         obj_context->codec_state.decode.current_render_target = render_target;
1286         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
1287         i965_release_buffer_store(&obj_context->codec_state.decode.iq_matrix);
1288         i965_release_buffer_store(&obj_context->codec_state.decode.bit_plane);
1289         i965_release_buffer_store(&obj_context->codec_state.decode.huffman_table);
1290
1291         for (i = 0; i < obj_context->codec_state.decode.num_slice_params; i++) {
1292             i965_release_buffer_store(&obj_context->codec_state.decode.slice_params[i]);
1293             i965_release_buffer_store(&obj_context->codec_state.decode.slice_datas[i]);
1294         }
1295
1296         obj_context->codec_state.decode.num_slice_params = 0;
1297         obj_context->codec_state.decode.num_slice_datas = 0;
1298     }
1299
1300     return vaStatus;
1301 }
1302
1303 #define I965_RENDER_BUFFER(category, name) i965_render_##category##_##name##_buffer(ctx, obj_context, obj_buffer)
1304
1305 #define DEF_RENDER_SINGLE_BUFFER_FUNC(category, name, member)           \
1306     static VAStatus                                                     \
1307     i965_render_##category##_##name##_buffer(VADriverContextP ctx,      \
1308                                              struct object_context *obj_context, \
1309                                              struct object_buffer *obj_buffer) \
1310     {                                                                   \
1311         struct category##_state *category = &obj_context->codec_state.category; \
1312         assert(obj_buffer->buffer_store->bo == NULL);                   \
1313         assert(obj_buffer->buffer_store->buffer);                       \
1314         i965_release_buffer_store(&category->member);                   \
1315         i965_reference_buffer_store(&category->member, obj_buffer->buffer_store); \
1316         return VA_STATUS_SUCCESS;                                       \
1317     }
1318
1319 #define DEF_RENDER_MULTI_BUFFER_FUNC(category, name, member)            \
1320     static VAStatus                                                     \
1321     i965_render_##category##_##name##_buffer(VADriverContextP ctx,      \
1322                                              struct object_context *obj_context, \
1323                                              struct object_buffer *obj_buffer) \
1324     {                                                                   \
1325         struct category##_state *category = &obj_context->codec_state.category; \
1326         if (category->num_##member == category->max_##member) {         \
1327             category->member = realloc(category->member, (category->max_##member + NUM_SLICES) * sizeof(*category->member)); \
1328             memset(category->member + category->max_##member, 0, NUM_SLICES * sizeof(*category->member)); \
1329             category->max_##member += NUM_SLICES;                       \
1330         }                                                               \
1331         i965_release_buffer_store(&category->member[category->num_##member]); \
1332         i965_reference_buffer_store(&category->member[category->num_##member], obj_buffer->buffer_store); \
1333         category->num_##member++;                                       \
1334         return VA_STATUS_SUCCESS;                                       \
1335     }
1336
1337 #define I965_RENDER_DECODE_BUFFER(name) I965_RENDER_BUFFER(decode, name)
1338
1339 #define DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(decode, name, member)
1340 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
1341 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(iq_matrix, iq_matrix)
1342 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(bit_plane, bit_plane)
1343 DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(huffman_table, huffman_table)
1344
1345 #define DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(name, member) DEF_RENDER_MULTI_BUFFER_FUNC(decode, name, member)
1346 DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
1347 DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_data, slice_datas)
1348
1349 static VAStatus 
1350 i965_decoder_render_picture(VADriverContextP ctx,
1351                             VAContextID context,
1352                             VABufferID *buffers,
1353                             int num_buffers)
1354 {
1355     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1356     struct object_context *obj_context = CONTEXT(context);
1357     VAStatus vaStatus = VA_STATUS_SUCCESS;
1358     int i;
1359
1360     for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
1361         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
1362         assert(obj_buffer);
1363
1364         switch (obj_buffer->type) {
1365         case VAPictureParameterBufferType:
1366             vaStatus = I965_RENDER_DECODE_BUFFER(picture_parameter);
1367             break;
1368             
1369         case VAIQMatrixBufferType:
1370             vaStatus = I965_RENDER_DECODE_BUFFER(iq_matrix);
1371             break;
1372
1373         case VABitPlaneBufferType:
1374             vaStatus = I965_RENDER_DECODE_BUFFER(bit_plane);
1375             break;
1376
1377         case VASliceParameterBufferType:
1378             vaStatus = I965_RENDER_DECODE_BUFFER(slice_parameter);
1379             break;
1380
1381         case VASliceDataBufferType:
1382             vaStatus = I965_RENDER_DECODE_BUFFER(slice_data);
1383             break;
1384
1385 #ifdef HAVE_VA_JPEG_DECODE
1386         case VAHuffmanTableBufferType:
1387             vaStatus = I965_RENDER_DECODE_BUFFER(huffman_table);
1388             break;
1389 #endif
1390
1391         default:
1392             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1393             break;
1394         }
1395     }
1396
1397     return vaStatus;
1398 }
1399
1400 #define I965_RENDER_ENCODE_BUFFER(name) I965_RENDER_BUFFER(encode, name)
1401
1402 #define DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(encode, name, member)
1403 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter, seq_param)    
1404 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
1405 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_control, pic_control)
1406 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(qmatrix, q_matrix)
1407 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(iqmatrix, iq_matrix)
1408
1409 #define DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(name, member) DEF_RENDER_MULTI_BUFFER_FUNC(encode, name, member)
1410 DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
1411
1412 static VAStatus 
1413 i965_encoder_render_picture(VADriverContextP ctx,
1414                             VAContextID context,
1415                             VABufferID *buffers,
1416                             int num_buffers)
1417 {
1418     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1419     struct object_context *obj_context = CONTEXT(context);
1420     VAStatus vaStatus = VA_STATUS_SUCCESS;
1421     int i;
1422
1423     for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
1424         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
1425         assert(obj_buffer);
1426
1427         switch (obj_buffer->type) {
1428         case VAEncSequenceParameterBufferType:
1429             vaStatus = I965_RENDER_ENCODE_BUFFER(sequence_parameter);
1430             break;
1431
1432         case VAEncPictureParameterBufferType:
1433             vaStatus = I965_RENDER_ENCODE_BUFFER(picture_parameter);
1434             break;              
1435
1436         case VAEncSliceParameterBufferType:
1437             vaStatus = I965_RENDER_ENCODE_BUFFER(slice_parameter);
1438             break;
1439
1440         case VAPictureParameterBufferType:
1441             vaStatus = I965_RENDER_ENCODE_BUFFER(picture_control);
1442             break;
1443
1444         case VAQMatrixBufferType:
1445             vaStatus = I965_RENDER_ENCODE_BUFFER(qmatrix);
1446             break;
1447
1448         case VAIQMatrixBufferType:
1449             vaStatus = I965_RENDER_ENCODE_BUFFER(iqmatrix);
1450             break;
1451
1452         default:
1453             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1454             break;
1455         }
1456     }   
1457
1458     return vaStatus;
1459 }
1460
1461 VAStatus 
1462 i965_RenderPicture(VADriverContextP ctx,
1463                    VAContextID context,
1464                    VABufferID *buffers,
1465                    int num_buffers)
1466 {
1467     struct i965_driver_data *i965 = i965_driver_data(ctx);
1468     struct object_context *obj_context;
1469     struct object_config *obj_config;
1470     VAContextID config;
1471     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1472
1473     obj_context = CONTEXT(context);
1474     assert(obj_context);
1475
1476     config = obj_context->config_id;
1477     obj_config = CONFIG(config);
1478     assert(obj_config);
1479
1480     if (VAEntrypointEncSlice == obj_config->entrypoint ){
1481         vaStatus = i965_encoder_render_picture(ctx, context, buffers, num_buffers);
1482     } else {
1483         vaStatus = i965_decoder_render_picture(ctx, context, buffers, num_buffers);
1484     }
1485
1486     return vaStatus;
1487 }
1488
1489 VAStatus 
1490 i965_EndPicture(VADriverContextP ctx, VAContextID context)
1491 {
1492     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1493     struct object_context *obj_context = CONTEXT(context);
1494     struct object_config *obj_config;
1495     VAContextID config;
1496
1497     assert(obj_context);
1498     config = obj_context->config_id;
1499     obj_config = CONFIG(config);
1500     assert(obj_config);
1501
1502     if (obj_context->codec_type == CODEC_ENC) {
1503         assert(VAEntrypointEncSlice == obj_config->entrypoint);
1504
1505         assert(obj_context->codec_state.encode.pic_param);
1506         assert(obj_context->codec_state.encode.seq_param);
1507         assert(obj_context->codec_state.encode.num_slice_params >= 1);
1508     } else {
1509         assert(obj_context->codec_state.decode.pic_param);
1510         assert(obj_context->codec_state.decode.num_slice_params >= 1);
1511         assert(obj_context->codec_state.decode.num_slice_datas >= 1);
1512         assert(obj_context->codec_state.decode.num_slice_params == obj_context->codec_state.decode.num_slice_datas);
1513     }
1514
1515     assert(obj_context->hw_context->run);
1516     obj_context->hw_context->run(ctx, obj_config->profile, &obj_context->codec_state, obj_context->hw_context);
1517
1518     return VA_STATUS_SUCCESS;
1519 }
1520
1521 VAStatus 
1522 i965_SyncSurface(VADriverContextP ctx,
1523                  VASurfaceID render_target)
1524 {
1525     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1526     struct object_surface *obj_surface = SURFACE(render_target);
1527
1528     assert(obj_surface);
1529
1530     if(obj_surface->bo)
1531         drm_intel_bo_wait_rendering(obj_surface->bo);
1532
1533     return VA_STATUS_SUCCESS;
1534 }
1535
1536 VAStatus 
1537 i965_QuerySurfaceStatus(VADriverContextP ctx,
1538                         VASurfaceID render_target,
1539                         VASurfaceStatus *status)        /* out */
1540 {
1541     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1542     struct object_surface *obj_surface = SURFACE(render_target);
1543
1544     assert(obj_surface);
1545
1546     if (obj_surface->bo) {
1547         if (drm_intel_bo_busy(obj_surface->bo)){
1548             *status = VASurfaceRendering;
1549         }
1550         else {
1551             *status = VASurfaceReady;
1552         }
1553     } else {
1554         *status = VASurfaceReady;
1555     }
1556
1557     return VA_STATUS_SUCCESS;
1558 }
1559
1560 static VADisplayAttribute *
1561 get_display_attribute(VADriverContextP ctx, VADisplayAttribType type)
1562 {
1563     struct i965_driver_data * const i965 = i965_driver_data(ctx);
1564     unsigned int i;
1565
1566     if (!i965->display_attributes)
1567         return NULL;
1568
1569     for (i = 0; i < i965->num_display_attributes; i++) {
1570         if (i965->display_attributes[i].type == type)
1571             return &i965->display_attributes[i];
1572     }
1573     return NULL;
1574 }
1575
1576 static bool
1577 i965_display_attributes_init(VADriverContextP ctx)
1578 {
1579     struct i965_driver_data * const i965 = i965_driver_data(ctx);
1580
1581     i965->num_display_attributes = ARRAY_ELEMS(i965_display_attributes);
1582     i965->display_attributes = malloc(
1583         i965->num_display_attributes * sizeof(i965->display_attributes[0]));
1584     if (!i965->display_attributes)
1585         return false;
1586
1587     memcpy(
1588         i965->display_attributes,
1589         i965_display_attributes,
1590         sizeof(i965_display_attributes)
1591     );
1592
1593     i965->rotation_attrib = get_display_attribute(ctx, VADisplayAttribRotation);
1594     if (!i965->rotation_attrib)
1595         return false;
1596     return true;
1597 }
1598
1599 static void
1600 i965_display_attributes_terminate(VADriverContextP ctx)
1601 {
1602     struct i965_driver_data * const i965 = i965_driver_data(ctx);
1603
1604     if (i965->display_attributes) {
1605         free(i965->display_attributes);
1606         i965->display_attributes = NULL;
1607         i965->num_display_attributes = 0;
1608     }
1609 }
1610
1611 /* 
1612  * Query display attributes 
1613  * The caller must provide a "attr_list" array that can hold at
1614  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1615  * returned in "attr_list" is returned in "num_attributes".
1616  */
1617 VAStatus 
1618 i965_QueryDisplayAttributes(
1619     VADriverContextP    ctx,
1620     VADisplayAttribute *attribs,        /* out */
1621     int                *num_attribs_ptr /* out */
1622 )
1623 {
1624     const int num_attribs = ARRAY_ELEMS(i965_display_attributes);
1625
1626     if (attribs && num_attribs > 0)
1627         memcpy(attribs, i965_display_attributes, sizeof(i965_display_attributes));
1628
1629     if (num_attribs_ptr)
1630         *num_attribs_ptr = num_attribs;
1631
1632     return VA_STATUS_SUCCESS;
1633 }
1634
1635 /* 
1636  * Get display attributes 
1637  * This function returns the current attribute values in "attr_list".
1638  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
1639  * from vaQueryDisplayAttributes() can have their values retrieved.  
1640  */
1641 VAStatus 
1642 i965_GetDisplayAttributes(
1643     VADriverContextP    ctx,
1644     VADisplayAttribute *attribs,        /* inout */
1645     int                 num_attribs     /* in */
1646 )
1647 {
1648     int i;
1649
1650     for (i = 0; i < num_attribs; i++) {
1651         VADisplayAttribute *src_attrib, * const dst_attrib = &attribs[i];
1652
1653         src_attrib = get_display_attribute(ctx, dst_attrib->type);
1654         if (src_attrib && (src_attrib->flags & VA_DISPLAY_ATTRIB_GETTABLE)) {
1655             dst_attrib->min_value = src_attrib->min_value;
1656             dst_attrib->max_value = src_attrib->max_value;
1657             dst_attrib->value     = src_attrib->value;
1658         }
1659         else
1660             dst_attrib->flags = VA_DISPLAY_ATTRIB_NOT_SUPPORTED;
1661     }
1662     return VA_STATUS_SUCCESS;
1663 }
1664
1665 /* 
1666  * Set display attributes 
1667  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
1668  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or 
1669  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
1670  */
1671 VAStatus 
1672 i965_SetDisplayAttributes(
1673     VADriverContextP    ctx,
1674     VADisplayAttribute *attribs,        /* in */
1675     int                 num_attribs     /* in */
1676 )
1677 {
1678     int i;
1679
1680     for (i = 0; i < num_attribs; i++) {
1681         VADisplayAttribute *dst_attrib, * const src_attrib = &attribs[i];
1682
1683         dst_attrib = get_display_attribute(ctx, src_attrib->type);
1684         if (!dst_attrib)
1685             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
1686
1687         if (!(dst_attrib->flags & VA_DISPLAY_ATTRIB_SETTABLE))
1688             continue;
1689
1690         if (src_attrib->value < dst_attrib->min_value ||
1691             src_attrib->value > dst_attrib->max_value)
1692             return VA_STATUS_ERROR_INVALID_PARAMETER;
1693
1694         dst_attrib->value = src_attrib->value;
1695         /* XXX: track modified attributes through timestamps */
1696     }
1697     return VA_STATUS_SUCCESS;
1698 }
1699
1700 VAStatus 
1701 i965_DbgCopySurfaceToBuffer(VADriverContextP ctx,
1702                             VASurfaceID surface,
1703                             void **buffer,              /* out */
1704                             unsigned int *stride)       /* out */
1705 {
1706     /* TODO */
1707     return VA_STATUS_ERROR_UNIMPLEMENTED;
1708 }
1709
1710 static VAStatus 
1711 i965_Init(VADriverContextP ctx)
1712 {
1713     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1714
1715     if (intel_driver_init(ctx) == False)
1716         return VA_STATUS_ERROR_UNKNOWN;
1717
1718     if (IS_HASWELL(i965->intel.device_id))
1719         i965->codec_info = &gen75_hw_codec_info;
1720     else if (IS_G4X(i965->intel.device_id))
1721         i965->codec_info = &g4x_hw_codec_info;
1722     else if (IS_IRONLAKE(i965->intel.device_id))
1723         i965->codec_info = &ironlake_hw_codec_info;
1724     else if (IS_GEN6(i965->intel.device_id))
1725         i965->codec_info = &gen6_hw_codec_info;
1726     else if (IS_GEN7(i965->intel.device_id))
1727         i965->codec_info = &gen7_hw_codec_info;
1728     else
1729         return VA_STATUS_ERROR_UNKNOWN;
1730
1731     i965->batch = intel_batchbuffer_new(&i965->intel, I915_EXEC_RENDER);
1732
1733     if (!i965_display_attributes_init(ctx))
1734         return VA_STATUS_ERROR_UNKNOWN;
1735
1736     if (i965_post_processing_init(ctx) == False)
1737         return VA_STATUS_ERROR_UNKNOWN;
1738
1739     if (i965_render_init(ctx) == False)
1740         return VA_STATUS_ERROR_UNKNOWN;
1741
1742 #ifdef HAVE_VA_WAYLAND
1743     if (IS_VA_WAYLAND(ctx) && !i965_output_wayland_init(ctx))
1744         return VA_STATUS_ERROR_UNKNOWN;
1745 #endif
1746
1747 #ifdef HAVE_VA_X11
1748     if (IS_VA_X11(ctx) && !i965_output_dri_init(ctx))
1749         return VA_STATUS_ERROR_UNKNOWN;
1750 #endif
1751
1752     _i965InitMutex(&i965->render_mutex);
1753
1754     return VA_STATUS_SUCCESS;
1755 }
1756
1757 static void
1758 i965_destroy_heap(struct object_heap *heap, 
1759                   void (*func)(struct object_heap *heap, struct object_base *object))
1760 {
1761     struct object_base *object;
1762     object_heap_iterator iter;    
1763
1764     object = object_heap_first(heap, &iter);
1765
1766     while (object) {
1767         if (func)
1768             func(heap, object);
1769
1770         object = object_heap_next(heap, &iter);
1771     }
1772
1773     object_heap_destroy(heap);
1774 }
1775
1776
1777 VAStatus 
1778 i965_DestroyImage(VADriverContextP ctx, VAImageID image);
1779
1780 VAStatus 
1781 i965_CreateImage(VADriverContextP ctx,
1782                  VAImageFormat *format,
1783                  int width,
1784                  int height,
1785                  VAImage *out_image)        /* out */
1786 {
1787     struct i965_driver_data *i965 = i965_driver_data(ctx);
1788     struct object_image *obj_image;
1789     VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED;
1790     VAImageID image_id;
1791     unsigned int width2, height2, size2, size;
1792
1793     out_image->image_id = VA_INVALID_ID;
1794     out_image->buf      = VA_INVALID_ID;
1795
1796     image_id = NEW_IMAGE_ID();
1797     if (image_id == VA_INVALID_ID)
1798         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1799
1800     obj_image = IMAGE(image_id);
1801     if (!obj_image)
1802         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1803     obj_image->bo         = NULL;
1804     obj_image->palette    = NULL;
1805     obj_image->derived_surface = VA_INVALID_ID;
1806
1807     VAImage * const image = &obj_image->image;
1808     image->image_id       = image_id;
1809     image->buf            = VA_INVALID_ID;
1810
1811     size    = width * height;
1812     width2  = (width  + 1) / 2;
1813     height2 = (height + 1) / 2;
1814     size2   = width2 * height2;
1815
1816     image->num_palette_entries = 0;
1817     image->entry_bytes         = 0;
1818     memset(image->component_order, 0, sizeof(image->component_order));
1819
1820     switch (format->fourcc) {
1821     case VA_FOURCC('I','A','4','4'):
1822     case VA_FOURCC('A','I','4','4'):
1823         image->num_planes = 1;
1824         image->pitches[0] = width;
1825         image->offsets[0] = 0;
1826         image->data_size  = image->offsets[0] + image->pitches[0] * height;
1827         image->num_palette_entries = 16;
1828         image->entry_bytes         = 3;
1829         image->component_order[0]  = 'R';
1830         image->component_order[1]  = 'G';
1831         image->component_order[2]  = 'B';
1832         break;
1833     case VA_FOURCC('A','R','G','B'):
1834     case VA_FOURCC('A','B','G','R'):
1835     case VA_FOURCC('B','G','R','A'):
1836     case VA_FOURCC('R','G','B','A'):
1837         image->num_planes = 1;
1838         image->pitches[0] = width * 4;
1839         image->offsets[0] = 0;
1840         image->data_size  = image->offsets[0] + image->pitches[0] * height;
1841         break;
1842     case VA_FOURCC('Y','V','1','2'):
1843         image->num_planes = 3;
1844         image->pitches[0] = width;
1845         image->offsets[0] = 0;
1846         image->pitches[1] = width2;
1847         image->offsets[1] = size + size2;
1848         image->pitches[2] = width2;
1849         image->offsets[2] = size;
1850         image->data_size  = size + 2 * size2;
1851         break;
1852     case VA_FOURCC('I','4','2','0'):
1853         image->num_planes = 3;
1854         image->pitches[0] = width;
1855         image->offsets[0] = 0;
1856         image->pitches[1] = width2;
1857         image->offsets[1] = size;
1858         image->pitches[2] = width2;
1859         image->offsets[2] = size + size2;
1860         image->data_size  = size + 2 * size2;
1861         break;
1862     case VA_FOURCC('N','V','1','2'):
1863         image->num_planes = 2;
1864         image->pitches[0] = width;
1865         image->offsets[0] = 0;
1866         image->pitches[1] = width;
1867         image->offsets[1] = size;
1868         image->data_size  = size + 2 * size2;
1869         break;
1870     default:
1871         goto error;
1872     }
1873
1874     va_status = i965_CreateBuffer(ctx, 0, VAImageBufferType,
1875                                   image->data_size, 1, NULL, &image->buf);
1876     if (va_status != VA_STATUS_SUCCESS)
1877         goto error;
1878
1879     obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
1880     dri_bo_reference(obj_image->bo);
1881
1882     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
1883         obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
1884         if (!obj_image->palette)
1885             goto error;
1886     }
1887
1888     image->image_id             = image_id;
1889     image->format               = *format;
1890     image->width                = width;
1891     image->height               = height;
1892
1893     *out_image                  = *image;
1894     return VA_STATUS_SUCCESS;
1895
1896  error:
1897     i965_DestroyImage(ctx, image_id);
1898     return va_status;
1899 }
1900
1901 void 
1902 i965_check_alloc_surface_bo(VADriverContextP ctx,
1903                             struct object_surface *obj_surface,
1904                             int tiled,
1905                             unsigned int fourcc,
1906                             unsigned int subsampling)
1907 {
1908     struct i965_driver_data *i965 = i965_driver_data(ctx);
1909     int region_width, region_height;
1910
1911     if (obj_surface->bo) {
1912         assert(obj_surface->fourcc);
1913         assert(obj_surface->fourcc == fourcc);
1914         assert(obj_surface->subsampling == subsampling);
1915         return;
1916     }
1917
1918     obj_surface->x_cb_offset = 0; /* X offset is always 0 */
1919     obj_surface->x_cr_offset = 0;
1920
1921     if (tiled) {
1922         assert(fourcc == VA_FOURCC('N', 'V', '1', '2') ||
1923                fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
1924                fourcc == VA_FOURCC('I', 'M', 'C', '3'));
1925
1926         obj_surface->width = ALIGN(obj_surface->orig_width, 128);
1927         obj_surface->height = ALIGN(obj_surface->orig_height, 32);
1928         obj_surface->cb_cr_pitch = obj_surface->width;
1929         region_width = obj_surface->width;
1930         region_height = obj_surface->height;
1931
1932         if (fourcc == VA_FOURCC('N', 'V', '1', '2')) {
1933             assert(subsampling == SUBSAMPLE_YUV420);
1934             obj_surface->y_cb_offset = obj_surface->height;
1935             obj_surface->y_cr_offset = obj_surface->height;
1936             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
1937             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
1938             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
1939         } else if (fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
1940                    fourcc == VA_FOURCC('I', 'M', 'C', '3')) {
1941             switch (subsampling) {
1942             case SUBSAMPLE_YUV400:
1943                 obj_surface->cb_cr_width = 0;
1944                 obj_surface->cb_cr_height = 0;
1945                 break;
1946
1947             case SUBSAMPLE_YUV420:
1948                 obj_surface->cb_cr_width = obj_surface->orig_width / 2;
1949                 obj_surface->cb_cr_height = obj_surface->orig_height / 2;
1950                 break;
1951
1952             case SUBSAMPLE_YUV422H:
1953                 obj_surface->cb_cr_width = obj_surface->orig_width / 2;
1954                 obj_surface->cb_cr_height = obj_surface->orig_height;
1955                 break;
1956
1957             case SUBSAMPLE_YUV422V:
1958                 obj_surface->cb_cr_width = obj_surface->orig_width;
1959                 obj_surface->cb_cr_height = obj_surface->orig_height / 2;
1960                 break;
1961
1962             case SUBSAMPLE_YUV444:
1963                 obj_surface->cb_cr_width = obj_surface->orig_width;
1964                 obj_surface->cb_cr_height = obj_surface->orig_height;
1965                 break;
1966
1967             case SUBSAMPLE_YUV411:
1968                 obj_surface->cb_cr_width = obj_surface->orig_width / 4;
1969                 obj_surface->cb_cr_height = obj_surface->orig_height;
1970                 break;
1971
1972             default:
1973                 assert(0);
1974                 break;
1975             }
1976
1977             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
1978
1979             if (fourcc == VA_FOURCC('I', 'M', 'C', '1')) {
1980                 obj_surface->y_cr_offset = obj_surface->height;
1981                 obj_surface->y_cb_offset = obj_surface->y_cr_offset + ALIGN(obj_surface->cb_cr_height, 32);
1982             } else {
1983                 obj_surface->y_cb_offset = obj_surface->height;
1984                 obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
1985             }
1986         }
1987     } else {
1988         assert(fourcc != VA_FOURCC('I', 'M', 'C', '1') &&
1989                fourcc != VA_FOURCC('I', 'M', 'C', '3'));
1990         assert(subsampling == SUBSAMPLE_YUV420);
1991
1992         region_width = obj_surface->width;
1993         region_height = obj_surface->height;
1994
1995         switch (fourcc) {
1996         case VA_FOURCC('N', 'V', '1', '2'):
1997             obj_surface->y_cb_offset = obj_surface->height;
1998             obj_surface->y_cr_offset = obj_surface->height;
1999             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
2000             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
2001             obj_surface->cb_cr_pitch = obj_surface->width;
2002             region_height = obj_surface->height + obj_surface->height / 2;
2003             break;
2004
2005         case VA_FOURCC('Y', 'V', '1', '2'):
2006         case VA_FOURCC('I', '4', '2', '0'):
2007             if (fourcc == VA_FOURCC('Y', 'V', '1', '2')) {
2008                 obj_surface->y_cr_offset = obj_surface->height;
2009                 obj_surface->y_cb_offset = obj_surface->height + obj_surface->height / 4;
2010             } else {
2011                 obj_surface->y_cb_offset = obj_surface->height;
2012                 obj_surface->y_cr_offset = obj_surface->height + obj_surface->height / 4;
2013             }
2014
2015             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
2016             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
2017             obj_surface->cb_cr_pitch = obj_surface->width / 2;
2018             region_height = obj_surface->height + obj_surface->height / 2;
2019             break;
2020
2021         default:
2022             assert(0);
2023             break;
2024         }
2025     }
2026
2027     obj_surface->size = ALIGN(region_width * region_height, 0x1000);
2028
2029     if (tiled) {
2030         uint32_t tiling_mode = I915_TILING_Y; /* always uses Y-tiled format */
2031         unsigned long pitch;
2032
2033         obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr, 
2034                                                    "vaapi surface",
2035                                                    region_width,
2036                                                    region_height,
2037                                                    1,
2038                                                    &tiling_mode,
2039                                                    &pitch,
2040                                                    0);
2041         assert(tiling_mode == I915_TILING_Y);
2042         assert(pitch == obj_surface->width);
2043     } else {
2044         obj_surface->bo = dri_bo_alloc(i965->intel.bufmgr,
2045                                        "vaapi surface",
2046                                        obj_surface->size,
2047                                        0x1000);
2048     }
2049
2050     obj_surface->fourcc = fourcc;
2051     obj_surface->subsampling = subsampling;
2052     assert(obj_surface->bo);
2053 }
2054
2055 VAStatus i965_DeriveImage(VADriverContextP ctx,
2056                           VASurfaceID surface,
2057                           VAImage *out_image)        /* out */
2058 {
2059     struct i965_driver_data *i965 = i965_driver_data(ctx);
2060     struct i965_render_state *render_state = &i965->render_state;
2061     struct object_image *obj_image;
2062     struct object_surface *obj_surface; 
2063     VAImageID image_id;
2064     unsigned int w_pitch, h_pitch;
2065     VAStatus va_status;
2066
2067     out_image->image_id = VA_INVALID_ID;
2068     obj_surface = SURFACE(surface);
2069
2070     if (!obj_surface)
2071         return VA_STATUS_ERROR_INVALID_SURFACE;
2072
2073     w_pitch = obj_surface->width;
2074     h_pitch = obj_surface->height;
2075
2076     image_id = NEW_IMAGE_ID();
2077
2078     if (image_id == VA_INVALID_ID)
2079         return VA_STATUS_ERROR_ALLOCATION_FAILED;
2080
2081     obj_image = IMAGE(image_id);
2082     
2083     if (!obj_image)
2084         return VA_STATUS_ERROR_ALLOCATION_FAILED;
2085
2086     obj_image->bo = NULL;
2087     obj_image->palette = NULL;
2088     obj_image->derived_surface = VA_INVALID_ID;
2089
2090     VAImage * const image = &obj_image->image;
2091     
2092     memset(image, 0, sizeof(*image));
2093     image->image_id = image_id;
2094     image->buf = VA_INVALID_ID;
2095     image->num_palette_entries = 0;
2096     image->entry_bytes = 0;
2097     image->width = obj_surface->orig_width;
2098     image->height = obj_surface->orig_height;
2099     image->data_size = obj_surface->size;
2100
2101     if (!render_state->inited) {
2102             image->format.fourcc = VA_FOURCC('Y','V','1','2');
2103             image->format.byte_order = VA_LSB_FIRST;
2104             image->format.bits_per_pixel = 12;
2105             image->num_planes = 3;
2106             image->pitches[0] = w_pitch;
2107             image->offsets[0] = 0;
2108             image->pitches[1] = w_pitch / 2;
2109             image->offsets[1] = w_pitch * h_pitch;
2110             image->pitches[2] = w_pitch / 2;
2111             image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2);
2112     } else {
2113         if (render_state->interleaved_uv) {
2114             image->format.fourcc = VA_FOURCC('N','V','1','2');
2115             image->format.byte_order = VA_LSB_FIRST;
2116             image->format.bits_per_pixel = 12;
2117             image->num_planes = 2;
2118             image->pitches[0] = w_pitch;
2119             image->offsets[0] = 0;
2120             image->pitches[1] = w_pitch;
2121             image->offsets[1] = w_pitch * h_pitch;
2122         } else {
2123             image->format.fourcc = VA_FOURCC('I','4','2','0');
2124             image->format.byte_order = VA_LSB_FIRST;
2125             image->format.bits_per_pixel = 12;
2126             image->num_planes = 3;
2127             image->pitches[0] = w_pitch;
2128             image->offsets[0] = 0;
2129             image->pitches[1] = w_pitch / 2;
2130             image->offsets[1] = w_pitch * h_pitch;
2131             image->pitches[2] = w_pitch / 2;
2132             image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2);
2133         }
2134     }
2135
2136     i965_check_alloc_surface_bo(ctx, obj_surface, HAS_TILED_SURFACE(i965), image->format.fourcc, SUBSAMPLE_YUV420);
2137     va_status = i965_create_buffer_internal(ctx, 0, VAImageBufferType,
2138                                             obj_surface->size, 1, NULL, obj_surface->bo, &image->buf);
2139     if (va_status != VA_STATUS_SUCCESS)
2140         goto error;
2141
2142     obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
2143     dri_bo_reference(obj_image->bo);
2144
2145     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
2146         obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
2147         if (!obj_image->palette) {
2148             va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
2149             goto error;
2150         }
2151     }
2152
2153     *out_image = *image;
2154     obj_surface->flags |= SURFACE_DERIVED;
2155     obj_image->derived_surface = surface;
2156
2157     return VA_STATUS_SUCCESS;
2158
2159  error:
2160     i965_DestroyImage(ctx, image_id);
2161     return va_status;
2162 }
2163
2164 static void 
2165 i965_destroy_image(struct object_heap *heap, struct object_base *obj)
2166 {
2167     object_heap_free(heap, obj);
2168 }
2169
2170
2171 VAStatus 
2172 i965_DestroyImage(VADriverContextP ctx, VAImageID image)
2173 {
2174     struct i965_driver_data *i965 = i965_driver_data(ctx);
2175     struct object_image *obj_image = IMAGE(image); 
2176     struct object_surface *obj_surface; 
2177
2178     if (!obj_image)
2179         return VA_STATUS_SUCCESS;
2180
2181     dri_bo_unreference(obj_image->bo);
2182     obj_image->bo = NULL;
2183
2184     if (obj_image->image.buf != VA_INVALID_ID) {
2185         i965_DestroyBuffer(ctx, obj_image->image.buf);
2186         obj_image->image.buf = VA_INVALID_ID;
2187     }
2188
2189     if (obj_image->palette) {
2190         free(obj_image->palette);
2191         obj_image->palette = NULL;
2192     }
2193
2194     obj_surface = SURFACE(obj_image->derived_surface);
2195
2196     if (obj_surface) {
2197         obj_surface->flags &= ~SURFACE_DERIVED;
2198     }
2199
2200     i965_destroy_image(&i965->image_heap, (struct object_base *)obj_image);
2201
2202     return VA_STATUS_SUCCESS;
2203 }
2204
2205 /*
2206  * pointer to an array holding the palette data.  The size of the array is
2207  * num_palette_entries * entry_bytes in size.  The order of the components
2208  * in the palette is described by the component_order in VASubpicture struct
2209  */
2210 VAStatus 
2211 i965_SetImagePalette(VADriverContextP ctx,
2212                      VAImageID image,
2213                      unsigned char *palette)
2214 {
2215     struct i965_driver_data *i965 = i965_driver_data(ctx);
2216     unsigned int i;
2217
2218     struct object_image *obj_image = IMAGE(image);
2219     if (!obj_image)
2220         return VA_STATUS_ERROR_INVALID_IMAGE;
2221
2222     if (!obj_image->palette)
2223         return VA_STATUS_ERROR_ALLOCATION_FAILED; /* XXX: unpaletted/error */
2224
2225     for (i = 0; i < obj_image->image.num_palette_entries; i++)
2226         obj_image->palette[i] = (((unsigned int)palette[3*i + 0] << 16) |
2227                                  ((unsigned int)palette[3*i + 1] <<  8) |
2228                                  (unsigned int)palette[3*i + 2]);
2229     return VA_STATUS_SUCCESS;
2230 }
2231
2232 static inline void
2233 memcpy_pic(uint8_t *dst, unsigned int dst_stride,
2234            const uint8_t *src, unsigned int src_stride,
2235            unsigned int len, unsigned int height)
2236 {
2237     unsigned int i;
2238
2239     for (i = 0; i < height; i++) {
2240         memcpy(dst, src, len);
2241         dst += dst_stride;
2242         src += src_stride;
2243     }
2244 }
2245
2246 static void
2247 get_image_i420(struct object_image *obj_image, uint8_t *image_data,
2248                struct object_surface *obj_surface,
2249                const VARectangle *rect)
2250 {
2251     uint8_t *dst[3], *src[3];
2252     const int Y = 0;
2253     const int U = obj_image->image.format.fourcc == obj_surface->fourcc ? 1 : 2;
2254     const int V = obj_image->image.format.fourcc == obj_surface->fourcc ? 2 : 1;
2255     unsigned int tiling, swizzle;
2256
2257     if (!obj_surface->bo)
2258         return;
2259
2260     assert(obj_surface->fourcc);
2261     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
2262
2263     if (tiling != I915_TILING_NONE)
2264         drm_intel_gem_bo_map_gtt(obj_surface->bo);
2265     else
2266         dri_bo_map(obj_surface->bo, 0);
2267
2268     if (!obj_surface->bo->virtual)
2269         return;
2270
2271     /* Dest VA image has either I420 or YV12 format.
2272        Source VA surface alway has I420 format */
2273     dst[Y] = image_data + obj_image->image.offsets[Y];
2274     src[0] = (uint8_t *)obj_surface->bo->virtual;
2275     dst[U] = image_data + obj_image->image.offsets[U];
2276     src[1] = src[0] + obj_surface->width * obj_surface->height;
2277     dst[V] = image_data + obj_image->image.offsets[V];
2278     src[2] = src[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
2279
2280     /* Y plane */
2281     dst[Y] += rect->y * obj_image->image.pitches[Y] + rect->x;
2282     src[0] += rect->y * obj_surface->width + rect->x;
2283     memcpy_pic(dst[Y], obj_image->image.pitches[Y],
2284                src[0], obj_surface->width,
2285                rect->width, rect->height);
2286
2287     /* U plane */
2288     dst[U] += (rect->y / 2) * obj_image->image.pitches[U] + rect->x / 2;
2289     src[1] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2;
2290     memcpy_pic(dst[U], obj_image->image.pitches[U],
2291                src[1], obj_surface->width / 2,
2292                rect->width / 2, rect->height / 2);
2293
2294     /* V plane */
2295     dst[V] += (rect->y / 2) * obj_image->image.pitches[V] + rect->x / 2;
2296     src[2] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2;
2297     memcpy_pic(dst[V], obj_image->image.pitches[V],
2298                src[2], obj_surface->width / 2,
2299                rect->width / 2, rect->height / 2);
2300
2301     if (tiling != I915_TILING_NONE)
2302         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
2303     else
2304         dri_bo_unmap(obj_surface->bo);
2305 }
2306
2307 static void
2308 get_image_nv12(struct object_image *obj_image, uint8_t *image_data,
2309                struct object_surface *obj_surface,
2310                const VARectangle *rect)
2311 {
2312     uint8_t *dst[2], *src[2];
2313     unsigned int tiling, swizzle;
2314
2315     if (!obj_surface->bo)
2316         return;
2317
2318     assert(obj_surface->fourcc);
2319     dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
2320
2321     if (tiling != I915_TILING_NONE)
2322         drm_intel_gem_bo_map_gtt(obj_surface->bo);
2323     else
2324         dri_bo_map(obj_surface->bo, 0);
2325
2326     if (!obj_surface->bo->virtual)
2327         return;
2328
2329     /* Both dest VA image and source surface have NV12 format */
2330     dst[0] = image_data + obj_image->image.offsets[0];
2331     src[0] = (uint8_t *)obj_surface->bo->virtual;
2332     dst[1] = image_data + obj_image->image.offsets[1];
2333     src[1] = src[0] + obj_surface->width * obj_surface->height;
2334
2335     /* Y plane */
2336     dst[0] += rect->y * obj_image->image.pitches[0] + rect->x;
2337     src[0] += rect->y * obj_surface->width + rect->x;
2338     memcpy_pic(dst[0], obj_image->image.pitches[0],
2339                src[0], obj_surface->width,
2340                rect->width, rect->height);
2341
2342     /* UV plane */
2343     dst[1] += (rect->y / 2) * obj_image->image.pitches[1] + (rect->x & -2);
2344     src[1] += (rect->y / 2) * obj_surface->width + (rect->x & -2);
2345     memcpy_pic(dst[1], obj_image->image.pitches[1],
2346                src[1], obj_surface->width,
2347                rect->width, rect->height / 2);
2348
2349     if (tiling != I915_TILING_NONE)
2350         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
2351     else
2352         dri_bo_unmap(obj_surface->bo);
2353 }
2354
2355 VAStatus 
2356 i965_GetImage(VADriverContextP ctx,
2357               VASurfaceID surface,
2358               int x,   /* coordinates of the upper left source pixel */
2359               int y,
2360               unsigned int width,      /* width and height of the region */
2361               unsigned int height,
2362               VAImageID image)
2363 {
2364     struct i965_driver_data *i965 = i965_driver_data(ctx);
2365     struct i965_render_state *render_state = &i965->render_state;
2366
2367     struct object_surface *obj_surface = SURFACE(surface);
2368     if (!obj_surface)
2369         return VA_STATUS_ERROR_INVALID_SURFACE;
2370
2371     struct object_image *obj_image = IMAGE(image);
2372     if (!obj_image)
2373         return VA_STATUS_ERROR_INVALID_IMAGE;
2374
2375     if (x < 0 || y < 0)
2376         return VA_STATUS_ERROR_INVALID_PARAMETER;
2377     if (x + width > obj_surface->orig_width ||
2378         y + height > obj_surface->orig_height)
2379         return VA_STATUS_ERROR_INVALID_PARAMETER;
2380     if (x + width > obj_image->image.width ||
2381         y + height > obj_image->image.height)
2382         return VA_STATUS_ERROR_INVALID_PARAMETER;
2383
2384     VAStatus va_status;
2385     void *image_data = NULL;
2386
2387     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
2388     if (va_status != VA_STATUS_SUCCESS)
2389         return va_status;
2390
2391     VARectangle rect;
2392     rect.x = x;
2393     rect.y = y;
2394     rect.width = width;
2395     rect.height = height;
2396
2397     switch (obj_image->image.format.fourcc) {
2398     case VA_FOURCC('Y','V','1','2'):
2399     case VA_FOURCC('I','4','2','0'):
2400         /* I420 is native format for MPEG-2 decoded surfaces */
2401         if (render_state->interleaved_uv)
2402             goto operation_failed;
2403         get_image_i420(obj_image, image_data, obj_surface, &rect);
2404         break;
2405     case VA_FOURCC('N','V','1','2'):
2406         /* NV12 is native format for H.264 decoded surfaces */
2407         if (!render_state->interleaved_uv)
2408             goto operation_failed;
2409         get_image_nv12(obj_image, image_data, obj_surface, &rect);
2410         break;
2411     default:
2412     operation_failed:
2413         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
2414         break;
2415     }
2416
2417     i965_UnmapBuffer(ctx, obj_image->image.buf);
2418     return va_status;
2419 }
2420
2421 VAStatus 
2422 i965_PutSurface(VADriverContextP ctx,
2423                 VASurfaceID surface,
2424                 void *draw, /* X Drawable */
2425                 short srcx,
2426                 short srcy,
2427                 unsigned short srcw,
2428                 unsigned short srch,
2429                 short destx,
2430                 short desty,
2431                 unsigned short destw,
2432                 unsigned short desth,
2433                 VARectangle *cliprects, /* client supplied clip list */
2434                 unsigned int number_cliprects, /* number of clip rects in the clip list */
2435                 unsigned int flags) /* de-interlacing flags */
2436 {
2437 #ifdef HAVE_VA_X11
2438     if (IS_VA_X11(ctx)) {
2439         VARectangle src_rect, dst_rect;
2440
2441         src_rect.x      = srcx;
2442         src_rect.y      = srcy;
2443         src_rect.width  = srcw;
2444         src_rect.height = srch;
2445
2446         dst_rect.x      = destx;
2447         dst_rect.y      = desty;
2448         dst_rect.width  = destw;
2449         dst_rect.height = desth;
2450
2451         return i965_put_surface_dri(ctx, surface, draw, &src_rect, &dst_rect,
2452                                     cliprects, number_cliprects, flags);
2453     }
2454 #endif
2455     return VA_STATUS_ERROR_UNIMPLEMENTED;
2456 }
2457
2458 VAStatus 
2459 i965_Terminate(VADriverContextP ctx)
2460 {
2461     struct i965_driver_data *i965 = i965_driver_data(ctx);
2462
2463     if (i965->batch)
2464         intel_batchbuffer_free(i965->batch);
2465
2466     _i965DestroyMutex(&i965->render_mutex);
2467
2468 #ifdef HAVE_VA_X11
2469     if (IS_VA_X11(ctx))
2470         i965_output_dri_terminate(ctx);
2471 #endif
2472
2473 #ifdef HAVE_VA_WAYLAND
2474     if (IS_VA_WAYLAND(ctx))
2475         i965_output_wayland_terminate(ctx);
2476 #endif
2477
2478     if (i965_render_terminate(ctx) == False)
2479         return VA_STATUS_ERROR_UNKNOWN;
2480
2481     if (i965_post_processing_terminate(ctx) == False)
2482         return VA_STATUS_ERROR_UNKNOWN;
2483
2484     i965_display_attributes_terminate(ctx);
2485
2486     i965_destroy_heap(&i965->buffer_heap, i965_destroy_buffer);
2487     i965_destroy_heap(&i965->image_heap, i965_destroy_image);
2488     i965_destroy_heap(&i965->subpic_heap, i965_destroy_subpic);
2489     i965_destroy_heap(&i965->surface_heap, i965_destroy_surface);
2490     i965_destroy_heap(&i965->context_heap, i965_destroy_context);
2491     i965_destroy_heap(&i965->config_heap, i965_destroy_config);
2492
2493     if (intel_driver_terminate(ctx) == False)
2494         return VA_STATUS_ERROR_UNKNOWN;
2495
2496     free(ctx->pDriverData);
2497     ctx->pDriverData = NULL;
2498
2499     return VA_STATUS_SUCCESS;
2500 }
2501
2502 static VAStatus
2503 i965_BufferInfo(
2504     VADriverContextP ctx,       /* in */
2505     VABufferID buf_id,          /* in */
2506     VABufferType *type,         /* out */
2507     unsigned int *size,         /* out */
2508     unsigned int *num_elements  /* out */
2509 )
2510 {
2511     struct i965_driver_data *i965 = NULL;
2512     struct object_buffer *obj_buffer = NULL;
2513
2514     i965 = i965_driver_data(ctx);
2515     obj_buffer = BUFFER(buf_id);
2516
2517     *type = obj_buffer->type;
2518     *size = obj_buffer->size_element;
2519     *num_elements = obj_buffer->num_elements;
2520
2521     return VA_STATUS_SUCCESS;
2522 }
2523
2524 static VAStatus
2525 i965_LockSurface(
2526     VADriverContextP ctx,           /* in */
2527     VASurfaceID surface,            /* in */
2528     unsigned int *fourcc,           /* out */
2529     unsigned int *luma_stride,      /* out */
2530     unsigned int *chroma_u_stride,  /* out */
2531     unsigned int *chroma_v_stride,  /* out */
2532     unsigned int *luma_offset,      /* out */
2533     unsigned int *chroma_u_offset,  /* out */
2534     unsigned int *chroma_v_offset,  /* out */
2535     unsigned int *buffer_name,      /* out */
2536     void **buffer                   /* out */
2537 )
2538 {
2539     VAStatus vaStatus = VA_STATUS_SUCCESS;
2540     struct i965_driver_data *i965 = i965_driver_data(ctx);
2541     struct object_surface *obj_surface = NULL;
2542     VAImage tmpImage;
2543
2544     assert(fourcc);
2545     assert(luma_stride);
2546     assert(chroma_u_stride);
2547     assert(chroma_v_stride);
2548     assert(luma_offset);
2549     assert(chroma_u_offset);
2550     assert(chroma_v_offset);
2551     assert(buffer_name);
2552     assert(buffer);
2553
2554     tmpImage.image_id = VA_INVALID_ID;
2555
2556     obj_surface = SURFACE(surface);
2557     if (obj_surface == NULL) {
2558         // Surface is absent.
2559         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2560         goto error;
2561     }
2562
2563     // Lock functionality is absent now.
2564     if (obj_surface->locked_image_id != VA_INVALID_ID) {
2565         // Surface is locked already.
2566         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2567         goto error;
2568     }
2569
2570     vaStatus = i965_DeriveImage(
2571         ctx,
2572         surface,
2573         &tmpImage);
2574     if (vaStatus != VA_STATUS_SUCCESS) {
2575         goto error;
2576     }
2577
2578     obj_surface->locked_image_id = tmpImage.image_id;
2579
2580     vaStatus = i965_MapBuffer(
2581         ctx,
2582         tmpImage.buf,
2583         buffer);
2584     if (vaStatus != VA_STATUS_SUCCESS) {
2585         goto error;
2586     }
2587
2588     *fourcc = tmpImage.format.fourcc;
2589     *luma_offset = tmpImage.offsets[0];
2590     *luma_stride = tmpImage.pitches[0];
2591     *chroma_u_offset = tmpImage.offsets[1];
2592     *chroma_u_stride = tmpImage.pitches[1];
2593     *chroma_v_offset = tmpImage.offsets[2];
2594     *chroma_v_stride = tmpImage.pitches[2];
2595     *buffer_name = tmpImage.buf;
2596
2597 error:
2598     if (vaStatus != VA_STATUS_SUCCESS) {
2599         buffer = NULL;
2600     }
2601
2602     return vaStatus;
2603 }
2604
2605 static VAStatus
2606 i965_UnlockSurface(
2607     VADriverContextP ctx,   /* in */
2608     VASurfaceID surface     /* in */
2609 )
2610 {
2611     VAStatus vaStatus = VA_STATUS_SUCCESS;
2612     struct i965_driver_data *i965 = i965_driver_data(ctx);
2613     struct object_image *locked_img = NULL;
2614     struct object_surface *obj_surface = NULL;
2615
2616     obj_surface = SURFACE(surface);
2617
2618     if (obj_surface == NULL) {
2619         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;   // Surface is absent
2620         return vaStatus;
2621     }
2622     if (obj_surface->locked_image_id == VA_INVALID_ID) {
2623         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;   // Surface is not locked
2624         return vaStatus;
2625     }
2626
2627     locked_img = IMAGE(obj_surface->locked_image_id);
2628     if (locked_img == NULL || (locked_img->image.image_id == VA_INVALID_ID)) {
2629         // Work image was deallocated before i965_UnlockSurface()
2630         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2631         goto error;
2632     }
2633
2634     vaStatus = i965_UnmapBuffer(
2635         ctx,
2636         locked_img->image.buf);
2637     if (vaStatus != VA_STATUS_SUCCESS) {
2638         goto error;
2639     }
2640
2641     vaStatus = i965_DestroyImage(
2642         ctx,
2643         locked_img->image.image_id);
2644     if (vaStatus != VA_STATUS_SUCCESS) {
2645         goto error;
2646     }
2647
2648     locked_img->image.image_id = VA_INVALID_ID;
2649
2650  error:
2651     obj_surface->locked_image_id = VA_INVALID_ID;
2652
2653     return vaStatus;
2654 }
2655
2656 VAStatus DLL_EXPORT
2657 VA_DRIVER_INIT_FUNC(VADriverContextP ctx);
2658
2659 VAStatus 
2660 VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
2661 {
2662     struct VADriverVTable * const vtable = ctx->vtable;
2663     struct i965_driver_data *i965;
2664     int result;
2665
2666     ctx->version_major = VA_MAJOR_VERSION;
2667     ctx->version_minor = VA_MINOR_VERSION;
2668     ctx->max_profiles = I965_MAX_PROFILES;
2669     ctx->max_entrypoints = I965_MAX_ENTRYPOINTS;
2670     ctx->max_attributes = I965_MAX_CONFIG_ATTRIBUTES;
2671     ctx->max_image_formats = I965_MAX_IMAGE_FORMATS;
2672     ctx->max_subpic_formats = I965_MAX_SUBPIC_FORMATS;
2673     ctx->max_display_attributes = 1 + ARRAY_ELEMS(i965_display_attributes);
2674
2675     vtable->vaTerminate = i965_Terminate;
2676     vtable->vaQueryConfigEntrypoints = i965_QueryConfigEntrypoints;
2677     vtable->vaQueryConfigProfiles = i965_QueryConfigProfiles;
2678     vtable->vaQueryConfigEntrypoints = i965_QueryConfigEntrypoints;
2679     vtable->vaQueryConfigAttributes = i965_QueryConfigAttributes;
2680     vtable->vaCreateConfig = i965_CreateConfig;
2681     vtable->vaDestroyConfig = i965_DestroyConfig;
2682     vtable->vaGetConfigAttributes = i965_GetConfigAttributes;
2683     vtable->vaCreateSurfaces = i965_CreateSurfaces;
2684     vtable->vaDestroySurfaces = i965_DestroySurfaces;
2685     vtable->vaCreateContext = i965_CreateContext;
2686     vtable->vaDestroyContext = i965_DestroyContext;
2687     vtable->vaCreateBuffer = i965_CreateBuffer;
2688     vtable->vaBufferSetNumElements = i965_BufferSetNumElements;
2689     vtable->vaMapBuffer = i965_MapBuffer;
2690     vtable->vaUnmapBuffer = i965_UnmapBuffer;
2691     vtable->vaDestroyBuffer = i965_DestroyBuffer;
2692     vtable->vaBeginPicture = i965_BeginPicture;
2693     vtable->vaRenderPicture = i965_RenderPicture;
2694     vtable->vaEndPicture = i965_EndPicture;
2695     vtable->vaSyncSurface = i965_SyncSurface;
2696     vtable->vaQuerySurfaceStatus = i965_QuerySurfaceStatus;
2697     vtable->vaPutSurface = i965_PutSurface;
2698     vtable->vaQueryImageFormats = i965_QueryImageFormats;
2699     vtable->vaCreateImage = i965_CreateImage;
2700     vtable->vaDeriveImage = i965_DeriveImage;
2701     vtable->vaDestroyImage = i965_DestroyImage;
2702     vtable->vaSetImagePalette = i965_SetImagePalette;
2703     vtable->vaGetImage = i965_GetImage;
2704     vtable->vaPutImage = i965_PutImage;
2705     vtable->vaQuerySubpictureFormats = i965_QuerySubpictureFormats;
2706     vtable->vaCreateSubpicture = i965_CreateSubpicture;
2707     vtable->vaDestroySubpicture = i965_DestroySubpicture;
2708     vtable->vaSetSubpictureImage = i965_SetSubpictureImage;
2709     vtable->vaSetSubpictureChromakey = i965_SetSubpictureChromakey;
2710     vtable->vaSetSubpictureGlobalAlpha = i965_SetSubpictureGlobalAlpha;
2711     vtable->vaAssociateSubpicture = i965_AssociateSubpicture;
2712     vtable->vaDeassociateSubpicture = i965_DeassociateSubpicture;
2713     vtable->vaQueryDisplayAttributes = i965_QueryDisplayAttributes;
2714     vtable->vaGetDisplayAttributes = i965_GetDisplayAttributes;
2715     vtable->vaSetDisplayAttributes = i965_SetDisplayAttributes;
2716     vtable->vaBufferInfo = i965_BufferInfo;
2717     vtable->vaLockSurface = i965_LockSurface;
2718     vtable->vaUnlockSurface = i965_UnlockSurface;
2719     //    vtable->vaDbgCopySurfaceToBuffer = i965_DbgCopySurfaceToBuffer;
2720
2721     i965 = (struct i965_driver_data *)calloc(1, sizeof(*i965));
2722     assert(i965);
2723     ctx->pDriverData = (void *)i965;
2724
2725     result = object_heap_init(&i965->config_heap, 
2726                               sizeof(struct object_config), 
2727                               CONFIG_ID_OFFSET);
2728     assert(result == 0);
2729
2730     result = object_heap_init(&i965->context_heap, 
2731                               sizeof(struct object_context), 
2732                               CONTEXT_ID_OFFSET);
2733     assert(result == 0);
2734
2735     result = object_heap_init(&i965->surface_heap, 
2736                               sizeof(struct object_surface), 
2737                               SURFACE_ID_OFFSET);
2738     assert(result == 0);
2739
2740     result = object_heap_init(&i965->buffer_heap, 
2741                               sizeof(struct object_buffer), 
2742                               BUFFER_ID_OFFSET);
2743     assert(result == 0);
2744
2745     result = object_heap_init(&i965->image_heap, 
2746                               sizeof(struct object_image), 
2747                               IMAGE_ID_OFFSET);
2748     assert(result == 0);
2749
2750     result = object_heap_init(&i965->subpic_heap, 
2751                               sizeof(struct object_subpic), 
2752                               SUBPIC_ID_OFFSET);
2753     assert(result == 0);
2754
2755     sprintf(i965->va_vendor, "%s %s driver - %d.%d.%d",
2756             INTEL_STR_DRIVER_VENDOR,
2757             INTEL_STR_DRIVER_NAME,
2758             INTEL_DRIVER_MAJOR_VERSION,
2759             INTEL_DRIVER_MINOR_VERSION,
2760             INTEL_DRIVER_MICRO_VERSION);
2761
2762     if (INTEL_DRIVER_PRE_VERSION > 0) {
2763         const int len = strlen(i965->va_vendor);
2764         sprintf(&i965->va_vendor[len], ".pre%d", INTEL_DRIVER_PRE_VERSION);
2765     }
2766     ctx->str_vendor = i965->va_vendor;
2767
2768     return i965_Init(ctx);
2769 }