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#include <common/utils/HwcTrace.h>
17#include <utils/String8.h>
18#include <ips/anniedale/AnnPlaneManager.h>
19#include <ips/anniedale/AnnRGBPlane.h>
20#include <ips/anniedale/AnnOverlayPlane.h>
21#include <ips/anniedale/AnnCursorPlane.h>
22#include <PlaneCapabilities.h>
23
24namespace android {
25namespace intel {
26
27
28struct PlaneDescription {
29    char nickname;
30    int type;
31    int index;
32};
33
34
35static PlaneDescription PLANE_DESC[] =
36{
37    // nickname must be continous and start with 'A',
38    // it is used to fast locate plane index and type
39    {'A', DisplayPlane::PLANE_PRIMARY, 0},
40    {'B', DisplayPlane::PLANE_PRIMARY, 1},
41    {'C', DisplayPlane::PLANE_PRIMARY, 2},
42    {'D', DisplayPlane::PLANE_SPRITE,  0},
43    {'E', DisplayPlane::PLANE_SPRITE,  1},
44    {'F', DisplayPlane::PLANE_SPRITE,  2},
45    {'G', DisplayPlane::PLANE_OVERLAY, 0},  // nickname for Overlay A
46    {'H', DisplayPlane::PLANE_OVERLAY, 1},  // nickname for Overlay C
47    {'I', DisplayPlane::PLANE_CURSOR,  0},  // nickname for cursor A
48    {'J', DisplayPlane::PLANE_CURSOR,  1},  // nickname for cursor B
49    {'K', DisplayPlane::PLANE_CURSOR,  2}   // nickname for cursor C
50};
51
52
53struct ZOrderDescription {
54    int index;  // based on overlay position
55    const char *zorder;
56};
57
58// If overlay is in the bottom of Z order, two legitimate combinations are Oa, D, E, F
59// and Oc, D, E, F. However, plane A has to be part of the blending chain as it can't
60//  be disabled [HW bug]. The only legitimate combinations including overlay and plane A is:
61// A, Oa, E, F
62// A, Oc, E, F
63#define OVERLAY_HW_WORKAROUND
64
65
66// Cursor plane can be placed on top of any plane below and is intentionally ignored
67// in the zorder table.
68
69static ZOrderDescription PIPE_A_ZORDER_DESC[] =
70{
71    {0, "ADEF"},  // no overlay
72#ifndef OVERLAY_HW_WORKAROUND
73    {1, "GDEF"},  // overlay A at bottom (1 << 0)
74    {1, "HDEF"},  // overlay C at bottom (1 << 0)
75#else
76    {1, "GEF"},  // overlay A at bottom (1 << 0)
77    {1, "HEF"},  // overlay C at bottom (1 << 0)
78#endif
79    {2, "AGEF"},  // overlay A at next to bottom (1 << 1)
80    {2, "AHEF"},  // overlay C at next to bottom (1 << 1)
81#ifndef OVERLAY_HW_WORKAROUND
82    {3, "GHEF"},  // overlay A, C at bottom
83#else
84    {3, "GHF"},   // overlay A, C at bottom
85#endif
86    {4, "ADGF"},  // overlay A at next to top (1 << 2)
87    {4, "ADHF"},  // overlay C at next to top (1 << 2)
88    {6, "AGHF"},  // overlay A, C in between
89    {8, "ADEG"},  // overlay A at top (1 << 3)
90    {8, "ADEH"},  // overlay C at top (1 <<3)
91    {12, "ADGH"}  // overlay A, C at top
92};
93
94// use overlay C over overlay A if possible on pipe B
95// workaround: use only overlay C on pipe B
96static ZOrderDescription PIPE_B_ZORDER_DESC[] =
97{
98    {0, "BD"},    // no overlay
99    {1, "GBD"},   // overlay A at bottom (1 << 0)
100    {1, "HBD"},   // overlay C at bottom (1 << 0)
101    {2, "BGD"},   // overlay A at middle (1 << 1)
102    {2, "BHD"},   // overlay C at middle (1 << 1)
103    {3, "GHBD"},  // overlay A and C at bottom ( 1 << 0 + 1 << 1)
104    {4, "BDG"},   // overlay A at top (1 << 2)
105    {4, "BDH"},   // overlay C at top (1 << 2)
106    {6, "BGHD"},  // overlay A/C at middle  1 << 1 + 1 << 2)
107    {12, "BDGH"}  // overlay A/C at top (1 << 2 + 1 << 3)
108};
109
110static const int PIPE_A_ZORDER_COMBINATIONS =
111        sizeof(PIPE_A_ZORDER_DESC)/sizeof(ZOrderDescription);
112static const int PIPE_B_ZORDER_COMBINATIONS =
113        sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription);
114
115AnnPlaneManager::AnnPlaneManager()
116    : DisplayPlaneManager()
117{
118}
119
120AnnPlaneManager::~AnnPlaneManager()
121{
122}
123
124bool AnnPlaneManager::initialize()
125{
126    mSpritePlaneCount = 3;  // Sprite D, E, F
127    mOverlayPlaneCount = 2; // Overlay A, C
128    mPrimaryPlaneCount = 3; // Primary A, B, C
129    mCursorPlaneCount = 3;
130
131    return DisplayPlaneManager::initialize();
132}
133
134void AnnPlaneManager::deinitialize()
135{
136    DisplayPlaneManager::deinitialize();
137}
138
139DisplayPlane* AnnPlaneManager::allocPlane(int index, int type)
140{
141    DisplayPlane *plane = NULL;
142
143    switch (type) {
144    case DisplayPlane::PLANE_PRIMARY:
145        plane = new AnnRGBPlane(index, DisplayPlane::PLANE_PRIMARY, index/*disp*/);
146        break;
147    case DisplayPlane::PLANE_SPRITE:
148        plane = new AnnRGBPlane(index, DisplayPlane::PLANE_SPRITE, 0/*disp*/);
149        break;
150    case DisplayPlane::PLANE_OVERLAY:
151        plane = new AnnOverlayPlane(index, 0/*disp*/);
152        break;
153    case DisplayPlane::PLANE_CURSOR:
154        plane = new AnnCursorPlane(index, index /*disp */);
155        break;
156    default:
157        ELOGTRACE("unsupported type %d", type);
158        break;
159    }
160
161    if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
162        ELOGTRACE("failed to initialize plane.");
163        DEINIT_AND_DELETE_OBJ(plane);
164    }
165
166    return plane;
167}
168
169bool AnnPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
170{
171    int size = (int)config.size();
172
173    if (size == 0 || size > 5) {
174        VLOGTRACE("invalid z order config size %d", size);
175        return false;
176    }
177
178    if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
179        int firstOverlay = -1;
180        for (int i = 0; i < size; i++) {
181            if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
182                firstOverlay = i;
183                break;
184            }
185        }
186
187        int sprites = 0;
188        for (int i = 0; i < size; i++) {
189            if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
190                config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
191                sprites++;
192            }
193        }
194
195        if (firstOverlay < 0 && sprites > 4) {
196            VLOGTRACE("not capable to support more than 4 sprite layers");
197            return false;
198        }
199
200#ifdef OVERLAY_HW_WORKAROUND
201        if (firstOverlay == 0 && sprites > 2) {
202            VLOGTRACE("not capable to support 3 sprite layers on top of overlay");
203            return false;
204        }
205#endif
206    } else if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
207        int sprites = 0;
208        for (int i = 0; i < size; i++) {
209            if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
210                config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
211                sprites++;
212            }
213        }
214        if (sprites > 2) {
215            ELOGTRACE("number of sprite: %d, maximum 1 sprite and 1 primary supported on pipe 1", sprites);
216            return false;
217        }
218    } else {
219        ELOGTRACE("invalid display device %d", dsp);
220        return false;
221    }
222    return true;
223}
224
225bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
226{
227    if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
228        ELOGTRACE("invalid display device %d", dsp);
229        return false;
230    }
231
232    int size = (int)config.size();
233
234    // calculate index based on overlay Z order position
235    int index = 0;
236    for (int i = 0; i < size; i++) {
237        if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
238            index += (1 << i);
239        }
240    }
241
242    int combinations = 0;
243    if (dsp == IDisplayDevice::DEVICE_PRIMARY)
244        combinations = PIPE_A_ZORDER_COMBINATIONS;
245    else
246        combinations = PIPE_B_ZORDER_COMBINATIONS;
247
248    ZOrderDescription *zorderDesc = NULL;
249    for (int i = 0; i < combinations; i++) {
250        if (dsp == IDisplayDevice::DEVICE_PRIMARY)
251            zorderDesc = &PIPE_A_ZORDER_DESC[i];
252        else
253            zorderDesc = &PIPE_B_ZORDER_DESC[i];
254
255        if (zorderDesc->index != index)
256            continue;
257
258        if (assignPlanes(dsp, config, zorderDesc->zorder)) {
259            VLOGTRACE("zorder assigned %s", zorderDesc->zorder);
260            return true;
261        }
262    }
263    return false;
264}
265
266bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config, const char *zorder)
267{
268    // zorder string does not include cursor plane, therefore cursor layer needs to be handled
269    // in a special way. Cursor layer must be on top of zorder and no more than one cursor layer.
270
271    int size = (int)config.size();
272
273    if (zorder == NULL || size == 0) {
274        //DLOGTRACE("invalid zorder or ZOrder config.");
275        return false;
276    }
277
278    int zorderLen = (int)strlen(zorder);
279
280    // test if plane is available
281    for (int i = 0; i < size; i++) {
282        if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
283            if (i != size - 1) {
284                ELOGTRACE("invalid zorder of cursor layer");
285                return false;
286            }
287            PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
288            if (!isFreePlane(desc.type, desc.index)) {
289                ELOGTRACE("cursor plane is not available");
290                return false;
291            }
292            continue;
293        }
294        if (i >= zorderLen) {
295            DLOGTRACE("index of ZOrderConfig is out of bound");
296            return false;
297        }
298        char id = *(zorder + i);
299        PlaneDescription& desc = PLANE_DESC[id - 'A'];
300        if (!isFreePlane(desc.type, desc.index)) {
301            DLOGTRACE("plane type %d index %d is not available", desc.type, desc.index);
302            return false;
303        }
304
305#if 0
306        // plane type check
307        if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY &&
308            desc.type != DisplayPlane::PLANE_OVERLAY) {
309            ELOGTRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
310            return false;
311        }
312
313        if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY) {
314            if (config[i]->planeType != DisplayPlane::PLANE_PRIMARY &&
315                config[i]->planeType != DisplayPlane::PLANE_SPRITE) {
316                ELOGTRACE("invalid plane type %d,", config[i]->planeType);
317                return false;
318            }
319            if (desc.type != DisplayPlane::PLANE_PRIMARY &&
320                desc.type != DisplayPlane::PLANE_SPRITE) {
321                ELOGTRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
322                return false;
323            }
324        }
325#endif
326
327        if  (desc.type == DisplayPlane::PLANE_OVERLAY && desc.index == 1 &&
328             config[i]->hwcLayer->getTransform() != 0) {
329            DLOGTRACE("overlay C does not support transform");
330            return false;
331        }
332    }
333
334    bool primaryPlaneActive = false;
335    // allocate planes
336    for (int i = 0; i < size; i++) {
337        if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
338            PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
339            ZOrderLayer *zLayer = config.itemAt(i);
340            zLayer->plane = getPlane(desc.type, desc.index);
341            if (zLayer->plane == NULL) {
342                ELOGTRACE("failed to get cursor plane, should never happen!");
343            }
344            continue;
345        }
346        char id = *(zorder + i);
347        PlaneDescription& desc = PLANE_DESC[id - 'A'];
348        ZOrderLayer *zLayer = config.itemAt(i);
349        zLayer->plane = getPlane(desc.type, desc.index);
350        if (zLayer->plane == NULL) {
351            ELOGTRACE("failed to get plane, should never happen!");
352        }
353        // override type
354        zLayer->planeType = desc.type;
355        if (desc.type == DisplayPlane::PLANE_PRIMARY) {
356            primaryPlaneActive = true;
357        }
358    }
359
360    // setup Z order
361    int slot = 0;
362    for (int i = 0; i < size; i++) {
363        slot = i;
364
365#ifdef OVERLAY_HW_WORKAROUND
366        if (!primaryPlaneActive && config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
367            slot += 1;
368        }
369#endif
370
371        config[i]->plane->setZOrderConfig(config, (void *)slot);
372        config[i]->plane->enable();
373    }
374
375#if 0
376    DLOGTRACE("config size %d, zorder %s", size, zorder);
377    for (int i = 0; i < size; i++) {
378        const ZOrderLayer *l = config.itemAt(i);
379        ILOGTRACE("%d: plane type %d, index %d, zorder %d",
380            i, l->planeType, l->plane->getIndex(), l->zorder);
381    }
382#endif
383
384    return true;
385}
386
387void* AnnPlaneManager::getZOrderConfig() const
388{
389    return NULL;
390}
391
392int AnnPlaneManager::getFreePlanes(int dsp, int type)
393{
394    RETURN_NULL_IF_NOT_INIT();
395
396    if (type != DisplayPlane::PLANE_SPRITE) {
397        return DisplayPlaneManager::getFreePlanes(dsp, type);
398    }
399
400    if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
401        ELOGTRACE("invalid display device %d", dsp);
402        return 0;
403    }
404
405    uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
406    int start = 0;
407    int stop = mSpritePlaneCount;
408    if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
409        // only Sprite D (index 0) can be assigned to pipe 1
410        // Sprites E/F (index 1, 2) are fixed on pipe 0
411        stop = 1;
412    }
413    int count = 0;
414    for (int i = start; i < stop; i++) {
415        if ((1 << i) & freePlanes) {
416            count++;
417        }
418    }
419    return count;
420}
421
422} // namespace intel
423} // namespace android
424
425