1/* 2 * Copyright 2018 The Android Open Source Project 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 17#pragma once 18 19#ifndef LOG_TAG 20#warning "ComposerResources.h included without LOG_TAG" 21#endif 22 23#include <memory> 24#include <mutex> 25#include <unordered_map> 26#include <vector> 27 28#include <android/hardware/graphics/mapper/2.0/IMapper.h> 29#include <log/log.h> 30 31namespace android { 32namespace hardware { 33namespace graphics { 34namespace composer { 35namespace V2_1 { 36namespace hal { 37 38// wrapper for IMapper to import buffers and sideband streams 39class ComposerHandleImporter { 40 public: 41 bool init() { 42 mMapper = mapper::V2_0::IMapper::getService(); 43 ALOGE_IF(!mMapper, "failed to get mapper service"); 44 return mMapper != nullptr; 45 } 46 47 Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) { 48 if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) { 49 *outBufferHandle = nullptr; 50 return Error::NONE; 51 } 52 53 mapper::V2_0::Error error; 54 const native_handle_t* bufferHandle; 55 mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { 56 error = tmpError; 57 bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); 58 }); 59 if (error != mapper::V2_0::Error::NONE) { 60 return Error::NO_RESOURCES; 61 } 62 63 *outBufferHandle = bufferHandle; 64 return Error::NONE; 65 } 66 67 void freeBuffer(const native_handle_t* bufferHandle) { 68 if (bufferHandle) { 69 mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); 70 } 71 } 72 73 Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) { 74 const native_handle_t* streamHandle = nullptr; 75 if (rawHandle) { 76 streamHandle = native_handle_clone(rawHandle); 77 if (!streamHandle) { 78 return Error::NO_RESOURCES; 79 } 80 } 81 82 *outStreamHandle = streamHandle; 83 return Error::NONE; 84 } 85 86 void freeStream(const native_handle_t* streamHandle) { 87 if (streamHandle) { 88 native_handle_close(streamHandle); 89 native_handle_delete(const_cast<native_handle_t*>(streamHandle)); 90 } 91 } 92 93 private: 94 sp<mapper::V2_0::IMapper> mMapper; 95}; 96 97class ComposerHandleCache { 98 public: 99 enum class HandleType { 100 INVALID, 101 BUFFER, 102 STREAM, 103 }; 104 105 ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize) 106 : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {} 107 108 // must be initialized later with initCache 109 ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {} 110 111 ~ComposerHandleCache() { 112 switch (mHandleType) { 113 case HandleType::BUFFER: 114 for (auto handle : mHandles) { 115 mImporter.freeBuffer(handle); 116 } 117 break; 118 case HandleType::STREAM: 119 for (auto handle : mHandles) { 120 mImporter.freeStream(handle); 121 } 122 break; 123 default: 124 break; 125 } 126 } 127 128 ComposerHandleCache(const ComposerHandleCache&) = delete; 129 ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; 130 131 bool initCache(HandleType type, uint32_t cacheSize) { 132 // already initialized 133 if (mHandleType != HandleType::INVALID) { 134 return false; 135 } 136 137 mHandleType = type; 138 mHandles.resize(cacheSize, nullptr); 139 140 return true; 141 } 142 143 Error lookupCache(uint32_t slot, const native_handle_t** outHandle) { 144 if (slot < mHandles.size()) { 145 *outHandle = mHandles[slot]; 146 return Error::NONE; 147 } else { 148 return Error::BAD_PARAMETER; 149 } 150 } 151 152 Error updateCache(uint32_t slot, const native_handle_t* handle, 153 const native_handle** outReplacedHandle) { 154 if (slot < mHandles.size()) { 155 auto& cachedHandle = mHandles[slot]; 156 *outReplacedHandle = cachedHandle; 157 cachedHandle = handle; 158 return Error::NONE; 159 } else { 160 return Error::BAD_PARAMETER; 161 } 162 } 163 164 // when fromCache is true, look up in the cache; otherwise, update the cache 165 Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 166 const native_handle_t** outHandle, const native_handle** outReplacedHandle) { 167 if (fromCache) { 168 *outReplacedHandle = nullptr; 169 return lookupCache(slot, outHandle); 170 } else { 171 *outHandle = inHandle; 172 return updateCache(slot, inHandle, outReplacedHandle); 173 } 174 } 175 176 private: 177 ComposerHandleImporter& mImporter; 178 HandleType mHandleType = HandleType::INVALID; 179 std::vector<const native_handle_t*> mHandles; 180}; 181 182// layer resource 183class ComposerLayerResource { 184 public: 185 ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize) 186 : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize), 187 mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {} 188 189 Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 190 const native_handle_t** outHandle, const native_handle** outReplacedHandle) { 191 return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); 192 } 193 194 Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 195 const native_handle_t** outHandle, 196 const native_handle** outReplacedHandle) { 197 return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, 198 outReplacedHandle); 199 } 200 201 protected: 202 ComposerHandleCache mBufferCache; 203 ComposerHandleCache mSidebandStreamCache; 204}; 205 206// display resource 207class ComposerDisplayResource { 208 public: 209 enum class DisplayType { 210 PHYSICAL, 211 VIRTUAL, 212 }; 213 214 ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, 215 uint32_t outputBufferCacheSize) 216 : mType(type), 217 mClientTargetCache(importer), 218 mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 219 outputBufferCacheSize) {} 220 221 bool initClientTargetCache(uint32_t cacheSize) { 222 return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); 223 } 224 225 bool isVirtual() const { return mType == DisplayType::VIRTUAL; } 226 227 Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 228 const native_handle_t** outHandle, 229 const native_handle** outReplacedHandle) { 230 return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, 231 outReplacedHandle); 232 } 233 234 Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, 235 const native_handle_t** outHandle, 236 const native_handle** outReplacedHandle) { 237 return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, 238 outReplacedHandle); 239 } 240 241 bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) { 242 auto result = mLayerResources.emplace(layer, std::move(layerResource)); 243 return result.second; 244 } 245 246 bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; } 247 248 ComposerLayerResource* findLayerResource(Layer layer) { 249 auto layerIter = mLayerResources.find(layer); 250 if (layerIter == mLayerResources.end()) { 251 return nullptr; 252 } 253 254 return layerIter->second.get(); 255 } 256 257 std::vector<Layer> getLayers() const { 258 std::vector<Layer> layers; 259 layers.reserve(mLayerResources.size()); 260 for (const auto& layerKey : mLayerResources) { 261 layers.push_back(layerKey.first); 262 } 263 return layers; 264 } 265 266 protected: 267 const DisplayType mType; 268 ComposerHandleCache mClientTargetCache; 269 ComposerHandleCache mOutputBufferCache; 270 271 std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources; 272}; 273 274class ComposerResources { 275 private: 276 template <bool isBuffer> 277 class ReplacedHandle; 278 279 public: 280 static std::unique_ptr<ComposerResources> create() { 281 auto resources = std::make_unique<ComposerResources>(); 282 return resources->init() ? std::move(resources) : nullptr; 283 } 284 285 ComposerResources() = default; 286 virtual ~ComposerResources() = default; 287 288 bool init() { return mImporter.init(); } 289 290 using RemoveDisplay = 291 std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>; 292 void clear(RemoveDisplay removeDisplay) { 293 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 294 for (const auto& displayKey : mDisplayResources) { 295 Display display = displayKey.first; 296 const ComposerDisplayResource& displayResource = *displayKey.second; 297 removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers()); 298 } 299 mDisplayResources.clear(); 300 } 301 302 Error addPhysicalDisplay(Display display) { 303 auto displayResource = 304 createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); 305 306 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 307 auto result = mDisplayResources.emplace(display, std::move(displayResource)); 308 return result.second ? Error::NONE : Error::BAD_DISPLAY; 309 } 310 311 Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) { 312 auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL, 313 outputBufferCacheSize); 314 315 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 316 auto result = mDisplayResources.emplace(display, std::move(displayResource)); 317 return result.second ? Error::NONE : Error::BAD_DISPLAY; 318 } 319 320 Error removeDisplay(Display display) { 321 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 322 return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY; 323 } 324 325 Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) { 326 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 327 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 328 if (!displayResource) { 329 return Error::BAD_DISPLAY; 330 } 331 332 return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE 333 : Error::BAD_PARAMETER; 334 } 335 336 Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { 337 auto layerResource = createLayerResource(bufferCacheSize); 338 339 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 340 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 341 if (!displayResource) { 342 return Error::BAD_DISPLAY; 343 } 344 345 return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE 346 : Error::BAD_LAYER; 347 } 348 349 Error removeLayer(Display display, Layer layer) { 350 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 351 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 352 if (!displayResource) { 353 return Error::BAD_DISPLAY; 354 } 355 356 return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER; 357 } 358 359 using ReplacedBufferHandle = ReplacedHandle<true>; 360 using ReplacedStreamHandle = ReplacedHandle<false>; 361 362 Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, 363 const native_handle_t* rawHandle, 364 const native_handle_t** outBufferHandle, 365 ReplacedBufferHandle* outReplacedBuffer) { 366 return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle, 367 outBufferHandle, outReplacedBuffer); 368 } 369 370 Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, 371 const native_handle_t* rawHandle, 372 const native_handle_t** outBufferHandle, 373 ReplacedBufferHandle* outReplacedBuffer) { 374 return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle, 375 outBufferHandle, outReplacedBuffer); 376 } 377 378 Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, 379 const native_handle_t* rawHandle, const native_handle_t** outBufferHandle, 380 ReplacedBufferHandle* outReplacedBuffer) { 381 return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle, 382 outBufferHandle, outReplacedBuffer); 383 } 384 385 Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle, 386 const native_handle_t** outStreamHandle, 387 ReplacedStreamHandle* outReplacedStream) { 388 return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle, 389 outStreamHandle, outReplacedStream); 390 } 391 392 protected: 393 virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource( 394 ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { 395 return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); 396 } 397 398 virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) { 399 return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize); 400 } 401 402 ComposerDisplayResource* findDisplayResourceLocked(Display display) { 403 auto iter = mDisplayResources.find(display); 404 if (iter == mDisplayResources.end()) { 405 return nullptr; 406 } 407 return iter->second.get(); 408 } 409 410 ComposerHandleImporter mImporter; 411 412 std::mutex mDisplayResourcesMutex; 413 std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources; 414 415 private: 416 enum class Cache { 417 CLIENT_TARGET, 418 OUTPUT_BUFFER, 419 LAYER_BUFFER, 420 LAYER_SIDEBAND_STREAM, 421 }; 422 423 // When a buffer in the cache is replaced by a new one, we must keep it 424 // alive until it has been replaced in ComposerHal. 425 template <bool isBuffer> 426 class ReplacedHandle { 427 public: 428 ReplacedHandle() = default; 429 ReplacedHandle(const ReplacedHandle&) = delete; 430 ReplacedHandle& operator=(const ReplacedHandle&) = delete; 431 432 ~ReplacedHandle() { reset(); } 433 434 void reset(ComposerHandleImporter* importer = nullptr, 435 const native_handle_t* handle = nullptr) { 436 if (mHandle) { 437 if (isBuffer) { 438 mImporter->freeBuffer(mHandle); 439 } else { 440 mImporter->freeStream(mHandle); 441 } 442 } 443 444 mImporter = importer; 445 mHandle = handle; 446 } 447 448 private: 449 ComposerHandleImporter* mImporter = nullptr; 450 const native_handle_t* mHandle = nullptr; 451 }; 452 453 template <Cache cache, bool isBuffer> 454 Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache, 455 const native_handle_t* rawHandle, const native_handle_t** outHandle, 456 ReplacedHandle<isBuffer>* outReplacedHandle) { 457 Error error; 458 459 // import the raw handle (or ignore raw handle when fromCache is true) 460 const native_handle_t* importedHandle = nullptr; 461 if (!fromCache) { 462 error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle) 463 : mImporter.importStream(rawHandle, &importedHandle); 464 if (error != Error::NONE) { 465 return error; 466 } 467 } 468 469 std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); 470 471 // find display/layer resource 472 const bool needLayerResource = 473 (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM); 474 ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); 475 ComposerLayerResource* layerResource = (displayResource && needLayerResource) 476 ? displayResource->findLayerResource(layer) 477 : nullptr; 478 479 // lookup or update cache 480 const native_handle_t* replacedHandle = nullptr; 481 if (displayResource && (!needLayerResource || layerResource)) { 482 switch (cache) { 483 case Cache::CLIENT_TARGET: 484 error = displayResource->getClientTarget(slot, fromCache, importedHandle, 485 outHandle, &replacedHandle); 486 break; 487 case Cache::OUTPUT_BUFFER: 488 error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, 489 outHandle, &replacedHandle); 490 break; 491 case Cache::LAYER_BUFFER: 492 error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle, 493 &replacedHandle); 494 break; 495 case Cache::LAYER_SIDEBAND_STREAM: 496 error = layerResource->getSidebandStream(slot, fromCache, importedHandle, 497 outHandle, &replacedHandle); 498 break; 499 default: 500 error = Error::BAD_PARAMETER; 501 break; 502 } 503 504 if (error != Error::NONE) { 505 ALOGW("invalid cache %d slot %d", int(cache), int(slot)); 506 } 507 } else if (!displayResource) { 508 error = Error::BAD_DISPLAY; 509 } else { 510 error = Error::BAD_LAYER; 511 } 512 513 // clean up on errors 514 if (error != Error::NONE) { 515 if (!fromCache) { 516 if (isBuffer) { 517 mImporter.freeBuffer(importedHandle); 518 } else { 519 mImporter.freeStream(importedHandle); 520 } 521 } 522 return error; 523 } 524 525 outReplacedHandle->reset(&mImporter, replacedHandle); 526 527 return Error::NONE; 528 } 529}; 530 531} // namespace hal 532} // namespace V2_1 533} // namespace composer 534} // namespace graphics 535} // namespace hardware 536} // namespace android 537