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