OSDN Git Service

Add NV12 image format.
[android-x86/hardware-intel-common-libva.git] / i965_drv_video / 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 <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33
34 #include "va/x11/va_dricommon.h"
35
36 #include "intel_driver.h"
37 #include "intel_memman.h"
38 #include "intel_batchbuffer.h"
39
40 #include "i965_media.h"
41 #include "i965_drv_video.h"
42 #include "i965_defines.h"
43
44 #define CONFIG_ID_OFFSET                0x01000000
45 #define CONTEXT_ID_OFFSET               0x02000000
46 #define SURFACE_ID_OFFSET               0x04000000
47 #define BUFFER_ID_OFFSET                0x08000000
48 #define IMAGE_ID_OFFSET                 0x0a000000
49 #define SUBPIC_ID_OFFSET                0x10000000
50
51 enum {
52     I965_SURFACETYPE_RGBA = 1,
53     I965_SURFACETYPE_YUV,
54     I965_SURFACETYPE_INDEXED
55 };
56
57 /* List of supported image formats */
58 typedef struct {
59     unsigned int        type;
60     VAImageFormat       va_format;
61 } i965_image_format_map_t;
62
63 static const i965_image_format_map_t
64 i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
65     { I965_SURFACETYPE_YUV,
66       { VA_FOURCC('Y','V','1','2'), VA_LSB_FIRST, 12, } },
67     { I965_SURFACETYPE_YUV,
68       { VA_FOURCC('I','4','2','0'), VA_LSB_FIRST, 12, } },
69     { I965_SURFACETYPE_YUV,
70       { VA_FOURCC('N','V','1','2'), VA_LSB_FIRST, 12, } },
71 };
72
73 /* List of supported subpicture formats */
74 typedef struct {
75     unsigned int        type;
76     unsigned int        format;
77     VAImageFormat       va_format;
78     unsigned int        va_flags;
79 } i965_subpic_format_map_t;
80
81 static const i965_subpic_format_map_t
82 i965_subpic_formats_map[I965_MAX_SUBPIC_FORMATS + 1] = {
83     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P4A4_UNORM,
84       { VA_FOURCC('I','A','4','4'), VA_MSB_FIRST, 8, },
85       0 },
86     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM,
87       { VA_FOURCC('A','I','4','4'), VA_MSB_FIRST, 8, },
88       0 },
89     { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM,
90       { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32,
91         32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
92       0 },
93     { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM,
94       { VA_FOURCC('R','G','B','A'), VA_LSB_FIRST, 32,
95         32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
96       0 },
97 };
98
99 static const i965_subpic_format_map_t *
100 get_subpic_format(const VAImageFormat *va_format)
101 {
102     unsigned int i;
103     for (i = 0; i965_subpic_formats_map[i].type != 0; i++) {
104         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[i];
105         if (m->va_format.fourcc == va_format->fourcc &&
106             (m->type == I965_SURFACETYPE_RGBA ?
107              (m->va_format.byte_order == va_format->byte_order &&
108               m->va_format.red_mask   == va_format->red_mask   &&
109               m->va_format.green_mask == va_format->green_mask &&
110               m->va_format.blue_mask  == va_format->blue_mask  &&
111               m->va_format.alpha_mask == va_format->alpha_mask) : 1))
112             return m;
113     }
114     return NULL;
115 }
116
117 VAStatus 
118 i965_QueryConfigProfiles(VADriverContextP ctx,
119                          VAProfile *profile_list,       /* out */
120                          int *num_profiles)             /* out */
121 {
122     int i = 0;
123
124     profile_list[i++] = VAProfileMPEG2Simple;
125     profile_list[i++] = VAProfileMPEG2Main;
126     profile_list[i++] = VAProfileH264Baseline;
127     profile_list[i++] = VAProfileH264Main;
128     profile_list[i++] = VAProfileH264High;
129
130     /* If the assert fails then I965_MAX_PROFILES needs to be bigger */
131     assert(i <= I965_MAX_PROFILES);
132     *num_profiles = i;
133
134     return VA_STATUS_SUCCESS;
135 }
136
137 VAStatus 
138 i965_QueryConfigEntrypoints(VADriverContextP ctx,
139                             VAProfile profile,
140                             VAEntrypoint *entrypoint_list,      /* out */
141                             int *num_entrypoints)               /* out */
142 {
143     VAStatus vaStatus = VA_STATUS_SUCCESS;
144
145     switch (profile) {
146     case VAProfileMPEG2Simple:
147     case VAProfileMPEG2Main:
148         *num_entrypoints = 1;
149         entrypoint_list[0] = VAEntrypointVLD;
150         break;
151
152     case VAProfileH264Baseline:
153     case VAProfileH264Main:
154     case VAProfileH264High:
155         *num_entrypoints = 1;
156         entrypoint_list[0] = VAEntrypointVLD;
157         break;
158
159     default:
160         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
161         *num_entrypoints = 0;
162         break;
163     }
164
165     /* If the assert fails then I965_MAX_ENTRYPOINTS needs to be bigger */
166     assert(*num_entrypoints <= I965_MAX_ENTRYPOINTS);
167
168     return vaStatus;
169 }
170
171 VAStatus 
172 i965_GetConfigAttributes(VADriverContextP ctx,
173                          VAProfile profile,
174                          VAEntrypoint entrypoint,
175                          VAConfigAttrib *attrib_list,  /* in/out */
176                          int num_attribs)
177 {
178     int i;
179
180     /* Other attributes don't seem to be defined */
181     /* What to do if we don't know the attribute? */
182     for (i = 0; i < num_attribs; i++) {
183         switch (attrib_list[i].type) {
184         case VAConfigAttribRTFormat:
185             attrib_list[i].value = VA_RT_FORMAT_YUV420;
186             break;
187
188         default:
189             /* Do nothing */
190             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
191             break;
192         }
193     }
194
195     return VA_STATUS_SUCCESS;
196 }
197
198 static void 
199 i965_destroy_config(struct object_heap *heap, struct object_base *obj)
200 {
201     object_heap_free(heap, obj);
202 }
203
204 static VAStatus 
205 i965_update_attribute(struct object_config *obj_config, VAConfigAttrib *attrib)
206 {
207     int i;
208
209     /* Check existing attrbiutes */
210     for (i = 0; obj_config->num_attribs < i; i++) {
211         if (obj_config->attrib_list[i].type == attrib->type) {
212             /* Update existing attribute */
213             obj_config->attrib_list[i].value = attrib->value;
214             return VA_STATUS_SUCCESS;
215         }
216     }
217
218     if (obj_config->num_attribs < I965_MAX_CONFIG_ATTRIBUTES) {
219         i = obj_config->num_attribs;
220         obj_config->attrib_list[i].type = attrib->type;
221         obj_config->attrib_list[i].value = attrib->value;
222         obj_config->num_attribs++;
223         return VA_STATUS_SUCCESS;
224     }
225
226     return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
227 }
228
229 VAStatus 
230 i965_CreateConfig(VADriverContextP ctx,
231                   VAProfile profile,
232                   VAEntrypoint entrypoint,
233                   VAConfigAttrib *attrib_list,
234                   int num_attribs,
235                   VAConfigID *config_id)                /* out */
236 {
237     struct i965_driver_data *i965 = i965_driver_data(ctx);
238     struct object_config *obj_config;
239     int configID;
240     int i;
241     VAStatus vaStatus;
242
243     /* Validate profile & entrypoint */
244     switch (profile) {
245     case VAProfileMPEG2Simple:
246     case VAProfileMPEG2Main:
247         if (VAEntrypointVLD == entrypoint) {
248             vaStatus = VA_STATUS_SUCCESS;
249         } else {
250             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
251         }
252         break;
253
254     case VAProfileH264Baseline:
255     case VAProfileH264Main:
256     case VAProfileH264High:
257         if (VAEntrypointVLD == entrypoint) {
258             vaStatus = VA_STATUS_SUCCESS;
259         } else {
260             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
261         }
262
263         break;
264
265     default:
266         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
267         break;
268     }
269
270     if (VA_STATUS_SUCCESS != vaStatus) {
271         return vaStatus;
272     }
273
274     configID = NEW_CONFIG_ID();
275     obj_config = CONFIG(configID);
276
277     if (NULL == obj_config) {
278         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
279         return vaStatus;
280     }
281
282     obj_config->profile = profile;
283     obj_config->entrypoint = entrypoint;
284     obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
285     obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
286     obj_config->num_attribs = 1;
287
288     for(i = 0; i < num_attribs; i++) {
289         vaStatus = i965_update_attribute(obj_config, &(attrib_list[i]));
290
291         if (VA_STATUS_SUCCESS != vaStatus) {
292             break;
293         }
294     }
295
296     /* Error recovery */
297     if (VA_STATUS_SUCCESS != vaStatus) {
298         i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
299     } else {
300         *config_id = configID;
301     }
302
303     return vaStatus;
304 }
305
306 VAStatus 
307 i965_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
308 {
309     struct i965_driver_data *i965 = i965_driver_data(ctx);
310     struct object_config *obj_config = CONFIG(config_id);
311     VAStatus vaStatus;
312
313     if (NULL == obj_config) {
314         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
315         return vaStatus;
316     }
317
318     i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
319     return VA_STATUS_SUCCESS;
320 }
321
322 VAStatus i965_QueryConfigAttributes(VADriverContextP ctx,
323                                     VAConfigID config_id,
324                                     VAProfile *profile,                 /* out */
325                                     VAEntrypoint *entrypoint,           /* out */
326                                     VAConfigAttrib *attrib_list,        /* out */
327                                     int *num_attribs)                   /* out */
328 {
329     struct i965_driver_data *i965 = i965_driver_data(ctx);
330     struct object_config *obj_config = CONFIG(config_id);
331     VAStatus vaStatus = VA_STATUS_SUCCESS;
332     int i;
333
334     assert(obj_config);
335     *profile = obj_config->profile;
336     *entrypoint = obj_config->entrypoint;
337     *num_attribs = obj_config->num_attribs;
338
339     for(i = 0; i < obj_config->num_attribs; i++) {
340         attrib_list[i] = obj_config->attrib_list[i];
341     }
342
343     return vaStatus;
344 }
345
346 static void 
347 i965_destroy_surface(struct object_heap *heap, struct object_base *obj)
348 {
349     struct object_surface *obj_surface = (struct object_surface *)obj;
350
351     dri_bo_unreference(obj_surface->bo);
352     obj_surface->bo = NULL;
353
354     if (obj_surface->free_private_data != NULL) {
355         obj_surface->free_private_data(&obj_surface->private_data);
356         obj_surface->private_data = NULL;
357     }
358
359     object_heap_free(heap, obj);
360 }
361
362 VAStatus 
363 i965_CreateSurfaces(VADriverContextP ctx,
364                     int width,
365                     int height,
366                     int format,
367                     int num_surfaces,
368                     VASurfaceID *surfaces)      /* out */
369 {
370     struct i965_driver_data *i965 = i965_driver_data(ctx);
371     int i;
372     VAStatus vaStatus = VA_STATUS_SUCCESS;
373
374     /* We only support one format */
375     if (VA_RT_FORMAT_YUV420 != format) {
376         return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
377     }
378
379     for (i = 0; i < num_surfaces; i++) {
380         int surfaceID = NEW_SURFACE_ID();
381         struct object_surface *obj_surface = SURFACE(surfaceID);
382
383         if (NULL == obj_surface) {
384             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
385             break;
386         }
387
388         surfaces[i] = surfaceID;
389         obj_surface->status = VASurfaceReady;
390         obj_surface->subpic = VA_INVALID_ID;
391         obj_surface->orig_width = width;
392         obj_surface->orig_height = height;
393         obj_surface->width = ALIGN(obj_surface->orig_width, 16);
394         obj_surface->height = ALIGN(obj_surface->orig_height, 16);
395         obj_surface->size = SIZE_YUV420(obj_surface->width, obj_surface->height);
396         obj_surface->flags = SURFACE_REFERENCED;
397         obj_surface->bo = NULL;
398         obj_surface->private_data = NULL;
399         obj_surface->free_private_data = NULL;
400     }
401
402     /* Error recovery */
403     if (VA_STATUS_SUCCESS != vaStatus) {
404         /* surfaces[i-1] was the last successful allocation */
405         for (; i--; ) {
406             struct object_surface *obj_surface = SURFACE(surfaces[i]);
407
408             surfaces[i] = VA_INVALID_SURFACE;
409             assert(obj_surface);
410             i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
411         }
412     }
413
414     return vaStatus;
415 }
416
417 VAStatus 
418 i965_DestroySurfaces(VADriverContextP ctx,
419                      VASurfaceID *surface_list,
420                      int num_surfaces)
421 {
422     struct i965_driver_data *i965 = i965_driver_data(ctx);
423     int i;
424
425     for (i = num_surfaces; i--; ) {
426         struct object_surface *obj_surface = SURFACE(surface_list[i]);
427
428         assert(obj_surface);
429         i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
430     }
431
432     return VA_STATUS_SUCCESS;
433 }
434
435 VAStatus 
436 i965_QueryImageFormats(VADriverContextP ctx,
437                        VAImageFormat *format_list,      /* out */
438                        int *num_formats)                /* out */
439 {
440     int n;
441
442     for (n = 0; i965_image_formats_map[n].va_format.fourcc != 0; n++) {
443         const i965_image_format_map_t * const m = &i965_image_formats_map[n];
444         if (format_list)
445             format_list[n] = m->va_format;
446     }
447
448     if (num_formats)
449         *num_formats = n;
450
451     return VA_STATUS_SUCCESS;
452 }
453
454 VAStatus 
455 i965_PutImage(VADriverContextP ctx,
456               VASurfaceID surface,
457               VAImageID image,
458               int src_x,
459               int src_y,
460               unsigned int src_width,
461               unsigned int src_height,
462               int dest_x,
463               int dest_y,
464               unsigned int dest_width,
465               unsigned int dest_height)
466 {
467     return VA_STATUS_SUCCESS;
468 }
469
470 VAStatus 
471 i965_QuerySubpictureFormats(VADriverContextP ctx,
472                             VAImageFormat *format_list,         /* out */
473                             unsigned int *flags,                /* out */
474                             unsigned int *num_formats)          /* out */
475 {
476     int n;
477
478     for (n = 0; i965_subpic_formats_map[n].va_format.fourcc != 0; n++) {
479         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[n];
480         if (format_list)
481             format_list[n] = m->va_format;
482         if (flags)
483             flags[n] = m->va_flags;
484     }
485
486     if (num_formats)
487         *num_formats = n;
488
489     return VA_STATUS_SUCCESS;
490 }
491
492 static void 
493 i965_destroy_subpic(struct object_heap *heap, struct object_base *obj)
494 {
495 //    struct object_subpic *obj_subpic = (struct object_subpic *)obj;
496
497     object_heap_free(heap, obj);
498 }
499
500 VAStatus 
501 i965_CreateSubpicture(VADriverContextP ctx,
502                       VAImageID image,
503                       VASubpictureID *subpicture)         /* out */
504 {
505     struct i965_driver_data *i965 = i965_driver_data(ctx);
506     VASubpictureID subpicID = NEW_SUBPIC_ID()
507         
508         struct object_subpic *obj_subpic = SUBPIC(subpicID);
509     if (!obj_subpic)
510         return VA_STATUS_ERROR_ALLOCATION_FAILED;
511
512     struct object_image *obj_image = IMAGE(image);
513     if (!obj_image)
514         return VA_STATUS_ERROR_INVALID_IMAGE;
515
516     const i965_subpic_format_map_t * const m = get_subpic_format(&obj_image->image.format);
517     if (!m)
518         return VA_STATUS_ERROR_UNKNOWN; /* XXX: VA_STATUS_ERROR_UNSUPPORTED_FORMAT? */
519
520     *subpicture = subpicID;
521     obj_subpic->image  = image;
522     obj_subpic->format = m->format;
523     obj_subpic->width  = obj_image->image.width;
524     obj_subpic->height = obj_image->image.height;
525     obj_subpic->pitch  = obj_image->image.pitches[0];
526     obj_subpic->bo     = obj_image->bo;
527     return VA_STATUS_SUCCESS;
528 }
529
530 VAStatus 
531 i965_DestroySubpicture(VADriverContextP ctx,
532                        VASubpictureID subpicture)
533 {
534         
535     struct i965_driver_data *i965 = i965_driver_data(ctx);
536     struct object_subpic *obj_subpic = SUBPIC(subpicture);
537     i965_destroy_subpic(&i965->subpic_heap, (struct object_base *)obj_subpic);
538     return VA_STATUS_SUCCESS;
539 }
540
541 VAStatus 
542 i965_SetSubpictureImage(VADriverContextP ctx,
543                         VASubpictureID subpicture,
544                         VAImageID image)
545 {
546     /* TODO */
547     return VA_STATUS_ERROR_UNIMPLEMENTED;
548 }
549
550 VAStatus 
551 i965_SetSubpictureChromakey(VADriverContextP ctx,
552                             VASubpictureID subpicture,
553                             unsigned int chromakey_min,
554                             unsigned int chromakey_max,
555                             unsigned int chromakey_mask)
556 {
557     /* TODO */
558     return VA_STATUS_ERROR_UNIMPLEMENTED;
559 }
560
561 VAStatus 
562 i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
563                               VASubpictureID subpicture,
564                               float global_alpha)
565 {
566     /* TODO */
567     return VA_STATUS_ERROR_UNIMPLEMENTED;
568 }
569
570 VAStatus 
571 i965_AssociateSubpicture(VADriverContextP ctx,
572                          VASubpictureID subpicture,
573                          VASurfaceID *target_surfaces,
574                          int num_surfaces,
575                          short src_x, /* upper left offset in subpicture */
576                          short src_y,
577                          unsigned short src_width,
578                          unsigned short src_height,
579                          short dest_x, /* upper left offset in surface */
580                          short dest_y,
581                          unsigned short dest_width,
582                          unsigned short dest_height,
583                          /*
584                           * whether to enable chroma-keying or global-alpha
585                           * see VA_SUBPICTURE_XXX values
586                           */
587                          unsigned int flags)
588 {
589     struct i965_driver_data *i965 = i965_driver_data(ctx);
590     struct object_subpic *obj_subpic = SUBPIC(subpicture);
591     int i;
592
593     obj_subpic->src_rect.x      = src_x;
594     obj_subpic->src_rect.y      = src_y;
595     obj_subpic->src_rect.width  = src_width;
596     obj_subpic->src_rect.height = src_height;
597     obj_subpic->dst_rect.x      = dest_x;
598     obj_subpic->dst_rect.y      = dest_y;
599     obj_subpic->dst_rect.width  = dest_width;
600     obj_subpic->dst_rect.height = dest_height;
601
602     for (i = 0; i < num_surfaces; i++) {
603         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
604         if (!obj_surface)
605             return VA_STATUS_ERROR_INVALID_SURFACE;
606         obj_surface->subpic = subpicture;
607     }
608     return VA_STATUS_SUCCESS;
609 }
610
611
612 VAStatus 
613 i965_DeassociateSubpicture(VADriverContextP ctx,
614                            VASubpictureID subpicture,
615                            VASurfaceID *target_surfaces,
616                            int num_surfaces)
617 {
618     struct i965_driver_data *i965 = i965_driver_data(ctx);
619     int i;
620
621     for (i = 0; i < num_surfaces; i++) {
622         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
623         if (!obj_surface)
624             return VA_STATUS_ERROR_INVALID_SURFACE;
625         if (obj_surface->subpic == subpicture)
626             obj_surface->subpic = VA_INVALID_ID;
627     }
628     return VA_STATUS_SUCCESS;
629 }
630
631 static void
632 i965_reference_buffer_store(struct buffer_store **ptr, 
633                             struct buffer_store *buffer_store)
634 {
635     assert(*ptr == NULL);
636
637     if (buffer_store) {
638         buffer_store->ref_count++;
639         *ptr = buffer_store;
640     }
641 }
642
643 static void 
644 i965_release_buffer_store(struct buffer_store **ptr)
645 {
646     struct buffer_store *buffer_store = *ptr;
647
648     if (buffer_store == NULL)
649         return;
650
651     assert(buffer_store->bo || buffer_store->buffer);
652     assert(!(buffer_store->bo && buffer_store->buffer));
653     buffer_store->ref_count--;
654     
655     if (buffer_store->ref_count == 0) {
656         dri_bo_unreference(buffer_store->bo);
657         free(buffer_store->buffer);
658         buffer_store->bo = NULL;
659         buffer_store->buffer = NULL;
660         free(buffer_store);
661     }
662
663     *ptr = NULL;
664 }
665
666 static void 
667 i965_destroy_context(struct object_heap *heap, struct object_base *obj)
668 {
669     struct object_context *obj_context = (struct object_context *)obj;
670     int i;
671
672     assert(obj_context->decode_state.num_slice_params <= obj_context->decode_state.max_slice_params);
673     assert(obj_context->decode_state.num_slice_datas <= obj_context->decode_state.max_slice_datas);
674
675     i965_release_buffer_store(&obj_context->decode_state.pic_param);
676     i965_release_buffer_store(&obj_context->decode_state.iq_matrix);
677     i965_release_buffer_store(&obj_context->decode_state.bit_plane);
678
679     for (i = 0; i < obj_context->decode_state.num_slice_params; i++)
680         i965_release_buffer_store(&obj_context->decode_state.slice_params[i]);
681
682     for (i = 0; i < obj_context->decode_state.num_slice_datas; i++)
683         i965_release_buffer_store(&obj_context->decode_state.slice_datas[i]);
684
685     free(obj_context->decode_state.slice_params);
686     free(obj_context->decode_state.slice_datas);
687     free(obj_context->render_targets);
688     object_heap_free(heap, obj);
689 }
690
691 VAStatus 
692 i965_CreateContext(VADriverContextP ctx,
693                    VAConfigID config_id,
694                    int picture_width,
695                    int picture_height,
696                    int flag,
697                    VASurfaceID *render_targets,
698                    int num_render_targets,
699                    VAContextID *context)                /* out */
700 {
701     struct i965_driver_data *i965 = i965_driver_data(ctx);
702     struct i965_render_state *render_state = &i965->render_state;
703     struct object_config *obj_config = CONFIG(config_id);
704     struct object_context *obj_context = NULL;
705     VAStatus vaStatus = VA_STATUS_SUCCESS;
706     int contextID;
707     int i;
708
709     if (NULL == obj_config) {
710         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
711         return vaStatus;
712     }
713
714     /* Validate flag */
715     /* Validate picture dimensions */
716     contextID = NEW_CONTEXT_ID();
717     obj_context = CONTEXT(contextID);
718
719     if (NULL == obj_context) {
720         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
721         return vaStatus;
722     }
723
724     switch (obj_config->profile) {
725     case VAProfileH264Baseline:
726     case VAProfileH264Main:
727     case VAProfileH264High:
728         render_state->interleaved_uv = 1;
729         break;
730     default:
731         render_state->interleaved_uv = 0;
732     }
733
734     obj_context->context_id = contextID;
735     *context = contextID;
736     memset(&obj_context->decode_state, 0, sizeof(obj_context->decode_state));
737     obj_context->decode_state.current_render_target = -1;
738     obj_context->decode_state.max_slice_params = NUM_SLICES;
739     obj_context->decode_state.max_slice_datas = NUM_SLICES;
740     obj_context->decode_state.slice_params = calloc(obj_context->decode_state.max_slice_params,
741                                                     sizeof(*obj_context->decode_state.slice_params));
742     obj_context->decode_state.slice_datas = calloc(obj_context->decode_state.max_slice_datas,
743                                                    sizeof(*obj_context->decode_state.slice_datas));
744     obj_context->config_id = config_id;
745     obj_context->picture_width = picture_width;
746     obj_context->picture_height = picture_height;
747     obj_context->num_render_targets = num_render_targets;
748     obj_context->render_targets = 
749         (VASurfaceID *)calloc(num_render_targets, sizeof(VASurfaceID));
750
751     for(i = 0; i < num_render_targets; i++) {
752         if (NULL == SURFACE(render_targets[i])) {
753             vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
754             break;
755         }
756
757         obj_context->render_targets[i] = render_targets[i];
758     }
759
760     obj_context->flags = flag;
761
762     /* Error recovery */
763     if (VA_STATUS_SUCCESS != vaStatus) {
764         i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
765     }
766
767     return vaStatus;
768 }
769
770 VAStatus 
771 i965_DestroyContext(VADriverContextP ctx, VAContextID context)
772 {
773     struct i965_driver_data *i965 = i965_driver_data(ctx);
774     struct object_context *obj_context = CONTEXT(context);
775
776     assert(obj_context);
777     i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
778
779     return VA_STATUS_SUCCESS;
780 }
781
782 static void 
783 i965_destroy_buffer(struct object_heap *heap, struct object_base *obj)
784 {
785     struct object_buffer *obj_buffer = (struct object_buffer *)obj;
786
787     assert(obj_buffer->buffer_store);
788     i965_release_buffer_store(&obj_buffer->buffer_store);
789     object_heap_free(heap, obj);
790 }
791
792 VAStatus 
793 i965_CreateBuffer(VADriverContextP ctx,
794                   VAContextID context,          /* in */
795                   VABufferType type,            /* in */
796                   unsigned int size,            /* in */
797                   unsigned int num_elements,    /* in */
798                   void *data,                   /* in */
799                   VABufferID *buf_id)           /* out */
800 {
801     struct i965_driver_data *i965 = i965_driver_data(ctx);
802     struct object_buffer *obj_buffer = NULL;
803     struct buffer_store *buffer_store = NULL;
804     int bufferID;
805
806     /* Validate type */
807     switch (type) {
808     case VAPictureParameterBufferType:
809     case VAIQMatrixBufferType:
810     case VABitPlaneBufferType:
811     case VASliceGroupMapBufferType:
812     case VASliceParameterBufferType:
813     case VASliceDataBufferType:
814     case VAMacroblockParameterBufferType:
815     case VAResidualDataBufferType:
816     case VADeblockingParameterBufferType:
817     case VAImageBufferType:
818         /* Ok */
819         break;
820
821     default:
822         return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
823     }
824
825     bufferID = NEW_BUFFER_ID();
826     obj_buffer = BUFFER(bufferID);
827
828     if (NULL == obj_buffer) {
829         return VA_STATUS_ERROR_ALLOCATION_FAILED;
830     }
831
832     obj_buffer->max_num_elements = num_elements;
833     obj_buffer->num_elements = num_elements;
834     obj_buffer->size_element = size;
835     obj_buffer->type = type;
836     obj_buffer->buffer_store = NULL;
837     buffer_store = calloc(1, sizeof(struct buffer_store));
838     assert(buffer_store);
839     buffer_store->ref_count = 1;
840
841     if (type == VASliceDataBufferType || type == VAImageBufferType) {
842         buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, 
843                                         "Buffer", 
844                                         size * num_elements, 64);
845         assert(buffer_store->bo);
846
847         if (data)
848             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
849     } else {
850         buffer_store->buffer = malloc(size * num_elements);
851         assert(buffer_store->buffer);
852
853         if (data)
854             memcpy(buffer_store->buffer, data, size * num_elements);
855     }
856
857     buffer_store->num_elements = obj_buffer->num_elements;
858     i965_reference_buffer_store(&obj_buffer->buffer_store, buffer_store);
859     i965_release_buffer_store(&buffer_store);
860     *buf_id = bufferID;
861
862     return VA_STATUS_SUCCESS;
863 }
864
865
866 VAStatus 
867 i965_BufferSetNumElements(VADriverContextP ctx,
868                           VABufferID buf_id,           /* in */
869                           unsigned int num_elements)   /* in */
870 {
871     struct i965_driver_data *i965 = i965_driver_data(ctx);
872     struct object_buffer *obj_buffer = BUFFER(buf_id);
873     VAStatus vaStatus = VA_STATUS_SUCCESS;
874
875     assert(obj_buffer);
876
877     if ((num_elements < 0) || 
878         (num_elements > obj_buffer->max_num_elements)) {
879         vaStatus = VA_STATUS_ERROR_UNKNOWN;
880     } else {
881         obj_buffer->num_elements = num_elements;
882     }
883
884     return vaStatus;
885 }
886
887 VAStatus 
888 i965_MapBuffer(VADriverContextP ctx,
889                VABufferID buf_id,       /* in */
890                void **pbuf)             /* out */
891 {
892     struct i965_driver_data *i965 = i965_driver_data(ctx);
893     struct object_buffer *obj_buffer = BUFFER(buf_id);
894     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
895
896     assert(obj_buffer && obj_buffer->buffer_store);
897     assert(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer);
898     assert(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer));
899
900     if (NULL != obj_buffer->buffer_store->bo) {
901         dri_bo_map(obj_buffer->buffer_store->bo, 1);
902         assert(obj_buffer->buffer_store->bo->virtual);
903         *pbuf = obj_buffer->buffer_store->bo->virtual;
904         vaStatus = VA_STATUS_SUCCESS;
905     } else if (NULL != obj_buffer->buffer_store->buffer) {
906         *pbuf = obj_buffer->buffer_store->buffer;
907         vaStatus = VA_STATUS_SUCCESS;
908     }
909
910     return vaStatus;
911 }
912
913 VAStatus 
914 i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
915 {
916     struct i965_driver_data *i965 = i965_driver_data(ctx);
917     struct object_buffer *obj_buffer = BUFFER(buf_id);
918     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
919
920     assert(obj_buffer && obj_buffer->buffer_store);
921     assert(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer);
922     assert(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer));
923
924     if (NULL != obj_buffer->buffer_store->bo) {
925         dri_bo_unmap(obj_buffer->buffer_store->bo);
926         vaStatus = VA_STATUS_SUCCESS;
927     } else if (NULL != obj_buffer->buffer_store->buffer) {
928         /* Do nothing */
929         vaStatus = VA_STATUS_SUCCESS;
930     }
931
932     return vaStatus;    
933 }
934
935 VAStatus 
936 i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
937 {
938     struct i965_driver_data *i965 = i965_driver_data(ctx);
939     struct object_buffer *obj_buffer = BUFFER(buffer_id);
940
941     assert(obj_buffer);
942     i965_destroy_buffer(&i965->buffer_heap, (struct object_base *)obj_buffer);
943
944     return VA_STATUS_SUCCESS;
945 }
946
947 VAStatus 
948 i965_BeginPicture(VADriverContextP ctx,
949                   VAContextID context,
950                   VASurfaceID render_target)
951 {
952     struct i965_driver_data *i965 = i965_driver_data(ctx); 
953     struct object_context *obj_context = CONTEXT(context);
954     struct object_surface *obj_surface = SURFACE(render_target);
955     struct object_config *obj_config;
956     VAContextID config;
957     VAStatus vaStatus;
958
959     assert(obj_context);
960     assert(obj_surface);
961
962     config = obj_context->config_id;
963     obj_config = CONFIG(config);
964     assert(obj_config);
965
966     switch (obj_config->profile) {
967     case VAProfileMPEG2Simple:
968     case VAProfileMPEG2Main:
969         vaStatus = VA_STATUS_SUCCESS;
970         break;
971
972     case VAProfileH264Baseline:
973     case VAProfileH264Main:
974     case VAProfileH264High:
975         vaStatus = VA_STATUS_SUCCESS;
976         break;
977
978     default:
979         assert(0);
980         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
981         break;
982     }
983
984     obj_context->decode_state.current_render_target = render_target;
985
986     return vaStatus;
987 }
988
989 static VAStatus
990 i965_render_picture_parameter_buffer(VADriverContextP ctx,
991                                      struct object_context *obj_context,
992                                      struct object_buffer *obj_buffer)
993 {
994     assert(obj_buffer->buffer_store->bo == NULL);
995     assert(obj_buffer->buffer_store->buffer);
996     i965_release_buffer_store(&obj_context->decode_state.pic_param);
997     i965_reference_buffer_store(&obj_context->decode_state.pic_param,
998                                 obj_buffer->buffer_store);
999
1000     return VA_STATUS_SUCCESS;
1001 }
1002
1003 static VAStatus
1004 i965_render_iq_matrix_buffer(VADriverContextP ctx,
1005                              struct object_context *obj_context,
1006                              struct object_buffer *obj_buffer)
1007 {
1008     assert(obj_buffer->buffer_store->bo == NULL);
1009     assert(obj_buffer->buffer_store->buffer);
1010     i965_release_buffer_store(&obj_context->decode_state.iq_matrix);
1011     i965_reference_buffer_store(&obj_context->decode_state.iq_matrix,
1012                                 obj_buffer->buffer_store);
1013
1014     return VA_STATUS_SUCCESS;
1015 }
1016
1017 static VAStatus
1018 i965_render_bit_plane_buffer(VADriverContextP ctx,
1019                              struct object_context *obj_context,
1020                              struct object_buffer *obj_buffer)
1021 {
1022     assert(obj_buffer->buffer_store->bo == NULL);
1023     assert(obj_buffer->buffer_store->buffer);
1024     i965_release_buffer_store(&obj_context->decode_state.bit_plane);
1025     i965_reference_buffer_store(&obj_context->decode_state.bit_plane,
1026                                 obj_buffer->buffer_store);
1027     
1028     return VA_STATUS_SUCCESS;
1029 }
1030
1031 static VAStatus
1032 i965_render_slice_parameter_buffer(VADriverContextP ctx,
1033                                    struct object_context *obj_context,
1034                                    struct object_buffer *obj_buffer)
1035 {
1036     assert(obj_buffer->buffer_store->bo == NULL);
1037     assert(obj_buffer->buffer_store->buffer);
1038     
1039     if (obj_context->decode_state.num_slice_params == obj_context->decode_state.max_slice_params) {
1040         obj_context->decode_state.slice_params = realloc(obj_context->decode_state.slice_params,
1041                                                          (obj_context->decode_state.max_slice_params + NUM_SLICES) * sizeof(*obj_context->decode_state.slice_params));
1042         memset(obj_context->decode_state.slice_params + obj_context->decode_state.max_slice_params, 0, NUM_SLICES * sizeof(*obj_context->decode_state.slice_params));
1043         obj_context->decode_state.max_slice_params += NUM_SLICES;
1044     }
1045         
1046     i965_release_buffer_store(&obj_context->decode_state.slice_params[obj_context->decode_state.num_slice_params]);
1047     i965_reference_buffer_store(&obj_context->decode_state.slice_params[obj_context->decode_state.num_slice_params],
1048                                 obj_buffer->buffer_store);
1049     obj_context->decode_state.num_slice_params++;
1050     
1051     return VA_STATUS_SUCCESS;
1052 }
1053
1054 static VAStatus
1055 i965_render_slice_data_buffer(VADriverContextP ctx,
1056                               struct object_context *obj_context,
1057                               struct object_buffer *obj_buffer)
1058 {
1059     assert(obj_buffer->buffer_store->buffer == NULL);
1060     assert(obj_buffer->buffer_store->bo);
1061
1062     if (obj_context->decode_state.num_slice_datas == obj_context->decode_state.max_slice_datas) {
1063         obj_context->decode_state.slice_datas = realloc(obj_context->decode_state.slice_datas,
1064                                                         (obj_context->decode_state.max_slice_datas + NUM_SLICES) * sizeof(*obj_context->decode_state.slice_datas));
1065         memset(obj_context->decode_state.slice_datas + obj_context->decode_state.max_slice_datas, 0, NUM_SLICES * sizeof(*obj_context->decode_state.slice_datas));
1066         obj_context->decode_state.max_slice_datas += NUM_SLICES;
1067     }
1068         
1069     i965_release_buffer_store(&obj_context->decode_state.slice_datas[obj_context->decode_state.num_slice_datas]);
1070     i965_reference_buffer_store(&obj_context->decode_state.slice_datas[obj_context->decode_state.num_slice_datas],
1071                                 obj_buffer->buffer_store);
1072     obj_context->decode_state.num_slice_datas++;
1073     
1074     return VA_STATUS_SUCCESS;
1075 }
1076
1077 VAStatus 
1078 i965_RenderPicture(VADriverContextP ctx,
1079                    VAContextID context,
1080                    VABufferID *buffers,
1081                    int num_buffers)
1082 {
1083     struct i965_driver_data *i965 = i965_driver_data(ctx);
1084     struct object_context *obj_context;
1085     int i;
1086     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1087
1088     obj_context = CONTEXT(context);
1089     assert(obj_context);
1090
1091     for (i = 0; i < num_buffers; i++) {
1092         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
1093         assert(obj_buffer);
1094
1095         switch (obj_buffer->type) {
1096         case VAPictureParameterBufferType:
1097             vaStatus = i965_render_picture_parameter_buffer(ctx, obj_context, obj_buffer);
1098             break;
1099             
1100         case VAIQMatrixBufferType:
1101             vaStatus = i965_render_iq_matrix_buffer(ctx, obj_context, obj_buffer);
1102             break;
1103
1104         case VABitPlaneBufferType:
1105             vaStatus = i965_render_bit_plane_buffer(ctx, obj_context, obj_buffer);
1106             break;
1107
1108         case VASliceParameterBufferType:
1109             vaStatus = i965_render_slice_parameter_buffer(ctx, obj_context, obj_buffer);
1110             break;
1111
1112         case VASliceDataBufferType:
1113             vaStatus = i965_render_slice_data_buffer(ctx, obj_context, obj_buffer);
1114             break;
1115
1116         default:
1117             break;
1118         }
1119     }
1120
1121     return vaStatus;
1122 }
1123
1124 VAStatus 
1125 i965_EndPicture(VADriverContextP ctx, VAContextID context)
1126 {
1127     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1128     struct object_context *obj_context = CONTEXT(context);
1129     struct object_config *obj_config;
1130     VAContextID config;
1131     int i;
1132
1133     assert(obj_context);
1134     assert(obj_context->decode_state.pic_param);
1135     assert(obj_context->decode_state.num_slice_params >= 1);
1136     assert(obj_context->decode_state.num_slice_datas >= 1);
1137     assert(obj_context->decode_state.num_slice_params == obj_context->decode_state.num_slice_datas);
1138
1139     config = obj_context->config_id;
1140     obj_config = CONFIG(config);
1141     assert(obj_config);
1142
1143     i965_media_decode_picture(ctx, obj_config->profile, &obj_context->decode_state);
1144     obj_context->decode_state.current_render_target = -1;
1145     obj_context->decode_state.num_slice_params = 0;
1146     obj_context->decode_state.num_slice_datas = 0;
1147     i965_release_buffer_store(&obj_context->decode_state.pic_param);
1148     i965_release_buffer_store(&obj_context->decode_state.iq_matrix);
1149     i965_release_buffer_store(&obj_context->decode_state.bit_plane);
1150
1151     for (i = 0; i < obj_context->decode_state.num_slice_params; i++) {
1152         i965_release_buffer_store(&obj_context->decode_state.slice_params[i]);
1153         i965_release_buffer_store(&obj_context->decode_state.slice_datas[i]);
1154     }
1155
1156     return VA_STATUS_SUCCESS;
1157 }
1158
1159 VAStatus 
1160 i965_SyncSurface(VADriverContextP ctx,
1161                  VASurfaceID render_target)
1162 {
1163     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1164     struct object_surface *obj_surface = SURFACE(render_target);
1165
1166     assert(obj_surface);
1167
1168     return VA_STATUS_SUCCESS;
1169 }
1170
1171 VAStatus 
1172 i965_QuerySurfaceStatus(VADriverContextP ctx,
1173                         VASurfaceID render_target,
1174                         VASurfaceStatus *status)        /* out */
1175 {
1176     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1177     struct object_surface *obj_surface = SURFACE(render_target);
1178
1179     assert(obj_surface);
1180     *status = obj_surface->status;
1181
1182     return VA_STATUS_SUCCESS;
1183 }
1184
1185
1186 /* 
1187  * Query display attributes 
1188  * The caller must provide a "attr_list" array that can hold at
1189  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1190  * returned in "attr_list" is returned in "num_attributes".
1191  */
1192 VAStatus 
1193 i965_QueryDisplayAttributes(VADriverContextP ctx,
1194                             VADisplayAttribute *attr_list,      /* out */
1195                             int *num_attributes)                /* out */
1196 {
1197     if (num_attributes)
1198         *num_attributes = 0;
1199
1200     return VA_STATUS_SUCCESS;
1201 }
1202
1203 /* 
1204  * Get display attributes 
1205  * This function returns the current attribute values in "attr_list".
1206  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
1207  * from vaQueryDisplayAttributes() can have their values retrieved.  
1208  */
1209 VAStatus 
1210 i965_GetDisplayAttributes(VADriverContextP ctx,
1211                           VADisplayAttribute *attr_list,        /* in/out */
1212                           int num_attributes)
1213 {
1214     /* TODO */
1215     return VA_STATUS_ERROR_UNIMPLEMENTED;
1216 }
1217
1218 /* 
1219  * Set display attributes 
1220  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
1221  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or 
1222  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
1223  */
1224 VAStatus 
1225 i965_SetDisplayAttributes(VADriverContextP ctx,
1226                           VADisplayAttribute *attr_list,
1227                           int num_attributes)
1228 {
1229     /* TODO */
1230     return VA_STATUS_ERROR_UNIMPLEMENTED;
1231 }
1232
1233 VAStatus 
1234 i965_DbgCopySurfaceToBuffer(VADriverContextP ctx,
1235                             VASurfaceID surface,
1236                             void **buffer,              /* out */
1237                             unsigned int *stride)       /* out */
1238 {
1239     /* TODO */
1240     return VA_STATUS_ERROR_UNIMPLEMENTED;
1241 }
1242
1243 static VAStatus 
1244 i965_Init(VADriverContextP ctx)
1245 {
1246     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1247
1248     if (intel_driver_init(ctx) == False)
1249         return VA_STATUS_ERROR_UNKNOWN;
1250
1251     if (!IS_G4X(i965->intel.device_id) &&
1252         !IS_IRONLAKE(i965->intel.device_id))
1253         return VA_STATUS_ERROR_UNKNOWN;
1254
1255     if (i965_media_init(ctx) == False)
1256         return VA_STATUS_ERROR_UNKNOWN;
1257
1258     if (i965_render_init(ctx) == False)
1259         return VA_STATUS_ERROR_UNKNOWN;
1260
1261     return VA_STATUS_SUCCESS;
1262 }
1263
1264 static void
1265 i965_destroy_heap(struct object_heap *heap, 
1266                   void (*func)(struct object_heap *heap, struct object_base *object))
1267 {
1268     struct object_base *object;
1269     object_heap_iterator iter;    
1270
1271     object = object_heap_first(heap, &iter);
1272
1273     while (object) {
1274         if (func)
1275             func(heap, object);
1276
1277         object = object_heap_next(heap, &iter);
1278     }
1279
1280     object_heap_destroy(heap);
1281 }
1282
1283
1284 VAStatus 
1285 i965_DestroyImage(VADriverContextP ctx, VAImageID image);
1286
1287 VAStatus 
1288 i965_CreateImage(VADriverContextP ctx,
1289                  VAImageFormat *format,
1290                  int width,
1291                  int height,
1292                  VAImage *out_image)        /* out */
1293 {
1294     struct i965_driver_data *i965 = i965_driver_data(ctx);
1295     struct object_image *obj_image;
1296     VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED;
1297     VAImageID image_id;
1298     unsigned int width2, height2, size2, size;
1299
1300     out_image->image_id = VA_INVALID_ID;
1301     out_image->buf      = VA_INVALID_ID;
1302
1303     image_id = NEW_IMAGE_ID();
1304     if (image_id == VA_INVALID_ID)
1305         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1306
1307     obj_image = IMAGE(image_id);
1308     if (!obj_image)
1309         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1310     obj_image->bo         = NULL;
1311     obj_image->palette    = NULL;
1312
1313     VAImage * const image = &obj_image->image;
1314     image->image_id       = image_id;
1315     image->buf            = VA_INVALID_ID;
1316
1317     size    = width * height;
1318     width2  = (width  + 1) / 2;
1319     height2 = (height + 1) / 2;
1320     size2   = width2 * height2;
1321
1322     image->num_palette_entries = 0;
1323     image->entry_bytes         = 0;
1324     memset(image->component_order, 0, sizeof(image->component_order));
1325
1326     switch (format->fourcc) {
1327     case VA_FOURCC('I','A','4','4'):
1328     case VA_FOURCC('A','I','4','4'):
1329         image->num_planes = 1;
1330         image->pitches[0] = width;
1331         image->offsets[0] = 0;
1332         image->data_size  = image->offsets[0] + image->pitches[0] * height;
1333         image->num_palette_entries = 16;
1334         image->entry_bytes         = 3;
1335         image->component_order[0]  = 'R';
1336         image->component_order[1]  = 'G';
1337         image->component_order[2]  = 'B';
1338         break;
1339     case VA_FOURCC('A','R','G','B'):
1340     case VA_FOURCC('A','B','G','R'):
1341     case VA_FOURCC('B','G','R','A'):
1342     case VA_FOURCC('R','G','B','A'):
1343         image->num_planes = 1;
1344         image->pitches[0] = width * 4;
1345         image->offsets[0] = 0;
1346         image->data_size  = image->offsets[0] + image->pitches[0] * height;
1347         break;
1348     case VA_FOURCC('Y','V','1','2'):
1349         image->num_planes = 3;
1350         image->pitches[0] = width;
1351         image->offsets[0] = 0;
1352         image->pitches[1] = width2;
1353         image->offsets[1] = size + size2;
1354         image->pitches[2] = width2;
1355         image->offsets[2] = size;
1356         image->data_size  = size + 2 * size2;
1357         break;
1358     case VA_FOURCC('I','4','2','0'):
1359         image->num_planes = 3;
1360         image->pitches[0] = width;
1361         image->offsets[0] = 0;
1362         image->pitches[1] = width2;
1363         image->offsets[1] = size;
1364         image->pitches[2] = width2;
1365         image->offsets[2] = size + size2;
1366         image->data_size  = size + 2 * size2;
1367         break;
1368     case VA_FOURCC('N','V','1','2'):
1369         image->num_planes = 2;
1370         image->pitches[0] = width;
1371         image->offsets[0] = 0;
1372         image->pitches[1] = width;
1373         image->offsets[1] = size;
1374         image->data_size  = size + 2 * size2;
1375         break;
1376     default:
1377         goto error;
1378     }
1379
1380     va_status = i965_CreateBuffer(ctx, 0, VAImageBufferType,
1381                                   image->data_size, 1, NULL, &image->buf);
1382     if (va_status != VA_STATUS_SUCCESS)
1383         goto error;
1384
1385     obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
1386
1387     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
1388         obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
1389         if (!obj_image->palette)
1390             goto error;
1391     }
1392
1393     image->image_id             = image_id;
1394     image->format               = *format;
1395     image->width                = width;
1396     image->height               = height;
1397
1398     *out_image                  = *image;
1399     return VA_STATUS_SUCCESS;
1400
1401 error:
1402     i965_DestroyImage(ctx, image_id);
1403     return va_status;
1404 }
1405
1406 VAStatus i965_DeriveImage(VADriverContextP ctx,
1407                           VASurfaceID surface,
1408                           VAImage *image)        /* out */
1409 {
1410     /* TODO */
1411     return VA_STATUS_ERROR_OPERATION_FAILED;
1412 }
1413
1414 static void 
1415 i965_destroy_image(struct object_heap *heap, struct object_base *obj)
1416 {
1417     object_heap_free(heap, obj);
1418 }
1419
1420
1421 VAStatus 
1422 i965_DestroyImage(VADriverContextP ctx, VAImageID image)
1423 {
1424     struct i965_driver_data *i965 = i965_driver_data(ctx);
1425     struct object_image *obj_image = IMAGE(image); 
1426
1427     if (!obj_image)
1428         return VA_STATUS_SUCCESS;
1429
1430     if (obj_image->image.buf != VA_INVALID_ID) {
1431         i965_DestroyBuffer(ctx, obj_image->image.buf);
1432         obj_image->image.buf = VA_INVALID_ID;
1433     }
1434
1435     if (obj_image->palette) {
1436         free(obj_image->palette);
1437         obj_image->palette = NULL;
1438     }
1439
1440     i965_destroy_image(&i965->image_heap, (struct object_base *)obj_image);
1441         
1442     return VA_STATUS_SUCCESS;
1443 }
1444
1445 /*
1446  * pointer to an array holding the palette data.  The size of the array is
1447  * num_palette_entries * entry_bytes in size.  The order of the components
1448  * in the palette is described by the component_order in VASubpicture struct
1449  */
1450 VAStatus 
1451 i965_SetImagePalette(VADriverContextP ctx,
1452                      VAImageID image,
1453                      unsigned char *palette)
1454 {
1455     struct i965_driver_data *i965 = i965_driver_data(ctx);
1456     unsigned int i;
1457
1458     struct object_image *obj_image = IMAGE(image);
1459     if (!obj_image)
1460         return VA_STATUS_ERROR_INVALID_IMAGE;
1461
1462     if (!obj_image->palette)
1463         return VA_STATUS_ERROR_ALLOCATION_FAILED; /* XXX: unpaletted/error */
1464
1465     for (i = 0; i < obj_image->image.num_palette_entries; i++)
1466         obj_image->palette[i] = (((unsigned int)palette[3*i + 0] << 16) |
1467                                  ((unsigned int)palette[3*i + 1] <<  8) |
1468                                  (unsigned int)palette[3*i + 2]);
1469     return VA_STATUS_SUCCESS;
1470 }
1471
1472 static void
1473 get_image_yv12(struct object_image *obj_image, uint8_t *image_data,
1474                struct object_surface *obj_surface,
1475                const VARectangle *rect)
1476 {
1477     uint8_t *dst[3], *src[3];
1478     int i, x, y, w, h;
1479
1480     if (!obj_surface->bo)
1481         return;
1482
1483     dri_bo_map(obj_surface->bo, 0);
1484
1485     if (!obj_surface->bo->virtual)
1486         return;
1487
1488     x = rect->x;
1489     y = rect->y;
1490     w = rect->width;
1491     h = rect->height;
1492
1493     dst[0] = image_data + obj_image->image.offsets[0];
1494     src[0] = (uint8_t *)obj_surface->bo->virtual;
1495     dst[1] = image_data + obj_image->image.offsets[1];
1496     src[1] = src[0] + obj_surface->width * obj_surface->height;
1497     dst[2] = image_data + obj_image->image.offsets[2];
1498     src[2] = src[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
1499
1500     dst[0] += y * obj_image->image.pitches[0] + x;
1501     src[0] += y * obj_surface->width + x;
1502     for (i = 0; i < h; i++) {
1503         memcpy(dst[0], src[0], w);
1504         dst[0] += obj_image->image.pitches[0];
1505         src[0] += obj_surface->width;
1506     }
1507
1508     x /= 2;
1509     y /= 2;
1510     w /= 2;
1511     h /= 2;
1512
1513     dst[1] += y * obj_image->image.pitches[1] + x;
1514     src[1] += y * obj_surface->width / 2 + x;
1515     for (i = 0; i < h; i++) {
1516         memcpy(dst[1], src[1], w);
1517         dst[1] += obj_image->image.pitches[1];
1518         src[1] += obj_surface->width / 2;
1519     }
1520
1521     dst[2] += y * obj_image->image.pitches[2] + y;
1522     src[2] += y * obj_surface->width / 2 + x;
1523     for (i = 0; i < h; i++) {
1524         memcpy(dst[2], src[2], w);
1525         dst[2] += obj_image->image.pitches[2];
1526         src[2] += obj_surface->width / 2;
1527     }
1528
1529     dri_bo_unmap(obj_surface->bo);
1530 }
1531
1532 static void
1533 get_image_nv12(struct object_image *obj_image, uint8_t *image_data,
1534                struct object_surface *obj_surface,
1535                const VARectangle *rect)
1536 {
1537     uint8_t *dst, *src;
1538     int i, x, y, w, h;
1539
1540     if (!obj_surface->bo)
1541         return;
1542
1543     dri_bo_map(obj_surface->bo, 0);
1544
1545     if (!obj_surface->bo->virtual)
1546         return;
1547
1548     x = rect->x;
1549     y = rect->y;
1550     w = rect->width;
1551     h = rect->height;
1552
1553     dst = image_data + obj_image->image.offsets[0] + y * obj_image->image.pitches[0] + x;
1554     src = (uint8_t *)obj_surface->bo->virtual + y * obj_surface->width + x;
1555     for (i = 0; i < h; i++) {
1556         memcpy(dst, src, w);
1557         dst += obj_image->image.pitches[0];
1558         src += obj_surface->width;
1559     }
1560
1561     x /= 2;
1562     y /= 2;
1563     h /= 2;
1564
1565     dst = image_data + obj_image->image.offsets[1] + y * obj_image->image.pitches[1] + x * 2;
1566     src = (uint8_t *)obj_surface->bo->virtual + obj_surface->width * obj_surface->height + y * obj_surface->width + x * 2;
1567     for (i = 0; i < h; i++) {
1568         memcpy(dst, src, w);
1569         dst += obj_image->image.pitches[1];
1570         src += obj_surface->width;
1571     }
1572
1573     dri_bo_unmap(obj_surface->bo);
1574 }
1575
1576 VAStatus 
1577 i965_GetImage(VADriverContextP ctx,
1578               VASurfaceID surface,
1579               int x,   /* coordinates of the upper left source pixel */
1580               int y,
1581               unsigned int width,      /* width and height of the region */
1582               unsigned int height,
1583               VAImageID image)
1584 {
1585     struct i965_driver_data *i965 = i965_driver_data(ctx);
1586     struct i965_render_state *render_state = &i965->render_state;
1587
1588     struct object_surface *obj_surface = SURFACE(surface);
1589     if (!obj_surface)
1590         return VA_STATUS_ERROR_INVALID_SURFACE;
1591
1592     struct object_image *obj_image = IMAGE(image);
1593     if (!obj_image)
1594         return VA_STATUS_ERROR_INVALID_IMAGE;
1595
1596     if (x < 0 || y < 0)
1597         return VA_STATUS_ERROR_INVALID_PARAMETER;
1598     if (x + width > obj_surface->orig_width ||
1599         y + height > obj_surface->orig_height)
1600         return VA_STATUS_ERROR_INVALID_PARAMETER;
1601     if (x + width > obj_image->image.width ||
1602         y + height > obj_image->image.height)
1603         return VA_STATUS_ERROR_INVALID_PARAMETER;
1604
1605     VAStatus va_status;
1606     void *image_data = NULL;
1607
1608     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
1609     if (va_status != VA_STATUS_SUCCESS)
1610         return va_status;
1611
1612     VARectangle rect;
1613     rect.x = x;
1614     rect.y = y;
1615     rect.width = width;
1616     rect.height = height;
1617
1618     switch (obj_image->image.format.fourcc) {
1619     case VA_FOURCC('Y','V','1','2'):
1620     case VA_FOURCC('I','4','2','0'):
1621         /* I420 is native format for MPEG-2 decoded surfaces */
1622         if (render_state->interleaved_uv)
1623             goto operation_failed;
1624         get_image_yv12(obj_image, image_data, obj_surface, &rect);
1625         break;
1626     case VA_FOURCC('N','V','1','2'):
1627         /* NV12 is native format for H.264 decoded surfaces */
1628         if (!render_state->interleaved_uv)
1629             goto operation_failed;
1630         get_image_nv12(obj_image, image_data, obj_surface, &rect);
1631         break;
1632     default:
1633     operation_failed:
1634         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
1635         break;
1636     }
1637
1638     i965_UnmapBuffer(ctx, obj_image->image.buf);
1639     return va_status;
1640 }
1641
1642 VAStatus 
1643 i965_PutSurface(VADriverContextP ctx,
1644                 VASurfaceID surface,
1645                 Drawable draw, /* X Drawable */
1646                 short srcx,
1647                 short srcy,
1648                 unsigned short srcw,
1649                 unsigned short srch,
1650                 short destx,
1651                 short desty,
1652                 unsigned short destw,
1653                 unsigned short desth,
1654                 VARectangle *cliprects, /* client supplied clip list */
1655                 unsigned int number_cliprects, /* number of clip rects in the clip list */
1656                 unsigned int flags) /* de-interlacing flags */
1657 {
1658     struct i965_driver_data *i965 = i965_driver_data(ctx); 
1659     struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
1660     struct i965_render_state *render_state = &i965->render_state;
1661     struct dri_drawable *dri_drawable;
1662     union dri_buffer *buffer;
1663     struct intel_region *dest_region;
1664     struct object_surface *obj_surface; 
1665     int ret;
1666     uint32_t name;
1667     Bool new_region = False;
1668     /* Currently don't support DRI1 */
1669     if (dri_state->driConnectedFlag != VA_DRI2)
1670         return VA_STATUS_ERROR_UNKNOWN;
1671
1672     /* Some broken sources such as H.264 conformance case FM2_SVA_C
1673      * will get here
1674      */
1675     obj_surface = SURFACE(surface);
1676     if (obj_surface->bo == NULL)
1677         return VA_STATUS_SUCCESS;
1678
1679     dri_drawable = dri_get_drawable(ctx, draw);
1680     assert(dri_drawable);
1681
1682     buffer = dri_get_rendering_buffer(ctx, dri_drawable);
1683     assert(buffer);
1684     
1685     dest_region = render_state->draw_region;
1686
1687     if (dest_region) {
1688         assert(dest_region->bo);
1689         dri_bo_flink(dest_region->bo, &name);
1690         
1691         if (buffer->dri2.name != name) {
1692             new_region = True;
1693             dri_bo_unreference(dest_region->bo);
1694         }
1695     } else {
1696         dest_region = (struct intel_region *)calloc(1, sizeof(*dest_region));
1697         assert(dest_region);
1698         render_state->draw_region = dest_region;
1699         new_region = True;
1700     }
1701
1702     if (new_region) {
1703         dest_region->x = dri_drawable->x;
1704         dest_region->y = dri_drawable->y;
1705         dest_region->width = dri_drawable->width;
1706         dest_region->height = dri_drawable->height;
1707         dest_region->cpp = buffer->dri2.cpp;
1708         dest_region->pitch = buffer->dri2.pitch;
1709
1710         dest_region->bo = intel_bo_gem_create_from_name(i965->intel.bufmgr, "rendering buffer", buffer->dri2.name);
1711         assert(dest_region->bo);
1712
1713         ret = dri_bo_get_tiling(dest_region->bo, &(dest_region->tiling), &(dest_region->swizzle));
1714         assert(ret == 0);
1715     }
1716
1717     i965_render_put_surface(ctx, surface,
1718                             srcx, srcy, srcw, srch,
1719                             destx, desty, destw, desth);
1720
1721     if(obj_surface->subpic != VA_INVALID_ID) {  
1722         i965_render_put_subpic(ctx, surface,
1723                                srcx, srcy, srcw, srch,
1724                                destx, desty, destw, desth);
1725     } 
1726
1727     dri_swap_buffer(ctx, dri_drawable);
1728     obj_surface->flags |= SURFACE_DISPLAYED;
1729
1730     if (!(obj_surface->flags & SURFACE_REFERENCED)) {
1731         dri_bo_unreference(obj_surface->bo);
1732         obj_surface->bo = NULL;
1733         obj_surface->flags = 0;
1734
1735         if (obj_surface->free_private_data)
1736             obj_surface->free_private_data(&obj_surface->private_data);
1737     }
1738
1739     return VA_STATUS_SUCCESS;
1740 }
1741
1742 VAStatus 
1743 i965_Terminate(VADriverContextP ctx)
1744 {
1745     struct i965_driver_data *i965 = i965_driver_data(ctx);
1746
1747     if (i965_render_terminate(ctx) == False)
1748         return VA_STATUS_ERROR_UNKNOWN;
1749
1750     if (i965_media_terminate(ctx) == False)
1751         return VA_STATUS_ERROR_UNKNOWN;
1752
1753     if (intel_driver_terminate(ctx) == False)
1754         return VA_STATUS_ERROR_UNKNOWN;
1755
1756     i965_destroy_heap(&i965->buffer_heap, i965_destroy_buffer);
1757     i965_destroy_heap(&i965->image_heap, i965_destroy_image);
1758     i965_destroy_heap(&i965->subpic_heap, i965_destroy_subpic);
1759     i965_destroy_heap(&i965->surface_heap, i965_destroy_surface);
1760     i965_destroy_heap(&i965->context_heap, i965_destroy_context);
1761     i965_destroy_heap(&i965->config_heap, i965_destroy_config);
1762
1763     free(ctx->pDriverData);
1764     ctx->pDriverData = NULL;
1765
1766     return VA_STATUS_SUCCESS;
1767 }
1768
1769 VAStatus 
1770 __vaDriverInit_0_31(  VADriverContextP ctx )
1771 {
1772     struct i965_driver_data *i965;
1773     int result;
1774
1775     ctx->version_major = VA_MAJOR_VERSION;
1776     ctx->version_minor = VA_MINOR_VERSION;
1777     ctx->max_profiles = I965_MAX_PROFILES;
1778     ctx->max_entrypoints = I965_MAX_ENTRYPOINTS;
1779     ctx->max_attributes = I965_MAX_CONFIG_ATTRIBUTES;
1780     ctx->max_image_formats = I965_MAX_IMAGE_FORMATS;
1781     ctx->max_subpic_formats = I965_MAX_SUBPIC_FORMATS;
1782     ctx->max_display_attributes = I965_MAX_DISPLAY_ATTRIBUTES;
1783     ctx->str_vendor = I965_STR_VENDOR;
1784
1785     ctx->vtable.vaTerminate = i965_Terminate;
1786     ctx->vtable.vaQueryConfigEntrypoints = i965_QueryConfigEntrypoints;
1787     ctx->vtable.vaQueryConfigProfiles = i965_QueryConfigProfiles;
1788     ctx->vtable.vaQueryConfigEntrypoints = i965_QueryConfigEntrypoints;
1789     ctx->vtable.vaQueryConfigAttributes = i965_QueryConfigAttributes;
1790     ctx->vtable.vaCreateConfig = i965_CreateConfig;
1791     ctx->vtable.vaDestroyConfig = i965_DestroyConfig;
1792     ctx->vtable.vaGetConfigAttributes = i965_GetConfigAttributes;
1793     ctx->vtable.vaCreateSurfaces = i965_CreateSurfaces;
1794     ctx->vtable.vaDestroySurfaces = i965_DestroySurfaces;
1795     ctx->vtable.vaCreateContext = i965_CreateContext;
1796     ctx->vtable.vaDestroyContext = i965_DestroyContext;
1797     ctx->vtable.vaCreateBuffer = i965_CreateBuffer;
1798     ctx->vtable.vaBufferSetNumElements = i965_BufferSetNumElements;
1799     ctx->vtable.vaMapBuffer = i965_MapBuffer;
1800     ctx->vtable.vaUnmapBuffer = i965_UnmapBuffer;
1801     ctx->vtable.vaDestroyBuffer = i965_DestroyBuffer;
1802     ctx->vtable.vaBeginPicture = i965_BeginPicture;
1803     ctx->vtable.vaRenderPicture = i965_RenderPicture;
1804     ctx->vtable.vaEndPicture = i965_EndPicture;
1805     ctx->vtable.vaSyncSurface = i965_SyncSurface;
1806     ctx->vtable.vaQuerySurfaceStatus = i965_QuerySurfaceStatus;
1807     ctx->vtable.vaPutSurface = i965_PutSurface;
1808     ctx->vtable.vaQueryImageFormats = i965_QueryImageFormats;
1809     ctx->vtable.vaCreateImage = i965_CreateImage;
1810     ctx->vtable.vaDeriveImage = i965_DeriveImage;
1811     ctx->vtable.vaDestroyImage = i965_DestroyImage;
1812     ctx->vtable.vaSetImagePalette = i965_SetImagePalette;
1813     ctx->vtable.vaGetImage = i965_GetImage;
1814     ctx->vtable.vaPutImage = i965_PutImage;
1815     ctx->vtable.vaQuerySubpictureFormats = i965_QuerySubpictureFormats;
1816     ctx->vtable.vaCreateSubpicture = i965_CreateSubpicture;
1817     ctx->vtable.vaDestroySubpicture = i965_DestroySubpicture;
1818     ctx->vtable.vaSetSubpictureImage = i965_SetSubpictureImage;
1819     ctx->vtable.vaSetSubpictureChromakey = i965_SetSubpictureChromakey;
1820     ctx->vtable.vaSetSubpictureGlobalAlpha = i965_SetSubpictureGlobalAlpha;
1821     ctx->vtable.vaAssociateSubpicture = i965_AssociateSubpicture;
1822     ctx->vtable.vaDeassociateSubpicture = i965_DeassociateSubpicture;
1823     ctx->vtable.vaQueryDisplayAttributes = i965_QueryDisplayAttributes;
1824     ctx->vtable.vaGetDisplayAttributes = i965_GetDisplayAttributes;
1825     ctx->vtable.vaSetDisplayAttributes = i965_SetDisplayAttributes;
1826 //    ctx->vtable.vaDbgCopySurfaceToBuffer = i965_DbgCopySurfaceToBuffer;
1827
1828     i965 = (struct i965_driver_data *)calloc(1, sizeof(*i965));
1829     assert(i965);
1830     ctx->pDriverData = (void *)i965;
1831
1832     result = object_heap_init(&i965->config_heap, 
1833                               sizeof(struct object_config), 
1834                               CONFIG_ID_OFFSET);
1835     assert(result == 0);
1836
1837     result = object_heap_init(&i965->context_heap, 
1838                               sizeof(struct object_context), 
1839                               CONTEXT_ID_OFFSET);
1840     assert(result == 0);
1841
1842     result = object_heap_init(&i965->surface_heap, 
1843                               sizeof(struct object_surface), 
1844                               SURFACE_ID_OFFSET);
1845     assert(result == 0);
1846
1847     result = object_heap_init(&i965->buffer_heap, 
1848                               sizeof(struct object_buffer), 
1849                               BUFFER_ID_OFFSET);
1850     assert(result == 0);
1851
1852     result = object_heap_init(&i965->image_heap, 
1853                               sizeof(struct object_image), 
1854                               IMAGE_ID_OFFSET);
1855     assert(result == 0);
1856         
1857     result = object_heap_init(&i965->subpic_heap, 
1858                               sizeof(struct object_subpic), 
1859                               SUBPIC_ID_OFFSET);
1860     assert(result == 0);
1861     
1862     return i965_Init(ctx);
1863 }