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        if (!mapper) {
221            ELOGTRACE("failed to map buffer %#x", handle);
222            bm->unlockDataBuffer(buffer);
223            return false;
224        }
225    } else {
226        VLOGTRACE("got mapper in saved data buffers and update source Crop");
227        mapper = mDataBuffers.valueAt(index);
228    }
229
230    // always update source crop to mapper
231    mapper->setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);
232
233    mapper->setIsCompression(isCompression);
234
235    // unlock buffer after getting mapper
236    bm->unlockDataBuffer(buffer);
237    buffer = NULL;
238
239    ret = setDataBuffer(*mapper);
240    if (ret) {
241        mCurrentDataBuffer = handle;
242        // update active buffers
243        updateActiveBuffers(mapper);
244    }
245    return ret;
246}
247
248BufferMapper* DisplayPlane::mapBuffer(DataBuffer *buffer)
249{
250    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
251
252    // invalidate buffer cache  if cache is full
253    if ((int)mDataBuffers.size() >= mCacheCapacity) {
254        invalidateBufferCache();
255    }
256
257    BufferMapper *mapper = bm->map(*buffer);
258    if (!mapper) {
259        ELOGTRACE("failed to map buffer");
260        return NULL;
261    }
262
263    // add it to data buffers
264    ssize_t index = mDataBuffers.add(buffer->getKey(), mapper);
265    if (index < 0) {
266        ELOGTRACE("failed to add mapper");
267        bm->unmap(mapper);
268        return NULL;
269    }
270
271    return mapper;
272}
273
274bool DisplayPlane::isActiveBuffer(BufferMapper *mapper)
275{
276    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
277        BufferMapper *activeMapper = mActiveBuffers.itemAt(i);
278        if (!activeMapper)
279            continue;
280        if (activeMapper->getKey() == mapper->getKey())
281            return true;
282    }
283
284    return false;
285}
286
287void DisplayPlane::updateActiveBuffers(BufferMapper *mapper)
288{
289    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
290
291    // unmap the first entry (oldest buffer)
292    if (mActiveBuffers.size() >= MIN_DATA_BUFFER_COUNT) {
293        BufferMapper *oldest = mActiveBuffers.itemAt(0);
294        bm->unmap(oldest);
295        mActiveBuffers.removeAt(0);
296    }
297
298    // queue it to active buffers
299    if (!isActiveBuffer(mapper)) {
300        mapper->incRef();
301        mActiveBuffers.push_back(mapper);
302    }
303}
304
305void DisplayPlane::invalidateActiveBuffers()
306{
307    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
308    BufferMapper* mapper;
309
310    RETURN_VOID_IF_NOT_INIT();
311
312    VLOGTRACE("invalidating active buffers");
313
314    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
315        mapper = mActiveBuffers.itemAt(i);
316        // unmap it
317        bm->unmap(mapper);
318    }
319
320    // clear recorded data buffers
321    mActiveBuffers.clear();
322}
323
324void DisplayPlane::invalidateBufferCache()
325{
326    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
327    BufferMapper* mapper;
328
329    RETURN_VOID_IF_NOT_INIT();
330
331    for (size_t i = 0; i < mDataBuffers.size(); i++) {
332        mapper = mDataBuffers.valueAt(i);
333        bm->unmap(mapper);
334    }
335
336    mDataBuffers.clear();
337    // reset current buffer
338    mCurrentDataBuffer = 0;
339}
340
341bool DisplayPlane::assignToDevice(int disp)
342{
343    RETURN_FALSE_IF_NOT_INIT();
344    ALOGTRACE("disp = %d", disp);
345
346    mDevice = disp;
347
348    Drm *drm = Hwcomposer::getInstance().getDrm();
349    if (!drm->getModeInfo(mDevice, mModeInfo)) {
350        ELOGTRACE("failed to get mode info");
351    }
352
353    mPanelOrientation = drm->getPanelOrientation(mDevice);
354
355    mForceScaling = DisplayQuery::forceFbScaling(disp);
356    drm->getDisplayResolution(disp, mDisplayWidth, mDisplayHeight);
357
358    if (mForceScaling) {
359        mModeInfo.hdisplay = mDisplayWidth;
360        mModeInfo.vdisplay = mDisplayHeight;
361
362    }
363
364    return true;
365}
366
367bool DisplayPlane::flip(void * /* ctx */)
368{
369    RETURN_FALSE_IF_NOT_INIT();
370
371    // always flip
372    return true;
373}
374
375void DisplayPlane::postFlip()
376{
377    mUpdateMasks = 0;
378}
379
380bool DisplayPlane::reset()
381{
382    // reclaim all allocated resources
383    if (mDataBuffers.size() > 0) {
384        invalidateBufferCache();
385    }
386
387    if (mActiveBuffers.size() > 0) {
388        invalidateActiveBuffers();
389    }
390
391    return true;
392}
393
394void DisplayPlane::setZOrder(int zorder)
395{
396    mZOrder = zorder;
397}
398
399int DisplayPlane::getZOrder() const
400{
401    return mZOrder;
402}
403
404} // namespace intel
405} // namespace android
406