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