/* * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "surface_impl.h" #include #include "buffer_client_producer.h" #include "buffer_common.h" #include "buffer_manager.h" #include "buffer_queue_consumer.h" #include "buffer_queue_producer.h" #include "surface_buffer_impl.h" namespace OHOS { SurfaceImpl::SurfaceImpl() : consumer_(nullptr), producer_(nullptr), IsConsumer_(true) { sid_ = { .handle = 0, .token = 0 }; } SurfaceImpl::SurfaceImpl(const SvcIdentity& sid) : sid_(sid), consumer_(nullptr), producer_(nullptr), IsConsumer_(false) { } SurfaceImpl::~SurfaceImpl() { if (consumer_ != nullptr) { delete consumer_; consumer_ = nullptr; } if (producer_ != nullptr) { delete producer_; producer_ = nullptr; } #ifdef __LINUX__ if (sid_.handle != 0) { BinderRelease(sid_.ipcContext, sid_.handle); } #endif } bool SurfaceImpl::Init() { if (!BufferManager::GetInstance()->Init()) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Failed init buffer manager"); return false; } if (IsConsumer_) { BufferQueue* bufferQueue = new BufferQueue(); if (bufferQueue == nullptr) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Surface consumer(buffer queue) init failed."); return false; } if (!bufferQueue->Init()) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Buffer queue init failed."); delete bufferQueue; return false; } producer_ = new BufferQueueProducer(bufferQueue); if (producer_ == nullptr) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Surface consumer(producer) init failed."); delete bufferQueue; return false; } consumer_ = new BufferQueueConsumer(*bufferQueue); if (consumer_ == nullptr) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Surface consumer(consumer) init failed."); delete producer_; producer_ = nullptr; return false; } SvcIdentity svc; int32_t ret = RegisterIpcCallback(IpcRequestHandler, 0, IPC_WAIT_FOREVER, &svc, producer_); if (ret != LITEIPC_OK) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Surface RegisterIpcCallback failed."); delete consumer_; consumer_ = nullptr; delete producer_; producer_ = nullptr; return false; } sid_ = svc; } else { producer_ = new BufferClientProducer(sid_); if (producer_ == nullptr) { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "Surface producer init failed."); return false; } } return true; } void SurfaceImpl::SetWidthAndHeight(uint32_t width, uint32_t height) { RETURN_IF_FAIL(producer_ != nullptr); RETURN_IF_FAIL(width > 0 && width <= SURFACE_MAX_WIDTH); RETURN_IF_FAIL(height > 0 && height <= SURFACE_MAX_HEIGHT); producer_->SetWidthAndHeight(width, height); } uint32_t SurfaceImpl::GetWidth() { RETURN_VAL_IF_FAIL(producer_, 0); return producer_->GetWidth(); } uint32_t SurfaceImpl::GetHeight() { RETURN_VAL_IF_FAIL(producer_, 0); return producer_->GetHeight(); } void SurfaceImpl::SetFormat(uint32_t format) { RETURN_IF_FAIL(producer_); producer_->SetFormat(format); } uint32_t SurfaceImpl::GetFormat() { RETURN_VAL_IF_FAIL(producer_, 0); return producer_->GetFormat(); } void SurfaceImpl::SetStrideAlignment(uint32_t strideAlignment) { RETURN_IF_FAIL(producer_); RETURN_IF_FAIL(strideAlignment >= SURFACE_MIN_STRIDE_ALIGNMENT && strideAlignment <= SURFACE_MAX_STRIDE_ALIGNMENT); producer_->SetStrideAlignment(strideAlignment); } uint32_t SurfaceImpl::GetStrideAlignment() { RETURN_VAL_IF_FAIL(producer_, 0); return producer_->GetStrideAlignment(); } uint32_t SurfaceImpl::GetStride() { RETURN_VAL_IF_FAIL(producer_, 0); return producer_->GetStride(); } void SurfaceImpl::SetSize(uint32_t size) { RETURN_IF_FAIL(producer_); RETURN_IF_FAIL(size > 0 && size < SURFACE_MAX_SIZE); producer_->SetSize(size); } uint32_t SurfaceImpl::GetSize() { RETURN_VAL_IF_FAIL(producer_, 0); return producer_->GetSize(); } void SurfaceImpl::SetUsage(uint32_t usage) { RETURN_IF_FAIL(producer_); RETURN_IF_FAIL(usage < BUFFER_CONSUMER_USAGE_MAX); producer_->SetUsage(usage); } uint32_t SurfaceImpl::GetUsage() { uint32_t usage = producer_->GetUsage(); return usage; } void SurfaceImpl::SetQueueSize(uint8_t queueSize) { RETURN_IF_FAIL(producer_); RETURN_IF_FAIL(queueSize >= SURFACE_MIN_QUEUE_SIZE && queueSize <= SURFACE_MAX_QUEUE_SIZE); producer_->SetQueueSize(queueSize); } uint8_t SurfaceImpl::GetQueueSize() { RETURN_VAL_IF_FAIL(producer_, SURFACE_ERROR_INVAILD_PARAM); uint8_t queueSize = producer_->GetQueueSize(); return queueSize; } void SurfaceImpl::SetUserData(const std::string& key, const std::string& value) { RETURN_IF_FAIL(producer_ != nullptr); producer_->SetUserData(key, value); } std::string SurfaceImpl::GetUserData(const std::string& key) { RETURN_VAL_IF_FAIL(producer_ != nullptr, std::string()); return producer_->GetUserData(key); } SurfaceBuffer* SurfaceImpl::RequestBuffer(uint8_t wait) { RETURN_VAL_IF_FAIL(producer_, nullptr); return producer_->RequestBuffer(wait); } int32_t SurfaceImpl::FlushBuffer(SurfaceBuffer* buffer) { RETURN_VAL_IF_FAIL(producer_, SURFACE_ERROR_INVAILD_PARAM); RETURN_VAL_IF_FAIL(buffer != nullptr, SURFACE_ERROR_INVAILD_PARAM); SurfaceBufferImpl* liteBuffer = reinterpret_cast(buffer); return producer_->FlushBuffer(liteBuffer); } SurfaceBuffer* SurfaceImpl::AcquireBuffer() { RETURN_VAL_IF_FAIL(consumer_, nullptr); return consumer_->AcquireBuffer(); } bool SurfaceImpl::ReleaseBuffer(SurfaceBuffer* buffer) { RETURN_VAL_IF_FAIL(consumer_, false); SurfaceBufferImpl* liteBuffer = reinterpret_cast(buffer); return consumer_->ReleaseBuffer(*liteBuffer); } void SurfaceImpl::CancelBuffer(SurfaceBuffer* buffer) { RETURN_IF_FAIL(producer_); RETURN_IF_FAIL(buffer != nullptr); SurfaceBufferImpl* liteBuffer = reinterpret_cast(buffer); producer_->Cancel(liteBuffer); } void SurfaceImpl::RegisterConsumerListener(IBufferConsumerListener& listener) { RETURN_IF_FAIL(producer_); BufferQueueProducer* bufferQueueProducer = reinterpret_cast(producer_); bufferQueueProducer->RegisterConsumerListener(listener); } void SurfaceImpl::UnregisterConsumerListener() { RETURN_IF_FAIL(producer_); BufferQueueProducer* bufferQueueProducer = reinterpret_cast(producer_); bufferQueueProducer->UnregisterConsumerListener(); } void SurfaceImpl::WriteIoIpcIo(IpcIo& io) { IpcIoPushSvc(&io, &sid_); } int32_t SurfaceImpl::IpcRequestHandler(const IpcContext* context, void* ipcMsg, IpcIo* io, void* arg) { BufferQueueProducer* product = (BufferQueueProducer*) arg; return product->OnIpcMsg(ipcMsg, io); } int32_t SurfaceImpl::DoIpcMsg(void* ipcMsg, IpcIo* io) { RETURN_VAL_IF_FAIL(producer_, SURFACE_ERROR_INVAILD_PARAM); RETURN_VAL_IF_FAIL(ipcMsg != nullptr, SURFACE_ERROR_INVAILD_PARAM); RETURN_VAL_IF_FAIL(io != nullptr, SURFACE_ERROR_INVAILD_PARAM); BufferQueueProducer* bufferQueueProducer = reinterpret_cast(producer_); return bufferQueueProducer->OnIpcMsg(ipcMsg, io); } Surface* SurfaceImpl::GenericSurfaceByIpcIo(IpcIo& io) { SvcIdentity* sid = IpcIoPopSvc(&io); if (sid != NULL) { SurfaceImpl* surface = new SurfaceImpl(*sid); #ifdef __LINUX__ BinderAcquire(sid->ipcContext, sid->handle); free(sid); sid = nullptr; #endif if (surface != nullptr) { if (surface->Init()) { return surface; } else { HILOG_ERROR(HILOG_MODULE_GRAPHIC, "surface init failed"); delete surface; } } } return nullptr; } } // namespace OHOS