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 42 namespace { 43 struct 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 72 namespace overlay { 73 74 //----------From class Res ------------------------------ 75 const char* const Res::fbPath = "/dev/graphics/fb%u"; 76 const char* const Res::rotPath = "/dev/msm_rotator"; 77 //-------------------------------------------------------- 78 79 80 81 namespace utils { 82 83 //-------------------------------------------------------- 84 //Refer to graphics.h, gralloc_priv.h, msm_mdp.h 85 int getMdpFormat(int format) { 86 switch (format) { 87 //From graphics.h 88 case HAL_PIXEL_FORMAT_RGBA_8888 : 89 return MDP_RGBA_8888; 90 case HAL_PIXEL_FORMAT_RGBX_8888: 91 return MDP_RGBX_8888; 92 case HAL_PIXEL_FORMAT_RGB_888: 93 return MDP_RGB_888; 94 case HAL_PIXEL_FORMAT_RGB_565: 95 return MDP_RGB_565; 96 case HAL_PIXEL_FORMAT_RGBA_5551: 97 return MDP_RGBA_5551; 98 case HAL_PIXEL_FORMAT_RGBA_4444: 99 return MDP_RGBA_4444; 100 case HAL_PIXEL_FORMAT_BGRA_8888: 101 return MDP_BGRA_8888; 102 case HAL_PIXEL_FORMAT_BGRX_8888: 103 return MDP_BGRX_8888; 104 case HAL_PIXEL_FORMAT_YV12: 105 return MDP_Y_CR_CB_GH2V2; 106 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 107 return MDP_Y_CBCR_H2V1; 108 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 109 return MDP_Y_CRCB_H2V2; 110 111 //From gralloc_priv.h 112 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: 113 return MDP_Y_CBCR_H2V2_TILE; 114 case HAL_PIXEL_FORMAT_YCbCr_420_SP: 115 return MDP_Y_CBCR_H2V2; 116 case HAL_PIXEL_FORMAT_YCrCb_422_SP: 117 return MDP_Y_CRCB_H2V1; 118 case HAL_PIXEL_FORMAT_YCbCr_422_I: 119 return MDP_YCBYCR_H2V1; 120 case HAL_PIXEL_FORMAT_YCrCb_422_I: 121 return MDP_YCRYCB_H2V1; 122 case HAL_PIXEL_FORMAT_YCbCr_444_SP: 123 return MDP_Y_CBCR_H1V1; 124 case HAL_PIXEL_FORMAT_YCrCb_444_SP: 125 return MDP_Y_CRCB_H1V1; 126 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: 127 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: 128 //NV12 encodeable format maps to the venus format on 129 //B-Family targets 130 return MDP_Y_CBCR_H2V2_VENUS; 131 default: 132 //Unsupported by MDP 133 //---gralloc_priv.h----- 134 //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01 135 //HAL_PIXEL_FORMAT_R_8 = 0x10D 136 //HAL_PIXEL_FORMAT_RG_88 = 0x10E 137 ALOGE("%s: Unsupported HAL format = 0x%x", __func__, format); 138 return -1; 139 } 140 // not reached 141 return -1; 142 } 143 144 int getMdpFormat(int format, int flags) 145 { 146 bool uBwcEnabled = (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED); 147 bool tileEnabled = (flags & private_handle_t::PRIV_FLAGS_TILE_RENDERED); 148 149 // Use UBWC extension, if UBWC is enabled 150 if (uBwcEnabled) { 151 switch (format) { 152 case HAL_PIXEL_FORMAT_RGBA_8888: 153 return MDP_RGBA_8888_UBWC; 154 case HAL_PIXEL_FORMAT_RGB_565: 155 return MDP_RGB_565_UBWC; 156 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: 157 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: 158 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: 159 return MDP_Y_CBCR_H2V2_UBWC; 160 default: 161 ALOGE("%s: Unsupported HAL format = 0x%x", __func__, format); 162 break; 163 } 164 } 165 166 if(!tileEnabled) { 167 return getMdpFormat(format); 168 } 169 switch (format) { 170 case HAL_PIXEL_FORMAT_RGBA_8888 : 171 return MDP_RGBA_8888_TILE; 172 case HAL_PIXEL_FORMAT_RGBX_8888: 173 return MDP_RGBX_8888_TILE; 174 case HAL_PIXEL_FORMAT_RGB_565: 175 return MDP_RGB_565_TILE; 176 case HAL_PIXEL_FORMAT_BGRA_8888: 177 return MDP_BGRA_8888_TILE; 178 case HAL_PIXEL_FORMAT_BGRX_8888: 179 return MDP_BGRX_8888_TILE; 180 default: 181 return getMdpFormat(format); 182 } 183 } 184 185 186 187 //Takes mdp format as input and translates to equivalent HAL format 188 //Refer to graphics.h, gralloc_priv.h, msm_mdp.h for formats. 189 int getHALFormat(int mdpFormat) { 190 switch (mdpFormat) { 191 //From graphics.h 192 case MDP_RGBA_8888: 193 return HAL_PIXEL_FORMAT_RGBA_8888; 194 case MDP_RGBX_8888: 195 return HAL_PIXEL_FORMAT_RGBX_8888; 196 case MDP_RGB_888: 197 return HAL_PIXEL_FORMAT_RGB_888; 198 case MDP_RGB_565: 199 return HAL_PIXEL_FORMAT_RGB_565; 200 case MDP_RGBA_5551: 201 return HAL_PIXEL_FORMAT_RGBA_5551; 202 case MDP_RGBA_4444: 203 return HAL_PIXEL_FORMAT_RGBA_4444; 204 case MDP_BGRA_8888: 205 return HAL_PIXEL_FORMAT_BGRA_8888; 206 case MDP_Y_CR_CB_GH2V2: 207 return HAL_PIXEL_FORMAT_YV12; 208 case MDP_Y_CBCR_H2V1: 209 return HAL_PIXEL_FORMAT_YCbCr_422_SP; 210 case MDP_Y_CRCB_H2V2: 211 return HAL_PIXEL_FORMAT_YCrCb_420_SP; 212 213 //From gralloc_priv.h 214 case MDP_Y_CBCR_H2V2_TILE: 215 return HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; 216 case MDP_Y_CBCR_H2V2: 217 return HAL_PIXEL_FORMAT_YCbCr_420_SP; 218 case MDP_Y_CRCB_H2V1: 219 return HAL_PIXEL_FORMAT_YCrCb_422_SP; 220 case MDP_YCBYCR_H2V1: 221 return HAL_PIXEL_FORMAT_YCbCr_422_I; 222 case MDP_YCRYCB_H2V1: 223 return HAL_PIXEL_FORMAT_YCrCb_422_I; 224 case MDP_Y_CBCR_H1V1: 225 return HAL_PIXEL_FORMAT_YCbCr_444_SP; 226 case MDP_Y_CRCB_H1V1: 227 return HAL_PIXEL_FORMAT_YCrCb_444_SP; 228 case MDP_Y_CBCR_H2V2_VENUS: 229 return HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; 230 default: 231 ALOGE("%s: Unsupported MDP format = 0x%x", __func__, mdpFormat); 232 return -1; 233 } 234 // not reached 235 return -1; 236 } 237 238 int getMdpOrient(eTransform rotation) { 239 int retTrans = 0; 240 bool trans90 = false; 241 int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion(); 242 bool aFamily = (mdpVersion < qdutils::MDSS_V5); 243 244 ALOGD_IF(DEBUG_OVERLAY, "%s: In rotation = %d", __FUNCTION__, rotation); 245 if(rotation & OVERLAY_TRANSFORM_ROT_90) { 246 retTrans |= MDP_ROT_90; 247 trans90 = true; 248 } 249 250 if(rotation & OVERLAY_TRANSFORM_FLIP_H) { 251 if(trans90 && aFamily) { 252 //Swap for a-family, since its driver does 90 first 253 retTrans |= MDP_FLIP_UD; 254 } else { 255 retTrans |= MDP_FLIP_LR; 256 } 257 } 258 259 if(rotation & OVERLAY_TRANSFORM_FLIP_V) { 260 if(trans90 && aFamily) { 261 //Swap for a-family, since its driver does 90 first 262 retTrans |= MDP_FLIP_LR; 263 } else { 264 retTrans |= MDP_FLIP_UD; 265 } 266 } 267 268 ALOGD_IF(DEBUG_OVERLAY, "%s: Out rotation = %d", __FUNCTION__, retTrans); 269 return retTrans; 270 } 271 272 void getDecimationFactor(const int& src_w, const int& src_h, 273 const int& dst_w, const int& dst_h, uint8_t& horzDeci, 274 uint8_t& vertDeci) { 275 horzDeci = 0; 276 vertDeci = 0; 277 float horDscale = ceilf((float)src_w / (float)dst_w); 278 float verDscale = ceilf((float)src_h / (float)dst_h); 279 qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance(); 280 281 //Next power of 2, if not already 282 horDscale = powf(2.0f, ceilf(log2f(horDscale))); 283 verDscale = powf(2.0f, ceilf(log2f(verDscale))); 284 285 //Since MDP can do downscale and has better quality, split the task 286 //between decimator and MDP downscale 287 horDscale /= (float)mdpHw.getMaxMDPDownscale(); 288 verDscale /= (float)mdpHw.getMaxMDPDownscale(); 289 290 if((int)horDscale) 291 horzDeci = (uint8_t)log2f(horDscale); 292 293 if((int)verDscale) 294 vertDeci = (uint8_t)log2f(verDscale); 295 296 if(src_w > (int) mdpHw.getMaxPipeWidth()) { 297 //If the client sends us something > what a layer mixer supports 298 //then it means it doesn't want to use split-pipe but wants us to 299 //decimate. A minimum decimation of 1 will ensure that the width is 300 //always within layer mixer limits. 301 const uint8_t minDeci = 1; 302 if(horzDeci < minDeci) 303 horzDeci = minDeci; 304 } 305 } 306 307 static inline int compute(const uint32_t& x, const uint32_t& y, 308 const uint32_t& z) { 309 return x - ( y + z ); 310 } 311 312 void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop) { 313 if(tr & OVERLAY_TRANSFORM_FLIP_H) { 314 srcCrop.x = compute(whf.w, srcCrop.x, srcCrop.w); 315 } 316 if(tr & OVERLAY_TRANSFORM_FLIP_V) { 317 srcCrop.y = compute(whf.h, srcCrop.y, srcCrop.h); 318 } 319 if(tr & OVERLAY_TRANSFORM_ROT_90) { 320 int tmp = srcCrop.x; 321 srcCrop.x = compute(whf.h, 322 srcCrop.y, 323 srcCrop.h); 324 srcCrop.y = tmp; 325 swap(whf.w, whf.h); 326 swap(srcCrop.w, srcCrop.h); 327 } 328 } 329 330 void getDump(char *buf, size_t len, const char *prefix, 331 const mdp_overlay& ov) { 332 char str[256] = {'\0'}; 333 snprintf(str, 256, 334 "%s id=%d z=%d alpha=%d mask=%d flags=0x%x H.Deci=%d," 335 "V.Deci=%d\n", 336 prefix, ov.id, ov.z_order, ov.alpha, 337 ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci); 338 strlcat(buf, str, len); 339 getDump(buf, len, "\tsrc", ov.src); 340 getDump(buf, len, "\tsrc_rect", ov.src_rect); 341 getDump(buf, len, "\tdst_rect", ov.dst_rect); 342 } 343 344 void getDump(char *buf, size_t len, const char *prefix, 345 const msmfb_img& ov) { 346 char str_src[256] = {'\0'}; 347 snprintf(str_src, 256, 348 "%s w=%d h=%d format=%d %s\n", 349 prefix, ov.width, ov.height, ov.format, 350 overlay::utils::getFormatString(ov.format)); 351 strlcat(buf, str_src, len); 352 } 353 354 void getDump(char *buf, size_t len, const char *prefix, 355 const mdp_rect& ov) { 356 char str_rect[256] = {'\0'}; 357 snprintf(str_rect, 256, 358 "%s x=%d y=%d w=%d h=%d\n", 359 prefix, ov.x, ov.y, ov.w, ov.h); 360 strlcat(buf, str_rect, len); 361 } 362 363 void getDump(char *buf, size_t len, const char *prefix, 364 const msmfb_overlay_data& ov) { 365 char str[256] = {'\0'}; 366 snprintf(str, 256, 367 "%s id=%d\n", 368 prefix, ov.id); 369 strlcat(buf, str, len); 370 getDump(buf, len, "\tdata", ov.data); 371 } 372 373 void getDump(char *buf, size_t len, const char *prefix, 374 const msmfb_data& ov) { 375 char str_data[256] = {'\0'}; 376 snprintf(str_data, 256, 377 "%s offset=%d memid=%d id=%d flags=0x%x\n", 378 prefix, ov.offset, ov.memory_id, ov.id, ov.flags); 379 strlcat(buf, str_data, len); 380 } 381 382 void getDump(char *buf, size_t len, const char *prefix, 383 const msm_rotator_img_info& rot) { 384 char str[256] = {'\0'}; 385 snprintf(str, 256, "%s sessid=%u rot=%d, enable=%d downscale=%d\n", 386 prefix, rot.session_id, rot.rotations, rot.enable, 387 rot.downscale_ratio); 388 strlcat(buf, str, len); 389 getDump(buf, len, "\tsrc", rot.src); 390 getDump(buf, len, "\tdst", rot.dst); 391 getDump(buf, len, "\tsrc_rect", rot.src_rect); 392 } 393 394 void getDump(char *buf, size_t len, const char *prefix, 395 const msm_rotator_data_info& rot) { 396 char str[256] = {'\0'}; 397 snprintf(str, 256, 398 "%s sessid=%u\n", 399 prefix, rot.session_id); 400 strlcat(buf, str, len); 401 getDump(buf, len, "\tsrc", rot.src); 402 getDump(buf, len, "\tdst", rot.dst); 403 } 404 405 //Helper to even out x,w and y,h pairs 406 //x,y are always evened to ceil and w,h are evened to floor 407 void normalizeCrop(uint32_t& xy, uint32_t& wh) { 408 if(xy & 1) { 409 even_ceil(xy); 410 if(wh & 1) 411 even_floor(wh); 412 else 413 wh -= 2; 414 } else { 415 even_floor(wh); 416 } 417 } 418 419 } // utils 420 421 } // overlay 422