1/* 2 * Copyright (c) 2020-2022 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 18#include <list> 19#include <string> 20 21#include "buffer_common.h" 22#include "buffer_manager.h" 23 24namespace OHOS { 25const int32_t BUFFER_STRIDE_ALIGNMENT_DEFAULT = 4; 26const uint8_t BUFFER_QUEUE_SIZE_DEFAULT = 1; 27const uint8_t BUFFER_QUEUE_SIZE_MAX = 10; 28const int32_t BUFFER_CONSUMER_USAGE_DEFAULT = BUFFER_CONSUMER_USAGE_SORTWARE; 29const uint8_t USER_DATA_COUNT = 100; 30 31BufferQueue::BufferQueue() 32 : width_(0), 33 height_(0), 34 format_(IMAGE_PIXEL_FORMAT_RGB565), 35 stride_(0), 36 usage_(BUFFER_CONSUMER_USAGE_DEFAULT), 37 size_(0), 38 queueSize_(BUFFER_QUEUE_SIZE_DEFAULT), 39 strideAlignment_(BUFFER_STRIDE_ALIGNMENT_DEFAULT), 40 attachCount_(0), 41 customSize_(false) 42{ 43} 44 45BufferQueue::~BufferQueue() 46{ 47 pthread_mutex_lock(&lock_); 48 freeList_.clear(); 49 dirtyList_.clear(); 50 std::list<SurfaceBufferImpl *>::iterator iterBuffer; 51 for (iterBuffer = allBuffers_.begin(); iterBuffer != allBuffers_.end(); ++iterBuffer) { 52 SurfaceBufferImpl* tmpBuffer = *iterBuffer; 53 BufferManager* bufferManager = BufferManager::GetInstance(); 54 if (bufferManager == nullptr) { 55 continue; 56 } 57 bufferManager->FreeBuffer(&tmpBuffer); 58 } 59 allBuffers_.clear(); 60 pthread_mutex_unlock(&lock_); 61 pthread_cond_destroy(&freeCond_); 62 pthread_mutex_destroy(&lock_); 63} 64 65bool BufferQueue::Init() 66{ 67 if (pthread_mutex_init(&lock_, NULL)) { 68 GRAPHIC_LOGE("Failed init mutex"); 69 return false; 70 } 71 if (pthread_cond_init(&freeCond_, NULL)) { 72 GRAPHIC_LOGE("Failed init cond"); 73 pthread_mutex_destroy(&lock_); 74 return false; 75 } 76 return true; 77} 78 79void BufferQueue::NeedAttach() 80{ 81 if (queueSize_ == attachCount_) { 82 GRAPHIC_LOGI("has alloced %d buffer, could not alloc more.", allBuffers_.size()); 83 return; 84 } 85 if (size_ == 0 && isValidAttr(width_, height_, format_, strideAlignment_) != SURFACE_ERROR_OK) { 86 GRAPHIC_LOGI("Invalid Attr."); 87 return; 88 } 89 BufferManager* bufferManager = BufferManager::GetInstance(); 90 RETURN_IF_FAIL(bufferManager); 91 SurfaceBufferImpl *buffer = nullptr; 92 if (size_ != 0 && customSize_) { 93 buffer = bufferManager->AllocBuffer(size_, usage_); 94 } else { 95 buffer = bufferManager->AllocBuffer(width_, height_, format_, usage_); 96 } 97 if (buffer == nullptr) { 98 GRAPHIC_LOGI("BufferManager alloc memory failed "); 99 return; 100 } 101 size_ = buffer->GetSize(); 102 stride_ = buffer->GetStride(); 103 attachCount_++; 104 freeList_.push_back(buffer); 105 allBuffers_.push_back(buffer); 106} 107 108bool BufferQueue::CanRequest(uint8_t wait) 109{ 110 bool res = true; 111 if (!freeList_.empty()) { 112 res = true; 113 goto ERROR; 114 } 115 if (attachCount_ < queueSize_) { 116 NeedAttach(); 117 res = true; 118 if (freeList_.empty()) { 119 GRAPHIC_LOGI("no buffer in freeQueue for dequeue."); 120 res = false; 121 } 122 goto ERROR; 123 } 124 if (wait) { 125 pthread_cond_wait(&freeCond_, &lock_); 126 res = true; 127 } 128ERROR: 129 return res; 130} 131 132SurfaceBufferImpl* BufferQueue::RequestBuffer(uint8_t wait) 133{ 134 SurfaceBufferImpl *buffer = nullptr; 135 pthread_mutex_lock(&lock_); 136 if (!CanRequest(wait)) { 137 GRAPHIC_LOGI("No buffer can request now."); 138 goto ERROR; 139 } 140 buffer = freeList_.front(); 141 if (buffer == nullptr) { 142 GRAPHIC_LOGI("freeQueue pop buffer failed."); 143 goto ERROR; 144 } 145 freeList_.pop_front(); 146 buffer->SetState(BUFFER_STATE_REQUEST); 147ERROR: 148 pthread_mutex_unlock(&lock_); 149 return buffer; 150} 151 152SurfaceBufferImpl* BufferQueue::GetBuffer(const SurfaceBufferImpl& buffer) 153{ 154 std::list<SurfaceBufferImpl *>::iterator iterBuffer; 155 for (iterBuffer = allBuffers_.begin(); iterBuffer != allBuffers_.end(); ++iterBuffer) { 156 SurfaceBufferImpl *tmpBuffer = *iterBuffer; 157 if (tmpBuffer->equals(buffer)) { 158 return tmpBuffer; 159 } 160 } 161 return nullptr; 162} 163 164int32_t BufferQueue::FlushBuffer(SurfaceBufferImpl& buffer) 165{ 166 pthread_mutex_lock(&lock_); 167 SurfaceBufferImpl *tmpBuffer = GetBuffer(buffer); 168 if (tmpBuffer == nullptr || tmpBuffer->GetState() != BUFFER_STATE_REQUEST) { 169 GRAPHIC_LOGI("Buffer is not existed or state invailed."); 170 pthread_mutex_unlock(&lock_); 171 return SURFACE_ERROR_BUFFER_NOT_EXISTED; 172 } 173 dirtyList_.push_back(tmpBuffer); 174 if (&buffer != tmpBuffer) { 175 tmpBuffer->CopyExtraData(buffer); 176 } 177 tmpBuffer->SetState(BUFFER_STATE_FLUSH); 178 pthread_mutex_unlock(&lock_); 179 return 0; 180} 181 182SurfaceBufferImpl* BufferQueue::AcquireBuffer() 183{ 184 pthread_mutex_lock(&lock_); 185 if (dirtyList_.empty()) { 186 pthread_mutex_unlock(&lock_); 187 GRAPHIC_LOGD("dirty queue is empty."); 188 return nullptr; 189 } 190 SurfaceBufferImpl *buffer = dirtyList_.front(); 191 if (buffer == nullptr) { 192 pthread_mutex_unlock(&lock_); 193 GRAPHIC_LOGW("dirty queue pop buffer failed."); 194 return nullptr; 195 } 196 buffer->SetState(BUFFER_STATE_ACQUIRE); 197 dirtyList_.pop_front(); 198 pthread_mutex_unlock(&lock_); 199 return buffer; 200} 201 202void BufferQueue::Detach(SurfaceBufferImpl *buffer) 203{ 204 if (buffer == nullptr) { 205 GRAPHIC_LOGW("Detach buffer failed, buffer is null."); 206 return; 207 } 208 freeList_.remove(buffer); 209 dirtyList_.remove(buffer); 210 allBuffers_.remove(buffer); 211 BufferManager* bufferManager = BufferManager::GetInstance(); 212 if (bufferManager != nullptr) { 213 bufferManager->FreeBuffer(&buffer); 214 } 215} 216 217bool BufferQueue::ReleaseBuffer(const SurfaceBufferImpl& buffer) 218{ 219 return ReleaseBuffer(buffer, BUFFER_STATE_ACQUIRE) == SURFACE_ERROR_OK; 220} 221 222int32_t BufferQueue::CancelBuffer(const SurfaceBufferImpl& buffer) 223{ 224 return ReleaseBuffer(buffer, BUFFER_STATE_REQUEST); 225} 226 227int32_t BufferQueue::ReleaseBuffer(const SurfaceBufferImpl& buffer, BufferState state) 228{ 229 int32_t ret = 0; 230 pthread_mutex_lock(&lock_); 231 SurfaceBufferImpl *tmpBuffer = GetBuffer(buffer); 232 if (tmpBuffer == nullptr || tmpBuffer->GetState() != state) { 233 GRAPHIC_LOGI("Buffer is not existed or state invailed."); 234 ret = SURFACE_ERROR_BUFFER_NOT_EXISTED; 235 goto ERROR; 236 } 237 238 if (tmpBuffer->GetDeletePending() == 1) { 239 GRAPHIC_LOGI("Release the buffer which state is deletePending."); 240 Detach(tmpBuffer); 241 ret = SURFACE_ERROR_OK; 242 goto ERROR; 243 } 244 245 if (allBuffers_.size() > queueSize_) { 246 GRAPHIC_LOGI("Release the buffer: alloc buffer count is more than max queue count."); 247 attachCount_--; 248 Detach(tmpBuffer); 249 ret = SURFACE_ERROR_OK; 250 goto ERROR; 251 } 252 253 freeList_.push_back(tmpBuffer); 254 tmpBuffer->SetState(BUFFER_STATE_RELEASE); 255 tmpBuffer->ClearExtraData(); 256ERROR: 257 pthread_mutex_unlock(&lock_); 258 pthread_cond_signal(&freeCond_); 259 return ret; 260} 261 262int32_t BufferQueue::isValidAttr(uint32_t width, uint32_t height, uint32_t format, uint32_t strideAlignment) 263{ 264 if (width == 0 || height == 0 || strideAlignment <= 0 265 || format == IMAGE_PIXEL_FORMAT_NONE) { 266 return SURFACE_ERROR_INVALID_PARAM; 267 } 268 return SURFACE_ERROR_OK; 269} 270 271int32_t BufferQueue::Reset(uint32_t size) 272{ 273 if (size == 0) { 274 if (isValidAttr(width_, height_, format_, strideAlignment_) != SURFACE_ERROR_OK) { 275 GRAPHIC_LOGI("Invalid Attr."); 276 return SURFACE_ERROR_INVALID_PARAM; 277 } else { 278 size_ = 0; 279 customSize_ = false; 280 } 281 } 282 std::list<SurfaceBufferImpl *>::iterator iterBuffer = freeList_.begin(); 283 while (iterBuffer != freeList_.end()) { 284 SurfaceBufferImpl *tmpBuffer = *iterBuffer; 285 dirtyList_.remove(tmpBuffer); 286 allBuffers_.remove(tmpBuffer); 287 BufferManager* bufferManager = BufferManager::GetInstance(); 288 if (bufferManager == nullptr) { 289 ++iterBuffer; 290 continue; 291 } 292 bufferManager->FreeBuffer(&tmpBuffer); 293 iterBuffer = freeList_.erase(iterBuffer); 294 } 295 for (iterBuffer = allBuffers_.begin(); iterBuffer != allBuffers_.end(); ++iterBuffer) { 296 SurfaceBufferImpl *tmpBuffer = *iterBuffer; 297 tmpBuffer->SetDeletePending(1); 298 } 299 attachCount_ = 0; 300 return 0; 301} 302 303void BufferQueue::SetQueueSize(uint8_t queueSize) 304{ 305 if (queueSize > BUFFER_QUEUE_SIZE_MAX || queueSize == queueSize_) { 306 GRAPHIC_LOGI("The queue count(%u) is invalid", queueSize); 307 return; 308 } 309 pthread_mutex_lock(&lock_); 310 if (queueSize_ > queueSize) { 311 uint8_t needDelete = queueSize_ - queueSize; 312 std::list<SurfaceBufferImpl *>::iterator iterBuffer = freeList_.begin(); 313 while (iterBuffer != freeList_.end()) { 314 SurfaceBufferImpl *tmpBuffer = *iterBuffer; 315 dirtyList_.remove(tmpBuffer); 316 allBuffers_.remove(tmpBuffer); 317 BufferManager* bufferManager = BufferManager::GetInstance(); 318 if (bufferManager == nullptr) { 319 ++iterBuffer; 320 continue; 321 } 322 bufferManager->FreeBuffer(&tmpBuffer); 323 iterBuffer = freeList_.erase(iterBuffer); 324 needDelete--; 325 attachCount_--; 326 if (needDelete == 0) { 327 break; 328 } 329 } 330 queueSize_ = queueSize; 331 pthread_mutex_unlock(&lock_); 332 } else if (queueSize_ < queueSize) { 333 queueSize_ = queueSize; 334 pthread_mutex_unlock(&lock_); 335 pthread_cond_signal(&freeCond_); 336 } 337} 338 339uint8_t BufferQueue::GetQueueSize() 340{ 341 return queueSize_; 342} 343 344void BufferQueue::SetWidthAndHeight(uint32_t width, uint32_t height) 345{ 346 pthread_mutex_lock(&lock_); 347 width_ = width; 348 height_ = height; 349 Reset(); 350 pthread_mutex_unlock(&lock_); 351 pthread_cond_signal(&freeCond_); 352} 353 354int32_t BufferQueue::GetWidth() 355{ 356 return width_; 357} 358 359int32_t BufferQueue::GetHeight() 360{ 361 return height_; 362} 363 364void BufferQueue::SetSize(uint32_t size) 365{ 366 pthread_mutex_lock(&lock_); 367 size_ = size; 368 customSize_ = true; 369 Reset(size); 370 pthread_mutex_unlock(&lock_); 371 pthread_cond_signal(&freeCond_); 372} 373 374int32_t BufferQueue::GetSize() 375{ 376 return size_; 377} 378 379void BufferQueue::SetUserData(const std::string& key, const std::string& value) 380{ 381 if (usrDataMap_.size() > USER_DATA_COUNT) { 382 return; 383 } 384 usrDataMap_[key] = value; 385} 386 387std::string BufferQueue::GetUserData(const std::string& key) 388{ 389 auto p = usrDataMap_.find(key); 390 if (p != usrDataMap_.end()) { 391 return p->second; 392 } 393 return std::string(); 394} 395 396void BufferQueue::SetFormat(uint32_t format) 397{ 398 if (format == IMAGE_PIXEL_FORMAT_NONE) { 399 GRAPHIC_LOGI("Format is invailed or not supported %u", format); 400 return; 401 } 402 pthread_mutex_lock(&lock_); 403 format_ = format; 404 Reset(); 405 pthread_mutex_unlock(&lock_); 406 pthread_cond_signal(&freeCond_); 407} 408 409int32_t BufferQueue::GetFormat() 410{ 411 return format_; 412} 413 414void BufferQueue::SetStrideAlignment(uint32_t stride) 415{ 416 pthread_mutex_lock(&lock_); 417 strideAlignment_ = stride; 418 Reset(); 419 pthread_mutex_unlock(&lock_); 420 pthread_cond_signal(&freeCond_); 421} 422 423int32_t BufferQueue::GetStrideAlignment() 424{ 425 return strideAlignment_; 426} 427 428int32_t BufferQueue::GetStride() 429{ 430 return stride_; 431} 432 433void BufferQueue::SetUsage(uint32_t usage) 434{ 435 pthread_mutex_lock(&lock_); 436 usage_ = usage; 437 Reset(); 438 pthread_mutex_unlock(&lock_); 439 pthread_cond_signal(&freeCond_); 440} 441 442int32_t BufferQueue::GetUsage() 443{ 444 return usage_; 445} 446} // end namespace 447