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 SPRITE_PLANE_MAX_WIDTH 4096
29 #define SPRITE_PLANE_MAX_HEIGHT 4096
30
31 #define OVERLAY_PLANE_MAX_STRIDE_PACKED 4096
32 #define OVERLAY_PLANE_MAX_STRIDE_LINEAR 8192
33
34 namespace android {
35 namespace intel {
36
isFormatSupported(int planeType,HwcLayer * hwcLayer)37 bool PlaneCapabilities::isFormatSupported(int planeType, HwcLayer *hwcLayer)
38 {
39 uint32_t format = hwcLayer->getFormat();
40 uint32_t trans = hwcLayer->getLayer()->transform;
41
42 if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) {
43 switch (format) {
44 case HAL_PIXEL_FORMAT_BGRA_8888:
45 case HAL_PIXEL_FORMAT_BGRX_8888:
46 case HAL_PIXEL_FORMAT_RGBA_8888:
47 case HAL_PIXEL_FORMAT_RGBX_8888:
48 case HAL_PIXEL_FORMAT_RGB_565:
49 return trans ? false : true;
50 default:
51 VLOGTRACE("unsupported format %#x", format);
52 return false;
53 }
54 } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
55 switch (format) {
56 case HAL_PIXEL_FORMAT_I420:
57 case HAL_PIXEL_FORMAT_YUY2:
58 case HAL_PIXEL_FORMAT_UYVY:
59 // TODO: overlay supports 180 degree rotation
60 if (trans == HAL_TRANSFORM_ROT_180) {
61 WLOGTRACE("180 degree rotation is not supported yet");
62 }
63 return trans ? false : true;
64 case HAL_PIXEL_FORMAT_INTEL_YV12:
65 return trans ? false: true;
66 case HAL_PIXEL_FORMAT_NV12:
67 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
68 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
69 return true;
70 default:
71 VLOGTRACE("unsupported format %#x", format);
72 return false;
73 }
74 } else {
75 ELOGTRACE("invalid plane type %d", planeType);
76 return false;
77 }
78 }
79
isSizeSupported(int planeType,HwcLayer * hwcLayer)80 bool PlaneCapabilities::isSizeSupported(int planeType, HwcLayer *hwcLayer)
81 {
82 uint32_t format = hwcLayer->getFormat();
83 const stride_t& stride = hwcLayer->getBufferStride();
84
85 bool isYUVPacked;
86 uint32_t maxStride;
87
88 if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) {
89 switch (format) {
90 case HAL_PIXEL_FORMAT_BGRA_8888:
91 case HAL_PIXEL_FORMAT_BGRX_8888:
92 case HAL_PIXEL_FORMAT_RGBA_8888:
93 case HAL_PIXEL_FORMAT_RGBX_8888:
94 case HAL_PIXEL_FORMAT_RGB_565:
95 VLOGTRACE("stride %d", stride.rgb.stride);
96 if (stride.rgb.stride > SPRITE_PLANE_MAX_STRIDE_LINEAR) {
97 VLOGTRACE("too large stride %d", stride.rgb.stride);
98 return false;
99 }
100 return true;
101 default:
102 VLOGTRACE("unsupported format %#x", format);
103 return false;
104 }
105 } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
106 switch (format) {
107 case HAL_PIXEL_FORMAT_INTEL_YV12:
108 case HAL_PIXEL_FORMAT_I420:
109 case HAL_PIXEL_FORMAT_NV12:
110 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
111 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
112 isYUVPacked = false;
113 break;
114 case HAL_PIXEL_FORMAT_YUY2:
115 case HAL_PIXEL_FORMAT_UYVY:
116 isYUVPacked = true;
117 break;
118 default:
119 VLOGTRACE("unsupported format %#x", format);
120 return false;
121 }
122 // don't use overlay plane if stride is too big
123 maxStride = OVERLAY_PLANE_MAX_STRIDE_LINEAR;
124 if (isYUVPacked) {
125 maxStride = OVERLAY_PLANE_MAX_STRIDE_PACKED;
126 }
127
128 if (stride.yuv.yStride > maxStride) {
129 VLOGTRACE("stride %d is too large", stride.yuv.yStride);
130 return false;
131 }
132 return true;
133 } else {
134 ELOGTRACE("invalid plane type %d", planeType);
135 return false;
136 }
137 }
138
isBlendingSupported(int planeType,HwcLayer * hwcLayer)139 bool PlaneCapabilities::isBlendingSupported(int planeType, HwcLayer *hwcLayer)
140 {
141 uint32_t blending = (uint32_t)hwcLayer->getLayer()->blending;
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
isScalingSupported(int planeType,HwcLayer * hwcLayer)164 bool 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 if ((dstW - 1) <= 0 || (dstH - 1) <= 0 ||
180 (dstW - 1) >= SPRITE_PLANE_MAX_WIDTH ||
181 (dstH - 1) >= SPRITE_PLANE_MAX_HEIGHT) {
182 // Should check size in isSizeSupported().
183 DLOGTRACE("invalid destination size: %d x %d, fall back to GLES", dstW, dstH);
184 return false;
185 }
186
187 // no scaling is supported
188 return ((srcW == dstW) && (srcH == dstH)) ? true : false;
189
190 } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
191 // overlay cannot support resolution that bigger than 2047x2047.
192 if ((srcW > INTEL_OVERLAY_MAX_WIDTH - 1) || (srcH > INTEL_OVERLAY_MAX_HEIGHT - 1)) {
193 return false;
194 }
195
196 if (dstW <= 1 || dstH <= 1 || srcW <= 1 || srcH <= 1) {
197 // Workaround: Overlay flip when height is 1 causes MIPI stall on TNG
198 DLOGTRACE("invalid destination size: %dx%d, fall back to GLES", dstW, dstH);
199 return false;
200 }
201
202 if (trans == HAL_TRANSFORM_ROT_90 || trans == HAL_TRANSFORM_ROT_270) {
203 int tmp = srcW;
204 srcW = srcH;
205 srcH = tmp;
206 }
207
208 if (!hwcLayer->isProtected()) {
209 if ((int)src.left & 63) {
210 DLOGTRACE("offset %d is not 64 bytes aligned, fall back to GLES", (int)src.left);
211 return false;
212 }
213
214 float scaleX = (float)srcW / dstW;
215 float scaleY = (float)srcH / dstH;
216 if (scaleX > 4.0 || scaleY > 4.0 || scaleX < 0.25 || scaleY < 0.25) {
217 WLOGTRACE("overlay scaling > 4, fall back to GLES");
218 return false;
219 }
220 }
221
222 return true;
223 } else {
224 ELOGTRACE("invalid plane type %d", planeType);
225 return false;
226 }
227 }
228
isTransformSupported(int planeType,HwcLayer * hwcLayer)229 bool PlaneCapabilities::isTransformSupported(int planeType, HwcLayer *hwcLayer)
230 {
231 uint32_t trans = hwcLayer->getLayer()->transform;
232
233 if (planeType == DisplayPlane::PLANE_OVERLAY) {
234 // overlay does not support FLIP_H/FLIP_V
235 switch (trans) {
236 case 0:
237 case HAL_TRANSFORM_ROT_90:
238 case HAL_TRANSFORM_ROT_270:
239 return true;
240 default:
241 return false;
242 }
243 }
244
245 // don't transform any tranform
246 return trans ? false : true;
247 }
248
249 } // namespace intel
250 } // namespace android
251
252