• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "wl_dma_buffer_factory.h"
17 
18 #include <cinttypes>
19 #include <map>
20 
21 #include <display_type.h>
22 #include <drm_fourcc.h>
23 #include <promise.h>
24 
25 #include "wayland-util.h"
26 #include "window_manager_hilog.h"
27 #include "wl_display.h"
28 
29 namespace OHOS {
30 namespace {
31 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0, "WMWlDMABufferFactory" };
32 std::map<struct zwp_linux_buffer_params_v1 *, sptr<Promise<struct wl_buffer *>>> g_bufferPromises;
33 constexpr int32_t STRIDE_NUM = 4;
34 constexpr int32_t MODIFY_OFFSET = 32;
35 constexpr int32_t BITS_OFFSET_32 = 32;
36 }
37 
GetInstance()38 sptr<WlDMABufferFactory> WlDMABufferFactory::GetInstance()
39 {
40     if (instance == nullptr) {
41         static std::mutex mutex;
42         std::lock_guard<std::mutex> lock(mutex);
43         if (instance == nullptr) {
44             instance = new WlDMABufferFactory();
45         }
46     }
47     return instance;
48 }
49 
Init()50 void WlDMABufferFactory::Init()
51 {
52     delegator.Dep<WaylandService>()->OnAppear(&WlDMABufferFactory::OnAppear);
53 }
54 
Deinit()55 void WlDMABufferFactory::Deinit()
56 {
57     if (dmabuf != nullptr) {
58         zwp_linux_dmabuf_v1_destroy(dmabuf);
59         dmabuf = nullptr;
60     }
61 }
62 
OnAppear(const GetServiceFunc get,const std::string & iname,uint32_t ver)63 void WlDMABufferFactory::OnAppear(const GetServiceFunc get, const std::string &iname, uint32_t ver)
64 {
65     if (iname == "zwp_linux_dmabuf_v1") {
66         constexpr uint32_t dmabufVersion = 3;
67         auto ret = get(&zwp_linux_dmabuf_v1_interface, dmabufVersion);
68         dmabuf = static_cast<struct zwp_linux_dmabuf_v1 *>(ret);
69     }
70 }
71 
72 namespace {
Success(void *,struct zwp_linux_buffer_params_v1 * param,struct wl_buffer * buffer)73 void Success(void *, struct zwp_linux_buffer_params_v1 *param, struct wl_buffer *buffer)
74 {
75     WMLOGFI("Success");
76     g_bufferPromises[param]->Resolve(buffer);
77 }
78 
Failure(void *,struct zwp_linux_buffer_params_v1 * param)79 void Failure(void *, struct zwp_linux_buffer_params_v1 *param)
80 {
81     WMLOGFI("Failure");
82     g_bufferPromises[param]->Resolve(nullptr);
83 }
84 } // namespace
85 
CreateParam(BufferHandle * handle)86 struct zwp_linux_buffer_params_v1 *WlDMABufferFactory::CreateParam(BufferHandle *handle)
87 {
88     auto display = delegator.Dep<WlDisplay>();
89     if (dmabuf == nullptr) {
90         WMLOGFE("dmabuf is nullptr");
91         return nullptr;
92     }
93 
94     auto param = zwp_linux_dmabuf_v1_create_params(dmabuf);
95     if (param == nullptr) {
96         auto err = display->GetError();
97         WMLOGFE("zwp_linux_dmabuf_v1_create_params failed with %{public}s", strerror(err));
98         return nullptr;
99     }
100 
101     uint64_t modifier = 0;
102     zwp_linux_buffer_params_v1_add(param, handle->fd, 0, 0,
103         handle->stride, modifier >> MODIFY_OFFSET, modifier & 0xffffffff);
104 
105     SendBufferHandle(param, handle);
106 
107     if (display->GetError() != 0) {
108         auto err = display->GetError();
109         WMLOGFE("zwp_linux_buffer_params_v1_add failed with %{public}s", strerror(err));
110         WMLOGFE("args: fd(%{public}d), w(%{public}d)", handle->fd, handle->width);
111         zwp_linux_buffer_params_v1_destroy(param);
112         return nullptr;
113     }
114 
115     const struct zwp_linux_buffer_params_v1_listener listener = { Success, Failure };
116     if (zwp_linux_buffer_params_v1_add_listener(param, &listener, nullptr) == -1) {
117         WMLOGFE("zwp_linux_buffer_params_v1_add_listener failed");
118         zwp_linux_buffer_params_v1_destroy(param);
119         return nullptr;
120     }
121     return param;
122 }
123 
124 namespace {
PixelFormatToDrmFormat(int32_t pixelFormat,uint32_t & drmFormat)125 bool PixelFormatToDrmFormat(int32_t pixelFormat, uint32_t &drmFormat)
126 {
127     constexpr struct {
128         int32_t pixelFormat;
129         uint32_t drmFormat;
130     } formatTable[] = {
131         {PIXEL_FMT_RGB_565, DRM_FORMAT_RGB565},
132         {PIXEL_FMT_RGBX_4444, DRM_FORMAT_RGBX4444},
133         {PIXEL_FMT_RGBA_4444, DRM_FORMAT_RGBA4444},
134         {PIXEL_FMT_RGBX_5551, DRM_FORMAT_RGBX5551},
135         {PIXEL_FMT_RGBA_5551, DRM_FORMAT_RGBA5551},
136         {PIXEL_FMT_RGBX_8888, DRM_FORMAT_RGBX8888},
137         {PIXEL_FMT_RGBA_8888, DRM_FORMAT_RGBA8888},
138         {PIXEL_FMT_RGB_888, DRM_FORMAT_RGB888},
139         {PIXEL_FMT_BGR_565, DRM_FORMAT_BGR565},
140         {PIXEL_FMT_BGRX_4444, DRM_FORMAT_BGRX4444},
141         {PIXEL_FMT_BGRA_4444, DRM_FORMAT_BGRA4444},
142         {PIXEL_FMT_BGRX_5551, DRM_FORMAT_BGRX5551},
143         {PIXEL_FMT_BGRA_5551, DRM_FORMAT_BGRA5551},
144         {PIXEL_FMT_BGRX_8888, DRM_FORMAT_BGRX8888},
145         {PIXEL_FMT_BGRA_8888, DRM_FORMAT_BGRA8888},
146         {PIXEL_FMT_YUV_422_I, DRM_FORMAT_YUV422},
147         {PIXEL_FMT_YUYV_422_PKG, DRM_FORMAT_YUYV},
148         {PIXEL_FMT_UYVY_422_PKG, DRM_FORMAT_UYVY},
149         {PIXEL_FMT_YVYU_422_PKG, DRM_FORMAT_YVYU},
150         {PIXEL_FMT_VYUY_422_PKG, DRM_FORMAT_VYUY},
151         {PIXEL_FMT_YCBCR_420_SP, DRM_FORMAT_NV12},
152         {PIXEL_FMT_YCRCB_420_SP, DRM_FORMAT_NV21},
153         {PIXEL_FMT_YCBCR_420_P, DRM_FORMAT_YUV420},
154     };
155 
156     for (const auto &fmt : formatTable) {
157         if (fmt.pixelFormat == pixelFormat) {
158             drmFormat = fmt.drmFormat;
159             return true;
160         }
161     }
162     return false;
163 }
164 } // namespace
165 
SendBufferHandle(zwp_linux_buffer_params_v1 * param,BufferHandle * handle)166 void WlDMABufferFactory::SendBufferHandle(zwp_linux_buffer_params_v1 *param, BufferHandle *handle)
167 {
168     auto display = delegator.Dep<WlDisplay>();
169     wl_array reservefds;
170     wl_array reserveints;
171 
172     WMLOGFI("BufferHandle->fd = %{public}d", handle->fd);
173     WMLOGFI("BufferHandle->width = %{public}d", handle->width);
174     WMLOGFI("BufferHandle->stride = %{public}d", handle->stride);
175     WMLOGFI("BufferHandle->height = %{public}d", handle->height);
176     WMLOGFI("BufferHandle->size = %{public}d", handle->size);
177     WMLOGFI("BufferHandle->format = %{public}d", handle->format);
178     WMLOGFI("BufferHandle->usage = %{public}" PRIu64 ", %{public}u, %{public}u",
179         handle->usage, (uint32_t)(handle->usage >> BITS_OFFSET_32), (uint32_t)(handle->usage & 0xFFFFFFFF));
180     WMLOGFI("BufferHandle->phyAddr = %{public}" PRIu64 ", %{public}u, %{public}u",
181         handle->phyAddr, (uint32_t)(handle->phyAddr >> BITS_OFFSET_32), (uint32_t)(handle->phyAddr & 0xFFFFFFFF));
182     WMLOGFI("BufferHandle->key = %{public}d", handle->key);
183 
184     WMLOGFI("BufferHandle->reserveFds = %{public}u", handle->reserveFds);
185     WMLOGFI("BufferHandle->reserveInts = %{public}u", handle->reserveInts);
186 
187     wl_array_init(&reservefds);
188     for (int i = 0; i < handle->reserveFds; i++) {
189         uint32_t *p = (uint32_t *)wl_array_add(&reservefds, sizeof(uint32_t));
190         if (p != nullptr) {
191             *p = handle->reserve[i];
192         }
193     }
194 
195     wl_array_init(&reserveints);
196     for (int i = 0; i < handle->reserveInts; i++) {
197         uint32_t *p = (uint32_t *)wl_array_add(&reserveints, sizeof(uint32_t));
198         if (p != nullptr) {
199             *p = handle->reserve[i + handle->reserveFds];
200         }
201     }
202 
203     zwp_linux_buffer_params_v1_add_buffer_handle(param,
204         handle->fd, handle->width, handle->stride, handle->height,
205         handle->size, handle->format, handle->usage >> BITS_OFFSET_32, handle->usage & 0xFFFFFFFF,
206         handle->phyAddr >> BITS_OFFSET_32, handle->phyAddr & 0xFFFFFFFF, handle->key,
207         &reservefds, &reserveints);
208 }
209 
Create(BufferHandle * handle)210 sptr<WlBuffer> WlDMABufferFactory::Create(BufferHandle *handle)
211 {
212     auto display = delegator.Dep<WlDisplay>();
213     uint32_t drmFormat;
214 
215     if (handle == nullptr) {
216         WMLOGFE("handle == nullptr");
217         return nullptr;
218     }
219 
220     if (PixelFormatToDrmFormat(handle->format, drmFormat) == false) {
221         WMLOGFE("PixelFormatToDrmFormat failed");
222         return nullptr;
223     }
224 
225     auto param = CreateParam(handle);
226     if (param == nullptr) {
227         return nullptr;
228     }
229 
230     // add death listener before send, and remove before erase(promise destroy)
231     g_bufferPromises[param] = new Promise<struct wl_buffer *>();
232     auto dl = display->AddDispatchDeathListener([&]() { g_bufferPromises[param]->Resolve(nullptr); });
233 
234     constexpr uint32_t flags = 0;
235     zwp_linux_buffer_params_v1_create(param, handle->width, handle->height, drmFormat, flags);
236     display->Flush(); // send request
237 
238     auto buffer = g_bufferPromises[param]->Await();
239     display->RemoveDispatchDeathListener(dl);
240     g_bufferPromises.erase(param);
241     if (display->GetError() != 0) {
242         WMLOGFE("zwp_linux_buffer_params_v1_create failed with %{public}d", display->GetError());
243         WMLOGFE("args: (%{public}dx%{public}d), format(0x%{public}x), flags(0x%{public}x)",
244             handle->width, handle->height, drmFormat, flags);
245         zwp_linux_buffer_params_v1_destroy(param);
246         return nullptr;
247     }
248 
249     zwp_linux_buffer_params_v1_destroy(param);
250     display->Sync();
251     if (display->GetError() != 0) {
252         WMLOGFW("zwp_linux_buffer_params_v1_destroy failed with %{public}d", display->GetError());
253     }
254 
255     if (buffer == nullptr) {
256         WMLOGFE("buffer is nullptr");
257         return nullptr;
258     }
259 
260     sptr<WlBuffer> ret = new WlBuffer(buffer);
261     if (ret == nullptr) {
262         WMLOGFE("new WlBuffer failed");
263         return nullptr;
264     }
265     return ret;
266 }
267 } // namespace OHOS
268