/* * Copyright (C) 2017-2020 ARM Limited. All rights reserved. * * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MALI_GRALLOC_BUFFER_H_ #define MALI_GRALLOC_BUFFER_H_ #include #include #include #include #include #include #include #include #include /* the max string size of GRALLOC_HARDWARE_GPU0 & GRALLOC_HARDWARE_FB0 * 8 is big enough for "gpu0" & "fb0" currently */ #define MALI_GRALLOC_HARDWARE_MAX_STR_LEN 8 /* Define number of shared file descriptors. Not guaranteed to be constant for a private_handle_t object * as fds that do not get initialized may instead be treated as integers. */ #define NUM_INTS_IN_PRIVATE_HANDLE ((sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int)) #define SZ_4K 0x00001000 #define SZ_2M 0x00200000 /* * Maximum number of pixel format planes. * Plane [0]: Single plane formats (inc. RGB, YUV) and Y * Plane [1]: U/V, UV * Plane [2]: V/U */ #define MAX_PLANES 3 /* * Maximum number of fds in a private_handle_t. */ #define MAX_FDS 4 /* * One fd is reserved for metadata dmabuf. */ #define MAX_BUFFER_FDS MAX_FDS - 1 /* * In the worst case, there will be one plane per fd. */ static_assert(MAX_BUFFER_FDS == MAX_PLANES, "MAX_PLANES and MAX_BUFFER_FDS defines do not match"); #ifdef __cplusplus #define DEFAULT_INITIALIZER(x) = x #else #define DEFAULT_INITIALIZER(x) #endif typedef struct plane_info { /* * Offset to plane (in bytes), * from the start of the allocation. */ int64_t offset; uint32_t fd_idx; uint64_t size; /* * Byte Stride: number of bytes between two vertically adjacent * pixels in given plane. This can be mathematically described by: * * byte_stride = ALIGN((alloc_width * bpp)/8, alignment) * * where, * * alloc_width: width of plane in pixels (c.f. pixel_stride) * bpp: average bits per pixel * alignment (in bytes): dependent upon pixel format and usage * * For uncompressed allocations, byte_stride might contain additional * padding beyond the alloc_width. For AFBC, alignment is zero. */ uint64_t byte_stride; /* * Dimensions of plane (in pixels). * * For single plane formats, pixels equates to luma samples. * For multi-plane formats, pixels equates to the number of sample sites * for the corresponding plane, even if subsampled. * * AFBC compressed formats: requested width/height are rounded-up * to a whole AFBC superblock/tile (next superblock at minimum). * Uncompressed formats: dimensions typically match width and height * but might require pixel stride alignment. * * See 'byte_stride' for relationship between byte_stride and alloc_width. * * Any crop rectangle defined by GRALLOC_ARM_BUFFER_ATTR_CROP_RECT must * be wholly within the allocation dimensions. The crop region top-left * will be relative to the start of allocation. */ uint64_t alloc_width; uint64_t alloc_height; } plane_info_t; struct private_handle_t; #ifndef __cplusplus /* C99 with pedantic don't allow anonymous unions which is used in below struct * Disable pedantic for C for this struct only. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #endif #ifdef __cplusplus struct private_handle_t : public native_handle { private: /* Having a default constructor makes sure that we zero out the padding * which prevents data leak. */ private_handle_t() = default; public: #else struct private_handle_t { struct native_handle nativeHandle; #endif #ifdef __cplusplus /* Never intended to be used from C code */ enum { PRIV_FLAGS_USES_2PRIVATE_DATA = 1U << 4, PRIV_FLAGS_USES_3PRIVATE_DATA = 1U << 5, }; enum { LOCK_STATE_WRITE = 1 << 31, LOCK_STATE_MAPPED = 1 << 30, LOCK_STATE_READ_MASK = 0x3FFFFFFF }; #endif /* * Shared file descriptor for dma_buf sharing. This must be the first element in the * structure so that binder knows where it is and can properly share it between * processes. * DO NOT MOVE THIS ELEMENT! */ union { int fds[MAX_FDS]; }; // ints int magic DEFAULT_INITIALIZER(sMagic); int flags DEFAULT_INITIALIZER(0); /* * Number of dmabuf fds, NOT including the metadata fd */ int fd_count DEFAULT_INITIALIZER(1); /* * Input properties. * * req_format: Pixel format, base + private modifiers. * width/height: Buffer dimensions. * producer/consumer_usage: Buffer usage (indicates IP) */ int width DEFAULT_INITIALIZER(0); int height DEFAULT_INITIALIZER(0); int req_format DEFAULT_INITIALIZER(0); uint64_t producer_usage DEFAULT_INITIALIZER(0); uint64_t consumer_usage DEFAULT_INITIALIZER(0); /* * DEPRECATED members. * Equivalent information can be obtained from other fields: * * - 'internal_format' --> alloc_format * - 'stride' (pixel stride) ~= plane_info[0].alloc_width * - 'byte_stride' ~= plane_info[0].byte_stride * - 'internalWidth' ~= plane_info[0].alloc_width * - 'internalHeight' ~= plane_info[0].alloc_height * * '~=' (approximately equal) is used because the fields were either previously * incorrectly populated by gralloc or the meaning has slightly changed. * * NOTE: 'stride' values sometimes vary significantly from plane_info[0].alloc_width. */ uint64_t stride DEFAULT_INITIALIZER(0); /* * Allocation properties. * * alloc_format: Pixel format (base + modifiers). NOTE: base might differ from requested * format (req_format) where fallback to single-plane format was required. * plane_info: Per plane allocation information. * size: Total bytes allocated for buffer (inc. all planes, layers. etc.). * layer_count: Number of layers allocated to buffer. * All layers are the same size (in bytes). * Multi-layers supported in v1.0, where GRALLOC1_CAPABILITY_LAYERED_BUFFERS is enabled. * Layer size: 'size' / 'layer_count'. * Layer (n) offset: n * ('size' / 'layer_count'), n=0 for the first layer. * */ uint64_t alloc_format DEFAULT_INITIALIZER(0); plane_info_t plane_info[MAX_PLANES] DEFAULT_INITIALIZER({}); uint32_t layer_count DEFAULT_INITIALIZER(0); uint64_t backing_store_id DEFAULT_INITIALIZER(0x0); int cpu_read DEFAULT_INITIALIZER(0); /**< Buffer is locked for CPU read when non-zero. */ int cpu_write DEFAULT_INITIALIZER(0); /**< Buffer is locked for CPU write when non-zero. */ // locally mapped shared attribute area int ion_handles[MAX_BUFFER_FDS]; uint64_t alloc_sizes[MAX_BUFFER_FDS]; off_t offset __attribute__((aligned (8))) DEFAULT_INITIALIZER(0); /* Size of the attribute shared region in bytes. */ uint64_t attr_size __attribute__((aligned (8))) DEFAULT_INITIALIZER(0); uint64_t reserved_region_size DEFAULT_INITIALIZER(0); uint64_t imapper_version DEFAULT_INITIALIZER(0); #ifdef __cplusplus /* * We track the number of integers in the structure. There are 16 unconditional * integers (magic - pid, yuv_info, fd and offset). Note that the fd element is * considered an int not an fd because it is not intended to be used outside the * surface flinger process. The GRALLOC_ARM_NUM_INTS variable is used to track the * number of integers that are conditionally included. Similar considerations apply * to the number of fds. */ static const int sMagic = 0x3141592; private_handle_t( int _flags, uint64_t _alloc_sizes[MAX_BUFFER_FDS], uint64_t _consumer_usage, uint64_t _producer_usage, int _fds[MAX_FDS], int _fd_count, int _req_format, uint64_t _alloc_format, int _width, int _height, uint64_t _stride, uint64_t _layer_count, plane_info_t _plane_info[MAX_PLANES]) : private_handle_t() { flags = _flags; fd_count = _fd_count; width = _width; height = _height; req_format = _req_format; producer_usage = _producer_usage; consumer_usage = _consumer_usage; stride = _stride; alloc_format = _alloc_format; layer_count = _layer_count; version = sizeof(native_handle); set_numfds(fd_count); memcpy(plane_info, _plane_info, sizeof(plane_info_t) * MAX_PLANES); if (_fds) memcpy(fds, _fds, sizeof(fds)); else memset(fds, -1, sizeof(fds)); if (_alloc_sizes) memcpy(alloc_sizes, _alloc_sizes, sizeof(alloc_sizes)); memset(ion_handles, 0, sizeof(ion_handles)); } ~private_handle_t() { magic = 0; } /* Set the number of allocated fds in the handle to n*/ void set_numfds(int n) { int total_ints = (sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int); numFds = n; numInts = total_ints - n; } /* Increments number of allocated fds in the handle by n */ int incr_numfds(int n) { numFds += n; numInts -= n; return numFds; } static int validate(const native_handle *h) { const private_handle_t *hnd = (const private_handle_t *)h; // Always validate for native_handle members before validating // private_handle_t members if (!h || h->version != sizeof(native_handle) || h->numFds + h->numInts != NUM_INTS_IN_PRIVATE_HANDLE) { return -EINVAL; } if (hnd->magic != sMagic) { return -EINVAL; } return 0; } bool is_multi_plane() const { /* For multi-plane, the byte stride for the second plane will always be non-zero. */ return (plane_info[1].byte_stride != 0); } uint64_t get_usage() const { return producer_usage | consumer_usage; } int get_share_attr_fd_index() const { /* share_attr can be at idx 1 to MAX_FDS */ if (fd_count <= 0 || fd_count > MAX_FDS) return -1; return fd_count; } int get_share_attr_fd() const { int idx = get_share_attr_fd_index(); if (idx <= 0) return -1; return fds[idx]; } void set_share_attr_fd(int fd) { int idx = get_share_attr_fd_index(); if (idx <= 0) return; fds[idx] = fd; } void close_share_attr_fd() { int fd = get_share_attr_fd(); if (fd < 0) return; close(fd); } void dump(const char *str) const { ALOGE("[%s] " "numInts(%d) numFds(%d) fd_count(%d) " "fd(%d %d %d %d) " "flags(%d) " "wh(%d %d) " "req_format(%#x) alloc_format(%#" PRIx64 ") " "usage_pc(0x%" PRIx64 " 0x%" PRIx64 ") " "stride(%" PRIu64 ") " "psize(%" PRIu64 ") byte_stride(%" PRIu64 ") internal_wh(%" PRIu64 " %" PRIu64 ") " "psize1(%" PRIu64 ") byte_stride1(%" PRIu64 ") internal_wh1(%" PRIu64 " %" PRIu64 ") " "psize2(%" PRIu64 ") byte_stride2(%" PRIu64 ") internal_wh2(%" PRIu64 " %" PRIu64 ") " "alloc_format(0x%" PRIx64 ") " "alloc_sizes(%" PRIu64 " %" PRIu64 " %" PRIu64 ") " "layer_count(%d) " "\n", str, numInts, numFds, fd_count, fds[0], fds[1], fds[2], fds[3], flags, width, height, req_format, alloc_format, producer_usage, consumer_usage, stride, plane_info[0].size, plane_info[0].byte_stride, plane_info[0].alloc_width, plane_info[0].alloc_height, plane_info[1].size, plane_info[1].byte_stride, plane_info[1].alloc_width, plane_info[1].alloc_height, plane_info[2].size, plane_info[2].byte_stride, plane_info[2].alloc_width, plane_info[2].alloc_height, alloc_format, alloc_sizes[0], alloc_sizes[1], alloc_sizes[2], layer_count ); } int get_alloc_format() const { return (int)(alloc_format & 0x00000000ffffffffULL); } static private_handle_t *dynamicCast(const native_handle *in) { if (validate(in) == 0) { return (private_handle_t *)in; } return NULL; } #endif }; #ifndef __cplusplus /* Restore previous diagnostic for pedantic */ #pragma GCC diagnostic pop #endif // The size of private_handle_t is calculated manually. This check ensures that private_handle_t has // the same layout for 32-bit and 64-bit processes. static_assert(sizeof(private_handle_t) == 328); #endif /* MALI_GRALLOC_BUFFER_H_ */