• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Taken from nativebase/nativebase.h
49 // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
50 #define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
51 
52 #define ANDROID_NATIVE_MAKE_CONSTANT(a, b, c, d)                                         \
53     ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
54      (ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | (ANDROID_NATIVE_UNSIGNED_CAST(d)))
55 
56 #define ANDROID_NATIVE_BUFFER_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_', 'b', 'f', 'r')
57 
58 typedef struct android_native_base_t
59 {
60     /* a magic value defined by the actual EGL native type */
61     int magic;
62     /* the sizeof() of the actual EGL native type */
63     int version;
64     void *reserved[4];
65     /* reference-counting interface */
66     void (*incRef)(struct android_native_base_t *base);
67     void (*decRef)(struct android_native_base_t *base);
68 } android_native_base_t;
69 
70 typedef struct ANativeWindowBuffer
71 {
72     struct android_native_base_t common;
73     int width;
74     int height;
75     int stride;
76     int format;
77     int usage_deprecated;
78     uintptr_t layerCount;
79     void *reserved[1];
80     const native_handle_t *handle;
81     uint64_t usage;
82     // we needed extra space for storing the 64-bits usage flags
83     // the number of slots to use from reserved_proc depends on the
84     // architecture.
85     void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
86 } ANativeWindowBuffer_t;
87 
88 namespace angle
89 {
90 
91 namespace android
92 {
93 
94 namespace
95 {
96 
97 // In the Android system:
98 // - AHardwareBuffer is essentially a typedef of GraphicBuffer. Conversion functions simply
99 // reinterpret_cast.
100 // - GraphicBuffer inherits from two base classes, ANativeWindowBuffer and RefBase.
101 //
102 // GraphicBuffer implements a getter for ANativeWindowBuffer (getNativeBuffer) by static_casting
103 // itself to its base class ANativeWindowBuffer. The offset of the ANativeWindowBuffer pointer
104 // from the GraphicBuffer pointer is 16 bytes. This is likely due to two pointers: The vtable of
105 // GraphicBuffer and the one pointer member of the RefBase class.
106 //
107 // This is not future proof at all. We need to look into getting utilities added to Android to
108 // perform this cast for us.
109 constexpr int kAHardwareBufferToANativeWindowBufferOffset = static_cast<int>(sizeof(void *)) * 2;
110 
111 template <typename T1, typename T2>
OffsetPointer(T2 * ptr,int bytes)112 T1 *OffsetPointer(T2 *ptr, int bytes)
113 {
114     return reinterpret_cast<T1 *>(reinterpret_cast<intptr_t>(ptr) + bytes);
115 }
116 
GetPixelFormatInfo(int pixelFormat,bool * isYUV)117 GLenum GetPixelFormatInfo(int pixelFormat, bool *isYUV)
118 {
119     *isYUV = false;
120     switch (pixelFormat)
121     {
122         case ANGLE_AHB_FORMAT_R8G8B8A8_UNORM:
123             return GL_RGBA8;
124         case ANGLE_AHB_FORMAT_R8G8B8X8_UNORM:
125             return GL_RGB8;
126         case ANGLE_AHB_FORMAT_R8G8B8_UNORM:
127             return GL_RGB8;
128         case ANGLE_AHB_FORMAT_R5G6B5_UNORM:
129             return GL_RGB565;
130         case ANGLE_AHB_FORMAT_B8G8R8A8_UNORM:
131             return GL_BGRA8_EXT;
132         case ANGLE_AHB_FORMAT_B5G5R5A1_UNORM:
133             return GL_RGB5_A1;
134         case ANGLE_AHB_FORMAT_B4G4R4A4_UNORM:
135             return GL_RGBA4;
136         case ANGLE_AHB_FORMAT_R16G16B16A16_FLOAT:
137             return GL_RGBA16F;
138         case ANGLE_AHB_FORMAT_R10G10B10A2_UNORM:
139             return GL_RGB10_A2;
140         case ANGLE_AHB_FORMAT_BLOB:
141             return GL_NONE;
142         case ANGLE_AHB_FORMAT_D16_UNORM:
143             return GL_DEPTH_COMPONENT16;
144         case ANGLE_AHB_FORMAT_D24_UNORM:
145             return GL_DEPTH_COMPONENT24;
146         case ANGLE_AHB_FORMAT_D24_UNORM_S8_UINT:
147             return GL_DEPTH24_STENCIL8;
148         case ANGLE_AHB_FORMAT_D32_FLOAT:
149             return GL_DEPTH_COMPONENT32F;
150         case ANGLE_AHB_FORMAT_D32_FLOAT_S8_UINT:
151             return GL_DEPTH32F_STENCIL8;
152         case ANGLE_AHB_FORMAT_S8_UINT:
153             return GL_STENCIL_INDEX8;
154         case ANGLE_AHB_FORMAT_R8_UNORM:
155             return GL_R8;
156         case ANGLE_AHB_FORMAT_Y8Cb8Cr8_420:
157         case ANGLE_AHB_FORMAT_YV12:
158         case ANGLE_AHB_FORMAT_IMPLEMENTATION_DEFINED:
159             *isYUV = true;
160             return GL_RGB8;
161         default:
162             // Treat unknown formats as RGB. They are vendor-specific YUV formats that would sample
163             // as RGB.
164             *isYUV = true;
165             return GL_RGB8;
166     }
167 }
168 
169 }  // anonymous namespace
170 
ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)171 ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)
172 {
173     return reinterpret_cast<ANativeWindowBuffer *>(clientBuffer);
174 }
175 
IsValidNativeWindowBuffer(ANativeWindowBuffer * windowBuffer)176 bool IsValidNativeWindowBuffer(ANativeWindowBuffer *windowBuffer)
177 {
178     return windowBuffer->common.magic == ANDROID_NATIVE_BUFFER_MAGIC;
179 }
180 
GetAHBUsage(int eglNativeBufferUsage)181 uint64_t GetAHBUsage(int eglNativeBufferUsage)
182 {
183     uint64_t ahbUsage = 0;
184 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
185     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID)
186     {
187         ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
188     }
189     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID)
190     {
191         ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
192     }
193     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)
194     {
195         ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
196     }
197 #endif  // ANGLE_AHARDWARE_BUFFER_SUPPORT
198     return ahbUsage;
199 }
200 
CreateEGLClientBufferFromAHardwareBuffer(int width,int height,int depth,int androidFormat,int usage)201 EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width,
202                                                          int height,
203                                                          int depth,
204                                                          int androidFormat,
205                                                          int usage)
206 {
207 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
208 
209     // The height and width are number of pixels of size format
210     AHardwareBuffer_Desc aHardwareBufferDescription = {};
211     aHardwareBufferDescription.width                = static_cast<uint32_t>(width);
212     aHardwareBufferDescription.height               = static_cast<uint32_t>(height);
213     aHardwareBufferDescription.layers               = static_cast<uint32_t>(depth);
214     aHardwareBufferDescription.format               = androidFormat;
215     aHardwareBufferDescription.usage                = GetAHBUsage(usage);
216 
217     // Allocate memory from Android Hardware Buffer
218     AHardwareBuffer *aHardwareBuffer = nullptr;
219     int res = AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer);
220     if (res != 0)
221     {
222         return nullptr;
223     }
224 
225     return AHardwareBufferToClientBuffer(aHardwareBuffer);
226 #else
227     return nullptr;
228 #endif  // ANGLE_AHARDWARE_BUFFER_SUPPORT
229 }
230 
GetANativeWindowBufferProperties(const ANativeWindowBuffer * buffer,int * width,int * height,int * depth,int * pixelFormat,uint64_t * usage)231 void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
232                                       int *width,
233                                       int *height,
234                                       int *depth,
235                                       int *pixelFormat,
236                                       uint64_t *usage)
237 {
238     *width       = buffer->width;
239     *height      = buffer->height;
240     *depth       = static_cast<int>(buffer->layerCount);
241     *height      = buffer->height;
242     *pixelFormat = buffer->format;
243     *usage       = buffer->usage;
244 }
245 
NativePixelFormatToGLInternalFormat(int pixelFormat)246 GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
247 {
248     bool isYuv = false;
249     return GetPixelFormatInfo(pixelFormat, &isYuv);
250 }
251 
GLInternalFormatToNativePixelFormat(GLenum internalFormat)252 int GLInternalFormatToNativePixelFormat(GLenum internalFormat)
253 {
254     switch (internalFormat)
255     {
256         case GL_R8:
257             return ANGLE_AHB_FORMAT_R8_UNORM;
258         case GL_RGBA8:
259             return ANGLE_AHB_FORMAT_R8G8B8A8_UNORM;
260         case GL_RGB8:
261             return ANGLE_AHB_FORMAT_R8G8B8X8_UNORM;
262         case GL_RGB565:
263             return ANGLE_AHB_FORMAT_R5G6B5_UNORM;
264         case GL_BGRA8_EXT:
265             return ANGLE_AHB_FORMAT_B8G8R8A8_UNORM;
266         case GL_RGB5_A1:
267             return ANGLE_AHB_FORMAT_B5G5R5A1_UNORM;
268         case GL_RGBA4:
269             return ANGLE_AHB_FORMAT_B4G4R4A4_UNORM;
270         case GL_RGBA16F:
271             return ANGLE_AHB_FORMAT_R16G16B16A16_FLOAT;
272         case GL_RGB10_A2:
273             return ANGLE_AHB_FORMAT_R10G10B10A2_UNORM;
274         case GL_NONE:
275             return ANGLE_AHB_FORMAT_BLOB;
276         case GL_DEPTH_COMPONENT16:
277             return ANGLE_AHB_FORMAT_D16_UNORM;
278         case GL_DEPTH_COMPONENT24:
279             return ANGLE_AHB_FORMAT_D24_UNORM;
280         case GL_DEPTH24_STENCIL8:
281             return ANGLE_AHB_FORMAT_D24_UNORM_S8_UINT;
282         case GL_DEPTH_COMPONENT32F:
283             return ANGLE_AHB_FORMAT_D32_FLOAT;
284         case GL_DEPTH32F_STENCIL8:
285             return ANGLE_AHB_FORMAT_D32_FLOAT_S8_UINT;
286         case GL_STENCIL_INDEX8:
287             return ANGLE_AHB_FORMAT_S8_UINT;
288         default:
289             WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0";
290             return 0;
291     }
292 }
293 
NativePixelFormatIsYUV(int pixelFormat)294 bool NativePixelFormatIsYUV(int pixelFormat)
295 {
296     bool isYuv = false;
297     GetPixelFormatInfo(pixelFormat, &isYuv);
298     return isYuv;
299 }
300 
ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer * windowBuffer)301 AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer *windowBuffer)
302 {
303     return OffsetPointer<AHardwareBuffer>(windowBuffer,
304                                           -kAHardwareBufferToANativeWindowBufferOffset);
305 }
306 
AHardwareBufferToClientBuffer(const AHardwareBuffer * hardwareBuffer)307 EGLClientBuffer AHardwareBufferToClientBuffer(const AHardwareBuffer *hardwareBuffer)
308 {
309     return OffsetPointer<EGLClientBuffer>(hardwareBuffer,
310                                           kAHardwareBufferToANativeWindowBufferOffset);
311 }
312 
ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)313 AHardwareBuffer *ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)
314 {
315     return OffsetPointer<AHardwareBuffer>(clientBuffer,
316                                           -kAHardwareBufferToANativeWindowBufferOffset);
317 }
318 
GetSystemProperty(const char * propertyName,std::string * value)319 bool GetSystemProperty(const char *propertyName, std::string *value)
320 {
321 #if defined(ANGLE_PLATFORM_ANDROID)
322     // PROP_VALUE_MAX from <sys/system_properties.h>
323     std::vector<char> propertyBuf(PROP_VALUE_MAX);
324     int len = __system_property_get(propertyName, propertyBuf.data());
325     if (len <= 0)
326     {
327         return false;
328     }
329     *value = std::string(propertyBuf.data());
330     return true;
331 #else
332     return false;
333 #endif
334 }
335 
336 }  // namespace android
337 }  // namespace angle
338