1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
18 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
19 #include <hidl/LegacySupport.h>
20 #include <qemu_pipe_bp.h>
21 
22 #include "glUtils.h"
23 #include "cb_handle_30.h"
24 #include "host_connection_session.h"
25 #include "types.h"
26 #include "debug.h"
27 
28 const int kOMX_COLOR_FormatYUV420Planar = 19;
29 
30 using ::android::hardware::hidl_handle;
31 using ::android::hardware::hidl_vec;
32 using ::android::hardware::hidl_bitfield;
33 using ::android::hardware::Return;
34 using ::android::hardware::Void;
35 
36 using ::android::hardware::graphics::common::V1_2::PixelFormat;
37 using ::android::hardware::graphics::common::V1_0::BufferUsage;
38 
39 namespace AllocatorV3 = ::android::hardware::graphics::allocator::V3_0;
40 namespace MapperV3 = ::android::hardware::graphics::mapper::V3_0;
41 
42 using IAllocator3 = AllocatorV3::IAllocator;
43 using IMapper3 = MapperV3::IMapper;
44 using Error3 = MapperV3::Error;
45 using BufferDescriptorInfo = IMapper3::BufferDescriptorInfo;
46 
47 class GoldfishAllocator : public IAllocator3 {
48 public:
GoldfishAllocator()49     GoldfishAllocator() : m_hostConn(HostConnection::createUnique()) {}
50 
dumpDebugInfo(dumpDebugInfo_cb hidl_cb)51     Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
52         hidl_cb("GoldfishAllocator::dumpDebugInfo is not implemented");
53         return {};
54     }
55 
allocate(const hidl_vec<uint32_t> & rawDescriptor,uint32_t count,allocate_cb hidl_cb)56     Return<void> allocate(const hidl_vec<uint32_t>& rawDescriptor,
57                           uint32_t count,
58                           allocate_cb hidl_cb) {
59         uint32_t stride = 0;
60         std::vector<cb_handle_30_t*> cbs;
61         cbs.reserve(count);
62 
63         const Error3 e = allocateImpl(rawDescriptor, count, &stride, &cbs);
64         if (e == Error3::NONE) {
65             hidl_vec<hidl_handle> handles(cbs.cbegin(), cbs.cend());
66             hidl_cb(Error3::NONE, stride, handles);
67         } else {
68             hidl_cb(e, 0, {});
69         }
70 
71         for (cb_handle_30_t* cb : cbs) {
72             freeCb(std::unique_ptr<cb_handle_30_t>(cb));
73         }
74 
75         return {};
76     }
77 
78 private:
79     // this function should be in sync with GoldfishMapper::isSupportedImpl
allocateImpl(const hidl_vec<uint32_t> & rawDescriptor,uint32_t count,uint32_t * pStride,std::vector<cb_handle_30_t * > * cbs)80     Error3 allocateImpl(const hidl_vec<uint32_t>& rawDescriptor,
81                         uint32_t count,
82                         uint32_t* pStride,
83                         std::vector<cb_handle_30_t*>* cbs) {
84         BufferDescriptorInfo descriptor;
85         if (!decodeBufferDescriptorInfo(rawDescriptor, &descriptor)) {
86             RETURN_ERROR(Error3::BAD_DESCRIPTOR);
87         }
88 
89         if (!descriptor.width) { RETURN_ERROR(Error3::UNSUPPORTED); }
90         if (!descriptor.height) { RETURN_ERROR(Error3::UNSUPPORTED); }
91         if (descriptor.layerCount != 1) { RETURN_ERROR(Error3::UNSUPPORTED); }
92 
93         const uint32_t usage = descriptor.usage;
94         const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
95         const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
96         const bool usageHwCamWrite = usage & BufferUsage::CAMERA_OUTPUT;
97         const bool usageHwCamRead = usage & BufferUsage::CAMERA_INPUT;
98 
99         int bpp = 1;
100         int glFormat = 0;
101         int glType = 0;
102         int align = 1;
103         bool yuv_format = false;
104         EmulatorFrameworkFormat emulatorFrameworkFormat =
105             EmulatorFrameworkFormat::GL_COMPATIBLE;
106 
107         PixelFormat format;
108         Error3 e = getBufferFormat(descriptor.format, usage, &format);
109         if (e != Error3::NONE) {
110             ALOGE("%s:%d Unsupported format: frameworkFormat=%d, usage=%x",
111                   __func__, __LINE__, descriptor.format, usage);
112             return e;
113         }
114 
115         switch (format) {
116         case PixelFormat::RGBA_8888:
117         case PixelFormat::RGBX_8888:
118         case PixelFormat::BGRA_8888:
119             bpp = 4;
120             glFormat = GL_RGBA;
121             glType = GL_UNSIGNED_BYTE;
122             break;
123 
124         case PixelFormat::RGB_888:
125             if (usage & (BufferUsage::GPU_TEXTURE |
126                          BufferUsage::GPU_RENDER_TARGET |
127                          BufferUsage::COMPOSER_OVERLAY |
128                          BufferUsage::COMPOSER_CLIENT_TARGET)) {
129                 RETURN_ERROR(Error3::UNSUPPORTED);
130             } else {
131                 bpp = 3;
132                 glFormat = GL_RGB;
133                 glType = GL_UNSIGNED_BYTE;
134             }
135             break;
136 
137         case PixelFormat::RGB_565:
138             bpp = 2;
139             glFormat = GL_RGB565;
140             glType = GL_UNSIGNED_SHORT_5_6_5;
141             break;
142 
143         case PixelFormat::RGBA_FP16:
144             bpp = 8;
145             glFormat = GL_RGBA16F;
146             glType = GL_HALF_FLOAT;
147             break;
148 
149         case PixelFormat::RGBA_1010102:
150             bpp = 4;
151             glFormat = GL_RGB10_A2;
152             glType = GL_UNSIGNED_INT_2_10_10_10_REV;
153             break;
154 
155         case PixelFormat::RAW16:
156         case PixelFormat::Y16:
157             bpp = 2;
158             align = 16 * bpp;
159             if (!((usageSwRead || usageHwCamRead) && (usageSwWrite || usageHwCamWrite))) {
160                 // Raw sensor data or Y16 only goes between camera and CPU
161                 RETURN_ERROR(Error3::UNSUPPORTED);
162             }
163             // Not expecting to actually create any GL surfaces for this
164             glFormat = GL_LUMINANCE;
165             glType = GL_UNSIGNED_SHORT;
166             break;
167 
168         case PixelFormat::BLOB:
169             if (!usageSwRead) {
170                 // Blob data cannot be used by HW other than camera emulator
171                 // But there is a CTS test trying to have access to it
172                 // BUG: https://buganizer.corp.google.com/issues/37719518
173                 RETURN_ERROR(Error3::UNSUPPORTED);
174             }
175             // Not expecting to actually create any GL surfaces for this
176             glFormat = GL_LUMINANCE;
177             glType = GL_UNSIGNED_BYTE;
178             break;
179 
180         case PixelFormat::YCRCB_420_SP:
181             yuv_format = true;
182             // Not expecting to actually create any GL surfaces for this
183             break;
184 
185         case PixelFormat::YV12:
186             align = 16;
187             yuv_format = true;
188             // We are going to use RGB8888 on the host for Vulkan
189             glFormat = GL_RGBA;
190             glType = GL_UNSIGNED_BYTE;
191             emulatorFrameworkFormat = EmulatorFrameworkFormat::YV12;
192             break;
193 
194         case PixelFormat::YCBCR_420_888:
195             yuv_format = true;
196             // We are going to use RGBA 8888 on the host
197             glFormat = GL_RGBA;
198             glType = GL_UNSIGNED_BYTE;
199             emulatorFrameworkFormat = EmulatorFrameworkFormat::YUV_420_888;
200             break;
201 
202         default:
203             ALOGE("%s:%d Unsupported format: format=%d, frameworkFormat=%d, usage=%x",
204                   __func__, __LINE__, format, descriptor.format, usage);
205             RETURN_ERROR(Error3::UNSUPPORTED);
206         }
207 
208         const size_t align1 = align - 1;
209         const uint32_t width = descriptor.width;
210         const uint32_t height = descriptor.height;
211         uint32_t stride;
212         size_t bufferSize;
213 
214         if (yuv_format) {
215             const size_t yStride = (width * bpp + align1) & ~align1;
216             const size_t uvStride = (yStride / 2 + align1) & ~align1;
217             const size_t uvHeight = height / 2;
218             bufferSize = yStride * height + 2 * (uvHeight * uvStride);
219             stride = yStride / bpp;
220         } else {
221             const size_t bpr = (width * bpp + align1) & ~align1;
222             bufferSize = bpr * height;
223             stride = bpr / bpp;
224         }
225 
226         *pStride = stride;
227 
228         return allocateImpl2(usage,
229                              width, height,
230                              format, emulatorFrameworkFormat,
231                              glFormat, glType,
232                              bufferSize,
233                              bpp, stride,
234                              count, cbs);
235     }
236 
allocateImpl2(const uint32_t usage,const uint32_t width,const uint32_t height,const PixelFormat format,const EmulatorFrameworkFormat emulatorFrameworkFormat,const int glFormat,const int glType,const size_t bufferSize,const uint32_t bytesPerPixel,const uint32_t stride,const uint32_t count,std::vector<cb_handle_30_t * > * cbs)237     Error3 allocateImpl2(const uint32_t usage,
238                          const uint32_t width, const uint32_t height,
239                          const PixelFormat format,
240                          const EmulatorFrameworkFormat emulatorFrameworkFormat,
241                          const int glFormat, const int glType,
242                          const size_t bufferSize,
243                          const uint32_t bytesPerPixel,
244                          const uint32_t stride,
245                          const uint32_t count,
246                          std::vector<cb_handle_30_t*>* cbs) {
247         for (uint32_t i = 0; i < count; ++i) {
248             cb_handle_30_t* cb;
249             Error3 e = allocateCb(usage,
250                                   width, height,
251                                   format, emulatorFrameworkFormat,
252                                   glFormat, glType,
253                                   bufferSize,
254                                   bytesPerPixel, stride,
255                                   &cb);
256             if (e == Error3::NONE) {
257                 cbs->push_back(cb);
258             } else {
259                 return e;
260             }
261         }
262 
263         RETURN(Error3::NONE);
264     }
265 
266     // see GoldfishMapper::encodeBufferDescriptorInfo
decodeBufferDescriptorInfo(const hidl_vec<uint32_t> & raw,BufferDescriptorInfo * d)267     static bool decodeBufferDescriptorInfo(const hidl_vec<uint32_t>& raw,
268                                            BufferDescriptorInfo* d) {
269         if (raw.size() == 5) {
270             d->width = raw[0];
271             d->height = raw[1];
272             d->layerCount = raw[2];
273             d->format = static_cast<PixelFormat>(raw[3]);
274             d->usage = raw[4];
275 
276             RETURN(true);
277         } else {
278             RETURN_ERROR(false);
279         }
280     }
281 
getBufferFormat(const PixelFormat frameworkFormat,const uint32_t usage,PixelFormat * format)282     static Error3 getBufferFormat(const PixelFormat frameworkFormat,
283                                   const uint32_t usage,
284                                   PixelFormat* format) {
285         if (frameworkFormat == PixelFormat::IMPLEMENTATION_DEFINED) {
286             if (usage & BufferUsage::CAMERA_OUTPUT) {
287                 if (usage & BufferUsage::GPU_TEXTURE) {
288                     // Camera-to-display is RGBA
289                     *format = PixelFormat::RGBA_8888;
290                     RETURN(Error3::NONE);
291                 } else if (usage & BufferUsage::VIDEO_ENCODER) {
292                     // Camera-to-encoder is NV21
293                     *format = PixelFormat::YCRCB_420_SP;
294                     RETURN(Error3::NONE);
295                 }
296             }
297             RETURN_ERROR(Error3::UNSUPPORTED);
298         } else if (static_cast<int>(frameworkFormat) == kOMX_COLOR_FormatYUV420Planar &&
299                (usage & BufferUsage::GPU_DATA_BUFFER)) {
300             ALOGW("gralloc_alloc: Requested OMX_COLOR_FormatYUV420Planar, given "
301               "YCbCr_420_888, taking experimental path. "
302               "usage=%x", usage);
303             *format = PixelFormat::YCBCR_420_888;
304             RETURN(Error3::NONE);
305         } else  {
306             *format = frameworkFormat;
307             RETURN(Error3::NONE);
308         }
309     }
310 
needHostCb(const uint32_t usage,const PixelFormat format)311     static bool needHostCb(const uint32_t usage, const PixelFormat format) {
312         return ((usage & BufferUsage::GPU_DATA_BUFFER)
313                    || (format != PixelFormat::BLOB &&
314                        format != PixelFormat::RAW16 &&
315                        format != PixelFormat::Y16))
316                && (usage & (BufferUsage::GPU_TEXTURE
317                             | BufferUsage::GPU_RENDER_TARGET
318                             | BufferUsage::COMPOSER_OVERLAY
319                             | BufferUsage::VIDEO_ENCODER
320                             | BufferUsage::COMPOSER_CLIENT_TARGET
321                             | BufferUsage::CPU_READ_MASK));
322     }
323 
allocateCb(const uint32_t usage,const uint32_t width,const uint32_t height,const PixelFormat format,const EmulatorFrameworkFormat emulatorFrameworkFormat,const int glFormat,const int glType,const size_t bufferSize,const int32_t bytesPerPixel,const int32_t stride,cb_handle_30_t ** cb)324     Error3 allocateCb(const uint32_t usage,
325                       const uint32_t width, const uint32_t height,
326                       const PixelFormat format,
327                       const EmulatorFrameworkFormat emulatorFrameworkFormat,
328                       const int glFormat, const int glType,
329                       const size_t bufferSize,
330                       const int32_t bytesPerPixel,
331                       const int32_t stride,
332                       cb_handle_30_t** cb) {
333         const HostConnectionSession conn = getHostConnectionSession();
334         ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
335         CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
336 
337         GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
338             rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
339         if (!host_memory_allocator.is_opened()) {
340             RETURN_ERROR(Error3::NO_RESOURCES);
341         }
342 
343         GoldfishAddressSpaceBlock bufferBits;
344         if (host_memory_allocator.hostMalloc(&bufferBits, bufferSize)) {
345             RETURN_ERROR(Error3::NO_RESOURCES);
346         }
347 
348         uint32_t hostHandle = 0;
349         QEMU_PIPE_HANDLE hostHandleRefCountFd = QEMU_PIPE_INVALID_HANDLE;
350         if (needHostCb(usage, format)) {
351             hostHandleRefCountFd = qemu_pipe_open("refcount");
352             if (!qemu_pipe_valid(hostHandleRefCountFd)) {
353                 RETURN_ERROR(Error3::NO_RESOURCES);
354             }
355 
356             const GLenum allocFormat =
357                 (PixelFormat::RGBX_8888 == format) ? GL_RGB : glFormat;
358 
359             hostHandle = rcEnc->rcCreateColorBufferDMA(
360                 rcEnc,
361                 width, height,
362                 allocFormat, static_cast<int>(emulatorFrameworkFormat));
363 
364             if (!hostHandle) {
365                 qemu_pipe_close(hostHandleRefCountFd);
366                 RETURN_ERROR(Error3::NO_RESOURCES);
367             }
368 
369             if (qemu_pipe_write(hostHandleRefCountFd,
370                                 &hostHandle,
371                                 sizeof(hostHandle)) != sizeof(hostHandle)) {
372                 rcEnc->rcCloseColorBuffer(rcEnc, hostHandle);
373                 qemu_pipe_close(hostHandleRefCountFd);
374                 RETURN_ERROR(Error3::NO_RESOURCES);
375             }
376         }
377 
378         std::unique_ptr<cb_handle_30_t> handle =
379             std::make_unique<cb_handle_30_t>(
380                 host_memory_allocator.release(),
381                 hostHandleRefCountFd,
382                 hostHandle,
383                 usage,
384                 width,
385                 height,
386                 static_cast<int>(format),
387                 glFormat,
388                 glType,
389                 bufferSize,
390                 bufferBits.guestPtr(),
391                 bufferBits.size(),
392                 bufferBits.offset(),
393                 bytesPerPixel,
394                 stride);
395 
396         bufferBits.release();
397         *cb = handle.release();
398         RETURN(Error3::NONE);
399     }
400 
freeCb(std::unique_ptr<cb_handle_30_t> cb)401     void freeCb(std::unique_ptr<cb_handle_30_t> cb) {
402         // no need to undo .hostMalloc: the kernel will take care of it once the
403         // last bufferFd (duped) is closed.
404 
405         if (qemu_pipe_valid(cb->hostHandleRefCountFd)) {
406             qemu_pipe_close(cb->hostHandleRefCountFd);
407         }
408         GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
409         GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
410     }
411 
getHostConnectionSession() const412     HostConnectionSession getHostConnectionSession() const {
413         return HostConnectionSession(m_hostConn.get());
414     }
415 
416     std::unique_ptr<HostConnection> m_hostConn;
417 };
418 
main(int,char **)419 int main(int, char**) {
420     using ::android::sp;
421 
422     ::android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
423 
424     sp<IAllocator3> allocator(new GoldfishAllocator());
425     if (allocator->registerAsService() != ::android::NO_ERROR) {
426         ALOGE("failed to register graphics [email protected] service");
427         return -EINVAL;
428     }
429 
430     ALOGI("graphics [email protected] service is initialized");
431     ::android::hardware::joinRpcThreadpool();
432 
433     ALOGI("graphics [email protected] service is terminating");
434     return 0;
435 }
436