psb_drv_video.c revision 9f388f4488bba39eeac0c97ddaa6480362edf952
1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Waldo Bastian <waldo.bastian@intel.com>
27 *
28 */
29
30#include <va/va_backend.h>
31#include <va/va_backend_tpi.h>
32#include <va/va_backend_egl.h>
33#include <va/va_dricommon.h>
34
35#include "psb_drv_video.h"
36#include "psb_texture.h"
37#include "psb_cmdbuf.h"
38#include "lnc_cmdbuf.h"
39#include "pnw_cmdbuf.h"
40#include "psb_surface.h"
41
42#ifdef PSBVIDEO_MRST
43#include "psb_MPEG2.h"
44#include "psb_MPEG4.h"
45#include "psb_H264.h"
46#include "psb_VC1.h"
47#include "lnc_MPEG4ES.h"
48#include "lnc_H264ES.h"
49#include "lnc_H263ES.h"
50#endif
51#ifdef PSBVIDEO_MFLD
52#include "pnw_MPEG2.h"
53#include "pnw_MPEG4.h"
54#include "pnw_H264.h"
55#include "pnw_VC1.h"
56#include "pnw_MPEG4ES.h"
57#include "pnw_H264ES.h"
58#include "pnw_H263ES.h"
59#include "pnw_jpeg.h"
60#endif
61#include "psb_output.h"
62#include "lnc_ospm.h"
63#include "psb_texstreaming.h"
64#include <stdio.h>
65#include <string.h>
66#include <stdarg.h>
67#include <time.h>
68#include <unistd.h>
69#include <wsbm/wsbm_pool.h>
70#include <wsbm/wsbm_manager.h>
71#include <wsbm/wsbm_util.h>
72#include <wsbm/wsbm_fencemgr.h>
73#include <linux/videodev2.h>
74#include <sys/mman.h>
75#include <errno.h>
76#include <system/graphics.h>
77#include <gralloc.h>
78#include "android/psb_gralloc.h"
79#include "android/psb_android_glue.h"
80#include "psb_def.h"
81#include "psb_ws_driver.h"
82#include "ci_va.h"
83#include "pnw_rotate.h"
84
85#ifndef PSB_PACKAGE_VERSION
86#define PSB_PACKAGE_VERSION "Undefined"
87#endif
88
89#define PSB_DRV_VERSION  PSB_PACKAGE_VERSION
90#define PSB_CHG_REVISION "(0X00000071)"
91
92#define PSB_STR_VENDOR_MRST     "Intel GMA500-MRST-" PSB_DRV_VERSION " " PSB_CHG_REVISION
93#define PSB_STR_VENDOR_MFLD     "Intel GMA500-MFLD-" PSB_DRV_VERSION " " PSB_CHG_REVISION
94
95#define MAX_UNUSED_BUFFERS      16
96
97#define PSB_MAX_FLIP_DELAY (1000/30/10)
98
99#ifdef DEBUG_TRACE
100#include <signal.h>
101#endif
102
103#define EXPORT __attribute__ ((visibility("default")))
104
105#define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
106#define INIT_FORMAT_VTABLE format_vtable_p format_vtable = ((profile < PSB_MAX_PROFILES) && (entrypoint < PSB_MAX_ENTRYPOINTS)) ? driver_data->profile2Format[profile][entrypoint] : NULL;
107
108#define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
109#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
110#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
111#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
112
113#define CONFIG_ID_OFFSET        0x01000000
114#define CONTEXT_ID_OFFSET       0x02000000
115#define SURFACE_ID_OFFSET       0x03000000
116#define BUFFER_ID_OFFSET        0x04000000
117#define IMAGE_ID_OFFSET         0x05000000
118#define SUBPIC_ID_OFFSET        0x06000000
119
120static int psb_get_device_info(VADriverContextP ctx);
121
122
123void psb_init_surface_pvr2dbuf(psb_driver_data_p driver_data);
124void psb_free_surface_pvr2dbuf(psb_driver_data_p driver_data);
125
126static FILE *psb_video_debug_fp = NULL;
127static FILE *psb_video_debug_dump_buffer_fp = NULL;
128static int  debug_fp_count = 0;
129static FILE *psb_video_debug_nv_buffer_fp=NULL;
130
131/*
132 * read a config "env" for libva.conf or from environment setting
133 * liva.conf has higher priority
134 * return 0: the "env" is set, and the value is copied into env_value
135 *        1: the env is not set
136 */
137int psb_parse_config(char *env, char *env_value)
138{
139    char *token, *value, *saveptr;
140    char oneline[1024];
141    FILE *fp = NULL;
142    char *env_ptr;
143
144    if (env == NULL)
145        return 1;
146
147    fp = fopen("/etc/psbvideo.conf", "r");
148    while (fp && (fgets(oneline, 1024, fp) != NULL)) {
149        if (strlen(oneline) == 1)
150            continue;
151        token = strtok_r(oneline, "=\n", &saveptr);
152        value = strtok_r(NULL, "=\n", &saveptr);
153
154        if (NULL == token || NULL == value)
155            continue;
156
157        if (strcmp(token, env) == 0) {
158            if (env_value)
159                strcpy(env_value, value);
160
161            fclose(fp);
162
163            return 0;
164        }
165    }
166    if (fp)
167        fclose(fp);
168
169    env_ptr = getenv(env);
170    if (env_ptr) {
171        if (env_value)
172            strncpy(env_value, env_ptr, strlen(env_ptr));
173
174        return 0;
175    }
176
177    return 1;
178}
179
180void psb__error_message(const char *msg, ...)
181{
182    va_list args;
183    FILE *fp;
184    char tag[128];
185
186    (void)tag;
187
188    if (psb_video_debug_fp == NULL) /* not set the debug */
189        fp = stderr;
190    else
191        fp = psb_video_debug_fp;
192
193    fprintf(fp, "[0x%08lx]psb_drv_video error(%d:0x%08lx) ",
194            GetTickCount(), getpid(), pthread_self());
195    va_start(args, msg);
196    vfprintf(fp, msg, args);
197#ifdef ANDROID
198    sprintf(tag, "pvr_drv_video[%d:0x%08lx]", getpid(), pthread_self());
199    __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, args);
200#endif
201    va_end(args);
202
203    fflush(fp);
204    fsync(fileno(fp));
205}
206
207void psb__dump_buffers_allkinds(object_buffer_p obj_buffer )
208{
209    int i, j,k;
210    void *mapped_buffer;
211    int print_num;
212
213    if(psb_video_debug_dump_buffer_fp) {
214        fprintf(psb_video_debug_dump_buffer_fp, "%s", buffer_type_to_string(obj_buffer->type));
215        print_num = fprintf(psb_video_debug_dump_buffer_fp, "BUFF SIZE :%d	NUMELEMENTS:%d BUFF INFO:\n", obj_buffer->size, obj_buffer->num_elements);
216
217        switch(obj_buffer->type) {
218            case VAPictureParameterBufferType:
219            case VAIQMatrixBufferType:
220            case VASliceParameterBufferType:
221                j=0;
222                for(k=0;k < obj_buffer->size;++k)
223                    print_num = fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ,",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
224                    fprintf(psb_video_debug_dump_buffer_fp,"\n ");
225                break;
226
227            case VASliceGroupMapBufferType:
228            case VABitPlaneBufferType:
229//            case VASliceDataBufferType:
230//            case VAProtectedSliceDataBufferType:
231                psb_buffer_map(obj_buffer->psb_buffer, &mapped_buffer);
232                for(j=0; j<obj_buffer->size;++j) {
233                    if(j%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
234                    for(k=0;k < obj_buffer->num_elements;++k)
235                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx   ",*((unsigned char *)(mapped_buffer+obj_buffer->num_elements*j+k)));
236                }
237
238                psb_buffer_unmap(obj_buffer->psb_buffer);
239                break;
240
241            case  VASliceDataBufferType:
242                fprintf(psb_video_debug_dump_buffer_fp,"first 256 bytes:\n");
243                psb_buffer_map(obj_buffer->psb_buffer, &mapped_buffer);
244                for(j=0; j<256;++j) {
245                    if(j%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
246                    for(k=0;k < obj_buffer->num_elements;++k)
247                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx   ",*((unsigned char *)(mapped_buffer+obj_buffer->num_elements*j+k)));
248                }
249                psb_buffer_unmap(obj_buffer->psb_buffer);
250                break;
251
252            default:
253                break;
254
255        }
256        fprintf(psb_video_debug_dump_buffer_fp, "\n");
257        fflush(psb_video_debug_dump_buffer_fp);
258        fsync(fileno(psb_video_debug_dump_buffer_fp));
259    }
260
261}
262
263void psb__dump_buffers(object_buffer_p obj_buffer )
264{
265    int i, j,k;
266    void *mapped_buffer;
267    if(psb_video_debug_dump_buffer_fp) {
268        fprintf(psb_video_debug_dump_buffer_fp, "%s", buffer_type_to_string(obj_buffer->type));
269        fprintf(psb_video_debug_dump_buffer_fp, "BUFF SIZE :%d	NUMELEMENTS:%d BUFF INFO:\n", obj_buffer->size, obj_buffer->num_elements);
270        switch(obj_buffer->type) {
271            case VAPictureParameterBufferType:
272                for(j=0; j < 340; j = j+20) {
273                    if(j==0) fprintf(psb_video_debug_dump_buffer_fp,"\nCurrPic:\n");
274                    else fprintf(psb_video_debug_dump_buffer_fp,"\nReferenceFrames%d\n", j / 20);
275                    fprintf(psb_video_debug_dump_buffer_fp,"picture_id:");
276                    for(k=0;k < 4;++k)
277                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
278                        fprintf(psb_video_debug_dump_buffer_fp,"    frame_idx:");
279                    for(k=4;k < 8;++k)
280                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
281                        fprintf(psb_video_debug_dump_buffer_fp,"    flags:");
282                    for(k=8;k < 12;++k)
283                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
284                        fprintf(psb_video_debug_dump_buffer_fp,"    TopFieldOrderCnt:");
285                    for(k=12;k < 16;++k)
286                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
287                        fprintf(psb_video_debug_dump_buffer_fp,"    BottomFieldOrderCnt:");
288                    for(k=16;k < 20;++k)
289                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
290                }
291                j=340;k=0;
292                fprintf(psb_video_debug_dump_buffer_fp,"\npicture_width_in_mbs_minus1:");
293                for(k=0;k < 2;++k)
294                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
295                j=342;k=0;
296                fprintf(psb_video_debug_dump_buffer_fp, "\npicture_height_in_mbs_minus1:");
297                for(k=0;k < 2;++k)
298                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
299                j=344;k=0;
300                fprintf(psb_video_debug_dump_buffer_fp,  "\nbit_depth_luma_minus8:");
301                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
302                j=345;k=0;
303                fprintf(psb_video_debug_dump_buffer_fp, "\nbit_depth_chroma_minus8:");
304                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
305                j=346;k=0;
306                fprintf(psb_video_debug_dump_buffer_fp, "\nnum_ref_frames:");
307                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
308                j=348;k=0;
309                fprintf(psb_video_debug_dump_buffer_fp,"\nseq_fields_value:");
310                for(k=0;k < 4;++k)
311                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
312                j=352;k=0;
313                fprintf(psb_video_debug_dump_buffer_fp,"\nnum_slice_groups_minus1:");
314                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
315                j=353;k=0;
316                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_group_map_type:");
317                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
318                j=354;k=0;
319                fprintf(psb_video_debug_dump_buffer_fp, "\nslice_group_change_rate_minus1:");
320                for(k=0;k < 2;++k)
321                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
322                j=356;k=0;
323                fprintf(psb_video_debug_dump_buffer_fp,"\npic_init_qp_minus26:");
324                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
325                j=357;k=0;
326                fprintf(psb_video_debug_dump_buffer_fp,"\npic_init_qs_minus26:");
327                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
328                j=358;k=0;
329                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_qp_index_offset:");
330                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
331                j=359;k=0;
332                fprintf(psb_video_debug_dump_buffer_fp, "\nsecond_chroma_qp_index_offset:");
333                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
334                j=360;k=0;
335                fprintf(psb_video_debug_dump_buffer_fp,"\npic_fields_value:");
336                for(k=0;k < 4;++k)
337                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
338                j=364;k=0;
339                fprintf(psb_video_debug_dump_buffer_fp,"\nframe_num:");
340                for(k=0;k < 2;++k)
341                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
342                break;
343
344            case VAIQMatrixBufferType:
345                for(j=0;j<96;j=j+16) {
346                    fprintf(psb_video_debug_dump_buffer_fp,"\nScalingList4x4_%d:", j/16);
347                    for(k=0; k<16;++k) {
348                        if(k%4 == 0) fprintf(psb_video_debug_dump_buffer_fp, "\n");
349                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx   ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
350                    }
351                }
352                for(j=96;j<224;j=j+64) {
353                    fprintf(psb_video_debug_dump_buffer_fp,"\nScalingList4x4_%d:",( j-96)/64);
354                    for(k=0; k<64;++k) {
355                        if(k%8 == 0) fprintf(psb_video_debug_dump_buffer_fp, "\n");
356                        printf(psb_video_debug_dump_buffer_fp,"0x%02lx   ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
357                    }
358                }
359                break;
360
361            case VASliceParameterBufferType:
362                j=0;k=0;
363                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_data_size:");
364                for(k=0;k < 4;++k)
365                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
366                j=4;k=0;
367                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_data_offset:");
368                for(k=0;k < 4;++k)
369                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
370                j=8;k=0;
371                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_data_flag:");
372                for(k=0;k < 4;++k)
373                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
374                j=12;k=0;
375                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_data_bit_offset:");
376                for(k=0;k < 2;++k)
377                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
378                j=14;k=0;
379                fprintf(psb_video_debug_dump_buffer_fp,"\nfirst_mb_in_slice:");
380                for(k=0;k < 2;++k)
381                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
382                j=16;k=0;
383                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_type:");
384                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
385                j=17;k=0;
386                fprintf(psb_video_debug_dump_buffer_fp,"\ndirect_spatial_mv_pred_flag:");
387                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
388                j=18;k=0;
389                fprintf(psb_video_debug_dump_buffer_fp,  "\nnum_ref_idx_l0_active_minus1:");
390                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
391                j=19;k=0;
392                fprintf(psb_video_debug_dump_buffer_fp, "\nnum_ref_idx_l1_active_minus1:");
393                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
394                j=20;k=0;
395                fprintf(psb_video_debug_dump_buffer_fp,"\ncabac_init_idc:");
396                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
397                j=21;k=0;
398                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_qp_delta:");
399                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
400                j=22;k=0;
401                fprintf(psb_video_debug_dump_buffer_fp, "\ndisable_deblocking_filter_idc:");
402                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
403                j=23;k=0;
404                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_alpha_c0_offset_div2:");
405                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
406                j=24;k=0;
407                fprintf(psb_video_debug_dump_buffer_fp,"\nslice_beta_offset_div2:");
408                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
409                for(j=28; j < 668; j = j+20) {
410                    fprintf(psb_video_debug_dump_buffer_fp,"\nRefPicList0 ListIndex=%d\n", (j -28)/ 20);
411                    fprintf(psb_video_debug_dump_buffer_fp,"picture_id:");
412                    for(k=0;k < 4;++k)
413                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
414                        fprintf(psb_video_debug_dump_buffer_fp,"   frame_idx:");
415                    for(k=4;k < 8;++k)
416                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
417                        fprintf(psb_video_debug_dump_buffer_fp,"   flags:");
418                    for(k=8;k < 12;++k)
419                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
420                        fprintf(psb_video_debug_dump_buffer_fp,"   TopFieldOrderCnt:");
421                    for(k=12;k < 16;++k)
422                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
423                        fprintf(psb_video_debug_dump_buffer_fp,"   BottomFieldOrderCnt:");
424                    for(k=16;k < 20;++k)
425                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
426                    }
427                for(j=668; j < 1308; j = j+20) {
428                    fprintf(psb_video_debug_dump_buffer_fp,"\nRefPicList1 ListIndex=%d\n", (j -668)/ 20);
429                    fprintf(psb_video_debug_dump_buffer_fp,"picture_id:");
430                    for(k=0;k < 4;++k)
431                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
432                        fprintf(psb_video_debug_dump_buffer_fp,"   frame_idx:");
433                    for(k=4;k < 8;++k)
434                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
435                        fprintf(psb_video_debug_dump_buffer_fp,"   flags:");
436                    for(k=8;k < 12;++k)
437                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
438                        fprintf(psb_video_debug_dump_buffer_fp,"   TopFieldOrderCnt:");
439                    for(k=12;k < 16;++k)
440                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
441                        fprintf(psb_video_debug_dump_buffer_fp,"   BottomFieldOrderCnt:");
442                    for(k=16;k < 20;++k)
443                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
444                    }
445                j=1308;k=0;
446                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_log2_weight_denom:");
447                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
448j=1309;k=0;
449                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_log2_weight_denom:");
450                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
451                j=1310;k=0;
452                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_weight_l0_flag:");
453                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
454                j=1312;k=0;
455                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_weight_l0:");
456                for(j=1312;j<1376;j=j+2) {
457                    if((j-1312)%16 == 0)fprintf(psb_video_debug_dump_buffer_fp,"\n");
458                    fprintf(psb_video_debug_dump_buffer_fp,"     :");
459                    for(k=0;k < 2;++k)
460                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
461                }
462                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_offset_l0:");
463                for(j=1376;j<1440;j=j+2) {
464                    if((j-1376)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
465                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
466                    for(k=0;k < 2;++k)
467                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
468                }
469                j=1440;k=0;
470                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_weight_l0_flag:");
471                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
472                j=1442;k=0;
473                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_weight_l0:");
474                for(j=1442;j<1570;j=j+4) {
475                    if((j-1442)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
476                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
477                    for(k=0;k < 2;++k)
478                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
479                        fprintf(psb_video_debug_dump_buffer_fp," , ");
480                    for(k=2;k < 4;++k)
481                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
482
483                }
484
485                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_offset_l0:");
486                for(j=1570;j<1698;j=j+4) {
487                    if((j-1570)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
488                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
489                    for(k=0;k < 2;++k)
490                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
491                        fprintf(psb_video_debug_dump_buffer_fp," , ");
492                    for(k=2;k < 4;++k)
493                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
494                }
495                j=1698;k=0;
496                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_weight_l1_flag:");
497                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
498                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_weight_l1:");
499                for(j=1700;j<1764;j=j+2) {
500                    if((j-1700)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
501                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
502                    for(k=0;k < 2;++k)
503                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
504                }
505                fprintf(psb_video_debug_dump_buffer_fp,"\nluma_offset_l1:");
506                for(j=1764;j<1828;j=j+2) {
507                    if((j-1764)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
508                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
509                    for(k=0;k < 2;++k)
510                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
511                }
512                j=1828;k=0;
513                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_weight_l1_flag:");
514                fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
515                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_weight_l1:");
516                for(j=1830;j<1958;j=j+4) {
517                    if((j-1830)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
518                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
519                    for(k=0;k < 2;++k)
520                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
521                        fprintf(psb_video_debug_dump_buffer_fp," , ");
522                    for(k=2;k < 4;++k)
523                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
524                }
525                fprintf(psb_video_debug_dump_buffer_fp,"\nchroma_offset_l1:");
526                for(j=1958;j<2086;j=j+4) {
527                    if((j-1958)%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
528                    fprintf(psb_video_debug_dump_buffer_fp,"     ");
529                    for(k=0;k < 2;++k)
530                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
531                        fprintf(psb_video_debug_dump_buffer_fp," , ");
532                    for(k=2;k < 4;++k)
533                    fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx ",*((unsigned char *)(obj_buffer->buffer_data+obj_buffer->num_elements*j+k)));
534                }
535                break;
536
537            case VASliceGroupMapBufferType:
538	///	    case VASliceDataBufferType:
539	///	    case VAProtectedSliceDataBufferType:
540                psb_buffer_map(obj_buffer->psb_buffer, &mapped_buffer);
541                for(j=0; j<obj_buffer->size;++j) {
542                    if(j%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
543                    for(k=0;k < obj_buffer->num_elements;++k)
544                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx   ",*((unsigned char *)(mapped_buffer+obj_buffer->num_elements*j+k)));
545                }
546                psb_buffer_unmap(obj_buffer->psb_buffer);
547                break;
548
549            case  VASliceDataBufferType:
550                fprintf(psb_video_debug_dump_buffer_fp,"first 256 bytes:\n");
551                psb_buffer_map(obj_buffer->psb_buffer, &mapped_buffer);
552                for(j=0; j<256;++j) {
553                    if(j%16 == 0) fprintf(psb_video_debug_dump_buffer_fp,"\n");
554                    for(k=0;k < obj_buffer->num_elements;++k)
555                        fprintf(psb_video_debug_dump_buffer_fp,"0x%02lx   ",*((unsigned char *)(mapped_buffer+obj_buffer->num_elements*j+k)));
556                }
557                psb_buffer_unmap(obj_buffer->psb_buffer);
558                break;
559            default:
560                break;
561
562            }
563        fprintf(psb_video_debug_dump_buffer_fp, "\n");
564        fflush(psb_video_debug_dump_buffer_fp);
565        fsync(fileno(psb_video_debug_dump_buffer_fp));
566    }
567
568}
569
570void psb__information_message(const char *msg, ...)
571{
572    if (psb_video_debug_fp) {
573        va_list args;
574        char tag[128];
575
576        (void)tag;
577
578        fprintf(psb_video_debug_fp, "[0x%08lx]psb_drv_video(%d:0x%08lx) ",
579                GetTickCount(), getpid(), pthread_self());
580        va_start(args, msg);
581        vfprintf(psb_video_debug_fp, msg, args);
582#ifdef ANDROID
583        sprintf(tag, "pvr_drv_video[%d:0x%08lx]", getpid(), pthread_self());
584        __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, args);
585#endif
586        va_end(args);
587        fflush(psb_video_debug_fp);
588        fsync(fileno(psb_video_debug_fp));
589    }
590}
591
592
593static void psb__open_log(void)
594{
595    char log_fn[1024];
596    unsigned int suffix;
597#ifdef ANDROID
598	LOGD("psb__open_log.\n");
599#endif
600    if(psb_parse_config("PSB_VIDEO_DEBUG_DUMP_BUFFER", &log_fn[0]) == 0) {
601
602        unsigned int suffix = 0xffff & ((unsigned int)time(NULL));
603        if(strcmp(log_fn, "/dev/stdout") != 0)
604        sprintf(log_fn + strlen(log_fn), ".%d", suffix);
605        psb_video_debug_dump_buffer_fp = fopen(log_fn, "w");
606    }
607
608    if(psb_parse_config("PSB_VIDEO_DEBUG_NV_BUFFER", &log_fn[0]) == 0) {
609        unsigned int suffix = 0xffff & ((unsigned int)time(NULL));
610        if(strcmp(log_fn, "/dev/stdout") != 0)
611        sprintf(log_fn + strlen(log_fn), ".%d", suffix);
612        psb_video_debug_nv_buffer_fp = fopen(log_fn, "ab");
613    }
614
615    if ((psb_video_debug_fp != NULL) && (psb_video_debug_fp != stderr)) {
616        debug_fp_count++;
617        return;
618    }
619
620    if (psb_parse_config("PSB_VIDEO_DEBUG", &log_fn[0]) != 0)
621        return;
622
623    suffix = 0xffff & ((unsigned int)time(NULL));
624    snprintf(log_fn + strnlen(log_fn, 1024),
625             (1024 - 8 - strnlen(log_fn, 1024)),
626             ".%d.%d", getpid(), suffix);
627    psb_video_debug_fp = fopen(log_fn, "w");
628    if (psb_video_debug_fp == 0) {
629        psb__error_message("Log file %s open failed, reason %s, fall back to stderr\n",
630                           log_fn, strerror(errno));
631        psb_video_debug_fp = stderr;
632    } else {
633        psb__information_message("Log file %s open successfully\n", log_fn);
634        debug_fp_count++;
635    }
636}
637
638static void psb__close_log(void)
639{
640    if ((psb_video_debug_fp != NULL) & (psb_video_debug_fp != stderr)) {
641        debug_fp_count--;
642        if (debug_fp_count == 0)
643            fclose(psb_video_debug_fp);
644    }
645
646    if(psb_video_debug_nv_buffer_fp !=NULL)
647        fclose(psb_video_debug_nv_buffer_fp);
648
649    return;
650}
651
652void psb__dump_NV_buffers(
653    object_surface_p obj_surface,
654    short srcx,
655    short srcy,
656    unsigned short srcw,
657    unsigned short srch)
658{
659    void *mapped_buffer;
660    void *mapped_buffer1, *mapped_buffer2;
661    if (psb_video_debug_nv_buffer_fp) {
662        psb_buffer_map(&obj_surface->psb_surface->buf, &mapped_buffer);
663
664        int j,k;
665        mapped_buffer1 = mapped_buffer +obj_surface->psb_surface->stride * srcy;
666        mapped_buffer2= mapped_buffer + obj_surface->psb_surface->stride * (obj_surface->height + srcy / 2);
667        mapped_buffer=mapped_buffer2;
668        for(j = 0; j < srch; ++j)
669        {
670            fwrite(mapped_buffer1,  srcw, 1, psb_video_debug_nv_buffer_fp);
671            mapped_buffer1 += obj_surface->psb_surface->stride;
672        }
673        for(j = 0 ; j < srch /2; ++j)
674        {
675            for(k = 0; k < srcw; ++k)
676            {
677                if((k%2) == 0)fwrite(mapped_buffer2,1,1,psb_video_debug_nv_buffer_fp);
678                mapped_buffer2++;
679            }
680            mapped_buffer2 += obj_surface->psb_surface->stride-srcw;
681        }
682        mapped_buffer2=mapped_buffer;
683        for(j = 0 ; j < srch /2; ++j)
684        {
685            for(k = 0; k < srcw; ++k)
686            {
687                if((k%2) == 1)fwrite(mapped_buffer2,1,1,psb_video_debug_nv_buffer_fp);
688                mapped_buffer2++;
689            }
690            mapped_buffer2 += obj_surface->psb_surface->stride-srcw;
691        }
692        psb_buffer_unmap(&obj_surface->psb_surface->buf);
693    }
694}
695
696#ifdef DEBUG_TRACE
697void psb__trace_message(const char *msg, ...)
698{
699    va_list args;
700    static const char *trace_file = 0;
701    static FILE *trace = 0;
702
703    if (!trace_file) {
704        char trace_fn[1024];
705
706        if (psb_parse_config("PSB_VIDEO_TRACE", &trace_fn[0]) == 0)
707            trace_file = trace_fn;
708
709        if (trace_file) {
710            trace = fopen(trace_file, "w");
711            if (trace) {
712                time_t curtime;
713                time(&curtime);
714                fprintf(trace, "---- %s\n---- Start Trace ----\n", ctime(&curtime));
715            }
716        } else {
717            trace_file = "none";
718        }
719    }
720    if (trace) {
721        if (msg) {
722            va_start(args, msg);
723            vfprintf(trace, msg, args);
724            va_end(args);
725        } else {
726            fflush(trace);
727        }
728    }
729}
730#endif
731
732VAStatus psb_QueryConfigProfiles(
733    VADriverContextP ctx,
734    VAProfile *profile_list,    /* out */
735    int *num_profiles            /* out */
736)
737{
738    (void) ctx; /* unused */
739    int i = 0;
740    VAStatus vaStatus = VA_STATUS_SUCCESS;
741    INIT_DRIVER_DATA
742
743    if (NULL == profile_list) {
744        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
745        DEBUG_FAILURE;
746        return vaStatus;
747    }
748    if (NULL == num_profiles) {
749        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
750        DEBUG_FAILURE;
751        return vaStatus;
752    }
753
754//    profile_list[i++] = VAProfileMPEG2Simple;
755    profile_list[i++] = VAProfileMPEG2Main;
756    profile_list[i++] = VAProfileMPEG4Simple;
757    profile_list[i++] = VAProfileMPEG4AdvancedSimple;
758//    profile_list[i++] = VAProfileMPEG4Main;
759    profile_list[i++] = VAProfileH264Baseline;
760    profile_list[i++] = VAProfileH264Main;
761    profile_list[i++] = VAProfileH264High;
762    profile_list[i++] = VAProfileVC1Simple;
763    profile_list[i++] = VAProfileVC1Main;
764    profile_list[i++] = VAProfileVC1Advanced;
765
766    if (IS_MFLD(driver_data)) {
767        profile_list[i++] = VAProfileH263Baseline;
768        profile_list[i++] = VAProfileJPEGBaseline;
769    } else if (IS_MRST(driver_data))
770        profile_list[i++] = VAProfileH263Baseline;
771    profile_list[i++] = VAProfileH264ConstrainedBaseline;
772
773    /* If the assert fails then PSB_MAX_PROFILES needs to be bigger */
774    ASSERT(i <= PSB_MAX_PROFILES);
775    *num_profiles = i;
776
777    return VA_STATUS_SUCCESS;
778}
779
780
781VAStatus psb_QueryConfigEntrypoints(
782    VADriverContextP ctx,
783    VAProfile profile,
784    VAEntrypoint  *entrypoint_list,    /* out */
785    int *num_entrypoints        /* out */
786)
787{
788    INIT_DRIVER_DATA
789    VAStatus vaStatus = VA_STATUS_SUCCESS;
790    int entrypoints = 0;
791    int i;
792
793    if (NULL == entrypoint_list) {
794        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
795        DEBUG_FAILURE;
796        return vaStatus;
797    }
798    if (NULL == num_entrypoints || profile >= PSB_MAX_PROFILES) {
799        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
800        DEBUG_FAILURE;
801        return vaStatus;
802    }
803
804    for (i = 0; i < PSB_MAX_ENTRYPOINTS; i++) {
805        if (driver_data->profile2Format[profile][i]) {
806            entrypoints++;
807            *entrypoint_list++ = i;
808        }
809    }
810
811    /* If the assert fails then PSB_MAX_ENTRYPOINTS needs to be bigger */
812    ASSERT(entrypoints <= PSB_MAX_ENTRYPOINTS);
813
814    if (0 == entrypoints) {
815        return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
816    }
817
818    *num_entrypoints = entrypoints;
819    return VA_STATUS_SUCCESS;
820}
821
822/*
823 * Figure out if we should return VA_STATUS_ERROR_UNSUPPORTED_PROFILE
824 * or VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT
825 */
826static VAStatus psb__error_unsupported_profile_entrypoint(psb_driver_data_p driver_data, VAProfile profile, VAEntrypoint entrypoint)
827{
828    /* Does the driver support _any_ entrypoint for this profile? */
829    if (profile < PSB_MAX_PROFILES) {
830        int i;
831
832        for (i = 0; i < PSB_MAX_ENTRYPOINTS; i++) {
833            if (driver_data->profile2Format[profile][i]) {
834                /* There is an entrypoint, so the profile is supported */
835                return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
836            }
837        }
838    }
839    return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
840}
841
842VAStatus psb_GetConfigAttributes(
843    VADriverContextP ctx,
844    VAProfile profile,
845    VAEntrypoint entrypoint,
846    VAConfigAttrib *attrib_list,    /* in/out */
847    int num_attribs
848)
849{
850    INIT_DRIVER_DATA
851    INIT_FORMAT_VTABLE
852    int i;
853    VAStatus vaStatus = VA_STATUS_SUCCESS;
854    if (NULL == format_vtable) {
855        return psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint);
856    }
857    if (NULL == attrib_list) {
858        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
859        DEBUG_FAILURE;
860        return vaStatus;
861    }
862    if (num_attribs <= 0) {
863        return VA_STATUS_ERROR_INVALID_PARAMETER;
864    }
865
866    /* Generic attributes */
867    for (i = 0; i < num_attribs; i++) {
868        switch (attrib_list[i].type) {
869        case VAConfigAttribRTFormat:
870            attrib_list[i].value = VA_RT_FORMAT_YUV420;
871            if (entrypoint == VAEntrypointEncPicture)
872                attrib_list[i].value |= VA_RT_FORMAT_YUV422;
873            break;
874
875        default:
876            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
877            break;
878        }
879    }
880    /* format specific attributes */
881    format_vtable->queryConfigAttributes(profile, entrypoint, attrib_list, num_attribs);
882
883    return VA_STATUS_SUCCESS;
884}
885
886static VAStatus psb__update_attribute(object_config_p obj_config, VAConfigAttrib *attrib)
887{
888    int i;
889    /* Check existing attributes */
890    for (i = 0; i < obj_config->attrib_count; i++) {
891        if (obj_config->attrib_list[i].type == attrib->type) {
892            /* Update existing attribute */
893            obj_config->attrib_list[i].value = attrib->value;
894            return VA_STATUS_SUCCESS;
895        }
896    }
897    if (obj_config->attrib_count < PSB_MAX_CONFIG_ATTRIBUTES) {
898        i = obj_config->attrib_count;
899        obj_config->attrib_list[i].type = attrib->type;
900        obj_config->attrib_list[i].value = attrib->value;
901        obj_config->attrib_count++;
902        return VA_STATUS_SUCCESS;
903    }
904    return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
905}
906
907static VAStatus psb__validate_config(object_config_p obj_config)
908{
909    int i;
910    /* Check all attributes */
911    for (i = 0; i < obj_config->attrib_count; i++) {
912        switch (obj_config->attrib_list[i].type) {
913        case VAConfigAttribRTFormat:
914            if (!(obj_config->attrib_list[i].value == VA_RT_FORMAT_YUV420
915                  || (obj_config->attrib_list[i].value == VA_RT_FORMAT_YUV422 &&
916                      obj_config->entrypoint == VAEntrypointEncPicture))) {
917                return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
918            }
919            break;
920
921        default:
922            /*
923             * Ignore unknown attributes here, it
924             * may be format specific.
925             */
926            break;
927        }
928    }
929    return VA_STATUS_SUCCESS;
930}
931
932static int psb_get_active_entrypoint_number(
933    VADriverContextP ctx,
934    unsigned int entrypoint)
935{
936    INIT_DRIVER_DATA;
937    struct drm_lnc_video_getparam_arg arg;
938    int count = 0;
939    int ret;
940
941    if (VAEntrypointVLD > entrypoint ||
942        entrypoint > VAEntrypointEncPicture) {
943        psb__error_message("%s :Invalid entrypoint %d.\n",
944                           __FUNCTION__, entrypoint);
945        return -1;
946    }
947
948    arg.key = PNW_VIDEO_QUERY_ENTRY;
949    arg.value = (uint64_t)((unsigned long) &count);
950    arg.arg = (uint64_t)((unsigned int)&entrypoint);
951    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
952                              &arg, sizeof(arg));
953    if (ret) {
954        psb__error_message("%s drmCommandWriteRead fails %d.\n",
955                           __FUNCTION__, ret);
956        return -1;
957    }
958
959    return count;
960}
961
962VAStatus psb_CreateConfig(
963    VADriverContextP ctx,
964    VAProfile profile,
965    VAEntrypoint entrypoint,
966    VAConfigAttrib *attrib_list,
967    int num_attribs,
968    VAConfigID *config_id        /* out */
969)
970{
971    INIT_DRIVER_DATA
972    INIT_FORMAT_VTABLE
973    VAStatus vaStatus = VA_STATUS_SUCCESS;
974    int configID;
975    object_config_p obj_config;
976    int i;
977
978    /*echo 8 > /sys/module/pvrsrvkm/parameters/no_ec will disable error concealment*/
979    if ((profile == VAProfileH264ConstrainedBaseline) && (VAEntrypointVLD == entrypoint)) {
980        char ec_disable[2];
981        FILE *ec_fp = fopen("/sys/module/pvrsrvkm/parameters/no_ec", "r");
982        if (ec_fp) {
983            if (fgets(ec_disable, 2, ec_fp) != NULL) {
984                /* force profile to VAProfileH264High */
985                if (strcmp(ec_disable, "8") == 0) {
986                    psb__information_message("disabled error concealment by setting profile to VAProfileH264High\n");
987                    profile = VAProfileH264High;
988                }
989            }
990            fclose(ec_fp);
991        }
992    }
993
994    if (NULL == config_id) {
995        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
996        return vaStatus;
997    }
998
999    if (num_attribs < 0) {
1000        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1001    }
1002
1003    if (NULL == attrib_list) {
1004        vaStatus =  VA_STATUS_ERROR_INVALID_PARAMETER;
1005        return vaStatus;
1006    }
1007
1008    if (NULL == format_vtable) {
1009        vaStatus = psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint);
1010    }
1011
1012    if (VA_STATUS_SUCCESS != vaStatus) {
1013        return vaStatus;
1014    }
1015
1016    if ((IS_MFLD(driver_data)) &&
1017        ((VAEntrypointEncPicture == entrypoint)
1018	|| (VAEntrypointEncSlice == entrypoint))) {
1019	int active_slc, active_pic;
1020        /* Only allow one encoding entrypoint at the sametime.
1021	 * But if video encoding request comes when process JPEG encoding,
1022	 * it will wait until current JPEG picture encoding finish.
1023	 * Further JPEG encoding should fall back to software path.*/
1024	active_slc = psb_get_active_entrypoint_number(ctx, VAEntrypointEncSlice);
1025	active_pic = psb_get_active_entrypoint_number(ctx, VAEntrypointEncPicture);
1026
1027	if (active_slc > 0) {
1028	    psb__error_message("There already is a active video encoding entrypoint."
1029		   "Entrypoint %d isn't available.\n", entrypoint);
1030	    return VA_STATUS_ERROR_HW_BUSY;
1031	}
1032	else if (active_pic > 0 && VAEntrypointEncPicture == entrypoint) {
1033	    psb__error_message("There already is a active picture encoding entrypoint."
1034		   "Entrypoint %d isn't available.\n", entrypoint);
1035	    return VA_STATUS_ERROR_HW_BUSY;
1036	}
1037    }
1038
1039    configID = object_heap_allocate(&driver_data->config_heap);
1040    obj_config = CONFIG(configID);
1041    if (NULL == obj_config) {
1042        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1043        return vaStatus;
1044    }
1045
1046
1047    MEMSET_OBJECT(obj_config, struct object_config_s);
1048
1049    obj_config->profile = profile;
1050    obj_config->format_vtable = format_vtable;
1051    obj_config->entrypoint = entrypoint;
1052    obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
1053    obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
1054    obj_config->attrib_count = 1;
1055
1056    for (i = 0; i < num_attribs; i++) {
1057        if (attrib_list[i].type > VAConfigAttribRateControl)
1058            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
1059
1060        vaStatus = psb__update_attribute(obj_config, &(attrib_list[i]));
1061        if (VA_STATUS_SUCCESS != vaStatus) {
1062            break;
1063        }
1064    }
1065
1066    if (VA_STATUS_SUCCESS == vaStatus) {
1067        vaStatus = psb__validate_config(obj_config);
1068    }
1069
1070    if (VA_STATUS_SUCCESS == vaStatus) {
1071        vaStatus = format_vtable->validateConfig(obj_config);
1072    }
1073
1074    /* Error recovery */
1075    if (VA_STATUS_SUCCESS != vaStatus) {
1076        object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
1077    } else {
1078        *config_id = configID;
1079    }
1080
1081    /* only VAProfileH264ConstrainedBaseline profile enable error concealment*/
1082    if (IS_MRST(driver_data) &&
1083        (getenv("PSB_VIDEO_NOEC") == NULL)
1084        && (profile == VAProfileH264ConstrainedBaseline)) {
1085        psb__information_message("profile is VAProfileH264ConstrainedBaseline, error concealment is enabled. \n");
1086        driver_data->ec_enabled = 1;
1087#ifdef MFLD_ERROR_CONCEALMENT
1088    } else if(IS_MFLD(driver_data) &&
1089        (getenv("PSB_VIDEO_NOEC") == NULL)
1090        && (profile == VAProfileH264ConstrainedBaseline)) {
1091        psb__information_message("profile is VAProfileH264ConstrainedBaseline, error concealment is enabled. \n");
1092        driver_data->ec_enabled = 1;
1093#endif
1094    } else {
1095        driver_data->ec_enabled = 0;
1096    }
1097    return vaStatus;
1098}
1099
1100VAStatus psb_DestroyConfig(
1101    VADriverContextP ctx,
1102    VAConfigID config_id
1103)
1104{
1105    INIT_DRIVER_DATA
1106    VAStatus vaStatus = VA_STATUS_SUCCESS;
1107    object_config_p obj_config;
1108
1109    obj_config = CONFIG(config_id);
1110    if (NULL == obj_config) {
1111        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1112        DEBUG_FAILURE;
1113        return vaStatus;
1114    }
1115
1116    object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
1117    return vaStatus;
1118}
1119
1120VAStatus psb_QueryConfigAttributes(
1121    VADriverContextP ctx,
1122    VAConfigID config_id,
1123    VAProfile *profile,        /* out */
1124    VAEntrypoint *entrypoint,     /* out */
1125    VAConfigAttrib *attrib_list,    /* out */
1126    int *num_attribs        /* out */
1127)
1128{
1129    INIT_DRIVER_DATA
1130    VAStatus vaStatus = VA_STATUS_SUCCESS;
1131    object_config_p obj_config;
1132    int i;
1133
1134    if (NULL == profile) {
1135        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1136        DEBUG_FAILURE;
1137        return vaStatus;
1138    }
1139    if (NULL == entrypoint) {
1140        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1141        DEBUG_FAILURE;
1142        return vaStatus;
1143    }
1144    if (NULL == attrib_list) {
1145        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1146        DEBUG_FAILURE;
1147        return vaStatus;
1148    }
1149    if (NULL == num_attribs) {
1150        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1151        DEBUG_FAILURE;
1152        return vaStatus;
1153    }
1154    obj_config = CONFIG(config_id);
1155    if (NULL == obj_config) {
1156        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1157        DEBUG_FAILURE;
1158        return vaStatus;
1159    }
1160
1161    *profile = obj_config->profile;
1162    *entrypoint = obj_config->entrypoint;
1163    *num_attribs =  obj_config->attrib_count;
1164    for (i = 0; i < obj_config->attrib_count; i++) {
1165        attrib_list[i] = obj_config->attrib_list[i];
1166    }
1167
1168    return vaStatus;
1169}
1170
1171static void psb__destroy_surface(psb_driver_data_p driver_data, object_surface_p obj_surface)
1172{
1173    if (NULL != obj_surface) {
1174        /* delete subpicture association */
1175        psb_SurfaceDeassociateSubpict(driver_data, obj_surface);
1176
1177	psb_surface_sync(obj_surface->psb_surface);
1178        psb_surface_destroy(obj_surface->psb_surface);
1179
1180        if (obj_surface->psb_surface_rotate) {
1181            psb_surface_destroy(obj_surface->psb_surface_rotate);
1182        }
1183
1184        free(obj_surface->psb_surface);
1185        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
1186    }
1187}
1188
1189static
1190VAStatus psb__checkSurfaceDimensions(psb_driver_data_p driver_data, int width, int height)
1191{
1192    if (driver_data->video_sd_disabled) {
1193        return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1194    }
1195    if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) {
1196        return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1197    }
1198    if (driver_data->video_hd_disabled) {
1199        if ((width > 1024) || (height > 576)) {
1200            return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1201        }
1202    }
1203
1204    return VA_STATUS_SUCCESS;
1205}
1206
1207
1208VAStatus psb_CreateSurfaces(
1209    VADriverContextP ctx,
1210    int width,
1211    int height,
1212    int format,
1213    int num_surfaces,
1214    VASurfaceID *surface_list,        /* out */
1215    VASurfaceAttrib *attrib_list,
1216    int num_attribs
1217)
1218{
1219    INIT_DRIVER_DATA
1220    VAStatus vaStatus = VA_STATUS_SUCCESS;
1221    int i, height_origin, usage, buffer_stride = 0;
1222    int protected = (VA_RT_FORMAT_PROTECTED & format);
1223    unsigned long fourcc;
1224    VAExternalMemoryBuffers *external_buffers = NULL;
1225    buffer_handle_t handle;
1226    void *vaddr[2];
1227    unsigned int *tmp_khandles = NULL;
1228
1229    format = format & (~VA_RT_FORMAT_PROTECTED);
1230    if (num_surfaces <= 0) {
1231        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1232        DEBUG_FAILURE;
1233        return vaStatus;
1234    }
1235    if (NULL == surface_list) {
1236        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1237        DEBUG_FAILURE;
1238        return vaStatus;
1239    }
1240
1241    if ((attrib_list != NULL) && (num_attribs > 0)) {
1242        for (i = 0; i < num_attribs; i++, attrib_list++) {
1243            if (!attrib_list)
1244                return VA_STATUS_ERROR_INVALID_PARAMETER;
1245            switch (attrib_list->type) {
1246            case VASurfaceAttribNativeHandle:
1247                if (external_buffers != NULL) {
1248                    //only support one VASurfaceAttribNativeHandle attribute
1249                    continue;
1250                } else if (attrib_list->value.type == VAGenericValueTypePointer) {
1251                    external_buffers = (VAExternalMemoryBuffers *)attrib_list->value.value.p_val;
1252                } else {
1253                    return VA_STATUS_ERROR_INVALID_PARAMETER;
1254                }
1255                break;
1256            default:
1257                psb__error_message("Unsupported attribute.\n");
1258                return VA_STATUS_ERROR_INVALID_PARAMETER;
1259            }
1260        }
1261    }
1262
1263    /* We only support one format */
1264    if ((VA_RT_FORMAT_YUV420 != format)
1265        && (VA_RT_FORMAT_YUV422 != format)) {
1266        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
1267        DEBUG_FAILURE;
1268        return vaStatus;
1269    }
1270
1271    /* the pixel_format also can only be NV12 */
1272    if (external_buffers && (HAL_PIXEL_FORMAT_NV12_VED != external_buffers->pixel_format)) {
1273        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
1274        DEBUG_FAILURE;
1275        return vaStatus;
1276    }
1277    if (external_buffers)
1278        driver_data->native_window = external_buffers->native_window;
1279
1280    vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
1281    if (VA_STATUS_SUCCESS != vaStatus) {
1282        DEBUG_FAILURE;
1283        return vaStatus;
1284    }
1285
1286    /* Adjust height to be a multiple of 32 (height of macroblock in interlaced mode) */
1287    height_origin = height;
1288    height = (height + 0x1f) & ~0x1f;
1289
1290    if(external_buffers != NULL) {
1291        int size = num_surfaces * sizeof(unsigned int);
1292
1293        tmp_khandles = calloc(1, size);
1294        if (tmp_khandles == NULL) {
1295            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1296            DEBUG_FAILURE;
1297            return vaStatus;
1298        }
1299    }
1300
1301    for (i = 0; i < num_surfaces; i++) {
1302        int surfaceID;
1303        object_surface_p obj_surface;
1304        psb_surface_p psb_surface;
1305
1306        surfaceID = object_heap_allocate(&driver_data->surface_heap);
1307        obj_surface = SURFACE(surfaceID);
1308        if (NULL == obj_surface) {
1309            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1310            DEBUG_FAILURE;
1311            break;
1312        }
1313        MEMSET_OBJECT(obj_surface, struct object_surface_s);
1314
1315        obj_surface->surface_id = surfaceID;
1316        surface_list[i] = surfaceID;
1317        obj_surface->context_id = -1;
1318        obj_surface->width = width;
1319        obj_surface->height = height;
1320        obj_surface->width_r = width;
1321        obj_surface->height_r = height;
1322        obj_surface->height_origin = height_origin;
1323
1324        psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
1325        if (NULL == psb_surface) {
1326            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
1327            obj_surface->surface_id = VA_INVALID_SURFACE;
1328
1329            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1330
1331            DEBUG_FAILURE;
1332            break;
1333        }
1334
1335        switch (format) {
1336        case VA_RT_FORMAT_YUV422:
1337            fourcc = VA_FOURCC_YV16;
1338            break;
1339        case VA_RT_FORMAT_YUV420:
1340        default:
1341            fourcc = VA_FOURCC_NV12;
1342            break;
1343        }
1344        if (external_buffers != NULL) {
1345            switch (external_buffers->type) {
1346            case VAExternalMemoryAndroidGrallocBuffer:
1347                /*hard code the gralloc buffer usage*/
1348                usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
1349                handle = (buffer_handle_t)external_buffers->buffers[i];
1350                if (gralloc_lock(handle, usage, 0, 0, width, height, (void **)&vaddr)) {
1351                    vaStatus = VA_STATUS_ERROR_UNKNOWN;
1352                } else {
1353                    vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
1354                        external_buffers, psb_surface, vaddr[0]);
1355                    psb_surface->buf.handle = handle;
1356                    obj_surface->share_info = (psb_surface_share_info_t *)vaddr[1];
1357                    memset(obj_surface->share_info, 0, sizeof(struct psb_surface_share_info_s));
1358                    obj_surface->share_info->force_output_method = protected ? OUTPUT_FORCE_OVERLAY : 0;
1359                    obj_surface->share_info->width = obj_surface->width;
1360                    obj_surface->share_info->height = obj_surface->height;
1361
1362                    obj_surface->share_info->luma_stride = psb_surface->stride;
1363                    obj_surface->share_info->chroma_u_stride = psb_surface->stride;
1364                    obj_surface->share_info->chroma_v_stride = psb_surface->stride;
1365                    obj_surface->share_info->format = VA_FOURCC_NV12;
1366
1367                    obj_surface->share_info->khandle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
1368                    obj_surface->share_info->khandles_count = num_surfaces;
1369                    tmp_khandles[i] = obj_surface->share_info->khandle;
1370
1371                    obj_surface->share_info->renderStatus = 0;
1372
1373                    psb__information_message("%s : Create graphic buffer success"
1374                         "surface_id= 0x%x, vaddr[0] (0x%x), vaddr[1] (0x%x)\n", __FUNCTION__, surfaceID, vaddr[0], vaddr[1]);
1375                    gralloc_unlock(handle);
1376                }
1377                break;
1378            default:
1379                psb__error_message("Unsupported external buffer.\n");
1380            }
1381        } else {
1382            vaStatus = psb_surface_create(driver_data, width, height, fourcc,
1383            protected, psb_surface);
1384        }
1385        if (VA_STATUS_SUCCESS != vaStatus) {
1386            free(psb_surface);
1387            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
1388            obj_surface->surface_id = VA_INVALID_SURFACE;
1389
1390            DEBUG_FAILURE;
1391            break;
1392        }
1393        buffer_stride = psb_surface->stride;
1394        /* by default, surface fourcc is NV12 */
1395        psb_surface->extra_info[4] = fourcc;
1396        obj_surface->psb_surface = psb_surface;
1397    }
1398
1399    /* Error recovery */
1400    if (VA_STATUS_SUCCESS != vaStatus) {
1401        /* surface_list[i-1] was the last successful allocation */
1402        for (; i--;) {
1403            object_surface_p obj_surface = SURFACE(surface_list[i]);
1404            psb__destroy_surface(driver_data, obj_surface);
1405            surface_list[i] = VA_INVALID_SURFACE;
1406        }
1407        psb__error_message("CreateSurfaces failed\n");
1408        return vaStatus;
1409    }
1410
1411    if (VA_STATUS_SUCCESS == vaStatus && external_buffers != NULL) {
1412        int max_num_to_copy = num_surfaces;
1413        if(max_num_to_copy >  MAX_SHARE_INFO_KHANDLES) {
1414            max_num_to_copy = MAX_SHARE_INFO_KHANDLES;
1415        }
1416        for (i = 0; i < num_surfaces; i++) {
1417            object_surface_p obj_surface = SURFACE(surface_list[i]);
1418            memcpy(obj_surface->share_info->khandles, tmp_khandles,
1419                   sizeof(unsigned int) * max_num_to_copy);
1420        }
1421    }
1422
1423    if (tmp_khandles != NULL)
1424        free(tmp_khandles);
1425
1426    if (fourcc == VA_FOURCC_NV12)
1427        psb_add_video_bcd(ctx, width, height, buffer_stride,
1428                          num_surfaces, surface_list);
1429    return vaStatus;
1430}
1431
1432
1433VAStatus psb_CreateSurfaceFromCIFrame(
1434    VADriverContextP ctx,
1435    unsigned long frame_id,
1436    VASurfaceID *surface        /* out */
1437)
1438{
1439    INIT_DRIVER_DATA
1440    VAStatus vaStatus = VA_STATUS_SUCCESS;
1441    int surfaceID;
1442    object_surface_p obj_surface;
1443    psb_surface_p psb_surface;
1444    struct ci_frame_info frame_info;
1445    int ret = 0, fd = -1;
1446    char *camera_dev = NULL;
1447
1448    if (IS_MRST(driver_data) == 0)
1449        return VA_STATUS_ERROR_UNKNOWN;
1450
1451    camera_dev = getenv("PSB_VIDEO_CAMERA_DEVNAME");
1452
1453    if (camera_dev)
1454        fd = open_device(camera_dev);
1455    else
1456        fd = open_device("/dev/video0");
1457    if (fd == -1)
1458        return  VA_STATUS_ERROR_UNKNOWN;
1459
1460    frame_info.frame_id = frame_id;
1461    ret = ci_get_frame_info(fd, &frame_info);
1462    close_device(fd);
1463
1464    if (ret != 0)
1465        return  VA_STATUS_ERROR_UNKNOWN;
1466
1467    psb__information_message("CI Frame: id=0x%08x, %dx%d, stride=%d, offset=0x%08x, fourcc=0x%08x\n",
1468                             frame_info.frame_id, frame_info.width, frame_info.height,
1469                             frame_info.stride, frame_info.offset, frame_info.fourcc);
1470
1471    if (frame_info.stride & 0x3f) {
1472        psb__error_message("CI Frame must be 64byte aligned!\n");
1473        /* return  VA_STATUS_ERROR_UNKNOWN; */
1474    }
1475
1476    if (frame_info.fourcc != VA_FOURCC_NV12) {
1477        psb__error_message("CI Frame must be NV12 format!\n");
1478        return  VA_STATUS_ERROR_UNKNOWN;
1479    }
1480    if (frame_info.offset & 0xfff) {
1481        psb__error_message("CI Frame offset must be page aligned!\n");
1482        /* return  VA_STATUS_ERROR_UNKNOWN; */
1483    }
1484
1485    /* all sanity check passed */
1486    surfaceID = object_heap_allocate(&driver_data->surface_heap);
1487    obj_surface = SURFACE(surfaceID);
1488    if (NULL == obj_surface) {
1489        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1490        DEBUG_FAILURE;
1491        return vaStatus;
1492    }
1493
1494    MEMSET_OBJECT(obj_surface, struct object_surface_s);
1495
1496    obj_surface->surface_id = surfaceID;
1497    *surface = surfaceID;
1498    obj_surface->context_id = -1;
1499    obj_surface->width = frame_info.width;
1500    obj_surface->height = frame_info.height;
1501
1502    psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
1503    if (NULL == psb_surface) {
1504        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
1505        obj_surface->surface_id = VA_INVALID_SURFACE;
1506
1507        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1508
1509        DEBUG_FAILURE;
1510
1511        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
1512        obj_surface->surface_id = VA_INVALID_SURFACE;
1513
1514        return vaStatus;
1515    }
1516
1517    vaStatus = psb_surface_create_camera(driver_data, frame_info.width, frame_info.height,
1518                                         frame_info.stride, frame_info.stride * frame_info.height,
1519                                         psb_surface,
1520                                         0, /* not V4L2 */
1521                                         frame_info.offset);
1522    if (VA_STATUS_SUCCESS != vaStatus) {
1523        free(psb_surface);
1524        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
1525        obj_surface->surface_id = VA_INVALID_SURFACE;
1526
1527        DEBUG_FAILURE;
1528
1529        return vaStatus;
1530    }
1531
1532    memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
1533    psb_surface->extra_info[4] = VA_FOURCC_NV12;
1534
1535    obj_surface->psb_surface = psb_surface;
1536
1537    /* Error recovery */
1538    if (VA_STATUS_SUCCESS != vaStatus) {
1539        object_surface_p obj_surface = SURFACE(*surface);
1540        psb__destroy_surface(driver_data, obj_surface);
1541        *surface = VA_INVALID_SURFACE;
1542    }
1543
1544    return vaStatus;
1545}
1546
1547VAStatus psb_DestroySurfaces(
1548    VADriverContextP ctx,
1549    VASurfaceID *surface_list,
1550    int num_surfaces
1551)
1552{
1553    INIT_DRIVER_DATA
1554    int i;
1555
1556    if (num_surfaces <= 0) {
1557        return VA_STATUS_ERROR_INVALID_PARAMETER;
1558    }
1559
1560    if (NULL == surface_list) {
1561        /* This is a workaround for bug 3419. If libva surfaces and context are pre-allocated,
1562         * mix call the function with NULL & 0 parameters to notify video driver when decoder is destroyed.
1563         */
1564#ifdef ANDROID
1565#include "android/psb_android_glue.h"
1566        if (driver_data->ts_source_created) {
1567            psb__information_message("In psb_release_video_bcd, call psb_android_texture_streaming_destroy to destroy texture streaming source.\n");
1568            psb_android_texture_streaming_destroy();
1569            driver_data->ts_source_created = 0;
1570        }
1571#endif
1572        return VA_STATUS_ERROR_INVALID_SURFACE;
1573    }
1574
1575    if (driver_data->bcd_registered != 0)
1576        if (VA_STATUS_SUCCESS != psb_release_video_bcd(ctx))
1577            return VA_STATUS_ERROR_UNKNOWN;
1578
1579    /* Free PVR2D buffer wrapped from the surfaces */
1580    psb_free_surface_pvr2dbuf(driver_data);
1581
1582    /* Make validation happy */
1583    for (i = 0; i < num_surfaces; i++) {
1584        object_surface_p obj_surface = SURFACE(surface_list[i]);
1585        if (obj_surface == NULL) {
1586            return VA_STATUS_ERROR_INVALID_SURFACE;
1587        }
1588        if (obj_surface->derived_imgcnt > 0) {
1589            psb__error_message("Some surface is deriving by images\n");
1590            return VA_STATUS_ERROR_OPERATION_FAILED;
1591        }
1592    }
1593
1594    for (i = 0; i < num_surfaces; i++) {
1595        object_surface_p obj_surface = SURFACE(surface_list[i]);
1596
1597        if (driver_data->cur_displaying_surface == surface_list[i]) {
1598            /* Surface is being displaying. Need to stop overlay here */
1599            psb_coverlay_stop(ctx);
1600        }
1601        psb__information_message("%s : obj_surface->surface_id = 0x%x\n",__FUNCTION__, obj_surface->surface_id);
1602        psb__destroy_surface(driver_data, obj_surface);
1603        surface_list[i] = VA_INVALID_SURFACE;
1604    }
1605
1606    return VA_STATUS_SUCCESS;
1607}
1608
1609int psb_new_context(psb_driver_data_p driver_data, int ctx_type)
1610{
1611    struct drm_lnc_video_getparam_arg arg;
1612    int ret = 0;
1613
1614    arg.key = IMG_VIDEO_NEW_CONTEXT;
1615    arg.value = (uint64_t)((unsigned long) & ctx_type);
1616    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
1617                              &arg, sizeof(arg));
1618    if (ret != 0)
1619        psb__error_message("Set context %d failed\n", ctx_type);
1620
1621    return ret;
1622}
1623
1624int psb_rm_context(psb_driver_data_p driver_data)
1625{
1626    struct drm_lnc_video_getparam_arg arg;
1627    int tmp;
1628    int ret = 0;
1629
1630    arg.key = IMG_VIDEO_RM_CONTEXT;
1631    arg.value = (uint64_t)((unsigned long) & tmp); /* value is ignored */
1632    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
1633                              &arg, sizeof(arg));
1634    if (ret != 0)
1635        psb__error_message("Remove context failed\n");
1636
1637    return ret;
1638}
1639
1640VAStatus psb_CreateContext(
1641    VADriverContextP ctx,
1642    VAConfigID config_id,
1643    int picture_width,
1644    int picture_height,
1645    int flag,
1646    VASurfaceID *render_targets,
1647    int num_render_targets,
1648    VAContextID *context        /* out */
1649)
1650{
1651    INIT_DRIVER_DATA
1652    VAStatus vaStatus = VA_STATUS_SUCCESS;
1653    object_config_p obj_config;
1654    int cmdbuf_num, encode = 0;
1655    int i;
1656
1657    if (num_render_targets <= 0) {
1658        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1659        DEBUG_FAILURE;
1660        return vaStatus;
1661    }
1662
1663    if (NULL == render_targets) {
1664        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1665        DEBUG_FAILURE;
1666        return vaStatus;
1667    }
1668    if (NULL == context) {
1669        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1670        DEBUG_FAILURE;
1671        return vaStatus;
1672    }
1673
1674    vaStatus = psb__checkSurfaceDimensions(driver_data, picture_width, picture_height);
1675    if (VA_STATUS_SUCCESS != vaStatus) {
1676        DEBUG_FAILURE;
1677        return vaStatus;
1678    }
1679
1680    obj_config = CONFIG(config_id);
1681    if (NULL == obj_config) {
1682        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1683        DEBUG_FAILURE;
1684        return vaStatus;
1685    }
1686
1687    int contextID = object_heap_allocate(&driver_data->context_heap);
1688    object_context_p obj_context = CONTEXT(contextID);
1689    if (NULL == obj_context) {
1690        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1691        DEBUG_FAILURE;
1692        return vaStatus;
1693    }
1694
1695    *context = contextID;
1696
1697    MEMSET_OBJECT(obj_context, struct object_context_s);
1698
1699    obj_context->driver_data = driver_data;
1700    obj_context->current_render_target = NULL;
1701    obj_context->is_oold = driver_data->is_oold;
1702    obj_context->context_id = contextID;
1703    obj_context->config_id = config_id;
1704    obj_context->picture_width = picture_width;
1705    obj_context->picture_height = picture_height;
1706    obj_context->num_render_targets = num_render_targets;
1707    obj_context->render_targets = (VASurfaceID *) calloc(1, num_render_targets * sizeof(VASurfaceID));
1708    if (obj_context->render_targets == NULL) {
1709        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1710        DEBUG_FAILURE;
1711
1712        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1713
1714        return vaStatus;
1715    }
1716
1717    /* allocate buffer points for vaRenderPicture */
1718    obj_context->num_buffers = 10;
1719    obj_context->buffer_list = (object_buffer_p *) calloc(1, sizeof(object_buffer_p) * obj_context->num_buffers);
1720    if (obj_context->buffer_list == NULL) {
1721        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1722        DEBUG_FAILURE;
1723
1724        free(obj_context->render_targets);
1725        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1726
1727        return vaStatus;
1728    }
1729
1730    memset(obj_context->buffers_unused, 0, sizeof(obj_context->buffers_unused));
1731    memset(obj_context->buffers_unused_count, 0, sizeof(obj_context->buffers_unused_count));
1732    memset(obj_context->buffers_unused_tail, 0, sizeof(obj_context->buffers_unused_tail));
1733    memset(obj_context->buffers_active, 0, sizeof(obj_context->buffers_active));
1734
1735    if (obj_config->entrypoint == VAEntrypointEncSlice
1736        || obj_config->entrypoint == VAEntrypointEncPicture) {
1737        encode = 1;
1738    }
1739
1740    if (encode)
1741        cmdbuf_num = LNC_MAX_CMDBUFS_ENCODE;
1742    else
1743        cmdbuf_num = PSB_MAX_CMDBUFS;
1744
1745    for (i = 0; i < num_render_targets; i++) {
1746        object_surface_p obj_surface = SURFACE(render_targets[i]);
1747        psb_surface_p psb_surface;
1748
1749        if (NULL == obj_surface) {
1750            vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1751            DEBUG_FAILURE;
1752            break;
1753        }
1754
1755        psb_surface = obj_surface->psb_surface;
1756
1757        /* Clear format specific surface info */
1758        obj_context->render_targets[i] = render_targets[i];
1759        obj_surface->context_id = contextID; /* Claim ownership of surface */
1760#if 0
1761        /* for decode, move the surface into |TT */
1762        if ((encode == 0) && /* decode */
1763            ((psb_surface->buf.pl_flags & DRM_PSB_FLAG_MEM_RAR) == 0)) /* surface not in RAR */
1764            psb_buffer_setstatus(&obj_surface->psb_surface->buf,
1765                                 WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED, DRM_PSB_FLAG_MEM_MMU);
1766#endif
1767    }
1768
1769    obj_context->va_flags = flag;
1770    obj_context->format_vtable = obj_config->format_vtable;
1771    obj_context->format_data = NULL;
1772
1773    if (VA_STATUS_SUCCESS == vaStatus) {
1774        vaStatus = obj_context->format_vtable->createContext(obj_context, obj_config);
1775    }
1776
1777    /* Error recovery */
1778    if (VA_STATUS_SUCCESS != vaStatus) {
1779        obj_context->context_id = -1;
1780        obj_context->config_id = -1;
1781        obj_context->picture_width = 0;
1782        obj_context->picture_height = 0;
1783        free(obj_context->render_targets);
1784        free(obj_context->buffer_list);
1785        obj_context->num_buffers = 0;
1786        obj_context->render_targets = NULL;
1787        obj_context->num_render_targets = 0;
1788        obj_context->va_flags = 0;
1789        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1790
1791        return vaStatus;
1792    }
1793
1794    /* initialize cmdbuf */
1795    for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) {
1796        obj_context->lnc_cmdbuf_list[i] = NULL;
1797    }
1798
1799    for (i = 0; i < PNW_MAX_CMDBUFS_ENCODE; i++) {
1800        obj_context->pnw_cmdbuf_list[i] = NULL;
1801    }
1802
1803    for (i = 0; i < PSB_MAX_CMDBUFS; i++) {
1804        obj_context->cmdbuf_list[i] = NULL;
1805    }
1806
1807    for (i = 0; i < cmdbuf_num; i++) {
1808        void  *cmdbuf;
1809
1810        if (encode) { /* Topaz encode context */
1811            if (IS_MFLD(obj_context->driver_data))
1812                cmdbuf = calloc(1, sizeof(struct pnw_cmdbuf_s));
1813            else
1814                cmdbuf = calloc(1, sizeof(struct lnc_cmdbuf_s));
1815        } else /* MSVDX decode context */
1816            cmdbuf =  calloc(1, sizeof(struct psb_cmdbuf_s));
1817
1818        if (NULL == cmdbuf) {
1819            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1820            DEBUG_FAILURE;
1821            break;
1822        }
1823
1824        if (encode) { /* Topaz encode context */
1825            if (IS_MFLD(obj_context->driver_data))
1826                vaStatus = pnw_cmdbuf_create(obj_context, driver_data, (pnw_cmdbuf_p)cmdbuf);
1827            else
1828                vaStatus = lnc_cmdbuf_create(obj_context, driver_data, (lnc_cmdbuf_p)cmdbuf);
1829        } else /* MSVDX decode context */
1830            vaStatus = psb_cmdbuf_create(obj_context, driver_data, (psb_cmdbuf_p)cmdbuf);
1831
1832        if (VA_STATUS_SUCCESS != vaStatus) {
1833            free(cmdbuf);
1834            DEBUG_FAILURE;
1835            break;
1836        }
1837        if (encode) {
1838            if (i >= LNC_MAX_CMDBUFS_ENCODE) {
1839                free(cmdbuf);
1840                DEBUG_FAILURE;
1841                break;
1842            }
1843
1844            if (IS_MFLD(obj_context->driver_data))
1845                obj_context->pnw_cmdbuf_list[i] = (pnw_cmdbuf_p)cmdbuf;
1846            else
1847                obj_context->lnc_cmdbuf_list[i] = (lnc_cmdbuf_p)cmdbuf;
1848        } else
1849            obj_context->cmdbuf_list[i] = (psb_cmdbuf_p)cmdbuf;
1850    }
1851    obj_context->cmdbuf_current = -1;
1852    obj_context->cmdbuf = NULL;
1853    obj_context->lnc_cmdbuf = NULL;
1854    obj_context->pnw_cmdbuf = NULL;
1855    obj_context->frame_count = 0;
1856    obj_context->slice_count = 0;
1857    obj_context->msvdx_context = ((driver_data->msvdx_context_base & 0xff0000) >> 16) |
1858                                 ((contextID & 0xff000000) >> 16);
1859#ifdef ANDROID
1860    if(IS_MFLD(driver_data)) {
1861        obj_context->msvdx_context = ((driver_data->drm_fd & 0xf) << 4) |
1862                                     ((unsigned int)gettid() & 0xf);
1863    }
1864#endif
1865    obj_context->profile = obj_config->profile;
1866    obj_context->entry_point = obj_config->entrypoint;
1867
1868    /* Error recovery */
1869    if (VA_STATUS_SUCCESS != vaStatus) {
1870        if (cmdbuf_num > LNC_MAX_CMDBUFS_ENCODE)
1871            cmdbuf_num = LNC_MAX_CMDBUFS_ENCODE;
1872        for (i = 0; i < cmdbuf_num; i++) {
1873            if (obj_context->lnc_cmdbuf_list[i]) {
1874                lnc_cmdbuf_destroy(obj_context->lnc_cmdbuf_list[i]);
1875                free(obj_context->lnc_cmdbuf_list[i]);
1876                obj_context->lnc_cmdbuf_list[i] = NULL;
1877            }
1878            if (obj_context->pnw_cmdbuf_list[i]) {
1879                pnw_cmdbuf_destroy(obj_context->pnw_cmdbuf_list[i]);
1880                free(obj_context->pnw_cmdbuf_list[i]);
1881                obj_context->pnw_cmdbuf_list[i] = NULL;
1882            }
1883            if (obj_context->cmdbuf_list[i]) {
1884                psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]);
1885                free(obj_context->cmdbuf_list[i]);
1886                obj_context->cmdbuf_list[i] = NULL;
1887            }
1888        }
1889
1890        obj_context->cmdbuf = NULL;
1891        obj_context->lnc_cmdbuf = NULL;
1892
1893        obj_context->context_id = -1;
1894        obj_context->config_id = -1;
1895        obj_context->picture_width = 0;
1896        obj_context->picture_height = 0;
1897        free(obj_context->render_targets);
1898        free(obj_context->buffer_list);
1899        obj_context->num_buffers = 0;
1900        obj_context->render_targets = NULL;
1901        obj_context->num_render_targets = 0;
1902        obj_context->va_flags = 0;
1903        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1904    } else
1905        lnc_ospm_start(driver_data, encode);
1906
1907    psb_new_context(driver_data, (obj_config->profile << 8) | obj_config->entrypoint);
1908
1909    return vaStatus;
1910}
1911
1912static VAStatus psb__allocate_malloc_buffer(object_buffer_p obj_buffer, int size)
1913{
1914    VAStatus vaStatus = VA_STATUS_SUCCESS;
1915
1916    obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size);
1917    if (NULL == obj_buffer->buffer_data) {
1918        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1919        DEBUG_FAILURE;
1920    }
1921    return vaStatus;
1922}
1923
1924static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer);
1925
1926static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer, int size, unsigned char *data, VABufferType type)
1927{
1928    VAStatus vaStatus = VA_STATUS_SUCCESS;
1929
1930    ASSERT(NULL == obj_buffer->buffer_data);
1931
1932    if (obj_buffer->psb_buffer && (psb_bs_queued == obj_buffer->psb_buffer->status)) {
1933        psb__information_message("Abandoning BO for buffer %08x type %s\n", obj_buffer->base.id,
1934                                 buffer_type_to_string(obj_buffer->type));
1935        /* need to set psb_buffer aside and get another one */
1936        obj_buffer->psb_buffer->status = psb_bs_abandoned;
1937        obj_buffer->psb_buffer = NULL;
1938        obj_buffer->size = 0;
1939        obj_buffer->alloc_size = 0;
1940    }
1941
1942    if (type == VAProtectedSliceDataBufferType) {
1943        if (obj_buffer->psb_buffer) {
1944            psb__information_message("RAR: old RAR slice buffer with RAR handle 0%08x, current RAR handle 0x%08x\n",
1945                                     obj_buffer->psb_buffer->rar_handle, (uint32_t)data);
1946            psb__information_message("RAR: force old RAR buffer destroy and new buffer re-allocation by set size=0\n");
1947            obj_buffer->alloc_size = 0;
1948        }
1949    }
1950
1951    if (obj_buffer->alloc_size < (unsigned int)size) {
1952        psb__information_message("Buffer size mismatch: Need %d, currently have %d\n", size, obj_buffer->alloc_size);
1953        if (obj_buffer->psb_buffer) {
1954            if (obj_buffer->buffer_data) {
1955                psb__unmap_buffer(obj_buffer);
1956            }
1957            psb_buffer_destroy(obj_buffer->psb_buffer);
1958            obj_buffer->alloc_size = 0;
1959        } else {
1960            obj_buffer->psb_buffer = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s));
1961            if (NULL == obj_buffer->psb_buffer) {
1962                vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1963                DEBUG_FAILURE;
1964            }
1965        }
1966        if (VA_STATUS_SUCCESS == vaStatus) {
1967            psb__information_message("Allocate new GPU buffers for vaCreateBuffer:type=%s,size=%d.\n",
1968                                     buffer_type_to_string(obj_buffer->type), size);
1969
1970            size = (size + 0x7fff) & ~0x7fff; /* Round up */
1971            if (obj_buffer->type == VAImageBufferType) /* Xserver side PutSurface, Image/subpicture buffer
1972                                                        * should be shared between two process
1973                                                        */
1974                vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu_shared, obj_buffer->psb_buffer);
1975            else if (obj_buffer->type == VAProtectedSliceDataBufferType) {
1976                if (IS_MFLD(driver_data))
1977                    vaStatus = psb_buffer_reference_imr(driver_data, (uint32_t)data, obj_buffer->psb_buffer);
1978            } else
1979                vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, obj_buffer->psb_buffer);
1980            if (VA_STATUS_SUCCESS != vaStatus) {
1981                free(obj_buffer->psb_buffer);
1982                obj_buffer->psb_buffer = NULL;
1983                DEBUG_FAILURE;
1984            } else {
1985                obj_buffer->alloc_size = size;
1986            }
1987        }
1988    }
1989    return vaStatus;
1990}
1991
1992static VAStatus psb__map_buffer(object_buffer_p obj_buffer)
1993{
1994    if (obj_buffer->psb_buffer) {
1995        return psb_buffer_map(obj_buffer->psb_buffer, &obj_buffer->buffer_data);
1996    }
1997    return VA_STATUS_SUCCESS;
1998}
1999
2000static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer)
2001{
2002    if (obj_buffer->psb_buffer) {
2003        obj_buffer->buffer_data = NULL;
2004        return psb_buffer_unmap(obj_buffer->psb_buffer);
2005    }
2006    return VA_STATUS_SUCCESS;
2007}
2008
2009static void psb__destroy_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer)
2010{
2011    if (obj_buffer->psb_buffer) {
2012        if (obj_buffer->buffer_data) {
2013            psb__unmap_buffer(obj_buffer);
2014        }
2015        psb_buffer_destroy(obj_buffer->psb_buffer);
2016        free(obj_buffer->psb_buffer);
2017        obj_buffer->psb_buffer = NULL;
2018    }
2019
2020    if (NULL != obj_buffer->buffer_data) {
2021        free(obj_buffer->buffer_data);
2022        obj_buffer->buffer_data = NULL;
2023        obj_buffer->size = 0;
2024    }
2025
2026    object_heap_free(&driver_data->buffer_heap, (object_base_p) obj_buffer);
2027}
2028
2029void psb__suspend_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer)
2030{
2031    if (obj_buffer->context) {
2032        VABufferType type = obj_buffer->type;
2033        object_context_p obj_context = obj_buffer->context;
2034
2035        /* Remove buffer from active list */
2036        *obj_buffer->pptr_prev_next = obj_buffer->ptr_next;
2037
2038        /* Add buffer to tail of unused list */
2039        obj_buffer->ptr_next = NULL;
2040        obj_buffer->last_used = obj_context->frame_count;
2041        if (obj_context->buffers_unused_tail[type]) {
2042            obj_buffer->pptr_prev_next = &(obj_context->buffers_unused_tail[type]->ptr_next);
2043        } else {
2044            obj_buffer->pptr_prev_next = &(obj_context->buffers_unused[type]);
2045        }
2046        *obj_buffer->pptr_prev_next = obj_buffer;
2047        obj_context->buffers_unused_tail[type] = obj_buffer;
2048        obj_context->buffers_unused_count[type]++;
2049
2050        psb__information_message("Adding buffer %08x type %s to unused list. unused count = %d\n", obj_buffer->base.id,
2051                                 buffer_type_to_string(obj_buffer->type), obj_context->buffers_unused_count[type]);
2052        object_heap_suspend_object((object_base_p) obj_buffer, 1); /* suspend */
2053        return;
2054    }
2055
2056    if (obj_buffer->psb_buffer && (psb_bs_queued == obj_buffer->psb_buffer->status)) {
2057        /* need to set psb_buffer aside */
2058        obj_buffer->psb_buffer->status = psb_bs_abandoned;
2059        obj_buffer->psb_buffer = NULL;
2060    }
2061
2062    psb__destroy_buffer(driver_data, obj_buffer);
2063}
2064
2065static void psb__destroy_context(psb_driver_data_p driver_data, object_context_p obj_context)
2066{
2067    int encode, i;
2068
2069    if (obj_context->entry_point == VAEntrypointEncSlice)
2070        encode = 1;
2071    else
2072        encode = 0;
2073
2074    lnc_ospm_stop(driver_data, encode);
2075
2076    obj_context->format_vtable->destroyContext(obj_context);
2077
2078    for (i = 0; i < PSB_MAX_BUFFERTYPES; i++) {
2079        object_buffer_p obj_buffer;
2080        obj_buffer = obj_context->buffers_active[i];
2081        for (; obj_buffer; obj_buffer = obj_buffer->ptr_next) {
2082            psb__information_message("%s: destroying active buffer %08x\n", __FUNCTION__, obj_buffer->base.id);
2083            psb__destroy_buffer(driver_data, obj_buffer);
2084        }
2085        obj_buffer = obj_context->buffers_unused[i];
2086        for (; obj_buffer; obj_buffer = obj_buffer->ptr_next) {
2087            psb__information_message("%s: destroying unused buffer %08x\n", __FUNCTION__, obj_buffer->base.id);
2088            psb__destroy_buffer(driver_data, obj_buffer);
2089        }
2090        obj_context->buffers_unused_count[i] = 0;
2091    }
2092
2093    for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) {
2094        if (obj_context->lnc_cmdbuf_list[i]) {
2095            lnc_cmdbuf_destroy(obj_context->lnc_cmdbuf_list[i]);
2096            free(obj_context->lnc_cmdbuf_list[i]);
2097            obj_context->lnc_cmdbuf_list[i] = NULL;
2098        }
2099    }
2100
2101    for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) {
2102        if (obj_context->pnw_cmdbuf_list[i]) {
2103            pnw_cmdbuf_destroy(obj_context->pnw_cmdbuf_list[i]);
2104            free(obj_context->pnw_cmdbuf_list[i]);
2105            obj_context->pnw_cmdbuf_list[i] = NULL;
2106        }
2107    }
2108
2109    for (i = 0; i < PSB_MAX_CMDBUFS; i++) {
2110        if (obj_context->cmdbuf_list[i]) {
2111            psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]);
2112            free(obj_context->cmdbuf_list[i]);
2113            obj_context->cmdbuf_list[i] = NULL;
2114        }
2115    }
2116    obj_context->cmdbuf = NULL;
2117    obj_context->lnc_cmdbuf = NULL;
2118
2119    obj_context->context_id = -1;
2120    obj_context->config_id = -1;
2121    obj_context->picture_width = 0;
2122    obj_context->picture_height = 0;
2123    if (obj_context->render_targets)
2124        free(obj_context->render_targets);
2125    obj_context->render_targets = NULL;
2126    obj_context->num_render_targets = 0;
2127    obj_context->va_flags = 0;
2128
2129    obj_context->current_render_target = NULL;
2130    if (obj_context->buffer_list)
2131        free(obj_context->buffer_list);
2132    obj_context->num_buffers = 0;
2133
2134    object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
2135
2136    psb_rm_context(driver_data);
2137}
2138
2139VAStatus psb_DestroyContext(
2140    VADriverContextP ctx,
2141    VAContextID context
2142)
2143{
2144    INIT_DRIVER_DATA
2145    VAStatus vaStatus = VA_STATUS_SUCCESS;
2146    object_context_p obj_context = CONTEXT(context);
2147    if (NULL == obj_context) {
2148        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2149        DEBUG_FAILURE;
2150        return vaStatus;
2151    }
2152
2153    psb__destroy_context(driver_data, obj_context);
2154
2155    return vaStatus;
2156}
2157
2158VAStatus psb__CreateBuffer(
2159    psb_driver_data_p driver_data,
2160    object_context_p obj_context,       /* in */
2161    VABufferType type,  /* in */
2162    unsigned int size,          /* in */
2163    unsigned int num_elements, /* in */
2164    unsigned char *data,         /* in */
2165    VABufferID *buf_desc    /* out */
2166)
2167{
2168    VAStatus vaStatus = VA_STATUS_SUCCESS;
2169    int bufferID;
2170    object_buffer_p obj_buffer = obj_context ? obj_context->buffers_unused[type] : NULL;
2171    int unused_count = obj_context ? obj_context->buffers_unused_count[type] : 0;
2172
2173
2174    /*
2175     * Buffer Management
2176     * For each buffer type, maintain
2177     *   - a LRU sorted list of unused buffers
2178     *   - a list of active buffers
2179     * We only create a new buffer when
2180     *   - no unused buffers are available
2181     *   - the last unused buffer is still queued
2182     *   - the last unused buffer was used very recently and may still be fenced
2183     *      - used recently is defined as within the current frame_count (subject to tweaks)
2184     *
2185     * The buffer that is returned will be moved to the list of active buffers
2186     *   - vaDestroyBuffer and vaRenderPicture will move the active buffer back to the list of unused buffers
2187    */
2188    psb__information_message("Requesting buffer creation, size=%d,elements=%d,type=%s\n", size, num_elements,
2189                             buffer_type_to_string(type));
2190
2191    /* on MFLD, data is IMR offset, and could be 0 */
2192    /*
2193    if ((type == VAProtectedSliceDataBufferType) && (data == NULL)) {
2194        psb__error_message("RAR: Create protected slice buffer, but RAR handle is NULL\n");
2195        return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE ;
2196    }
2197    */
2198
2199    if (obj_buffer && obj_buffer->psb_buffer) {
2200        if (psb_bs_queued == obj_buffer->psb_buffer->status) {
2201            /* Buffer is still queued, allocate new buffer instead */
2202            psb__information_message("Skipping idle buffer %08x, still queued\n", obj_buffer->base.id);
2203            obj_buffer = NULL;
2204        } else if ((obj_buffer->last_used == obj_context->frame_count) && (unused_count < MAX_UNUSED_BUFFERS)) {
2205            /* Buffer was used for this frame, allocate new buffer instead */
2206            psb__information_message("Skipping idle buffer %08x, recently used. Unused = %d\n", obj_buffer->base.id, unused_count);
2207            obj_buffer = NULL;
2208        } else if (obj_context->frame_count - obj_buffer->last_used < 5) {
2209            /* Buffer was used for previous frame, allocate new buffer instead */
2210            psb__information_message("Skipping idle buffer %08x used by frame %d. Unused = %d\n", obj_buffer->base.id, obj_buffer->last_used, unused_count);
2211            obj_buffer = NULL;
2212        }
2213    }
2214
2215    if (obj_buffer) {
2216        bufferID = obj_buffer->base.id;
2217        psb__information_message("Reusing buffer %08x type %s from unused list. Unused = %d\n", bufferID,
2218                                 buffer_type_to_string(type), unused_count);
2219
2220        /* Remove from unused list */
2221        obj_context->buffers_unused[type] = obj_buffer->ptr_next;
2222        if (obj_context->buffers_unused[type]) {
2223            obj_context->buffers_unused[type]->pptr_prev_next = &(obj_context->buffers_unused[type]);
2224            ASSERT(obj_context->buffers_unused_tail[type] != obj_buffer);
2225        } else {
2226            ASSERT(obj_context->buffers_unused_tail[type] == obj_buffer);
2227            obj_context->buffers_unused_tail[type] = 0;
2228        }
2229        obj_context->buffers_unused_count[type]--;
2230
2231        object_heap_suspend_object((object_base_p)obj_buffer, 0); /* Make BufferID valid again */
2232        ASSERT(type == obj_buffer->type);
2233        ASSERT(obj_context == obj_buffer->context);
2234    } else {
2235        bufferID = object_heap_allocate(&driver_data->buffer_heap);
2236        obj_buffer = BUFFER(bufferID);
2237        if (NULL == obj_buffer) {
2238            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2239            DEBUG_FAILURE;
2240            return vaStatus;
2241        }
2242
2243        MEMSET_OBJECT(obj_buffer, struct object_buffer_s);
2244
2245        psb__information_message("Allocating new buffer %08x type %s.\n", bufferID, buffer_type_to_string(type));
2246        obj_buffer->type = type;
2247        obj_buffer->buffer_data = NULL;
2248        obj_buffer->psb_buffer = NULL;
2249        obj_buffer->size = 0;
2250        obj_buffer->max_num_elements = 0;
2251        obj_buffer->alloc_size = 0;
2252        obj_buffer->context = obj_context;
2253    }
2254    if (obj_context) {
2255        /* Add to front of active list */
2256        obj_buffer->ptr_next = obj_context->buffers_active[type];
2257        if (obj_buffer->ptr_next) {
2258            obj_buffer->ptr_next->pptr_prev_next = &(obj_buffer->ptr_next);
2259        }
2260        obj_buffer->pptr_prev_next = &(obj_context->buffers_active[type]);
2261        *obj_buffer->pptr_prev_next = obj_buffer;
2262    }
2263
2264    switch (obj_buffer->type) {
2265    case VABitPlaneBufferType:
2266    case VASliceDataBufferType:
2267    case VAResidualDataBufferType:
2268    case VAImageBufferType:
2269    case VASliceGroupMapBufferType:
2270    case VAEncCodedBufferType:
2271    case VAProtectedSliceDataBufferType:
2272        vaStatus = psb__allocate_BO_buffer(driver_data, obj_buffer, size * num_elements, data, obj_buffer->type);
2273        DEBUG_FAILURE;
2274        break;
2275    case VAPictureParameterBufferType:
2276    case VAIQMatrixBufferType:
2277    case VASliceParameterBufferType:
2278    case VAMacroblockParameterBufferType:
2279    case VADeblockingParameterBufferType:
2280    case VAEncSequenceParameterBufferType:
2281    case VAEncPictureParameterBufferType:
2282    case VAEncSliceParameterBufferType:
2283    case VAQMatrixBufferType:
2284    case VAEncMiscParameterBufferType:
2285        psb__information_message("Allocate new malloc buffers for vaCreateBuffer:type=%s,size=%d, buffer_data=%p.\n",
2286                                 buffer_type_to_string(type), size, obj_buffer->buffer_data);
2287        vaStatus = psb__allocate_malloc_buffer(obj_buffer, size * num_elements);
2288        DEBUG_FAILURE;
2289        break;
2290
2291    default:
2292        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
2293        DEBUG_FAILURE;
2294        break;;
2295    }
2296
2297    if (VA_STATUS_SUCCESS == vaStatus) {
2298        obj_buffer->size = size;
2299        obj_buffer->max_num_elements = num_elements;
2300        obj_buffer->num_elements = num_elements;
2301        if (data && (obj_buffer->type != VAProtectedSliceDataBufferType)) {
2302            vaStatus = psb__map_buffer(obj_buffer);
2303            if (VA_STATUS_SUCCESS == vaStatus) {
2304                memcpy(obj_buffer->buffer_data, data, size * num_elements);
2305
2306                psb__unmap_buffer(obj_buffer);
2307            }
2308        }
2309    }
2310    if (VA_STATUS_SUCCESS == vaStatus) {
2311        *buf_desc = bufferID;
2312    } else {
2313        psb__destroy_buffer(driver_data, obj_buffer);
2314    }
2315
2316    return vaStatus;
2317}
2318
2319VAStatus psb_CreateBuffer(
2320    VADriverContextP ctx,
2321    VAContextID context,        /* in */
2322    VABufferType type,  /* in */
2323    unsigned int size,          /* in */
2324    unsigned int num_elements, /* in */
2325    void *data,         /* in */
2326    VABufferID *buf_desc    /* out */
2327)
2328{
2329    INIT_DRIVER_DATA
2330    VAStatus vaStatus = VA_STATUS_SUCCESS;
2331
2332    if (num_elements <= 0) {
2333        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2334        DEBUG_FAILURE;
2335        return vaStatus;
2336    }
2337
2338    switch (type) {
2339    case VABitPlaneBufferType:
2340    case VASliceDataBufferType:
2341    case VAProtectedSliceDataBufferType:
2342    case VAResidualDataBufferType:
2343    case VASliceGroupMapBufferType:
2344    case VAPictureParameterBufferType:
2345    case VAIQMatrixBufferType:
2346    case VASliceParameterBufferType:
2347    case VAMacroblockParameterBufferType:
2348    case VADeblockingParameterBufferType:
2349    case VAEncCodedBufferType:
2350    case VAEncSequenceParameterBufferType:
2351    case VAEncPictureParameterBufferType:
2352    case VAEncSliceParameterBufferType:
2353    case VAQMatrixBufferType:
2354    case VAEncMiscParameterBufferType:
2355        break;
2356
2357    default:
2358        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
2359        DEBUG_FAILURE;
2360        return vaStatus;
2361    }
2362
2363    object_context_p obj_context = CONTEXT(context);
2364    if (NULL == obj_context) {
2365        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2366        DEBUG_FAILURE;
2367        return vaStatus;
2368    }
2369    if (NULL == buf_desc) {
2370        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2371        DEBUG_FAILURE;
2372        return vaStatus;
2373    }
2374
2375    return psb__CreateBuffer(driver_data, obj_context, type, size, num_elements, data, buf_desc);
2376}
2377
2378
2379VAStatus psb_BufferInfo(
2380    VADriverContextP ctx,
2381    VABufferID buf_id,  /* in */
2382    VABufferType *type, /* out */
2383    unsigned int *size,         /* out */
2384    unsigned int *num_elements /* out */
2385)
2386{
2387    INIT_DRIVER_DATA
2388    VAStatus vaStatus = VA_STATUS_SUCCESS;
2389
2390    object_buffer_p obj_buffer = BUFFER(buf_id);
2391    if (NULL == obj_buffer) {
2392        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2393        DEBUG_FAILURE;
2394        return vaStatus;
2395    }
2396
2397    *type = obj_buffer->type;
2398    *size = obj_buffer->size;
2399    *num_elements = obj_buffer->num_elements;
2400    return VA_STATUS_SUCCESS;
2401}
2402
2403
2404VAStatus psb_BufferSetNumElements(
2405    VADriverContextP ctx,
2406    VABufferID buf_id,    /* in */
2407    unsigned int num_elements    /* in */
2408)
2409{
2410    INIT_DRIVER_DATA
2411    VAStatus vaStatus = VA_STATUS_SUCCESS;
2412    object_buffer_p obj_buffer = BUFFER(buf_id);
2413    if (NULL == obj_buffer) {
2414        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2415        DEBUG_FAILURE;
2416        return vaStatus;
2417    }
2418
2419    if ((num_elements <= 0) || (num_elements > obj_buffer->max_num_elements)) {
2420        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2421    }
2422    if (VA_STATUS_SUCCESS == vaStatus) {
2423        obj_buffer->num_elements = num_elements;
2424    }
2425
2426    return vaStatus;
2427}
2428
2429VAStatus psb_MapBuffer(
2430    VADriverContextP ctx,
2431    VABufferID buf_id,    /* in */
2432    void **pbuf         /* out */
2433)
2434{
2435    INIT_DRIVER_DATA
2436    VAStatus vaStatus = VA_STATUS_SUCCESS;
2437    object_buffer_p obj_buffer = BUFFER(buf_id);
2438    if (NULL == obj_buffer) {
2439        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2440        DEBUG_FAILURE;
2441        return vaStatus;
2442    }
2443
2444
2445    if (NULL == pbuf) {
2446        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2447        DEBUG_FAILURE;
2448        return vaStatus;
2449    }
2450
2451    vaStatus = psb__map_buffer(obj_buffer);
2452    if (VA_STATUS_SUCCESS != vaStatus) {
2453        DEBUG_FAILURE;
2454        return vaStatus;
2455    }
2456
2457    if (NULL != obj_buffer->buffer_data) {
2458        *pbuf = obj_buffer->buffer_data;
2459
2460        /* specifically for Topaz encode
2461         * write validate coded data offset in CodedBuffer
2462         */
2463        if (obj_buffer->type == VAEncCodedBufferType)
2464            psb_codedbuf_map_mangle(ctx, obj_buffer, pbuf);
2465        /* *(IMG_UINT32 *)((unsigned char *)obj_buffer->buffer_data + 4) = 16; */
2466    } else {
2467        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2468    }
2469    return vaStatus;
2470}
2471
2472VAStatus psb_UnmapBuffer(
2473    VADriverContextP ctx,
2474    VABufferID buf_id    /* in */
2475)
2476{
2477    INIT_DRIVER_DATA
2478    VAStatus vaStatus = VA_STATUS_SUCCESS;
2479    object_buffer_p obj_buffer = BUFFER(buf_id);
2480    if (NULL == obj_buffer) {
2481        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2482        DEBUG_FAILURE;
2483        return vaStatus;
2484    }
2485
2486    vaStatus = psb__unmap_buffer(obj_buffer);
2487
2488    return vaStatus;
2489}
2490
2491
2492VAStatus psb_DestroyBuffer(
2493    VADriverContextP ctx,
2494    VABufferID buffer_id
2495)
2496{
2497    INIT_DRIVER_DATA
2498    VAStatus vaStatus = VA_STATUS_SUCCESS;
2499    object_buffer_p obj_buffer = BUFFER(buffer_id);
2500
2501    if (NULL == obj_buffer) {
2502        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2503        DEBUG_FAILURE;
2504        return vaStatus;
2505    }
2506
2507    psb__suspend_buffer(driver_data, obj_buffer);
2508    return vaStatus;
2509}
2510
2511
2512VAStatus psb_BeginPicture(
2513    VADriverContextP ctx,
2514    VAContextID context,
2515    VASurfaceID render_target
2516)
2517{
2518    INIT_DRIVER_DATA
2519    VAStatus vaStatus = VA_STATUS_SUCCESS;
2520    object_context_p obj_context;
2521    object_surface_p obj_surface;
2522    object_config_p obj_config;
2523    int i;
2524
2525    obj_context = CONTEXT(context);
2526    if (NULL == obj_context) {
2527        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2528        DEBUG_FAILURE;
2529        return vaStatus;
2530    }
2531
2532    /* Must not be within BeginPicture / EndPicture already */
2533    ASSERT(obj_context->current_render_target == NULL);
2534
2535    obj_surface = SURFACE(render_target);
2536    if (NULL == obj_surface) {
2537        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2538        DEBUG_FAILURE;
2539        return vaStatus;
2540    }
2541
2542    obj_context->current_render_surface_id = render_target;
2543    obj_context->current_render_target = obj_surface;
2544    obj_context->slice_count = 0;
2545
2546    obj_config = CONFIG(obj_context->config_id);
2547    /* if the surface is decode render target, and in displaying */
2548    if (obj_config &&
2549        (obj_config->entrypoint != VAEntrypointEncSlice) &&
2550        (driver_data->cur_displaying_surface == render_target))
2551        psb__error_message("WARNING: rendering a displaying surface, may see tearing\n");
2552
2553    if (VA_STATUS_SUCCESS == vaStatus) {
2554        vaStatus = obj_context->format_vtable->beginPicture(obj_context);
2555    }
2556
2557    /* want msvdx to do rotate
2558     * but check per-context stream type: interlace or not
2559     */
2560    if ((obj_config->entrypoint != VAEntrypointEncSlice) &&
2561        (obj_config->entrypoint != VAEntrypointEncPicture) &&
2562        driver_data->native_window) {
2563        psb_RecalcRotate(ctx, obj_context);
2564    }
2565
2566    if (obj_context->interlaced_stream || driver_data->disable_msvdx_rotate) {
2567        obj_context->msvdx_rotate = 0;
2568        for (i = 0; i < obj_context->num_render_targets; i++) {
2569            object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]);
2570            /*we invalidate all surfaces's rotate buffer share info here.*/
2571            if (obj_surface->share_info) {
2572                obj_surface->share_info->surface_rotate = 0;
2573            }
2574        }
2575    }
2576    else
2577        obj_context->msvdx_rotate = driver_data->msvdx_rotate_want;
2578
2579    /* the main surface track current rotate information
2580     * try to reuse the allocated rotate surfaces and don't destroy them
2581     * thus the rotation info in obj_surface->psb_surface_rotate may not be updated
2582     */
2583    SET_SURFACE_INFO_rotate(obj_surface->psb_surface, obj_context->msvdx_rotate);
2584    if (IS_MFLD(driver_data) && CONTEXT_ROTATE(obj_context)) {
2585        psb_CreateRotateSurface(ctx, obj_surface, obj_context->msvdx_rotate);
2586    }
2587
2588    if (driver_data->is_oold &&  !obj_surface->psb_surface->in_loop_buf) {
2589        psb_surface_p psb_surface = obj_surface->psb_surface;
2590
2591        psb_surface->in_loop_buf = calloc(1, sizeof(struct psb_buffer_s));
2592        if (NULL == psb_surface->in_loop_buf) {
2593            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2594            DEBUG_FAILURE;
2595            return vaStatus;
2596        }
2597
2598        /* FIXME: For RAR surface, need allocate RAR buffer  */
2599        vaStatus = psb_buffer_create(obj_context->driver_data,
2600                                     psb_surface->size,
2601                                     psb_bt_surface,
2602                                     psb_surface->in_loop_buf);
2603    } else if (!driver_data->is_oold && obj_surface->psb_surface->in_loop_buf) {
2604        psb_surface_p psb_surface = obj_surface->psb_surface;
2605
2606        psb_buffer_destroy(psb_surface->in_loop_buf);
2607        free(psb_surface->in_loop_buf);
2608        psb_surface->in_loop_buf = NULL;
2609    }
2610    obj_context->is_oold = driver_data->is_oold;
2611
2612    psb__information_message("---BeginPicture 0x%08x for frame %d --\n",
2613                             render_target, obj_context->frame_count);
2614#ifdef DEBUG_TRACE
2615    psb__trace_message("------Trace frame %d------\n", obj_context->frame_count);
2616#endif
2617
2618    return vaStatus;
2619}
2620
2621VAStatus psb_RenderPicture(
2622    VADriverContextP ctx,
2623    VAContextID context,
2624    VABufferID *buffers,
2625    int num_buffers
2626)
2627{
2628    INIT_DRIVER_DATA
2629    VAStatus vaStatus = VA_STATUS_SUCCESS;
2630    object_context_p obj_context;
2631    object_buffer_p *buffer_list;
2632    int i;
2633
2634    obj_context = CONTEXT(context);
2635    if (NULL == obj_context) {
2636        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2637        DEBUG_FAILURE;
2638        return vaStatus;
2639    }
2640
2641    if (num_buffers <= 0) {
2642        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2643        DEBUG_FAILURE;
2644        return vaStatus;
2645    }
2646
2647    if (NULL == buffers) {
2648        /* Don't crash on NULL pointers */
2649        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2650        DEBUG_FAILURE;
2651        return vaStatus;
2652    }
2653    /* Must be within BeginPicture / EndPicture */
2654    ASSERT(obj_context->current_render_target != NULL);
2655
2656    if (num_buffers > obj_context->num_buffers) {
2657        free(obj_context->buffer_list);
2658
2659        obj_context->buffer_list = (object_buffer_p *) calloc(1, sizeof(object_buffer_p) * num_buffers);
2660        if (obj_context->buffer_list == NULL) {
2661            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2662            obj_context->num_buffers = 0;
2663        }
2664
2665        obj_context->num_buffers = num_buffers;
2666    }
2667    buffer_list = obj_context->buffer_list;
2668
2669    if (VA_STATUS_SUCCESS == vaStatus) {
2670        /* Lookup buffer references */
2671        for (i = 0; i < num_buffers; i++) {
2672            object_buffer_p obj_buffer = BUFFER(buffers[i]);
2673            if (NULL == obj_buffer) {
2674                vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2675                DEBUG_FAILURE;
2676                return vaStatus;
2677            }
2678            buffer_list[i] = obj_buffer;
2679            psb__information_message("Render buffer %08x type %s\n", obj_buffer->base.id,
2680                                     buffer_type_to_string(obj_buffer->type));
2681        }
2682    }
2683
2684    if (VA_STATUS_SUCCESS == vaStatus) {
2685        vaStatus = obj_context->format_vtable->renderPicture(obj_context, buffer_list, num_buffers);
2686    }
2687
2688    if (buffer_list) {
2689        /* Release buffers */
2690        for (i = 0; i < num_buffers; i++) {
2691            if (buffer_list[i]) {
2692                psb__suspend_buffer(driver_data, buffer_list[i]);
2693            }
2694        }
2695    }
2696
2697    return vaStatus;
2698}
2699
2700VAStatus psb_EndPicture(
2701    VADriverContextP ctx,
2702    VAContextID context
2703)
2704{
2705    INIT_DRIVER_DATA
2706    VAStatus vaStatus;
2707    object_context_p obj_context;
2708
2709    obj_context = CONTEXT(context);
2710    if (NULL == obj_context) {
2711        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2712        DEBUG_FAILURE;
2713        return vaStatus;
2714    }
2715
2716    vaStatus = obj_context->format_vtable->endPicture(obj_context);
2717
2718    psb__information_message("---EndPicture for frame %d --\n", obj_context->frame_count);
2719
2720    obj_context->current_render_target = NULL;
2721    obj_context->frame_count++;
2722#ifdef DEBUG_TRACE
2723    psb__trace_message("FrameCount = %03d\n", obj_context->frame_count);
2724    psb__information_message("FrameCount = %03d\n", obj_context->frame_count);
2725    psb__trace_message(NULL);
2726#endif
2727
2728    return vaStatus;
2729}
2730
2731
2732static void psb__surface_usage(
2733    psb_driver_data_p driver_data,
2734    object_surface_p obj_surface,
2735    int *decode, int *encode, int *rc_enable
2736)
2737{
2738    object_context_p obj_context;
2739    object_config_p obj_config;
2740    VAEntrypoint tmp;
2741    unsigned int eRCmode;
2742    int i;
2743
2744
2745    *decode = 0;
2746    *encode = 0;
2747    *rc_enable = 0;
2748
2749    obj_context = CONTEXT(obj_surface->context_id);
2750    if (NULL == obj_context) /* not associate with a context */
2751        return;
2752
2753    obj_config = CONFIG(obj_context->config_id);
2754    if (NULL == obj_config) /* not have a validate context */
2755        return;
2756
2757    tmp = obj_config->entrypoint;
2758
2759    *encode = (tmp == VAEntrypointEncSlice) || (tmp == VAEntrypointEncPicture);
2760    *decode = (VAEntrypointVLD <= tmp) && (tmp <= VAEntrypointDeblocking);
2761
2762    if (*encode) {
2763        for (i = 0; i < obj_config->attrib_count; i++) {
2764            if (obj_config->attrib_list[i].type == VAConfigAttribRateControl)
2765                break;
2766        }
2767
2768        if (i >= obj_config->attrib_count)
2769            eRCmode = VA_RC_NONE;
2770        else
2771            eRCmode = obj_config->attrib_list[i].value;
2772
2773        if (eRCmode == VA_RC_NONE)
2774            *rc_enable = 0;
2775        else
2776            *rc_enable = 1;
2777    }
2778}
2779
2780VAStatus psb_SyncSurface(
2781    VADriverContextP ctx,
2782    VASurfaceID render_target
2783)
2784{
2785    INIT_DRIVER_DATA
2786    VAStatus vaStatus = VA_STATUS_SUCCESS;
2787    object_surface_p obj_surface;
2788    int decode = 0, encode = 0, rc_enable = 0;
2789
2790    psb__information_message("psb_SyncSurface: 0x%08x\n", render_target);
2791
2792    obj_surface = SURFACE(render_target);
2793    if (NULL == obj_surface) {
2794        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2795        DEBUG_FAILURE;
2796        return vaStatus;
2797    }
2798
2799    /* The cur_displaying_surface indicates the surface being displayed by overlay.
2800     * The diaplay_timestamp records the time point of put surface, which would
2801     * be set to zero while using texture blit.*/
2802
2803    /* don't use mutex here for performance concern... */
2804    //pthread_mutex_lock(&output->output_mutex);
2805    if (render_target == driver_data->cur_displaying_surface)
2806        vaStatus = VA_STATUS_ERROR_SURFACE_IN_DISPLAYING;
2807    else if ((VA_INVALID_SURFACE != driver_data->cur_displaying_surface)    /* use overlay */
2808             && (render_target == driver_data->last_displaying_surface)) {  /* It's the last displaying surface*/
2809        object_surface_p cur_obj_surface = SURFACE(driver_data->cur_displaying_surface);
2810        /*  The flip operation on current displaying surface could be delayed to
2811         *  next VBlank and hadn't been finished yet. Then, the last displaying
2812         *  surface shouldn't be freed, because the hardware may not
2813         *  complete loading data of it. Any change of the last surface could
2814         *  have a impect on the scrren.*/
2815        if (NULL != cur_obj_surface) {
2816            while ((GetTickCount() - cur_obj_surface->display_timestamp) < PSB_MAX_FLIP_DELAY)
2817                usleep(PSB_MAX_FLIP_DELAY * 1000);
2818        }
2819    }
2820    //pthread_mutex_unlock(&output->output_mutex);
2821
2822    if (vaStatus != VA_STATUS_ERROR_SURFACE_IN_DISPLAYING)
2823        vaStatus = psb_surface_sync(obj_surface->psb_surface);
2824
2825    /* report any error of decode for Android */
2826    psb__surface_usage(driver_data, obj_surface, &decode, &encode, &rc_enable);
2827
2828    if (decode && IS_MRST(driver_data)) {
2829        struct drm_lnc_video_getparam_arg arg;
2830        uint32_t ret, handle, fw_status = 0;
2831        handle = wsbmKBufHandle(wsbmKBuf(obj_surface->psb_surface->buf.drm_buf));
2832        arg.key = IMG_VIDEO_DECODE_STATUS;
2833        arg.arg = (uint64_t)((unsigned long) & handle);
2834        arg.value = (uint64_t)((unsigned long) & fw_status);
2835        ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
2836                                  &arg, sizeof(arg));
2837        if (ret == 0) {
2838            if (fw_status != 0)
2839                vaStatus = VA_STATUS_ERROR_DECODING_ERROR;
2840        } else {
2841            psb__information_message("IMG_VIDEO_DECODE_STATUS ioctl return failed.\n");
2842            vaStatus = VA_STATUS_ERROR_UNKNOWN;
2843        }
2844    }
2845    psb__dump_NV_buffers(obj_surface, 0, 0, obj_surface->width, obj_surface->height);
2846    DEBUG_FAILURE;
2847    return vaStatus;
2848}
2849
2850
2851VAStatus psb_QuerySurfaceStatus(
2852    VADriverContextP ctx,
2853    VASurfaceID render_target,
2854    VASurfaceStatus *status    /* out */
2855)
2856{
2857    INIT_DRIVER_DATA
2858    VAStatus vaStatus = VA_STATUS_SUCCESS;
2859    object_surface_p obj_surface;
2860    VASurfaceStatus surface_status;
2861    int frame_skip = 0, encode = 0, decode = 0, rc_enable = 0;
2862
2863    obj_surface = SURFACE(render_target);
2864    if (NULL == obj_surface) {
2865        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2866        DEBUG_FAILURE;
2867        return vaStatus;
2868    }
2869    if (NULL == status) {
2870        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2871        DEBUG_FAILURE;
2872        return vaStatus;
2873    }
2874
2875    vaStatus = psb_surface_query_status(obj_surface->psb_surface, &surface_status);
2876
2877    /* The cur_displaying_surface indicates the surface being displayed by overlay.
2878     * The diaplay_timestamp records the time point of put surface, which would
2879     * be set to zero while using texture blit.*/
2880    pthread_mutex_lock(&driver_data->output_mutex);
2881    if (render_target == driver_data->cur_displaying_surface)
2882        surface_status = VASurfaceDisplaying;
2883    else if ((VA_INVALID_SURFACE != driver_data->cur_displaying_surface)    /* use overlay */
2884             && (render_target == driver_data->last_displaying_surface)) {  /* It's the last displaying surface*/
2885        object_surface_p cur_obj_surface = SURFACE(driver_data->cur_displaying_surface);
2886        /*The flip operation on current displaying surface could be delayed to
2887         *  next VBlank and hadn't been finished yet. Then, the last displaying
2888         *  surface shouldn't be freed, because the hardware may not
2889         *  complete loading data of it. Any change of the last surface could
2890         *  have a impect on the scrren.*/
2891        if ((NULL != cur_obj_surface)
2892            && ((GetTickCount() - cur_obj_surface->display_timestamp) < PSB_MAX_FLIP_DELAY)) {
2893            surface_status = VASurfaceDisplaying;
2894        }
2895    }
2896    pthread_mutex_unlock(&driver_data->output_mutex);
2897
2898    /* try to get frameskip flag for encode */
2899    psb__surface_usage(driver_data, obj_surface, &decode, &encode, &rc_enable);
2900    if (encode && rc_enable) {
2901        if (IS_MRST(driver_data))
2902            lnc_surface_get_frameskip(driver_data, obj_surface->psb_surface, &frame_skip);
2903        else
2904            pnw_surface_get_frameskip(driver_data, obj_surface->psb_surface, &frame_skip);
2905
2906        if (frame_skip == 1)
2907            surface_status = surface_status | VASurfaceSkipped;
2908    } else if (decode) {
2909
2910        if(obj_surface->share_info->renderStatus == 1) {
2911            surface_status = VASurfaceDisplaying;
2912        }else if (obj_surface->share_info->renderStatus == 0) {
2913            surface_status = VASurfaceReady;
2914        }
2915    }
2916
2917    *status = surface_status;
2918
2919    return vaStatus;
2920}
2921
2922VAStatus psb_QuerySurfaceError(
2923    VADriverContextP ctx,
2924    VASurfaceID render_target,
2925    VAStatus error_status,
2926    void **error_info /*out*/
2927)
2928{
2929    INIT_DRIVER_DATA
2930    VAStatus vaStatus = VA_STATUS_SUCCESS;
2931    object_surface_p obj_surface;
2932    uint32_t i;
2933
2934    obj_surface = SURFACE(render_target);
2935    if (NULL == obj_surface) {
2936        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2937        DEBUG_FAILURE;
2938        return vaStatus;
2939    }
2940
2941#ifdef MFLD_ERROR_CONCEALMENT
2942    if (driver_data->ec_enabled == 0) {
2943#else
2944    if (!IS_MRST(driver_data) || (driver_data->ec_enabled == 0)) {
2945#endif
2946        psb__information_message("error concealment is not supported for this profile.\n");
2947        error_info = NULL;
2948        return VA_STATUS_ERROR_UNKNOWN;
2949    }
2950
2951    if (error_status == VA_STATUS_ERROR_DECODING_ERROR) {
2952        drm_psb_msvdx_decode_status_t *decode_status = driver_data->msvdx_decode_status;
2953        struct drm_lnc_video_getparam_arg arg;
2954        uint32_t ret, handle;
2955        handle = wsbmKBufHandle(wsbmKBuf(obj_surface->psb_surface->buf.drm_buf));
2956
2957        arg.key = IMG_VIDEO_MB_ERROR;
2958        arg.arg = (uint64_t)((unsigned long) & handle);
2959        arg.value = (uint64_t)((unsigned long)decode_status);
2960        ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
2961                                  &arg, sizeof(arg));
2962
2963        if (decode_status->num_error_slice > MAX_MB_ERRORS) {
2964            psb__information_message("too much mb errors are reported.\n");
2965            return VA_STATUS_ERROR_UNKNOWN;
2966        }
2967        i = 0;
2968        for (i = 0; i < decode_status->num_error_slice; ++i) {
2969            driver_data->surface_mb_error[i].status = 1;
2970            driver_data->surface_mb_error[i].start_mb = decode_status->start_error_mb_list[i];
2971            driver_data->surface_mb_error[i].end_mb = decode_status->end_error_mb_list[i];
2972            driver_data->surface_mb_error[i].decode_error_type = decode_status->slice_missing_or_error[i];
2973        }
2974        driver_data->surface_mb_error[i].status = -1;
2975        *error_info = driver_data->surface_mb_error;
2976
2977        return vaStatus;
2978    } else {
2979        error_info = NULL;
2980        return VA_STATUS_ERROR_UNKNOWN;
2981    }
2982}
2983
2984VAStatus psb_LockSurface(
2985    VADriverContextP ctx,
2986    VASurfaceID surface,
2987    unsigned int *fourcc, /* following are output argument */
2988    unsigned int *luma_stride,
2989    unsigned int *chroma_u_stride,
2990    unsigned int *chroma_v_stride,
2991    unsigned int *luma_offset,
2992    unsigned int *chroma_u_offset,
2993    unsigned int *chroma_v_offset,
2994    unsigned int *buffer_name,
2995    void **buffer
2996)
2997{
2998    INIT_DRIVER_DATA
2999    VAStatus vaStatus = VA_STATUS_SUCCESS;
3000    unsigned char *surface_data;
3001    int ret;
3002
3003    object_surface_p obj_surface = SURFACE(surface);
3004    psb_surface_p psb_surface;
3005    if (NULL == obj_surface) {
3006        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
3007        DEBUG_FAILURE;
3008        return vaStatus;
3009    }
3010
3011    psb_surface = obj_surface->psb_surface;
3012    if (buffer_name)
3013        *buffer_name = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
3014
3015    if (buffer) { /* map the surface buffer */
3016        uint32_t srf_buf_ofs = 0;
3017        ret = psb_buffer_map(&psb_surface->buf, &surface_data);
3018        if (ret) {
3019            *buffer = NULL;
3020            vaStatus = VA_STATUS_ERROR_UNKNOWN;
3021            DEBUG_FAILURE;
3022            return vaStatus;
3023        }
3024        srf_buf_ofs = psb_surface->buf.buffer_ofs;
3025        *buffer = surface_data + srf_buf_ofs;
3026    }
3027
3028    *fourcc = VA_FOURCC_NV12;
3029    *luma_stride = psb_surface->stride;
3030    *chroma_u_stride = psb_surface->stride;
3031    *chroma_v_stride = psb_surface->stride;
3032    *luma_offset = 0;
3033    *chroma_u_offset = obj_surface->height * psb_surface->stride;
3034    *chroma_v_offset = obj_surface->height * psb_surface->stride + 1;
3035
3036    return vaStatus;
3037}
3038
3039
3040VAStatus psb_UnlockSurface(
3041    VADriverContextP ctx,
3042    VASurfaceID surface
3043)
3044{
3045    INIT_DRIVER_DATA
3046    VAStatus vaStatus = VA_STATUS_SUCCESS;
3047
3048    object_surface_p obj_surface = SURFACE(surface);
3049    if (NULL == obj_surface) {
3050        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
3051        DEBUG_FAILURE;
3052        return vaStatus;
3053    }
3054
3055    psb_surface_p psb_surface = obj_surface->psb_surface;
3056
3057    psb_buffer_unmap(&psb_surface->buf);
3058
3059    return VA_STATUS_SUCCESS;
3060}
3061
3062VAStatus psb_GetEGLClientBufferFromSurface(
3063    VADriverContextP ctx,
3064    VASurfaceID surface,
3065    void **buffer
3066)
3067{
3068    INIT_DRIVER_DATA
3069    VAStatus vaStatus = VA_STATUS_SUCCESS;
3070
3071    object_surface_p obj_surface = SURFACE(surface);
3072    if (NULL == obj_surface) {
3073        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
3074        DEBUG_FAILURE;
3075        return vaStatus;
3076    }
3077
3078    psb_surface_p psb_surface = obj_surface->psb_surface;
3079    *buffer = (unsigned char *)psb_surface->bc_buffer;
3080
3081    return vaStatus;
3082}
3083
3084VAStatus psb_CreateSurfaceFromV4L2Buf(
3085    VADriverContextP ctx,
3086    int v4l2_fd,         /* file descriptor of V4L2 device */
3087    struct v4l2_format *v4l2_fmt,       /* format of V4L2 */
3088    struct v4l2_buffer *v4l2_buf,       /* V4L2 buffer */
3089    VASurfaceID *surface        /* out */
3090)
3091{
3092    INIT_DRIVER_DATA;
3093    VAStatus vaStatus = VA_STATUS_SUCCESS;
3094    int surfaceID;
3095    object_surface_p obj_surface;
3096    psb_surface_p psb_surface;
3097    int width, height, buf_stride, buf_offset, size;
3098    unsigned long *user_ptr = NULL;
3099
3100    if (IS_MRST(driver_data) == 0 && IS_MFLD(driver_data) == 0) {
3101        psb__error_message("CreateSurfaceFromV4L2Buf isn't supported on non-MRST platform\n");
3102        return VA_STATUS_ERROR_UNKNOWN;
3103    }
3104
3105    /* Todo:
3106     * sanity check if the v4l2 device on MRST is supported
3107     */
3108    if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) {
3109        unsigned long tmp = (unsigned long)(v4l2_buf->m.userptr);
3110
3111        if (tmp & 0xfff) {
3112            psb__error_message("The buffer address 0x%08x must be page aligned\n", tmp);
3113            return VA_STATUS_ERROR_UNKNOWN;
3114        }
3115    }
3116
3117    surfaceID = object_heap_allocate(&driver_data->surface_heap);
3118    obj_surface = SURFACE(surfaceID);
3119    if (NULL == obj_surface) {
3120        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
3121        DEBUG_FAILURE;
3122        return vaStatus;
3123    }
3124    MEMSET_OBJECT(obj_surface, struct object_surface_s);
3125
3126    width = v4l2_fmt->fmt.pix.width;
3127    height = v4l2_fmt->fmt.pix.height;
3128
3129    buf_stride = width; /* ? */
3130    buf_offset = v4l2_buf->m.offset;
3131    size = v4l2_buf->length;
3132
3133    psb__information_message("Create Surface from V4L2 buffer: %dx%d, stride=%d, buffer offset=0x%08x, size=%d\n",
3134                             width, height, buf_stride, buf_offset, size);
3135
3136    obj_surface->surface_id = surfaceID;
3137    *surface = surfaceID;
3138    obj_surface->context_id = -1;
3139    obj_surface->width = width;
3140    obj_surface->height = height;
3141    obj_surface->subpictures = NULL;
3142    obj_surface->subpic_count = 0;
3143    obj_surface->derived_imgcnt = 0;
3144    obj_surface->display_timestamp = 0;
3145
3146    psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
3147    if (NULL == psb_surface) {
3148        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
3149        obj_surface->surface_id = VA_INVALID_SURFACE;
3150
3151        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
3152
3153        DEBUG_FAILURE;
3154
3155        return vaStatus;
3156    }
3157
3158    /* current assume it is NV12 */
3159    if (IS_MRST(driver_data))
3160        vaStatus = psb_surface_create_camera(driver_data, width, height, buf_stride, size, psb_surface, 1, buf_offset);
3161    else {
3162        if (V4L2_MEMORY_USERPTR == v4l2_buf->memory)
3163            user_ptr = (unsigned long *)(v4l2_buf->m.userptr);
3164        else {
3165            user_ptr = mmap(NULL /* start anywhere */ ,
3166                            v4l2_buf->length,
3167                            PROT_READ ,
3168                            MAP_SHARED /* recommended */ ,
3169                            v4l2_fd, v4l2_buf->m.offset);
3170        }
3171
3172        if (NULL != user_ptr && MAP_FAILED != user_ptr)
3173            vaStatus = psb_surface_create_camera_from_ub(driver_data, width, height,
3174                       buf_stride, size, psb_surface, 1, buf_offset, user_ptr);
3175        else {
3176            DEBUG_FAILURE;
3177            vaStatus = VA_STATUS_ERROR_UNKNOWN;
3178        }
3179    }
3180
3181    if (VA_STATUS_SUCCESS != vaStatus) {
3182        free(psb_surface);
3183        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
3184        obj_surface->surface_id = VA_INVALID_SURFACE;
3185
3186        DEBUG_FAILURE;
3187
3188        return vaStatus;
3189    }
3190
3191    memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
3192    psb_surface->extra_info[4] = VA_FOURCC_NV12; /* temp treat is as IYUV */
3193
3194    obj_surface->psb_surface = psb_surface;
3195
3196    /* Error recovery */
3197    if (VA_STATUS_SUCCESS != vaStatus) {
3198        object_surface_p obj_surface = SURFACE(*surface);
3199        psb__destroy_surface(driver_data, obj_surface);
3200        *surface = VA_INVALID_SURFACE;
3201    }
3202
3203    return vaStatus;
3204}
3205
3206
3207VAStatus psb_CreateSurfacesForUserPtr(
3208    VADriverContextP ctx,
3209    int Width,
3210    int Height,
3211    int format,
3212    int num_surfaces,
3213    VASurfaceID *surface_list,       /* out */
3214    unsigned size, /* total buffer size need to be allocated */
3215    unsigned int fourcc, /* expected fourcc */
3216    unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
3217    unsigned int chroma_u_stride, /* chroma stride */
3218    unsigned int chroma_v_stride,
3219    unsigned int luma_offset, /* could be 0 */
3220    unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
3221    unsigned int chroma_v_offset
3222)
3223{
3224    INIT_DRIVER_DATA
3225    VAStatus vaStatus = VA_STATUS_SUCCESS;
3226    int i, height_origin;
3227    unsigned long buffer_stride;
3228
3229    /* silient compiler warning */
3230    unsigned int width = (unsigned int)Width;
3231    unsigned int height = (unsigned int)Height;
3232
3233    psb__information_message("Create surface: width %d, height %d, format 0x%08x"
3234                             "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x"
3235                             "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d"
3236                             "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n",
3237                             width, height, format,
3238                             num_surfaces, size, fourcc,
3239                             luma_stride, chroma_u_stride, chroma_v_stride,
3240                             luma_offset, chroma_u_offset, chroma_v_offset);
3241
3242    if (num_surfaces <= 0) {
3243        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
3244        DEBUG_FAILURE;
3245        return vaStatus;
3246    }
3247
3248    if (NULL == surface_list) {
3249        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
3250        DEBUG_FAILURE;
3251        return vaStatus;
3252    }
3253
3254    /* We only support one format */
3255    if ((VA_RT_FORMAT_YUV420 != format)
3256        && (VA_RT_FORMAT_YUV422 != format)) {
3257        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
3258        DEBUG_FAILURE;
3259        return vaStatus;
3260    }
3261
3262    /* We only support NV12/YV12 */
3263    if (((VA_RT_FORMAT_YUV420 == format) && (fourcc != VA_FOURCC_NV12)) ||
3264        ((VA_RT_FORMAT_YUV422 == format) && (fourcc != VA_FOURCC_YV16))) {
3265        psb__error_message("Only support NV12/YV16 format\n");
3266        return VA_STATUS_ERROR_UNKNOWN;
3267    }
3268
3269    vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
3270    if (VA_STATUS_SUCCESS != vaStatus) {
3271        DEBUG_FAILURE;
3272        return vaStatus;
3273    }
3274
3275    if ((size < width * height * 1.5) ||
3276        (luma_stride < width) ||
3277        (chroma_u_stride * 2 < width) ||
3278        (chroma_v_stride * 2 < width) ||
3279        (chroma_u_offset < luma_offset + width * height) ||
3280        (chroma_v_offset < luma_offset + width * height)) {
3281
3282        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
3283        DEBUG_FAILURE;
3284        return vaStatus;
3285    }
3286
3287    height_origin = height;
3288
3289    for (i = 0; i < num_surfaces; i++) {
3290        int surfaceID;
3291        object_surface_p obj_surface;
3292        psb_surface_p psb_surface;
3293
3294        surfaceID = object_heap_allocate(&driver_data->surface_heap);
3295        obj_surface = SURFACE(surfaceID);
3296        if (NULL == obj_surface) {
3297            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
3298            DEBUG_FAILURE;
3299            break;
3300        }
3301        MEMSET_OBJECT(obj_surface, struct object_surface_s);
3302
3303        obj_surface->surface_id = surfaceID;
3304        surface_list[i] = surfaceID;
3305        obj_surface->context_id = -1;
3306        obj_surface->width = width;
3307        obj_surface->height = height;
3308        obj_surface->width_r = width;
3309        obj_surface->height_r = height;
3310        obj_surface->height_origin = height_origin;
3311
3312        psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
3313        if (NULL == psb_surface) {
3314            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
3315            obj_surface->surface_id = VA_INVALID_SURFACE;
3316
3317            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
3318
3319            DEBUG_FAILURE;
3320            break;
3321        }
3322
3323        switch (format) {
3324        case VA_RT_FORMAT_YUV422:
3325            fourcc = VA_FOURCC_YV16;
3326            break;
3327        case VA_RT_FORMAT_YUV420:
3328        default:
3329            fourcc = VA_FOURCC_NV12;
3330            break;
3331        }
3332
3333        vaStatus = psb_surface_create_for_userptr(driver_data, width, height,
3334                   size,
3335                   fourcc,
3336                   luma_stride,
3337                   chroma_u_stride,
3338                   chroma_v_stride,
3339                   luma_offset,
3340                   chroma_u_offset,
3341                   chroma_v_offset,
3342                   psb_surface
3343                                                 );
3344
3345        if (VA_STATUS_SUCCESS != vaStatus) {
3346            free(psb_surface);
3347            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
3348            obj_surface->surface_id = VA_INVALID_SURFACE;
3349
3350            DEBUG_FAILURE;
3351            break;
3352        }
3353        buffer_stride = psb_surface->stride;
3354        /* by default, surface fourcc is NV12 */
3355        memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
3356        psb_surface->extra_info[4] = fourcc;
3357
3358        obj_surface->psb_surface = psb_surface;
3359    }
3360
3361    /* Error recovery */
3362    if (VA_STATUS_SUCCESS != vaStatus) {
3363        /* surface_list[i-1] was the last successful allocation */
3364        for (; i--;) {
3365            object_surface_p obj_surface = SURFACE(surface_list[i]);
3366            psb__destroy_surface(driver_data, obj_surface);
3367            surface_list[i] = VA_INVALID_SURFACE;
3368        }
3369    }
3370
3371
3372    return vaStatus;
3373}
3374
3375VAStatus  psb_CreateSurfaceFromKbuf(
3376    VADriverContextP ctx,
3377    int _width,
3378    int _height,
3379    int format,
3380    VASurfaceID *surface,       /* out */
3381    unsigned int kbuf_handle, /* kernel buffer handle*/
3382    unsigned size, /* kernel buffer size */
3383    unsigned int kBuf_fourcc, /* expected fourcc */
3384    unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
3385    unsigned int chroma_u_stride, /* chroma stride */
3386    unsigned int chroma_v_stride,
3387    unsigned int luma_offset, /* could be 0 */
3388    unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
3389    unsigned int chroma_v_offset
3390)
3391{
3392    INIT_DRIVER_DATA
3393    VAStatus vaStatus = VA_STATUS_SUCCESS;
3394    int i ;
3395    unsigned long buffer_stride;
3396
3397    /* silient compiler warning */
3398    unsigned int width = (unsigned int)_width;
3399    unsigned int height = (unsigned int)_height;
3400
3401    psb__information_message("Create surface: width %d, height %d, format 0x%08x"
3402                             "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x"
3403                             "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d"
3404                             "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n",
3405                             width, height, format,
3406                             size, kBuf_fourcc,
3407                             luma_stride, chroma_u_stride, chroma_v_stride,
3408                             luma_offset, chroma_u_offset, chroma_v_offset);
3409
3410    if (NULL == surface) {
3411        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
3412        DEBUG_FAILURE;
3413        return vaStatus;
3414    }
3415
3416    /* We only support one format */
3417    if ((VA_RT_FORMAT_YUV420 != format)
3418        && (VA_RT_FORMAT_YUV422 != format)) {
3419        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
3420        DEBUG_FAILURE;
3421        return vaStatus;
3422    }
3423
3424    /* We only support NV12/YV12 */
3425
3426    if (((VA_RT_FORMAT_YUV420 == format) && (kBuf_fourcc != VA_FOURCC_NV12)) ||
3427        ((VA_RT_FORMAT_YUV422 == format) && (kBuf_fourcc != VA_FOURCC_YV16))) {
3428        psb__error_message("Only support NV12/YV16 format\n");
3429        return VA_STATUS_ERROR_UNKNOWN;
3430    }
3431
3432    vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
3433    if (VA_STATUS_SUCCESS != vaStatus) {
3434        DEBUG_FAILURE;
3435        return vaStatus;
3436    }
3437
3438    if ((size < width * height * 1.5) ||
3439        (luma_stride < width) ||
3440        (chroma_u_stride * 2 < width) ||
3441        (chroma_v_stride * 2 < width) ||
3442        (chroma_u_offset < luma_offset + width * height) ||
3443        (chroma_v_offset < luma_offset + width * height)) {
3444
3445        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
3446        DEBUG_FAILURE;
3447        return vaStatus;
3448    }
3449
3450    int surfaceID;
3451    object_surface_p obj_surface;
3452    psb_surface_p psb_surface;
3453
3454    surfaceID = object_heap_allocate(&driver_data->surface_heap);
3455    obj_surface = SURFACE(surfaceID);
3456    if (NULL == obj_surface) {
3457        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
3458        DEBUG_FAILURE;
3459    }
3460    MEMSET_OBJECT(obj_surface, struct object_surface_s);
3461
3462    obj_surface->surface_id = surfaceID;
3463    *surface = surfaceID;
3464    obj_surface->context_id = -1;
3465    obj_surface->width = width;
3466    obj_surface->height = height;
3467    obj_surface->width_r = width;
3468    obj_surface->height_r = height;
3469    obj_surface->height_origin = height;
3470
3471    psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
3472    if (NULL == psb_surface) {
3473        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
3474        obj_surface->surface_id = VA_INVALID_SURFACE;
3475
3476        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
3477
3478        DEBUG_FAILURE;
3479    }
3480
3481    vaStatus = psb_surface_create_from_kbuf(driver_data, width, height,
3482                                            size,
3483                                            kBuf_fourcc,
3484                                            kbuf_handle,
3485                                            luma_stride,
3486                                            chroma_u_stride,
3487                                            chroma_v_stride,
3488                                            luma_offset,
3489                                            chroma_u_offset,
3490                                            chroma_v_offset,
3491                                            psb_surface);
3492
3493    if (VA_STATUS_SUCCESS != vaStatus) {
3494        free(psb_surface);
3495        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
3496        obj_surface->surface_id = VA_INVALID_SURFACE;
3497
3498        DEBUG_FAILURE;
3499    }
3500    buffer_stride = psb_surface->stride;
3501    /* by default, surface fourcc is NV12 */
3502    memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
3503    psb_surface->extra_info[4] = kBuf_fourcc;
3504    obj_surface->psb_surface = psb_surface;
3505
3506    /* Error recovery */
3507    if (VA_STATUS_SUCCESS != vaStatus) {
3508        object_surface_p obj_surface = SURFACE(surfaceID);
3509        psb__destroy_surface(driver_data, obj_surface);
3510        *surface = VA_INVALID_SURFACE;
3511    }
3512
3513    return vaStatus;
3514}
3515
3516
3517VAStatus psb_PutSurfaceBuf(
3518    VADriverContextP ctx,
3519    VASurfaceID surface,
3520    unsigned char* data,
3521    int* data_len,
3522    short srcx,
3523    short srcy,
3524    unsigned short srcw,
3525    unsigned short srch,
3526    short destx,
3527    short desty,
3528    unsigned short destw,
3529    unsigned short desth,
3530    VARectangle *cliprects, /* client supplied clip list */
3531    unsigned int number_cliprects, /* number of clip rects in the clip list */
3532    unsigned int flags /* de-interlacing flags */
3533)
3534{
3535    INIT_DRIVER_DATA;
3536    object_surface_p obj_surface = SURFACE(surface);
3537    psb_surface_p psb_surface;
3538
3539    obj_surface = SURFACE(surface);
3540    psb_surface = obj_surface->psb_surface;
3541
3542    psb_putsurface_textureblit(ctx, data, surface, srcx, srcy, srcw, srch, destx, desty, destw, desth, 1, /* check subpicture */
3543                               obj_surface->width, obj_surface->height,
3544                               psb_surface->stride, psb_surface->buf.drm_buf,
3545                               psb_surface->buf.pl_flags, 1 /* wrap dst */);
3546
3547    return VA_STATUS_SUCCESS;
3548}
3549
3550
3551int  LOCK_HARDWARE(psb_driver_data_p driver_data)
3552{
3553    char ret = 0;
3554
3555    if (driver_data->dri2 || driver_data->dri_dummy)
3556        return 0;
3557
3558    pthread_mutex_lock(&driver_data->drm_mutex);
3559    DRM_CAS(driver_data->drm_lock, driver_data->drm_context,
3560            (DRM_LOCK_HELD | driver_data->drm_context), ret);
3561    if (ret) {
3562        ret = drmGetLock(driver_data->drm_fd, driver_data->drm_context, 0);
3563        /* driver_data->contended_lock=1; */
3564    }
3565
3566    return ret;
3567}
3568
3569int UNLOCK_HARDWARE(psb_driver_data_p driver_data)
3570{
3571    /* driver_data->contended_lock=0; */
3572    if (driver_data->dri2 || driver_data->dri_dummy)
3573        return 0;
3574
3575    DRM_UNLOCK(driver_data->drm_fd, driver_data->drm_lock, driver_data->drm_context);
3576    pthread_mutex_unlock(&driver_data->drm_mutex);
3577
3578    return 0;
3579}
3580
3581
3582static void psb__deinitDRM(VADriverContextP ctx)
3583{
3584    INIT_DRIVER_DATA
3585    struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
3586
3587    if (driver_data->main_pool) {
3588        driver_data->main_pool->takeDown(driver_data->main_pool);
3589        driver_data->main_pool = NULL;
3590    }
3591    if (driver_data->fence_mgr) {
3592        wsbmFenceMgrTTMTakedown(driver_data->fence_mgr);
3593        driver_data->fence_mgr = NULL;
3594    }
3595
3596    if (wsbmIsInitialized())
3597        wsbmTakedown();
3598
3599    close(driver_data->drm_fd);
3600    driver_data->drm_fd = dri_state->fd = -1;
3601}
3602
3603
3604static VAStatus psb__initDRI(VADriverContextP ctx)
3605{
3606    INIT_DRIVER_DATA
3607    struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
3608
3609    assert(dri_state);
3610    assert(dri_state->driConnectedFlag == VA_DRI2 ||
3611           dri_state->driConnectedFlag == VA_DUMMY);
3612
3613    driver_data->drm_fd = dri_state->fd;
3614    driver_data->dri_dummy = (dri_state->driConnectedFlag == VA_DUMMY);
3615    driver_data->dri2 = (dri_state->driConnectedFlag == VA_DRI2);
3616    driver_data->ws_priv = NULL;
3617    driver_data->bus_id = NULL;
3618
3619    return VA_STATUS_SUCCESS;
3620}
3621
3622
3623static VAStatus psb__initTTM(VADriverContextP ctx)
3624{
3625    INIT_DRIVER_DATA
3626
3627    const char drm_ext[] = "psb_ttm_placement_alphadrop";
3628    union drm_psb_extension_arg arg;
3629    struct _WsbmBufferPool *pool;
3630    int ret;
3631    const char exec_ext[] = "psb_ttm_execbuf_alphadrop";
3632    union drm_psb_extension_arg exec_arg;
3633    const char lncvideo_getparam_ext[] = "lnc_video_getparam";
3634    union drm_psb_extension_arg lncvideo_getparam_arg;
3635
3636    /* init wsbm */
3637    ret = wsbmInit(wsbmNullThreadFuncs(), psbVNodeFuncs());
3638    if (ret) {
3639        psb__error_message("failed initializing libwsbm.\n");
3640        return VA_STATUS_ERROR_UNKNOWN;
3641    }
3642
3643    strncpy(arg.extension, drm_ext, sizeof(arg.extension));
3644    /* FIXME: should check dri enabled?
3645     * it seems not init dri here at all
3646     */
3647    ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION,
3648                              &arg, sizeof(arg));
3649    if (ret != 0 || !arg.rep.exists) {
3650        psb__error_message("failed to detect DRM extension \"%s\".\n",
3651                           drm_ext);
3652        driver_data->main_pool = NULL;
3653        return VA_STATUS_ERROR_UNKNOWN;
3654    } else {
3655        pool = wsbmTTMPoolInit(driver_data->drm_fd,
3656                               arg.rep.driver_ioctl_offset);
3657        if (pool == NULL) {
3658            psb__error_message("failed to get ttm pool\n");
3659            return VA_STATUS_ERROR_UNKNOWN;
3660        }
3661        driver_data->main_pool = pool;
3662    }
3663
3664    strncpy(exec_arg.extension, exec_ext, sizeof(exec_arg.extension));
3665    ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &exec_arg,
3666                              sizeof(exec_arg));
3667    if (ret != 0 || !exec_arg.rep.exists) {
3668        psb__error_message("failed to detect DRM extension \"%s\".\n",
3669                           exec_ext);
3670        return FALSE;
3671    }
3672    driver_data->execIoctlOffset = exec_arg.rep.driver_ioctl_offset;
3673
3674    strncpy(lncvideo_getparam_arg.extension, lncvideo_getparam_ext, sizeof(lncvideo_getparam_arg.extension));
3675    ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &lncvideo_getparam_arg,
3676                              sizeof(lncvideo_getparam_arg));
3677    if (ret != 0 || !lncvideo_getparam_arg.rep.exists) {
3678        psb__error_message("failed to detect DRM extension \"%s\".\n",
3679                           lncvideo_getparam_ext);
3680        /* return FALSE; */ /* not reture FALSE, so it still can run */
3681    }
3682    driver_data->getParamIoctlOffset = lncvideo_getparam_arg.rep.driver_ioctl_offset;
3683    return VA_STATUS_SUCCESS;
3684}
3685
3686static VAStatus psb__initDRM(VADriverContextP ctx)
3687{
3688    VAStatus vaStatus;
3689
3690    vaStatus = psb__initDRI(ctx);
3691
3692    if (vaStatus == VA_STATUS_SUCCESS)
3693        return psb__initTTM(ctx);
3694    else
3695        return vaStatus;
3696}
3697
3698VAStatus psb_Terminate(VADriverContextP ctx)
3699{
3700    INIT_DRIVER_DATA
3701    object_subpic_p obj_subpic;
3702    object_image_p obj_image;
3703    object_buffer_p obj_buffer;
3704    object_surface_p obj_surface;
3705    object_context_p obj_context;
3706    object_config_p obj_config;
3707    object_heap_iterator iter;
3708
3709    psb__information_message("vaTerminate: begin to tear down\n");
3710
3711    if (driver_data->bcd_registered != 0)
3712        if (VA_STATUS_SUCCESS != psb_release_video_bcd(ctx))
3713            return VA_STATUS_ERROR_UNKNOWN;
3714
3715    /* Clean up left over contexts */
3716    obj_context = (object_context_p) object_heap_first(&driver_data->context_heap, &iter);
3717    while (obj_context) {
3718        psb__information_message("vaTerminate: contextID %08x still allocated, destroying\n", obj_context->base.id);
3719        psb__destroy_context(driver_data, obj_context);
3720        obj_context = (object_context_p) object_heap_next(&driver_data->context_heap, &iter);
3721    }
3722    object_heap_destroy(&driver_data->context_heap);
3723
3724    /* Clean up SubpicIDs */
3725    obj_subpic = (object_subpic_p) object_heap_first(&driver_data->subpic_heap, &iter);
3726    while (obj_subpic) {
3727        psb__information_message("vaTerminate: subpictureID %08x still allocated, destroying\n", obj_subpic->base.id);
3728        psb__destroy_subpicture(driver_data, obj_subpic);
3729        obj_subpic = (object_subpic_p) object_heap_next(&driver_data->subpic_heap, &iter);
3730    }
3731    object_heap_destroy(&driver_data->subpic_heap);
3732
3733    /* Clean up ImageIDs */
3734    obj_image = (object_image_p) object_heap_first(&driver_data->image_heap, &iter);
3735    while (obj_image) {
3736        psb__information_message("vaTerminate: imageID %08x still allocated, destroying\n", obj_image->base.id);
3737        psb__destroy_image(driver_data, obj_image);
3738        obj_image = (object_image_p) object_heap_next(&driver_data->image_heap, &iter);
3739    }
3740    object_heap_destroy(&driver_data->image_heap);
3741
3742    /* Clean up left over buffers */
3743    obj_buffer = (object_buffer_p) object_heap_first(&driver_data->buffer_heap, &iter);
3744    while (obj_buffer) {
3745        psb__information_message("vaTerminate: bufferID %08x still allocated, destroying\n", obj_buffer->base.id);
3746        psb__destroy_buffer(driver_data, obj_buffer);
3747        obj_buffer = (object_buffer_p) object_heap_next(&driver_data->buffer_heap, &iter);
3748    }
3749    object_heap_destroy(&driver_data->buffer_heap);
3750
3751    /* Clean up left over surfaces */
3752
3753    /* Free PVR2D buffer wrapped from the surfaces */
3754    psb_free_surface_pvr2dbuf(driver_data);
3755    obj_surface = (object_surface_p) object_heap_first(&driver_data->surface_heap, &iter);
3756    while (obj_surface) {
3757        psb__information_message("vaTerminate: surfaceID %08x still allocated, destroying\n", obj_surface->base.id);
3758        psb__destroy_surface(driver_data, obj_surface);
3759        obj_surface = (object_surface_p) object_heap_next(&driver_data->surface_heap, &iter);
3760    }
3761    object_heap_destroy(&driver_data->surface_heap);
3762
3763    /* Clean up configIDs */
3764    obj_config = (object_config_p) object_heap_first(&driver_data->config_heap, &iter);
3765    while (obj_config) {
3766        object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
3767        obj_config = (object_config_p) object_heap_next(&driver_data->config_heap, &iter);
3768    }
3769    object_heap_destroy(&driver_data->config_heap);
3770
3771    if (driver_data->camera_bo) {
3772        psb__information_message("vaTerminate: clearup camera global BO\n");
3773
3774        psb_buffer_destroy((psb_buffer_p)driver_data->camera_bo);
3775        free(driver_data->camera_bo);
3776        driver_data->camera_bo = NULL;
3777    }
3778
3779    if (driver_data->rar_bo) {
3780        psb__information_message("vaTerminate: clearup RAR global BO\n");
3781
3782        psb_buffer_destroy((psb_buffer_p)driver_data->rar_bo);
3783        free(driver_data->rar_bo);
3784        driver_data->rar_bo = NULL;
3785    }
3786
3787    if (driver_data->ws_priv) {
3788        psb__information_message("vaTerminate: tear down output portion\n");
3789
3790        psb_deinitOutput(ctx);
3791        driver_data->ws_priv = NULL;
3792    }
3793
3794    psb__information_message("vaTerminate: de-initialized DRM\n");
3795
3796    psb__deinitDRM(ctx);
3797
3798    if (driver_data->msvdx_decode_status)
3799        free(driver_data->msvdx_decode_status);
3800
3801    if (driver_data->surface_mb_error)
3802        free(driver_data->surface_mb_error);
3803
3804    if (driver_data->bcd_buffer_surfaces)
3805        free(driver_data->bcd_buffer_surfaces);
3806
3807    free(ctx->pDriverData);
3808    free(ctx->vtable_egl);
3809    free(ctx->vtable_tpi);
3810
3811    ctx->pDriverData = NULL;
3812    psb__information_message("vaTerminate: goodbye\n\n");
3813
3814    psb__close_log();
3815
3816    return VA_STATUS_SUCCESS;
3817}
3818
3819EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx)
3820{
3821    psb_driver_data_p driver_data;
3822    struct VADriverVTableTPI *tpi;
3823    struct VADriverVTableEGL *va_egl;
3824    int result;
3825
3826#ifdef DEBUG_TRACE
3827    /* make gdb always stop here */
3828    signal(SIGUSR1, SIG_IGN);
3829    kill(getpid(), SIGUSR1);
3830#endif
3831
3832    psb__open_log();
3833
3834    psb__information_message("vaInitilize: start the journey\n");
3835
3836    ctx->version_major = 0;
3837    ctx->version_minor = 31;
3838
3839    ctx->max_profiles = PSB_MAX_PROFILES;
3840    ctx->max_entrypoints = PSB_MAX_ENTRYPOINTS;
3841    ctx->max_attributes = PSB_MAX_CONFIG_ATTRIBUTES;
3842    ctx->max_image_formats = PSB_MAX_IMAGE_FORMATS;
3843    ctx->max_subpic_formats = PSB_MAX_SUBPIC_FORMATS;
3844    ctx->max_display_attributes = PSB_MAX_DISPLAY_ATTRIBUTES;
3845
3846    ctx->vtable->vaTerminate = psb_Terminate;
3847    ctx->vtable->vaQueryConfigEntrypoints = psb_QueryConfigEntrypoints;
3848    ctx->vtable->vaTerminate = psb_Terminate;
3849    ctx->vtable->vaQueryConfigProfiles = psb_QueryConfigProfiles;
3850    ctx->vtable->vaQueryConfigEntrypoints = psb_QueryConfigEntrypoints;
3851    ctx->vtable->vaQueryConfigAttributes = psb_QueryConfigAttributes;
3852    ctx->vtable->vaCreateConfig = psb_CreateConfig;
3853    ctx->vtable->vaDestroyConfig = psb_DestroyConfig;
3854    ctx->vtable->vaGetConfigAttributes = psb_GetConfigAttributes;
3855    ctx->vtable->vaCreateSurfaces = psb_CreateSurfaces;
3856    ctx->vtable->vaDestroySurfaces = psb_DestroySurfaces;
3857    ctx->vtable->vaCreateContext = psb_CreateContext;
3858    ctx->vtable->vaDestroyContext = psb_DestroyContext;
3859    ctx->vtable->vaCreateBuffer = psb_CreateBuffer;
3860    ctx->vtable->vaBufferSetNumElements = psb_BufferSetNumElements;
3861    ctx->vtable->vaMapBuffer = psb_MapBuffer;
3862    ctx->vtable->vaUnmapBuffer = psb_UnmapBuffer;
3863    ctx->vtable->vaDestroyBuffer = psb_DestroyBuffer;
3864    ctx->vtable->vaBeginPicture = psb_BeginPicture;
3865    ctx->vtable->vaRenderPicture = psb_RenderPicture;
3866    ctx->vtable->vaEndPicture = psb_EndPicture;
3867    ctx->vtable->vaSyncSurface = psb_SyncSurface;
3868    ctx->vtable->vaQuerySurfaceStatus = psb_QuerySurfaceStatus;
3869    ctx->vtable->vaQuerySurfaceError = psb_QuerySurfaceError;
3870    ctx->vtable->vaPutSurface = psb_PutSurface;
3871    ctx->vtable->vaQueryImageFormats = psb_QueryImageFormats;
3872    ctx->vtable->vaCreateImage = psb_CreateImage;
3873    ctx->vtable->vaDeriveImage = psb_DeriveImage;
3874    ctx->vtable->vaDestroyImage = psb_DestroyImage;
3875    ctx->vtable->vaSetImagePalette = psb_SetImagePalette;
3876    ctx->vtable->vaGetImage = psb_GetImage;
3877    ctx->vtable->vaPutImage = psb_PutImage;
3878    ctx->vtable->vaQuerySubpictureFormats = psb_QuerySubpictureFormats;
3879    ctx->vtable->vaCreateSubpicture = psb_CreateSubpicture;
3880    ctx->vtable->vaDestroySubpicture = psb_DestroySubpicture;
3881    ctx->vtable->vaSetSubpictureImage = psb_SetSubpictureImage;
3882    ctx->vtable->vaSetSubpictureChromakey = psb_SetSubpictureChromakey;
3883    ctx->vtable->vaSetSubpictureGlobalAlpha = psb_SetSubpictureGlobalAlpha;
3884    ctx->vtable->vaAssociateSubpicture = psb_AssociateSubpicture;
3885    ctx->vtable->vaDeassociateSubpicture = psb_DeassociateSubpicture;
3886    ctx->vtable->vaQueryDisplayAttributes = psb_QueryDisplayAttributes;
3887    ctx->vtable->vaGetDisplayAttributes = psb_GetDisplayAttributes;
3888    ctx->vtable->vaSetDisplayAttributes = psb_SetDisplayAttributes;
3889    ctx->vtable->vaBufferInfo = psb_BufferInfo;
3890    ctx->vtable->vaLockSurface = psb_LockSurface;
3891    ctx->vtable->vaUnlockSurface = psb_UnlockSurface;
3892    ctx->vtable_tpi = calloc(1, sizeof(struct VADriverVTableTPI));
3893    if (NULL == ctx->vtable_tpi)
3894        return VA_STATUS_ERROR_ALLOCATION_FAILED;
3895
3896    tpi = (struct VADriverVTableTPI *)ctx->vtable_tpi;
3897    tpi->vaCreateSurfaceFromCIFrame = psb_CreateSurfaceFromCIFrame;
3898    tpi->vaCreateSurfaceFromV4L2Buf = psb_CreateSurfaceFromV4L2Buf;
3899    tpi->vaCreateSurfacesForUserPtr = psb_CreateSurfacesForUserPtr;
3900    tpi->vaCreateSurfaceFromKBuf = psb_CreateSurfaceFromKbuf;
3901    tpi->vaPutSurfaceBuf = psb_PutSurfaceBuf;
3902
3903    ctx->vtable_egl = calloc(1, sizeof(struct VADriverVTableEGL));
3904    if (NULL == ctx->vtable_egl)
3905        return VA_STATUS_ERROR_ALLOCATION_FAILED;
3906
3907    va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
3908    va_egl->vaGetEGLClientBufferFromSurface = psb_GetEGLClientBufferFromSurface;
3909
3910    driver_data = (psb_driver_data_p) calloc(1, sizeof(*driver_data));
3911    ctx->pDriverData = (unsigned char *) driver_data;
3912    if (NULL == driver_data) {
3913        if (ctx->vtable_tpi)
3914            free(ctx->vtable_tpi);
3915        if (ctx->vtable_egl)
3916            free(ctx->vtable_egl);
3917        return VA_STATUS_ERROR_ALLOCATION_FAILED;
3918    }
3919
3920    if (VA_STATUS_SUCCESS != psb__initDRM(ctx)) {
3921        free(ctx->pDriverData);
3922        ctx->pDriverData = NULL;
3923        return VA_STATUS_ERROR_UNKNOWN;
3924    }
3925
3926    pthread_mutex_init(&driver_data->drm_mutex, NULL);
3927
3928    /*
3929     * To read PBO.MSR.CCF Mode and Status Register C-Spec -p112
3930     */
3931#define PCI_PORT5_REG80_VIDEO_SD_DISABLE        0x0008
3932#define PCI_PORT5_REG80_VIDEO_HD_DISABLE        0x0010
3933
3934#if 0
3935    struct drm_psb_hw_info hw_info;
3936    do {
3937        result = drmCommandRead(driver_data->drm_fd, DRM_PSB_HW_INFO, &hw_info, sizeof(hw_info));
3938    } while (result == EAGAIN);
3939
3940    if (result != 0) {
3941        psb__deinitDRM(ctx);
3942        free(ctx->pDriverData);
3943        ctx->pDriverData = NULL;
3944        return VA_STATUS_ERROR_UNKNOWN;
3945    }
3946
3947    driver_data->video_sd_disabled = !!(hw_info.caps & PCI_PORT5_REG80_VIDEO_SD_DISABLE);
3948    driver_data->video_hd_disabled = !!(hw_info.caps & PCI_PORT5_REG80_VIDEO_HD_DISABLE);
3949    psb__information_message("hw_info: rev_id = %08x capabilities = %08x\n", hw_info.rev_id, hw_info.caps);
3950    psb__information_message("hw_info: video_sd_disable=%d,video_hd_disable=%d\n",
3951                             driver_data->video_sd_disabled, driver_data->video_hd_disabled);
3952    if (driver_data->video_sd_disabled != 0) {
3953        psb__error_message("MRST: hw_info shows video_sd_disable is true,fix it manually\n");
3954        driver_data->video_sd_disabled = 0;
3955    }
3956    if (driver_data->video_hd_disabled != 0) {
3957        psb__error_message("MRST: hw_info shows video_hd_disable is true,fix it manually\n");
3958        driver_data->video_hd_disabled = 0;
3959    }
3960#endif
3961
3962    if (0 != psb_get_device_info(ctx)) {
3963        psb__error_message("ERROR: failed to get video device info\n");
3964        driver_data->encode_supported = 1;
3965        driver_data->decode_supported = 1;
3966        driver_data->hd_encode_supported = 1;
3967        driver_data->hd_decode_supported = 1;
3968    }
3969
3970    psb_init_surface_pvr2dbuf(driver_data);
3971
3972    struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
3973    if (dri_state->driConnectedFlag == VA_DRI1 ||
3974        dri_state->driConnectedFlag == VA_DRI2 ||
3975        dri_state->driConnectedFlag == VA_DUMMY) {
3976        if (VA_STATUS_SUCCESS != psb_initOutput(ctx)) {
3977            psb__deinitDRM(ctx);
3978            free(ctx->pDriverData);
3979            ctx->pDriverData = NULL;
3980            return VA_STATUS_ERROR_UNKNOWN;
3981        }
3982    }
3983
3984    driver_data->msvdx_context_base = (((unsigned int) getpid()) & 0xffff) << 16;
3985#ifdef PSBVIDEO_MFLD
3986    if (IS_MFLD(driver_data)) {
3987        driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &pnw_H263ES_vtable;
3988        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &pnw_H264ES_vtable;
3989        driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &pnw_H264ES_vtable;
3990        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &pnw_MPEG4ES_vtable;
3991        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &pnw_MPEG4ES_vtable;
3992        driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointEncPicture] = &pnw_JPEG_vtable;
3993
3994        driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &pnw_MPEG2_vtable;
3995
3996        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &pnw_MPEG4_vtable;
3997        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &pnw_MPEG4_vtable;
3998
3999        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &pnw_H264_vtable;
4000        driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &pnw_H264_vtable;
4001        driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &pnw_H264_vtable;
4002
4003        driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &pnw_VC1_vtable;
4004        driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &pnw_VC1_vtable;
4005        driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &pnw_VC1_vtable;
4006        driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &pnw_H264_vtable;
4007    }
4008#endif
4009#ifdef PSBVIDEO_MRST
4010    if (IS_MRST(driver_data)) {
4011    driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &psb_MPEG2_vtable;
4012    driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointMoComp] = &psb_MPEG2MC_vtable;
4013
4014    driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &psb_MPEG4_vtable;
4015    driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &psb_MPEG4_vtable;
4016
4017    driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &psb_H264_vtable;
4018    driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &psb_H264_vtable;
4019    driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &psb_H264_vtable;
4020    driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &psb_H264_vtable;
4021
4022    driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &psb_VC1_vtable;
4023    driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &psb_VC1_vtable;
4024    driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &psb_VC1_vtable;
4025    driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &psb_H264_vtable;
4026
4027    if(driver_data->encode_supported) {
4028
4029        driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &lnc_H263ES_vtable;
4030        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &lnc_H264ES_vtable;
4031        driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &lnc_H264ES_vtable;
4032        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &lnc_MPEG4ES_vtable;
4033        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &lnc_MPEG4ES_vtable;
4034    }
4035}
4036#endif
4037    result = object_heap_init(&driver_data->config_heap, sizeof(struct object_config_s), CONFIG_ID_OFFSET);
4038    ASSERT(result == 0);
4039
4040    result = object_heap_init(&driver_data->context_heap, sizeof(struct object_context_s), CONTEXT_ID_OFFSET);
4041    ASSERT(result == 0);
4042
4043    result = object_heap_init(&driver_data->surface_heap, sizeof(struct object_surface_s), SURFACE_ID_OFFSET);
4044    ASSERT(result == 0);
4045
4046    result = object_heap_init(&driver_data->buffer_heap, sizeof(struct object_buffer_s), BUFFER_ID_OFFSET);
4047    ASSERT(result == 0);
4048
4049    result = object_heap_init(&driver_data->image_heap, sizeof(struct object_image_s), IMAGE_ID_OFFSET);
4050    ASSERT(result == 0);
4051
4052    result = object_heap_init(&driver_data->subpic_heap, sizeof(struct object_subpic_s), SUBPIC_ID_OFFSET);
4053    ASSERT(result == 0);
4054
4055    driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
4056    driver_data->last_displaying_surface = VA_INVALID_SURFACE;
4057
4058    driver_data->clear_color = 0;
4059    driver_data->blend_color = 0;
4060    driver_data->blend_mode = 0;
4061    driver_data->overlay_auto_paint_color_key = 0;
4062
4063    if (IS_MFLD(driver_data))
4064        ctx->str_vendor = PSB_STR_VENDOR_MFLD;
4065    else
4066        ctx->str_vendor = PSB_STR_VENDOR_MRST;
4067
4068
4069    driver_data->msvdx_decode_status = calloc(1, sizeof(drm_psb_msvdx_decode_status_t));
4070    if (NULL == driver_data->msvdx_decode_status) {
4071        return VA_STATUS_ERROR_ALLOCATION_FAILED;
4072    }
4073    driver_data->surface_mb_error = calloc(MAX_MB_ERRORS, sizeof(VASurfaceDecodeMBErrors));
4074    if (NULL == driver_data->surface_mb_error) {
4075        return VA_STATUS_ERROR_ALLOCATION_FAILED;
4076    }
4077
4078    psb__information_message("vaInitilize: succeeded!\n\n");
4079
4080#ifdef ANDROID
4081    gralloc_init();
4082#endif
4083    return VA_STATUS_SUCCESS;
4084}
4085
4086
4087EXPORT VAStatus __vaDriverInit_0_32(VADriverContextP ctx)
4088{
4089    return __vaDriverInit_0_31(ctx);
4090}
4091
4092
4093
4094static int psb_get_device_info(VADriverContextP ctx)
4095{
4096    INIT_DRIVER_DATA;
4097    struct drm_lnc_video_getparam_arg arg;
4098    unsigned long device_info;
4099    int ret = 0;
4100    unsigned long video_capability;
4101    unsigned long pci_device;
4102
4103    driver_data->dev_id = 0x4100; /* by default MRST */
4104
4105    arg.key = LNC_VIDEO_DEVICE_INFO;
4106    arg.value = (uint64_t)((unsigned long) & device_info);
4107    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
4108                              &arg, sizeof(arg));
4109    if (ret != 0) {
4110        psb__information_message("failed to get video device info\n");
4111        return ret;
4112    }
4113
4114    pci_device = (device_info >> 16) & 0xffff;
4115    video_capability = device_info & 0xffff;
4116
4117    driver_data->dev_id = pci_device;
4118    psb__information_message("Retrieve Device ID 0x%04x\n", driver_data->dev_id);
4119
4120    if ((IS_MRST(driver_data) && (pci_device != 0x4101)) ||
4121        IS_MFLD(driver_data))
4122        driver_data->encode_supported = 1;
4123    else /* 0x4101 or other device hasn't encode support */
4124        driver_data->encode_supported = 0;
4125
4126    if (IS_MRST(driver_data)) {
4127        driver_data->decode_supported = !(video_capability & 0x2);
4128        driver_data->hd_decode_supported = !(video_capability & 0x3);
4129        driver_data->hd_encode_supported = !(video_capability & 0x4);
4130
4131        psb__information_message("video capability: decode %s, HD decode %s\n",
4132                                 driver_data->decode_supported ? "support" : "not support",
4133                                 driver_data->hd_decode_supported ? "support" : "not support");
4134
4135        psb__information_message("video capability: encode %s, HD encode %s\n",
4136                                 driver_data->encode_supported ? "support" : "not support",
4137                                 driver_data->hd_encode_supported ? "support" : "not support");
4138
4139    } else {
4140        driver_data->decode_supported = 1;
4141        driver_data->hd_decode_supported = 1;
4142        driver_data->hd_encode_supported = 1;
4143    }
4144
4145    return ret;
4146}
4147