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