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         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 
mapBuffer(DataBuffer * buffer)248 BufferMapper* 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 
isActiveBuffer(BufferMapper * mapper)274 bool 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 
updateActiveBuffers(BufferMapper * mapper)287 void 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 
invalidateActiveBuffers()305 void 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 
invalidateBufferCache()324 void 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 
assignToDevice(int disp)341 bool 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 
flip(void *)367 bool DisplayPlane::flip(void * /* ctx */)
368 {
369     RETURN_FALSE_IF_NOT_INIT();
370 
371     // always flip
372     return true;
373 }
374 
postFlip()375 void DisplayPlane::postFlip()
376 {
377     mUpdateMasks = 0;
378 }
379 
reset()380 bool 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 
setZOrder(int zorder)394 void DisplayPlane::setZOrder(int zorder)
395 {
396     mZOrder = zorder;
397 }
398 
getZOrder() const399 int DisplayPlane::getZOrder() const
400 {
401     return mZOrder;
402 }
403 
404 } // namespace intel
405 } // namespace android
406