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 "surface_buffer_impl.h"
17
18 #include <mutex>
19
20 #include <message_parcel.h>
21 #include <securec.h>
22 #include <sys/mman.h>
23 #include "buffer_log.h"
24 #include "buffer_manager.h"
25 #include "buffer_extra_data_impl.h"
26 #include "native_buffer.h"
27 #include "v1_0/include/idisplay_buffer.h"
28
29 namespace OHOS {
30 namespace {
GenerateError(GSError err,GraphicDispErrCode code)31 GSError GenerateError(GSError err, GraphicDispErrCode code)
32 {
33 switch (code) {
34 case GRAPHIC_DISPLAY_SUCCESS: return static_cast<GSError>(err + 0);
35 case GRAPHIC_DISPLAY_FAILURE: return static_cast<GSError>(err + LOWERROR_FAILURE);
36 case GRAPHIC_DISPLAY_FD_ERR: return static_cast<GSError>(err + EBADF);
37 case GRAPHIC_DISPLAY_PARAM_ERR: return static_cast<GSError>(err + EINVAL);
38 case GRAPHIC_DISPLAY_NULL_PTR: return static_cast<GSError>(err + EINVAL);
39 case GRAPHIC_DISPLAY_NOT_SUPPORT: return static_cast<GSError>(err + EOPNOTSUPP);
40 case GRAPHIC_DISPLAY_NOMEM: return static_cast<GSError>(err + ENOMEM);
41 case GRAPHIC_DISPLAY_SYS_BUSY: return static_cast<GSError>(err + EBUSY);
42 case GRAPHIC_DISPLAY_NOT_PERM: return static_cast<GSError>(err + EPERM);
43 default: break;
44 }
45 return static_cast<GSError>(err + LOWERROR_INVALID);
46 }
47
GenerateError(GSError err,int32_t code)48 inline GSError GenerateError(GSError err, int32_t code)
49 {
50 return GenerateError(err, static_cast<GraphicDispErrCode>(code));
51 }
52
53 using namespace OHOS::HDI::Display::Buffer::V1_0;
54 using IDisplayBufferSptr = std::shared_ptr<IDisplayBuffer>;
55 static IDisplayBufferSptr g_displayBuffer;
56 static std::mutex g_DisplayBufferMutex;
57 class DisplayBufferDiedRecipient : public OHOS::IRemoteObject::DeathRecipient {
58 public:
59 DisplayBufferDiedRecipient() = default;
60 virtual ~DisplayBufferDiedRecipient() = default;
OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> & remote)61 void OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject>& remote) override
62 {
63 std::lock_guard<std::mutex> lock(g_DisplayBufferMutex);
64 g_displayBuffer = nullptr;
65 BLOGD("IDisplayBuffer died and g_displayBuffer is nullptr");
66 };
67 };
GetDisplayBuffer()68 IDisplayBufferSptr GetDisplayBuffer()
69 {
70 std::lock_guard<std::mutex> lock(g_DisplayBufferMutex);
71 if (g_displayBuffer != nullptr) {
72 return g_displayBuffer;
73 }
74
75 g_displayBuffer.reset(IDisplayBuffer::Get());
76 if (g_displayBuffer == nullptr) {
77 BLOGE("IDisplayBuffer::Get return nullptr.");
78 return nullptr;
79 }
80 sptr<IRemoteObject::DeathRecipient> recipient = new DisplayBufferDiedRecipient();
81 g_displayBuffer->AddDeathRecipient(recipient);
82 return g_displayBuffer;
83 }
84
85 }
86
Create()87 sptr<SurfaceBuffer> SurfaceBuffer::Create()
88 {
89 sptr<SurfaceBuffer> surfaceBufferImpl = new SurfaceBufferImpl();
90 return surfaceBufferImpl;
91 }
92
DisplayBufferDeathCallback(void * data)93 void SurfaceBufferImpl::DisplayBufferDeathCallback(void* data)
94 {
95 std::lock_guard<std::mutex> lock(g_DisplayBufferMutex);
96 g_displayBuffer = nullptr;
97 BLOGD("gralloc_host died and g_displayBuffer is nullptr.");
98 }
99
SurfaceBufferImpl()100 SurfaceBufferImpl::SurfaceBufferImpl()
101 {
102 {
103 static std::mutex mutex;
104 mutex.lock();
105
106 static uint32_t sequence_number_ = 0;
107 sequenceNumber_ = sequence_number_++;
108
109 mutex.unlock();
110 }
111 bedata_ = new BufferExtraDataImpl;
112 BLOGD("ctor +[%{public}u]", sequenceNumber_);
113 }
114
SurfaceBufferImpl(uint32_t seqNum)115 SurfaceBufferImpl::SurfaceBufferImpl(uint32_t seqNum)
116 {
117 sequenceNumber_ = seqNum;
118 bedata_ = new BufferExtraDataImpl;
119 BLOGD("ctor =[%{public}u]", sequenceNumber_);
120 }
121
~SurfaceBufferImpl()122 SurfaceBufferImpl::~SurfaceBufferImpl()
123 {
124 BLOGD("dtor ~[%{public}u]", sequenceNumber_);
125 FreeBufferHandleLocked();
126 }
127
FromBase(const sptr<SurfaceBuffer> & buffer)128 SurfaceBufferImpl *SurfaceBufferImpl::FromBase(const sptr<SurfaceBuffer>& buffer)
129 {
130 return static_cast<SurfaceBufferImpl*>(buffer.GetRefPtr());
131 }
132
Alloc(const BufferRequestConfig & config)133 GSError SurfaceBufferImpl::Alloc(const BufferRequestConfig &config)
134 {
135 if (GetDisplayBuffer() == nullptr) {
136 BLOGE("GetDisplayBuffer failed!");
137 return GSERROR_INTERNAL;
138 }
139
140 {
141 std::lock_guard<std::mutex> lock(mutex_);
142 if (handle_ != nullptr) {
143 FreeBufferHandleLocked();
144 }
145 }
146
147 GSError ret = CheckBufferConfig(config.width, config.height, config.format, config.usage);
148 if (ret != GSERROR_OK) {
149 return GSERROR_INVALID_ARGUMENTS;
150 }
151
152 BufferHandle *handle = nullptr;
153 AllocInfo info = {config.width, config.height, config.usage, config.format};
154 auto dret = g_displayBuffer->AllocMem(info, handle);
155 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
156 std::lock_guard<std::mutex> lock(mutex_);
157 surfaceBufferColorGamut_ = static_cast<GraphicColorGamut>(config.colorGamut);
158 transform_ = static_cast<GraphicTransformType>(config.transform);
159 surfaceBufferWidth_ = config.width;
160 surfaceBufferHeight_ = config.height;
161 handle_ = handle;
162 BLOGD("buffer handle w: %{public}d h: %{public}d t: %{public}d",
163 handle_->width, handle_->height, config.transform);
164 return GSERROR_OK;
165 }
166 BLOGW("Failed with %{public}d", dret);
167 return GenerateError(GSERROR_API_FAILED, dret);
168 }
Map()169 GSError SurfaceBufferImpl::Map()
170 {
171 if (GetDisplayBuffer() == nullptr) {
172 BLOGE("GetDisplayBuffer failed!");
173 return GSERROR_INTERNAL;
174 }
175
176 BufferHandle *handle = nullptr;
177 {
178 std::lock_guard<std::mutex> lock(mutex_);
179 if (handle_ == nullptr) {
180 BLOGE("handle is nullptr");
181 return GSERROR_INVALID_OPERATING;
182 } else if (handle_->virAddr != nullptr) {
183 BLOGD("handle_->virAddr has been maped");
184 return GSERROR_OK;
185 }
186 handle = handle_;
187 }
188 #ifdef RS_ENABLE_AFBC
189 handle->usage |= (BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA);
190 #endif
191 void *virAddr = g_displayBuffer->Mmap(*handle);
192 if (virAddr == nullptr || virAddr == MAP_FAILED) {
193 return GSERROR_API_FAILED;
194 }
195 return GSERROR_OK;
196 }
Unmap()197 GSError SurfaceBufferImpl::Unmap()
198 {
199 if (GetDisplayBuffer() == nullptr) {
200 BLOGE("GetDisplayBuffer failed!");
201 return GSERROR_INTERNAL;
202 }
203 BufferHandle *handle = nullptr;
204 {
205 std::lock_guard<std::mutex> lock(mutex_);
206 if (handle_ == nullptr) {
207 BLOGE("handle is nullptr");
208 return GSERROR_INVALID_OPERATING;
209 } else if (handle_->virAddr == nullptr) {
210 BLOGW("handle has been unmaped");
211 return GSERROR_OK;
212 }
213 handle = handle_;
214 }
215
216 auto dret = g_displayBuffer->Unmap(*handle);
217 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
218 handle_->virAddr = nullptr;
219 return GSERROR_OK;
220 }
221 BLOGW("Failed with %{public}d", dret);
222 return GenerateError(GSERROR_API_FAILED, dret);
223 }
FlushCache()224 GSError SurfaceBufferImpl::FlushCache()
225 {
226 if (GetDisplayBuffer() == nullptr) {
227 BLOGE("GetDisplayBuffer failed!");
228 return GSERROR_INTERNAL;
229 }
230 BufferHandle *handle = nullptr;
231 {
232 std::lock_guard<std::mutex> lock(mutex_);
233 if (handle_ == nullptr) {
234 BLOGE("handle is nullptr");
235 return GSERROR_INVALID_OPERATING;
236 }
237 handle = handle_;
238 }
239
240 if (handle->virAddr == nullptr) {
241 return GSERROR_API_FAILED;
242 }
243
244 auto dret = g_displayBuffer->FlushCache(*handle);
245 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
246 return GSERROR_OK;
247 }
248 BLOGW("Failed with %{public}d", dret);
249 return GenerateError(GSERROR_API_FAILED, dret);
250 }
251
InvalidateCache()252 GSError SurfaceBufferImpl::InvalidateCache()
253 {
254 if (GetDisplayBuffer() == nullptr) {
255 BLOGE("GetDisplayBuffer failed!");
256 return GSERROR_INTERNAL;
257 }
258 BufferHandle *handle = nullptr;
259 {
260 std::lock_guard<std::mutex> lock(mutex_);
261 if (handle_ == nullptr) {
262 BLOGE("handle is nullptr");
263 return GSERROR_INVALID_OPERATING;
264 }
265 handle = handle_;
266 }
267
268 auto dret = g_displayBuffer->InvalidateCache(*handle);
269 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
270 return GSERROR_OK;
271 }
272 BLOGW("Failed with %{public}d", dret);
273 return GenerateError(GSERROR_API_FAILED, dret);
274 }
275
FreeBufferHandleLocked()276 void SurfaceBufferImpl::FreeBufferHandleLocked()
277 {
278 if (handle_) {
279 if (handle_->virAddr != nullptr && g_displayBuffer != nullptr) {
280 g_displayBuffer->Unmap(*handle_);
281 handle_->virAddr = nullptr;
282 }
283 FreeBufferHandle(handle_);
284 }
285 handle_ = nullptr;
286 }
287
GetBufferHandle() const288 BufferHandle *SurfaceBufferImpl::GetBufferHandle() const
289 {
290 std::lock_guard<std::mutex> lock(mutex_);
291 return handle_;
292 }
293
SetSurfaceBufferColorGamut(const GraphicColorGamut & colorGamut)294 void SurfaceBufferImpl::SetSurfaceBufferColorGamut(const GraphicColorGamut& colorGamut)
295 {
296 std::lock_guard<std::mutex> lock(mutex_);
297 surfaceBufferColorGamut_ = colorGamut;
298 }
299
GetSurfaceBufferColorGamut() const300 const GraphicColorGamut& SurfaceBufferImpl::GetSurfaceBufferColorGamut() const
301 {
302 std::lock_guard<std::mutex> lock(mutex_);
303 return surfaceBufferColorGamut_;
304 }
305
SetSurfaceBufferTransform(const GraphicTransformType & transform)306 void SurfaceBufferImpl::SetSurfaceBufferTransform(const GraphicTransformType& transform)
307 {
308 std::lock_guard<std::mutex> lock(mutex_);
309 transform_ = transform;
310 }
311
GetSurfaceBufferTransform() const312 const GraphicTransformType& SurfaceBufferImpl::GetSurfaceBufferTransform() const
313 {
314 std::lock_guard<std::mutex> lock(mutex_);
315 return transform_;
316 }
317
GetSurfaceBufferWidth() const318 int32_t SurfaceBufferImpl::GetSurfaceBufferWidth() const
319 {
320 std::lock_guard<std::mutex> lock(mutex_);
321 return surfaceBufferWidth_;
322 }
323
GetSurfaceBufferHeight() const324 int32_t SurfaceBufferImpl::GetSurfaceBufferHeight() const
325 {
326 std::lock_guard<std::mutex> lock(mutex_);
327 return surfaceBufferHeight_;
328 }
329
SetSurfaceBufferWidth(int32_t width)330 void SurfaceBufferImpl::SetSurfaceBufferWidth(int32_t width)
331 {
332 std::lock_guard<std::mutex> lock(mutex_);
333 surfaceBufferWidth_ = width;
334 }
335
SetSurfaceBufferHeight(int32_t height)336 void SurfaceBufferImpl::SetSurfaceBufferHeight(int32_t height)
337 {
338 std::lock_guard<std::mutex> lock(mutex_);
339 surfaceBufferHeight_ = height;
340 }
341
GetWidth() const342 int32_t SurfaceBufferImpl::GetWidth() const
343 {
344 std::lock_guard<std::mutex> lock(mutex_);
345 if (handle_ == nullptr) {
346 BLOGE("handle is nullptr");
347 return -1;
348 }
349 return handle_->width;
350 }
351
GetHeight() const352 int32_t SurfaceBufferImpl::GetHeight() const
353 {
354 std::lock_guard<std::mutex> lock(mutex_);
355 if (handle_ == nullptr) {
356 BLOGE("handle is nullptr");
357 return -1;
358 }
359 return handle_->height;
360 }
361
GetStride() const362 int32_t SurfaceBufferImpl::GetStride() const
363 {
364 std::lock_guard<std::mutex> lock(mutex_);
365 if (handle_ == nullptr) {
366 BLOGE("handle is nullptr");
367 return -1;
368 }
369 return handle_->stride;
370 }
371
GetFormat() const372 int32_t SurfaceBufferImpl::GetFormat() const
373 {
374 std::lock_guard<std::mutex> lock(mutex_);
375 if (handle_ == nullptr) {
376 BLOGE("handle is nullptr");
377 return -1;
378 }
379 return handle_->format;
380 }
381
GetUsage() const382 uint64_t SurfaceBufferImpl::GetUsage() const
383 {
384 std::lock_guard<std::mutex> lock(mutex_);
385 if (handle_ == nullptr) {
386 BLOGE("handle is nullptr");
387 return -1;
388 }
389 return handle_->usage;
390 }
391
GetPhyAddr() const392 uint64_t SurfaceBufferImpl::GetPhyAddr() const
393 {
394 std::lock_guard<std::mutex> lock(mutex_);
395 if (handle_ == nullptr) {
396 BLOGE("handle is nullptr");
397 return 0;
398 }
399 return handle_->phyAddr;
400 }
401
GetVirAddr()402 void *SurfaceBufferImpl::GetVirAddr()
403 {
404 GSError ret = this->Map();
405 if (ret != GSERROR_OK) {
406 BLOGW("Map failed");
407 return nullptr;
408 }
409 return handle_->virAddr;
410 }
411
GetFileDescriptor() const412 int32_t SurfaceBufferImpl::GetFileDescriptor() const
413 {
414 std::lock_guard<std::mutex> lock(mutex_);
415 if (handle_ == nullptr) {
416 BLOGE("handle is nullptr");
417 return -1;
418 }
419 return handle_->fd;
420 }
421
GetSize() const422 uint32_t SurfaceBufferImpl::GetSize() const
423 {
424 std::lock_guard<std::mutex> lock(mutex_);
425 if (handle_ == nullptr) {
426 BLOGW("handle is nullptr");
427 return 0;
428 }
429 return handle_->size;
430 }
431
SetExtraData(const sptr<BufferExtraData> & bedata)432 void SurfaceBufferImpl::SetExtraData(const sptr<BufferExtraData> &bedata)
433 {
434 std::lock_guard<std::mutex> lock(mutex_);
435 bedata_ = bedata;
436 }
437
GetExtraData() const438 const sptr<BufferExtraData>& SurfaceBufferImpl::GetExtraData() const
439 {
440 std::lock_guard<std::mutex> lock(mutex_);
441 return bedata_;
442 }
443
SetBufferHandle(BufferHandle * handle)444 void SurfaceBufferImpl::SetBufferHandle(BufferHandle *handle)
445 {
446 std::lock_guard<std::mutex> lock(mutex_);
447 handle_ = handle;
448 }
449
WriteToMessageParcel(MessageParcel & parcel)450 GSError SurfaceBufferImpl::WriteToMessageParcel(MessageParcel &parcel)
451 {
452 BufferHandle *handle = nullptr;
453 {
454 std::lock_guard<std::mutex> lock(mutex_);
455 if (handle_ == nullptr) {
456 BLOGE("Failure, Reason: handle_ is nullptr");
457 return GSERROR_NOT_INIT;
458 }
459 handle = handle_;
460 }
461
462 bool ret = WriteBufferHandle(parcel, *handle);
463 if (ret == false) {
464 BLOGE("Failure, Reason: WriteBufferHandle return false");
465 return GSERROR_API_FAILED;
466 }
467
468 return GSERROR_OK;
469 }
470
ReadFromMessageParcel(MessageParcel & parcel)471 GSError SurfaceBufferImpl::ReadFromMessageParcel(MessageParcel &parcel)
472 {
473 std::lock_guard<std::mutex> lock(mutex_);
474 FreeBufferHandleLocked();
475 handle_ = ReadBufferHandle(parcel);
476 if (handle_ == nullptr) {
477 return GSERROR_API_FAILED;
478 }
479
480 return GSERROR_OK;
481 }
482
SurfaceBufferToNativeBuffer()483 OH_NativeBuffer* SurfaceBufferImpl::SurfaceBufferToNativeBuffer()
484 {
485 return reinterpret_cast<OH_NativeBuffer *>(this);
486 }
487
GetSeqNum() const488 uint32_t SurfaceBufferImpl::GetSeqNum() const
489 {
490 return sequenceNumber_;
491 }
492
GetEglData() const493 sptr<EglData> SurfaceBufferImpl::GetEglData() const
494 {
495 return eglData_;
496 }
497
SetEglData(const sptr<EglData> & data)498 void SurfaceBufferImpl::SetEglData(const sptr<EglData>& data)
499 {
500 eglData_ = data;
501 }
502
CheckBufferConfig(int32_t width,int32_t height,int32_t format,uint64_t usage)503 GSError SurfaceBufferImpl::CheckBufferConfig(int32_t width, int32_t height,
504 int32_t format, uint64_t usage)
505 {
506 if (width <= 0 || height <= 0) {
507 BLOGE("width or height is greater than 0, now is w %{public}d h %{public}d", width, height);
508 return GSERROR_INVALID_ARGUMENTS;
509 }
510
511 if (format < 0 || format > GRAPHIC_PIXEL_FMT_BUTT) {
512 BLOGE("format [0, %{public}d], now is %{public}d", GRAPHIC_PIXEL_FMT_BUTT, format);
513 return GSERROR_INVALID_ARGUMENTS;
514 }
515
516 return GSERROR_OK;
517 }
518
GetBufferWrapper()519 BufferWrapper SurfaceBufferImpl::GetBufferWrapper()
520 {
521 BufferWrapper wrapper;
522 return wrapper;
523 }
524
SetBufferWrapper(BufferWrapper wrapper)525 void SurfaceBufferImpl::SetBufferWrapper(BufferWrapper wrapper) {}
526 } // namespace OHOS
527