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