blob: 4d7e6199fe1feb412cbd1375476d516e2577bf4f [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright (C) 2016 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//#define LOG_NDEBUG 0
18#define LOG_TAG "C2AllocatorGralloc"
19#include <utils/Log.h>
20
Marissa Wall2a24a302019-11-25 11:19:18 -080021#include <mutex>
22
23#include <android/hardware/graphics/common/1.2/types.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080024#include <cutils/native_handle.h>
25#include <hardware/gralloc.h>
Marissa Wall2a24a302019-11-25 11:19:18 -080026#include <ui/GraphicBufferAllocator.h>
27#include <ui/GraphicBufferMapper.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080028
29#include <C2AllocatorGralloc.h>
30#include <C2Buffer.h>
31#include <C2PlatformSupport.h>
32
Marissa Wall2a24a302019-11-25 11:19:18 -080033using ::android::hardware::hidl_handle;
34using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
35
Pawin Vongmasa36653902018-11-15 00:10:25 -080036namespace android {
37
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070038namespace /* unnamed */ {
Pawin Vongmasa36653902018-11-15 00:10:25 -080039 enum : uint64_t {
40 /**
41 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
42 */
43 PASSTHROUGH_USAGE_MASK =
44 ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
45 };
46
47 // verify that passthrough mask is within the platform mask
48 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070049} // unnamed
Pawin Vongmasa36653902018-11-15 00:10:25 -080050
51C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
52 // gralloc does not support WRITE_PROTECTED
53 return C2MemoryUsage(
54 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
55 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
56 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
57 (usage & PASSTHROUGH_USAGE_MASK));
58}
59
60uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
61 // gralloc does not support WRITE_PROTECTED
62 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
63 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
64 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
65 (expected & PASSTHROUGH_USAGE_MASK));
66}
67
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070068namespace /* unnamed */ {
69
Pawin Vongmasa36653902018-11-15 00:10:25 -080070/* ===================================== GRALLOC ALLOCATION ==================================== */
Pawin Vongmasa36653902018-11-15 00:10:25 -080071bool native_handle_is_invalid(const native_handle_t *const handle) {
72 // perform basic validation of a native handle
73 if (handle == nullptr) {
74 // null handle is considered valid
75 return false;
76 }
77 return ((size_t)handle->version != sizeof(native_handle_t) ||
78 handle->numFds < 0 ||
79 handle->numInts < 0 ||
80 // for sanity assume handles must occupy less memory than INT_MAX bytes
81 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
82}
83
84class C2HandleGralloc : public C2Handle {
85private:
86 struct ExtraData {
87 uint32_t width;
88 uint32_t height;
89 uint32_t format;
90 uint32_t usage_lo;
91 uint32_t usage_hi;
92 uint32_t stride;
93 uint32_t generation;
94 uint32_t igbp_id_lo;
95 uint32_t igbp_id_hi;
96 uint32_t igbp_slot;
97 uint32_t magic;
98 };
99
100 enum {
101 NUM_INTS = sizeof(ExtraData) / sizeof(int),
102 };
103 const static uint32_t MAGIC = '\xc2gr\x00';
104
105 static
John Stultz653ddd12020-09-19 05:26:24 +0000106 const ExtraData* GetExtraData(const C2Handle *const handle) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800107 if (handle == nullptr
108 || native_handle_is_invalid(handle)
109 || handle->numInts < NUM_INTS) {
110 return nullptr;
111 }
112 return reinterpret_cast<const ExtraData*>(
113 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
114 }
115
116 static
John Stultz653ddd12020-09-19 05:26:24 +0000117 ExtraData *GetExtraData(C2Handle *const handle) {
118 return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800119 }
120
121public:
122 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
John Stultz653ddd12020-09-19 05:26:24 +0000123 const ExtraData *ed = GetExtraData(this);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800124 *generation = ed->generation;
125 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
126 *igbp_slot = ed->igbp_slot;
127 }
128
John Stultz653ddd12020-09-19 05:26:24 +0000129 static bool IsValid(const C2Handle *const o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800130 if (o == nullptr) { // null handle is always valid
131 return true;
132 }
John Stultz653ddd12020-09-19 05:26:24 +0000133 const ExtraData *xd = GetExtraData(o);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800134 // we cannot validate width/height/format/usage without accessing gralloc driver
135 return xd != nullptr && xd->magic == MAGIC;
136 }
137
Sungtak Leea4d13be2019-01-23 15:24:46 -0800138 static C2HandleGralloc* WrapAndMoveNativeHandle(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800139 const native_handle_t *const handle,
140 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
141 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
142 //CHECK(handle != nullptr);
143 if (native_handle_is_invalid(handle) ||
144 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
145 return nullptr;
146 }
147 ExtraData xd = {
148 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
149 stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
150 igbp_slot, MAGIC
151 };
152 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
153 if (res != nullptr) {
154 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
John Stultz653ddd12020-09-19 05:26:24 +0000155 *GetExtraData(res) = xd;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800156 }
157 return reinterpret_cast<C2HandleGralloc *>(res);
158 }
159
Sungtak Leea4d13be2019-01-23 15:24:46 -0800160 static C2HandleGralloc* WrapNativeHandle(
161 const native_handle_t *const handle,
162 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
163 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
164 if (handle == nullptr) {
165 return nullptr;
166 }
167 native_handle_t *clone = native_handle_clone(handle);
168 if (clone == nullptr) {
169 return nullptr;
170 }
171 C2HandleGralloc *res = WrapAndMoveNativeHandle(
172 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
173 if (res == nullptr) {
174 native_handle_close(clone);
175 }
176 native_handle_delete(clone);
177 return res;
178 }
179
Sungtak Lee08515812019-06-05 11:16:32 -0700180 static bool MigrateNativeHandle(
181 native_handle_t *handle,
182 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
John Stultz653ddd12020-09-19 05:26:24 +0000183 if (handle == nullptr || !IsValid(handle)) {
Sungtak Lee08515812019-06-05 11:16:32 -0700184 return false;
185 }
John Stultz653ddd12020-09-19 05:26:24 +0000186 ExtraData *ed = GetExtraData(handle);
Sungtak Lee08515812019-06-05 11:16:32 -0700187 if (!ed) return false;
188 ed->generation = generation;
189 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
190 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
191 ed->igbp_slot = igbp_slot;
192 return true;
193 }
194
195
Pawin Vongmasa36653902018-11-15 00:10:25 -0800196 static native_handle_t* UnwrapNativeHandle(
197 const C2Handle *const handle) {
John Stultz653ddd12020-09-19 05:26:24 +0000198 const ExtraData *xd = GetExtraData(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800199 if (xd == nullptr || xd->magic != MAGIC) {
200 return nullptr;
201 }
202 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
203 if (res != nullptr) {
204 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
205 }
206 return res;
207 }
208
Pawin Vongmasa36653902018-11-15 00:10:25 -0800209 static const C2HandleGralloc* Import(
210 const C2Handle *const handle,
211 uint32_t *width, uint32_t *height, uint32_t *format,
212 uint64_t *usage, uint32_t *stride,
213 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
John Stultz653ddd12020-09-19 05:26:24 +0000214 const ExtraData *xd = GetExtraData(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800215 if (xd == nullptr) {
216 return nullptr;
217 }
218 *width = xd->width;
219 *height = xd->height;
220 *format = xd->format;
221 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
222 *stride = xd->stride;
223 *generation = xd->generation;
224 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
225 *igbp_slot = xd->igbp_slot;
226 return reinterpret_cast<const C2HandleGralloc *>(handle);
227 }
228};
229
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700230} // unnamed namespace
231
Pawin Vongmasa36653902018-11-15 00:10:25 -0800232native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
233 return C2HandleGralloc::UnwrapNativeHandle(handle);
234}
235
Pawin Vongmasa36653902018-11-15 00:10:25 -0800236C2Handle *WrapNativeCodec2GrallocHandle(
237 const native_handle_t *const handle,
238 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
239 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
240 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
241 generation, igbp_id, igbp_slot);
242}
243
Sungtak Lee08515812019-06-05 11:16:32 -0700244bool MigrateNativeCodec2GrallocHandle(
245 native_handle_t *handle,
246 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
247 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
248}
249
250
Pawin Vongmasa36653902018-11-15 00:10:25 -0800251class C2AllocationGralloc : public C2GraphicAllocation {
252public:
253 virtual ~C2AllocationGralloc() override;
254
255 virtual c2_status_t map(
256 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
257 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
258 virtual c2_status_t unmap(
259 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
260 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
261 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
262 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
263
264 // internal methods
265 // |handle| will be moved.
Marissa Wall2a24a302019-11-25 11:19:18 -0800266
Pawin Vongmasa36653902018-11-15 00:10:25 -0800267 C2AllocationGralloc(
Marissa Wall2a24a302019-11-25 11:19:18 -0800268 uint32_t width, uint32_t height,
269 uint32_t format, uint32_t layerCount,
270 uint64_t grallocUsage, uint32_t stride,
Marissa Wall8806edc2019-06-21 09:50:47 -0700271 hidl_handle &hidlHandle,
272 const C2HandleGralloc *const handle,
273 C2Allocator::id_t allocatorId);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800274 int dup() const;
275 c2_status_t status() const;
276
277private:
Marissa Wall2a24a302019-11-25 11:19:18 -0800278 const uint32_t mWidth;
279 const uint32_t mHeight;
280 const uint32_t mFormat;
281 const uint32_t mLayerCount;
282 const uint64_t mGrallocUsage;
283 const uint32_t mStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800284 const hidl_handle mHidlHandle;
285 const C2HandleGralloc *mHandle;
286 buffer_handle_t mBuffer;
287 const C2HandleGralloc *mLockedHandle;
288 bool mLocked;
289 C2Allocator::id_t mAllocatorId;
290 std::mutex mMappedLock;
291};
292
293C2AllocationGralloc::C2AllocationGralloc(
Marissa Wall2a24a302019-11-25 11:19:18 -0800294 uint32_t width, uint32_t height,
295 uint32_t format, uint32_t layerCount,
296 uint64_t grallocUsage, uint32_t stride,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800297 hidl_handle &hidlHandle,
298 const C2HandleGralloc *const handle,
299 C2Allocator::id_t allocatorId)
Marissa Wall2a24a302019-11-25 11:19:18 -0800300 : C2GraphicAllocation(width, height),
301 mWidth(width),
302 mHeight(height),
303 mFormat(format),
304 mLayerCount(layerCount),
305 mGrallocUsage(grallocUsage),
306 mStride(stride),
Marissa Wall8806edc2019-06-21 09:50:47 -0700307 mHidlHandle(std::move(hidlHandle)),
308 mHandle(handle),
309 mBuffer(nullptr),
310 mLockedHandle(nullptr),
311 mLocked(false),
312 mAllocatorId(allocatorId) {
313}
314
Pawin Vongmasa36653902018-11-15 00:10:25 -0800315C2AllocationGralloc::~C2AllocationGralloc() {
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800316 if (mBuffer && mLocked) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 // implementation ignores addresss and rect
318 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
319 unmap(addr, C2Rect(), nullptr);
320 }
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800321 if (mBuffer) {
Marissa Wall2a24a302019-11-25 11:19:18 -0800322 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
323 if (err) {
324 ALOGE("failed transaction: freeBuffer");
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700325 }
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800326 }
327 if (mHandle) {
328 native_handle_delete(
329 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
330 }
Sungtak Lee2729dcf2019-01-18 13:15:07 -0800331 if (mLockedHandle) {
332 native_handle_delete(
333 const_cast<native_handle_t *>(
334 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
335 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800336}
337
338c2_status_t C2AllocationGralloc::map(
339 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
340 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
341 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
342 ALOGV("mapping buffer with usage %#llx => %#llx",
343 (long long)usage.expected, (long long)grallocUsage);
344
345 // TODO
Marissa Wall2a24a302019-11-25 11:19:18 -0800346 (void)fence;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800347
348 std::lock_guard<std::mutex> lock(mMappedLock);
349 if (mBuffer && mLocked) {
350 ALOGD("already mapped");
351 return C2_DUPLICATE;
352 }
353 if (!layout || !addr) {
354 ALOGD("wrong param");
355 return C2_BAD_VALUE;
356 }
357
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358 if (!mBuffer) {
Marissa Wall2a24a302019-11-25 11:19:18 -0800359 status_t err = GraphicBufferMapper::get().importBuffer(
360 mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
361 mFormat, mGrallocUsage, mStride, &mBuffer);
362 if (err) {
363 ALOGE("failed transaction: importBuffer");
364 return C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800365 }
366 if (mBuffer == nullptr) {
367 ALOGD("importBuffer returned null buffer");
368 return C2_CORRUPTED;
369 }
370 uint32_t generation = 0;
371 uint64_t igbp_id = 0;
372 uint32_t igbp_slot = 0;
373 if (mHandle) {
374 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
375 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800376
Marissa Wall2a24a302019-11-25 11:19:18 -0800377 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
378 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
379 mStride, generation, igbp_id, igbp_slot);
Marissa Wall8806edc2019-06-21 09:50:47 -0700380 }
Marissa Wall2a24a302019-11-25 11:19:18 -0800381 switch (mFormat) {
382 case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700383 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
384 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
385 // default to YUV for now.
386 void *pointer = nullptr;
Marissa Wall2a24a302019-11-25 11:19:18 -0800387 // TODO: fence
388 status_t err = GraphicBufferMapper::get().lock(
389 const_cast<native_handle_t *>(mBuffer), grallocUsage,
390 { (int32_t)rect.left, (int32_t)rect.top,
391 (int32_t)rect.width, (int32_t)rect.height },
392 &pointer);
393 if (err) {
394 ALOGE("failed transaction: lock(RGBA_1010102)");
395 return C2_CORRUPTED;
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700396 }
397 // treat as 32-bit values
398 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
399 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
400 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
401 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
402 layout->type = C2PlanarLayout::TYPE_YUVA;
403 layout->numPlanes = 4;
404 layout->rootPlanes = 1;
405 layout->planes[C2PlanarLayout::PLANE_Y] = {
406 C2PlaneInfo::CHANNEL_Y, // channel
407 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800408 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700409 1, // mColSampling
410 1, // mRowSampling
411 32, // allocatedDepth
412 10, // bitDepth
413 10, // rightShift
414 C2PlaneInfo::LITTLE_END, // endianness
415 C2PlanarLayout::PLANE_Y, // rootIx
416 0, // offset
417 };
418 layout->planes[C2PlanarLayout::PLANE_U] = {
419 C2PlaneInfo::CHANNEL_CB, // channel
420 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800421 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700422 1, // mColSampling
423 1, // mRowSampling
424 32, // allocatedDepth
425 10, // bitDepth
426 0, // rightShift
427 C2PlaneInfo::LITTLE_END, // endianness
428 C2PlanarLayout::PLANE_Y, // rootIx
429 0, // offset
430 };
431 layout->planes[C2PlanarLayout::PLANE_V] = {
432 C2PlaneInfo::CHANNEL_CR, // channel
433 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800434 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700435 1, // mColSampling
436 1, // mRowSampling
437 32, // allocatedDepth
438 10, // bitDepth
439 20, // rightShift
440 C2PlaneInfo::LITTLE_END, // endianness
441 C2PlanarLayout::PLANE_Y, // rootIx
442 0, // offset
443 };
444 layout->planes[C2PlanarLayout::PLANE_A] = {
445 C2PlaneInfo::CHANNEL_A, // channel
446 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800447 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700448 1, // mColSampling
449 1, // mRowSampling
450 32, // allocatedDepth
451 2, // bitDepth
452 30, // rightShift
453 C2PlaneInfo::LITTLE_END, // endianness
454 C2PlanarLayout::PLANE_Y, // rootIx
455 0, // offset
456 };
457 break;
458 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459
Marissa Wall2a24a302019-11-25 11:19:18 -0800460 case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700461 // TODO: alpha channel
462 // fall-through
Marissa Wall2a24a302019-11-25 11:19:18 -0800463 case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700464 void *pointer = nullptr;
Marissa Wall2a24a302019-11-25 11:19:18 -0800465 // TODO: fence
466 status_t err = GraphicBufferMapper::get().lock(
467 const_cast<native_handle_t*>(mBuffer), grallocUsage,
468 { (int32_t)rect.left, (int32_t)rect.top,
469 (int32_t)rect.width, (int32_t)rect.height },
470 &pointer);
471 if (err) {
472 ALOGE("failed transaction: lock(RGBA_8888)");
473 return C2_CORRUPTED;
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700474 }
475 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
476 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
477 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
478 layout->type = C2PlanarLayout::TYPE_RGB;
479 layout->numPlanes = 3;
480 layout->rootPlanes = 1;
481 layout->planes[C2PlanarLayout::PLANE_R] = {
482 C2PlaneInfo::CHANNEL_R, // channel
483 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800484 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700485 1, // mColSampling
486 1, // mRowSampling
487 8, // allocatedDepth
488 8, // bitDepth
489 0, // rightShift
490 C2PlaneInfo::NATIVE, // endianness
491 C2PlanarLayout::PLANE_R, // rootIx
492 0, // offset
493 };
494 layout->planes[C2PlanarLayout::PLANE_G] = {
495 C2PlaneInfo::CHANNEL_G, // channel
496 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800497 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700498 1, // mColSampling
499 1, // mRowSampling
500 8, // allocatedDepth
501 8, // bitDepth
502 0, // rightShift
503 C2PlaneInfo::NATIVE, // endianness
504 C2PlanarLayout::PLANE_R, // rootIx
505 1, // offset
506 };
507 layout->planes[C2PlanarLayout::PLANE_B] = {
508 C2PlaneInfo::CHANNEL_B, // channel
509 4, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800510 static_cast<int32_t>(4 * mStride), // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700511 1, // mColSampling
512 1, // mRowSampling
513 8, // allocatedDepth
514 8, // bitDepth
515 0, // rightShift
516 C2PlaneInfo::NATIVE, // endianness
517 C2PlanarLayout::PLANE_R, // rootIx
518 2, // offset
519 };
520 break;
521 }
522
David Stevens1cadc75d2020-04-03 10:50:51 +0900523 case static_cast<uint32_t>(PixelFormat4::BLOB): {
524 void *pointer = nullptr;
525 // TODO: fence
526 status_t err = GraphicBufferMapper::get().lock(
527 const_cast<native_handle_t*>(mBuffer), grallocUsage,
528 { (int32_t)rect.left, (int32_t)rect.top,
529 (int32_t)rect.width, (int32_t)rect.height },
530 &pointer);
531 if (err) {
532 ALOGE("failed transaction: lock(BLOB)");
533 return C2_CORRUPTED;
534 }
535 *addr = (uint8_t *)pointer;
536 break;
537 }
538
Marissa Wall2a24a302019-11-25 11:19:18 -0800539 case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700540 // fall-through
Marissa Wall2a24a302019-11-25 11:19:18 -0800541 case static_cast<uint32_t>(PixelFormat4::YV12):
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700542 // fall-through
543 default: {
Marissa Wall2a24a302019-11-25 11:19:18 -0800544 android_ycbcr ycbcrLayout;
545
546 status_t err = GraphicBufferMapper::get().lockYCbCr(
547 const_cast<native_handle_t*>(mBuffer), grallocUsage,
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700548 { (int32_t)rect.left, (int32_t)rect.top,
549 (int32_t)rect.width, (int32_t)rect.height },
Marissa Wall2a24a302019-11-25 11:19:18 -0800550 &ycbcrLayout);
551 if (err) {
552 ALOGE("failed transaction: lockYCbCr");
Marissa Wall469b90a2019-11-06 10:12:43 -0800553 return C2_CORRUPTED;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700554 }
Marissa Wall2a24a302019-11-25 11:19:18 -0800555
Pawin Vongmasa36653902018-11-15 00:10:25 -0800556 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
557 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
558 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
559 layout->type = C2PlanarLayout::TYPE_YUV;
560 layout->numPlanes = 3;
561 layout->rootPlanes = 3;
562 layout->planes[C2PlanarLayout::PLANE_Y] = {
563 C2PlaneInfo::CHANNEL_Y, // channel
564 1, // colInc
Marissa Wall2a24a302019-11-25 11:19:18 -0800565 (int32_t)ycbcrLayout.ystride, // rowInc
Pawin Vongmasa36653902018-11-15 00:10:25 -0800566 1, // mColSampling
567 1, // mRowSampling
568 8, // allocatedDepth
569 8, // bitDepth
570 0, // rightShift
571 C2PlaneInfo::NATIVE, // endianness
572 C2PlanarLayout::PLANE_Y, // rootIx
573 0, // offset
574 };
575 layout->planes[C2PlanarLayout::PLANE_U] = {
576 C2PlaneInfo::CHANNEL_CB, // channel
Marissa Wall2a24a302019-11-25 11:19:18 -0800577 (int32_t)ycbcrLayout.chroma_step, // colInc
578 (int32_t)ycbcrLayout.cstride, // rowInc
Pawin Vongmasa36653902018-11-15 00:10:25 -0800579 2, // mColSampling
580 2, // mRowSampling
581 8, // allocatedDepth
582 8, // bitDepth
583 0, // rightShift
584 C2PlaneInfo::NATIVE, // endianness
585 C2PlanarLayout::PLANE_U, // rootIx
586 0, // offset
587 };
588 layout->planes[C2PlanarLayout::PLANE_V] = {
589 C2PlaneInfo::CHANNEL_CR, // channel
Marissa Wall2a24a302019-11-25 11:19:18 -0800590 (int32_t)ycbcrLayout.chroma_step, // colInc
591 (int32_t)ycbcrLayout.cstride, // rowInc
Pawin Vongmasa36653902018-11-15 00:10:25 -0800592 2, // mColSampling
593 2, // mRowSampling
594 8, // allocatedDepth
595 8, // bitDepth
596 0, // rightShift
597 C2PlaneInfo::NATIVE, // endianness
598 C2PlanarLayout::PLANE_V, // rootIx
599 0, // offset
600 };
601 // handle interleaved formats
602 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
Marissa Wall2a24a302019-11-25 11:19:18 -0800603 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800604 layout->rootPlanes = 2;
605 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
606 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
Marissa Wall2a24a302019-11-25 11:19:18 -0800607 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800608 layout->rootPlanes = 2;
609 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
610 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
611 }
612 break;
613 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800614 }
615 mLocked = true;
616
617 return C2_OK;
618}
619
620c2_status_t C2AllocationGralloc::unmap(
621 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
622 // TODO: check addr and size, use fence
623 (void)addr;
624 (void)rect;
Marissa Wall2a24a302019-11-25 11:19:18 -0800625 (void)fence;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800626
627 std::lock_guard<std::mutex> lock(mMappedLock);
Marissa Wall2a24a302019-11-25 11:19:18 -0800628 // TODO: fence
629 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
630 if (err) {
631 ALOGE("failed transaction: unlock");
632 return C2_CORRUPTED;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700633 }
Marissa Wall2a24a302019-11-25 11:19:18 -0800634
635 mLocked = false;
636 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800637}
638
639bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
640 return other && other->handle() == handle();
641}
642
643/* ===================================== GRALLOC ALLOCATOR ==================================== */
644class C2AllocatorGralloc::Impl {
645public:
646 Impl(id_t id, bool bufferQueue);
647
648 id_t getId() const {
649 return mTraits->id;
650 }
651
652 C2String getName() const {
653 return mTraits->name;
654 }
655
656 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
657 return mTraits;
658 }
659
660 c2_status_t newGraphicAllocation(
661 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
662 std::shared_ptr<C2GraphicAllocation> *allocation);
663
664 c2_status_t priorGraphicAllocation(
665 const C2Handle *handle,
666 std::shared_ptr<C2GraphicAllocation> *allocation);
667
668 c2_status_t status() const { return mInit; }
669
670private:
671 std::shared_ptr<C2Allocator::Traits> mTraits;
672 c2_status_t mInit;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800673 const bool mBufferQueue;
674};
675
676void _UnwrapNativeCodec2GrallocMetadata(
677 const C2Handle *const handle,
678 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
679 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
680 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
681 generation, igbp_id, igbp_slot);
682}
683
684C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
685 : mInit(C2_OK), mBufferQueue(bufferQueue) {
686 // TODO: get this from allocator
687 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
688 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
689 mTraits = std::make_shared<C2Allocator::Traits>(traits);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800690}
691
692c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
693 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
694 std::shared_ptr<C2GraphicAllocation> *allocation) {
695 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
696 ALOGV("allocating buffer with usage %#llx => %#llx",
697 (long long)usage.expected, (long long)grallocUsage);
698
Marissa Wall2a24a302019-11-25 11:19:18 -0800699 buffer_handle_t buffer;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700700
Marissa Wall2a24a302019-11-25 11:19:18 -0800701 uint32_t stride = 0;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700702
Marissa Wall2a24a302019-11-25 11:19:18 -0800703 status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
704 1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
705 if (err) {
706 ALOGE("failed transaction: allocate");
707 return C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800708 }
Marissa Wall2a24a302019-11-25 11:19:18 -0800709
710 hidl_handle hidlHandle;
711 hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
712
713 allocation->reset(new C2AllocationGralloc(
714 width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
715 C2HandleGralloc::WrapAndMoveNativeHandle(
716 hidlHandle, width, height,
717 format, grallocUsage, stride,
718 0, 0, mBufferQueue ? ~0 : 0),
719 mTraits->id));
720 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800721}
722
723c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
724 const C2Handle *handle,
725 std::shared_ptr<C2GraphicAllocation> *allocation) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700726
Marissa Wall2a24a302019-11-25 11:19:18 -0800727 uint32_t generation;
728 uint64_t igbp_id;
729 uint32_t igbp_slot;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700730
Marissa Wall2a24a302019-11-25 11:19:18 -0800731 uint32_t width;
732 uint32_t height;
733 uint32_t format;
734 uint32_t layerCount = 1;
735 uint64_t grallocUsage;
736 uint32_t stride;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700737
Marissa Wall2a24a302019-11-25 11:19:18 -0800738 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
739 handle, &width, &height, &format, &grallocUsage, &stride,
740 &generation, &igbp_id, &igbp_slot);
741 if (grallocHandle == nullptr) {
742 return C2_BAD_VALUE;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800743 }
Marissa Wall2a24a302019-11-25 11:19:18 -0800744
745 hidl_handle hidlHandle;
746 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
747
748 allocation->reset(new C2AllocationGralloc(
749 width, height, format, layerCount,
750 grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
751 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800752}
753
754C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
755 : mImpl(new Impl(id, bufferQueue)) {}
756
757C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
758
759C2Allocator::id_t C2AllocatorGralloc::getId() const {
760 return mImpl->getId();
761}
762
763C2String C2AllocatorGralloc::getName() const {
764 return mImpl->getName();
765}
766
767std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
768 return mImpl->getTraits();
769}
770
771c2_status_t C2AllocatorGralloc::newGraphicAllocation(
772 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
773 std::shared_ptr<C2GraphicAllocation> *allocation) {
774 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
775}
776
777c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
778 const C2Handle *handle,
779 std::shared_ptr<C2GraphicAllocation> *allocation) {
780 return mImpl->priorGraphicAllocation(handle, allocation);
781}
782
783c2_status_t C2AllocatorGralloc::status() const {
784 return mImpl->status();
785}
786
John Stultz653ddd12020-09-19 05:26:24 +0000787// static
788bool C2AllocatorGralloc::CheckHandle(const C2Handle* const o) {
789 return C2HandleGralloc::IsValid(o);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800790}
791
792} // namespace android