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#include "surface_impl.h"
16#include <unistd.h>
17#include "buffer_client_producer.h"
18#include "buffer_common.h"
19#include "buffer_manager.h"
20#include "buffer_queue_consumer.h"
21#include "buffer_queue_producer.h"
22#include "surface_buffer_impl.h"
23
24namespace OHOS {
25SurfaceImpl::SurfaceImpl()
26    : consumer_(nullptr), producer_(nullptr), IsConsumer_(true)
27{
28    sid_ = {
29        .handle = 0,
30        .token = 0
31    };
32}
33
34SurfaceImpl::SurfaceImpl(const SvcIdentity& sid)
35    : sid_(sid), consumer_(nullptr), producer_(nullptr), IsConsumer_(false)
36{
37}
38
39SurfaceImpl::~SurfaceImpl()
40{
41    if (consumer_ != nullptr) {
42        delete consumer_;
43        consumer_ = nullptr;
44    }
45    if (producer_ != nullptr) {
46        delete producer_;
47        producer_ = nullptr;
48    }
49    if (sid_.handle != 0) {
50        ReleaseSvc(sid_);
51    }
52}
53
54bool SurfaceImpl::Init()
55{
56    if (!BufferManager::GetInstance()->Init()) {
57        GRAPHIC_LOGE("Failed init buffer manager");
58        return false;
59    }
60    if (IsConsumer_) {
61        BufferQueue* bufferQueue = new BufferQueue();
62        if (bufferQueue == nullptr) {
63            GRAPHIC_LOGE("Surface consumer(buffer queue) init failed.");
64            return false;
65        }
66
67        if (!bufferQueue->Init()) {
68            GRAPHIC_LOGE("Buffer queue init failed.");
69            delete bufferQueue;
70            return false;
71        }
72
73        producer_ = new BufferQueueProducer(bufferQueue);
74        if (producer_ == nullptr) {
75            GRAPHIC_LOGE("Surface consumer(producer) init failed.");
76            delete bufferQueue;
77            return false;
78        }
79        consumer_ = new BufferQueueConsumer(*bufferQueue);
80        if (consumer_ == nullptr) {
81            GRAPHIC_LOGE("Surface consumer(consumer) init failed.");
82            delete producer_;
83            producer_ = nullptr;
84            return false;
85        }
86        objectStub_.func = IpcRequestHandler;
87        objectStub_.args = reinterpret_cast<void*>(producer_);
88        objectStub_.isRemote = false;
89        sid_.handle = IPC_INVALID_HANDLE;
90        sid_.token  = SERVICE_TYPE_ANONYMOUS;
91        sid_.cookie = reinterpret_cast<uintptr_t>(&objectStub_);
92    } else {
93        producer_ = new BufferClientProducer(sid_);
94        if (producer_ == nullptr) {
95            GRAPHIC_LOGE("Surface producer init failed.");
96            return false;
97        }
98    }
99    return true;
100}
101
102void SurfaceImpl::SetWidthAndHeight(uint32_t width, uint32_t height)
103{
104    RETURN_IF_FAIL(producer_ != nullptr);
105    RETURN_IF_FAIL(width > 0 && width <= SURFACE_MAX_WIDTH);
106    RETURN_IF_FAIL(height > 0 && height <= SURFACE_MAX_HEIGHT);
107    producer_->SetWidthAndHeight(width, height);
108}
109
110uint32_t SurfaceImpl::GetWidth()
111{
112    RETURN_VAL_IF_FAIL(producer_, 0);
113    return producer_->GetWidth();
114}
115
116uint32_t SurfaceImpl::GetHeight()
117{
118    RETURN_VAL_IF_FAIL(producer_, 0);
119    return producer_->GetHeight();
120}
121
122void SurfaceImpl::SetFormat(uint32_t format)
123{
124    RETURN_IF_FAIL(producer_);
125    producer_->SetFormat(format);
126}
127
128uint32_t SurfaceImpl::GetFormat()
129{
130    RETURN_VAL_IF_FAIL(producer_, 0);
131    return producer_->GetFormat();
132}
133
134void SurfaceImpl::SetStrideAlignment(uint32_t strideAlignment)
135{
136    RETURN_IF_FAIL(producer_);
137    RETURN_IF_FAIL(strideAlignment >= SURFACE_MIN_STRIDE_ALIGNMENT && strideAlignment <= SURFACE_MAX_STRIDE_ALIGNMENT);
138    producer_->SetStrideAlignment(strideAlignment);
139}
140
141uint32_t SurfaceImpl::GetStrideAlignment()
142{
143    RETURN_VAL_IF_FAIL(producer_, 0);
144    return producer_->GetStrideAlignment();
145}
146
147uint32_t SurfaceImpl::GetStride()
148{
149    RETURN_VAL_IF_FAIL(producer_, 0);
150    return producer_->GetStride();
151}
152
153void SurfaceImpl::SetSize(uint32_t size)
154{
155    RETURN_IF_FAIL(producer_);
156    RETURN_IF_FAIL(size > 0 && size < SURFACE_MAX_SIZE);
157    producer_->SetSize(size);
158}
159
160uint32_t SurfaceImpl::GetSize()
161{
162    RETURN_VAL_IF_FAIL(producer_, 0);
163    return producer_->GetSize();
164}
165
166void SurfaceImpl::SetUsage(uint32_t usage)
167{
168    RETURN_IF_FAIL(producer_);
169    RETURN_IF_FAIL(usage < BUFFER_CONSUMER_USAGE_MAX);
170    producer_->SetUsage(usage);
171}
172
173uint32_t SurfaceImpl::GetUsage()
174{
175    uint32_t usage = producer_->GetUsage();
176    return usage;
177}
178
179void SurfaceImpl::SetQueueSize(uint8_t queueSize)
180{
181    RETURN_IF_FAIL(producer_);
182    RETURN_IF_FAIL(queueSize >= SURFACE_MIN_QUEUE_SIZE && queueSize <= SURFACE_MAX_QUEUE_SIZE);
183    producer_->SetQueueSize(queueSize);
184}
185
186uint8_t SurfaceImpl::GetQueueSize()
187{
188    RETURN_VAL_IF_FAIL(producer_, SURFACE_ERROR_INVALID_PARAM);
189    uint8_t queueSize = producer_->GetQueueSize();
190    return queueSize;
191}
192
193void SurfaceImpl::SetUserData(const std::string& key, const std::string& value)
194{
195    RETURN_IF_FAIL(producer_ != nullptr);
196    producer_->SetUserData(key, value);
197}
198
199std::string SurfaceImpl::GetUserData(const std::string& key)
200{
201    RETURN_VAL_IF_FAIL(producer_ != nullptr, std::string());
202    return producer_->GetUserData(key);
203}
204
205SurfaceBuffer* SurfaceImpl::RequestBuffer(uint8_t wait)
206{
207    RETURN_VAL_IF_FAIL(producer_, nullptr);
208    return producer_->RequestBuffer(wait);
209}
210
211int32_t SurfaceImpl::FlushBuffer(SurfaceBuffer* buffer)
212{
213    RETURN_VAL_IF_FAIL(producer_, SURFACE_ERROR_INVALID_PARAM);
214    RETURN_VAL_IF_FAIL(buffer != nullptr, SURFACE_ERROR_INVALID_PARAM);
215    SurfaceBufferImpl* liteBuffer = reinterpret_cast<SurfaceBufferImpl*>(buffer);
216    return producer_->FlushBuffer(liteBuffer);
217}
218
219SurfaceBuffer* SurfaceImpl::AcquireBuffer()
220{
221    RETURN_VAL_IF_FAIL(consumer_, nullptr);
222    return consumer_->AcquireBuffer();
223}
224
225bool SurfaceImpl::ReleaseBuffer(SurfaceBuffer* buffer)
226{
227    RETURN_VAL_IF_FAIL(consumer_, false);
228    SurfaceBufferImpl* liteBuffer = reinterpret_cast<SurfaceBufferImpl*>(buffer);
229    return consumer_->ReleaseBuffer(*liteBuffer);
230}
231
232void SurfaceImpl::CancelBuffer(SurfaceBuffer* buffer)
233{
234    RETURN_IF_FAIL(producer_);
235    RETURN_IF_FAIL(buffer != nullptr);
236    SurfaceBufferImpl* liteBuffer = reinterpret_cast<SurfaceBufferImpl*>(buffer);
237    producer_->Cancel(liteBuffer);
238}
239
240void SurfaceImpl::RegisterConsumerListener(IBufferConsumerListener& listener)
241{
242    RETURN_IF_FAIL(producer_);
243    BufferQueueProducer* bufferQueueProducer = reinterpret_cast<BufferQueueProducer *>(producer_);
244    bufferQueueProducer->RegisterConsumerListener(listener);
245}
246
247void SurfaceImpl::UnregisterConsumerListener()
248{
249    RETURN_IF_FAIL(producer_);
250    BufferQueueProducer* bufferQueueProducer = reinterpret_cast<BufferQueueProducer *>(producer_);
251    bufferQueueProducer->UnregisterConsumerListener();
252}
253
254void SurfaceImpl::WriteIoIpcIo(IpcIo& io)
255{
256    WriteRemoteObject(&io, &sid_);
257}
258
259int32_t SurfaceImpl::IpcRequestHandler(uint32_t code, IpcIo* data, IpcIo* reply, MessageOption option)
260{
261    BufferQueueProducer* product = reinterpret_cast<BufferQueueProducer*>(option.args);
262    return product->OnIpcMsg(code, data, reply, option);
263}
264
265int32_t SurfaceImpl::DoIpcMsg(uint32_t code, IpcIo* data, IpcIo* reply, MessageOption option)
266{
267    RETURN_VAL_IF_FAIL(producer_, SURFACE_ERROR_INVALID_PARAM);
268    RETURN_VAL_IF_FAIL(data != nullptr, SURFACE_ERROR_INVALID_PARAM);
269    BufferQueueProducer* bufferQueueProducer = reinterpret_cast<BufferQueueProducer*>(producer_);
270    return bufferQueueProducer->OnIpcMsg(code, data, reply, option);
271}
272
273Surface* SurfaceImpl::GenericSurfaceByIpcIo(IpcIo& io)
274{
275    SvcIdentity sid;
276    bool ret = ReadRemoteObject(&io, &sid);
277    if (ret) {
278        SurfaceImpl* surface = new SurfaceImpl(sid);
279        if (surface != nullptr) {
280            if (surface->Init()) {
281                return reinterpret_cast<Surface *>(surface);
282            } else {
283                GRAPHIC_LOGE("surface init failed");
284                delete surface;
285            }
286        }
287    }
288    return nullptr;
289}
290} // namespace OHOS
291