1/* 2// Copyright (c) 2014 Intel Corporation 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15*/ 16 17#include <common/utils/HwcTrace.h> 18#include <DisplayPlane.h> 19#include <PlaneCapabilities.h> 20#include <ips/common/OverlayHardware.h> 21#include <common/base/HwcLayer.h> 22#include <khronos/openmax/OMX_IntelVideoExt.h> 23#include <hal_public.h> 24 25#define SPRITE_PLANE_MAX_STRIDE_TILED 16384 26#define SPRITE_PLANE_MAX_STRIDE_LINEAR 16384 27 28#define OVERLAY_PLANE_MAX_STRIDE_PACKED 4096 29#define OVERLAY_PLANE_MAX_STRIDE_LINEAR 8192 30 31namespace android { 32namespace intel { 33 34bool PlaneCapabilities::isFormatSupported(int planeType, HwcLayer *hwcLayer) 35{ 36 uint32_t format = hwcLayer->getFormat(); 37 uint32_t trans = hwcLayer->getLayer()->transform; 38 39 if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) { 40 switch (format) { 41 case HAL_PIXEL_FORMAT_BGRA_8888: 42 case HAL_PIXEL_FORMAT_BGRX_8888: 43 case HAL_PIXEL_FORMAT_RGBA_8888: 44 case HAL_PIXEL_FORMAT_RGBX_8888: 45 case HAL_PIXEL_FORMAT_RGB_565: 46 return trans ? false : true; 47 default: 48 VLOGTRACE("unsupported format %#x", format); 49 return false; 50 } 51 } else if (planeType == DisplayPlane::PLANE_OVERLAY) { 52 switch (format) { 53 case HAL_PIXEL_FORMAT_I420: 54 case HAL_PIXEL_FORMAT_YUY2: 55 case HAL_PIXEL_FORMAT_UYVY: 56 // TODO: overlay supports 180 degree rotation 57 if (trans == HAL_TRANSFORM_ROT_180) { 58 WLOGTRACE("180 degree rotation is not supported yet"); 59 } 60 return trans ? false : true; 61 case HAL_PIXEL_FORMAT_YV12: 62 return trans ? false: true; 63 case HAL_PIXEL_FORMAT_NV12: 64 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: 65 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: 66 return true; 67 default: 68 VLOGTRACE("unsupported format %#x", format); 69 return false; 70 } 71 } else { 72 ELOGTRACE("invalid plane type %d", planeType); 73 return false; 74 } 75} 76 77bool PlaneCapabilities::isSizeSupported(int planeType, HwcLayer *hwcLayer) 78{ 79 uint32_t format = hwcLayer->getFormat(); 80 uint32_t w = hwcLayer->getBufferWidth(); 81 uint32_t h = hwcLayer->getBufferHeight(); 82 const stride_t& stride = hwcLayer->getBufferStride(); 83 84 bool isYUVPacked; 85 uint32_t maxStride; 86 87 if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) { 88 switch (format) { 89 case HAL_PIXEL_FORMAT_BGRA_8888: 90 case HAL_PIXEL_FORMAT_BGRX_8888: 91 case HAL_PIXEL_FORMAT_RGBA_8888: 92 case HAL_PIXEL_FORMAT_RGBX_8888: 93 case HAL_PIXEL_FORMAT_RGB_565: 94 VLOGTRACE("stride %d", stride.rgb.stride); 95 if (stride.rgb.stride > SPRITE_PLANE_MAX_STRIDE_LINEAR) { 96 VLOGTRACE("too large stride %d", stride.rgb.stride); 97 return false; 98 } 99 return true; 100 default: 101 VLOGTRACE("unsupported format %#x", format); 102 return false; 103 } 104 } else if (planeType == DisplayPlane::PLANE_OVERLAY) { 105 switch (format) { 106 case HAL_PIXEL_FORMAT_YV12: 107 case HAL_PIXEL_FORMAT_I420: 108 case HAL_PIXEL_FORMAT_NV12: 109 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: 110 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: 111 isYUVPacked = false; 112 break; 113 case HAL_PIXEL_FORMAT_YUY2: 114 case HAL_PIXEL_FORMAT_UYVY: 115 isYUVPacked = true; 116 break; 117 default: 118 VLOGTRACE("unsupported format %#x", format); 119 return false; 120 } 121 // don't use overlay plane if stride is too big 122 maxStride = OVERLAY_PLANE_MAX_STRIDE_LINEAR; 123 if (isYUVPacked) { 124 maxStride = OVERLAY_PLANE_MAX_STRIDE_PACKED; 125 } 126 127 if (stride.yuv.yStride > maxStride) { 128 VLOGTRACE("stride %d is too large", stride.yuv.yStride); 129 return false; 130 } 131 return true; 132 } else { 133 ELOGTRACE("invalid plane type %d", planeType); 134 return false; 135 } 136} 137 138bool PlaneCapabilities::isBlendingSupported(int planeType, HwcLayer *hwcLayer) 139{ 140 uint32_t blending = (uint32_t)hwcLayer->getLayer()->blending; 141 uint8_t planeAlpha = hwcLayer->getLayer()->planeAlpha; 142 143 if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) { 144 // support premultipled & none blanding 145 switch (blending) { 146 case HWC_BLENDING_NONE: 147 case HWC_BLENDING_PREMULT: 148 // add coverage alpha support for ann 149 case HWC_BLENDING_COVERAGE: 150 return true; 151 default: 152 VLOGTRACE("unsupported blending %#x", blending); 153 return false; 154 } 155 } else if (planeType == DisplayPlane::PLANE_OVERLAY) { 156 // overlay doesn't support blending 157 return (blending == HWC_BLENDING_NONE) ? true : false; 158 } else { 159 ELOGTRACE("invalid plane type %d", planeType); 160 return false; 161 } 162} 163 164bool PlaneCapabilities::isScalingSupported(int planeType, HwcLayer *hwcLayer) 165{ 166 hwc_frect_t& src = hwcLayer->getLayer()->sourceCropf; 167 hwc_rect_t& dest = hwcLayer->getLayer()->displayFrame; 168 uint32_t trans = hwcLayer->getLayer()->transform; 169 170 int srcW, srcH; 171 int dstW, dstH; 172 173 srcW = (int)src.right - (int)src.left; 174 srcH = (int)src.bottom - (int)src.top; 175 dstW = dest.right - dest.left; 176 dstH = dest.bottom - dest.top; 177 178 if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) { 179 // no scaling is supported 180 return ((srcW == dstW) && (srcH == dstH)) ? true : false; 181 182 } else if (planeType == DisplayPlane::PLANE_OVERLAY) { 183 // overlay cannot support resolution that bigger than 2047x2047. 184 if ((srcW > INTEL_OVERLAY_MAX_WIDTH - 1) || (srcH > INTEL_OVERLAY_MAX_HEIGHT - 1)) { 185 return false; 186 } 187 188 if (dstW <= 1 || dstH <= 1 || srcW <= 1 || srcH <= 1) { 189 // Workaround: Overlay flip when height is 1 causes MIPI stall on TNG 190 DLOGTRACE("invalid destination size: %dx%d, fall back to GLES", dstW, dstH); 191 return false; 192 } 193 194 if (trans == HAL_TRANSFORM_ROT_90 || trans == HAL_TRANSFORM_ROT_270) { 195 int tmp = srcW; 196 srcW = srcH; 197 srcH = tmp; 198 } 199 200 if (!hwcLayer->isProtected()) { 201 if ((int)src.left & 63) { 202 DLOGTRACE("offset %d is not 64 bytes aligned, fall back to GLES", (int)src.left); 203 return false; 204 } 205 206 float scaleX = (float)srcW / dstW; 207 float scaleY = (float)srcH / dstH; 208 if (scaleX > 4.0 || scaleY > 4.0 || scaleX < 0.25 || scaleY < 0.25) { 209 WLOGTRACE("overlay scaling > 4, fall back to GLES"); 210 return false; 211 } 212 } 213 214 return true; 215 } else { 216 ELOGTRACE("invalid plane type %d", planeType); 217 return false; 218 } 219} 220 221bool PlaneCapabilities::isTransformSupported(int planeType, HwcLayer *hwcLayer) 222{ 223 uint32_t trans = hwcLayer->getLayer()->transform; 224 225 if (planeType == DisplayPlane::PLANE_OVERLAY) { 226 // overlay does not support FLIP_H/FLIP_V 227 switch (trans) { 228 case 0: 229 case HAL_TRANSFORM_ROT_90: 230 case HAL_TRANSFORM_ROT_180: 231 case HAL_TRANSFORM_ROT_270: 232 return true; 233 default: 234 return false; 235 } 236 } 237 238 // don't transform any tranform 239 return trans ? false : true; 240} 241 242} // namespace intel 243} // namespace android 244 245