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
24 namespace OHOS {
25 const int32_t BUFFER_STRIDE_ALIGNMENT_DEFAULT = 4;
26 const uint8_t BUFFER_QUEUE_SIZE_DEFAULT = 1;
27 const uint8_t BUFFER_QUEUE_SIZE_MAX = 10;
28 const int32_t BUFFER_CONSUMER_USAGE_DEFAULT = BUFFER_CONSUMER_USAGE_SORTWARE;
29 const uint8_t USER_DATA_COUNT = 100;
30
BufferQueue()31 BufferQueue::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
~BufferQueue()45 BufferQueue::~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
Init()65 bool 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
NeedAttach()79 void 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
CanRequest(uint8_t wait)108 bool 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 }
128 ERROR:
129 return res;
130 }
131
RequestBuffer(uint8_t wait)132 SurfaceBufferImpl* 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);
147 ERROR:
148 pthread_mutex_unlock(&lock_);
149 return buffer;
150 }
151
GetBuffer(const SurfaceBufferImpl & buffer)152 SurfaceBufferImpl* 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
FlushBuffer(SurfaceBufferImpl & buffer)164 int32_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
AcquireBuffer()182 SurfaceBufferImpl* 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
Detach(SurfaceBufferImpl * buffer)202 void 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
ReleaseBuffer(const SurfaceBufferImpl & buffer)217 bool BufferQueue::ReleaseBuffer(const SurfaceBufferImpl& buffer)
218 {
219 return ReleaseBuffer(buffer, BUFFER_STATE_ACQUIRE) == SURFACE_ERROR_OK;
220 }
221
CancelBuffer(const SurfaceBufferImpl & buffer)222 int32_t BufferQueue::CancelBuffer(const SurfaceBufferImpl& buffer)
223 {
224 return ReleaseBuffer(buffer, BUFFER_STATE_REQUEST);
225 }
226
ReleaseBuffer(const SurfaceBufferImpl & buffer,BufferState state)227 int32_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();
256 ERROR:
257 pthread_mutex_unlock(&lock_);
258 pthread_cond_signal(&freeCond_);
259 return ret;
260 }
261
isValidAttr(uint32_t width,uint32_t height,uint32_t format,uint32_t strideAlignment)262 int32_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
Reset(uint32_t size)271 int32_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
SetQueueSize(uint8_t queueSize)303 void 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
GetQueueSize()339 uint8_t BufferQueue::GetQueueSize()
340 {
341 return queueSize_;
342 }
343
SetWidthAndHeight(uint32_t width,uint32_t height)344 void 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
GetWidth()354 int32_t BufferQueue::GetWidth()
355 {
356 return width_;
357 }
358
GetHeight()359 int32_t BufferQueue::GetHeight()
360 {
361 return height_;
362 }
363
SetSize(uint32_t size)364 void 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
GetSize()374 int32_t BufferQueue::GetSize()
375 {
376 return size_;
377 }
378
SetUserData(const std::string & key,const std::string & value)379 void 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
GetUserData(const std::string & key)387 std::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
SetFormat(uint32_t format)396 void 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
GetFormat()409 int32_t BufferQueue::GetFormat()
410 {
411 return format_;
412 }
413
SetStrideAlignment(uint32_t stride)414 void 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
GetStrideAlignment()423 int32_t BufferQueue::GetStrideAlignment()
424 {
425 return strideAlignment_;
426 }
427
GetStride()428 int32_t BufferQueue::GetStride()
429 {
430 return stride_;
431 }
432
SetUsage(uint32_t usage)433 void 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
GetUsage()442 int32_t BufferQueue::GetUsage()
443 {
444 return usage_;
445 }
446 } // end namespace
447