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 <IDisplayDevice.h>
18#include <DisplayPlaneManager.h>
19
20namespace android {
21namespace intel {
22
23DisplayPlaneManager::DisplayPlaneManager()
24    : mTotalPlaneCount(0),
25      mPrimaryPlaneCount(DEFAULT_PRIMARY_PLANE_COUNT),
26      mSpritePlaneCount(0),
27      mOverlayPlaneCount(0),
28      mInitialized(false)
29{
30    int i;
31
32    for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
33        mPlaneCount[i] = 0;
34        mFreePlanes[i] = 0;
35        mReclaimedPlanes[i] = 0;
36    }
37}
38
39DisplayPlaneManager::~DisplayPlaneManager()
40{
41    WARN_IF_NOT_DEINIT();
42}
43
44void DisplayPlaneManager::deinitialize()
45{
46    int i;
47    size_t j;
48
49    for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
50        for (j = 0; j < mPlanes[i].size(); j++) {
51            // reset plane
52            DisplayPlane *plane = mPlanes[i].itemAt(j);
53            plane->reset();
54
55            DEINIT_AND_DELETE_OBJ(plane);
56        }
57        mPlanes[i].clear();
58    }
59
60    mInitialized = false;
61}
62
63bool DisplayPlaneManager::initialize()
64{
65    int i, j;
66
67    if (mInitialized) {
68        WLOGTRACE("object has been initialized");
69        return true;
70    }
71
72
73    // calculate total plane number and free plane bitmaps
74    mPlaneCount[DisplayPlane::PLANE_SPRITE] = mSpritePlaneCount;
75    mPlaneCount[DisplayPlane::PLANE_OVERLAY] = mOverlayPlaneCount;
76    mPlaneCount[DisplayPlane::PLANE_PRIMARY] = mPrimaryPlaneCount;
77    mPlaneCount[DisplayPlane::PLANE_CURSOR] = mCursorPlaneCount;
78
79    mTotalPlaneCount = mSpritePlaneCount+ mOverlayPlaneCount+ mPrimaryPlaneCount + mCursorPlaneCount;
80    if (mTotalPlaneCount == 0) {
81        ELOGTRACE("plane count is not initialized");
82        return false;
83    }
84
85    for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
86        mFreePlanes[i] = ((1 << mPlaneCount[i]) - 1);
87    }
88
89    // allocate plane pools
90    for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
91        if (mPlaneCount[i]) {
92            mPlanes[i].setCapacity(mPlaneCount[i]);
93
94            for (j = 0; j < mPlaneCount[i]; j++) {
95                DisplayPlane* plane = allocPlane(j, i);
96                if (!plane) {
97                    ELOGTRACE("failed to allocate plane %d, type %d", j, i);
98                    DEINIT_AND_RETURN_FALSE();
99                }
100                mPlanes[i].push_back(plane);
101            }
102        }
103    }
104
105    mInitialized = true;
106    return true;
107}
108
109int DisplayPlaneManager::getPlane(uint32_t& mask)
110{
111    if (!mask)
112        return -1;
113
114    for (int i = 0; i < 32; i++) {
115        int bit = (1 << i);
116        if (bit & mask) {
117            mask &= ~bit;
118            return i;
119        }
120    }
121
122    return -1;
123}
124
125void DisplayPlaneManager::putPlane(int index, uint32_t& mask)
126{
127    if (index < 0 || index >= 32)
128        return;
129
130    int bit = (1 << index);
131
132    if (bit & mask) {
133        WLOGTRACE("bit %d was set", index);
134        return;
135    }
136
137    mask |= bit;
138}
139
140int DisplayPlaneManager::getPlane(uint32_t& mask, int index)
141{
142    if (!mask || index < 0 || index > mTotalPlaneCount)
143        return -1;
144
145    int bit = (1 << index);
146    if (bit & mask) {
147        mask &= ~bit;
148        return index;
149    }
150
151    return -1;
152}
153
154DisplayPlane* DisplayPlaneManager::getPlane(int type, int index)
155{
156    RETURN_NULL_IF_NOT_INIT();
157
158    if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
159        ELOGTRACE("Invalid plane type %d", type);
160        return 0;
161    }
162
163    int freePlaneIndex = getPlane(mReclaimedPlanes[type], index);
164    if (freePlaneIndex >= 0)
165        return mPlanes[type].itemAt(freePlaneIndex);
166
167    freePlaneIndex = getPlane(mFreePlanes[type], index);
168    if (freePlaneIndex >= 0)
169        return mPlanes[type].itemAt(freePlaneIndex);
170
171    return 0;
172}
173
174DisplayPlane* DisplayPlaneManager::getAnyPlane(int type)
175{
176    RETURN_NULL_IF_NOT_INIT();
177
178    if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
179        ELOGTRACE("Invalid plane type %d", type);
180        return 0;
181    }
182
183    int freePlaneIndex = getPlane(mReclaimedPlanes[type]);
184    if (freePlaneIndex >= 0)
185        return mPlanes[type].itemAt(freePlaneIndex);
186
187    freePlaneIndex = getPlane(mFreePlanes[type]);
188    if (freePlaneIndex >= 0)
189        return mPlanes[type].itemAt(freePlaneIndex);
190
191    return 0;
192}
193
194void DisplayPlaneManager::putPlane(int /* dsp */, DisplayPlane& plane)
195{
196    int index;
197    int type;
198
199    RETURN_VOID_IF_NOT_INIT();
200
201    index = plane.getIndex();
202    type = plane.getType();
203
204    if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
205        ELOGTRACE("Invalid plane type %d", type);
206        return;
207    }
208
209    putPlane(index, mFreePlanes[type]);
210}
211
212bool DisplayPlaneManager::isFreePlane(int type, int index)
213{
214    if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
215        ELOGTRACE("Invalid plane type %d", type);
216        return false;
217    }
218
219    int freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
220    if ((freePlanes & (1 << index)) == 0)
221        return false;
222
223    return true;
224}
225
226int DisplayPlaneManager::getFreePlanes(int dsp, int type)
227{
228    RETURN_NULL_IF_NOT_INIT();
229
230    if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
231        ELOGTRACE("Invalid display device %d", dsp);
232        return 0;
233    }
234
235    if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
236        ELOGTRACE("Invalid plane type %d", type);
237        return 0;
238    }
239
240
241    uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
242    if (type == DisplayPlane::PLANE_PRIMARY ||
243        type == DisplayPlane::PLANE_CURSOR) {
244        return ((freePlanes & (1 << dsp)) == 0) ? 0 : 1;
245    } else {
246        int count = 0;
247        for (int i = 0; i < 32; i++) {
248            if ((1 << i) & freePlanes) {
249                count++;
250            }
251        }
252        return count;
253    }
254    return 0;
255}
256
257void DisplayPlaneManager::reclaimPlane(int /* dsp */, DisplayPlane& plane)
258{
259    RETURN_VOID_IF_NOT_INIT();
260
261    int index = plane.getIndex();
262    int type = plane.getType();
263
264    ALOGTRACE("reclaimPlane = %d, type = %d", index, plane.getType());
265
266    if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
267        ELOGTRACE("Invalid plane type %d", type);
268        return;
269    }
270
271    putPlane(index, mReclaimedPlanes[type]);
272
273    // NOTE: don't invalidate plane's data cache here because the reclaimed
274    // plane might be re-assigned to the same layer later
275}
276
277void DisplayPlaneManager::disableReclaimedPlanes()
278{
279    int i, j;
280    bool ret;
281
282    RETURN_VOID_IF_NOT_INIT();
283
284    for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
285        // disable reclaimed planes
286        if (mReclaimedPlanes[i]) {
287            for (j = 0; j < mPlaneCount[i]; j++) {
288                int bit = (1 << j);
289                if (mReclaimedPlanes[i] & bit) {
290                    DisplayPlane* plane = mPlanes[i].itemAt(j);
291                    // check plane state first
292                    ret = plane->isDisabled();
293                    // reset plane
294                    if (ret)
295                        ret = plane->reset();
296                    if (ret) {
297                        // only merge into free bitmap if it is successfully disabled and reset
298                        // otherwise, plane will be disabled and reset again.
299                        mFreePlanes[i] |=bit;
300                        mReclaimedPlanes[i] &= ~bit;
301                    }
302                }
303            }
304        }
305    }
306}
307
308bool DisplayPlaneManager::isOverlayPlanesDisabled()
309{
310    for (int i = 0; i < DisplayPlane::PLANE_MAX; i++) {
311        for (int j = 0; j < mPlaneCount[i]; j++) {
312            DisplayPlane* plane = (DisplayPlane *)mPlanes[i][j];
313            if (plane && plane->getType() == DisplayPlane::PLANE_OVERLAY) {
314                if (!plane->isDisabled())
315                    return false;
316            }
317        }
318    }
319
320    return true;
321}
322
323void DisplayPlaneManager::dump(Dump& d)
324{
325    d.append("Display Plane Manager state:\n");
326    d.append("-------------------------------------------------------------\n");
327    d.append(" PLANE TYPE | COUNT |   FREE   | RECLAIMED \n");
328    d.append("------------+-------+----------+-----------\n");
329    d.append("    SPRITE  |  %2d   | %08x | %08x\n",
330             mPlaneCount[DisplayPlane::PLANE_SPRITE],
331             mFreePlanes[DisplayPlane::PLANE_SPRITE],
332             mReclaimedPlanes[DisplayPlane::PLANE_SPRITE]);
333    d.append("   OVERLAY  |  %2d   | %08x | %08x\n",
334             mPlaneCount[DisplayPlane::PLANE_OVERLAY],
335             mFreePlanes[DisplayPlane::PLANE_OVERLAY],
336             mReclaimedPlanes[DisplayPlane::PLANE_OVERLAY]);
337    d.append("   PRIMARY  |  %2d   | %08x | %08x\n",
338             mPlaneCount[DisplayPlane::PLANE_PRIMARY],
339             mFreePlanes[DisplayPlane::PLANE_PRIMARY],
340             mReclaimedPlanes[DisplayPlane::PLANE_PRIMARY]);
341    d.append("   CURSOR   |  %2d   | %08x | %08x\n",
342             mPlaneCount[DisplayPlane::PLANE_CURSOR],
343             mFreePlanes[DisplayPlane::PLANE_CURSOR],
344             mReclaimedPlanes[DisplayPlane::PLANE_CURSOR]);
345}
346
347} // namespace intel
348} // namespace android
349
350
351