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 <HwcTrace.h>
17#include <Hwcomposer.h>
18#include <DisplayPlane.h>
19#include <GraphicBuffer.h>
20
21namespace android {
22namespace intel {
23
24DisplayPlane::DisplayPlane(int index, int type, int disp)
25    : mIndex(index),
26      mType(type),
27      mZOrder(-1),
28      mDevice(disp),
29      mInitialized(false),
30      mDataBuffers(),
31      mActiveBuffers(),
32      mCacheCapacity(0),
33      mIsProtectedBuffer(false),
34      mTransform(0),
35      mPlaneAlpha(0),
36      mBlending(HWC_BLENDING_NONE),
37      mCurrentDataBuffer(0),
38      mUpdateMasks(0)
39{
40    CTRACE();
41    memset(&mPosition, 0, sizeof(mPosition));
42    memset(&mSrcCrop, 0, sizeof(mSrcCrop));
43}
44
45DisplayPlane::~DisplayPlane()
46{
47    WARN_IF_NOT_DEINIT();
48}
49
50bool DisplayPlane::initialize(uint32_t bufferCount)
51{
52    CTRACE();
53
54    if (bufferCount < MIN_DATA_BUFFER_COUNT) {
55        WTRACE("buffer count %d is too small", bufferCount);
56        bufferCount = MIN_DATA_BUFFER_COUNT;
57    }
58
59    // create buffer cache, adding few extra slots as buffer rendering is async
60    // buffer could still be queued in the display pipeline such that they
61    // can't be unmapped]
62    mCacheCapacity = bufferCount;
63    mDataBuffers.setCapacity(bufferCount);
64    mActiveBuffers.setCapacity(MIN_DATA_BUFFER_COUNT);
65    mInitialized = true;
66    return true;
67}
68
69void DisplayPlane::deinitialize()
70{
71    // invalidate cached data buffers
72    if (mDataBuffers.size()) {
73        // invalidateBufferCache will assert if object is not initialized
74        // so invoking it only there is buffer to invalidate.
75        invalidateBufferCache();
76    }
77
78    // invalidate active buffers
79    if (mActiveBuffers.size()) {
80        invalidateActiveBuffers();
81    }
82
83    mCurrentDataBuffer = 0;
84    mInitialized = false;
85}
86
87void DisplayPlane::checkPosition(int& x, int& y, int& w, int& h)
88{
89    drmModeModeInfoPtr mode = &mModeInfo;
90
91    if (mode->hdisplay == 0 || mode->vdisplay == 0)
92        return;
93
94    if (x < 0)
95        x = 0;
96    if (y < 0)
97        y = 0;
98    if ((x + w) > mode->hdisplay)
99        w = mode->hdisplay - x;
100    if ((y + h) > mode->vdisplay)
101        h = mode->vdisplay - y;
102}
103
104void DisplayPlane::setPosition(int x, int y, int w, int h)
105{
106    ATRACE("Position = %d, %d - %dx%d", x, y, w, h);
107
108    if (mPosition.x != x || mPosition.y != y ||
109        mPosition.w != w || mPosition.h != h) {
110        mUpdateMasks |= PLANE_POSITION_CHANGED;
111        mPosition.x = x;
112        mPosition.y = y;
113        mPosition.w = w;
114        mPosition.h = h;
115    }
116}
117
118void DisplayPlane::setSourceCrop(int x, int y, int w, int h)
119{
120    ATRACE("Source crop = %d, %d - %dx%d", x, y, w, h);
121
122    if (mSrcCrop.x != x || mSrcCrop.y != y ||
123        mSrcCrop.w != w || mSrcCrop.h != h) {
124        mUpdateMasks |= PLANE_SOURCE_CROP_CHANGED;
125        mSrcCrop.x = x;
126        mSrcCrop.y = y;
127        if (mType == DisplayPlane::PLANE_OVERLAY) {
128            mSrcCrop.w = w & (~0x01);
129            mSrcCrop.h = h & (~0x01);
130        } else {
131            mSrcCrop.w = w;
132            mSrcCrop.h = h;
133        }
134    }
135}
136
137void DisplayPlane::setTransform(int trans)
138{
139    ATRACE("transform = %d", trans);
140
141    if (mTransform == trans) {
142        return;
143    }
144
145    mTransform = trans;
146
147    mUpdateMasks |= PLANE_TRANSFORM_CHANGED;
148}
149
150void DisplayPlane::setPlaneAlpha(uint8_t alpha, uint32_t blending)
151{
152    ATRACE("plane alpha = 0x%x", alpha);
153
154    if (mPlaneAlpha != alpha) {
155        mPlaneAlpha = alpha;
156        mUpdateMasks |= PLANE_BUFFER_CHANGED;
157    }
158
159    if (mBlending != blending) {
160        mBlending = blending;
161        mUpdateMasks |= PLANE_BUFFER_CHANGED;
162    }
163}
164
165bool DisplayPlane::setDataBuffer(buffer_handle_t handle)
166{
167    DataBuffer *buffer;
168    BufferMapper *mapper;
169    ssize_t index;
170    bool ret;
171    bool isCompression;
172    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
173
174    RETURN_FALSE_IF_NOT_INIT();
175    ATRACE("handle = %#x", handle);
176
177    if (!handle) {
178        WTRACE("invalid buffer handle");
179        return false;
180    }
181
182    // do not need to update the buffer handle
183    if (mCurrentDataBuffer != handle)
184        mUpdateMasks |= PLANE_BUFFER_CHANGED;
185
186    // if no update then do Not need set data buffer
187    if (!mUpdateMasks)
188        return true;
189
190    buffer = bm->lockDataBuffer(handle);
191    if (!buffer) {
192        ETRACE("failed to get buffer");
193        return false;
194    }
195
196    mIsProtectedBuffer = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);
197    isCompression = GraphicBuffer::isCompressionBuffer((GraphicBuffer*)buffer);
198
199    // map buffer if it's not in cache
200    index = mDataBuffers.indexOfKey(buffer->getKey());
201    if (index < 0) {
202        VTRACE("unmapped buffer, mapping...");
203        mapper = mapBuffer(buffer);
204        if (!mapper) {
205            ETRACE("failed to map buffer %p", handle);
206            bm->unlockDataBuffer(buffer);
207            return false;
208        }
209    } else {
210        VTRACE("got mapper in saved data buffers and update source Crop");
211        mapper = mDataBuffers.valueAt(index);
212    }
213
214    // always update source crop to mapper
215    mapper->setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);
216
217    mapper->setIsCompression(isCompression);
218
219    // unlock buffer after getting mapper
220    bm->unlockDataBuffer(buffer);
221    buffer = NULL;
222
223    ret = setDataBuffer(*mapper);
224    if (ret) {
225        mCurrentDataBuffer = handle;
226        // update active buffers
227        updateActiveBuffers(mapper);
228    }
229    return ret;
230}
231
232BufferMapper* DisplayPlane::mapBuffer(DataBuffer *buffer)
233{
234    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
235
236    // invalidate buffer cache  if cache is full
237    if ((int)mDataBuffers.size() >= mCacheCapacity) {
238        invalidateBufferCache();
239    }
240
241    BufferMapper *mapper = bm->map(*buffer);
242    if (!mapper) {
243        ETRACE("failed to map buffer");
244        return NULL;
245    }
246
247    // add it to data buffers
248    ssize_t index = mDataBuffers.add(buffer->getKey(), mapper);
249    if (index < 0) {
250        ETRACE("failed to add mapper");
251        bm->unmap(mapper);
252        return NULL;
253    }
254
255    return mapper;
256}
257
258int DisplayPlane::findActiveBuffer(BufferMapper *mapper)
259{
260    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
261        BufferMapper *activeMapper = mActiveBuffers.itemAt(i);
262        if (!activeMapper)
263            continue;
264        if (activeMapper->getKey() == mapper->getKey())
265            return i;
266    }
267
268    return -1;
269}
270
271void DisplayPlane::updateActiveBuffers(BufferMapper *mapper)
272{
273    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
274    int index = findActiveBuffer(mapper);
275    bool exist = (0 <= index && index < (int)mActiveBuffers.size());
276
277    // unmap the first entry (oldest buffer)
278    if (!exist && mActiveBuffers.size() >= MIN_DATA_BUFFER_COUNT) {
279        BufferMapper *oldest = mActiveBuffers.itemAt(0);
280        bm->unmap(oldest);
281        mActiveBuffers.removeAt(0);
282    }
283
284    // queue it to active buffers
285    if (!exist) {
286        mapper->incRef();
287    } else {
288        mActiveBuffers.removeAt(index);
289    }
290    mActiveBuffers.push_back(mapper);
291}
292
293void DisplayPlane::invalidateActiveBuffers()
294{
295    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
296    BufferMapper* mapper;
297
298    RETURN_VOID_IF_NOT_INIT();
299
300    VTRACE("invalidating active buffers");
301
302    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
303        mapper = mActiveBuffers.itemAt(i);
304        // unmap it
305        bm->unmap(mapper);
306    }
307
308    // clear recorded data buffers
309    mActiveBuffers.clear();
310}
311
312void DisplayPlane::invalidateBufferCache()
313{
314    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
315    BufferMapper* mapper;
316
317    RETURN_VOID_IF_NOT_INIT();
318
319    for (size_t i = 0; i < mDataBuffers.size(); i++) {
320        mapper = mDataBuffers.valueAt(i);
321        bm->unmap(mapper);
322    }
323
324    mDataBuffers.clear();
325    // reset current buffer
326    mCurrentDataBuffer = 0;
327}
328
329void DisplayPlane::resetCurrentBuffer()
330{
331    // reset current data buffer
332    mCurrentDataBuffer = 0;
333}
334
335bool DisplayPlane::assignToDevice(int disp)
336{
337    RETURN_FALSE_IF_NOT_INIT();
338    ATRACE("disp = %d", disp);
339
340    mDevice = disp;
341
342    Drm *drm = Hwcomposer::getInstance().getDrm();
343    if (!drm->getModeInfo(mDevice, mModeInfo)) {
344        ETRACE("failed to get mode info");
345    }
346
347    mPanelOrientation = drm->getPanelOrientation(mDevice);
348
349    return true;
350}
351
352bool DisplayPlane::flip(void *ctx)
353{
354    RETURN_FALSE_IF_NOT_INIT();
355
356    // always flip
357    return true;
358}
359
360void DisplayPlane::postFlip()
361{
362    mUpdateMasks = 0;
363}
364
365bool DisplayPlane::reset()
366{
367    // reclaim all allocated resources
368    if (mDataBuffers.size() > 0) {
369        invalidateBufferCache();
370    }
371
372    if (mActiveBuffers.size() > 0) {
373        invalidateActiveBuffers();
374    }
375
376    return true;
377}
378
379void DisplayPlane::setZOrder(int zorder)
380{
381    mZOrder = zorder;
382}
383
384int DisplayPlane::getZOrder() const
385{
386    return mZOrder;
387}
388
389} // namespace intel
390} // namespace android
391