1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "buffer_queue.h" 17#include <algorithm> 18#include <fstream> 19#include <sstream> 20#include <sys/time.h> 21#include <cinttypes> 22#include <unistd.h> 23#include <parameters.h> 24 25#include "acquire_fence_manager.h" 26#include "buffer_utils.h" 27#include "buffer_log.h" 28#include "hebc_white_list.h" 29#include "hitrace_meter.h" 30#include "metadata_helper.h" 31#include "sandbox_utils.h" 32#include "surface_buffer_impl.h" 33#include "sync_fence.h" 34#include "sync_fence_tracker.h" 35#include "surface_utils.h" 36#include "surface_trace.h" 37#include "v2_0/buffer_handle_meta_key_type.h" 38 39namespace OHOS { 40namespace { 41constexpr int32_t FORCE_GLOBAL_ALPHA_MIN = -1; 42constexpr int32_t FORCE_GLOBAL_ALPHA_MAX = 255; 43constexpr uint32_t UNIQUE_ID_OFFSET = 32; 44constexpr uint32_t BUFFER_MEMSIZE_RATE = 1024; 45constexpr uint32_t BUFFER_MEMSIZE_FORMAT = 2; 46constexpr uint32_t MAXIMUM_LENGTH_OF_APP_FRAMEWORK = 64; 47constexpr uint32_t INVALID_SEQUENCE = 0xFFFFFFFF; 48constexpr uint32_t ONE_SECOND_TIMESTAMP = 1e9; 49} 50 51static const std::map<BufferState, std::string> BufferStateStrs = { 52 {BUFFER_STATE_RELEASED, "0 <released>"}, 53 {BUFFER_STATE_REQUESTED, "1 <requested>"}, 54 {BUFFER_STATE_FLUSHED, "2 <flushed>"}, 55 {BUFFER_STATE_ACQUIRED, "3 <acquired>"}, 56 {BUFFER_STATE_ATTACHED, "4 <attached>"}, 57}; 58 59static uint64_t GetUniqueIdImpl() 60{ 61 static std::atomic<uint32_t> counter { 0 }; 62 static uint64_t id = static_cast<uint64_t>(GetRealPid()) << UNIQUE_ID_OFFSET; 63 return id | counter.fetch_add(1, std::memory_order_relaxed); 64} 65 66static bool IsLocalRender() 67{ 68 std::ifstream procfile("/proc/self/cmdline"); 69 if (!procfile.is_open()) { 70 BLOGE("Error opening procfile!"); 71 return false; 72 } 73 std::string processName; 74 std::getline(procfile, processName); 75 procfile.close(); 76 std::string target = "/system/bin/render_service"; 77 bool result = processName.substr(0, target.size()) == target; 78 return result; 79} 80 81BufferQueue::BufferQueue(const std::string &name, bool isShared) 82 : name_(name), uniqueId_(GetUniqueIdImpl()), isShared_(isShared), isLocalRender_(IsLocalRender()) 83{ 84 BLOGD("BufferQueue ctor, uniqueId: %{public}" PRIu64 ".", uniqueId_); 85 if (isShared_ == true) { 86 bufferQueueSize_ = 1; 87 } 88 89 if (isLocalRender_) { 90 if (!HebcWhiteList::GetInstance().Init()) { 91 BLOGW("HebcWhiteList init failed"); 92 } 93 } 94 acquireLastFlushedBufSequence_ = INVALID_SEQUENCE; 95} 96 97BufferQueue::~BufferQueue() 98{ 99 BLOGD("~BufferQueue dtor, uniqueId: %{public}" PRIu64 ".", uniqueId_); 100 for (auto &[id, _] : bufferQueueCache_) { 101 if (onBufferDeleteForRSMainThread_ != nullptr) { 102 onBufferDeleteForRSMainThread_(id); 103 } 104 if (onBufferDeleteForRSHardwareThread_ != nullptr) { 105 onBufferDeleteForRSHardwareThread_(id); 106 } 107 } 108} 109 110uint32_t BufferQueue::GetUsedSize() 111{ 112 return static_cast<uint32_t>(bufferQueueCache_.size()); 113} 114 115GSError BufferQueue::GetProducerInitInfo(ProducerInitInfo &info) 116{ 117 std::lock_guard<std::mutex> lockGuard(mutex_); 118 info.name = name_; 119 info.width = defaultWidth_; 120 info.height = defaultHeight_; 121 info.uniqueId = uniqueId_; 122 info.isInHebcList = HebcWhiteList::GetInstance().Check(info.appName); 123 return GSERROR_OK; 124} 125 126GSError BufferQueue::PopFromFreeListLocked(sptr<SurfaceBuffer> &buffer, 127 const BufferRequestConfig &config) 128{ 129 if (isShared_ == true && GetUsedSize() > 0) { 130 buffer = bufferQueueCache_.begin()->second.buffer; 131 return GSERROR_OK; 132 } 133 134 for (auto it = freeList_.begin(); it != freeList_.end(); it++) { 135 auto mapIter = bufferQueueCache_.find(*it); 136 if (mapIter != bufferQueueCache_.end() && mapIter->second.config == config) { 137 if (mapIter->first == acquireLastFlushedBufSequence_) { 138 continue; 139 } 140 buffer = mapIter->second.buffer; 141 freeList_.erase(it); 142 return GSERROR_OK; 143 } 144 } 145 146 if (freeList_.empty() || GetUsedSize() < bufferQueueSize_ || 147 (freeList_.size() == 1 && freeList_.front() == acquireLastFlushedBufSequence_)) { 148 buffer = nullptr; 149 return GSERROR_NO_BUFFER; 150 } 151 152 if (freeList_.front() == acquireLastFlushedBufSequence_) { 153 freeList_.pop_front(); 154 freeList_.push_back(acquireLastFlushedBufSequence_); 155 } 156 157 buffer = bufferQueueCache_[freeList_.front()].buffer; 158 buffer->SetSurfaceBufferColorGamut(config.colorGamut); 159 buffer->SetSurfaceBufferTransform(config.transform); 160 freeList_.pop_front(); 161 return GSERROR_OK; 162} 163 164GSError BufferQueue::PopFromDirtyListLocked(sptr<SurfaceBuffer> &buffer) 165{ 166 if (isShared_ == true && GetUsedSize() > 0) { 167 buffer = bufferQueueCache_.begin()->second.buffer; 168 return GSERROR_OK; 169 } 170 171 if (!dirtyList_.empty()) { 172 buffer = bufferQueueCache_[dirtyList_.front()].buffer; 173 dirtyList_.pop_front(); 174 return GSERROR_OK; 175 } else { 176 buffer = nullptr; 177 return GSERROR_NO_BUFFER; 178 } 179} 180 181GSError BufferQueue::CheckRequestConfig(const BufferRequestConfig &config) 182{ 183 uint32_t align = config.strideAlignment; 184 if (align < SURFACE_MIN_STRIDE_ALIGNMENT || align > SURFACE_MAX_STRIDE_ALIGNMENT) { 185 BLOGW("align is %{public}d, uniqueId: %{public}" PRIu64 ".", align, uniqueId_); 186 return GSERROR_INVALID_ARGUMENTS; 187 } 188 189 if (align & (align - 1)) { 190 BLOGW("align is %{public}d, uniqueId: %{public}" PRIu64 ".", align, uniqueId_); 191 return GSERROR_INVALID_ARGUMENTS; 192 } 193 194 if (config.colorGamut <= GraphicColorGamut::GRAPHIC_COLOR_GAMUT_INVALID || 195 config.colorGamut > GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020 + 1) { 196 BLOGW("colorGamut is %{public}d, uniqueId: %{public}" PRIu64 ".", 197 static_cast<uint32_t>(config.colorGamut), uniqueId_); 198 return GSERROR_INVALID_ARGUMENTS; 199 } 200 201 if (config.transform < GraphicTransformType::GRAPHIC_ROTATE_NONE || 202 config.transform >= GraphicTransformType::GRAPHIC_ROTATE_BUTT) { 203 BLOGW("transform is %{public}d, uniqueId: %{public}" PRIu64 ".", config.transform, uniqueId_); 204 return GSERROR_INVALID_ARGUMENTS; 205 } 206 return GSERROR_OK; 207} 208 209GSError BufferQueue::CheckFlushConfig(const BufferFlushConfigWithDamages &config) 210{ 211 for (decltype(config.damages.size()) i = 0; i < config.damages.size(); i++) { 212 if (config.damages[i].w < 0 || config.damages[i].h < 0) { 213 BLOGW("damages[%{public}zu].w is %{public}d, .h is %{public}d, uniqueId: %{public}" PRIu64 ".", 214 i, config.damages[i].w, config.damages[i].h, uniqueId_); 215 return GSERROR_INVALID_ARGUMENTS; 216 } 217 } 218 return GSERROR_OK; 219} 220 221bool BufferQueue::QueryIfBufferAvailable() 222{ 223 std::lock_guard<std::mutex> lockGuard(mutex_); 224 bool ret = !freeList_.empty() || (GetUsedSize() < bufferQueueSize_); 225 return ret; 226} 227 228static GSError DelegatorDequeueBuffer(wptr<ConsumerSurfaceDelegator>& delegator, 229 const BufferRequestConfig& config, 230 sptr<BufferExtraData>& bedata, 231 struct IBufferProducer::RequestBufferReturnValue& retval) 232{ 233 auto consumerDelegator = delegator.promote(); 234 if (consumerDelegator == nullptr) { 235 BLOGE("Consumer surface delegator has been expired"); 236 return GSERROR_INVALID_ARGUMENTS; 237 } 238 auto ret = consumerDelegator->DequeueBuffer(config, bedata, retval); 239 if (ret != GSERROR_OK) { 240 BLOGE("Consumer surface delegator failed to dequeuebuffer, err: %{public}d", ret); 241 return ret; 242 } 243 244 ret = retval.buffer->Map(); 245 if (ret != GSERROR_OK) { 246 BLOGE("Buffer map failed, err: %{public}d", ret); 247 return ret; 248 } 249 retval.buffer->SetSurfaceBufferWidth(retval.buffer->GetWidth()); 250 retval.buffer->SetSurfaceBufferHeight(retval.buffer->GetHeight()); 251 252 return GSERROR_OK; 253} 254 255static void SetReturnValue(sptr<SurfaceBuffer>& buffer, sptr<BufferExtraData>& bedata, 256 struct IBufferProducer::RequestBufferReturnValue& retval) 257{ 258 retval.sequence = buffer->GetSeqNum(); 259 bedata = buffer->GetExtraData(); 260 retval.fence = SyncFence::InvalidFence(); 261} 262 263void BufferQueue::SetSurfaceBufferHebcMetaLocked(sptr<SurfaceBuffer> buffer) 264{ 265 using namespace HDI::Display::Graphic::Common; 266 // usage does not contain BUFFER_USAGE_CPU_HW_BOTH, just return 267 if (!(buffer->GetUsage() & BUFFER_USAGE_CPU_HW_BOTH)) { 268 return; 269 } 270 271 V2_0::BufferHandleAttrKey key = V2_0::BufferHandleAttrKey::ATTRKEY_REQUEST_ACCESS_TYPE; 272 std::vector<uint8_t> values; 273 if (isCpuAccessable_) { // hebc is off 274 values.emplace_back(static_cast<uint8_t>(V2_0::HebcAccessType::HEBC_ACCESS_CPU_ACCESS)); 275 } else { // hebc is on 276 values.emplace_back(static_cast<uint8_t>(V2_0::HebcAccessType::HEBC_ACCESS_HW_ONLY)); 277 } 278 279 buffer->SetMetadata(key, values); 280} 281 282void BufferQueue::SetBatchHandle(bool batch) 283{ 284 std::unique_lock<std::mutex> lock(mutex_); 285 isBatch_ = batch; 286} 287 288GSError BufferQueue::RequestBufferCheckStatus() 289{ 290 { 291 std::unique_lock<std::mutex> lock(mutex_); 292 if (isBatch_) { 293 return GSERROR_OK; 294 } 295 if (!GetStatusLocked()) { 296 SURFACE_TRACE_NAME_FMT("RequestBufferCheckStatus status wrong," 297 "surface name: %s queueId: %" PRIu64 " status: %u", name_.c_str(), uniqueId_, GetStatusLocked()); 298 BLOGN_FAILURE_RET(GSERROR_NO_CONSUMER); 299 } 300 } 301 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 302 if (listener_ == nullptr && listenerClazz_ == nullptr) { 303 SURFACE_TRACE_NAME_FMT("RequestBufferCheckStatus no listener, surface name: %s queueId: %" PRIu64, 304 name_.c_str(), uniqueId_); 305 BLOGN_FAILURE_RET(SURFACE_ERROR_CONSUMER_UNREGISTER_LISTENER); 306 } 307 308 return GSERROR_OK; 309} 310 311bool BufferQueue::WaitForCondition() 312{ 313 return (!freeList_.empty() && !(freeList_.size() == 1 && freeList_.front() == acquireLastFlushedBufSequence_)) || 314 (GetUsedSize() < bufferQueueSize_) || !GetStatusLocked(); 315} 316 317void BufferQueue::RequestBufferDebugInfoLocked() 318{ 319 SURFACE_TRACE_NAME_FMT("lockLastFlushedBuffer seq: %u", acquireLastFlushedBufSequence_); 320 std::map<BufferState, int32_t> bufferState; 321 for (auto &[id, ele] : bufferQueueCache_) { 322 SURFACE_TRACE_NAME_FMT("request buffer id: %u state: %u", id, ele.state); 323 BLOGD("request no buffer, buffer id:%{public}d state:%{public}d, uniqueId: %{public}" PRIu64 ".", 324 id, ele.state, uniqueId_); 325 bufferState[ele.state] += 1; 326 } 327 std::string str = std::to_string(uniqueId_) + 328 ", Released: " + std::to_string(bufferState[BUFFER_STATE_RELEASED]) + 329 " Requested: " + std::to_string(bufferState[BUFFER_STATE_REQUESTED]) + 330 " Flushed: " + std::to_string(bufferState[BUFFER_STATE_FLUSHED]) + 331 " Acquired: " + std::to_string(bufferState[BUFFER_STATE_ACQUIRED]); 332 if (str.compare(requestBufferStateStr_) != 0) { 333 requestBufferStateStr_ = str; 334 BLOGE("all buffer are using, uniqueId: %{public}s", str.c_str()); 335 } 336} 337 338GSError BufferQueue::RequestBuffer(const BufferRequestConfig &config, sptr<BufferExtraData> &bedata, 339 struct IBufferProducer::RequestBufferReturnValue &retval) 340{ 341 if (wpCSurfaceDelegator_ != nullptr) { 342 return DelegatorDequeueBuffer(wpCSurfaceDelegator_, config, bedata, retval); 343 } 344 345 GSError ret = RequestBufferCheckStatus(); 346 if (ret != GSERROR_OK) { 347 return ret; 348 } 349 350 // check param 351 ret = CheckRequestConfig(config); 352 if (ret != GSERROR_OK) { 353 BLOGE("CheckRequestConfig ret: %{public}d, uniqueId: %{public}" PRIu64 ".", ret, uniqueId_); 354 return SURFACE_ERROR_UNKOWN; 355 } 356 357 std::unique_lock<std::mutex> lock(mutex_); 358 SURFACE_TRACE_NAME_FMT("RequestBuffer name: %s queueId: %" PRIu64 " queueSize: %u", 359 name_.c_str(), uniqueId_, bufferQueueSize_); 360 // dequeue from free list 361 sptr<SurfaceBuffer>& buffer = retval.buffer; 362 ret = PopFromFreeListLocked(buffer, config); 363 if (ret == GSERROR_OK) { 364 return ReuseBuffer(config, bedata, retval); 365 } 366 367 // check queue size 368 if (GetUsedSize() >= bufferQueueSize_) { 369 waitReqCon_.wait_for(lock, std::chrono::milliseconds(config.timeout), 370 [this]() { return WaitForCondition(); }); 371 if (!GetStatusLocked() && !isBatch_) { 372 SURFACE_TRACE_NAME_FMT("Status wrong, status: %d", GetStatusLocked()); 373 BLOGN_FAILURE_RET(GSERROR_NO_CONSUMER); 374 } 375 // try dequeue from free list again 376 ret = PopFromFreeListLocked(buffer, config); 377 if (ret == GSERROR_OK) { 378 return ReuseBuffer(config, bedata, retval); 379 } else if (GetUsedSize() >= bufferQueueSize_) { 380 RequestBufferDebugInfoLocked(); 381 return GSERROR_NO_BUFFER; 382 } 383 } 384 385 ret = AllocBuffer(buffer, config); 386 if (ret == GSERROR_OK) { 387 SetSurfaceBufferHebcMetaLocked(buffer); 388 SetSurfaceBufferGlobalAlphaUnlocked(buffer); 389 SetReturnValue(buffer, bedata, retval); 390 BLOGD("Success alloc Buffer[%{public}d %{public}d] seq: %{public}d, uniqueId: %{public}" PRIu64 ".", 391 config.width, config.height, retval.sequence, uniqueId_); 392 } else { 393 BLOGE("Fail to alloc or map Buffer[%{public}d %{public}d] ret: %{public}d, uniqueId: %{public}" PRIu64, 394 config.width, config.height, ret, uniqueId_); 395 } 396 397 return ret; 398} 399 400GSError BufferQueue::SetProducerCacheCleanFlag(bool flag) 401{ 402 std::unique_lock<std::mutex> lock(mutex_); 403 return SetProducerCacheCleanFlagLocked(flag); 404} 405 406GSError BufferQueue::SetProducerCacheCleanFlagLocked(bool flag) 407{ 408 producerCacheClean_ = flag; 409 producerCacheList_.clear(); 410 return GSERROR_OK; 411} 412 413bool BufferQueue::CheckProducerCacheListLocked() 414{ 415 for (auto &[id, _] : bufferQueueCache_) { 416 if (std::find(producerCacheList_.begin(), producerCacheList_.end(), id) == producerCacheList_.end()) { 417 return false; 418 } 419 } 420 return true; 421} 422 423GSError BufferQueue::ReallocBufferLocked(const BufferRequestConfig &config, 424 struct IBufferProducer::RequestBufferReturnValue &retval) 425{ 426 if (isShared_) { 427 BLOGE("shared mode, uniqueId: %{public}" PRIu64, uniqueId_); 428 return SURFACE_ERROR_UNKOWN; 429 } 430 DeleteBufferInCache(retval.sequence); 431 432 sptr<SurfaceBuffer> buffer = nullptr; 433 auto sret = AllocBuffer(buffer, config); 434 if (sret != GSERROR_OK) { 435 BLOGE("AllocBuffer failed: %{public}d, uniqueId: %{public}" PRIu64 ".", sret, uniqueId_); 436 return sret; 437 } 438 439 retval.buffer = buffer; 440 retval.sequence = buffer->GetSeqNum(); 441 bufferQueueCache_[retval.sequence].config = config; 442 return GSERROR_OK; 443} 444 445GSError BufferQueue::ReuseBuffer(const BufferRequestConfig &config, sptr<BufferExtraData> &bedata, 446 struct IBufferProducer::RequestBufferReturnValue &retval) 447{ 448 if (retval.buffer == nullptr) { 449 BLOGE("input buffer is null, uniqueId: %{public}" PRIu64 ".", uniqueId_); 450 return SURFACE_ERROR_UNKOWN; 451 } 452 retval.sequence = retval.buffer->GetSeqNum(); 453 if (bufferQueueCache_.find(retval.sequence) == bufferQueueCache_.end()) { 454 BLOGE("cache not find the buffer(%{public}u), uniqueId: %{public}" PRIu64 ".", retval.sequence, uniqueId_); 455 return SURFACE_ERROR_UNKOWN; 456 } 457 auto &cacheConfig = bufferQueueCache_[retval.sequence].config; 458 SURFACE_TRACE_NAME_FMT("ReuseBuffer config width: %d height: %d usage: %llu format: %d id: %u", 459 cacheConfig.width, cacheConfig.height, cacheConfig.usage, cacheConfig.format, retval.sequence); 460 461 bool needRealloc = (config != bufferQueueCache_[retval.sequence].config); 462 // config, realloc 463 if (needRealloc) { 464 auto sret = ReallocBufferLocked(config, retval); 465 if (sret != GSERROR_OK) { 466 return sret; 467 } 468 } 469 470 bufferQueueCache_[retval.sequence].state = BUFFER_STATE_REQUESTED; 471 retval.fence = bufferQueueCache_[retval.sequence].fence; 472 bedata = retval.buffer->GetExtraData(); 473 SetSurfaceBufferHebcMetaLocked(retval.buffer); 474 SetSurfaceBufferGlobalAlphaUnlocked(retval.buffer); 475 476 auto &dbs = retval.deletingBuffers; 477 dbs.reserve(dbs.size() + deletingList_.size()); 478 dbs.insert(dbs.end(), deletingList_.begin(), deletingList_.end()); 479 deletingList_.clear(); 480 481 if (needRealloc || isShared_ || producerCacheClean_ || retval.buffer->GetConsumerAttachBufferFlag()) { 482 BLOGD("requestBuffer Succ realloc Buffer[%{public}d %{public}d] with new config "\ 483 "seq: %{public}u attachFlag: %{public}d, uniqueId: %{public}" PRIu64 ".", 484 config.width, config.height, retval.sequence, retval.buffer->GetConsumerAttachBufferFlag(), uniqueId_); 485 if (producerCacheClean_) { 486 producerCacheList_.push_back(retval.sequence); 487 if (CheckProducerCacheListLocked()) { 488 SetProducerCacheCleanFlagLocked(false); 489 } 490 } 491 retval.buffer->SetConsumerAttachBufferFlag(false); 492 } else { 493 BLOGD("RequestBuffer Succ Buffer[%{public}d %{public}d] in seq id: %{public}u "\ 494 "releaseFence: %{public}d, uniqueId: %{public}" PRIu64 ".", 495 config.width, config.height, retval.sequence, retval.fence->Get(), uniqueId_); 496 retval.buffer = nullptr; 497 } 498 499 SURFACE_TRACE_NAME_FMT("%s:%u", name_.c_str(), retval.sequence); 500 if (IsTagEnabled(HITRACE_TAG_GRAPHIC_AGP) && isLocalRender_) { 501 static SyncFenceTracker releaseFenceThread("Release Fence"); 502 releaseFenceThread.TrackFence(retval.fence); 503 } 504 return GSERROR_OK; 505} 506 507GSError BufferQueue::CancelBuffer(uint32_t sequence, sptr<BufferExtraData> bedata) 508{ 509 SURFACE_TRACE_NAME_FMT("CancelBuffer name: %s queueId: %" PRIu64 " sequence: %u", 510 name_.c_str(), uniqueId_, sequence); 511 if (isShared_) { 512 BLOGN_FAILURE_RET(GSERROR_INVALID_OPERATING); 513 } 514 std::lock_guard<std::mutex> lockGuard(mutex_); 515 516 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 517 return SURFACE_ERROR_BUFFER_NOT_INCACHE; 518 } 519 520 if (bufferQueueCache_[sequence].state != BUFFER_STATE_REQUESTED && 521 bufferQueueCache_[sequence].state != BUFFER_STATE_ATTACHED) { 522 return SURFACE_ERROR_BUFFER_STATE_INVALID; 523 } 524 bufferQueueCache_[sequence].state = BUFFER_STATE_RELEASED; 525 freeList_.push_back(sequence); 526 if (bufferQueueCache_[sequence].buffer == nullptr) { 527 BLOGE("cache buffer is nullptr, sequence:%{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 528 return SURFACE_ERROR_UNKOWN; 529 } 530 bufferQueueCache_[sequence].buffer->SetExtraData(bedata); 531 532 waitReqCon_.notify_all(); 533 waitAttachCon_.notify_all(); 534 BLOGD("Success Buffer id: %{public}d, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 535 536 return GSERROR_OK; 537} 538 539GSError BufferQueue::CheckBufferQueueCache(uint32_t sequence) 540{ 541 std::lock_guard<std::mutex> lockGuard(mutex_); 542 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 543 BLOGE("no find seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 544 return SURFACE_ERROR_BUFFER_NOT_INCACHE; 545 } 546 547 if (isShared_ == false) { 548 auto &state = bufferQueueCache_[sequence].state; 549 if (state != BUFFER_STATE_REQUESTED && state != BUFFER_STATE_ATTACHED) { 550 BLOGE("seq: %{public}u, invalid state %{public}d, uniqueId: %{public}" PRIu64 ".", 551 sequence, state, uniqueId_); 552 return SURFACE_ERROR_BUFFER_STATE_INVALID; 553 } 554 } 555 return GSERROR_OK; 556} 557 558GSError BufferQueue::DelegatorQueueBuffer(uint32_t sequence, sptr<SyncFence> fence) 559{ 560 auto consumerDelegator = wpCSurfaceDelegator_.promote(); 561 if (consumerDelegator == nullptr) { 562 BLOGE("Consumer surface delegator has been expired"); 563 return GSERROR_INVALID_ARGUMENTS; 564 } 565 sptr<SurfaceBuffer> buffer = nullptr; 566 { 567 std::lock_guard<std::mutex> lockGuard(mutex_); 568 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 569 return GSERROR_NO_ENTRY; 570 } 571 bufferQueueCache_[sequence].state = BUFFER_STATE_ACQUIRED; 572 buffer = bufferQueueCache_[sequence].buffer; 573 } 574 GSError ret = consumerDelegator->QueueBuffer(buffer, fence->Get()); 575 if (ret != GSERROR_OK) { 576 BLOGE("Consumer surface delegator failed to queuebuffer"); 577 } 578 ret = ReleaseBuffer(buffer, SyncFence::InvalidFence()); 579 if (ret != GSERROR_OK) { 580 BLOGE("Consumer surface delegator failed to releasebuffer"); 581 } 582 return ret; 583} 584 585void BufferQueue::CallConsumerListener() 586{ 587 SURFACE_TRACE_NAME_FMT("CallConsumerListener"); 588 sptr<IBufferConsumerListener> listener; 589 IBufferConsumerListenerClazz *listenerClazz; 590 { 591 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 592 listener = listener_; 593 listenerClazz = listenerClazz_; 594 } 595 if (listener != nullptr) { 596 listener->OnBufferAvailable(); 597 } else if (listenerClazz != nullptr) { 598 listenerClazz->OnBufferAvailable(); 599 } 600} 601 602GSError BufferQueue::FlushBuffer(uint32_t sequence, sptr<BufferExtraData> bedata, 603 sptr<SyncFence> fence, const BufferFlushConfigWithDamages &config) 604{ 605 SURFACE_TRACE_NAME_FMT("FlushBuffer name: %s queueId: %" PRIu64 " sequence: %u", 606 name_.c_str(), uniqueId_, sequence); 607 { 608 std::lock_guard<std::mutex> lockGuard(mutex_); 609 if (!GetStatusLocked()) { 610 SURFACE_TRACE_NAME_FMT("status: %d", GetStatusLocked()); 611 BLOGN_FAILURE_RET(GSERROR_NO_CONSUMER); 612 } 613 } 614 // check param 615 auto sret = CheckFlushConfig(config); 616 if (sret != GSERROR_OK) { 617 BLOGE("CheckFlushConfig ret: %{public}d, uniqueId: %{public}" PRIu64 ".", sret, uniqueId_); 618 return sret; 619 } 620 621 sret = CheckBufferQueueCache(sequence); 622 if (sret != GSERROR_OK) { 623 return sret; 624 } 625 626 { 627 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 628 if (listener_ == nullptr && listenerClazz_ == nullptr) { 629 SURFACE_TRACE_NAME("listener is nullptr"); 630 BLOGE("listener is nullptr, uniqueId: %{public}" PRIu64 ".", uniqueId_); 631 CancelBuffer(sequence, bedata); 632 return SURFACE_ERROR_CONSUMER_UNREGISTER_LISTENER; 633 } 634 } 635 636 sret = DoFlushBuffer(sequence, bedata, fence, config); 637 if (sret != GSERROR_OK) { 638 return sret; 639 } 640 CallConsumerListener(); 641 BLOGD("Success Buffer seq id: %{public}d AcquireFence:%{public}d, uniqueId: %{public}" PRIu64 ".", 642 sequence, fence->Get(), uniqueId_); 643 644 if (wpCSurfaceDelegator_ != nullptr) { 645 sret = DelegatorQueueBuffer(sequence, fence); 646 } 647 return sret; 648} 649 650GSError BufferQueue::GetLastFlushedBuffer(sptr<SurfaceBuffer>& buffer, 651 sptr<SyncFence>& fence, float matrix[16], uint32_t matrixSize, bool isUseNewMatrix, bool needRecordSequence) 652{ 653 std::lock_guard<std::mutex> lockGuard(mutex_); 654 if (needRecordSequence && acquireLastFlushedBufSequence_ != INVALID_SEQUENCE) { 655 BLOGE("last flushed buffer(%{public}d) is using, uniqueId: %{public}" PRIu64 ".", 656 acquireLastFlushedBufSequence_, uniqueId_); 657 return SURFACE_ERROR_BUFFER_STATE_INVALID; 658 } 659 if (bufferQueueCache_.find(lastFlusedSequence_) == bufferQueueCache_.end()) { 660 BLOGE("cache ont find the buffer(%{public}u), uniqueId: %{public}" PRIu64 ".", lastFlusedSequence_, uniqueId_); 661 return SURFACE_ERROR_UNKOWN; 662 } 663 auto &state = bufferQueueCache_[lastFlusedSequence_].state; 664 if (state == BUFFER_STATE_REQUESTED) { 665 BLOGE("seq: %{public}u, invalid state %{public}d, uniqueId: %{public}" PRIu64 ".", 666 lastFlusedSequence_, state, uniqueId_); 667 return SURFACE_ERROR_BUFFER_STATE_INVALID; 668 } 669 buffer = bufferQueueCache_[lastFlusedSequence_].buffer; 670 auto usage = buffer->GetUsage(); 671 if (usage & BUFFER_USAGE_PROTECTED) { 672 BLOGE("lastFlusedSeq: %{public}u, usage: %{public}" PRIu64 ", uniqueId: %{public}" PRIu64 ".", 673 lastFlusedSequence_, usage, uniqueId_); 674 return SURFACE_ERROR_NOT_SUPPORT; 675 } 676 677 fence = lastFlusedFence_; 678 Rect damage = {}; 679 damage.w = buffer->GetWidth(); 680 damage.h = buffer->GetHeight(); 681 682 auto utils = SurfaceUtils::GetInstance(); 683 if (isUseNewMatrix) { 684 utils->ComputeTransformMatrixV2(matrix, matrixSize, buffer, lastFlushedTransform_, damage); 685 } else { 686 utils->ComputeTransformMatrix(matrix, matrixSize, buffer, lastFlushedTransform_, damage); 687 } 688 689 if (needRecordSequence) { 690 acquireLastFlushedBufSequence_ = lastFlusedSequence_; 691 SURFACE_TRACE_NAME_FMT("GetLastFlushedBuffer(needRecordSequence) name: %s queueId: %" PRIu64 " seq: %u", 692 name_.c_str(), uniqueId_, acquireLastFlushedBufSequence_); 693 } 694 return GSERROR_OK; 695} 696 697GSError BufferQueue::AcquireLastFlushedBuffer(sptr<SurfaceBuffer> &buffer, sptr<SyncFence> &fence, 698 float matrix[16], uint32_t matrixSize, bool isUseNewMatrix) 699{ 700 return GetLastFlushedBuffer(buffer, fence, matrix, matrixSize, isUseNewMatrix, true); 701} 702 703GSError BufferQueue::ReleaseLastFlushedBuffer(uint32_t sequence) 704{ 705 SURFACE_TRACE_NAME_FMT("ReleaseLastFlushedBuffer name: %s queueId: %" PRIu64 " seq: %u", 706 name_.c_str(), uniqueId_, sequence); 707 std::lock_guard<std::mutex> lockGuard(mutex_); 708 if (acquireLastFlushedBufSequence_ == INVALID_SEQUENCE || acquireLastFlushedBufSequence_ != sequence) { 709 BLOGE("ReleaseLastFlushedBuffer lastFlushBuffer:%{public}d sequence:%{public}d, uniqueId: %{public}" PRIu64, 710 acquireLastFlushedBufSequence_, sequence, uniqueId_); 711 return SURFACE_ERROR_BUFFER_STATE_INVALID; 712 } 713 acquireLastFlushedBufSequence_ = INVALID_SEQUENCE; 714 waitReqCon_.notify_all(); 715 return GSERROR_OK; 716} 717 718GSError BufferQueue::DoFlushBuffer(uint32_t sequence, sptr<BufferExtraData> bedata, 719 sptr<SyncFence> fence, const BufferFlushConfigWithDamages &config) 720{ 721 SURFACE_TRACE_NAME_FMT("DoFlushBuffer name: %s queueId: %" PRIu64 " seq: %u", 722 name_.c_str(), uniqueId_, sequence); 723 std::lock_guard<std::mutex> lockGuard(mutex_); 724 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 725 BLOGE("bufferQueueCache not find sequence:%{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 726 return SURFACE_ERROR_BUFFER_NOT_INCACHE; 727 } 728 if (bufferQueueCache_[sequence].isDeleting) { 729 DeleteBufferInCache(sequence); 730 BLOGD("DoFlushBuffer delete seq: %{public}d, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 731 CountTrace(HITRACE_TAG_GRAPHIC_AGP, name_, static_cast<int32_t>(dirtyList_.size())); 732 return GSERROR_OK; 733 } 734 735 bufferQueueCache_[sequence].state = BUFFER_STATE_FLUSHED; 736 dirtyList_.push_back(sequence); 737 bufferQueueCache_[sequence].buffer->SetExtraData(bedata); 738 bufferQueueCache_[sequence].fence = fence; 739 bufferQueueCache_[sequence].damages = config.damages; 740 lastFlusedSequence_ = sequence; 741 lastFlusedFence_ = fence; 742 lastFlushedTransform_ = transform_; 743 bufferQueueCache_[sequence].buffer->SetSurfaceBufferTransform(transform_); 744 745 uint64_t usage = static_cast<uint32_t>(bufferQueueCache_[sequence].config.usage); 746 if (usage & BUFFER_USAGE_CPU_WRITE) { 747 // api flush 748 auto sret = bufferQueueCache_[sequence].buffer->FlushCache(); 749 if (sret != GSERROR_OK) { 750 BLOGE("FlushCache ret: %{public}d, seq: %{public}u, uniqueId: %{public}" PRIu64 ".", 751 sret, sequence, uniqueId_); 752 return sret; 753 } 754 } 755 SetDesiredPresentTimestampAndUiTimestamp(sequence, config.desiredPresentTimestamp, config.timestamp); 756 bool traceTag = IsTagEnabled(HITRACE_TAG_GRAPHIC_AGP); 757 if (isLocalRender_) { 758 AcquireFenceTracker::TrackFence(fence, traceTag); 759 } 760 // if you need dump SurfaceBuffer to file, you should execute hdc shell param set persist.dumpbuffer.enabled 1 761 // and reboot your device 762 static bool dumpBufferEnabled = system::GetParameter("persist.dumpbuffer.enabled", "0") != "0"; 763 if (dumpBufferEnabled) { 764 // Wait for the status of the fence to change to SIGNALED. 765 fence->Wait(-1); 766 DumpToFileAsync(GetRealPid(), name_, bufferQueueCache_[sequence].buffer); 767 } 768 769 CountTrace(HITRACE_TAG_GRAPHIC_AGP, name_, static_cast<int32_t>(dirtyList_.size())); 770 return GSERROR_OK; 771} 772 773void BufferQueue::SetDesiredPresentTimestampAndUiTimestamp(uint32_t sequence, int64_t desiredPresentTimestamp, 774 uint64_t uiTimestamp) 775{ 776 if (desiredPresentTimestamp <= 0) { 777 if (desiredPresentTimestamp == 0 && uiTimestamp != 0 778 && uiTimestamp <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { 779 bufferQueueCache_[sequence].desiredPresentTimestamp = static_cast<int64_t>(uiTimestamp); 780 } else { 781 bufferQueueCache_[sequence].desiredPresentTimestamp = std::chrono::duration_cast<std::chrono::nanoseconds>( 782 std::chrono::steady_clock::now().time_since_epoch()).count(); 783 bufferQueueCache_[sequence].isAutoTimestamp = true; 784 } 785 } else { 786 bufferQueueCache_[sequence].desiredPresentTimestamp = desiredPresentTimestamp; 787 } 788 bufferQueueCache_[sequence].timestamp = static_cast<int64_t>(uiTimestamp); 789} 790 791void BufferQueue::LogAndTraceAllBufferInBufferQueueCache() 792{ 793 std::map<BufferState, int32_t> bufferState; 794 for (auto &[id, ele] : bufferQueueCache_) { 795 SURFACE_TRACE_NAME_FMT("acquire buffer id: %d state: %d desiredPresentTimestamp: %" PRId64 796 " isAotuTimestamp: %d", id, ele.state, ele.desiredPresentTimestamp, ele.isAutoTimestamp); 797 BLOGD("acquire no buffer, buffer id:%{public}d state:%{public}d, uniqueId: %{public}" PRIu64 798 "desiredPresentTimestamp: %{public}" PRId64 " isAotuTimestamp: %{public}d.", 799 id, ele.state, uniqueId_, ele.desiredPresentTimestamp, ele.isAutoTimestamp); 800 bufferState[ele.state] += 1; 801 } 802 std::string str = std::to_string(uniqueId_) + 803 ", Released: " + std::to_string(bufferState[BUFFER_STATE_RELEASED]) + 804 " Requested: " + std::to_string(bufferState[BUFFER_STATE_REQUESTED]) + 805 " Flushed: " + std::to_string(bufferState[BUFFER_STATE_FLUSHED]) + 806 " Acquired: " + std::to_string(bufferState[BUFFER_STATE_ACQUIRED]); 807 if (str.compare(acquireBufferStateStr_) != 0) { 808 acquireBufferStateStr_ = str; 809 BLOGE("there is no dirty buffer or no dirty buffer ready, uniqueId: %{public}s", str.c_str()); 810 } 811} 812 813GSError BufferQueue::AcquireBuffer(sptr<SurfaceBuffer> &buffer, 814 sptr<SyncFence> &fence, int64_t ×tamp, std::vector<Rect> &damages) 815{ 816 SURFACE_TRACE_NAME_FMT("AcquireBuffer name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 817 // dequeue from dirty list 818 std::lock_guard<std::mutex> lockGuard(mutex_); 819 GSError ret = PopFromDirtyListLocked(buffer); 820 if (ret == GSERROR_OK) { 821 uint32_t sequence = buffer->GetSeqNum(); 822 bufferQueueCache_[sequence].state = BUFFER_STATE_ACQUIRED; 823 824 fence = bufferQueueCache_[sequence].fence; 825 timestamp = bufferQueueCache_[sequence].timestamp; 826 damages = bufferQueueCache_[sequence].damages; 827 SURFACE_TRACE_NAME_FMT("acquire buffer sequence: %u", sequence); 828 BLOGD("Success Buffer seq id: %{public}u AcquireFence:%{public}d, uniqueId: %{public}" PRIu64 ".", 829 sequence, fence->Get(), uniqueId_); 830 } else if (ret == GSERROR_NO_BUFFER) { 831 LogAndTraceAllBufferInBufferQueueCache(); 832 } 833 834 CountTrace(HITRACE_TAG_GRAPHIC_AGP, name_, static_cast<int32_t>(dirtyList_.size())); 835 return ret; 836} 837 838GSError BufferQueue::AcquireBuffer(IConsumerSurface::AcquireBufferReturnValue &returnValue, 839 int64_t expectPresentTimestamp, bool isUsingAutoTimestamp) 840{ 841 SURFACE_TRACE_NAME_FMT("AcquireBuffer with PresentTimestamp name: %s queueId: %" PRIu64 " queueSize: %u" 842 "expectPresentTimestamp: %" PRId64, name_.c_str(), uniqueId_, bufferQueueSize_, expectPresentTimestamp); 843 if (isShared_ || expectPresentTimestamp <= 0) { 844 return AcquireBuffer(returnValue.buffer, returnValue.fence, returnValue.timestamp, returnValue.damages); 845 } 846 std::vector<BufferElement*> dropBufferElements; 847 // traverse dirtyList_ 848 { 849 std::lock_guard<std::mutex> lockGuard(mutex_); 850 std::list<uint32_t>::iterator frontSequence = dirtyList_.begin(); 851 if (frontSequence == dirtyList_.end()) { 852 LogAndTraceAllBufferInBufferQueueCache(); 853 return GSERROR_NO_BUFFER; 854 } 855 BufferElement& frontBufferElement = bufferQueueCache_[*frontSequence]; 856 int64_t frontDesiredPresentTimestamp = frontBufferElement.desiredPresentTimestamp; 857 bool frontIsAutoTimestamp = frontBufferElement.isAutoTimestamp; 858 if (!frontIsAutoTimestamp && frontDesiredPresentTimestamp > expectPresentTimestamp 859 && frontDesiredPresentTimestamp - ONE_SECOND_TIMESTAMP <= expectPresentTimestamp) { 860 LogAndTraceAllBufferInBufferQueueCache(); 861 return GSERROR_NO_BUFFER_READY; 862 } 863 while (!(frontIsAutoTimestamp && !isUsingAutoTimestamp) 864 && frontDesiredPresentTimestamp <= expectPresentTimestamp) { 865 BufferElement& frontBufferElement = bufferQueueCache_[*frontSequence]; 866 if (++frontSequence == dirtyList_.end()) { 867 BLOGD("Buffer seq(%{public}d) is the last buffer, do acquire.", dirtyList_.front()); 868 break; 869 } 870 BufferElement& secondBufferElement = bufferQueueCache_[*frontSequence]; 871 872 if ((secondBufferElement.isAutoTimestamp && !isUsingAutoTimestamp) 873 || secondBufferElement.desiredPresentTimestamp > expectPresentTimestamp) { 874 BLOGD("Next dirty buffer desiredPresentTimestamp: %{public}" PRId64 " not match expectPresentTimestamp" 875 ": %{public}" PRId64 ".", secondBufferElement.desiredPresentTimestamp, expectPresentTimestamp); 876 break; 877 } 878 //second buffer match, should drop front buffer 879 SURFACE_TRACE_NAME_FMT("DropBuffer name: %s queueId: %" PRIu64 " ,buffer seq: %u , buffer " 880 "desiredPresentTimestamp: %" PRId64 " acquire expectPresentTimestamp: %" PRId64, name_.c_str(), 881 uniqueId_, frontBufferElement.buffer->GetSeqNum(), frontBufferElement.desiredPresentTimestamp, 882 expectPresentTimestamp); 883 dirtyList_.pop_front(); 884 frontBufferElement.state = BUFFER_STATE_ACQUIRED; 885 dropBufferElements.push_back(&frontBufferElement); 886 frontDesiredPresentTimestamp = secondBufferElement.desiredPresentTimestamp; 887 frontIsAutoTimestamp = secondBufferElement.isAutoTimestamp; 888 } 889 //Present Later When first buffer not ready 890 if (!frontIsAutoTimestamp && !IsPresentTimestampReady(frontDesiredPresentTimestamp, expectPresentTimestamp)) { 891 SURFACE_TRACE_NAME_FMT("Acquire no buffer ready"); 892 LogAndTraceAllBufferInBufferQueueCache(); 893 return GSERROR_NO_BUFFER_READY; 894 } 895 } 896 //drop buffers 897 for (const auto& dropBufferElement : dropBufferElements) { 898 if (dropBufferElement == nullptr) { 899 continue; 900 } 901 auto ret = ReleaseBuffer(dropBufferElement->buffer, dropBufferElement->fence); 902 if (ret != GSERROR_OK) { 903 BLOGE("DropBuffer failed, ret: %{public}d, sequence: %{public}u, uniqueId: %{public}" PRIu64 ".", 904 ret, dropBufferElement->buffer->GetSeqNum(), uniqueId_); 905 } 906 } 907 //Acquire 908 return AcquireBuffer(returnValue.buffer, returnValue.fence, returnValue.timestamp, returnValue.damages); 909} 910 911bool BufferQueue::IsPresentTimestampReady(int64_t desiredPresentTimestamp, int64_t expectPresentTimestamp) 912{ 913 if (desiredPresentTimestamp <= expectPresentTimestamp) { 914 return true; 915 } 916 if (desiredPresentTimestamp - ONE_SECOND_TIMESTAMP > expectPresentTimestamp) { 917 return true; 918 } 919 return false; 920} 921 922void BufferQueue::ListenerBufferReleasedCb(sptr<SurfaceBuffer> &buffer, const sptr<SyncFence> &fence) 923{ 924 { 925 std::lock_guard<std::mutex> lockGuard(onBufferReleaseMutex_); 926 if (onBufferRelease_ != nullptr) { 927 SURFACE_TRACE_NAME_FMT("OnBufferRelease_ sequence: %u", buffer->GetSeqNum()); 928 sptr<SurfaceBuffer> buf = buffer; 929 (void)onBufferRelease_(buf); 930 } 931 } 932 933 sptr<IProducerListener> listener; 934 { 935 std::lock_guard<std::mutex> lockGuard(producerListenerMutex_); 936 listener = producerListener_; 937 } 938 939 if (listener != nullptr) { 940 SURFACE_TRACE_NAME_FMT("onBufferReleasedForProducer sequence: %u", buffer->GetSeqNum()); 941 if (listener->OnBufferReleased() != GSERROR_OK) { 942 BLOGE("seq: %{public}u, OnBufferReleased faile, uniqueId: %{public}" PRIu64 ".", 943 buffer->GetSeqNum(), uniqueId_); 944 } 945 if (listener->OnBufferReleasedWithFence(buffer, fence) != GSERROR_OK) { 946 BLOGE("seq: %{public}u, OnBufferReleasedWithFence failed, uniqueId: %{public}" PRIu64 ".", 947 buffer->GetSeqNum(), uniqueId_); 948 } 949 } 950 std::lock_guard<std::mutex> lockGuard(mutex_); 951 OnBufferDeleteCbForHardwareThreadLocked(buffer); 952} 953 954void BufferQueue::OnBufferDeleteCbForHardwareThreadLocked(const sptr<SurfaceBuffer> &buffer) const 955{ 956 if (onBufferDeleteForRSHardwareThread_ != nullptr) { 957 onBufferDeleteForRSHardwareThread_(buffer->GetSeqNum()); 958 } 959} 960 961GSError BufferQueue::ReleaseBuffer(sptr<SurfaceBuffer> &buffer, const sptr<SyncFence>& fence) 962{ 963 if (buffer == nullptr) { 964 return GSERROR_INVALID_ARGUMENTS; 965 } 966 967 uint32_t sequence = buffer->GetSeqNum(); 968 SURFACE_TRACE_NAME_FMT("ReleaseBuffer name: %s queueId: %" PRIu64 " seq: %u", name_.c_str(), uniqueId_, sequence); 969 { 970 std::lock_guard<std::mutex> lockGuard(mutex_); 971 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 972 SURFACE_TRACE_NAME_FMT("buffer not found in cache"); 973 BLOGE("cache not find the buffer(%{public}u), uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 974 OnBufferDeleteCbForHardwareThreadLocked(buffer); 975 return SURFACE_ERROR_BUFFER_NOT_INCACHE; 976 } 977 978 if (isShared_ == false) { 979 const auto &state = bufferQueueCache_[sequence].state; 980 if (state != BUFFER_STATE_ACQUIRED && state != BUFFER_STATE_ATTACHED) { 981 SURFACE_TRACE_NAME_FMT("invalid state: %u", state); 982 BLOGD("invalid state: %{public}d, uniqueId: %{public}" PRIu64 ".", state, uniqueId_); 983 return SURFACE_ERROR_BUFFER_STATE_INVALID; 984 } 985 } 986 987 bufferQueueCache_[sequence].state = BUFFER_STATE_RELEASED; 988 bufferQueueCache_[sequence].fence = fence; 989 990 if (bufferQueueCache_[sequence].isDeleting) { 991 DeleteBufferInCache(sequence); 992 BLOGD("Succ delete Buffer seq id: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 993 } else { 994 freeList_.push_back(sequence); 995 BLOGD("Succ push Buffer seq id: %{public}u to free list, releaseFence: %{public}d," 996 "uniqueId: %{public}" PRIu64 ".", sequence, fence->Get(), uniqueId_); 997 } 998 waitReqCon_.notify_all(); 999 waitAttachCon_.notify_all(); 1000 } 1001 ListenerBufferReleasedCb(buffer, fence); 1002 1003 return GSERROR_OK; 1004} 1005 1006GSError BufferQueue::AllocBuffer(sptr<SurfaceBuffer> &buffer, 1007 const BufferRequestConfig &config) 1008{ 1009 sptr<SurfaceBuffer> bufferImpl = new SurfaceBufferImpl(); 1010 uint32_t sequence = bufferImpl->GetSeqNum(); 1011 SURFACE_TRACE_NAME_FMT("AllocBuffer config width: %d height: %d usage: %llu format: %d id: %u", 1012 config.width, config.height, config.usage, config.format, sequence); 1013 1014 BufferRequestConfig updateConfig = config; 1015 updateConfig.usage |= defaultUsage_; 1016 1017 GSError ret = bufferImpl->Alloc(updateConfig); 1018 if (ret != GSERROR_OK) { 1019 BLOGE("Alloc failed, sequence:%{public}u, ret:%{public}d, uniqueId: %{public}" PRIu64 ".", 1020 sequence, ret, uniqueId_); 1021 return SURFACE_ERROR_UNKOWN; 1022 } 1023 1024 BufferElement ele = { 1025 .buffer = bufferImpl, 1026 .state = BUFFER_STATE_REQUESTED, 1027 .isDeleting = false, 1028 .config = config, 1029 .fence = SyncFence::InvalidFence(), 1030 .scalingMode = scalingMode_, 1031 }; 1032 1033 if (config.usage & BUFFER_USAGE_PROTECTED) { 1034 BLOGD("usage is BUFFER_USAGE_PROTECTED, uniqueId: %{public}" PRIu64 ".", uniqueId_); 1035 bufferQueueCache_[sequence] = ele; 1036 buffer = bufferImpl; 1037 return SURFACE_ERROR_OK; 1038 } 1039 1040 ret = bufferImpl->Map(); 1041 if (ret == GSERROR_OK) { 1042 BLOGD("Map Success, seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 1043 bufferQueueCache_[sequence] = ele; 1044 buffer = bufferImpl; 1045 } else { 1046 BLOGE("Map failed, seq:%{public}u, ret:%{public}d, uniqueId: %{public}" PRIu64 ".", 1047 sequence, ret, uniqueId_); 1048 return SURFACE_ERROR_UNKOWN; 1049 } 1050 return SURFACE_ERROR_OK; 1051} 1052 1053void BufferQueue::DeleteBufferInCache(uint32_t sequence) 1054{ 1055 auto it = bufferQueueCache_.find(sequence); 1056 if (it != bufferQueueCache_.end()) { 1057 if (onBufferDeleteForRSMainThread_ != nullptr) { 1058 onBufferDeleteForRSMainThread_(sequence); 1059 } 1060 if (onBufferDeleteForRSHardwareThread_ != nullptr) { 1061 onBufferDeleteForRSHardwareThread_(sequence); 1062 } 1063 BLOGD("DeleteBufferInCache seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 1064 bufferQueueCache_.erase(it); 1065 deletingList_.push_back(sequence); 1066 } 1067} 1068 1069uint32_t BufferQueue::GetQueueSize() 1070{ 1071 std::unique_lock<std::mutex> lock(mutex_); 1072 return bufferQueueSize_; 1073} 1074 1075void BufferQueue::DeleteBuffersLocked(int32_t count) 1076{ 1077 SURFACE_TRACE_NAME_FMT("DeleteBuffersLocked count: %d", count); 1078 if (count <= 0) { 1079 return; 1080 } 1081 1082 while (!freeList_.empty()) { 1083 DeleteBufferInCache(freeList_.front()); 1084 freeList_.pop_front(); 1085 count--; 1086 if (count <= 0) { 1087 return; 1088 } 1089 } 1090 1091 while (!dirtyList_.empty()) { 1092 DeleteBufferInCache(dirtyList_.front()); 1093 dirtyList_.pop_front(); 1094 count--; 1095 if (count <= 0) { 1096 return; 1097 } 1098 } 1099 1100 for (auto&& ele : bufferQueueCache_) { 1101 ele.second.isDeleting = true; 1102 // we don't have to do anything 1103 count--; 1104 if (count <= 0) { 1105 break; 1106 } 1107 } 1108} 1109 1110GSError BufferQueue::AttachBufferUpdateStatus(std::unique_lock<std::mutex> &lock, uint32_t sequence, int32_t timeOut) 1111{ 1112 BufferState state = bufferQueueCache_[sequence].state; 1113 if (state == BUFFER_STATE_RELEASED) { 1114 bufferQueueCache_[sequence].state = BUFFER_STATE_ATTACHED; 1115 } else { 1116 waitAttachCon_.wait_for(lock, std::chrono::milliseconds(timeOut), 1117 [this, sequence]() { return (bufferQueueCache_[sequence].state == BUFFER_STATE_RELEASED); }); 1118 if (bufferQueueCache_[sequence].state == BUFFER_STATE_RELEASED) { 1119 bufferQueueCache_[sequence].state = BUFFER_STATE_ATTACHED; 1120 } else { 1121 BLOGN_FAILURE_RET(SURFACE_ERROR_BUFFER_STATE_INVALID); 1122 } 1123 } 1124 1125 for (auto iter = freeList_.begin(); iter != freeList_.end(); iter++) { 1126 if (sequence == *iter) { 1127 freeList_.erase(iter); 1128 break; 1129 } 1130 } 1131 return GSERROR_OK; 1132} 1133 1134void BufferQueue::AttachBufferUpdateBufferInfo(sptr<SurfaceBuffer>& buffer) 1135{ 1136 buffer->Map(); 1137 buffer->SetSurfaceBufferWidth(buffer->GetWidth()); 1138 buffer->SetSurfaceBufferHeight(buffer->GetHeight()); 1139} 1140 1141GSError BufferQueue::AttachBufferToQueue(sptr<SurfaceBuffer> buffer, InvokerType invokerType) 1142{ 1143 SURFACE_TRACE_NAME_FMT("AttachBufferToQueue name: %s queueId: %" PRIu64 " sequence: %u invokerType: %u", 1144 name_.c_str(), uniqueId_, buffer->GetSeqNum(), invokerType); 1145 { 1146 std::lock_guard<std::mutex> lockGuard(mutex_); 1147 uint32_t sequence = buffer->GetSeqNum(); 1148 if (GetUsedSize() >= bufferQueueSize_) { 1149 BLOGE("seq: %{public}u, buffer queue size:%{public}u, used size:%{public}u," 1150 "uniqueId: %{public}" PRIu64 ".", sequence, bufferQueueSize_, GetUsedSize(), uniqueId_); 1151 return SURFACE_ERROR_BUFFER_QUEUE_FULL; 1152 } 1153 if (bufferQueueCache_.find(sequence) != bufferQueueCache_.end()) { 1154 BLOGE("seq: %{public}u, buffer is already in cache, uniqueId: %{public}" PRIu64 ".", 1155 sequence, uniqueId_); 1156 return SURFACE_ERROR_BUFFER_IS_INCACHE; 1157 } 1158 BufferElement ele; 1159 ele = { 1160 .buffer = buffer, 1161 .isDeleting = false, 1162 .config = buffer->GetBufferRequestConfig(), 1163 .fence = SyncFence::InvalidFence(), 1164 .scalingMode = scalingMode_, 1165 }; 1166 if (invokerType == InvokerType::PRODUCER_INVOKER) { 1167 ele.state = BUFFER_STATE_REQUESTED; 1168 } else { 1169 ele.state = BUFFER_STATE_ACQUIRED; 1170 } 1171 AttachBufferUpdateBufferInfo(buffer); 1172 bufferQueueCache_[sequence] = ele; 1173 } 1174 return GSERROR_OK; 1175} 1176 1177GSError BufferQueue::DetachBufferFromQueue(sptr<SurfaceBuffer> buffer, InvokerType invokerType) 1178{ 1179 SURFACE_TRACE_NAME_FMT("DetachBufferFromQueue name: %s queueId: %" PRIu64 " sequence: %u invokerType%u", 1180 name_.c_str(), uniqueId_, buffer->GetSeqNum(), invokerType); 1181 { 1182 std::lock_guard<std::mutex> lockGuard(mutex_); 1183 uint32_t sequence = buffer->GetSeqNum(); 1184 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1185 BLOGE("seq: %{public}u, not find in cache, uniqueId: %{public}" PRIu64 ".", 1186 sequence, uniqueId_); 1187 return SURFACE_ERROR_BUFFER_NOT_INCACHE; 1188 } 1189 if (invokerType == InvokerType::PRODUCER_INVOKER) { 1190 if (bufferQueueCache_[sequence].state != BUFFER_STATE_REQUESTED) { 1191 BLOGE("seq: %{public}u, state: %{public}d, uniqueId: %{public}" PRIu64 ".", 1192 sequence, bufferQueueCache_[sequence].state, uniqueId_); 1193 return SURFACE_ERROR_BUFFER_STATE_INVALID; 1194 } 1195 } else { 1196 if (bufferQueueCache_[sequence].state != BUFFER_STATE_ACQUIRED) { 1197 BLOGE("seq: %{public}u, state: %{public}d, uniqueId: %{public}" PRIu64 ".", 1198 sequence, bufferQueueCache_[sequence].state, uniqueId_); 1199 return SURFACE_ERROR_BUFFER_STATE_INVALID; 1200 } 1201 } 1202 bufferQueueCache_.erase(sequence); 1203 } 1204 return GSERROR_OK; 1205} 1206 1207GSError BufferQueue::AttachBuffer(sptr<SurfaceBuffer> &buffer, int32_t timeOut) 1208{ 1209 SURFACE_TRACE_NAME_FMT("%s", __func__); 1210 { 1211 std::lock_guard<std::mutex> lockGuard(mutex_); 1212 if (!GetStatusLocked()) { 1213 BLOGN_FAILURE_RET(GSERROR_NO_CONSUMER); 1214 } 1215 } 1216 { 1217 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1218 if (listener_ == nullptr && listenerClazz_ == nullptr) { 1219 BLOGN_FAILURE_RET(SURFACE_ERROR_CONSUMER_UNREGISTER_LISTENER); 1220 } 1221 } 1222 1223 if (isShared_ || buffer == nullptr) { 1224 BLOGN_FAILURE_RET(GSERROR_INVALID_OPERATING); 1225 } 1226 1227 uint32_t sequence = buffer->GetSeqNum(); 1228 std::unique_lock<std::mutex> lock(mutex_); 1229 if (bufferQueueCache_.find(sequence) != bufferQueueCache_.end()) { 1230 return AttachBufferUpdateStatus(lock, sequence, timeOut); 1231 } 1232 1233 BufferElement ele = { 1234 .buffer = buffer, 1235 .state = BUFFER_STATE_ATTACHED, 1236 .config = { 1237 .width = buffer->GetWidth(), .height = buffer->GetHeight(), .strideAlignment = 0x8, 1238 .format = buffer->GetFormat(), .usage = buffer->GetUsage(), .timeout = timeOut, 1239 }, 1240 .damages = { { .w = buffer->GetWidth(), .h = buffer->GetHeight(), } }, 1241 }; 1242 AttachBufferUpdateBufferInfo(buffer); 1243 int32_t usedSize = static_cast<int32_t>(GetUsedSize()); 1244 int32_t queueSize = static_cast<int32_t>(bufferQueueSize_); 1245 if (usedSize >= queueSize) { 1246 int32_t freeSize = static_cast<int32_t>(dirtyList_.size() + freeList_.size()); 1247 if (freeSize >= usedSize - queueSize + 1) { 1248 DeleteBuffersLocked(usedSize - queueSize + 1); 1249 bufferQueueCache_[sequence] = ele; 1250 BLOGD("AttachBuffer release seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 1251 return GSERROR_OK; 1252 } else { 1253 BLOGN_FAILURE_RET(GSERROR_OUT_OF_RANGE); 1254 } 1255 } else { 1256 bufferQueueCache_[sequence] = ele; 1257 BLOGD("AttachBuffer no release seq: %{public}d, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 1258 return GSERROR_OK; 1259 } 1260} 1261 1262GSError BufferQueue::DetachBuffer(sptr<SurfaceBuffer> &buffer) 1263{ 1264 SURFACE_TRACE_NAME_FMT("%s", __func__); 1265 if (isShared_) { 1266 BLOGN_FAILURE_RET(GSERROR_INVALID_OPERATING); 1267 } 1268 1269 if (buffer == nullptr) { 1270 BLOGN_FAILURE_RET(GSERROR_INVALID_ARGUMENTS); 1271 } 1272 1273 std::lock_guard<std::mutex> lockGuard(mutex_); 1274 uint32_t sequence = buffer->GetSeqNum(); 1275 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1276 return GSERROR_NO_ENTRY; 1277 } 1278 1279 if (bufferQueueCache_[sequence].state == BUFFER_STATE_REQUESTED) { 1280 BLOGD("DetachBuffer requested seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 1281 } else if (bufferQueueCache_[sequence].state == BUFFER_STATE_ACQUIRED) { 1282 BLOGD("DetachBuffer acquired seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); 1283 } else { 1284 BLOGE("DetachBuffer invalid state: %{public}d, seq: %{public}u, uniqueId: %{public}" PRIu64 ".", 1285 bufferQueueCache_[sequence].state, sequence, uniqueId_); 1286 return GSERROR_NO_ENTRY; 1287 } 1288 if (onBufferDeleteForRSMainThread_ != nullptr) { 1289 onBufferDeleteForRSMainThread_(sequence); 1290 } 1291 if (onBufferDeleteForRSHardwareThread_ != nullptr) { 1292 onBufferDeleteForRSHardwareThread_(sequence); 1293 } 1294 bufferQueueCache_.erase(sequence); 1295 return GSERROR_OK; 1296} 1297 1298GSError BufferQueue::RegisterSurfaceDelegator(sptr<IRemoteObject> client, sptr<Surface> cSurface) 1299{ 1300 sptr<ConsumerSurfaceDelegator> surfaceDelegator = ConsumerSurfaceDelegator::Create(); 1301 if (surfaceDelegator == nullptr) { 1302 BLOGE("Failed to register consumer delegator because the surface delegator is nullptr"); 1303 return GSERROR_INVALID_ARGUMENTS; 1304 } 1305 if (!surfaceDelegator->SetClient(client)) { 1306 BLOGE("Failed to set client"); 1307 return GSERROR_INVALID_ARGUMENTS; 1308 } 1309 if (!surfaceDelegator->SetBufferQueue(this)) { 1310 BLOGE("Failed to set bufferqueue"); 1311 return GSERROR_INVALID_ARGUMENTS; 1312 } 1313 1314 surfaceDelegator->SetSurface(cSurface); 1315 wpCSurfaceDelegator_ = surfaceDelegator; 1316 return GSERROR_OK; 1317} 1318 1319GSError BufferQueue::SetQueueSize(uint32_t queueSize) 1320{ 1321 if (isShared_ == true && queueSize != 1) { 1322 BLOGW("shared queue size: %{public}u, uniqueId: %{public}" PRIu64 ".", queueSize, uniqueId_); 1323 return GSERROR_INVALID_ARGUMENTS; 1324 } 1325 1326 if (queueSize == 0) { 1327 BLOGW("queue size: %{public}u, uniqueId: %{public}" PRIu64 ".", queueSize, uniqueId_); 1328 return GSERROR_INVALID_ARGUMENTS; 1329 } 1330 1331 if (queueSize > SURFACE_MAX_QUEUE_SIZE) { 1332 BLOGW("invalid queueSize: %{public}u, uniqueId: %{public}" PRIu64 ".", 1333 queueSize, uniqueId_); 1334 return GSERROR_INVALID_ARGUMENTS; 1335 } 1336 1337 std::lock_guard<std::mutex> lockGuard(mutex_); 1338 if (bufferQueueSize_ > queueSize) { 1339 DeleteBuffersLocked(bufferQueueSize_ - queueSize); 1340 } 1341 // if increase the queue size, try to wakeup the blocked thread 1342 if (queueSize > bufferQueueSize_) { 1343 bufferQueueSize_ = queueSize; 1344 waitReqCon_.notify_all(); 1345 } else { 1346 bufferQueueSize_ = queueSize; 1347 } 1348 1349 BLOGD("queue size: %{public}d, uniqueId: %{public}" PRIu64 ".", bufferQueueSize_, uniqueId_); 1350 return GSERROR_OK; 1351} 1352 1353GSError BufferQueue::GetName(std::string &name) 1354{ 1355 name = name_; 1356 return GSERROR_OK; 1357} 1358 1359GSError BufferQueue::RegisterConsumerListener(sptr<IBufferConsumerListener> &listener) 1360{ 1361 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1362 listener_ = listener; 1363 return GSERROR_OK; 1364} 1365 1366GSError BufferQueue::RegisterConsumerListener(IBufferConsumerListenerClazz *listener) 1367{ 1368 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1369 listenerClazz_ = listener; 1370 return GSERROR_OK; 1371} 1372 1373GSError BufferQueue::UnregisterConsumerListener() 1374{ 1375 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1376 listener_ = nullptr; 1377 listenerClazz_ = nullptr; 1378 return GSERROR_OK; 1379} 1380 1381GSError BufferQueue::RegisterReleaseListener(OnReleaseFunc func) 1382{ 1383 std::lock_guard<std::mutex> lockGuard(onBufferReleaseMutex_); 1384 onBufferRelease_ = func; 1385 return GSERROR_OK; 1386} 1387 1388GSError BufferQueue::RegisterProducerReleaseListener(sptr<IProducerListener> listener) 1389{ 1390 std::lock_guard<std::mutex> lockGuard(producerListenerMutex_); 1391 producerListener_ = listener; 1392 return GSERROR_OK; 1393} 1394 1395GSError BufferQueue::UnRegisterProducerReleaseListener() 1396{ 1397 std::lock_guard<std::mutex> lockGuard(producerListenerMutex_); 1398 producerListener_ = nullptr; 1399 return GSERROR_OK; 1400} 1401 1402GSError BufferQueue::RegisterDeleteBufferListener(OnDeleteBufferFunc func, bool isForUniRedraw) 1403{ 1404 std::lock_guard<std::mutex> lockGuard(mutex_); 1405 if (isForUniRedraw) { 1406 if (onBufferDeleteForRSHardwareThread_ != nullptr) { 1407 return GSERROR_OK; 1408 } 1409 onBufferDeleteForRSHardwareThread_ = func; 1410 } else { 1411 if (onBufferDeleteForRSMainThread_ != nullptr) { 1412 return GSERROR_OK; 1413 } 1414 onBufferDeleteForRSMainThread_ = func; 1415 } 1416 return GSERROR_OK; 1417} 1418 1419GSError BufferQueue::SetDefaultWidthAndHeight(int32_t width, int32_t height) 1420{ 1421 if (width <= 0) { 1422 BLOGW("width is %{public}d, uniqueId: %{public}" PRIu64 ".", width, uniqueId_); 1423 return GSERROR_INVALID_ARGUMENTS; 1424 } 1425 1426 if (height <= 0) { 1427 BLOGW("height is %{public}d, uniqueId: %{public}" PRIu64 ".", height, uniqueId_); 1428 return GSERROR_INVALID_ARGUMENTS; 1429 } 1430 BLOGD("SetDefaultWidthAndHeight(width: %{public}d, height: %{public}d), uniqueId: %{public}" PRIu64 ".", 1431 width, height, uniqueId_); 1432 std::lock_guard<std::mutex> lockGuard(mutex_); 1433 defaultWidth_ = width; 1434 defaultHeight_ = height; 1435 return GSERROR_OK; 1436} 1437 1438int32_t BufferQueue::GetDefaultWidth() 1439{ 1440 std::lock_guard<std::mutex> lockGuard(mutex_); 1441 return defaultWidth_; 1442} 1443 1444int32_t BufferQueue::GetDefaultHeight() 1445{ 1446 std::lock_guard<std::mutex> lockGuard(mutex_); 1447 return defaultHeight_; 1448} 1449 1450GSError BufferQueue::SetDefaultUsage(uint64_t usage) 1451{ 1452 BLOGD("SetDefaultUsage(usage: %{public}" PRIu64 ") , uniqueId: %{public}" PRIu64 ".", usage, uniqueId_); 1453 std::lock_guard<std::mutex> lockGuard(mutex_); 1454 defaultUsage_ = usage; 1455 return GSERROR_OK; 1456} 1457 1458uint64_t BufferQueue::GetDefaultUsage() 1459{ 1460 std::lock_guard<std::mutex> lockGuard(mutex_); 1461 return defaultUsage_; 1462} 1463 1464void BufferQueue::ClearLocked() 1465{ 1466 for (auto &[id, ele] : bufferQueueCache_) { 1467 if (onBufferDeleteForRSMainThread_ != nullptr) { 1468 onBufferDeleteForRSMainThread_(id); 1469 } 1470 if (onBufferDeleteForRSHardwareThread_ != nullptr) { 1471 onBufferDeleteForRSHardwareThread_(id); 1472 } 1473 1474 if (name_ == "RosenWeb") { 1475 BLOGD("ClearLocked, bufferFd: %{public}d, refCount: %{public}d.", 1476 ele.buffer->GetBufferHandle()->fd, ele.buffer->GetSptrRefCount()); 1477 } 1478 } 1479 bufferQueueCache_.clear(); 1480 freeList_.clear(); 1481 dirtyList_.clear(); 1482 deletingList_.clear(); 1483} 1484 1485GSError BufferQueue::GoBackground() 1486{ 1487 BLOGD("GoBackground, uniqueId: %{public}" PRIu64 ".", uniqueId_); 1488 sptr<IBufferConsumerListener> listener; 1489 IBufferConsumerListenerClazz *listenerClazz; 1490 { 1491 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1492 listener = listener_; 1493 listenerClazz = listenerClazz_; 1494 } 1495 if (listener != nullptr) { 1496 SURFACE_TRACE_NAME_FMT("OnGoBackground name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 1497 listener->OnGoBackground(); 1498 } else if (listenerClazz != nullptr) { 1499 SURFACE_TRACE_NAME_FMT("OnGoBackground name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 1500 listenerClazz->OnGoBackground(); 1501 } 1502 std::lock_guard<std::mutex> lockGuard(mutex_); 1503 ClearLocked(); 1504 waitReqCon_.notify_all(); 1505 SetProducerCacheCleanFlagLocked(false); 1506 return GSERROR_OK; 1507} 1508 1509GSError BufferQueue::CleanCache(bool cleanAll) 1510{ 1511 BLOGD("CleanCache, uniqueId: %{public}" PRIu64 ". cleanAll: %{public}d.", uniqueId_, cleanAll); 1512 sptr<IBufferConsumerListener> listener; 1513 IBufferConsumerListenerClazz *listenerClazz; 1514 { 1515 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1516 listener = listener_; 1517 listenerClazz = listenerClazz_; 1518 } 1519 if (cleanAll) { 1520 if (listener != nullptr) { 1521 SURFACE_TRACE_NAME_FMT("OnGoBackground name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 1522 listener->OnGoBackground(); 1523 } else if (listenerClazz != nullptr) { 1524 SURFACE_TRACE_NAME_FMT("OnGoBackground name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 1525 listenerClazz->OnGoBackground(); 1526 } 1527 } else { 1528 if (listener != nullptr) { 1529 SURFACE_TRACE_NAME_FMT("OnCleanCache name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 1530 listener->OnCleanCache(); 1531 } else if (listenerClazz != nullptr) { 1532 SURFACE_TRACE_NAME_FMT("OnCleanCache name: %s queueId: %" PRIu64, name_.c_str(), uniqueId_); 1533 listenerClazz->OnCleanCache(); 1534 } 1535 } 1536 std::lock_guard<std::mutex> lockGuard(mutex_); 1537 ClearLocked(); 1538 waitReqCon_.notify_all(); 1539 return GSERROR_OK; 1540} 1541 1542GSError BufferQueue::OnConsumerDied() 1543{ 1544 std::lock_guard<std::mutex> lockGuard(mutex_); 1545 ClearLocked(); 1546 waitReqCon_.notify_all(); 1547 return GSERROR_OK; 1548} 1549 1550GSError BufferQueue::IsSurfaceBufferInCache(uint32_t seqNum, bool &isInCache) 1551{ 1552 std::unique_lock<std::mutex> lock(mutex_); 1553 if (bufferQueueCache_.find(seqNum) != bufferQueueCache_.end()) { 1554 isInCache = true; 1555 } else { 1556 isInCache = false; 1557 } 1558 return GSERROR_OK; 1559} 1560 1561uint64_t BufferQueue::GetUniqueId() const 1562{ 1563 std::unique_lock<std::mutex> lock(mutex_); 1564 return uniqueId_; 1565} 1566 1567GSError BufferQueue::SetTransform(GraphicTransformType transform) 1568{ 1569 { 1570 std::unique_lock<std::mutex> lock(mutex_); 1571 if (transform_ == transform) { 1572 return GSERROR_OK; 1573 } 1574 1575 transform_ = transform; 1576 } 1577 sptr<IBufferConsumerListener> listener; 1578 IBufferConsumerListenerClazz *listenerClazz; 1579 { 1580 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1581 listener = listener_; 1582 listenerClazz = listenerClazz_; 1583 } 1584 if (listener != nullptr) { 1585 SURFACE_TRACE_NAME_FMT("OnTransformChange transform: %u", transform); 1586 listener->OnTransformChange(); 1587 } else if (listenerClazz != nullptr) { 1588 SURFACE_TRACE_NAME_FMT("OnTransformChange transform: %u", transform); 1589 listenerClazz->OnTransformChange(); 1590 } 1591 return GSERROR_OK; 1592} 1593 1594GraphicTransformType BufferQueue::GetTransform() const 1595{ 1596 std::unique_lock<std::mutex> lock(mutex_); 1597 return transform_; 1598} 1599 1600GSError BufferQueue::SetTransformHint(GraphicTransformType transformHint) 1601{ 1602 std::unique_lock<std::mutex> lock(mutex_); 1603 transformHint_ = transformHint; 1604 return GSERROR_OK; 1605} 1606 1607GraphicTransformType BufferQueue::GetTransformHint() const 1608{ 1609 std::unique_lock<std::mutex> lock(mutex_); 1610 return transformHint_; 1611} 1612 1613GSError BufferQueue::SetSurfaceSourceType(OHSurfaceSource sourceType) 1614{ 1615 std::unique_lock<std::mutex> lock(mutex_); 1616 sourceType_ = sourceType; 1617 return GSERROR_OK; 1618} 1619 1620OHSurfaceSource BufferQueue::GetSurfaceSourceType() const 1621{ 1622 std::unique_lock<std::mutex> lock(mutex_); 1623 return sourceType_; 1624} 1625 1626GSError BufferQueue::SetHdrWhitePointBrightness(float brightness) 1627{ 1628 std::unique_lock<std::mutex> lock(mutex_); 1629 hdrWhitePointBrightness_ = brightness; 1630 return GSERROR_OK; 1631} 1632 1633GSError BufferQueue::SetSdrWhitePointBrightness(float brightness) 1634{ 1635 std::unique_lock<std::mutex> lock(mutex_); 1636 sdrWhitePointBrightness_ = brightness; 1637 return GSERROR_OK; 1638} 1639 1640float BufferQueue::GetHdrWhitePointBrightness() const 1641{ 1642 std::unique_lock<std::mutex> lock(mutex_); 1643 return hdrWhitePointBrightness_; 1644} 1645 1646float BufferQueue::GetSdrWhitePointBrightness() const 1647{ 1648 std::unique_lock<std::mutex> lock(mutex_); 1649 return sdrWhitePointBrightness_; 1650} 1651 1652GSError BufferQueue::SetSurfaceAppFrameworkType(std::string appFrameworkType) 1653{ 1654 if (appFrameworkType.empty()) { 1655 return GSERROR_NO_ENTRY; 1656 } 1657 if (appFrameworkType.size() > MAXIMUM_LENGTH_OF_APP_FRAMEWORK) { 1658 return GSERROR_OUT_OF_RANGE; 1659 } 1660 std::unique_lock<std::mutex> lock(mutex_); 1661 appFrameworkType_ = appFrameworkType; 1662 return GSERROR_OK; 1663} 1664 1665std::string BufferQueue::GetSurfaceAppFrameworkType() const 1666{ 1667 std::unique_lock<std::mutex> lock(mutex_); 1668 return appFrameworkType_; 1669} 1670 1671GSError BufferQueue::IsSupportedAlloc(const std::vector<BufferVerifyAllocInfo> &infos, 1672 std::vector<bool> &supporteds) const 1673{ 1674 supporteds.clear(); 1675 for (uint32_t index = 0; index < infos.size(); index++) { 1676 if (infos[index].format == GRAPHIC_PIXEL_FMT_RGBA_8888 || 1677 infos[index].format == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) { 1678 supporteds.push_back(true); 1679 } else { 1680 supporteds.push_back(false); 1681 } 1682 } 1683 return GSERROR_OK; 1684} 1685 1686GSError BufferQueue::SetBufferHold(bool hold) 1687{ 1688 std::unique_lock<std::mutex> lock(mutex_); 1689 isBufferHold_ = hold; 1690 return GSERROR_OK; 1691} 1692 1693GSError BufferQueue::SetScalingMode(uint32_t sequence, ScalingMode scalingMode) 1694{ 1695 std::lock_guard<std::mutex> lockGuard(mutex_); 1696 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1697 return GSERROR_NO_ENTRY; 1698 } 1699 bufferQueueCache_[sequence].scalingMode = scalingMode; 1700 return GSERROR_OK; 1701} 1702 1703GSError BufferQueue::SetScalingMode(ScalingMode scalingMode) 1704{ 1705 std::lock_guard<std::mutex> lockGuard(mutex_); 1706 for (auto it = bufferQueueCache_.begin(); it != bufferQueueCache_.end(); it++) { 1707 it->second.scalingMode = scalingMode; 1708 } 1709 scalingMode_ = scalingMode; 1710 return GSERROR_OK; 1711} 1712 1713GSError BufferQueue::GetScalingMode(uint32_t sequence, ScalingMode &scalingMode) 1714{ 1715 std::lock_guard<std::mutex> lockGuard(mutex_); 1716 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1717 return GSERROR_NO_ENTRY; 1718 } 1719 scalingMode = bufferQueueCache_.at(sequence).scalingMode; 1720 return GSERROR_OK; 1721} 1722 1723GSError BufferQueue::SetMetaData(uint32_t sequence, const std::vector<GraphicHDRMetaData> &metaData) 1724{ 1725 std::lock_guard<std::mutex> lockGuard(mutex_); 1726 if (metaData.size() == 0) { 1727 BLOGW("metaData size is 0, uniqueId: %{public}" PRIu64 ".", uniqueId_); 1728 return GSERROR_INVALID_ARGUMENTS; 1729 } 1730 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1731 return GSERROR_NO_ENTRY; 1732 } 1733 bufferQueueCache_[sequence].metaData.clear(); 1734 bufferQueueCache_[sequence].metaData = metaData; 1735 bufferQueueCache_[sequence].hdrMetaDataType = HDRMetaDataType::HDR_META_DATA; 1736 return GSERROR_OK; 1737} 1738 1739GSError BufferQueue::SetMetaDataSet(uint32_t sequence, GraphicHDRMetadataKey key, 1740 const std::vector<uint8_t> &metaData) 1741{ 1742 std::lock_guard<std::mutex> lockGuard(mutex_); 1743 if (key < GraphicHDRMetadataKey::GRAPHIC_MATAKEY_RED_PRIMARY_X || 1744 key > GraphicHDRMetadataKey::GRAPHIC_MATAKEY_HDR_VIVID) { 1745 BLOGW("key is %{public}d, uniqueId: %{public}" PRIu64 ".", key, uniqueId_); 1746 return GSERROR_INVALID_ARGUMENTS; 1747 } 1748 if (metaData.size() == 0) { 1749 BLOGW("metaData size is 0, uniqueId: %{public}" PRIu64 ".", uniqueId_); 1750 return GSERROR_INVALID_ARGUMENTS; 1751 } 1752 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1753 return GSERROR_NO_ENTRY; 1754 } 1755 bufferQueueCache_[sequence].metaDataSet.clear(); 1756 bufferQueueCache_[sequence].key = key; 1757 bufferQueueCache_[sequence].metaDataSet = metaData; 1758 bufferQueueCache_[sequence].hdrMetaDataType = HDRMetaDataType::HDR_META_DATA_SET; 1759 return GSERROR_OK; 1760} 1761 1762GSError BufferQueue::QueryMetaDataType(uint32_t sequence, HDRMetaDataType &type) 1763{ 1764 std::lock_guard<std::mutex> lockGuard(mutex_); 1765 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1766 return GSERROR_NO_ENTRY; 1767 } 1768 type = bufferQueueCache_.at(sequence).hdrMetaDataType; 1769 return GSERROR_OK; 1770} 1771 1772GSError BufferQueue::GetMetaData(uint32_t sequence, std::vector<GraphicHDRMetaData> &metaData) 1773{ 1774 std::lock_guard<std::mutex> lockGuard(mutex_); 1775 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1776 return GSERROR_NO_ENTRY; 1777 } 1778 metaData.clear(); 1779 metaData = bufferQueueCache_.at(sequence).metaData; 1780 return GSERROR_OK; 1781} 1782 1783GSError BufferQueue::GetMetaDataSet(uint32_t sequence, GraphicHDRMetadataKey &key, 1784 std::vector<uint8_t> &metaData) 1785{ 1786 std::lock_guard<std::mutex> lockGuard(mutex_); 1787 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1788 return GSERROR_NO_ENTRY; 1789 } 1790 metaData.clear(); 1791 key = bufferQueueCache_.at(sequence).key; 1792 metaData = bufferQueueCache_.at(sequence).metaDataSet; 1793 return GSERROR_OK; 1794} 1795 1796GSError BufferQueue::SetTunnelHandle(const sptr<SurfaceTunnelHandle> &handle) 1797{ 1798 std::lock_guard<std::mutex> lockGuard(mutex_); 1799 bool tunnelHandleChange = false; 1800 if (tunnelHandle_ == nullptr) { 1801 if (handle == nullptr) { 1802 BLOGW("tunnel handle is nullptr, uniqueId: %{public}" PRIu64 ".", uniqueId_); 1803 return GSERROR_INVALID_ARGUMENTS; 1804 } 1805 tunnelHandleChange = true; 1806 } else { 1807 tunnelHandleChange = tunnelHandle_->Different(handle); 1808 } 1809 if (!tunnelHandleChange) { 1810 BLOGW("same tunnel handle, uniqueId: %{public}" PRIu64 ".", uniqueId_); 1811 return GSERROR_NO_ENTRY; 1812 } 1813 tunnelHandle_ = handle; 1814 sptr<IBufferConsumerListener> listener; 1815 IBufferConsumerListenerClazz *listenerClazz; 1816 { 1817 std::lock_guard<std::mutex> lockGuard(listenerMutex_); 1818 listener = listener_; 1819 listenerClazz = listenerClazz_; 1820 } 1821 if (listener != nullptr) { 1822 SURFACE_TRACE_NAME("OnTunnelHandleChange"); 1823 listener->OnTunnelHandleChange(); 1824 } else if (listenerClazz != nullptr) { 1825 SURFACE_TRACE_NAME("OnTunnelHandleChange"); 1826 listenerClazz->OnTunnelHandleChange(); 1827 } else { 1828 return SURFACE_ERROR_CONSUMER_UNREGISTER_LISTENER; 1829 } 1830 return GSERROR_OK; 1831} 1832 1833sptr<SurfaceTunnelHandle> BufferQueue::GetTunnelHandle() 1834{ 1835 std::lock_guard<std::mutex> lockGuard(mutex_); 1836 return tunnelHandle_; 1837} 1838 1839GSError BufferQueue::SetPresentTimestamp(uint32_t sequence, const GraphicPresentTimestamp ×tamp) 1840{ 1841 std::lock_guard<std::mutex> lockGuard(mutex_); 1842 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1843 return GSERROR_NO_ENTRY; 1844 } 1845 bufferQueueCache_[sequence].presentTimestamp = timestamp; 1846 return GSERROR_OK; 1847} 1848 1849GSError BufferQueue::GetPresentTimestamp(uint32_t sequence, GraphicPresentTimestampType type, int64_t &time) 1850{ 1851 std::lock_guard<std::mutex> lockGuard(mutex_); 1852 if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { 1853 return GSERROR_NO_ENTRY; 1854 } 1855 if (type != bufferQueueCache_.at(sequence).presentTimestamp.type) { 1856 BLOGE("seq: %{public}u, PresentTimestampType [%{public}d] is not supported, the supported type is [%{public}d]," 1857 "uniqueId: %{public}" PRIu64 ".", sequence, type, 1858 bufferQueueCache_.at(sequence).presentTimestamp.type, uniqueId_); 1859 return GSERROR_NO_ENTRY; 1860 } 1861 switch (type) { 1862 case GraphicPresentTimestampType::GRAPHIC_DISPLAY_PTS_DELAY: { 1863 time = bufferQueueCache_.at(sequence).presentTimestamp.time; 1864 return GSERROR_OK; 1865 } 1866 case GraphicPresentTimestampType::GRAPHIC_DISPLAY_PTS_TIMESTAMP: { 1867 time = bufferQueueCache_.at(sequence).presentTimestamp.time - bufferQueueCache_.at(sequence).timestamp; 1868 return GSERROR_OK; 1869 } 1870 default: { 1871 BLOGE("seq: %{public}u, unsupported type: %{public}d, uniqueId: %{public}" PRIu64 ".", 1872 sequence, type, uniqueId_); 1873 return GSERROR_TYPE_ERROR; 1874 } 1875 } 1876} 1877 1878void BufferQueue::SetSurfaceBufferGlobalAlphaUnlocked(sptr<SurfaceBuffer> buffer) 1879{ 1880 std::lock_guard<std::mutex> lockGuard(globalAlphaMutex_); 1881 if (globalAlpha_ < FORCE_GLOBAL_ALPHA_MIN || globalAlpha_ > FORCE_GLOBAL_ALPHA_MAX) { 1882 BLOGE("Invalid global alpha value: %{public}d, uniqueId: %{public}" PRIu64 ".", globalAlpha_, uniqueId_); 1883 return; 1884 } 1885 using namespace HDI::Display::Graphic::Common; 1886 V2_0::BufferHandleAttrKey key = V2_0::BufferHandleAttrKey::ATTRKEY_FORCE_GLOBAL_ALPHA; 1887 std::vector<uint8_t> values; 1888 auto ret = MetadataHelper::ConvertMetadataToVec(globalAlpha_, values); 1889 if (ret != GSERROR_OK) { 1890 BLOGE("Convert global alpha value failed, ret: %{public}d, value: %{public}d, uniqueId: %{public}" PRIu64 ".", 1891 ret, globalAlpha_, uniqueId_); 1892 return; 1893 } 1894 buffer->SetMetadata(key, values); 1895} 1896 1897GSError BufferQueue::SetGlobalAlpha(int32_t alpha) 1898{ 1899 std::lock_guard<std::mutex> lockGuard(globalAlphaMutex_); 1900 globalAlpha_ = alpha; 1901 return GSERROR_OK; 1902} 1903 1904GSError BufferQueue::GetGlobalAlpha(int32_t &alpha) 1905{ 1906 std::lock_guard<std::mutex> lockGuard(globalAlphaMutex_); 1907 alpha = globalAlpha_; 1908 return GSERROR_OK; 1909} 1910 1911void BufferQueue::DumpMetadata(std::string &result, BufferElement element) 1912{ 1913 HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType colorSpaceType; 1914 MetadataHelper::GetColorSpaceType(element.buffer, colorSpaceType); 1915 HDI::Display::Graphic::Common::V1_0::CM_HDR_Metadata_Type hdrMetadataType = 1916 HDI::Display::Graphic::Common::V1_0::CM_METADATA_NONE; 1917 std::vector<uint8_t> dataStatic; 1918 std::vector<uint8_t> dataDynamic; 1919 MetadataHelper::GetHDRDynamicMetadata(element.buffer, dataDynamic); 1920 MetadataHelper::GetHDRStaticMetadata(element.buffer, dataStatic); 1921 MetadataHelper::GetHDRMetadataType(element.buffer, hdrMetadataType); 1922 result += std::to_string(colorSpaceType) + ", "; 1923 result += " [staticMetadata: "; 1924 for (auto x : dataStatic) { 1925 result += std::to_string(x); 1926 result += " "; 1927 } 1928 result += " ],[dynamicMetadata: "; 1929 for (auto x : dataDynamic) { 1930 result += std::to_string(x); 1931 result += " "; 1932 } 1933 result += " ],[metadataType: "; 1934 result += std::to_string(hdrMetadataType) + "],"; 1935} 1936 1937void BufferQueue::DumpCache(std::string &result) 1938{ 1939 for (auto it = bufferQueueCache_.begin(); it != bufferQueueCache_.end(); it++) { 1940 BufferElement element = it->second; 1941 if (BufferStateStrs.find(element.state) != BufferStateStrs.end()) { 1942 result += " sequence = " + std::to_string(it->first) + 1943 ", state = " + std::to_string(element.state) + 1944 ", timestamp = " + std::to_string(element.timestamp); 1945 } 1946 for (decltype(element.damages.size()) i = 0; i < element.damages.size(); i++) { 1947 result += ", damagesRect = [" + std::to_string(i) + "] = [" + 1948 std::to_string(element.damages[i].x) + ", " + 1949 std::to_string(element.damages[i].y) + ", " + 1950 std::to_string(element.damages[i].w) + ", " + 1951 std::to_string(element.damages[i].h) + "],"; 1952 } 1953 result += " config = [" + std::to_string(element.config.width) + "x" + 1954 std::to_string(element.config.height) + ", " + 1955 std::to_string(element.config.strideAlignment) + ", " + 1956 std::to_string(element.config.format) +", " + 1957 std::to_string(element.config.usage) + ", " + 1958 std::to_string(element.config.timeout) + ", " + 1959 std::to_string(element.config.colorGamut) + ", " + 1960 std::to_string(element.config.transform) + "],"; 1961 DumpMetadata(result, element); 1962 result += " scalingMode = " + std::to_string(element.scalingMode) + ","; 1963 result += " HDR = " + std::to_string(element.hdrMetaDataType) + ", "; 1964 1965 double bufferMemSize = 0; 1966 if (element.buffer != nullptr) { 1967 result += " bufferWith = " + std::to_string(element.buffer->GetWidth()) + 1968 ", bufferHeight = " + std::to_string(element.buffer->GetHeight()); 1969 bufferMemSize = static_cast<double>(element.buffer->GetSize()) / BUFFER_MEMSIZE_RATE; 1970 } 1971 1972 std::ostringstream ss; 1973 ss.precision(BUFFER_MEMSIZE_FORMAT); 1974 ss.setf(std::ios::fixed); 1975 ss << bufferMemSize; 1976 std::string str = ss.str(); 1977 result += ", bufferMemSize = " + str + "(KiB).\n"; 1978 } 1979} 1980 1981void BufferQueue::Dump(std::string &result) 1982{ 1983 std::lock_guard<std::mutex> lockGuard(mutex_); 1984 std::ostringstream ss; 1985 ss.precision(BUFFER_MEMSIZE_FORMAT); 1986 ss.setf(std::ios::fixed); 1987 static double allSurfacesMemSize = 0; 1988 uint64_t totalBufferListSize = 0; 1989 double memSizeInKB = 0; 1990 1991 for (auto it = bufferQueueCache_.begin(); it != bufferQueueCache_.end(); it++) { 1992 BufferElement element = it->second; 1993 if (element.buffer != nullptr) { 1994 totalBufferListSize += element.buffer->GetSize(); 1995 } 1996 } 1997 memSizeInKB = static_cast<double>(totalBufferListSize) / BUFFER_MEMSIZE_RATE; 1998 1999 allSurfacesMemSize += memSizeInKB; 2000 uint32_t resultLen = result.size(); 2001 std::string dumpEndFlag = "dumpend"; 2002 if (resultLen > dumpEndFlag.size() && resultLen > 1) { 2003 std::string dumpEndIn(result, resultLen - dumpEndFlag.size(), resultLen - 1); 2004 if (dumpEndIn == dumpEndFlag) { 2005 ss << allSurfacesMemSize; 2006 std::string dumpEndStr = ss.str(); 2007 result.erase(resultLen - dumpEndFlag.size(), resultLen - 1); 2008 result += dumpEndStr + " KiB.\n"; 2009 allSurfacesMemSize = 0; 2010 return; 2011 } 2012 } 2013 2014 ss.str(""); 2015 ss << memSizeInKB; 2016 std::string str = ss.str(); 2017 result.append("\nBufferQueue:\n"); 2018 result += " default-size = [" + std::to_string(defaultWidth_) + "x" + std::to_string(defaultHeight_) + "]" + 2019 ", FIFO = " + std::to_string(bufferQueueSize_) + 2020 ", name = " + name_ + 2021 ", uniqueId = " + std::to_string(uniqueId_) + 2022 ", usedBufferListLen = " + std::to_string(GetUsedSize()) + 2023 ", freeBufferListLen = " + std::to_string(freeList_.size()) + 2024 ", dirtyBufferListLen = " + std::to_string(dirtyList_.size()) + 2025 ", totalBuffersMemSize = " + str + "(KiB)" + 2026 ", hdrWhitePointBrightness = " + std::to_string(hdrWhitePointBrightness_) + 2027 ", sdrWhitePointBrightness = " + std::to_string(sdrWhitePointBrightness_) + 2028 ", lockLastFlushedBuffer seq = " + std::to_string(acquireLastFlushedBufSequence_) + "\n"; 2029 2030 result.append(" bufferQueueCache:\n"); 2031 DumpCache(result); 2032} 2033 2034bool BufferQueue::GetStatusLocked() const 2035{ 2036 return isValidStatus_; 2037} 2038 2039bool BufferQueue::GetStatus() const 2040{ 2041 std::lock_guard<std::mutex> lockGuard(mutex_); 2042 return GetStatusLocked(); 2043} 2044 2045void BufferQueue::SetStatus(bool status) 2046{ 2047 std::lock_guard<std::mutex> lockGuard(mutex_); 2048 isValidStatus_ = status; 2049 waitReqCon_.notify_all(); 2050} 2051 2052uint32_t BufferQueue::GetAvailableBufferCount() 2053{ 2054 std::lock_guard<std::mutex> lockGuard(mutex_); 2055 return static_cast<uint32_t>(dirtyList_.size()); 2056} 2057}; // namespace OHOS 2058