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