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 
22 namespace android {
23 namespace intel {
24 
DisplayPlane(int index,int type,int disp)25 DisplayPlane::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 
~DisplayPlane()51 DisplayPlane::~DisplayPlane()
52 {
53     WARN_IF_NOT_DEINIT();
54 }
55 
initialize(uint32_t bufferCount)56 bool 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 
deinitialize()75 void 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 
checkPosition(int & x,int & y,int & w,int & h)93 void 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 
setPosition(int x,int y,int w,int h)110 void 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 
setSourceCrop(int x,int y,int w,int h)139 void 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 
setTransform(int trans)153 void 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 
setPlaneAlpha(uint8_t alpha,uint32_t blending)166 void 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 
setDataBuffer(uint32_t handle)181 bool 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 
mapBuffer(DataBuffer * buffer)251 BufferMapper* 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 
isActiveBuffer(BufferMapper * mapper)277 bool 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 
updateActiveBuffers(BufferMapper * mapper)290 void 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 
invalidateActiveBuffers()308 void 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 
invalidateBufferCache()327 void 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 
assignToDevice(int disp)344 bool 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 
flip(void *)370 bool DisplayPlane::flip(void * /* ctx */)
371 {
372     RETURN_FALSE_IF_NOT_INIT();
373 
374     // always flip
375     return true;
376 }
377 
postFlip()378 void DisplayPlane::postFlip()
379 {
380     mUpdateMasks = 0;
381 }
382 
reset()383 bool 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 
setZOrder(int zorder)397 void DisplayPlane::setZOrder(int zorder)
398 {
399     mZOrder = zorder;
400 }
401 
getZOrder() const402 int DisplayPlane::getZOrder() const
403 {
404     return mZOrder;
405 }
406 
407 } // namespace intel
408 } // namespace android
409