• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             if (static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format) ==
204                     android::hardware::graphics::common::V1_1::PixelFormat::YCBCR_P010) {
205                 yuv_format = true;
206                 glFormat = GL_RGBA;
207                 glType = GL_UNSIGNED_BYTE;
208                 bpp = 2;
209                 break;
210             }
211 
212             ALOGE("%s:%d Unsupported format: format=%d, frameworkFormat=%d, usage=%x",
213                   __func__, __LINE__, format, descriptor.format, usage);
214             RETURN_ERROR(Error3::UNSUPPORTED);
215         }
216 
217         const size_t align1 = align - 1;
218         const uint32_t width = descriptor.width;
219         const uint32_t height = descriptor.height;
220         uint32_t stride;
221         size_t bufferSize;
222 
223         if (yuv_format) {
224             const size_t yStride = (width * bpp + align1) & ~align1;
225             const size_t uvStride = (yStride / 2 + align1) & ~align1;
226             const size_t uvHeight = height / 2;
227             bufferSize = yStride * height + 2 * (uvHeight * uvStride);
228             stride = yStride / bpp;
229         } else {
230             const size_t bpr = (width * bpp + align1) & ~align1;
231             bufferSize = bpr * height;
232             stride = bpr / bpp;
233         }
234 
235         *pStride = stride;
236 
237         return allocateImpl2(usage,
238                              width, height,
239                              format, emulatorFrameworkFormat,
240                              glFormat, glType,
241                              bufferSize,
242                              bpp, stride,
243                              count, cbs);
244     }
245 
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)246     Error3 allocateImpl2(const uint32_t usage,
247                          const uint32_t width, const uint32_t height,
248                          const PixelFormat format,
249                          const EmulatorFrameworkFormat emulatorFrameworkFormat,
250                          const int glFormat, const int glType,
251                          const size_t bufferSize,
252                          const uint32_t bytesPerPixel,
253                          const uint32_t stride,
254                          const uint32_t count,
255                          std::vector<cb_handle_30_t*>* cbs) {
256         for (uint32_t i = 0; i < count; ++i) {
257             cb_handle_30_t* cb;
258             Error3 e = allocateCb(usage,
259                                   width, height,
260                                   format, emulatorFrameworkFormat,
261                                   glFormat, glType,
262                                   bufferSize,
263                                   bytesPerPixel, stride,
264                                   &cb);
265             if (e == Error3::NONE) {
266                 cbs->push_back(cb);
267             } else {
268                 return e;
269             }
270         }
271 
272         RETURN(Error3::NONE);
273     }
274 
275     // see GoldfishMapper::encodeBufferDescriptorInfo
decodeBufferDescriptorInfo(const hidl_vec<uint32_t> & raw,BufferDescriptorInfo * d)276     static bool decodeBufferDescriptorInfo(const hidl_vec<uint32_t>& raw,
277                                            BufferDescriptorInfo* d) {
278         if (raw.size() == 5) {
279             d->width = raw[0];
280             d->height = raw[1];
281             d->layerCount = raw[2];
282             d->format = static_cast<PixelFormat>(raw[3]);
283             d->usage = raw[4];
284 
285             RETURN(true);
286         } else {
287             RETURN_ERROR(false);
288         }
289     }
290 
getBufferFormat(const PixelFormat frameworkFormat,const uint32_t usage,PixelFormat * format)291     static Error3 getBufferFormat(const PixelFormat frameworkFormat,
292                                   const uint32_t usage,
293                                   PixelFormat* format) {
294         if (frameworkFormat == PixelFormat::IMPLEMENTATION_DEFINED) {
295             if (usage & BufferUsage::CAMERA_OUTPUT) {
296                 if (usage & BufferUsage::GPU_TEXTURE) {
297                     // Camera-to-display is RGBA
298                     *format = PixelFormat::RGBA_8888;
299                     RETURN(Error3::NONE);
300                 } else if (usage & BufferUsage::VIDEO_ENCODER) {
301                     // Camera-to-encoder is NV21
302                     *format = PixelFormat::YCRCB_420_SP;
303                     RETURN(Error3::NONE);
304                 } else {
305                     // b/189957071
306                     *format = PixelFormat::YCBCR_420_888;
307                     RETURN(Error3::NONE);
308                 }
309             }
310             RETURN_ERROR(Error3::UNSUPPORTED);
311         } else if (static_cast<int>(frameworkFormat) == kOMX_COLOR_FormatYUV420Planar &&
312                (usage & BufferUsage::GPU_DATA_BUFFER)) {
313             ALOGW("gralloc_alloc: Requested OMX_COLOR_FormatYUV420Planar, given "
314               "YCbCr_420_888, taking experimental path. "
315               "usage=%x", usage);
316             *format = PixelFormat::YCBCR_420_888;
317             RETURN(Error3::NONE);
318         } else  {
319             *format = frameworkFormat;
320             RETURN(Error3::NONE);
321         }
322     }
323 
needHostCb(const uint32_t usage,const PixelFormat format)324     static bool needHostCb(const uint32_t usage, const PixelFormat format) {
325         if (static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format) ==
326                 android::hardware::graphics::common::V1_1::PixelFormat::YCBCR_P010) {
327             return false;
328         }
329 
330         // b/186585177
331         if ((usage & (BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK)) &&
332                 (0 == (usage & ~(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK)))) {
333             return false;
334         }
335 
336         return ((usage & BufferUsage::GPU_DATA_BUFFER)
337                    || (format != PixelFormat::BLOB &&
338                        format != PixelFormat::RAW16 &&
339                        format != PixelFormat::Y16))
340                && (usage & (BufferUsage::GPU_TEXTURE
341                             | BufferUsage::GPU_RENDER_TARGET
342                             | BufferUsage::COMPOSER_OVERLAY
343                             | BufferUsage::VIDEO_ENCODER
344                             | BufferUsage::COMPOSER_CLIENT_TARGET
345                             | BufferUsage::CPU_READ_MASK));
346     }
347 
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)348     Error3 allocateCb(const uint32_t usage,
349                       const uint32_t width, const uint32_t height,
350                       const PixelFormat format,
351                       const EmulatorFrameworkFormat emulatorFrameworkFormat,
352                       const int glFormat, const int glType,
353                       const size_t bufferSize,
354                       const int32_t bytesPerPixel,
355                       const int32_t stride,
356                       cb_handle_30_t** cb) {
357         const HostConnectionSession conn = getHostConnectionSession();
358         ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
359         CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
360 
361         GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
362             rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
363         if (!host_memory_allocator.is_opened()) {
364             RETURN_ERROR(Error3::NO_RESOURCES);
365         }
366 
367         GoldfishAddressSpaceBlock bufferBits;
368         if (host_memory_allocator.hostMalloc(&bufferBits, bufferSize)) {
369             RETURN_ERROR(Error3::NO_RESOURCES);
370         }
371 
372         uint32_t hostHandle = 0;
373         QEMU_PIPE_HANDLE hostHandleRefCountFd = QEMU_PIPE_INVALID_HANDLE;
374         if (needHostCb(usage, format)) {
375             hostHandleRefCountFd = qemu_pipe_open("refcount");
376             if (!qemu_pipe_valid(hostHandleRefCountFd)) {
377                 RETURN_ERROR(Error3::NO_RESOURCES);
378             }
379 
380             const GLenum allocFormat =
381                 (PixelFormat::RGBX_8888 == format) ? GL_RGB : glFormat;
382 
383             hostHandle = rcEnc->rcCreateColorBufferDMA(
384                 rcEnc,
385                 width, height,
386                 allocFormat, static_cast<int>(emulatorFrameworkFormat));
387 
388             if (!hostHandle) {
389                 qemu_pipe_close(hostHandleRefCountFd);
390                 RETURN_ERROR(Error3::NO_RESOURCES);
391             }
392 
393             if (qemu_pipe_write(hostHandleRefCountFd,
394                                 &hostHandle,
395                                 sizeof(hostHandle)) != sizeof(hostHandle)) {
396                 rcEnc->rcCloseColorBuffer(rcEnc, hostHandle);
397                 qemu_pipe_close(hostHandleRefCountFd);
398                 RETURN_ERROR(Error3::NO_RESOURCES);
399             }
400         }
401 
402         std::unique_ptr<cb_handle_30_t> handle =
403             std::make_unique<cb_handle_30_t>(
404                 host_memory_allocator.release(),
405                 hostHandleRefCountFd,
406                 hostHandle,
407                 usage,
408                 width,
409                 height,
410                 static_cast<int>(format),
411                 glFormat,
412                 glType,
413                 bufferSize,
414                 bufferBits.guestPtr(),
415                 bufferBits.size(),
416                 bufferBits.offset(),
417                 bytesPerPixel,
418                 stride);
419 
420         bufferBits.release();
421         *cb = handle.release();
422         RETURN(Error3::NONE);
423     }
424 
freeCb(std::unique_ptr<cb_handle_30_t> cb)425     void freeCb(std::unique_ptr<cb_handle_30_t> cb) {
426         // no need to undo .hostMalloc: the kernel will take care of it once the
427         // last bufferFd (duped) is closed.
428 
429         if (qemu_pipe_valid(cb->hostHandleRefCountFd)) {
430             qemu_pipe_close(cb->hostHandleRefCountFd);
431         }
432         GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
433         GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
434     }
435 
getHostConnectionSession() const436     HostConnectionSession getHostConnectionSession() const {
437         return HostConnectionSession(m_hostConn.get());
438     }
439 
440     std::unique_ptr<HostConnection> m_hostConn;
441 };
442 
main(int,char **)443 int main(int, char**) {
444     using ::android::sp;
445 
446     ::android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
447 
448     sp<IAllocator3> allocator(new GoldfishAllocator());
449     if (allocator->registerAsService() != ::android::NO_ERROR) {
450         ALOGE("failed to register graphics IAllocator@3.0 service");
451         return -EINVAL;
452     }
453 
454     ALOGI("graphics IAllocator@3.0 service is initialized");
455     ::android::hardware::joinRpcThreadpool();
456 
457     ALOGI("graphics IAllocator@3.0 service is terminating");
458     return 0;
459 }
460