psb_output_android.c revision 0a86723905982451dd72a9cad792b8cb8e8528ae
1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Zhaohan Ren  <zhaohan.ren@intel.com>
26 *    Shengquan Yuan  <shengquan.yuan@intel.com>
27 *    Jiang Fei <jiang.fei@intel.com>
28 *    Binglin Chen <binglin.chen@intel.com>
29 *
30 */
31
32#include <va/va_backend.h>
33#include "psb_output.h"
34#include "psb_surface.h"
35#include "psb_buffer.h"
36#include "psb_overlay.h"
37#include "psb_texture.h"
38#include <stdio.h>
39#include <string.h>
40#include <stdarg.h>
41#include "psb_android_glue.h"
42#include "psb_texstreaming.h"
43#include "psb_output_android.h"
44#include "psb_HDMIExtMode.h"
45#include "pnw_rotate.h"
46#include <wsbm/wsbm_manager.h>
47#include <psb_drm.h>
48#include <hardware.h>
49
50#define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
51#define INIT_OUTPUT_PRIV    psb_android_output_p output = (psb_android_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
52
53#define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
54#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
55#define IMAGE(id)  ((object_image_p) object_heap_lookup( &driver_data->image_heap, id ))
56#define SUBPIC(id)  ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id ))
57#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
58
59#define GET_SURFACE_INFO_rotate(psb_surface) ((int) psb_surface->extra_info[5])
60#define GET_SURFACE_INFO_protect(psb_surface) ((int) psb_surface->extra_info[6])
61#define MAX_OVERLAY_IDLE_FRAME 4
62
63enum {
64    eWidiOff             = 1,
65    eWidiClone           = 2,
66    eWidiExtendedVideo   = 3,
67};
68extern unsigned int update_forced;
69
70inline int va2hw_rotation(int va_rotate)
71{
72    switch (va_rotate) {
73    case VA_ROTATION_90:
74        return HAL_TRANSFORM_ROT_270;
75    case VA_ROTATION_180:
76        return HAL_TRANSFORM_ROT_180;
77    case VA_ROTATION_270:
78        return HAL_TRANSFORM_ROT_90;
79defaut:
80        return 0;
81    }
82
83    return 0;
84}
85
86void *psb_android_output_init(VADriverContextP ctx)
87{
88    INIT_DRIVER_DATA;
89    char put_surface[1024];
90    struct drm_psb_register_rw_arg regs;
91    psb_android_output_p output = calloc(1, sizeof(psb_android_output_s));
92    struct fb_var_screeninfo vinfo;
93    int fbfd = -1;
94    int ret;
95
96    if (output == NULL) {
97        psb__error_message("Can't malloc memory\n");
98        return NULL;
99    }
100    memset(output, 0, sizeof(psb_android_output_s));
101
102    /* Guess the screen size */
103    output->screen_width = 800;
104    output->screen_height = 480;
105
106    // Open the frame buffer for reading
107    memset(&vinfo, 0, sizeof(vinfo));
108    fbfd = open("/dev/graphics/fb0", O_RDONLY);
109    if (fbfd) {
110        if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
111            psb__information_message("Error reading screen information.\n");
112    }
113    close(fbfd);
114    output->screen_width = vinfo.xres;
115    output->screen_height = vinfo.yres;
116
117    /* TS by default */
118    driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
119    driver_data->color_key = 0x000001; /*light blue*/
120    driver_data->overlay_idle_frame = 1;
121
122    if (psb_parse_config("PSB_VIDEO_CTEXTURES", &put_surface[0]) == 0) {
123        psb__information_message("PSB_VIDEO_CTEXTURES is enabled for vaPutSurfaceBuf\n");
124        driver_data->ctexture = 1; /* Init CTEXTURE for vaPutSurfaceBuf */
125    }
126
127    if (psb_parse_config("PSB_VIDEO_TS", &put_surface[0]) == 0) {
128        psb__information_message("Putsurface use texstreaming\n");
129        driver_data->output_method = PSB_PUTSURFACE_FORCE_TEXSTREAMING;
130    }
131
132    if (psb_parse_config("PSB_VIDEO_COVERLAY", &put_surface[0]) == 0) {
133        psb__information_message("Putsurface use client overlay\n");
134        driver_data->output_method = PSB_PUTSURFACE_FORCE_COVERLAY;
135    }
136
137    if (IS_MFLD(driver_data)) {
138        driver_data->coverlay = 1;
139        output->psb_HDMIExt_info = psb_HDMIExt_init(ctx, output);
140        if (!output->psb_HDMIExt_info) {
141            psb__error_message("Failed to init psb_HDMIExt.\n");
142            free(output);
143            return NULL;
144        }
145    }
146
147    return output;
148}
149
150VAStatus psb_android_output_deinit(VADriverContextP ctx)
151{
152    INIT_DRIVER_DATA;
153    INIT_OUTPUT_PRIV;
154    //psb_android_output_p output = GET_OUTPUT_DATA(ctx);
155    if (IS_MFLD(driver_data)) {
156        psb_HDMIExt_deinit(output);
157    }
158
159    return VA_STATUS_SUCCESS;
160}
161
162static VAStatus psb_putsurface_ctexture(
163    VADriverContextP ctx,
164    VASurfaceID surface,
165    unsigned char* data,
166    short srcx,
167    short srcy,
168    unsigned short srcw,
169    unsigned short srch,
170    short destx,
171    short desty,
172    unsigned short destw,
173    unsigned short desth,
174    unsigned int flags /* de-interlacing flags */
175)
176{
177    INIT_DRIVER_DATA;
178    INIT_OUTPUT_PRIV;
179    object_surface_p obj_surface = SURFACE(surface);
180    int offset = 0;
181    psb_surface_p psb_surface;
182
183    obj_surface = SURFACE(surface);
184    psb_surface = obj_surface->psb_surface;
185
186    //    psb_surface->buf.drm_buf;
187    //    psb_surface->buf.pl_flags;
188    psb_putsurface_textureblit(ctx, data, surface, srcx, srcy, srcw, srch,
189                               destx, desty, destw, desth, 0, /* no subtitle */
190                               obj_surface->width, obj_surface->height,
191                               psb_surface->stride, psb_surface->buf.drm_buf,
192                               psb_surface->buf.pl_flags, 1 /* need wrap dst */);
193
194    psb_android_postBuffer(offset);
195
196    return VA_STATUS_SUCCESS;
197}
198
199VAStatus psb_putsurface_coverlay(
200    VADriverContextP ctx,
201    VASurfaceID surface,
202    short srcx,
203    short srcy,
204    unsigned short srcw,
205    unsigned short srch,
206    short destx, /* screen cooridination */
207    short desty,
208    unsigned short destw,
209    unsigned short desth,
210    unsigned int flags /* de-interlacing flags */
211)
212{
213    INIT_OUTPUT_PRIV;
214    VAStatus vaStatus = VA_STATUS_SUCCESS;
215
216    /* USE_FIT_SCR_SIZE */
217    /* calculate fit screen size of frame */
218    unsigned short _scr_x = output->screen_width;
219    unsigned short _scr_y = output->screen_height;
220    float _slope_xy = (float)srch / srcw;
221    unsigned short _destw = (short)(_scr_y / _slope_xy);
222    unsigned short _desth = (short)(_scr_x * _slope_xy);
223    short _pos_x, _pos_y;
224
225    if (_destw <= _scr_x) {
226        _desth = _scr_y;
227        _pos_x = (_scr_x - _destw) >> 1;
228        _pos_y = 0;
229    } else {
230        _destw = _scr_x;
231        _pos_x = 0;
232        _pos_y = (_scr_y - _desth) >> 1;
233    }
234    destx += _pos_x;
235    desty += _pos_y;
236    destw = _destw;
237    desth = _desth;
238
239    psb__information_message("psb_putsurface_overlay: src (%d, %d, %d, %d), destx (%d, %d, %d, %d).\n",
240                             srcx, srcy, srcw, srch, destx, desty, destw, desth);
241    /* display by overlay */
242    vaStatus = psb_putsurface_overlay(
243                   ctx, surface, srcx, srcy, srcw, srch,
244                   destx, desty, destw, desth, /* screen coordinate */
245                   flags, OVERLAY_A, PIPEA);
246
247    return vaStatus;
248}
249
250
251VAStatus psb_putsurface_ts(
252    VADriverContextP ctx,
253    VASurfaceID surface,
254    void *android_isurface,
255    int buffer_index,
256    short srcx,
257    short srcy,
258    unsigned short srcw,
259    unsigned short srch,
260    short destx,
261    short desty,
262    unsigned short destw,
263    unsigned short desth,
264    VARectangle *cliprects, /* client supplied clip list */
265    unsigned int number_cliprects, /* number of clip rects in the clip list */
266    unsigned int flags /* de-interlacing flags */
267)
268{
269    INIT_DRIVER_DATA;
270    INIT_OUTPUT_PRIV;
271    object_surface_p obj_surface = SURFACE(surface);
272
273    if (driver_data->overlay_idle_frame == 0) {
274        psb_android_texture_streaming_resetParams();
275        update_forced = 1;
276    }
277
278    /* blend/positioning setting can be called by app directly, or enable VA_ENABLE_BLEND flag to let driver call */
279    if (flags & VA_ENABLE_BLEND)
280        psb_android_texture_streaming_set_blend(destx, desty, destw, desth,
281                                                driver_data->clear_color,
282                                                driver_data->blend_color,
283                                                driver_data->blend_mode);
284    /*cropping can be also used for dynamic resolution change feature, only high to low resolution*/
285    /*by default, srcw and srch is set to video width and height*/
286    if ((0 == srcw) || (0 == srch)) {
287        srcw = obj_surface->width;
288        srch = obj_surface->height_origin;
289    }
290    psb_android_texture_streaming_set_texture_dim(srcw, srch);
291    if (driver_data->va_rotate)
292        psb_android_texture_streaming_set_rotate(va2hw_rotation(driver_data->va_rotate));
293
294#if 0
295    /* use cliprect for crop */
296    if (cliprects && (number_cliprects == 1))
297        psb_android_texture_streaming_set_crop(cliprects->x, cliprects->y, cliprects->width, cliprects->height);
298#endif
299
300    psb_android_texture_streaming_display(buffer_index);
301
302    driver_data->overlay_idle_frame++;
303    update_forced = 0;
304
305    return VA_STATUS_SUCCESS;
306}
307
308
309static int psb_update_destbox(
310    VADriverContextP ctx
311)
312{
313    INIT_DRIVER_DATA;
314    INIT_OUTPUT_PRIV;
315    short destx;
316    short desty;
317    unsigned short destw;
318    unsigned short desth;
319    VAStatus vaStatus = VA_STATUS_SUCCESS;
320
321    psb_android_get_destbox(&destx, &desty, &destw, &desth);
322    /*psb__information_message("destbox = (%d,%d,%d,%d)\n", destx, desty, destw, desth);*/
323    if ((destx >= 0) && (desty >= 0) &&
324            ((destx + destw) <= output->screen_width) &&
325            ((desty + desth) <= output->screen_height) &&
326            (output->destx != destx ||
327             output->desty != desty ||
328             output->destw != destw ||
329             output->desth != desth)) {
330        output->destx = destx;
331        output->desty = desty;
332        output->destw = destw;
333        output->desth = desth;
334        output->new_destbox = 1;
335
336        LOGD("==========New Destbox=============\n");
337        LOGD("output->destbox = (%d,%d,%d,%d)\n", output->destx, output->desty, output->destw, output->desth);
338    }
339
340    return vaStatus;
341}
342
343static int psb_check_outputmethod(
344    VADriverContextP ctx,
345    VASurfaceID surface,
346    unsigned short srcw,
347    unsigned short srch,
348    void *android_isurface,
349    psb_hdmi_mode *hdmi_mode
350)
351{
352    INIT_DRIVER_DATA;
353    INIT_OUTPUT_PRIV;
354    psb_HDMIExt_info_p psb_HDMIExt_info = (psb_HDMIExt_info_p)output->psb_HDMIExt_info;
355    object_surface_p obj_surface;
356    int rotation = 0, widi = 0;
357    int delta_rotation = 0;
358    int srf_rotate; /* primary surface rotation */
359    psb_surface_p rotate_surface; /* rotate surface */
360    int rotate_srf_rotate = -1; /* degree of the rotate surface */
361
362    if ((srcw >= 2048) || (srch >= 2048)) {
363        psb__information_message("Clip size extend overlay hw limit, use texstreaming\n");
364        driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
365        return 0;
366    }
367
368    /* use saved status to avoid per-frame checking */
369    if ((driver_data->frame_count % driver_data->outputmethod_checkinterval) != 0) {
370        *hdmi_mode = psb_HDMIExt_get_mode(output);
371        return 0;
372    }
373
374    /* check the status at outputmethod_checkinterval frequency */
375    /* at first check HDMI status */
376    if (psb_HDMIExt_update(ctx, psb_HDMIExt_info)) {
377        psb__error_message("%s: Failed to update HDMIExt info.\n", __FUNCTION__);
378        return -1;
379    }
380
381    *hdmi_mode = psb_HDMIExt_get_mode(output);
382    if ((*hdmi_mode == EXTENDED_VIDEO) || (*hdmi_mode == CLONE)) {
383        unsigned short _destw, _desth;
384        short _pos_x, _pos_y;
385        unsigned short crtc_width = 0, crtc_height = 0;
386        float _slope_xy;
387
388        /* need to handle VA rotation, and set WM rotate to 0
389         * for Android, MIPI0/HDMI has the same WM rotation always
390         */
391        if (driver_data->mipi0_rotation != 0) {
392            driver_data->mipi0_rotation = 0;
393            driver_data->hdmi_rotation = 0;
394            output->new_destbox = 1;
395            psb_RecalcRotate(ctx);
396        }
397
398        psb_HDMIExt_get_prop(output, &crtc_width, &crtc_height);
399
400        /*recalculate the render box to fit the ratio of height/width*/
401        if ((driver_data->extend_rotation == VA_ROTATION_90) ||
402            (driver_data->extend_rotation == VA_ROTATION_270))
403            _slope_xy = (float)srcw / srch;
404        else
405            _slope_xy = (float)srch / srcw;
406
407        _destw = (short)(crtc_height / _slope_xy);
408        _desth = (short)(crtc_width * _slope_xy);
409        if (_destw <= crtc_width) {
410            _desth = crtc_height;
411            _pos_x = (crtc_width - _destw) >> 1;
412            _pos_y = 0;
413        } else {
414            _destw = crtc_width;
415            _pos_x = 0;
416            _pos_y = (crtc_height - _desth) >> 1;
417        }
418        driver_data->render_rect.x = _pos_x;
419        driver_data->render_rect.y = _pos_y;
420        driver_data->render_rect.width = _destw;
421        driver_data->render_rect.height = _desth;
422        psb__information_message("HDMI mode is on (%d), Render Rect: (%d,%d,%d,%d)\n",
423                                 *hdmi_mode,
424                                 driver_data->render_rect.x, driver_data->render_rect.y,
425                                 driver_data->render_rect.width, driver_data->render_rect.height);
426        return 0;
427    }
428
429    /*Update output destbox using layerbuffer's visible region*/
430    psb_update_destbox(ctx);
431
432    if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_COVERLAY)
433        || (driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXSTREAMING))
434        return 0;
435
436    /*If overlay can not get correct destbox, use texstreaming.*/
437    if (output->destw == 0 || output->desth == 0 ||
438        ((output->destw == srcw) && (output->desth == srch))) {
439        psb__information_message("No proper destbox, use texstreaming (%dx%d+%d+%d)\n",
440                                 output->destw, output->desth, output->destx, output->desty);
441        driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
442        return 0;
443    }
444
445    /* HDMI is not enabled */
446    psb_android_surfaceflinger_status(android_isurface, &output->sf_composition, &rotation, &widi);
447    if (widi == eWidiClone) {
448        psb__information_message("WIDI service is detected, use texstreaming\n");
449        driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
450        driver_data->msvdx_rotate_want = 0;/* disable msvdx rotae */
451
452        return 0;
453    }
454
455    /* only care local rotation */
456    delta_rotation = Rotation2Angle(driver_data->mipi0_rotation) - Rotation2Angle(rotation);
457    if ((((abs(delta_rotation) == 90) || (abs(delta_rotation) == 270)) && output->new_destbox) ||
458        (abs(delta_rotation) == 180)) {
459        psb__information_message("New rotation degree %d of MIPI0 WM, Recalc rotation\n", rotation);
460        driver_data->mipi0_rotation = rotation;
461        driver_data->hdmi_rotation = rotation;
462
463        psb_RecalcRotate(ctx);
464    }
465    output->new_destbox = 0;
466
467    obj_surface = SURFACE(surface);
468    if (GET_SURFACE_INFO_protect(obj_surface->psb_surface)) {
469        psb__information_message("Protected surface, use overlay\n");
470        driver_data->output_method = PSB_PUTSURFACE_COVERLAY;
471
472        return 0;
473    }
474
475    if (output->sf_composition) {
476        psb__information_message("Composition is detected, use texstreaming\n");
477        driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
478        return 0;
479    }
480
481    srf_rotate = GET_SURFACE_INFO_rotate(obj_surface->psb_surface);
482    rotate_surface = obj_surface->psb_surface_rotate;
483    if (rotate_surface != NULL)
484        rotate_srf_rotate = GET_SURFACE_INFO_rotate(rotate_surface);
485
486    psb__information_message("SF rotation %d, VA rotation %d, final MSVDX rotation %d\n",
487                             rotation, driver_data->va_rotate, driver_data->local_rotation);
488    psb__information_message("Primary surface rotation %d, rotated surface rotation %d\n",
489                             srf_rotate, rotate_srf_rotate);
490
491    /* The surface rotation is not same with the final rotation */
492    if ((driver_data->local_rotation != 0) &&
493        ((srf_rotate != driver_data->local_rotation) || (rotate_srf_rotate != driver_data->local_rotation))) {
494        psb__information_message("Use texstreaming due to different VA surface rotation and final rotaion\n",
495                                 srf_rotate, rotate_srf_rotate);
496        driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
497        return 0;
498    }
499
500    driver_data->output_method = PSB_PUTSURFACE_COVERLAY;
501
502    return 0;
503}
504
505VAStatus psb_PutSurface(
506    VADriverContextP ctx,
507    VASurfaceID surface,
508    void *android_isurface,
509    short srcx,
510    short srcy,
511    unsigned short srcw,
512    unsigned short srch,
513    short destx,
514    short desty,
515    unsigned short destw,
516    unsigned short desth,
517    VARectangle *cliprects, /* client supplied clip list */
518    unsigned int number_cliprects, /* number of clip rects in the clip list */
519    unsigned int flags /* de-interlacing flags */
520)
521{
522    INIT_DRIVER_DATA;
523    INIT_OUTPUT_PRIV;
524    object_surface_p obj_surface;
525    VAStatus vaStatus = VA_STATUS_SUCCESS;
526    PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
527    psb_hdmi_mode hdmi_mode = OFF;
528    int sf_composition = 0, buffer_index = 0, i = 0;
529    uint32_t ttm_handle;
530    psb_surface_p psb_surface;
531
532    obj_surface = SURFACE(surface);
533    if (NULL == obj_surface) {
534        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
535        DEBUG_FAILURE;
536        return vaStatus;
537    }
538
539    if ((NULL == cliprects) && (0 != number_cliprects)) {
540        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
541        DEBUG_FAILURE;
542        return vaStatus;
543    }
544
545    if ((srcx < 0) || (srcx > obj_surface->width) || (srcw > (obj_surface->width - srcx)) ||
546            (srcy < 0) || (srcy > obj_surface->height_origin) || (srch > (obj_surface->height_origin - srcy))) {
547        psb__error_message("vaPutSurface: source rectangle passed from upper layer is not correct.\n");
548        return VA_STATUS_ERROR_UNKNOWN;
549    }
550    if ((destx < 0) || (desty < 0)) {
551        psb__error_message("vaPutSurface: dest rectangle passed from upper layer is not correct.\n");
552        return VA_STATUS_ERROR_UNKNOWN;
553    }
554
555    if (driver_data->dummy_putsurface) {
556        psb__information_message("vaPutSurface: dummy mode, return directly\n");
557        return VA_STATUS_SUCCESS;
558    }
559
560    /*get bcd buffer index of current surface*/
561    psb_surface = obj_surface->psb_surface;
562    ttm_handle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
563
564    for (i = 0; i < driver_data->bcd_buffer_num; i++) {
565        if (driver_data->bcd_ttm_handles[i] == ttm_handle)
566            break;
567    }
568    if (i == driver_data->bcd_buffer_num) {
569        psb__error_message("Failed to get buffer index.\n");
570        return VA_STATUS_ERROR_UNKNOWN;
571    }
572    buffer_index = i;
573
574    /* set the current displaying video frame into kernel */
575    psb_surface_set_displaying(driver_data, obj_surface->width, obj_surface->height_origin, obj_surface->psb_surface);
576
577    /* exit MRST path at first */
578    if (IS_MRST(driver_data)) {
579        if (driver_data->output_method == PSB_PUTSURFACE_FORCE_COVERLAY) { /* overlay is for testing, not POR */
580            psb__information_message("Force overlay to display\n");
581            vaStatus = psb_putsurface_coverlay(ctx, surface,
582                                               srcx, srcy, srcw, srch,
583                                               destx, desty, destw, desth,
584                                               flags);
585        } else {
586            psb__information_message("Use texstreaming to display.\n");
587            vaStatus = psb_putsurface_ts(ctx, surface, android_isurface, buffer_index,
588                                         srcx, srcy, srcw, srch,
589                                         destx, desty, destw, desth,
590                                         cliprects, number_cliprects, /* number of clip rects in the clip list */
591                                         flags);
592        }
593
594        return vaStatus;
595    }
596
597    if (psb_android_register_isurface(android_isurface, driver_data->bcd_id, srcw, srch)) {
598        psb__error_message("In psb_PutSurface, android_isurface is not a valid isurface object.\n");
599        return VA_STATUS_ERROR_UNKNOWN;
600    }
601
602    /* time for MFLD platform */
603    psb_check_outputmethod(ctx, surface, srcw, srch, android_isurface, &hdmi_mode);
604
605    if (hdmi_mode == UNDEFINED) {
606        psb__information_message("HDMI: Undefined mode, drop the frame.\n");
607        return vaStatus;
608    }
609
610    /* Extvideo: Use overlay to render external HDMI display */
611    if (hdmi_mode == EXTENDED_VIDEO) {
612        psb__information_message("HDMI: ExtVideo mode enabled, use overlay to render external HDMI display.\n");
613        /*we also need to clear local display if colorkey dirty.*/
614        if (driver_data->overlay_idle_frame != 0) {
615            psb_android_texture_streaming_set_background_color(driver_data->color_key | 0xff000000);
616            psb_android_texture_streaming_display(buffer_index);
617            driver_data->overlay_idle_frame = 0;
618        }
619        vaStatus = psb_putsurface_overlay(ctx, surface,
620                                          srcx, srcy, srcw, srch,
621                                          driver_data->render_rect.x, driver_data->render_rect.y,
622                                          driver_data->render_rect.width, driver_data->render_rect.height,
623                                          flags, OVERLAY_A, PIPEB);
624
625        return vaStatus;
626    }
627
628    /* Clone mode: Use TS to render both MIPI and HDMI display */
629    if (hdmi_mode == CLONE) {
630        psb__information_message("HDMI: Clone mode enabled, use texsteaming for both devices\n");
631        vaStatus = psb_putsurface_ts(ctx, surface, android_isurface, buffer_index,
632                                     srcx, srcy, srcw, srch,
633                                     destx, desty, destw, desth,
634                                     cliprects, number_cliprects, /* number of clip rects in the clip list */
635                                     flags);
636        return vaStatus;
637    }
638
639    /* local video playback */
640    if ((driver_data->output_method == PSB_PUTSURFACE_TEXSTREAMING) ||
641        (driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXSTREAMING)) {
642        psb__information_message("MIPI: Use texstreaming to display.\n");
643
644        vaStatus = psb_putsurface_ts(ctx, surface, android_isurface, buffer_index,
645                                     srcx, srcy, srcw, srch,
646                                     destx, desty, destw, desth,
647                                     cliprects, number_cliprects, /* number of clip rects in the clip list */
648                                     flags);
649    } else {
650        psb__information_message("MIPI: Use overlay to display.\n");
651
652        /*initialize output destbox using default destbox if it has not been initialized until here.*/
653        if (output->destw == 0 || output->desth == 0) {
654            output->destx = (destx > 0) ? destx : 0;
655            output->desty = (desty > 0) ? desty : 0;
656            output->destw = ((output->destx + destw) > output->screen_width) ? (output->screen_width - output->destx) : destw;
657            output->desth = ((output->desty + desth) > output->screen_height) ? (output->screen_height - output->desty) : desth;
658        }
659
660        /* Hack for repaint color key to black(0,0,0). */
661        if (driver_data->overlay_idle_frame != 0) {
662            psb__information_message("Paint color key to 0x%x\n", driver_data->color_key);
663            psb_android_texture_streaming_set_background_color(driver_data->color_key | 0xff000000);
664            psb_android_texture_streaming_display(buffer_index);
665            driver_data->overlay_idle_frame = 0;
666        }
667
668        psb__information_message("Overlay position = (%d,%d,%d,%d)\n", output->destx, output->desty, output->destw, output->desth);
669        vaStatus = psb_putsurface_overlay(ctx, surface,
670                                          srcx, srcy, srcw, srch,
671                                          output->destx, output->desty, output->destw, output->desth,
672                                          flags, OVERLAY_A, PIPEA);
673    }
674
675    if (driver_data->overlay_idle_frame == MAX_OVERLAY_IDLE_FRAME)
676        psb_coverlay_stop(ctx);
677
678    driver_data->frame_count++;
679
680
681    return vaStatus;
682}
683