overlayUtils.cpp revision f96e0b957a215582702db2a5ec6c744afd94eae3
1/*
2* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are
6* met:
7*    * Redistributions of source code must retain the above copyright
8*      notice, this list of conditions and the following disclaimer.
9*    * Redistributions in binary form must reproduce the above
10*      copyright notice, this list of conditions and the following
11*      disclaimer in the documentation and/or other materials provided
12*      with the distribution.
13*    * Neither the name of The Linux Foundation nor the names of its
14*      contributors may be used to endorse or promote products derived
15*      from this software without specific prior written permission.
16*
17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include <stdlib.h>
31#include <math.h>
32#include <utils/Log.h>
33#include <linux/msm_mdp.h>
34#include <cutils/properties.h>
35#include "gralloc_priv.h"
36#include "overlayUtils.h"
37#include "mdpWrapper.h"
38#include "mdp_version.h"
39#include <hardware/hwcomposer_defs.h>
40
41// just a helper static thingy
42namespace {
43struct IOFile {
44    IOFile(const char* s, const char* mode) : fp(0) {
45        fp = ::fopen(s, mode);
46        if(!fp) {
47            ALOGE("Failed open %s", s);
48        }
49    }
50    template <class T>
51            size_t read(T& r, size_t elem) {
52                if(fp) {
53                    return ::fread(&r, sizeof(T), elem, fp);
54                }
55                return 0;
56            }
57    size_t write(const char* s, uint32_t val) {
58        if(fp) {
59            return ::fprintf(fp, s, val);
60        }
61        return 0;
62    }
63    bool valid() const { return fp != 0; }
64    ~IOFile() {
65        if(fp) ::fclose(fp);
66        fp=0;
67    }
68    FILE* fp;
69};
70}
71
72namespace overlay {
73
74//----------From class Res ------------------------------
75const char* const Res::fbPath = "/dev/graphics/fb%u";
76const char* const Res::rotPath = "/dev/msm_rotator";
77const char* const Res::format3DFile =
78        "/sys/class/graphics/fb1/format_3d";
79const char* const Res::edid3dInfoFile =
80        "/sys/class/graphics/fb1/3d_present";
81const char* const Res::barrierFile =
82        "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier";
83//--------------------------------------------------------
84
85
86
87namespace utils {
88
89//--------------------------------------------------------
90//Refer to graphics.h, gralloc_priv.h, msm_mdp.h
91int getMdpFormat(int format) {
92    switch (format) {
93        //From graphics.h
94        case HAL_PIXEL_FORMAT_RGBA_8888 :
95            return MDP_RGBA_8888;
96        case HAL_PIXEL_FORMAT_RGBX_8888:
97            return MDP_RGBX_8888;
98        case HAL_PIXEL_FORMAT_RGB_888:
99            return MDP_RGB_888;
100        case HAL_PIXEL_FORMAT_RGB_565:
101            return MDP_RGB_565;
102        case HAL_PIXEL_FORMAT_BGRA_8888:
103            return MDP_BGRA_8888;
104        case HAL_PIXEL_FORMAT_BGRX_8888:
105            return MDP_BGRX_8888;
106        case HAL_PIXEL_FORMAT_YV12:
107            return MDP_Y_CR_CB_GH2V2;
108        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
109            return MDP_Y_CBCR_H2V1;
110        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
111            return MDP_Y_CRCB_H2V2;
112
113        //From gralloc_priv.h
114        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
115            return MDP_Y_CBCR_H2V2_TILE;
116        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
117            return MDP_Y_CBCR_H2V2;
118        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
119            return MDP_Y_CRCB_H2V1;
120        case HAL_PIXEL_FORMAT_YCbCr_422_I:
121            return MDP_YCBYCR_H2V1;
122        case HAL_PIXEL_FORMAT_YCrCb_422_I:
123            return MDP_YCRYCB_H2V1;
124        case HAL_PIXEL_FORMAT_YCbCr_444_SP:
125            return MDP_Y_CBCR_H1V1;
126        case HAL_PIXEL_FORMAT_YCrCb_444_SP:
127            return MDP_Y_CRCB_H1V1;
128        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
129        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
130            //NV12 encodeable format maps to the venus format on
131            //B-Family targets
132            return MDP_Y_CBCR_H2V2_VENUS;
133        default:
134            //Unsupported by MDP
135            //---graphics.h--------
136            //HAL_PIXEL_FORMAT_RGBA_5551
137            //HAL_PIXEL_FORMAT_RGBA_4444
138            //---gralloc_priv.h-----
139            //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01
140            //HAL_PIXEL_FORMAT_R_8                    = 0x10D
141            //HAL_PIXEL_FORMAT_RG_88                  = 0x10E
142            ALOGE("%s: Unsupported HAL format = 0x%x", __func__, format);
143            return -1;
144    }
145    // not reached
146    return -1;
147}
148
149// This function returns corresponding tile format
150// MDSS support following RGB tile formats
151//  32 bit formats
152//  16 bit formats
153int getMdpFormat(int format, bool tileEnabled)
154{
155    if(!tileEnabled) {
156        return getMdpFormat(format);
157    }
158    switch (format) {
159        case HAL_PIXEL_FORMAT_RGBA_8888 :
160            return MDP_RGBA_8888_TILE;
161        case HAL_PIXEL_FORMAT_RGBX_8888:
162            return MDP_RGBX_8888_TILE;
163        case HAL_PIXEL_FORMAT_RGB_565:
164            return MDP_RGB_565_TILE;
165        case HAL_PIXEL_FORMAT_BGRA_8888:
166            return MDP_BGRA_8888_TILE;
167        case HAL_PIXEL_FORMAT_BGRX_8888:
168            return MDP_BGRX_8888_TILE;
169        default:
170            return getMdpFormat(format);
171    }
172}
173
174
175
176//Takes mdp format as input and translates to equivalent HAL format
177//Refer to graphics.h, gralloc_priv.h, msm_mdp.h for formats.
178int getHALFormat(int mdpFormat) {
179    switch (mdpFormat) {
180        //From graphics.h
181        case MDP_RGBA_8888:
182            return HAL_PIXEL_FORMAT_RGBA_8888;
183        case MDP_RGBX_8888:
184            return HAL_PIXEL_FORMAT_RGBX_8888;
185        case MDP_RGB_888:
186            return HAL_PIXEL_FORMAT_RGB_888;
187        case MDP_RGB_565:
188            return HAL_PIXEL_FORMAT_RGB_565;
189        case MDP_BGRA_8888:
190            return HAL_PIXEL_FORMAT_BGRA_8888;
191        case MDP_Y_CR_CB_GH2V2:
192            return HAL_PIXEL_FORMAT_YV12;
193        case MDP_Y_CBCR_H2V1:
194            return HAL_PIXEL_FORMAT_YCbCr_422_SP;
195        case MDP_Y_CRCB_H2V2:
196            return HAL_PIXEL_FORMAT_YCrCb_420_SP;
197
198        //From gralloc_priv.h
199        case MDP_Y_CBCR_H2V2_TILE:
200            return HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED;
201        case MDP_Y_CBCR_H2V2:
202            return HAL_PIXEL_FORMAT_YCbCr_420_SP;
203        case MDP_Y_CRCB_H2V1:
204            return HAL_PIXEL_FORMAT_YCrCb_422_SP;
205        case MDP_YCBYCR_H2V1:
206            return HAL_PIXEL_FORMAT_YCbCr_422_I;
207        case MDP_YCRYCB_H2V1:
208            return HAL_PIXEL_FORMAT_YCrCb_422_I;
209         case MDP_Y_CBCR_H1V1:
210            return HAL_PIXEL_FORMAT_YCbCr_444_SP;
211        case MDP_Y_CRCB_H1V1:
212            return HAL_PIXEL_FORMAT_YCrCb_444_SP;
213        case MDP_Y_CBCR_H2V2_VENUS:
214            return HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
215        default:
216            ALOGE("%s: Unsupported MDP format = 0x%x", __func__, mdpFormat);
217            return -1;
218    }
219    // not reached
220    return -1;
221}
222
223int getMdpOrient(eTransform rotation) {
224    int retTrans = 0;
225    bool trans90 = false;
226    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
227    bool aFamily = (mdpVersion < qdutils::MDSS_V5);
228
229    ALOGD_IF(DEBUG_OVERLAY, "%s: In rotation = %d", __FUNCTION__, rotation);
230    if(rotation & OVERLAY_TRANSFORM_ROT_90) {
231        retTrans |= MDP_ROT_90;
232        trans90 = true;
233    }
234
235    if(rotation & OVERLAY_TRANSFORM_FLIP_H) {
236        if(trans90 && aFamily) {
237            //Swap for a-family, since its driver does 90 first
238            retTrans |= MDP_FLIP_UD;
239        } else {
240            retTrans |= MDP_FLIP_LR;
241        }
242    }
243
244    if(rotation & OVERLAY_TRANSFORM_FLIP_V) {
245        if(trans90 && aFamily) {
246            //Swap for a-family, since its driver does 90 first
247            retTrans |= MDP_FLIP_LR;
248        } else {
249            retTrans |= MDP_FLIP_UD;
250        }
251    }
252
253    ALOGD_IF(DEBUG_OVERLAY, "%s: Out rotation = %d", __FUNCTION__, retTrans);
254    return retTrans;
255}
256
257int getDownscaleFactor(const int& src_w, const int& src_h,
258        const int& dst_w, const int& dst_h) {
259    int dscale_factor = utils::ROT_DS_NONE;
260    // We need this check to engage the rotator whenever possible to assist MDP
261    // in performing video downscale.
262    // This saves bandwidth and avoids causing the driver to make too many panel
263    // -mode switches between BLT (writeback) and non-BLT (Direct) modes.
264    // Use-case: Video playback [with downscaling and rotation].
265    if (dst_w && dst_h)
266    {
267        float fDscale =  (float)(src_w * src_h) / (float)(dst_w * dst_h);
268        uint32_t dscale = (int)sqrtf(fDscale);
269
270        if(dscale < 2) {
271            // Down-scale to > 50% of orig.
272            dscale_factor = utils::ROT_DS_NONE;
273        } else if(dscale < 4) {
274            // Down-scale to between > 25% to <= 50% of orig.
275            dscale_factor = utils::ROT_DS_HALF;
276        } else if(dscale < 8) {
277            // Down-scale to between > 12.5% to <= 25% of orig.
278            dscale_factor = utils::ROT_DS_FOURTH;
279        } else {
280            // Down-scale to <= 12.5% of orig.
281            dscale_factor = utils::ROT_DS_EIGHTH;
282        }
283    }
284    return dscale_factor;
285}
286
287//Since this is unavailable on Android, defining it in terms of base 10
288static inline float log2f(const float& x) {
289    return log(x) / log(2);
290}
291
292void getDecimationFactor(const int& src_w, const int& src_h,
293        const int& dst_w, const int& dst_h, float& horDscale,
294        float& verDscale) {
295    horDscale = ceilf((float)src_w / (float)dst_w);
296    verDscale = ceilf((float)src_h / (float)dst_h);
297
298    //Next power of 2, if not already
299    horDscale = powf(2.0f, ceilf(log2f(horDscale)));
300    verDscale = powf(2.0f, ceilf(log2f(verDscale)));
301
302    //Since MDP can do 1/4 dscale and has better quality, split the task
303    //between decimator and MDP downscale
304    horDscale /= 4.0f;
305    verDscale /= 4.0f;
306}
307
308static inline int compute(const uint32_t& x, const uint32_t& y,
309        const uint32_t& z) {
310    return x - ( y + z );
311}
312
313void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop) {
314    if(tr & OVERLAY_TRANSFORM_FLIP_H) {
315        srcCrop.x = compute(whf.w, srcCrop.x, srcCrop.w);
316    }
317    if(tr & OVERLAY_TRANSFORM_FLIP_V) {
318        srcCrop.y = compute(whf.h, srcCrop.y, srcCrop.h);
319    }
320    if(tr & OVERLAY_TRANSFORM_ROT_90) {
321        int tmp = srcCrop.x;
322        srcCrop.x = compute(whf.h,
323                srcCrop.y,
324                srcCrop.h);
325        srcCrop.y = tmp;
326        swap(whf.w, whf.h);
327        swap(srcCrop.w, srcCrop.h);
328    }
329}
330
331bool is3DTV() {
332    char is3DTV = '0';
333    IOFile fp(Res::edid3dInfoFile, "r");
334    (void)fp.read(is3DTV, 1);
335    ALOGI("3DTV EDID flag: %d", is3DTV);
336    return (is3DTV == '0') ? false : true;
337}
338
339bool isPanel3D() {
340    OvFD fd;
341    if(!overlay::open(fd, 0 /*fb*/, Res::fbPath)){
342        ALOGE("isPanel3D Can't open framebuffer 0");
343        return false;
344    }
345    fb_fix_screeninfo finfo;
346    if(!mdp_wrapper::getFScreenInfo(fd.getFD(), finfo)) {
347        ALOGE("isPanel3D read fb0 failed");
348    }
349    fd.close();
350    return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
351}
352
353bool usePanel3D() {
354    if(!isPanel3D())
355        return false;
356    char value[PROPERTY_VALUE_MAX];
357    property_get("persist.user.panel3D", value, "0");
358    int usePanel3D = atoi(value);
359    return usePanel3D ? true : false;
360}
361
362bool send3DInfoPacket (uint32_t format3D) {
363    IOFile fp(Res::format3DFile, "wb");
364    (void)fp.write("%d", format3D);
365    if(!fp.valid()) {
366        ALOGE("send3DInfoPacket: no sysfs entry for setting 3d mode");
367        return false;
368    }
369    return true;
370}
371
372bool enableBarrier (uint32_t orientation) {
373    IOFile fp(Res::barrierFile, "wb");
374    (void)fp.write("%d", orientation);
375    if(!fp.valid()) {
376        ALOGE("enableBarrier no sysfs entry for "
377                "enabling barriers on 3D panel");
378        return false;
379    }
380    return true;
381}
382
383uint32_t getS3DFormat(uint32_t fmt) {
384    // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
385    // an explicit check for the format
386    if (fmt == HAL_PIXEL_FORMAT_YV12) {
387        return 0;
388    }
389    uint32_t fmt3D = format3D(fmt);
390    uint32_t fIn3D = format3DInput(fmt3D); // MSB 2 bytes - inp
391    uint32_t fOut3D = format3DOutput(fmt3D); // LSB 2 bytes - out
392    fmt3D = fIn3D | fOut3D;
393    if (!fIn3D) {
394        fmt3D |= fOut3D << SHIFT_TOT_3D; //Set the input format
395    }
396    if (!fOut3D) {
397        switch (fIn3D) {
398            case HAL_3D_IN_SIDE_BY_SIDE_L_R:
399            case HAL_3D_IN_SIDE_BY_SIDE_R_L:
400                // For all side by side formats, set the output
401                // format as Side-by-Side i.e 0x1
402                fmt3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_TOT_3D;
403                break;
404            default:
405                fmt3D |= fIn3D >> SHIFT_TOT_3D; //Set the output format
406        }
407    }
408    return fmt3D;
409}
410
411void getDump(char *buf, size_t len, const char *prefix,
412        const mdp_overlay& ov) {
413    char str[256] = {'\0'};
414    snprintf(str, 256,
415            "%s id=%d z=%d fg=%d alpha=%d mask=%d flags=0x%x H.Deci=%d,"
416            "V.Deci=%d\n",
417            prefix, ov.id, ov.z_order, ov.is_fg, ov.alpha,
418            ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci);
419    strlcat(buf, str, len);
420    getDump(buf, len, "\tsrc", ov.src);
421    getDump(buf, len, "\tsrc_rect", ov.src_rect);
422    getDump(buf, len, "\tdst_rect", ov.dst_rect);
423}
424
425void getDump(char *buf, size_t len, const char *prefix,
426        const msmfb_img& ov) {
427    char str_src[256] = {'\0'};
428    snprintf(str_src, 256,
429            "%s w=%d h=%d format=%d %s\n",
430            prefix, ov.width, ov.height, ov.format,
431            overlay::utils::getFormatString(ov.format));
432    strlcat(buf, str_src, len);
433}
434
435void getDump(char *buf, size_t len, const char *prefix,
436        const mdp_rect& ov) {
437    char str_rect[256] = {'\0'};
438    snprintf(str_rect, 256,
439            "%s x=%d y=%d w=%d h=%d\n",
440            prefix, ov.x, ov.y, ov.w, ov.h);
441    strlcat(buf, str_rect, len);
442}
443
444void getDump(char *buf, size_t len, const char *prefix,
445        const msmfb_overlay_data& ov) {
446    char str[256] = {'\0'};
447    snprintf(str, 256,
448            "%s id=%d\n",
449            prefix, ov.id);
450    strlcat(buf, str, len);
451    getDump(buf, len, "\tdata", ov.data);
452}
453
454void getDump(char *buf, size_t len, const char *prefix,
455        const msmfb_data& ov) {
456    char str_data[256] = {'\0'};
457    snprintf(str_data, 256,
458            "%s offset=%d memid=%d id=%d flags=0x%x\n",
459            prefix, ov.offset, ov.memory_id, ov.id, ov.flags);
460    strlcat(buf, str_data, len);
461}
462
463void getDump(char *buf, size_t len, const char *prefix,
464        const msm_rotator_img_info& rot) {
465    char str[256] = {'\0'};
466    snprintf(str, 256, "%s sessid=%u rot=%d, enable=%d downscale=%d\n",
467            prefix, rot.session_id, rot.rotations, rot.enable,
468            rot.downscale_ratio);
469    strlcat(buf, str, len);
470    getDump(buf, len, "\tsrc", rot.src);
471    getDump(buf, len, "\tdst", rot.dst);
472    getDump(buf, len, "\tsrc_rect", rot.src_rect);
473}
474
475void getDump(char *buf, size_t len, const char *prefix,
476        const msm_rotator_data_info& rot) {
477    char str[256] = {'\0'};
478    snprintf(str, 256,
479            "%s sessid=%u\n",
480            prefix, rot.session_id);
481    strlcat(buf, str, len);
482    getDump(buf, len, "\tsrc", rot.src);
483    getDump(buf, len, "\tdst", rot.dst);
484}
485
486//Helper to even out x,w and y,h pairs
487//x,y are always evened to ceil and w,h are evened to floor
488void normalizeCrop(uint32_t& xy, uint32_t& wh) {
489    if(xy & 1) {
490        even_ceil(xy);
491        if(wh & 1)
492            even_floor(wh);
493        else
494            wh -= 2;
495    } else {
496        even_floor(wh);
497    }
498}
499
500} // utils
501
502} // overlay
503