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/mapper/3.0/IMapper.h>
18 #include <cutils/native_handle.h>
19 #include <sync/sync.h>
20
21 #include "cb_handle_30.h"
22 #include "host_connection_session.h"
23 #include "FormatConversions.h"
24 #include "debug.h"
25
26 const int kOMX_COLOR_FormatYUV420Planar = 19;
27
28 using ::android::hardware::hidl_handle;
29 using ::android::hardware::hidl_vec;
30 using ::android::hardware::Return;
31 using ::android::hardware::Void;
32
33 using ::android::hardware::graphics::common::V1_2::PixelFormat;
34 using ::android::hardware::graphics::common::V1_0::BufferUsage;
35
36 namespace MapperV3 = ::android::hardware::graphics::mapper::V3_0;
37
38 using IMapper3 = MapperV3::IMapper;
39 using Error3 = MapperV3::Error;
40 using YCbCrLayout3 = MapperV3::YCbCrLayout;
41
42 namespace {
align(const size_t v,const size_t a)43 size_t align(const size_t v, const size_t a) { return (v + a - 1) & ~(a - 1); }
44
waitFenceFd(const int fd,const char * logname)45 static int waitFenceFd(const int fd, const char* logname) {
46 const int warningTimeout = 5000;
47 if (sync_wait(fd, warningTimeout) < 0) {
48 if (errno == ETIME) {
49 ALOGW("%s: fence %d didn't signal in %d ms", logname, fd, warningTimeout);
50 if (sync_wait(fd, -1) < 0) {
51 RETURN_ERROR(errno);
52 } else {
53 RETURN(0);
54 }
55 } else {
56 RETURN_ERROR(errno);
57 }
58 } else {
59 RETURN(0);
60 }
61 }
62
waitHidlFence(const hidl_handle & hidlHandle,const char * logname)63 int waitHidlFence(const hidl_handle& hidlHandle, const char* logname) {
64 const native_handle_t* nativeHandle = hidlHandle.getNativeHandle();
65
66 if (!nativeHandle) {
67 RETURN(0);
68 }
69 if (nativeHandle->numFds > 1) {
70 RETURN_ERROR(-EINVAL);
71 }
72 if (nativeHandle->numInts != 0) {
73 RETURN_ERROR(-EINVAL);
74 }
75
76 return waitFenceFd(nativeHandle->data[0], logname);
77 }
78
79 class GoldfishMapper : public IMapper3 {
80 public:
GoldfishMapper()81 GoldfishMapper() : m_hostConn(HostConnection::createUnique()) {
82 GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(false);
83 CRASH_IF(!host_memory_allocator.is_opened(),
84 "GoldfishAddressSpaceHostMemoryAllocator failed to open");
85
86 GoldfishAddressSpaceBlock bufferBits;
87 CRASH_IF(host_memory_allocator.hostMalloc(&bufferBits, 256),
88 "hostMalloc failed");
89
90 m_physAddrToOffset = bufferBits.physAddr() - bufferBits.offset();
91
92 host_memory_allocator.hostFree(&bufferBits);
93 }
94
importBuffer(const hidl_handle & hh,importBuffer_cb hidl_cb)95 Return<void> importBuffer(const hidl_handle& hh,
96 importBuffer_cb hidl_cb) {
97 native_handle_t* imported = nullptr;
98 const Error3 e = importBufferImpl(hh.getNativeHandle(), &imported);
99 if (e == Error3::NONE) {
100 hidl_cb(Error3::NONE, imported);
101 } else {
102 hidl_cb(e, nullptr);
103 }
104 return {};
105 }
106
freeBuffer(void * raw)107 Return<Error3> freeBuffer(void* raw) {
108 if (!raw) {
109 RETURN_ERROR(Error3::BAD_BUFFER);
110 }
111 cb_handle_30_t* cb = cb_handle_30_t::from(raw);
112 if (!cb) {
113 RETURN_ERROR(Error3::BAD_BUFFER);
114 }
115
116 if (cb->hostHandle) {
117 const HostConnectionSession conn = getHostConnectionSession();
118 ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
119 rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle);
120 }
121
122 if (cb->mmapedSize > 0) {
123 GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
124 }
125
126 native_handle_close(cb);
127 native_handle_delete(cb);
128
129 RETURN(Error3::NONE);
130 }
131
lock(void * raw,uint64_t cpuUsage,const Rect & accessRegion,const hidl_handle & acquireFence,lock_cb hidl_cb)132 Return<void> lock(void* raw,
133 uint64_t cpuUsage,
134 const Rect& accessRegion,
135 const hidl_handle& acquireFence,
136 lock_cb hidl_cb) {
137 void* ptr = nullptr;
138 int32_t bytesPerPixel = 0;
139 int32_t bytesPerStride = 0;
140
141 const Error3 e = lockImpl(raw, cpuUsage, accessRegion, acquireFence,
142 &ptr, &bytesPerPixel, &bytesPerStride);
143 if (e == Error3::NONE) {
144 hidl_cb(Error3::NONE, ptr, bytesPerPixel, bytesPerStride);
145 } else {
146 hidl_cb(e, nullptr, 0, 0);
147 }
148 return {};
149 }
150
lockYCbCr(void * raw,uint64_t cpuUsage,const Rect & accessRegion,const hidl_handle & acquireFence,lockYCbCr_cb hidl_cb)151 Return<void> lockYCbCr(void* raw,
152 uint64_t cpuUsage,
153 const Rect& accessRegion,
154 const hidl_handle& acquireFence,
155 lockYCbCr_cb hidl_cb) {
156 YCbCrLayout3 ycbcr = {};
157 const Error3 e = lockYCbCrImpl(raw, cpuUsage, accessRegion, acquireFence,
158 &ycbcr);
159 if (e == Error3::NONE) {
160 hidl_cb(Error3::NONE, ycbcr);
161 } else {
162 hidl_cb(e, {});
163 }
164 return {};
165 }
166
unlock(void * raw,unlock_cb hidl_cb)167 Return<void> unlock(void* raw, unlock_cb hidl_cb) {
168 hidl_cb(unlockImpl(raw), {});
169 return {};
170
171 }
172
createDescriptor(const BufferDescriptorInfo & description,createDescriptor_cb hidl_cb)173 Return<void> createDescriptor(const BufferDescriptorInfo& description,
174 createDescriptor_cb hidl_cb) {
175 hidl_vec<uint32_t> raw;
176 encodeBufferDescriptorInfo(description, &raw);
177 hidl_cb(Error3::NONE, raw);
178 return {};
179 }
180
isSupported(const IMapper::BufferDescriptorInfo & description,isSupported_cb hidl_cb)181 Return<void> isSupported(const IMapper::BufferDescriptorInfo& description,
182 isSupported_cb hidl_cb) {
183 hidl_cb(Error3::NONE, isSupportedImpl(description));
184 return {};
185 }
186
validateBufferSize(void * buffer,const BufferDescriptorInfo & descriptor,uint32_t stride)187 Return<Error3> validateBufferSize(void* buffer,
188 const BufferDescriptorInfo& descriptor,
189 uint32_t stride) {
190 const cb_handle_30_t* cb = cb_handle_30_t::from(buffer);
191 if (cb) {
192 return validateBufferSizeImpl(*cb, descriptor, stride);
193 } else {
194 RETURN_ERROR(Error3::BAD_BUFFER);
195 }
196 }
197
getTransportSize(void * buffer,getTransportSize_cb hidl_cb)198 Return<void> getTransportSize(void* buffer,
199 getTransportSize_cb hidl_cb) {
200 const cb_handle_30_t* cb = cb_handle_30_t::from(buffer);
201 if (cb) {
202 hidl_cb(Error3::NONE, cb->numFds, cb->numInts);
203 } else {
204 hidl_cb(Error3::BAD_BUFFER, 0, 0);
205 }
206
207 return {};
208 }
209
210 private: // **** impl ****
importBufferImpl(const native_handle_t * nh,native_handle_t ** phandle)211 Error3 importBufferImpl(const native_handle_t* nh, native_handle_t** phandle) {
212 if (!nh) {
213 RETURN_ERROR(Error3::BAD_BUFFER);
214 }
215 native_handle_t* imported = native_handle_clone(nh);
216 if (!imported) {
217 RETURN_ERROR(Error3::BAD_BUFFER);
218 }
219 cb_handle_30_t* cb = cb_handle_30_t::from(imported);
220 if (!cb) {
221 native_handle_close(imported);
222 native_handle_delete(imported);
223 RETURN_ERROR(Error3::BAD_BUFFER);
224 }
225
226 if (cb->mmapedSize > 0) {
227 void* ptr;
228 const int res = GoldfishAddressSpaceBlock::memoryMap(
229 cb->getBufferPtr(),
230 cb->mmapedSize,
231 cb->bufferFd,
232 cb->getMmapedOffset(),
233 &ptr);
234 if (res) {
235 native_handle_close(imported);
236 native_handle_delete(imported);
237 RETURN_ERROR(Error3::NO_RESOURCES);
238 }
239 cb->setBufferPtr(ptr);
240 }
241
242 if (cb->hostHandle) {
243 const HostConnectionSession conn = getHostConnectionSession();
244 ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
245 rcEnc->rcOpenColorBuffer2(rcEnc, cb->hostHandle);
246 }
247
248 *phandle = imported;
249 RETURN(Error3::NONE);
250 }
251
lockImpl(void * raw,uint64_t cpuUsage,const Rect & accessRegion,const hidl_handle & acquireFence,void ** pptr,int32_t * pBytesPerPixel,int32_t * pBytesPerStride)252 Error3 lockImpl(void* raw,
253 uint64_t cpuUsage,
254 const Rect& accessRegion,
255 const hidl_handle& acquireFence,
256 void** pptr,
257 int32_t* pBytesPerPixel,
258 int32_t* pBytesPerStride) {
259 if (!raw) {
260 RETURN_ERROR(Error3::BAD_BUFFER);
261 }
262 cb_handle_30_t* cb = cb_handle_30_t::from(raw);
263 if (!cb) {
264 RETURN_ERROR(Error3::BAD_BUFFER);
265 }
266 if (!cb->bufferSize) {
267 RETURN_ERROR(Error3::BAD_BUFFER);
268 }
269 char* const bufferBits = static_cast<char*>(cb->getBufferPtr());
270 if (!bufferBits) {
271 RETURN_ERROR(Error3::BAD_BUFFER);
272 }
273 if (waitHidlFence(acquireFence, __func__)) {
274 RETURN_ERROR(Error3::BAD_VALUE);
275 }
276
277 if (cb->hostHandle) {
278 const Error3 e = lockHostImpl(*cb, cpuUsage, accessRegion, bufferBits);
279 if (e != Error3::NONE) {
280 return e;
281 }
282 }
283
284 *pptr = bufferBits;
285 *pBytesPerPixel = cb->bytesPerPixel;
286 *pBytesPerStride = cb->bytesPerPixel * cb->stride;
287 RETURN(Error3::NONE);
288 }
289
lockYCbCrImpl(void * raw,uint64_t cpuUsage,const Rect & accessRegion,const hidl_handle & acquireFence,YCbCrLayout3 * pYcbcr)290 Error3 lockYCbCrImpl(void* raw,
291 uint64_t cpuUsage,
292 const Rect& accessRegion,
293 const hidl_handle& acquireFence,
294 YCbCrLayout3* pYcbcr) {
295 if (!raw) {
296 RETURN_ERROR(Error3::BAD_BUFFER);
297 }
298 cb_handle_30_t* cb = cb_handle_30_t::from(raw);
299 if (!cb) {
300 RETURN_ERROR(Error3::BAD_BUFFER);
301 }
302 if (!cb->bufferSize) {
303 RETURN_ERROR(Error3::BAD_BUFFER);
304 }
305 char* const bufferBits = static_cast<char*>(cb->getBufferPtr());
306 if (!bufferBits) {
307 RETURN_ERROR(Error3::BAD_BUFFER);
308 }
309 if (waitHidlFence(acquireFence, __func__)) {
310 RETURN_ERROR(Error3::BAD_VALUE);
311 }
312
313 size_t uOffset;
314 size_t vOffset;
315 size_t yStride;
316 size_t cStride;
317 size_t cStep;
318 switch (static_cast<PixelFormat>(cb->format)) {
319 case PixelFormat::YCRCB_420_SP:
320 yStride = cb->width;
321 cStride = yStride;
322 vOffset = yStride * cb->height;
323 uOffset = vOffset + 1;
324 cStep = 2;
325 break;
326
327 case PixelFormat::YV12:
328 // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
329 yStride = align(cb->width, 16);
330 cStride = align(yStride / 2, 16);
331 vOffset = yStride * cb->height;
332 uOffset = vOffset + (cStride * cb->height / 2);
333 cStep = 1;
334 break;
335
336 case PixelFormat::YCBCR_420_888:
337 yStride = cb->width;
338 cStride = yStride / 2;
339 uOffset = cb->height * yStride;
340 vOffset = uOffset + cStride * cb->height / 2;
341 cStep = 1;
342 break;
343
344 default:
345 ALOGE("%s:%d unexpected format (%d)", __func__, __LINE__, cb->format);
346 RETURN_ERROR(Error3::BAD_BUFFER);
347 }
348
349 if (cb->hostHandle) {
350 const Error3 e = lockHostImpl(*cb, cpuUsage, accessRegion, bufferBits);
351 if (e != Error3::NONE) {
352 return e;
353 }
354 }
355
356 pYcbcr->y = bufferBits;
357 pYcbcr->cb = bufferBits + uOffset;
358 pYcbcr->cr = bufferBits + vOffset;
359 pYcbcr->yStride = yStride;
360 pYcbcr->cStride = cStride;
361 pYcbcr->chromaStep = cStep;
362
363 RETURN(Error3::NONE);
364 }
365
lockHostImpl(cb_handle_30_t & cb,const uint32_t usage,const Rect & accessRegion,char * const bufferBits)366 Error3 lockHostImpl(cb_handle_30_t& cb,
367 const uint32_t usage,
368 const Rect& accessRegion,
369 char* const bufferBits) {
370 const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
371 const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
372 const bool usageHwCamera = usage & (BufferUsage::CAMERA_INPUT | BufferUsage::CAMERA_OUTPUT);
373 const bool usageHwCameraWrite = usage & BufferUsage::CAMERA_OUTPUT;
374
375 const HostConnectionSession conn = getHostConnectionSession();
376 ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
377
378 const int res = rcEnc->rcColorBufferCacheFlush(
379 rcEnc, cb.hostHandle, 0, usageSwRead);
380 if (res < 0) {
381 RETURN_ERROR(Error3::NO_RESOURCES);
382 }
383
384 // camera delivers bits to the buffer directly and does not require
385 // an explicit read.
386 if (usageSwRead && !usageHwCamera) {
387 if (gralloc_is_yuv_format(cb.format)) {
388 if (rcEnc->hasYUVCache()) {
389 uint32_t bufferSize;
390 switch (static_cast<PixelFormat>(cb.format)) {
391 case PixelFormat::YV12:
392 get_yv12_offsets(cb.width, cb.height,
393 nullptr, nullptr, &bufferSize);
394 break;
395 case PixelFormat::YCBCR_420_888:
396 get_yuv420p_offsets(cb.width, cb.height,
397 nullptr, nullptr, &bufferSize);
398 break;
399 default:
400 CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
401 break;
402 }
403
404 rcEnc->rcReadColorBufferYUV(rcEnc, cb.hostHandle,
405 0, 0, cb.width, cb.height,
406 bufferBits, bufferSize);
407 } else {
408 // We are using RGB888
409 std::vector<char> tmpBuf(cb.width * cb.height * 3);
410 rcEnc->rcReadColorBuffer(rcEnc, cb.hostHandle,
411 0, 0, cb.width, cb.height,
412 cb.glFormat, cb.glType,
413 tmpBuf.data());
414 switch (static_cast<PixelFormat>(cb.format)) {
415 case PixelFormat::YV12:
416 rgb888_to_yv12(bufferBits, tmpBuf.data(),
417 cb.width, cb.height,
418 accessRegion.left,
419 accessRegion.top,
420 accessRegion.left + accessRegion.width - 1,
421 accessRegion.top + accessRegion.height - 1);
422 break;
423 case PixelFormat::YCBCR_420_888:
424 rgb888_to_yuv420p(bufferBits, tmpBuf.data(),
425 cb.width, cb.height,
426 accessRegion.left,
427 accessRegion.top,
428 accessRegion.left + accessRegion.width - 1,
429 accessRegion.top + accessRegion.height - 1);
430 break;
431 default:
432 CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
433 break;
434 }
435 }
436 } else {
437 rcEnc->rcReadColorBuffer(rcEnc,
438 cb.hostHandle,
439 0, 0, cb.width, cb.height,
440 cb.glFormat, cb.glType,
441 bufferBits);
442 }
443 }
444
445 if (usageSwWrite || usageHwCameraWrite) {
446 cb.lockedLeft = accessRegion.left;
447 cb.lockedTop = accessRegion.top;
448 cb.lockedWidth = accessRegion.width;
449 cb.lockedHeight = accessRegion.height;
450 } else {
451 cb.lockedLeft = 0;
452 cb.lockedTop = 0;
453 cb.lockedWidth = cb.width;
454 cb.lockedHeight = cb.height;
455 }
456
457 RETURN(Error3::NONE);
458 }
459
unlockImpl(void * raw)460 Error3 unlockImpl(void* raw) {
461 if (!raw) {
462 RETURN_ERROR(Error3::BAD_BUFFER);
463 }
464 cb_handle_30_t* cb = cb_handle_30_t::from(raw);
465 if (!cb) {
466 RETURN_ERROR(Error3::BAD_BUFFER);
467 }
468 if (!cb->bufferSize) {
469 RETURN_ERROR(Error3::BAD_BUFFER);
470 }
471 char* const bufferBits = static_cast<char*>(cb->getBufferPtr());
472 if (!bufferBits) {
473 RETURN_ERROR(Error3::BAD_BUFFER);
474 }
475
476 if (cb->hostHandle) {
477 unlockHostImpl(*cb, bufferBits);
478 }
479
480 RETURN(Error3::NONE);
481 }
482
unlockHostImpl(cb_handle_30_t & cb,char * const bufferBits)483 void unlockHostImpl(cb_handle_30_t& cb, char* const bufferBits) {
484 const int bpp = glUtilsPixelBitSize(cb.glFormat, cb.glType) >> 3;
485 const int left = cb.lockedLeft;
486 const int top = cb.lockedTop;
487 const int width = cb.lockedWidth;
488 const int height = cb.lockedHeight;
489 const uint32_t rgbSize = width * height * bpp;
490 std::vector<char> convertedBuf;
491 const char* bitsToSend;
492 uint32_t sizeToSend;
493
494 if (gralloc_is_yuv_format(cb.format)) {
495 bitsToSend = bufferBits;
496 switch (static_cast<PixelFormat>(cb.format)) {
497 case PixelFormat::YV12:
498 get_yv12_offsets(width, height, nullptr, nullptr, &sizeToSend);
499 break;
500 case PixelFormat::YCBCR_420_888:
501 get_yuv420p_offsets(width, height, nullptr, nullptr, &sizeToSend);
502 break;
503 default:
504 CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
505 break;
506 }
507 } else {
508 convertedBuf.resize(rgbSize);
509 copy_rgb_buffer_from_unlocked(
510 convertedBuf.data(), bufferBits,
511 cb.width,
512 width, height, top, left, bpp);
513 bitsToSend = convertedBuf.data();
514 sizeToSend = rgbSize;
515 }
516
517 {
518 const HostConnectionSession conn = getHostConnectionSession();
519 ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
520 rcEnc->bindDmaDirectly(bufferBits,
521 getMmapedPhysAddr(cb.getMmapedOffset()));
522 rcEnc->rcUpdateColorBufferDMA(rcEnc, cb.hostHandle,
523 left, top, width, height,
524 cb.glFormat, cb.glType,
525 const_cast<char*>(bitsToSend), sizeToSend);
526 }
527
528 cb.lockedLeft = 0;
529 cb.lockedTop = 0;
530 cb.lockedWidth = 0;
531 cb.lockedHeight = 0;
532 }
533
isSupportedImpl(const IMapper::BufferDescriptorInfo & descriptor) const534 bool isSupportedImpl(const IMapper::BufferDescriptorInfo& descriptor) const {
535 if (!descriptor.width) { RETURN(false); }
536 if (!descriptor.height) { RETURN(false); }
537 if (descriptor.layerCount != 1) { RETURN(false); }
538
539 const uint32_t usage = descriptor.usage;
540 const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
541 const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
542 const bool usageHwCamWrite = usage & BufferUsage::CAMERA_OUTPUT;
543 const bool usageHwCamRead = usage & BufferUsage::CAMERA_INPUT;
544
545 switch (descriptor.format) {
546 case PixelFormat::RGBA_8888:
547 case PixelFormat::RGBX_8888:
548 case PixelFormat::BGRA_8888:
549 case PixelFormat::RGB_565:
550 case PixelFormat::RGBA_FP16:
551 case PixelFormat::RGBA_1010102:
552 case PixelFormat::YCRCB_420_SP:
553 case PixelFormat::YV12:
554 case PixelFormat::YCBCR_420_888:
555 RETURN(true);
556
557 case PixelFormat::IMPLEMENTATION_DEFINED:
558 if (usage & BufferUsage::CAMERA_OUTPUT) {
559 if (usage & BufferUsage::GPU_TEXTURE) {
560 RETURN(true);
561 } else if (usage & BufferUsage::VIDEO_ENCODER) {
562 RETURN(true);
563 }
564 }
565 RETURN(false);
566
567 case PixelFormat::RGB_888:
568 RETURN(0 == (usage & (BufferUsage::GPU_TEXTURE |
569 BufferUsage::GPU_RENDER_TARGET |
570 BufferUsage::COMPOSER_OVERLAY |
571 BufferUsage::COMPOSER_CLIENT_TARGET)));
572
573 case PixelFormat::RAW16:
574 case PixelFormat::Y16:
575 RETURN((usageSwRead || usageHwCamRead) &&
576 (usageSwWrite || usageHwCamWrite));
577
578 case PixelFormat::BLOB:
579 RETURN(usageSwRead);
580
581 default:
582 if (static_cast<int>(descriptor.format) == kOMX_COLOR_FormatYUV420Planar) {
583 return (usage & BufferUsage::GPU_DATA_BUFFER) != 0;
584 }
585
586 RETURN(false);
587 }
588 }
589
validateBufferSizeImpl(const cb_handle_t &,const BufferDescriptorInfo &,uint32_t)590 Error3 validateBufferSizeImpl(const cb_handle_t& /*cb*/,
591 const BufferDescriptorInfo& /*descriptor*/,
592 uint32_t /*stride*/) {
593 RETURN(Error3::NONE);
594 }
595
getHostConnectionSession() const596 HostConnectionSession getHostConnectionSession() const {
597 return HostConnectionSession(m_hostConn.get());
598 }
599
encodeBufferDescriptorInfo(const BufferDescriptorInfo & d,hidl_vec<uint32_t> * raw)600 static void encodeBufferDescriptorInfo(const BufferDescriptorInfo& d,
601 hidl_vec<uint32_t>* raw) {
602 raw->resize(5);
603
604 (*raw)[0] = d.width;
605 (*raw)[1] = d.height;
606 (*raw)[2] = d.layerCount;
607 (*raw)[3] = static_cast<uint32_t>(d.format);
608 (*raw)[4] = d.usage & UINT32_MAX;
609 }
610
getMmapedPhysAddr(uint64_t offset) const611 uint64_t getMmapedPhysAddr(uint64_t offset) const {
612 return m_physAddrToOffset + offset;
613 }
614
615 std::unique_ptr<HostConnection> m_hostConn;
616 uint64_t m_physAddrToOffset;
617 };
618 } // namespace
619
HIDL_FETCH_IMapper(const char *)620 extern "C" IMapper3* HIDL_FETCH_IMapper(const char* /*name*/) {
621 return new GoldfishMapper;
622 }
623