psb_output.c revision 67612a448651896b2557796ff98d46c5e0dbbdc6
1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
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 *    Shengquan Yuan  <shengquan.yuan@intel.com>
26 *    Zhaohan Ren  <zhaohan.ren@intel.com>
27 *    Jason Hu <jason.hu@intel.com>
28 *
29 */
30
31#ifndef ANDROID
32#include <X11/Xutil.h>
33#include <X11/extensions/Xrandr.h>
34#include <va/va_dricommon.h>
35#include "x11/psb_x11.h"
36#include "x11/psb_xrandr.h"
37#endif
38#include <va/va_backend.h>
39#include <dlfcn.h>
40#include <stdlib.h>
41#include "psb_output.h"
42#include "psb_surface.h"
43#include "psb_buffer.h"
44#include "psb_surface_ext.h"
45#include "pnw_rotate.h"
46#include <stdio.h>
47#include <string.h>
48#include <stdarg.h>
49#include <wsbm/wsbm_manager.h>
50
51#include <string.h>
52#include <unistd.h>
53#include <sys/ioctl.h>
54
55#define INIT_DRIVER_DATA        psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
56
57#define SURFACE(id)     ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
58#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
59#define IMAGE(id)  ((object_image_p) object_heap_lookup( &driver_data->image_heap, id ))
60#define SUBPIC(id)  ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id ))
61#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
62
63
64/* surfaces link list associated with a subpicture */
65typedef struct _subpic_surface {
66    VASurfaceID surface_id;
67    struct _subpic_surface *next;
68} subpic_surface_s, *subpic_surface_p;
69
70
71static VAImageFormat psb__SubpicFormat[] = {
72    psb__ImageRGBA,
73    //psb__ImageAYUV,
74    //psb__ImageAI44
75};
76
77static VAImageFormat psb__CreateImageFormat[] = {
78    psb__ImageNV12,
79    psb__ImageRGBA,
80    //psb__ImageAYUV,
81    //psb__ImageAI44,
82    psb__ImageYV16
83};
84
85unsigned char *psb_x11_output_init(VADriverContextP ctx);
86VAStatus psb_x11_output_deinit(VADriverContextP ctx);
87unsigned char *psb_android_output_init(VADriverContextP ctx);
88VAStatus psb_android_output_deinit(VADriverContextP ctx);
89
90int psb_coverlay_init(VADriverContextP ctx);
91int psb_coverlay_deinit(VADriverContextP ctx);
92
93VAStatus psb_initOutput(VADriverContextP ctx)
94{
95    INIT_DRIVER_DATA;
96    unsigned char *ws_priv = NULL;
97    char *fps = NULL;
98    char env_value[1024];
99
100    pthread_mutex_init(&driver_data->output_mutex, NULL);
101
102    if (psb_parse_config("PSB_VIDEO_PUTSURFACE_DUMMY", &env_value[0]) == 0) {
103        psb__information_message("vaPutSurface: dummy mode, return directly\n");
104        driver_data->dummy_putsurface = 0;
105
106        return VA_STATUS_SUCCESS;
107    }
108
109    if (psb_parse_config("PSB_VIDEO_FPS", &env_value[0]) == 0) {
110        driver_data->fixed_fps = atoi(env_value);
111        psb__information_message("Throttling at FPS=%d\n", driver_data->fixed_fps);
112    } else
113        driver_data->fixed_fps = 0;
114
115    driver_data->outputmethod_checkinterval = 1;
116    if (psb_parse_config("PSB_VIDEO_INTERVAL", &env_value[0]) == 0) {
117        driver_data->outputmethod_checkinterval = atoi(env_value);
118        psb__information_message("Check output method at %d frames interval\n",
119                                 driver_data->outputmethod_checkinterval);
120    }
121
122    driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
123    driver_data->last_displaying_surface = VA_INVALID_SURFACE;
124
125    psb_InitRotate(ctx);
126
127#ifdef ANDROID
128    ws_priv = psb_android_output_init(ctx);
129    driver_data->is_android = 1;
130#else
131    ws_priv = psb_x11_output_init(ctx);
132    driver_data->is_android = 0;
133#endif
134    driver_data->ws_priv = ws_priv;
135
136
137    //use client textureblit
138    if (driver_data->ctexture == 1) {
139        int ret = psb_ctexture_init(ctx);
140        if (ret != 0)
141            driver_data->ctexture = 0;
142    }
143
144    /*
145    //use texture streaming
146    if (driver_data->ctexstreaming == 1)
147    psb_ctexstreaing_init(ctx);
148    */
149
150    return VA_STATUS_SUCCESS;
151}
152
153VAStatus psb_deinitOutput(
154    VADriverContextP ctx
155)
156{
157    INIT_DRIVER_DATA;
158
159    //use client textureblit
160    if (driver_data->ctexture == 1)
161        psb_ctexture_deinit(ctx);
162
163    if (driver_data->coverlay_init) {
164        psb_coverlay_deinit(ctx);
165        driver_data->coverlay_init = 0;
166    }
167
168#ifndef ANDROID
169    psb_x11_output_deinit(ctx);
170#else
171    psb_android_output_deinit(ctx);
172#endif
173
174    /* free here, but allocate in window system specific */
175    free(driver_data->ws_priv);
176    /*
177    //use texture streaming
178    if (driver_data->ctexstreaming == 1)
179        psb_ctexstreaing_deinit(ctx);
180    */
181    /* clean the displaying surface information in kernel */
182    psb_surface_set_displaying(driver_data, 0, 0, NULL);
183
184    pthread_mutex_destroy(&driver_data->output_mutex);
185
186    return VA_STATUS_SUCCESS;
187}
188
189#ifndef VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
190#define VA_STATUS_ERROR_INVALID_IMAGE_FORMAT VA_STATUS_ERROR_UNKNOWN
191#endif
192
193static VAImageFormat *psb__VAImageCheckFourCC(
194    VAImageFormat       *src_format,
195    VAImageFormat       *dst_format,
196    int                 dst_num
197)
198{
199    int i;
200    if (NULL == src_format || dst_format == NULL) {
201        return NULL;
202    }
203
204    /* check VAImage at first */
205    for (i = 0; i < dst_num; i++) {
206        if (dst_format[i].fourcc == src_format->fourcc)
207            return &dst_format[i];
208    }
209
210    psb__error_message("Unsupport fourcc 0x%x\n", src_format->fourcc);
211    return NULL;
212}
213
214static void psb__VAImageCheckRegion(
215    object_surface_p surface,
216    VAImage *image,
217    int *src_x,
218    int *src_y,
219    int *dest_x,
220    int *dest_y,
221    int *width,
222    int *height
223)
224{
225    /* check for image */
226    if (*src_x < 0) *src_x = 0;
227    if (*src_x > image->width) *src_x = image->width - 1;
228    if (*src_y < 0) *src_y = 0;
229    if (*src_y > image->height) *src_y = image->height - 1;
230
231    if (((*width) + (*src_x)) > image->width) *width = image->width - *src_x;
232    if (((*height) + (*src_y)) > image->height) *height = image->height - *src_x;
233
234    /* check for surface */
235    if (*dest_x < 0) *dest_x = 0;
236    if (*dest_x > surface->width) *dest_x = surface->width - 1;
237    if (*dest_y < 0) *dest_y = 0;
238    if (*dest_y > surface->height) *dest_y = surface->height - 1;
239
240    if (((*width) + (*dest_x)) > surface->width) *width = surface->width - *dest_x;
241    if (((*height) + (*dest_y)) > surface->height) *height = surface->height - *dest_x;
242}
243
244
245VAStatus psb_QueryImageFormats(
246    VADriverContextP ctx,
247    VAImageFormat *format_list,        /* out */
248    int *num_formats           /* out */
249)
250{
251    VAStatus vaStatus = VA_STATUS_SUCCESS;
252
253    if (NULL == format_list) {
254        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
255        DEBUG_FAILURE;
256        return vaStatus;
257    }
258    if (NULL == num_formats) {
259        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
260        DEBUG_FAILURE;
261        return vaStatus;
262    }
263    memcpy(format_list, psb__CreateImageFormat, sizeof(psb__CreateImageFormat));
264    *num_formats = PSB_MAX_IMAGE_FORMATS;
265
266    return VA_STATUS_SUCCESS;
267}
268
269inline int min_POT(int n)
270{
271    if ((n & (n - 1)) == 0) /* already POT */
272        return n;
273
274    return n |= n >> 16, n |= n >> 8, n |= n >> 4, n |= n >> 2, n |= n >> 1, n + 1;
275    /* return ((((n |= n>>16) |= n>>8) |= n>>4) |= n>>2) |= n>>1, n + 1; */
276}
277
278VAStatus psb_CreateImage(
279    VADriverContextP ctx,
280    VAImageFormat *format,
281    int width,
282    int height,
283    VAImage *image     /* out */
284)
285{
286    INIT_DRIVER_DATA;
287    VAImageID imageID;
288    object_image_p obj_image;
289    VAStatus vaStatus = VA_STATUS_SUCCESS;
290    VAImageFormat *img_fmt;
291    int pitch_pot;
292
293    (void)driver_data;
294
295    img_fmt = psb__VAImageCheckFourCC(format, psb__CreateImageFormat,
296                                      sizeof(psb__CreateImageFormat) / sizeof(VAImageFormat));
297    if (img_fmt == NULL)
298        return VA_STATUS_ERROR_UNKNOWN;
299
300    if (NULL == image) {
301        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
302        return vaStatus;
303    }
304
305    imageID = object_heap_allocate(&driver_data->image_heap);
306    obj_image = IMAGE(imageID);
307    if (NULL == obj_image) {
308        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
309        return vaStatus;
310    }
311
312    MEMSET_OBJECT(obj_image, struct object_image_s);
313
314    obj_image->image.image_id = imageID;
315    obj_image->image.format = *img_fmt;
316    obj_image->subpic_ref = 0;
317
318    pitch_pot = min_POT(width);
319
320    switch (format->fourcc) {
321    case VA_FOURCC_NV12: {
322        obj_image->image.width = width;
323        obj_image->image.height = height;
324        obj_image->image.data_size = pitch_pot * height /*Y*/ + 2 * (pitch_pot / 2) * (height / 2);/*UV*/
325        obj_image->image.num_planes = 2;
326        obj_image->image.pitches[0] = pitch_pot;
327        obj_image->image.pitches[1] = pitch_pot;
328        obj_image->image.offsets[0] = 0;
329        obj_image->image.offsets[1] = pitch_pot * height;
330        obj_image->image.num_palette_entries = 0;
331        obj_image->image.entry_bytes = 0;
332        obj_image->image.component_order[0] = 'Y';
333        obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
334        obj_image->image.component_order[2] = 'V';
335        obj_image->image.component_order[3] = '\0';
336        break;
337    }
338    case VA_FOURCC_AYUV: {
339        obj_image->image.width = width;
340        obj_image->image.height = height;
341        obj_image->image.data_size = 4 * pitch_pot * height;
342        obj_image->image.num_planes = 1;
343        obj_image->image.pitches[0] = 4 * pitch_pot;
344        obj_image->image.num_palette_entries = 0;
345        obj_image->image.entry_bytes = 0;
346        obj_image->image.component_order[0] = 'V';
347        obj_image->image.component_order[1] = 'U';
348        obj_image->image.component_order[2] = 'Y';
349        obj_image->image.component_order[3] = 'A';
350        break;
351    }
352    case VA_FOURCC_RGBA: {
353        obj_image->image.width = width;
354        obj_image->image.height = height;
355        obj_image->image.data_size = 4 * pitch_pot * height;
356        obj_image->image.num_planes = 1;
357        obj_image->image.pitches[0] = 4 * pitch_pot;
358        obj_image->image.num_palette_entries = 0;
359        obj_image->image.entry_bytes = 0;
360        obj_image->image.component_order[0] = 'R';
361        obj_image->image.component_order[1] = 'G';
362        obj_image->image.component_order[2] = 'B';
363        obj_image->image.component_order[3] = 'A';
364        break;
365    }
366    case VA_FOURCC_AI44: {
367        obj_image->image.width = width;
368        obj_image->image.height = height;
369        obj_image->image.data_size = pitch_pot * height;/* one byte one element */
370        obj_image->image.num_planes = 1;
371        obj_image->image.pitches[0] = pitch_pot;
372        obj_image->image.num_palette_entries = 16;
373        obj_image->image.entry_bytes = 4; /* AYUV */
374        obj_image->image.component_order[0] = 'I';
375        obj_image->image.component_order[1] = 'A';
376        obj_image->image.component_order[2] = '\0';
377        obj_image->image.component_order[3] = '\0';
378        break;
379    }
380    case VA_FOURCC_IYUV: {
381        obj_image->image.width = width;
382        obj_image->image.height = height;
383        obj_image->image.data_size = pitch_pot * height /*Y*/ + 2 * (pitch_pot / 2) * (height / 2);/*UV*/
384        obj_image->image.num_planes = 3;
385        obj_image->image.pitches[0] = pitch_pot;
386        obj_image->image.pitches[1] = pitch_pot / 2;
387        obj_image->image.pitches[2] = pitch_pot / 2;
388        obj_image->image.offsets[0] = 0;
389        obj_image->image.offsets[1] = pitch_pot * height;
390        obj_image->image.offsets[2] = pitch_pot * height + (pitch_pot / 2) * (height / 2);
391        obj_image->image.num_palette_entries = 0;
392        obj_image->image.entry_bytes = 0;
393        obj_image->image.component_order[0] = 'Y';
394        obj_image->image.component_order[1] = 'U';
395        obj_image->image.component_order[2] = 'V';
396        obj_image->image.component_order[3] = '\0';
397        break;
398    }
399    default: {
400        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
401        break;
402    }
403    }
404
405    if (VA_STATUS_SUCCESS == vaStatus) {
406        /* create the buffer */
407        vaStatus = psb__CreateBuffer(driver_data, NULL, VAImageBufferType,
408                                     obj_image->image.data_size, 1, NULL, &obj_image->image.buf);
409    }
410
411    obj_image->derived_surface = 0;
412
413    if (VA_STATUS_SUCCESS != vaStatus) {
414        object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
415    } else {
416        memcpy(image, &obj_image->image, sizeof(VAImage));
417    }
418
419    return vaStatus;
420}
421
422VAStatus psb_DeriveImage(
423    VADriverContextP ctx,
424    VASurfaceID surface,
425    VAImage *image     /* out */
426)
427{
428    INIT_DRIVER_DATA;
429    VAStatus vaStatus = VA_STATUS_SUCCESS;
430    VABufferID bufferID;
431    object_buffer_p obj_buffer;
432    VAImageID imageID;
433    object_image_p obj_image;
434    object_surface_p obj_surface = SURFACE(surface);
435    unsigned int fourcc, fourcc_index = ~0, i;
436    uint32_t srf_buf_ofs = 0;
437
438    if (NULL == obj_surface) {
439        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
440        DEBUG_FAILURE;
441        return vaStatus;
442    }
443
444    if (NULL == image) {
445        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
446        return vaStatus;
447    }
448
449    fourcc = obj_surface->psb_surface->extra_info[4];
450    for (i = 0; i < PSB_MAX_IMAGE_FORMATS; i++) {
451        if (psb__CreateImageFormat[i].fourcc == fourcc) {
452            fourcc_index = i;
453            break;
454        }
455    }
456    if (i == PSB_MAX_IMAGE_FORMATS) {
457        psb__error_message("Can't support the Fourcc\n");
458        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
459        return vaStatus;
460    }
461
462    /* create the image */
463    imageID = object_heap_allocate(&driver_data->image_heap);
464    obj_image = IMAGE(imageID);
465    if (NULL == obj_image) {
466        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
467        return vaStatus;
468    }
469
470    MEMSET_OBJECT(obj_image, struct object_image_s);
471
472    /* create a buffer to represent surface buffer */
473    bufferID = object_heap_allocate(&driver_data->buffer_heap);
474    obj_buffer = BUFFER(bufferID);
475    if (NULL == obj_buffer) {
476        object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
477        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
478        DEBUG_FAILURE;
479        return vaStatus;
480    }
481    MEMSET_OBJECT(obj_buffer, struct object_buffer_s);
482
483    obj_buffer->type = VAImageBufferType;
484    obj_buffer->buffer_data = NULL;
485    obj_buffer->psb_buffer = &obj_surface->psb_surface->buf;
486    obj_buffer->size = obj_surface->psb_surface->size;
487    obj_buffer->max_num_elements = 0;
488    obj_buffer->alloc_size = obj_buffer->size;
489
490    /* fill obj_image data structure */
491    obj_image->image.image_id = imageID;
492    obj_image->image.format = psb__CreateImageFormat[fourcc_index];
493    obj_image->subpic_ref = 0;
494
495    obj_image->image.buf = bufferID;
496    obj_image->image.width = obj_surface->width;
497    obj_image->image.height = obj_surface->height;
498    obj_image->image.data_size = obj_surface->psb_surface->size;
499
500    srf_buf_ofs = obj_surface->psb_surface->buf.buffer_ofs;
501
502    switch (fourcc) {
503    case VA_FOURCC_NV12: {
504        obj_image->image.num_planes = 2;
505        obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
506        obj_image->image.pitches[1] = obj_surface->psb_surface->stride;
507
508        obj_image->image.offsets[0] = srf_buf_ofs;
509        obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
510        obj_image->image.num_palette_entries = 0;
511        obj_image->image.entry_bytes = 0;
512        obj_image->image.component_order[0] = 'Y';
513        obj_image->image.component_order[1] = 'U';/* fixed me: packed UV packed here! */
514        obj_image->image.component_order[2] = 'V';
515        obj_image->image.component_order[3] = '\0';
516        break;
517    }
518    case VA_FOURCC_YV16: {
519        obj_image->image.num_planes = 3;
520        obj_image->image.pitches[0] = obj_surface->psb_surface->stride;
521        obj_image->image.pitches[1] = obj_surface->psb_surface->stride / 2;
522        obj_image->image.pitches[2] = obj_surface->psb_surface->stride / 2;
523
524        obj_image->image.offsets[0] = srf_buf_ofs;
525        obj_image->image.offsets[1] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride;
526        obj_image->image.offsets[2] = srf_buf_ofs + obj_surface->height * obj_surface->psb_surface->stride * 3 / 2;
527        obj_image->image.num_palette_entries = 0;
528        obj_image->image.entry_bytes = 0;
529        obj_image->image.component_order[0] = 'Y';
530        obj_image->image.component_order[1] = 'V';/* fixed me: packed UV packed here! */
531        obj_image->image.component_order[2] = 'U';
532        obj_image->image.component_order[3] = '\0';
533        break;
534    }
535    default:
536        break;
537    }
538
539    obj_image->derived_surface = surface; /* this image is derived from a surface */
540    obj_surface->derived_imgcnt++;
541
542    memcpy(image, &obj_image->image, sizeof(VAImage));
543
544    return vaStatus;
545}
546
547VAStatus psb__destroy_image(psb_driver_data_p driver_data, object_image_p obj_image)
548{
549    VAStatus vaStatus = VA_STATUS_SUCCESS;
550
551    if (obj_image->subpic_ref > 0) {
552        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
553        return vaStatus;
554    }
555
556    object_surface_p obj_surface = SURFACE(obj_image->derived_surface);
557
558    if (obj_surface == NULL) { /* destroy the buffer */
559        object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
560        if (NULL == obj_buffer) {
561            vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
562            DEBUG_FAILURE;
563            return vaStatus;
564        }
565        psb__suspend_buffer(driver_data, obj_buffer);
566    } else {
567        object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
568        object_heap_free(&driver_data->buffer_heap, &obj_buffer->base);
569        obj_surface->derived_imgcnt--;
570    }
571    object_heap_free(&driver_data->image_heap, (object_base_p) obj_image);
572
573    return VA_STATUS_SUCCESS;
574}
575
576VAStatus psb_DestroyImage(
577    VADriverContextP ctx,
578    VAImageID image
579)
580{
581    INIT_DRIVER_DATA
582    VAStatus vaStatus = VA_STATUS_SUCCESS;
583    object_image_p obj_image;
584
585    obj_image = IMAGE(image);
586    if (NULL == obj_image) {
587        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
588        DEBUG_FAILURE;
589        return vaStatus;
590    }
591    return psb__destroy_image(driver_data, obj_image);
592}
593
594VAStatus psb_SetImagePalette(
595    VADriverContextP ctx,
596    VAImageID image,
597    /*
598     * pointer to an array holding the palette data.  The size of the array is
599     * num_palette_entries * entry_bytes in size.  The order of the components
600     * in the palette is described by the component_order in VAImage struct
601     */
602    unsigned char *palette
603)
604{
605    INIT_DRIVER_DATA;
606    VAStatus vaStatus = VA_STATUS_SUCCESS;
607
608    object_image_p obj_image = IMAGE(image);
609    if (NULL == obj_image) {
610        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
611        DEBUG_FAILURE;
612        return vaStatus;
613    }
614
615    if (obj_image->image.format.fourcc != VA_FOURCC_AI44) {
616        /* only support AI44 palette */
617        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
618        return vaStatus;
619    }
620
621    if (obj_image->image.num_palette_entries > 16) {
622        psb__error_message("image.num_palette_entries(%d) is too big\n", obj_image->image.num_palette_entries);
623        memcpy(obj_image->palette, palette, 16);
624    } else
625        memcpy(obj_image->palette, palette, obj_image->image.num_palette_entries * sizeof(unsigned int));
626
627    return vaStatus;
628}
629
630static VAStatus lnc_unpack_topaz_rec(int src_width, int src_height,
631                                     unsigned char *p_srcY, unsigned char *p_srcUV,
632                                     unsigned char *p_dstY, unsigned char *p_dstU, unsigned char *p_dstV,
633                                     int dstY_stride, int dstU_stride, int dstV_stride,
634                                     int surface_height)
635{
636    unsigned char *tmp_dstY = NULL;
637    unsigned char *tmp_dstUV = NULL;
638
639    int n, i, index;
640
641    psb__information_message("Unpack reconstructed frame to image\n");
642
643    /* do this one column at a time. */
644    tmp_dstY = (unsigned char *)calloc(1, 16 * src_height);
645    if (tmp_dstY == NULL)
646        return  VA_STATUS_ERROR_ALLOCATION_FAILED;
647
648    tmp_dstUV = (unsigned char*)calloc(1, 16 * src_height / 2);
649    if (tmp_dstUV == NULL) {
650        free(tmp_dstY);
651        return VA_STATUS_ERROR_ALLOCATION_FAILED;
652    }
653
654    /*  Copy Y data */
655    for (n = 0; n < src_width / 16; n++) {
656        memcpy((void*)tmp_dstY, p_srcY, 16 * src_height);
657        p_srcY += (16 * surface_height);
658        for (i = 0; i < src_height; i++) {
659            memcpy(p_dstY + dstY_stride * i + n * 16, tmp_dstY + 16 * i, 16);
660        }
661    }
662
663    /* Copy U/V data */
664    for (n = 0; n < src_width / 16; n++) {
665        memcpy((void*)tmp_dstUV, p_srcUV, 16 * src_height / 2);
666        p_srcUV += (16 * surface_height / 2);
667        for (i = 0; i < src_height / 2; i++) {
668            for (index = 0; index < 8; index++) {
669                p_dstU[i*dstU_stride + n*8 + index] = tmp_dstUV[index*2 + i*16];
670                p_dstV[i*dstV_stride + n*8 + index] = tmp_dstUV[index*2 + i*16+1];
671            }
672        }
673    }
674    if (tmp_dstY)
675        free(tmp_dstY);
676    if (tmp_dstUV)
677        free(tmp_dstUV);
678
679    return VA_STATUS_SUCCESS;
680}
681
682
683VAStatus psb_GetImage(
684    VADriverContextP ctx,
685    VASurfaceID surface,
686    int x,     /* coordinates of the upper left source pixel */
687    int y,
688    unsigned int width, /* width and height of the region */
689    unsigned int height,
690    VAImageID image_id
691)
692{
693    INIT_DRIVER_DATA;
694    VAStatus vaStatus = VA_STATUS_SUCCESS;
695    int ret, src_x = 0, src_y = 0, dest_x = 0, dest_y = 0;
696
697    (void)driver_data;
698    (void)lnc_unpack_topaz_rec;
699
700    object_image_p obj_image = IMAGE(image_id);
701    if (NULL == obj_image) {
702        psb__error_message("Invalidate Image\n");
703
704        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
705        DEBUG_FAILURE;
706        return vaStatus;
707    }
708
709    if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
710        psb__error_message("target VAImage fourcc should be NV12 or IYUV\n");
711        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
712        return vaStatus;
713    }
714
715    object_surface_p obj_surface = SURFACE(surface);
716    if (NULL == obj_surface) {
717        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
718        DEBUG_FAILURE;
719        return vaStatus;
720    }
721
722    psb__VAImageCheckRegion(obj_surface, &obj_image->image, &src_x, &src_y, &dest_x, &dest_y,
723                            (int *)&width, (int *)&height);
724
725    psb_surface_p psb_surface = obj_surface->psb_surface;
726    unsigned char *surface_data;
727    ret = psb_buffer_map(&psb_surface->buf, &surface_data);
728    if (ret) {
729        return VA_STATUS_ERROR_UNKNOWN;
730    }
731
732    object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
733    if (NULL == obj_buffer) {
734        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
735        DEBUG_FAILURE;
736        return vaStatus;
737    }
738
739    unsigned char *image_data;
740    ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
741    if (ret) {
742        psb__error_message("Map buffer failed\n");
743
744        psb_buffer_unmap(&psb_surface->buf);
745        return VA_STATUS_ERROR_UNKNOWN;
746    }
747
748    image_data += obj_surface->psb_surface->buf.buffer_ofs;
749
750    switch (obj_image->image.format.fourcc) {
751    case VA_FOURCC_NV12: {
752        unsigned char *source_y, *src_uv, *dst_y, *dst_uv;
753        unsigned int i;
754        /* copy Y plane */
755        dst_y = image_data;
756        source_y = surface_data + y * psb_surface->stride + x;
757        for (i = 0; i < height; i++)  {
758            memcpy(dst_y, source_y, width);
759            dst_y += obj_image->image.pitches[0];
760            source_y += psb_surface->stride;
761        }
762
763        /* copy UV plane */
764        dst_uv = image_data + obj_image->image.offsets[1];
765        src_uv = surface_data + psb_surface->stride * obj_surface->height + (y / 2) * psb_surface->stride + x;;
766        for (i = 0; i < obj_image->image.height / 2; i++) {
767            memcpy(dst_uv, src_uv, width);
768            dst_uv += obj_image->image.pitches[1];
769            src_uv += psb_surface->stride;
770        }
771        break;
772    }
773#if 0
774    case VA_FOURCC_IYUV: {
775        unsigned char *source_y, *dst_y;
776        unsigned char *source_uv, *source_u, *source_v, *dst_u, *dst_v;
777        unsigned int i;
778
779        if (psb_surface->extra_info[4] == VA_FOURCC_IREC) {
780            /* copy Y plane */
781            dst_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
782            dst_u = image_data + obj_image->image.offsets[1] + src_y * obj_image->image.pitches[1] + src_x;
783            dst_v = image_data + obj_image->image.offsets[2] + src_y * obj_image->image.pitches[2] + src_x;
784
785            source_y = surface_data + dest_y * psb_surface->stride + dest_x;
786            source_uv = surface_data + obj_surface->height * psb_surface->stride
787                        + dest_y * (psb_surface->stride / 2) + dest_x;
788
789            vaStatus = lnc_unpack_topaz_rec(width, height, source_y, source_uv,
790                                            dst_y, dst_u, dst_v,
791                                            obj_image->image.pitches[0],
792                                            obj_image->image.pitches[1],
793                                            obj_image->image.pitches[2],
794                                            obj_surface->height);
795        }
796
797        break;
798    }
799#endif
800    default:
801        break;
802    }
803    psb_buffer_unmap(obj_buffer->psb_buffer);
804    psb_buffer_unmap(&psb_surface->buf);
805
806    return vaStatus;
807}
808
809static VAStatus psb_PutImage2(
810    VADriverContextP ctx,
811    VASurfaceID surface,
812    VAImageID image_id,
813    int src_x,
814    int src_y,
815    unsigned int width,
816    unsigned int height,
817    int dest_x,
818    int dest_y
819)
820{
821    INIT_DRIVER_DATA;
822    VAStatus vaStatus = VA_STATUS_SUCCESS;
823    int ret;
824
825    object_image_p obj_image = IMAGE(image_id);
826    if (NULL == obj_image) {
827        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
828        DEBUG_FAILURE;
829        return vaStatus;
830    }
831
832    object_surface_p obj_surface = SURFACE(surface);
833    if (NULL == obj_surface) {
834        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
835        DEBUG_FAILURE;
836        return vaStatus;
837    }
838
839    if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
840        psb__error_message("target VAImage fourcc should be NV12 or IYUV\n");
841        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
842        return vaStatus;
843    }
844
845    psb__VAImageCheckRegion(obj_surface, &obj_image->image, &src_x, &src_y, &dest_x, &dest_y,
846                            (int *)&width, (int *)&height);
847
848    psb_surface_p psb_surface = obj_surface->psb_surface;
849    unsigned char *surface_data;
850    ret = psb_buffer_map(&psb_surface->buf, &surface_data);
851    if (ret) {
852        return VA_STATUS_ERROR_UNKNOWN;
853    }
854
855    object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
856    if (NULL == obj_buffer) {
857        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
858        DEBUG_FAILURE;
859        return vaStatus;
860    }
861
862    unsigned char *image_data;
863    ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
864    if (ret) {
865        psb_buffer_unmap(&psb_surface->buf);
866        return VA_STATUS_ERROR_UNKNOWN;
867    }
868
869    image_data += obj_surface->psb_surface->buf.buffer_ofs;
870
871    switch (obj_image->image.format.fourcc) {
872    case VA_FOURCC_NV12: {
873        unsigned char *source_y, *src_uv, *dst_y, *dst_uv;
874        unsigned int i;
875
876        /* copy Y plane */
877        source_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
878        dst_y = surface_data + dest_y * psb_surface->stride + dest_x;
879        for (i = 0; i < height; i++)  {
880            memcpy(dst_y, source_y, width);
881            source_y += obj_image->image.pitches[0];
882            dst_y += psb_surface->stride;
883        }
884
885        /* copy UV plane */
886        src_uv = image_data + obj_image->image.offsets[1] + (src_y / 2) * obj_image->image.pitches[1] + src_x;
887        dst_uv = surface_data + psb_surface->stride * obj_surface->height + (dest_y / 2) * psb_surface->stride + dest_x;
888        for (i = 0; i < obj_image->image.height / 2; i++) {
889            memcpy(dst_uv, src_uv, width);
890            src_uv += obj_image->image.pitches[1];
891            dst_uv += psb_surface->stride;
892        }
893        break;
894    }
895#if 0
896    case VA_FOURCC_IYUV: {
897        char *source_y, *dst_y;
898        char *source_u, *source_v, *dst_u, *dst_v;
899        unsigned int i;
900
901        /* copy Y plane */
902        source_y = image_data + obj_image->image.offsets[0] + src_y * obj_image->image.pitches[0] + src_x;
903        source_u = image_data + obj_image->image.offsets[1] + src_y * obj_image->image.pitches[1] + src_x;
904        source_v = image_data + obj_image->image.offsets[2] + src_y * obj_image->image.pitches[2] + src_x;
905
906        dst_y = surface_data + dest_y * psb_surface->stride + dest_x;
907        dst_u = surface_data + obj_surface->height * psb_surface->stride
908                + dest_y * (psb_surface->stride / 2) + dest_x;
909        dst_v = surface_data + obj_surface->height * psb_surface->stride
910                + (obj_surface->height / 2) * (psb_surface->stride / 2)
911                + dest_y * (psb_surface->stride / 2) + dest_x;
912
913        for (i = 0; i < height; i++)  {
914            memcpy(dst_y, source_y, width);
915            source_y += obj_image->image.pitches[0];
916            dst_y += psb_surface->stride;
917        }
918
919        /* copy UV plane */
920        for (i = 0; i < obj_image->image.height / 2; i++) {
921            memcpy(dst_u, source_u, width);
922            memcpy(dst_v, source_v, width);
923
924            source_u += obj_image->image.pitches[1];
925            source_v += obj_image->image.pitches[2];
926
927            dst_u += psb_surface->stride / 2;
928            dst_v += psb_surface->stride / 2;
929        }
930        break;
931    }
932#endif
933    default:
934        break;
935    }
936
937    psb_buffer_unmap(obj_buffer->psb_buffer);
938    psb_buffer_unmap(&psb_surface->buf);
939
940    return VA_STATUS_SUCCESS;
941}
942
943
944static void psb__VAImageCheckRegion2(
945    object_surface_p surface,
946    VAImage *image,
947    int *src_x,
948    int *src_y,
949    unsigned int *src_width,
950    unsigned int *src_height,
951    int *dest_x,
952    int *dest_y,
953    int *dest_width,
954    int *dest_height
955)
956{
957    /* check for image */
958    if (*src_x < 0) *src_x = 0;
959    if (*src_x > image->width) *src_x = image->width - 1;
960    if (*src_y < 0) *src_y = 0;
961    if (*src_y > image->height) *src_y = image->height - 1;
962
963    if (((*src_width) + (*src_x)) > image->width) *src_width = image->width - *src_x;
964    if (((*src_height) + (*src_y)) > image->height) *src_height = image->height - *src_x;
965
966    /* check for surface */
967    if (*dest_x < 0) *dest_x = 0;
968    if (*dest_x > surface->width) *dest_x = surface->width - 1;
969    if (*dest_y < 0) *dest_y = 0;
970    if (*dest_y > surface->height) *dest_y = surface->height - 1;
971
972    if (((*dest_width) + (*dest_x)) > (int)surface->width) *dest_width = surface->width - *dest_x;
973    if (((*dest_height) + (*dest_y)) > (int)surface->height) *dest_height = surface->height - *dest_x;
974}
975
976VAStatus psb_PutImage(
977    VADriverContextP ctx,
978    VASurfaceID surface,
979    VAImageID image_id,
980    int src_x,
981    int src_y,
982    unsigned int src_width,
983    unsigned int src_height,
984    int dest_x,
985    int dest_y,
986    unsigned int dest_width,
987    unsigned int dest_height
988)
989{
990    INIT_DRIVER_DATA;
991    VAStatus vaStatus = VA_STATUS_SUCCESS;
992    int ret;
993
994    if ((src_width == dest_width) && (src_height == dest_height)) {
995        /* Shortcut if scaling is not required */
996        return psb_PutImage2(ctx, surface, image_id, src_x, src_y, src_width, src_height, dest_x, dest_y);
997    }
998
999    object_image_p obj_image = IMAGE(image_id);
1000    if (NULL == obj_image) {
1001        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
1002        DEBUG_FAILURE;
1003        return vaStatus;
1004    }
1005
1006    if (obj_image->image.format.fourcc != VA_FOURCC_NV12) {
1007        /* only support NV12 getImage/putImage */
1008        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
1009        return vaStatus;
1010    }
1011
1012    object_surface_p obj_surface = SURFACE(surface);
1013    if (NULL == obj_surface) {
1014        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1015        DEBUG_FAILURE;
1016        return vaStatus;
1017    }
1018
1019    psb__VAImageCheckRegion2(obj_surface, &obj_image->image,
1020                             &src_x, &src_y, &src_width, &src_height,
1021                             &dest_x, &dest_y, (int *)&dest_width, (int *)&dest_height);
1022
1023    psb_surface_p psb_surface = obj_surface->psb_surface;
1024    unsigned char *surface_data;
1025    ret = psb_buffer_map(&psb_surface->buf, &surface_data);
1026    if (ret) {
1027        return VA_STATUS_ERROR_UNKNOWN;
1028    }
1029
1030    object_buffer_p obj_buffer = BUFFER(obj_image->image.buf);
1031    if (NULL == obj_buffer) {
1032        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
1033        DEBUG_FAILURE;
1034        return vaStatus;
1035    }
1036
1037    unsigned char *image_data;
1038    ret = psb_buffer_map(obj_buffer->psb_buffer, &image_data);
1039    if (ret) {
1040        psb_buffer_unmap(&psb_surface->buf);
1041        return VA_STATUS_ERROR_UNKNOWN;
1042    }
1043
1044    /* just a prototype, the algorithm is ugly and not optimized */
1045    switch (obj_image->image.format.fourcc) {
1046    case VA_FOURCC_NV12: {
1047        unsigned char *source_y, *dst_y;
1048        unsigned short *source_uv, *dst_uv;
1049        unsigned int i, j;
1050        float xratio = (float) src_width / dest_width;
1051        float yratio = (float) src_height / dest_height;
1052
1053        /* dst_y/dst_uv: Y/UV plane of destination */
1054        dst_y = (unsigned char *)(surface_data + dest_y * psb_surface->stride + dest_x);
1055        dst_uv = (unsigned short *)(surface_data + psb_surface->stride * obj_surface->height
1056                                    + (dest_y / 2) * psb_surface->stride + dest_x);
1057
1058        for (j = 0; j < dest_height; j++)  {
1059            unsigned char *dst_y_tmp = dst_y;
1060            unsigned short *dst_uv_tmp = dst_uv;
1061
1062            for (i = 0; i < dest_width; i++)  {
1063                int x = (int)(i * xratio);
1064                int y = (int)(j * yratio);
1065
1066                source_y = image_data + obj_image->image.offsets[0]
1067                           + (src_y + y) * obj_image->image.pitches[0]
1068                           + (src_x + x);
1069                *dst_y_tmp = *source_y;
1070                dst_y_tmp++;
1071
1072                if (((i & 1) == 0)) {
1073                    source_uv = (unsigned short *)(image_data + obj_image->image.offsets[1]
1074                                                   + ((src_y + y) / 2) * obj_image->image.pitches[1])
1075                                + ((src_x + x) / 2);
1076                    *dst_uv_tmp = *source_uv;
1077                    dst_uv_tmp++;
1078                }
1079            }
1080            dst_y += psb_surface->stride;
1081
1082            if (j & 1)
1083                dst_uv = (unsigned short *)((unsigned char *)dst_uv + psb_surface->stride);
1084        }
1085        break;
1086    }
1087    default:/* will not reach here */
1088        break;
1089    }
1090
1091    psb_buffer_unmap(obj_buffer->psb_buffer);
1092    psb_buffer_unmap(&psb_surface->buf);
1093
1094    return VA_STATUS_SUCCESS;
1095}
1096
1097/*
1098 * Link supbicture into one surface, when update is zero, not need to
1099 * update the location information
1100 * The image informatio and its BO of subpicture will copied to surface
1101 * so need to update it when a vaSetSubpictureImage is called
1102 */
1103static VAStatus psb__LinkSubpictIntoSurface(
1104    psb_driver_data_p driver_data,
1105    object_surface_p obj_surface,
1106    object_subpic_p obj_subpic,
1107    short src_x,
1108    short src_y,
1109    unsigned short src_w,
1110    unsigned short src_h,
1111    short dest_x,
1112    short dest_y,
1113    unsigned short dest_w,
1114    unsigned short dest_h,
1115    int update /* update subpicture location */
1116)
1117{
1118    PsbVASurfaceRec *surface_subpic;
1119    object_image_p obj_image = IMAGE(obj_subpic->image_id);
1120    if (NULL == obj_image) {
1121        return VA_STATUS_ERROR_INVALID_IMAGE;
1122    }
1123
1124    VAImage *image = &obj_image->image;
1125    object_buffer_p obj_buffer = BUFFER(image->buf);
1126    if (NULL == obj_buffer) {
1127        return VA_STATUS_ERROR_INVALID_BUFFER;
1128    }
1129
1130    int found = 0;
1131
1132    if (obj_surface->subpictures != NULL) {
1133        surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
1134        do {
1135            if (surface_subpic->subpic_id == obj_subpic->subpic_id) {
1136                found = 1;
1137                break;
1138            } else
1139                surface_subpic = surface_subpic->next;
1140        } while (surface_subpic);
1141    }
1142
1143    if (found == 0) { /* new node */
1144        if (obj_surface->subpic_count >= PSB_SUBPIC_MAX_NUM) {
1145            psb__error_message("can't support so many sub-pictures for the surface\n");
1146            return VA_STATUS_ERROR_UNKNOWN;
1147        }
1148
1149        surface_subpic = (PsbVASurfaceRec *)calloc(1, sizeof(*surface_subpic));
1150        if (NULL == surface_subpic)
1151            return VA_STATUS_ERROR_ALLOCATION_FAILED;
1152    }
1153
1154    surface_subpic->subpic_id = obj_subpic->subpic_id;
1155    surface_subpic->fourcc = image->format.fourcc;
1156    surface_subpic->size = image->data_size;
1157    surface_subpic->bo = obj_buffer->psb_buffer->drm_buf;
1158    surface_subpic->bufid = wsbmKBufHandle(wsbmKBuf(obj_buffer->psb_buffer->drm_buf));
1159    surface_subpic->pl_flags = obj_buffer->psb_buffer->pl_flags;
1160    surface_subpic->subpic_flags = obj_subpic->flags;
1161
1162    surface_subpic->width = image->width;
1163    surface_subpic->height = image->height;
1164    switch (surface_subpic->fourcc) {
1165    case VA_FOURCC_AYUV:
1166        surface_subpic->stride = image->pitches[0] / 4;
1167        break;
1168    case VA_FOURCC_RGBA:
1169        surface_subpic->stride = image->pitches[0] / 4;
1170        break;
1171    case VA_FOURCC_AI44:
1172        surface_subpic->stride = image->pitches[0];
1173        /* point to Image palette */
1174        surface_subpic->palette_ptr = (PsbAYUVSample8 *) & obj_image->palette[0];
1175        break;
1176    }
1177
1178    if (update) {
1179        surface_subpic->subpic_srcx = src_x;
1180        surface_subpic->subpic_srcy = src_y;
1181        surface_subpic->subpic_dstx = dest_x;
1182        surface_subpic->subpic_dsty = dest_y;
1183        surface_subpic->subpic_srcw = src_w;
1184        surface_subpic->subpic_srch = src_h;
1185        surface_subpic->subpic_dstw = dest_w;
1186        surface_subpic->subpic_dsth = dest_h;
1187    }
1188
1189    if (found == 0) { /* new node, link into the list */
1190        if (NULL == obj_surface->subpictures) {
1191            obj_surface->subpictures = (void *)surface_subpic;
1192        } else { /* insert as the head */
1193            surface_subpic->next = (PsbVASurfacePtr)obj_surface->subpictures;
1194            obj_surface->subpictures = (void *)surface_subpic;
1195        }
1196        obj_surface->subpic_count++;
1197    }
1198
1199    return VA_STATUS_SUCCESS;
1200}
1201
1202
1203static VAStatus psb__LinkSurfaceIntoSubpict(
1204    object_subpic_p obj_subpic,
1205    VASurfaceID surface_id
1206)
1207{
1208    subpic_surface_s *subpic_surface;
1209    int found = 0;
1210
1211    if (obj_subpic->surfaces != NULL) {
1212        subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1213        do  {
1214            if (subpic_surface->surface_id == surface_id) {
1215                found = 1;
1216                return VA_STATUS_SUCCESS; /* reture directly */
1217            } else
1218                subpic_surface = subpic_surface->next;
1219        } while (subpic_surface);
1220    }
1221
1222    /* not found */
1223    subpic_surface = (subpic_surface_s *)calloc(1, sizeof(*subpic_surface));
1224    if (NULL == subpic_surface)
1225        return VA_STATUS_ERROR_ALLOCATION_FAILED;
1226
1227    subpic_surface->surface_id = surface_id;
1228    subpic_surface->next = NULL;
1229
1230    if (NULL == obj_subpic->surfaces) {
1231        obj_subpic->surfaces = (void *)subpic_surface;
1232    } else { /* insert as the head */
1233        subpic_surface->next = (subpic_surface_p)obj_subpic->surfaces;
1234        obj_subpic->surfaces = (void *)subpic_surface;
1235    }
1236
1237    return VA_STATUS_SUCCESS;
1238}
1239
1240static VAStatus psb__DelinkSubpictFromSurface(
1241    object_surface_p obj_surface,
1242    VASubpictureID subpic_id
1243)
1244{
1245    PsbVASurfaceRec *surface_subpic, *pre_surface_subpic = NULL;
1246    int found = 0;
1247
1248    if (obj_surface->subpictures != NULL) {
1249        surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
1250        do  {
1251            if (surface_subpic->subpic_id == subpic_id) {
1252                found = 1;
1253                break;
1254            } else {
1255                pre_surface_subpic = surface_subpic;
1256                surface_subpic = surface_subpic->next;
1257            }
1258        } while (surface_subpic);
1259    }
1260
1261    if (found == 1) {
1262        if (pre_surface_subpic == NULL) { /* remove the first node */
1263            obj_surface->subpictures = (void *)surface_subpic->next;
1264        } else {
1265            pre_surface_subpic->next = surface_subpic->next;
1266        }
1267        free(surface_subpic);
1268        obj_surface->subpic_count--;
1269    }
1270
1271    return VA_STATUS_SUCCESS;
1272}
1273
1274
1275static VAStatus psb__DelinkSurfaceFromSubpict(
1276    object_subpic_p obj_subpic,
1277    VASurfaceID surface_id
1278)
1279{
1280    subpic_surface_s *subpic_surface, *pre_subpic_surface = NULL;
1281    int found = 0;
1282
1283    if (obj_subpic->surfaces != NULL) {
1284        subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1285        do {
1286            if (subpic_surface->surface_id == surface_id) {
1287                found = 1;
1288                break;
1289            } else {
1290                pre_subpic_surface = subpic_surface;
1291                subpic_surface = subpic_surface->next;
1292            }
1293        } while (subpic_surface);
1294    }
1295
1296    if (found == 1) {
1297        if (pre_subpic_surface == NULL) { /* remove the first node */
1298            obj_subpic->surfaces = (void *)subpic_surface->next;
1299        } else {
1300            pre_subpic_surface->next = subpic_surface->next;
1301        }
1302        free(subpic_surface);
1303    }
1304
1305    return VA_STATUS_SUCCESS;
1306}
1307
1308
1309VAStatus psb_QuerySubpictureFormats(
1310    VADriverContextP ctx,
1311    VAImageFormat *format_list,        /* out */
1312    unsigned int *flags,       /* out */
1313    unsigned int *num_formats  /* out */
1314)
1315{
1316    VAStatus vaStatus = VA_STATUS_SUCCESS;
1317
1318    if (NULL == format_list) {
1319        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1320        DEBUG_FAILURE;
1321        return vaStatus;
1322    }
1323    if (NULL == flags) {
1324        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1325        DEBUG_FAILURE;
1326        return vaStatus;
1327    }
1328    if (NULL == num_formats) {
1329        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1330        DEBUG_FAILURE;
1331        return vaStatus;
1332    }
1333    memcpy(format_list, psb__SubpicFormat, sizeof(psb__SubpicFormat));
1334    *num_formats = PSB_MAX_SUBPIC_FORMATS;
1335    *flags = PSB_SUPPORTED_SUBPIC_FLAGS;
1336
1337    return VA_STATUS_SUCCESS;
1338}
1339
1340
1341VAStatus psb_CreateSubpicture(
1342    VADriverContextP ctx,
1343    VAImageID image,
1344    VASubpictureID *subpicture   /* out */
1345)
1346{
1347    INIT_DRIVER_DATA;
1348    VASubpictureID subpicID;
1349    object_subpic_p obj_subpic;
1350    object_image_p obj_image;
1351    VAStatus vaStatus = VA_STATUS_SUCCESS;
1352    VAImageFormat *img_fmt;
1353
1354    obj_image = IMAGE(image);
1355
1356    if (NULL == subpicture) {
1357        vaStatus = VA_STATUS_ERROR_INVALID_SUBPICTURE;
1358        DEBUG_FAILURE;
1359        return vaStatus;
1360    }
1361
1362    if (NULL == obj_image) {
1363        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
1364        return vaStatus;
1365    }
1366
1367    img_fmt = psb__VAImageCheckFourCC(&obj_image->image.format, psb__SubpicFormat,
1368                                      sizeof(psb__SubpicFormat) / sizeof(VAImageFormat));
1369    if (img_fmt == NULL)
1370        return VA_STATUS_ERROR_UNKNOWN;
1371
1372    subpicID = object_heap_allocate(&driver_data->subpic_heap);
1373    obj_subpic = SUBPIC(subpicID);
1374    if (NULL == obj_subpic) {
1375        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1376        return vaStatus;
1377    }
1378    MEMSET_OBJECT(obj_subpic, struct object_subpic_s);
1379
1380    obj_subpic->subpic_id = subpicID;
1381    obj_subpic->image_id = obj_image->image.image_id;
1382    obj_subpic->surfaces = NULL;
1383    obj_subpic->global_alpha = 255;
1384
1385    obj_image->subpic_ref ++;
1386
1387    *subpicture = subpicID;
1388
1389    return VA_STATUS_SUCCESS;
1390}
1391
1392
1393
1394VAStatus psb__destroy_subpicture(psb_driver_data_p driver_data, object_subpic_p obj_subpic)
1395{
1396    subpic_surface_s *subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1397    VASubpictureID subpicture = obj_subpic->subpic_id;
1398
1399    if (subpic_surface) {
1400        do {
1401            subpic_surface_s *tmp = subpic_surface;
1402            object_surface_p obj_surface = SURFACE(subpic_surface->surface_id);
1403
1404            if (obj_surface) { /* remove subpict from surface */
1405                psb__DelinkSubpictFromSurface(obj_surface, subpicture);
1406            }
1407            subpic_surface = subpic_surface->next;
1408            free(tmp);
1409        } while (subpic_surface);
1410    }
1411
1412    object_heap_free(&driver_data->subpic_heap, (object_base_p) obj_subpic);
1413    return VA_STATUS_SUCCESS;
1414}
1415
1416
1417VAStatus psb_DestroySubpicture(
1418    VADriverContextP ctx,
1419    VASubpictureID subpicture
1420)
1421{
1422    INIT_DRIVER_DATA;
1423    object_subpic_p obj_subpic;
1424    VAStatus vaStatus = VA_STATUS_SUCCESS;
1425
1426    obj_subpic = SUBPIC(subpicture);
1427    if (NULL == obj_subpic) {
1428        vaStatus = VA_STATUS_ERROR_INVALID_SUBPICTURE;
1429        return vaStatus;
1430    }
1431
1432
1433    return psb__destroy_subpicture(driver_data, obj_subpic);
1434}
1435
1436VAStatus psb_SetSubpictureImage(
1437    VADriverContextP ctx,
1438    VASubpictureID subpicture,
1439    VAImageID image
1440)
1441{
1442    INIT_DRIVER_DATA;
1443    object_subpic_p obj_subpic;
1444    object_image_p obj_image;
1445    VAStatus vaStatus = VA_STATUS_SUCCESS;
1446    subpic_surface_s *subpic_surface;
1447    VAImageFormat *img_fmt;
1448
1449    obj_image = IMAGE(image);
1450    if (NULL == obj_image) {
1451        vaStatus = VA_STATUS_ERROR_INVALID_IMAGE;
1452        return vaStatus;
1453    }
1454
1455    img_fmt = psb__VAImageCheckFourCC(&obj_image->image.format,
1456                                      psb__SubpicFormat,
1457                                      sizeof(psb__SubpicFormat) / sizeof(VAImageFormat));
1458    if (img_fmt == NULL)
1459        return VA_STATUS_ERROR_INVALID_IMAGE;
1460
1461    obj_subpic = SUBPIC(subpicture);
1462    if (NULL == obj_subpic) {
1463        vaStatus = VA_STATUS_ERROR_INVALID_SUBPICTURE;
1464        return vaStatus;
1465    }
1466
1467    object_image_p old_obj_image = IMAGE(obj_subpic->image_id);
1468    if (old_obj_image) {
1469        old_obj_image->subpic_ref--;/* decrease reference count */
1470    }
1471
1472    /* reset the image */
1473    obj_subpic->image_id = obj_image->image.image_id;
1474    obj_image->subpic_ref ++;
1475
1476    /* relink again */
1477    if (obj_subpic->surfaces != NULL) {
1478        /* the subpicture already linked into surfaces
1479         * so not check the return value of psb__LinkSubpictIntoSurface
1480         */
1481        subpic_surface = (subpic_surface_s *)obj_subpic->surfaces;
1482        do {
1483            object_surface_p obj_surface = SURFACE(subpic_surface->surface_id);
1484            if (NULL == obj_surface) {
1485                vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1486                return vaStatus;
1487            }
1488
1489            psb__LinkSubpictIntoSurface(driver_data, obj_surface, obj_subpic,
1490                                        0, 0, 0, 0, 0, 0, 0, 0,
1491                                        0 /* not update location */
1492                                       );
1493            subpic_surface = subpic_surface->next;
1494        } while (subpic_surface);
1495    }
1496
1497
1498    return VA_STATUS_SUCCESS;
1499}
1500
1501
1502VAStatus psb_SetSubpictureChromakey(
1503    VADriverContextP ctx,
1504    VASubpictureID subpicture,
1505    unsigned int chromakey_min,
1506    unsigned int chromakey_max,
1507    unsigned int chromakey_mask
1508)
1509{
1510    INIT_DRIVER_DATA;
1511    (void)driver_data;
1512    /* TODO */
1513    if ((chromakey_mask < chromakey_min) || (chromakey_mask > chromakey_max)) {
1514        psb__error_message("Invalid chromakey value %d, chromakey value should between min and max\n", chromakey_mask);
1515        return VA_STATUS_ERROR_INVALID_PARAMETER;
1516    }
1517    object_subpic_p obj_subpic = SUBPIC(subpicture);
1518    if (NULL == obj_subpic) {
1519        psb__error_message("Invalid subpicture value %d\n", subpicture);
1520        return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1521    }
1522
1523    return VA_STATUS_SUCCESS;
1524}
1525
1526VAStatus psb_SetSubpictureGlobalAlpha(
1527    VADriverContextP ctx,
1528    VASubpictureID subpicture,
1529    float global_alpha
1530)
1531{
1532    INIT_DRIVER_DATA;
1533
1534    if (global_alpha < 0 || global_alpha > 1) {
1535        psb__error_message("Invalid global alpha value %07f, global alpha value should between 0 and 1\n", global_alpha);
1536        return VA_STATUS_ERROR_INVALID_PARAMETER;
1537    }
1538
1539    object_subpic_p obj_subpic = SUBPIC(subpicture);
1540    if (NULL == obj_subpic) {
1541        psb__error_message("Invalid subpicture value %d\n", subpicture);
1542        return VA_STATUS_ERROR_INVALID_SUBPICTURE;
1543    }
1544
1545    obj_subpic->global_alpha = global_alpha * 255;
1546
1547    return VA_STATUS_SUCCESS;
1548}
1549
1550
1551VAStatus psb__AssociateSubpicture(
1552    VADriverContextP ctx,
1553    VASubpictureID subpicture,
1554    VASurfaceID *target_surfaces,
1555    int num_surfaces,
1556    short src_x, /* upper left offset in subpicture */
1557    short src_y,
1558    unsigned short src_w,
1559    unsigned short src_h,
1560    short dest_x, /* upper left offset in surface */
1561    short dest_y,
1562    unsigned short dest_w,
1563    unsigned short dest_h,
1564    /*
1565     * whether to enable chroma-keying or global-alpha
1566     * see VA_SUBPICTURE_XXX values
1567     */
1568    unsigned int flags
1569)
1570{
1571    INIT_DRIVER_DATA;
1572
1573    object_subpic_p obj_subpic;
1574    VAStatus vaStatus = VA_STATUS_SUCCESS;
1575    int i;
1576
1577    if (num_surfaces <= 0) {
1578        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1579        DEBUG_FAILURE;
1580        return vaStatus;
1581    }
1582
1583    obj_subpic = SUBPIC(subpicture);
1584    if (NULL == obj_subpic) {
1585        vaStatus = VA_STATUS_ERROR_INVALID_SUBPICTURE;
1586        DEBUG_FAILURE;
1587        return vaStatus;
1588    }
1589
1590    if (NULL == target_surfaces) {
1591        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1592        DEBUG_FAILURE;
1593        return vaStatus;
1594    }
1595
1596    if (flags & ~PSB_SUPPORTED_SUBPIC_FLAGS) {
1597#ifdef VA_STATUS_ERROR_FLAG_NOT_SUPPORTED
1598        vaStatus = VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
1599#else
1600        vaStatus = VA_STATUS_ERROR_UNKNOWN;
1601#endif
1602        DEBUG_FAILURE;
1603        return vaStatus;
1604    } else {
1605
1606        /* If flags are ok, copy them to the subpicture object */
1607        obj_subpic->flags = flags;
1608
1609    }
1610
1611    /* Validate input params */
1612    for (i = 0; i < num_surfaces; i++) {
1613        object_surface_p obj_surface = SURFACE(target_surfaces[i]);
1614        if (NULL == obj_surface) {
1615            vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1616            DEBUG_FAILURE;
1617            return vaStatus;
1618        }
1619    }
1620
1621    VASurfaceID *surfaces = target_surfaces;
1622    for (i = 0; i < num_surfaces; i++) {
1623        object_surface_p obj_surface = SURFACE(*surfaces);
1624        if (obj_surface) {
1625            vaStatus = psb__LinkSubpictIntoSurface(driver_data, obj_surface, obj_subpic,
1626                                                   src_x, src_y, src_w, src_h,
1627                                                   dest_x, dest_y, dest_w, dest_h, 1);
1628            if (VA_STATUS_SUCCESS == vaStatus) {
1629                vaStatus = psb__LinkSurfaceIntoSubpict(obj_subpic, *surfaces);
1630            }
1631            if (VA_STATUS_SUCCESS != vaStatus) { /* failed with malloc */
1632                DEBUG_FAILURE;
1633                return vaStatus;
1634            }
1635        } else {
1636            /* Should never get here */
1637            psb__error_message("Invalid surfaces,SurfaceID=0x%x\n", *surfaces);
1638        }
1639
1640        surfaces++;
1641    }
1642
1643    return VA_STATUS_SUCCESS;
1644}
1645
1646
1647VAStatus psb_AssociateSubpicture(
1648    VADriverContextP ctx,
1649    VASubpictureID subpicture,
1650    VASurfaceID *target_surfaces,
1651    int num_surfaces,
1652    short src_x, /* upper left offset in subpicture */
1653    short src_y,
1654    unsigned short src_width,
1655    unsigned short src_height,
1656    short dest_x, /* upper left offset in surface */
1657    short dest_y,
1658    unsigned short dest_width,
1659    unsigned short dest_height,
1660    /*
1661     * whether to enable chroma-keying or global-alpha
1662     * see VA_SUBPICTURE_XXX values
1663     */
1664    unsigned int flags
1665)
1666{
1667    return psb__AssociateSubpicture(ctx, subpicture, target_surfaces, num_surfaces,
1668                                    src_x, src_y, src_width, src_height,
1669                                    dest_x, dest_y, dest_width, dest_height,
1670                                    flags
1671                                   );
1672}
1673
1674
1675VAStatus psb_DeassociateSubpicture(
1676    VADriverContextP ctx,
1677    VASubpictureID subpicture,
1678    VASurfaceID *target_surfaces,
1679    int num_surfaces
1680)
1681{
1682    INIT_DRIVER_DATA;
1683
1684    object_subpic_p obj_subpic;
1685    VAStatus vaStatus = VA_STATUS_SUCCESS;
1686    object_image_p obj_image;
1687    int i;
1688
1689    if (num_surfaces <= 0) {
1690        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1691        DEBUG_FAILURE;
1692        return vaStatus;
1693    }
1694
1695    obj_subpic = SUBPIC(subpicture);
1696    if (NULL == obj_subpic) {
1697        vaStatus = VA_STATUS_ERROR_INVALID_SUBPICTURE;
1698        DEBUG_FAILURE;
1699        return vaStatus;
1700    }
1701
1702    if (NULL == target_surfaces) {
1703        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1704        DEBUG_FAILURE;
1705        return vaStatus;
1706    }
1707
1708    VASurfaceID *surfaces = target_surfaces;
1709    for (i = 0; i < num_surfaces; i++) {
1710        object_surface_p obj_surface = SURFACE(*surfaces);
1711
1712        if (obj_surface) {
1713            psb__DelinkSubpictFromSurface(obj_surface, subpicture);
1714            psb__DelinkSurfaceFromSubpict(obj_subpic, obj_surface->surface_id);
1715        } else {
1716            psb__error_message("vaDeassociateSubpicture: Invalid surface, VASurfaceID=0x%08x\n", *surfaces);
1717        }
1718
1719        surfaces++;
1720    }
1721
1722    obj_image = IMAGE(obj_subpic->image_id);
1723    if (obj_image)
1724        obj_image->subpic_ref--;/* decrease reference count */
1725
1726    return VA_STATUS_SUCCESS;
1727}
1728
1729
1730void psb_SurfaceDeassociateSubpict(
1731    psb_driver_data_p driver_data,
1732    object_surface_p obj_surface
1733)
1734{
1735    PsbVASurfaceRec *surface_subpic = (PsbVASurfaceRec *)obj_surface->subpictures;
1736
1737    if (surface_subpic != NULL) {
1738        do  {
1739            PsbVASurfaceRec *tmp = surface_subpic;
1740            object_subpic_p obj_subpic = SUBPIC(surface_subpic->subpic_id);
1741            if (obj_subpic)
1742                psb__DelinkSurfaceFromSubpict(obj_subpic, obj_surface->surface_id);
1743            surface_subpic = surface_subpic->next;
1744            free(tmp);
1745        } while (surface_subpic);
1746    }
1747}
1748
1749
1750static  VADisplayAttribute psb__DisplayAttribute[] = {
1751    {
1752        VADisplayAttribBrightness,
1753        BRIGHTNESS_MIN,
1754        BRIGHTNESS_MAX,
1755        BRIGHTNESS_DEFAULT_VALUE,
1756        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1757    },
1758
1759    {
1760        VADisplayAttribContrast,
1761        CONTRAST_MIN,
1762        CONTRAST_MAX,
1763        CONTRAST_DEFAULT_VALUE,
1764        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1765    },
1766
1767    {
1768        VADisplayAttribHue,
1769        HUE_MIN,
1770        HUE_MAX,
1771        HUE_DEFAULT_VALUE,
1772        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1773    },
1774
1775    {
1776        VADisplayAttribSaturation,
1777        SATURATION_MIN,
1778        SATURATION_MAX,
1779        SATURATION_DEFAULT_VALUE,
1780        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1781    },
1782    {
1783        VADisplayAttribBackgroundColor,
1784        0x00000000,
1785        0xffffffff,
1786        0x00000000,
1787        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1788    },
1789    {
1790        VADisplayAttribRotation,
1791        VA_ROTATION_NONE,
1792        VA_ROTATION_270,
1793        VA_ROTATION_NONE,
1794        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1795    },
1796    {
1797        VADisplayAttribOutofLoopDeblock,
1798        VA_OOL_DEBLOCKING_FALSE,
1799        VA_OOL_DEBLOCKING_TRUE,
1800        VA_OOL_DEBLOCKING_FALSE,
1801        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1802    },
1803    {
1804        VADisplayAttribBLEBlackMode,
1805        0x00000000,
1806        0xffffffff,
1807        0x00000000,
1808        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1809    },
1810    {
1811        VADisplayAttribBLEWhiteMode,
1812        0x00000000,
1813        0xffffffff,
1814        0x00000000,
1815        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1816    },
1817
1818    {
1819        VADisplayAttribBlueStretch,
1820        0x00000000,
1821        0xffffffff,
1822        0x00000000,
1823        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1824    },
1825    {
1826        VADisplayAttribSkinColorCorrection,
1827        0x00000000,
1828        0xffffffff,
1829        0x00000000,
1830        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1831    },
1832    {
1833        VADisplayAttribBlendColor,
1834        0x00000000,
1835        0xffffffff,
1836        0x00000000,
1837        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1838    },
1839    {
1840        VADisplayAttribOverlayColorKey,
1841        0x00000000,
1842        0xffffffff,
1843        0x00000000,
1844        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1845    },
1846    {
1847        VADisplayAttribOverlayAutoPaintColorKey,
1848        0x00000000,
1849        0xffffffff,
1850        0x00000000,
1851        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1852    },
1853    {
1854        VADisplayAttribCSCMatrix,
1855        0x00000000,
1856        0xffffffff,
1857        0x00000000,
1858        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1859    },
1860    {
1861        VADisplayAttribRenderDevice,
1862        0x00000000,
1863        0xffffffff,
1864        0x00000000,
1865        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1866    },
1867    {
1868        VADisplayAttribRenderMode,
1869        0x00000000,
1870        0xffffffff,
1871        0x00000000,
1872        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1873    },
1874    {
1875        VADisplayAttribRenderRect,
1876        0x00000000,
1877        0xffffffff,
1878        0x00000000,
1879        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
1880    }
1881};
1882
1883/*
1884 * Query display attributes
1885 * The caller must provide a "attr_list" array that can hold at
1886 * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1887 * returned in "attr_list" is returned in "num_attributes".
1888 */
1889VAStatus psb_QueryDisplayAttributes(
1890    VADriverContextP ctx,
1891    VADisplayAttribute *attr_list,      /* out */
1892    int *num_attributes         /* out */
1893)
1894{
1895    VAStatus vaStatus = VA_STATUS_SUCCESS;
1896
1897    if (NULL == attr_list) {
1898        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1899        DEBUG_FAILURE;
1900        return vaStatus;
1901    }
1902    if (NULL == num_attributes) {
1903        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1904        DEBUG_FAILURE;
1905        return vaStatus;
1906    }
1907    *num_attributes = min(*num_attributes, PSB_MAX_DISPLAY_ATTRIBUTES);
1908    memcpy(attr_list, psb__DisplayAttribute, (*num_attributes)*sizeof(VADisplayAttribute));
1909    return VA_STATUS_SUCCESS;
1910}
1911
1912/*
1913 * Get display attributes
1914 * This function returns the current attribute values in "attr_list".
1915 * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
1916 * from vaQueryDisplayAttributes() can have their values retrieved.
1917 */
1918VAStatus psb_GetDisplayAttributes(
1919    VADriverContextP ctx,
1920    VADisplayAttribute *attr_list,      /* in/out */
1921    int num_attributes
1922)
1923{
1924    INIT_DRIVER_DATA;
1925    VADisplayAttribute *p = attr_list;
1926    int i;
1927    VAStatus vaStatus = VA_STATUS_SUCCESS;
1928
1929    if (NULL == attr_list) {
1930        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1931        DEBUG_FAILURE;
1932        return vaStatus;
1933    }
1934
1935    if (num_attributes <= 0) {
1936        return VA_STATUS_ERROR_INVALID_PARAMETER;
1937    }
1938
1939    for (i = 0; i < num_attributes; i++) {
1940        switch (p->type) {
1941        case VADisplayAttribBrightness:
1942            /* -50*(1<<10) ~ 50*(1<<10) ==> 0~100*/
1943            p->value = (driver_data->brightness.value / (1 << 10)) + 50;
1944            p->min_value = 0;
1945            p->max_value = 100;
1946            break;
1947        case VADisplayAttribContrast:
1948            /* 0 ~ 2*(1<<25) ==> 0~100 */
1949            p->value = (driver_data->contrast.value / (1 << 25)) * 50;
1950            p->min_value = 0;
1951            p->max_value = 100;
1952            break;
1953        case VADisplayAttribHue:
1954            /* -30*(1<<25) ~ 30*(1<<25) ==> 0~100*/
1955            p->value = ((driver_data->hue.value / (1 << 25)) + 30) * 10 / 6;
1956            p->min_value = 0;
1957            p->max_value = 100;
1958            break;
1959        case VADisplayAttribSaturation:
1960            /* 0 ~ 2*(1<<25) ==> 0~100 */
1961            p->value = (driver_data->saturation.value / (1 << 25)) * 50;
1962            p->min_value = 0;
1963            p->max_value = 100;
1964            break;
1965        case VADisplayAttribBackgroundColor:
1966            p->value = driver_data->clear_color;
1967            break;
1968        case VADisplayAttribBlendColor:
1969            p->value = driver_data->blend_color;
1970            break;
1971        case VADisplayAttribOverlayColorKey:
1972            p->value = driver_data->color_key;
1973            p->min_value = 0;
1974            p->max_value = 0xFFFFFF;
1975            break;
1976        case VADisplayAttribOverlayAutoPaintColorKey:
1977            p->value = driver_data->overlay_auto_paint_color_key;
1978            p->min_value = 0;
1979            p->max_value = 1;
1980            break;
1981        case VADisplayAttribRotation:
1982            p->value = driver_data->va_rotate = p->value;
1983            p->min_value = VA_ROTATION_NONE;
1984            p->max_value = VA_ROTATION_270;
1985            break;
1986        case VADisplayAttribOutofLoopDeblock:
1987            p->value = driver_data->is_oold = p->value;
1988            p->min_value = VA_OOL_DEBLOCKING_FALSE;
1989            p->max_value = VA_OOL_DEBLOCKING_TRUE;
1990            break;
1991        case VADisplayAttribCSCMatrix:
1992            p->value = driver_data->load_csc_matrix = p->value;
1993            p->min_value = 0;
1994            p->max_value = 255;
1995            break;
1996        case VADisplayAttribRenderDevice:
1997            p->value = driver_data->render_device = p->value;
1998            p->min_value = 0;
1999            p->max_value = 255;
2000            break;
2001        case VADisplayAttribRenderMode:
2002            p->value = driver_data->render_mode = p->value;
2003            p->min_value = 0;
2004            p->max_value = 255;
2005            break;
2006        case VADisplayAttribRenderRect:
2007            ((VARectangle *)(p->value))->x = driver_data->render_rect.x = ((VARectangle *)(p->value))->x;
2008            ((VARectangle *)(p->value))->y = driver_data->render_rect.y = ((VARectangle *)(p->value))->y;
2009            ((VARectangle *)(p->value))->width = driver_data->render_rect.width = ((VARectangle *)(p->value))->width;
2010            ((VARectangle *)(p->value))->height = driver_data->render_rect.height = ((VARectangle *)(p->value))->height;
2011            p->min_value = 0;
2012            p->max_value = 255;
2013            break;
2014
2015        default:
2016            break;
2017        }
2018        p++;
2019    }
2020
2021    return VA_STATUS_SUCCESS;
2022}
2023
2024/*
2025 * Set display attributes
2026 * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
2027 * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or
2028 * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
2029 */
2030#define CLAMP_ATTR(a,max,min) (a>max?max:(a<min?min:a))
2031VAStatus psb_SetDisplayAttributes(
2032    VADriverContextP ctx,
2033    VADisplayAttribute *attr_list,
2034    int num_attributes
2035)
2036{
2037    INIT_DRIVER_DATA;
2038    VAStatus vaStatus = VA_STATUS_SUCCESS;
2039    struct psb_texture_s *texture_priv = &driver_data->ctexture_priv;
2040    PsbPortPrivPtr overlay_priv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
2041    int j, k;
2042
2043    if (NULL == attr_list) {
2044        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2045        DEBUG_FAILURE;
2046        return vaStatus;
2047    }
2048
2049    VADisplayAttribute *p = attr_list;
2050    int i, update_coeffs = 0;
2051    unsigned int *p_tmp;
2052
2053    if (num_attributes <= 0) {
2054        return VA_STATUS_ERROR_INVALID_PARAMETER;
2055    }
2056
2057    for (i = 0; i < num_attributes; i++) {
2058        switch (p->type) {
2059        case VADisplayAttribBrightness:
2060            /* 0~100 ==> -50*(1<<10) ~ 50*(1<<10)*/
2061            driver_data->brightness.value = (p->value - 50) * (1 << 10);
2062            /* 0~100 ==> -50~50 */
2063            overlay_priv->brightness.Value = texture_priv->brightness.Value = p->value - 50;
2064            update_coeffs = 1;
2065            break;
2066        case VADisplayAttribContrast:
2067            /* 0~100 ==> 0 ~ 2*(1<<25) */
2068            driver_data->contrast.value = (p->value / 50) * (1 << 25);
2069            /* 0~100 ==> -100~100 */
2070            overlay_priv->contrast.Value = texture_priv->contrast.Value = p->value * 2 - 100;
2071            update_coeffs = 1;
2072            break;
2073        case VADisplayAttribHue:
2074            /* 0~100 ==> -30*(1<<25) ~ 30*(1<<25) */
2075            driver_data->hue.value = ((p->value * 2 - 100) * 3 / 10) * (1 << 25);
2076            /* 0~100 ==> -30~30 */
2077            overlay_priv->hue.Value = texture_priv->hue.Value = (p->value * 2 - 100) * 3 / 10;
2078            update_coeffs = 1;
2079            break;
2080        case VADisplayAttribSaturation:
2081            /* 0~100 ==> 0 ~ 2*(1<<25) */
2082            driver_data->contrast.value = (p->value / 50) * (1 << 25);
2083            /* 0~100 ==> 100~200 */
2084            overlay_priv->saturation.Value = texture_priv->saturation.Value = p->value + 100;
2085            update_coeffs = 1;
2086            break;
2087        case VADisplayAttribBLEBlackMode:
2088            driver_data->ble_black_mode.value = p->value;
2089            update_coeffs = 1;
2090            break;
2091        case VADisplayAttribBLEWhiteMode:
2092            driver_data->ble_white_mode.value = p->value;
2093            update_coeffs = 1;
2094            break;
2095        case VADisplayAttribBlueStretch:
2096            driver_data->blueStretch_gain.value = p->value;
2097            update_coeffs = 1;
2098            break;
2099        case VADisplayAttribSkinColorCorrection:
2100            driver_data->skinColorCorrection_gain.value = p->value;
2101            update_coeffs = 1;
2102            break;
2103        case VADisplayAttribBackgroundColor:
2104            driver_data->clear_color = p->value;
2105            break;
2106        case VADisplayAttribOutofLoopDeblock:
2107            driver_data->is_oold = p->value;
2108            break;
2109        case VADisplayAttribRotation:
2110            driver_data->va_rotate = p->value;
2111            driver_data->rotation_dirty |= PSB_NEW_VA_ROTATION;
2112            break;
2113
2114        case VADisplayAttribCSCMatrix:
2115            driver_data->load_csc_matrix = 1;
2116            p_tmp = (unsigned int *)p->value;
2117            for (j = 0; j < CSC_MATRIX_Y; j++)
2118                for (k = 0; k < CSC_MATRIX_X; k++) {
2119                    if (p_tmp)
2120                        driver_data->csc_matrix[j][k] = *p_tmp;
2121                   p_tmp++;
2122                }
2123            break;
2124
2125        case VADisplayAttribBlendColor:
2126            driver_data->blend_color = p->value;
2127            break;
2128        case VADisplayAttribOverlayColorKey:
2129            overlay_priv->colorKey = driver_data->color_key = p->value;
2130            break;
2131        case VADisplayAttribOverlayAutoPaintColorKey:
2132            driver_data->overlay_auto_paint_color_key = p->value;
2133            break;
2134
2135        case VADisplayAttribRenderDevice:
2136            driver_data->render_device = p->value & VA_RENDER_DEVICE_MASK;
2137        case VADisplayAttribRenderMode:
2138            if (p->value & VA_RENDER_MODE_EXTERNAL_GPU) {
2139                psb__error_message("%s:Invalid parameter.VARenderModeExternalGPU is not supported.\n", __FUNCTION__);
2140                return VA_STATUS_ERROR_INVALID_PARAMETER;
2141            }
2142            if (((p->value & VA_RENDER_MODE_LOCAL_OVERLAY) && (p->value & VA_RENDER_MODE_LOCAL_GPU)) ||
2143                ((p->value & VA_RENDER_MODE_EXTERNAL_OVERLAY) && (p->value & VA_RENDER_MODE_EXTERNAL_GPU))) {
2144                psb__error_message("%s:Invalid parameter. Conflict setting for VADisplayAttribRenderMode.\n", __FUNCTION__);
2145                return VA_STATUS_ERROR_INVALID_PARAMETER;
2146            }
2147            driver_data->render_mode = p->value & VA_RENDER_MODE_MASK;
2148            break;
2149        case VADisplayAttribRenderRect:
2150            driver_data->render_rect.x = ((VARectangle *)(p->value))->x;
2151            driver_data->render_rect.y = ((VARectangle *)(p->value))->y;
2152            driver_data->render_rect.width = ((VARectangle *)(p->value))->width;
2153            driver_data->render_rect.height = ((VARectangle *)(p->value))->height;
2154            break;
2155
2156        default:
2157            break;
2158        }
2159        p++;
2160    }
2161
2162    if (update_coeffs) {
2163        /* TODO */
2164#ifndef ANDROID
2165        texture_priv->update_coeffs = 1;
2166#endif
2167    }
2168
2169    return VA_STATUS_SUCCESS;
2170}
2171
2172