xref: /aosp_15_r20/external/angle/src/common/android_util.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // android_util.cpp: Utilities for the using the Android platform
8 
9 #include "common/android_util.h"
10 #include "common/debug.h"
11 
12 #if defined(ANGLE_PLATFORM_ANDROID)
13 #    include <sys/system_properties.h>
14 #endif
15 
16 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
17 #    define ANGLE_AHARDWARE_BUFFER_SUPPORT
18 // NDK header file for access to Android Hardware Buffers
19 #    include <android/hardware_buffer.h>
20 #endif
21 
22 // Taken from cutils/native_handle.h:
23 // https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
24 typedef struct native_handle
25 {
26     int version; /* sizeof(native_handle_t) */
27     int numFds;  /* number of file-descriptors at &data[0] */
28     int numInts; /* number of ints at &data[numFds] */
29 #if defined(__clang__)
30 #    pragma clang diagnostic push
31 #    pragma clang diagnostic ignored "-Wzero-length-array"
32 #elif defined(_MSC_VER)
33 #    pragma warning(push)
34 #    pragma warning(disable : 4200)
35 #endif
36     int data[0]; /* numFds + numInts ints */
37 #if defined(__clang__)
38 #    pragma clang diagnostic pop
39 #elif defined(_MSC_VER)
40 #    pragma warning(pop)
41 #endif
42 } native_handle_t;
43 
44 // Taken from nativebase/nativebase.h
45 // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
46 typedef const native_handle_t *buffer_handle_t;
47 
48 typedef struct android_native_base_t
49 {
50     /* a magic value defined by the actual EGL native type */
51     int magic;
52     /* the sizeof() of the actual EGL native type */
53     int version;
54     void *reserved[4];
55     /* reference-counting interface */
56     void (*incRef)(struct android_native_base_t *base);
57     void (*decRef)(struct android_native_base_t *base);
58 } android_native_base_t;
59 
60 typedef struct ANativeWindowBuffer
61 {
62     struct android_native_base_t common;
63     int width;
64     int height;
65     int stride;
66     int format;
67     int usage_deprecated;
68     uintptr_t layerCount;
69     void *reserved[1];
70     const native_handle_t *handle;
71     uint64_t usage;
72     // we needed extra space for storing the 64-bits usage flags
73     // the number of slots to use from reserved_proc depends on the
74     // architecture.
75     void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
76 } ANativeWindowBuffer_t;
77 
78 namespace angle
79 {
80 
81 namespace android
82 {
83 
84 namespace
85 {
86 
87 // In the Android system:
88 // - AHardwareBuffer is essentially a typedef of GraphicBuffer. Conversion functions simply
89 // reinterpret_cast.
90 // - GraphicBuffer inherits from two base classes, ANativeWindowBuffer and RefBase.
91 //
92 // GraphicBuffer implements a getter for ANativeWindowBuffer (getNativeBuffer) by static_casting
93 // itself to its base class ANativeWindowBuffer. The offset of the ANativeWindowBuffer pointer
94 // from the GraphicBuffer pointer is 16 bytes. This is likely due to two pointers: The vtable of
95 // GraphicBuffer and the one pointer member of the RefBase class.
96 //
97 // This is not future proof at all. We need to look into getting utilities added to Android to
98 // perform this cast for us.
99 constexpr int kAHardwareBufferToANativeWindowBufferOffset = static_cast<int>(sizeof(void *)) * 2;
100 
101 template <typename T1, typename T2>
OffsetPointer(T2 * ptr,int bytes)102 T1 *OffsetPointer(T2 *ptr, int bytes)
103 {
104     return reinterpret_cast<T1 *>(reinterpret_cast<intptr_t>(ptr) + bytes);
105 }
106 
GetPixelFormatInfo(int pixelFormat,bool * isYUV)107 GLenum GetPixelFormatInfo(int pixelFormat, bool *isYUV)
108 {
109     *isYUV = false;
110     switch (pixelFormat)
111     {
112         case ANGLE_AHB_FORMAT_R8G8B8A8_UNORM:
113             return GL_RGBA8;
114         case ANGLE_AHB_FORMAT_R8G8B8X8_UNORM:
115             return GL_RGB8;
116         case ANGLE_AHB_FORMAT_R8G8B8_UNORM:
117             return GL_RGB8;
118         case ANGLE_AHB_FORMAT_R5G6B5_UNORM:
119             return GL_RGB565;
120         case ANGLE_AHB_FORMAT_B8G8R8A8_UNORM:
121             return GL_BGRA8_EXT;
122         case ANGLE_AHB_FORMAT_B5G5R5A1_UNORM:
123             return GL_RGB5_A1;
124         case ANGLE_AHB_FORMAT_B4G4R4A4_UNORM:
125             return GL_RGBA4;
126         case ANGLE_AHB_FORMAT_R16G16B16A16_FLOAT:
127             return GL_RGBA16F;
128         case ANGLE_AHB_FORMAT_R10G10B10A2_UNORM:
129             return GL_RGB10_A2;
130         case ANGLE_AHB_FORMAT_BLOB:
131             return GL_NONE;
132         case ANGLE_AHB_FORMAT_D16_UNORM:
133             return GL_DEPTH_COMPONENT16;
134         case ANGLE_AHB_FORMAT_D24_UNORM:
135             return GL_DEPTH_COMPONENT24;
136         case ANGLE_AHB_FORMAT_D24_UNORM_S8_UINT:
137             return GL_DEPTH24_STENCIL8;
138         case ANGLE_AHB_FORMAT_D32_FLOAT:
139             return GL_DEPTH_COMPONENT32F;
140         case ANGLE_AHB_FORMAT_D32_FLOAT_S8_UINT:
141             return GL_DEPTH32F_STENCIL8;
142         case ANGLE_AHB_FORMAT_S8_UINT:
143             return GL_STENCIL_INDEX8;
144         case ANGLE_AHB_FORMAT_R8_UNORM:
145             return GL_R8;
146         case ANGLE_AHB_FORMAT_Y8Cb8Cr8_420:
147         case ANGLE_AHB_FORMAT_YV12:
148         case ANGLE_AHB_FORMAT_IMPLEMENTATION_DEFINED:
149             *isYUV = true;
150             return GL_RGB8;
151         default:
152             // Treat unknown formats as RGB. They are vendor-specific YUV formats that would sample
153             // as RGB.
154             *isYUV = true;
155             return GL_RGB8;
156     }
157 }
158 
159 }  // anonymous namespace
160 
ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)161 ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)
162 {
163     return reinterpret_cast<ANativeWindowBuffer *>(clientBuffer);
164 }
165 
GetAHBUsage(int eglNativeBufferUsage)166 uint64_t GetAHBUsage(int eglNativeBufferUsage)
167 {
168     uint64_t ahbUsage = 0;
169 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
170     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID)
171     {
172         ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
173     }
174     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID)
175     {
176         ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
177     }
178     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)
179     {
180         ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
181     }
182 #endif  // ANGLE_AHARDWARE_BUFFER_SUPPORT
183     return ahbUsage;
184 }
185 
CreateEGLClientBufferFromAHardwareBuffer(int width,int height,int depth,int androidFormat,int usage)186 EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width,
187                                                          int height,
188                                                          int depth,
189                                                          int androidFormat,
190                                                          int usage)
191 {
192 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
193 
194     // The height and width are number of pixels of size format
195     AHardwareBuffer_Desc aHardwareBufferDescription = {};
196     aHardwareBufferDescription.width                = static_cast<uint32_t>(width);
197     aHardwareBufferDescription.height               = static_cast<uint32_t>(height);
198     aHardwareBufferDescription.layers               = static_cast<uint32_t>(depth);
199     aHardwareBufferDescription.format               = androidFormat;
200     aHardwareBufferDescription.usage                = GetAHBUsage(usage);
201 
202     // Allocate memory from Android Hardware Buffer
203     AHardwareBuffer *aHardwareBuffer = nullptr;
204     int res = AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer);
205     if (res != 0)
206     {
207         return nullptr;
208     }
209 
210     return AHardwareBufferToClientBuffer(aHardwareBuffer);
211 #else
212     return nullptr;
213 #endif  // ANGLE_AHARDWARE_BUFFER_SUPPORT
214 }
215 
GetANativeWindowBufferProperties(const ANativeWindowBuffer * buffer,int * width,int * height,int * depth,int * pixelFormat,uint64_t * usage)216 void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
217                                       int *width,
218                                       int *height,
219                                       int *depth,
220                                       int *pixelFormat,
221                                       uint64_t *usage)
222 {
223     *width       = buffer->width;
224     *height      = buffer->height;
225     *depth       = static_cast<int>(buffer->layerCount);
226     *height      = buffer->height;
227     *pixelFormat = buffer->format;
228     *usage       = buffer->usage;
229 }
230 
NativePixelFormatToGLInternalFormat(int pixelFormat)231 GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
232 {
233     bool isYuv = false;
234     return GetPixelFormatInfo(pixelFormat, &isYuv);
235 }
236 
GLInternalFormatToNativePixelFormat(GLenum internalFormat)237 int GLInternalFormatToNativePixelFormat(GLenum internalFormat)
238 {
239     switch (internalFormat)
240     {
241         case GL_R8:
242             return ANGLE_AHB_FORMAT_R8_UNORM;
243         case GL_RGBA8:
244             return ANGLE_AHB_FORMAT_R8G8B8A8_UNORM;
245         case GL_RGB8:
246             return ANGLE_AHB_FORMAT_R8G8B8X8_UNORM;
247         case GL_RGB565:
248             return ANGLE_AHB_FORMAT_R5G6B5_UNORM;
249         case GL_BGRA8_EXT:
250             return ANGLE_AHB_FORMAT_B8G8R8A8_UNORM;
251         case GL_RGB5_A1:
252             return ANGLE_AHB_FORMAT_B5G5R5A1_UNORM;
253         case GL_RGBA4:
254             return ANGLE_AHB_FORMAT_B4G4R4A4_UNORM;
255         case GL_RGBA16F:
256             return ANGLE_AHB_FORMAT_R16G16B16A16_FLOAT;
257         case GL_RGB10_A2:
258             return ANGLE_AHB_FORMAT_R10G10B10A2_UNORM;
259         case GL_NONE:
260             return ANGLE_AHB_FORMAT_BLOB;
261         case GL_DEPTH_COMPONENT16:
262             return ANGLE_AHB_FORMAT_D16_UNORM;
263         case GL_DEPTH_COMPONENT24:
264             return ANGLE_AHB_FORMAT_D24_UNORM;
265         case GL_DEPTH24_STENCIL8:
266             return ANGLE_AHB_FORMAT_D24_UNORM_S8_UINT;
267         case GL_DEPTH_COMPONENT32F:
268             return ANGLE_AHB_FORMAT_D32_FLOAT;
269         case GL_DEPTH32F_STENCIL8:
270             return ANGLE_AHB_FORMAT_D32_FLOAT_S8_UINT;
271         case GL_STENCIL_INDEX8:
272             return ANGLE_AHB_FORMAT_S8_UINT;
273         default:
274             WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0";
275             return 0;
276     }
277 }
278 
NativePixelFormatIsYUV(int pixelFormat)279 bool NativePixelFormatIsYUV(int pixelFormat)
280 {
281     bool isYuv = false;
282     GetPixelFormatInfo(pixelFormat, &isYuv);
283     return isYuv;
284 }
285 
ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer * windowBuffer)286 AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer *windowBuffer)
287 {
288     return OffsetPointer<AHardwareBuffer>(windowBuffer,
289                                           -kAHardwareBufferToANativeWindowBufferOffset);
290 }
291 
AHardwareBufferToClientBuffer(const AHardwareBuffer * hardwareBuffer)292 EGLClientBuffer AHardwareBufferToClientBuffer(const AHardwareBuffer *hardwareBuffer)
293 {
294     return OffsetPointer<EGLClientBuffer>(hardwareBuffer,
295                                           kAHardwareBufferToANativeWindowBufferOffset);
296 }
297 
ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)298 AHardwareBuffer *ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)
299 {
300     return OffsetPointer<AHardwareBuffer>(clientBuffer,
301                                           -kAHardwareBufferToANativeWindowBufferOffset);
302 }
303 
GetSystemProperty(const char * propertyName,std::string * value)304 bool GetSystemProperty(const char *propertyName, std::string *value)
305 {
306 #if defined(ANGLE_PLATFORM_ANDROID)
307     // PROP_VALUE_MAX from <sys/system_properties.h>
308     std::vector<char> propertyBuf(PROP_VALUE_MAX);
309     int len = __system_property_get(propertyName, propertyBuf.data());
310     if (len <= 0)
311     {
312         return false;
313     }
314     *value = std::string(propertyBuf.data());
315     return true;
316 #else
317     return false;
318 #endif
319 }
320 
321 }  // namespace android
322 }  // namespace angle
323