1 /*
2 * Copyright (C) 2024 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 <cstring>
18 #include <string_view>
19
20 #include <sched.h>
21
22 #include <android-base/unique_fd.h>
23 #include <android/binder_manager.h>
24 #include <android/binder_process.h>
25
26 #include <aidl/android/hardware/graphics/allocator/AllocationError.h>
27 #include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
28 #include <aidl/android/hardware/graphics/allocator/BnAllocator.h>
29 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
30 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
31 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
32
33 #include <aidlcommonsupport/NativeHandle.h>
34
35 #include <debug.h>
36 #include <drm_fourcc.h>
37 #include <glUtils.h>
38 #include <goldfish_address_space.h>
39 #include <gralloc_cb_bp.h>
40 #include <qemu_pipe_bp.h>
41
42 #include "CbExternalMetadata.h"
43 #include "DebugLevel.h"
44 #include "HostConnectionSession.h"
45
46 using ::aidl::android::hardware::graphics::allocator::AllocationError;
47 using ::aidl::android::hardware::graphics::allocator::AllocationResult;
48 using ::aidl::android::hardware::graphics::allocator::BnAllocator;
49 using ::aidl::android::hardware::graphics::allocator::BufferDescriptorInfo;
50 using ::aidl::android::hardware::graphics::common::BufferUsage;
51 using ::aidl::android::hardware::graphics::common::PixelFormat;
52 using ::aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
53
54 #ifndef GL_RGBA16F
55 #define GL_RGBA16F 0x881A
56 #endif // GL_RGBA16F
57
58 #ifndef GL_HALF_FLOAT
59 #define GL_HALF_FLOAT 0x140B
60 #endif // GL_HALF_FLOAT
61
62 #ifndef GL_RGB10_A2
63 #define GL_RGB10_A2 0x8059
64 #endif // GL_RGB10_A2
65
66 #ifndef GL_UNSIGNED_INT_2_10_10_10_REV
67 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
68 #endif // GL_UNSIGNED_INT_2_10_10_10_REV
69
70 namespace {
71 enum class EmulatorFrameworkFormat : uint8_t {
72 GL_COMPATIBLE = 0,
73 YV12 = 1,
74 YUV_420_888 = 2, // (Y+)(U+)(V+)
75 };
76
align(const size_t value,const size_t alignmentP2)77 size_t align(const size_t value, const size_t alignmentP2) {
78 return (value + alignmentP2 - 1) & ~(alignmentP2 - 1);
79 }
80
strnlen(const char * str,const size_t maxSize)81 size_t strnlen(const char* str, const size_t maxSize) {
82 const char* const begin = str;
83 const char* const end = begin + maxSize;
84 for (; *str && (str != end); ++str) {}
85 return str - begin;
86 }
87
toBinderStatus(const AllocationError error)88 ndk::ScopedAStatus toBinderStatus(const AllocationError error) {
89 return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(error));
90 }
91
toUsage64(const BufferUsage usage)92 uint64_t toUsage64(const BufferUsage usage) {
93 return static_cast<uint64_t>(usage);
94 }
95
needGpuBuffer(const uint64_t usage)96 bool needGpuBuffer(const uint64_t usage) {
97 return usage & (toUsage64(BufferUsage::GPU_TEXTURE)
98 | toUsage64(BufferUsage::GPU_RENDER_TARGET)
99 | toUsage64(BufferUsage::COMPOSER_OVERLAY)
100 | toUsage64(BufferUsage::COMPOSER_CLIENT_TARGET)
101 | toUsage64(BufferUsage::GPU_DATA_BUFFER));
102 }
103
needCpuBuffer(const uint64_t usage)104 bool needCpuBuffer(const uint64_t usage) {
105 return usage & (toUsage64(BufferUsage::CPU_READ_MASK)
106 | toUsage64(BufferUsage::CPU_WRITE_MASK));
107 }
108
makePlaneLayoutComponent(const PlaneLayoutComponentType type,const unsigned offsetInBits,const unsigned sizeInBits)109 PlaneLayoutComponent makePlaneLayoutComponent(const PlaneLayoutComponentType type,
110 const unsigned offsetInBits,
111 const unsigned sizeInBits) {
112 return {
113 .type = static_cast<uint32_t>(type),
114 .offsetInBits = static_cast<uint16_t>(offsetInBits),
115 .sizeInBits = static_cast<uint16_t>(sizeInBits),
116 };
117 }
118
initPlaneLayout(PlaneLayout & plane,const uint32_t width,const uint32_t height,const size_t offsetInBytes,const uint32_t alignment,const unsigned sampleSizeInBytes,const unsigned subsamplingShift,const unsigned componentsBase,const unsigned componentsSize)119 size_t initPlaneLayout(PlaneLayout& plane,
120 const uint32_t width,
121 const uint32_t height,
122 const size_t offsetInBytes,
123 const uint32_t alignment,
124 const unsigned sampleSizeInBytes,
125 const unsigned subsamplingShift,
126 const unsigned componentsBase,
127 const unsigned componentsSize) {
128 const uint32_t strideInBytes = align(width * sampleSizeInBytes, alignment);
129
130 plane.offsetInBytes = offsetInBytes;
131 plane.strideInBytes = strideInBytes;
132 plane.totalSizeInBytes = strideInBytes * height;
133 plane.sampleIncrementInBytes = sampleSizeInBytes;
134 plane.horizontalSubsamplingShift = subsamplingShift;
135 plane.verticalSubsamplingShift = subsamplingShift;
136 plane.componentsBase = componentsBase;
137 plane.componentsSize = componentsSize;
138
139 return offsetInBytes + plane.totalSizeInBytes;
140 }
141
142 struct GoldfishAllocator : public BnAllocator {
GoldfishAllocator__anon4bbb6fa40111::GoldfishAllocator143 GoldfishAllocator()
144 : mHostConn(HostConnection::createUnique(kCapsetNone))
145 , mDebugLevel(getDebugLevel()) {}
146
allocate2__anon4bbb6fa40111::GoldfishAllocator147 ndk::ScopedAStatus allocate2(const BufferDescriptorInfo& desc,
148 const int32_t count,
149 AllocationResult* const outResult) override {
150 if (count <= 0) {
151 return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
152 "%s: count=%d", "BAD_DESCRIPTOR",
153 count));
154 }
155 if (desc.width <= 0) {
156 return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
157 "%s: width=%d", "BAD_DESCRIPTOR",
158 desc.width));
159 }
160 if (desc.height <= 0) {
161 return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
162 "%s: height=%d", "BAD_DESCRIPTOR",
163 desc.height));
164 }
165 if (!validateUsage(desc.usage)) {
166 return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
167 "%s: usage=0x%" PRIX64, "BAD_DESCRIPTOR",
168 toUsage64(desc.usage)));
169 }
170 if (desc.layerCount != 1) {
171 return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
172 "%s: layerCount=%d", "BAD_DESCRIPTOR",
173 desc.layerCount));
174 }
175 if (desc.reservedSize < 0) {
176 return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
177 "%s: reservedSize=%" PRId64, "BAD_DESCRIPTOR",
178 desc.reservedSize));
179 }
180 if (!desc.additionalOptions.empty()) {
181 return toBinderStatus(FAILURE_V(
182 AllocationError::BAD_DESCRIPTOR, "%s: %s", "BAD_DESCRIPTOR",
183 "'BufferDescriptorInfo::additionalOptions' are not supported"));
184 }
185
186 const uint64_t usage = toUsage64(desc.usage);
187 const uint32_t width = desc.width;
188 const uint32_t height = desc.height;
189 size_t offsetInBytes = 0;
190
191 AllocationRequest req;
192 switch (desc.format) {
193 case PixelFormat::RGBA_8888:
194 req.glFormat = GL_RGBA;
195 req.glType = GL_UNSIGNED_BYTE;
196
197 req.drmFormat = DRM_FORMAT_ABGR8888;
198
199 req.planeSize = 1;
200 offsetInBytes = initPlaneLayout(
201 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
202 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
203 /*componentsBase=*/ 0, /*componentsSize*/ 4);
204 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 8);
205 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
206 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 16, 8);
207 req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 24, 8);
208 break;
209
210 case PixelFormat::RGBX_8888:
211 req.glFormat = GL_RGBA;
212 req.glType = GL_UNSIGNED_BYTE;
213
214 req.drmFormat = DRM_FORMAT_XBGR8888;
215
216 req.planeSize = 1;
217 offsetInBytes = initPlaneLayout(
218 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
219 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
220 /*componentsBase=*/ 0, /*componentsSize*/ 3);
221 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 8);
222 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
223 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 16, 8);
224 break;
225
226 case PixelFormat::BGRA_8888:
227 req.glFormat = GL_RGBA;
228 req.glType = GL_UNSIGNED_BYTE;
229
230 req.drmFormat = DRM_FORMAT_ARGB8888;
231
232 req.planeSize = 1;
233 offsetInBytes = initPlaneLayout(
234 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
235 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
236 /*componentsBase=*/ 0, /*componentsSize*/ 4);
237 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 0, 8);
238 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
239 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 16, 8);
240 req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 24, 8);
241 break;
242
243 case PixelFormat::RGB_888:
244 if (needGpuBuffer(usage)) {
245 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
246 }
247
248 req.drmFormat = DRM_FORMAT_BGR888;
249
250 req.planeSize = 1;
251 offsetInBytes = initPlaneLayout(
252 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
253 /*sampleSizeInBytes=*/ 3, /*subsamplingShift=*/ 0,
254 /*componentsBase=*/ 0, /*componentsSize*/ 3);
255 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 8);
256 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
257 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 16, 8);
258 break;
259
260 case PixelFormat::RGB_565:
261 req.glFormat = GL_RGB565;
262 req.glType = GL_UNSIGNED_SHORT_5_6_5;
263
264 req.drmFormat = DRM_FORMAT_BGR565;
265
266 req.planeSize = 1;
267 offsetInBytes = initPlaneLayout(
268 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
269 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
270 /*componentsBase=*/ 0, /*componentsSize*/ 3);
271 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 5);
272 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 5, 6);
273 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 11, 5);
274 break;
275
276 case PixelFormat::RGBA_FP16:
277 req.glFormat = GL_RGBA16F;
278 req.glType = GL_HALF_FLOAT;
279
280 req.drmFormat = DRM_FORMAT_ABGR16161616F;
281
282 req.planeSize = 1;
283 offsetInBytes = initPlaneLayout(
284 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
285 /*sampleSizeInBytes=*/ 8, /*subsamplingShift=*/ 0,
286 /*componentsBase=*/ 0, /*componentsSize*/ 4);
287 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 16);
288 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 16, 16);
289 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 32, 16);
290 req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 48, 16);
291 break;
292
293 case PixelFormat::RGBA_1010102:
294 req.glFormat = GL_RGB10_A2;
295 req.glType = GL_UNSIGNED_INT_2_10_10_10_REV;
296
297 req.drmFormat = DRM_FORMAT_ABGR2101010;
298
299 req.planeSize = 1;
300 offsetInBytes = initPlaneLayout(
301 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
302 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
303 /*componentsBase=*/ 0, /*componentsSize*/ 4);
304 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 10);
305 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 10, 10);
306 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 20, 10);
307 req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 30, 2);
308 break;
309
310 case PixelFormat::RAW16:
311 if (needGpuBuffer(usage)) {
312 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
313 }
314
315 req.drmFormat = DRM_FORMAT_R16;
316
317 req.planeSize = 1;
318 offsetInBytes = initPlaneLayout(
319 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 16,
320 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
321 /*componentsBase=*/ 0, /*componentsSize*/ 1);
322 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::RAW, 0, 16);
323 break;
324
325 case PixelFormat::Y16:
326 if (needGpuBuffer(usage)) {
327 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
328 }
329
330 req.drmFormat = DRM_FORMAT_R16;
331
332 req.planeSize = 1;
333 offsetInBytes = initPlaneLayout(
334 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 16,
335 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
336 /*componentsBase=*/ 0, /*componentsSize*/ 1);
337 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 16);
338 break;
339
340 case PixelFormat::BLOB:
341 if (needGpuBuffer(usage)) {
342 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
343 }
344
345 req.planeSize = 1;
346 offsetInBytes = initPlaneLayout(
347 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
348 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
349 /*componentsBase=*/ 0, /*componentsSize*/ 1);
350 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::RAW, 0, 8);
351 break;
352
353 case PixelFormat::YCRCB_420_SP: // Y + CrCb interleaved
354 if (needGpuBuffer(usage)) {
355 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
356 }
357
358 req.drmFormat = DRM_FORMAT_YVU420;
359
360 req.planeSize = 2;
361 offsetInBytes = initPlaneLayout(
362 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
363 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
364 /*componentsBase=*/ 0, /*componentsSize*/ 1);
365 offsetInBytes = initPlaneLayout(
366 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
367 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 1,
368 /*componentsBase=*/ 1, /*componentsSize*/ 2);
369 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 8);
370 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 0, 8);
371 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 8, 8);
372 break;
373
374 case PixelFormat::YV12: // 3 planes (Y, Cr, Cb), 16bytes aligned
375 req.glFormat = GL_RGBA;
376 req.glType = GL_UNSIGNED_BYTE;
377 req.emuFwkFormat = EmulatorFrameworkFormat::YV12;
378
379 req.drmFormat = DRM_FORMAT_YVU420;
380
381 req.planeSize = 3;
382 offsetInBytes = initPlaneLayout(
383 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 16,
384 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
385 /*componentsBase=*/ 0, /*componentsSize*/ 1);
386 offsetInBytes = initPlaneLayout(
387 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 16,
388 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
389 /*componentsBase=*/ 1, /*componentsSize*/ 1);
390 offsetInBytes = initPlaneLayout(
391 req.plane[2], width / 2, height / 2, offsetInBytes, /*alignment=*/ 16,
392 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
393 /*componentsBase=*/ 2, /*componentsSize*/ 1);
394
395 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 8);
396 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 0, 8);
397 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 0, 8);
398 break;
399
400 case PixelFormat::YCBCR_420_888: // 3 planes (Y, Cb, Cr)
401 req.glFormat = GL_RGBA;
402 req.glType = GL_UNSIGNED_BYTE;
403 req.emuFwkFormat = EmulatorFrameworkFormat::YUV_420_888;
404
405 req.drmFormat = DRM_FORMAT_YUV420;
406
407 req.planeSize = 3;
408 offsetInBytes = initPlaneLayout(
409 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
410 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
411 /*componentsBase=*/ 0, /*componentsSize*/ 1);
412 offsetInBytes = initPlaneLayout(
413 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
414 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
415 /*componentsBase=*/ 1, /*componentsSize*/ 1);
416 offsetInBytes = initPlaneLayout(
417 req.plane[2], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
418 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
419 /*componentsBase=*/ 2, /*componentsSize*/ 1);
420
421 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 8);
422 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 0, 8);
423 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 0, 8);
424 break;
425
426 case PixelFormat::YCBCR_P010: // Y + CbCr interleaved, 2bytes per component
427 req.glFormat = GL_RGBA;
428 req.glType = GL_UNSIGNED_BYTE;
429
430 req.drmFormat = DRM_FORMAT_YUV420_10BIT;
431
432 req.planeSize = 2;
433 offsetInBytes = initPlaneLayout(
434 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
435 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
436 /*componentsBase=*/ 0, /*componentsSize*/ 1);
437 offsetInBytes = initPlaneLayout(
438 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
439 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 1,
440 /*componentsBase=*/ 1, /*componentsSize*/ 2);
441
442 req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 6, 10);
443 req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 6, 10);
444 req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 6 + 10 + 6, 10);
445 break;
446
447 default:
448 return toBinderStatus(FAILURE_V(AllocationError::UNSUPPORTED,
449 "Unsupported format: format=0x%X, usage=%" PRIX64,
450 static_cast<uint32_t>(desc.format), desc.usage));
451 }
452
453 req.name = std::string_view(reinterpret_cast<const char*>(desc.name.data()),
454 strnlen(reinterpret_cast<const char*>(desc.name.data()),
455 desc.name.size()));
456 req.usage = usage;
457 req.width = width;
458 req.height = height;
459 req.format = desc.format;
460 req.reservedRegionSize = desc.reservedSize;
461
462 if (needCpuBuffer(usage)) {
463 req.imageSizeInBytes = offsetInBytes;
464 req.stride0 = (req.planeSize == 1) ?
465 (req.plane[0].strideInBytes /
466 req.plane[0].sampleIncrementInBytes) : 0;
467 } else {
468 req.imageSizeInBytes = 0; // the image is not allocated
469 /*
470 * b/359874912: the spec does not say how to handle PLANE_LAYOUTS
471 * if the CPU buffer is not allocated. Let's not populate them
472 * without the CPU buffer (sizes and offsets don't make sense anyway).
473 */
474 req.planeSize = 0;
475 req.stride0 = 0;
476 }
477
478 if (needGpuBuffer(usage)) {
479 req.rcAllocFormat = (req.format == PixelFormat::RGBX_8888) ? GL_RGB : req.glFormat;
480 } else {
481 req.glFormat = -1; // no GPU buffer - no GPU formats
482 req.glType = -1;
483 req.rcAllocFormat = -1;
484 }
485
486 std::vector<std::unique_ptr<cb_handle_t>> cbs(count);
487
488 {
489 HostConnectionSession connSession(mHostConn.get());
490 ExtendedRCEncoderContext* const rcEnc = connSession.getRcEncoder();
491 LOG_ALWAYS_FATAL_IF(!rcEnc);
492 const bool hasSharedSlots =
493 rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator;
494
495 for (int i = 0; i < count; ++i) {
496 std::unique_ptr<cb_handle_t> cb = allocateImpl(
497 req, *rcEnc, ++mBufferIdGenerator, hasSharedSlots);
498 if (cb) {
499 cbs[i] = std::move(cb);
500 } else {
501 for (--i; i > 0; --i) {
502 unallocate(std::move(cbs[i]));
503 }
504 return toBinderStatus(FAILURE(AllocationError::NO_RESOURCES));
505 }
506 }
507 }
508
509 outResult->stride = req.stride0;
510 outResult->buffers.reserve(count);
511 for (auto& cb : cbs) {
512 outResult->buffers.push_back(android::dupToAidl(cb.get()));
513 unallocate(std::move(cb));
514 }
515
516 return ndk::ScopedAStatus::ok();
517 }
518
isSupported__anon4bbb6fa40111::GoldfishAllocator519 ndk::ScopedAStatus isSupported(const BufferDescriptorInfo& descriptor,
520 bool* outResult) override {
521 *outResult = isSupportedImpl(descriptor);
522 return ndk::ScopedAStatus::ok();
523 }
524
getIMapperLibrarySuffix__anon4bbb6fa40111::GoldfishAllocator525 ndk::ScopedAStatus getIMapperLibrarySuffix(std::string* outResult) override {
526 *outResult = "ranchu";
527 return ndk::ScopedAStatus::ok();
528 }
529
allocate__anon4bbb6fa40111::GoldfishAllocator530 ndk::ScopedAStatus allocate(const std::vector<uint8_t>& encodedDescriptor,
531 const int32_t count,
532 AllocationResult* const outResult) override {
533 (void)encodedDescriptor;
534 (void)count;
535 (void)outResult;
536 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
537 }
538
539 private:
540 struct AllocationRequest {
541 std::string_view name;
542 PlaneLayout plane[3];
543 PlaneLayoutComponent planeComponent[4];
544 size_t imageSizeInBytes = 0;
545 size_t reservedRegionSize = 0;
546 uint64_t usage = 0;
547 uint32_t width = 0;
548 uint32_t height = 0;
549 uint32_t stride0 = 0;
550 uint32_t drmFormat = DRM_FORMAT_INVALID;
551 PixelFormat format = PixelFormat::UNSPECIFIED;
552 int glFormat = -1;
553 int glType = -1;
554 int rcAllocFormat = -1;
555 EmulatorFrameworkFormat emuFwkFormat = EmulatorFrameworkFormat::GL_COMPATIBLE;
556 uint8_t planeSize = 0;
557 };
558
559 std::unique_ptr<cb_handle_t>
allocateImpl__anon4bbb6fa40111::GoldfishAllocator560 allocateImpl(const AllocationRequest& req,
561 ExtendedRCEncoderContext& rcEnc,
562 const uint64_t bufferID,
563 const bool hasSharedSlots) const {
564 android::base::unique_fd cpuAlocatorFd;
565 GoldfishAddressSpaceBlock bufferBits;
566 const size_t imageSizeInBytesAligned = align(req.imageSizeInBytes, 16);
567 const size_t totalAllocationSize =
568 imageSizeInBytesAligned + sizeof(CbExternalMetadata) + req.reservedRegionSize;
569
570 {
571 GoldfishAddressSpaceHostMemoryAllocator hostMemoryAllocator(hasSharedSlots);
572 LOG_ALWAYS_FATAL_IF(!hostMemoryAllocator.is_opened());
573
574 if (hostMemoryAllocator.hostMalloc(&bufferBits, totalAllocationSize)) {
575 return FAILURE(nullptr);
576 }
577
578 cpuAlocatorFd.reset(hostMemoryAllocator.release());
579
580 CbExternalMetadata& metadata =
581 *reinterpret_cast<CbExternalMetadata*>(
582 static_cast<char*>(bufferBits.guestPtr()) + imageSizeInBytesAligned);
583
584 memset(&metadata, 0, sizeof(metadata));
585 metadata.magic = CbExternalMetadata::kMagicValue;
586 metadata.bufferID = bufferID;
587 metadata.nameSize = std::min(req.name.size(), sizeof(CbExternalMetadata::name));
588 memcpy(metadata.name, req.name.data(), metadata.nameSize);
589
590 metadata.planeLayoutSize = req.planeSize;
591 if (req.planeSize) {
592 static_assert(sizeof(metadata.planeLayout) == sizeof(req.plane));
593 memcpy(metadata.planeLayout, req.plane, sizeof(req.plane));
594
595 static_assert(sizeof(metadata.planeLayoutComponent) ==
596 sizeof(req.planeComponent));
597 memcpy(metadata.planeLayoutComponent, req.planeComponent,
598 sizeof(req.planeComponent));
599 }
600
601 metadata.reservedRegionSize = req.reservedRegionSize;
602 metadata.width = req.width;
603 metadata.height = req.height;
604 metadata.glFormat = req.glFormat;
605 metadata.glType = req.glType;
606 }
607
608 uint32_t hostHandle = 0;
609 android::base::unique_fd hostHandleRefCountFd;
610 if (needGpuBuffer(req.usage)) {
611 hostHandleRefCountFd.reset(qemu_pipe_open("refcount"));
612 if (!hostHandleRefCountFd.ok()) {
613 return FAILURE(nullptr);
614 }
615
616 hostHandle = rcEnc.rcCreateColorBufferDMA(
617 &rcEnc, req.width, req.height,
618 req.rcAllocFormat, static_cast<int>(req.emuFwkFormat));
619 if (!hostHandle) {
620 return FAILURE(nullptr);
621 }
622
623 if (qemu_pipe_write(hostHandleRefCountFd.get(),
624 &hostHandle,
625 sizeof(hostHandle)) != sizeof(hostHandle)) {
626 rcEnc.rcCloseColorBuffer(&rcEnc, hostHandle);
627 return FAILURE(nullptr);
628 }
629 }
630
631 if (mDebugLevel >= DebugLevel::ALLOC) {
632 char hostHandleValueStr[128];
633 if (hostHandle) {
634 snprintf(hostHandleValueStr, sizeof(hostHandleValueStr),
635 "0x%X glFormat=0x%X glType=0x%X "
636 "rcAllocFormat=0x%X emuFwkFormat=%d",
637 hostHandle, req.glFormat, req.glType, req.rcAllocFormat,
638 static_cast<int>(req.emuFwkFormat));
639 } else {
640 strcpy(hostHandleValueStr, "null");
641 }
642
643 char bufferValueStr[96];
644 if (req.imageSizeInBytes) {
645 snprintf(bufferValueStr, sizeof(bufferValueStr),
646 "{ ptr=%p mappedSize=%zu offset=0x%" PRIX64 " } imageSizeInBytes=%zu",
647 bufferBits.guestPtr(), size_t(bufferBits.size()),
648 bufferBits.offset(), size_t(req.imageSizeInBytes));
649 } else {
650 strcpy(bufferValueStr, "null");
651 }
652
653 ALOGD("%s:%d name='%.*s' id=%" PRIu64 " width=%u height=%u format=0x%X "
654 "usage=0x%" PRIX64 " hostHandle=%s buffer=%s reservedSize=%zu",
655 __func__, __LINE__, int(req.name.size()), req.name.data(), bufferID,
656 req.width, req.height, static_cast<uint32_t>(req.format),
657 req.usage, hostHandleValueStr, bufferValueStr,
658 req.reservedRegionSize);
659 }
660
661 auto cb = std::make_unique<cb_handle_t>(
662 cpuAlocatorFd.release(), hostHandleRefCountFd.release(), hostHandle,
663 req.usage, static_cast<uint32_t>(req.format), req.drmFormat,
664 req.stride0, req.imageSizeInBytes, bufferBits.guestPtr(),
665 bufferBits.size(), bufferBits.offset(),
666 imageSizeInBytesAligned);
667
668 bufferBits.release(); // now cb owns it
669 return cb;
670 }
671
unallocate__anon4bbb6fa40111::GoldfishAllocator672 static void unallocate(const std::unique_ptr<cb_handle_t> cb) {
673 if (cb->hostHandleRefcountFd >= 0) {
674 ::close(cb->hostHandleRefcountFd);
675 }
676
677 if (cb->bufferFd >= 0) {
678 if (cb->mmapedSize > 0) {
679 GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
680 }
681
682 GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
683 }
684 }
685
validateUsage__anon4bbb6fa40111::GoldfishAllocator686 static bool validateUsage(const BufferUsage usage) {
687 static constexpr uint64_t kReservedUsage =
688 (1U << 10) | (1U << 13) | (1U << 19) | (1U << 21);
689
690 return 0 == (toUsage64(usage) & kReservedUsage);
691 }
692
isSupportedImpl__anon4bbb6fa40111::GoldfishAllocator693 static bool isSupportedImpl(const BufferDescriptorInfo& desc) {
694 if (desc.width <= 0) { return false; }
695 if (desc.height <= 0) { return false; }
696 if (desc.layerCount != 1) { return false; }
697 if (desc.reservedSize < 0) { return false; }
698 if (!desc.additionalOptions.empty()) { return false; }
699
700 switch (desc.format) {
701 case PixelFormat::RGBA_8888:
702 case PixelFormat::RGBX_8888:
703 case PixelFormat::BGRA_8888:
704 case PixelFormat::RGB_565:
705 case PixelFormat::RGBA_FP16:
706 case PixelFormat::RGBA_1010102:
707 case PixelFormat::YV12:
708 case PixelFormat::YCBCR_420_888:
709 case PixelFormat::YCBCR_P010:
710 return validateUsage(desc.usage);
711
712 case PixelFormat::RGB_888:
713 case PixelFormat::YCRCB_420_SP:
714 case PixelFormat::RAW16:
715 case PixelFormat::Y16:
716 case PixelFormat::BLOB:
717 return validateUsage(desc.usage) &&
718 !needGpuBuffer(toUsage64(desc.usage));
719
720 case PixelFormat::IMPLEMENTATION_DEFINED: // we don't support it
721 default:
722 return false;
723 }
724 }
725
726 const std::unique_ptr<HostConnection> mHostConn;
727 uint64_t mBufferIdGenerator = 0;
728 const DebugLevel mDebugLevel;
729 };
730 } // namespace
731
main(int,char **)732 int main(int /*argc*/, char** /*argv*/) {
733 struct sched_param param = {0};
734 param.sched_priority = 2;
735 if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) {
736 ALOGW("Failed to set priority: %s", strerror(errno));
737 }
738
739 auto allocator = ndk::SharedRefBase::make<GoldfishAllocator>();
740
741 {
742 const std::string instance = std::string(GoldfishAllocator::descriptor) + "/default";
743 if (AServiceManager_addService(allocator->asBinder().get(),
744 instance.c_str()) != STATUS_OK) {
745 ALOGE("Failed to register: '%s'", instance.c_str());
746 return EXIT_FAILURE;
747 }
748 }
749
750 ABinderProcess_setThreadPoolMaxThreadCount(4);
751 ABinderProcess_startThreadPool();
752 ABinderProcess_joinThreadPool();
753 return EXIT_FAILURE; // joinThreadPool is not expected to return
754 }
755