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 #include <cstdint>
13
14 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
15 # define ANGLE_AHARDWARE_BUFFER_SUPPORT
16 // NDK header file for access to Android Hardware Buffers
17 # include <android/hardware_buffer.h>
18 #endif
19
20 // Taken from cutils/native_handle.h:
21 // https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
22 typedef struct native_handle
23 {
24 int version; /* sizeof(native_handle_t) */
25 int numFds; /* number of file-descriptors at &data[0] */
26 int numInts; /* number of ints at &data[numFds] */
27 #if defined(__clang__)
28 # pragma clang diagnostic push
29 # pragma clang diagnostic ignored "-Wzero-length-array"
30 #elif defined(_MSC_VER)
31 # pragma warning(push)
32 # pragma warning(disable : 4200)
33 #endif
34 int data[0]; /* numFds + numInts ints */
35 #if defined(__clang__)
36 # pragma clang diagnostic pop
37 #elif defined(_MSC_VER)
38 # pragma warning(pop)
39 #endif
40 } native_handle_t;
41
42 // Taken from nativebase/nativebase.h
43 // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
44 typedef const native_handle_t *buffer_handle_t;
45
46 typedef struct android_native_base_t
47 {
48 /* a magic value defined by the actual EGL native type */
49 int magic;
50 /* the sizeof() of the actual EGL native type */
51 int version;
52 void *reserved[4];
53 /* reference-counting interface */
54 void (*incRef)(struct android_native_base_t *base);
55 void (*decRef)(struct android_native_base_t *base);
56 } android_native_base_t;
57
58 typedef struct ANativeWindowBuffer
59 {
60 struct android_native_base_t common;
61 int width;
62 int height;
63 int stride;
64 int format;
65 int usage_deprecated;
66 uintptr_t layerCount;
67 void *reserved[1];
68 const native_handle_t *handle;
69 uint64_t usage;
70 // we needed extra space for storing the 64-bits usage flags
71 // the number of slots to use from reserved_proc depends on the
72 // architecture.
73 void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
74 } ANativeWindowBuffer_t;
75
76 // Taken from android/hardware_buffer.h
77 // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h
78
79 // AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM,
80 // AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM formats were deprecated and re-added explicitly.
81
82 // clang-format off
83 /**
84 * Buffer pixel formats.
85 */
86 enum {
87
88 #ifndef ANGLE_AHARDWARE_BUFFER_SUPPORT
89 /**
90 * Corresponding formats:
91 * Vulkan: VK_FORMAT_R8G8B8A8_UNORM
92 * OpenGL ES: GL_RGBA8
93 */
94 AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
95
96 /**
97 * 32 bits per pixel, 8 bits per channel format where alpha values are
98 * ignored (always opaque).
99 * Corresponding formats:
100 * Vulkan: VK_FORMAT_R8G8B8A8_UNORM
101 * OpenGL ES: GL_RGB8
102 */
103 AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2,
104
105 /**
106 * Corresponding formats:
107 * Vulkan: VK_FORMAT_R8G8B8_UNORM
108 * OpenGL ES: GL_RGB8
109 */
110 AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3,
111
112 /**
113 * Corresponding formats:
114 * Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16
115 * OpenGL ES: GL_RGB565
116 */
117 AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4,
118 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
119
120 AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5,
121 AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 6,
122 AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 7,
123
124 #ifndef ANGLE_AHARDWARE_BUFFER_SUPPORT
125 /**
126 * Corresponding formats:
127 * Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT
128 * OpenGL ES: GL_RGBA16F
129 */
130 AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16,
131
132 /**
133 * Corresponding formats:
134 * Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32
135 * OpenGL ES: GL_RGB10_A2
136 */
137 AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b,
138
139 /**
140 * An opaque binary blob format that must have height 1, with width equal to
141 * the buffer size in bytes.
142 */
143 AHARDWAREBUFFER_FORMAT_BLOB = 0x21,
144
145 /**
146 * Corresponding formats:
147 * Vulkan: VK_FORMAT_D16_UNORM
148 * OpenGL ES: GL_DEPTH_COMPONENT16
149 */
150 AHARDWAREBUFFER_FORMAT_D16_UNORM = 0x30,
151
152 /**
153 * Corresponding formats:
154 * Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32
155 * OpenGL ES: GL_DEPTH_COMPONENT24
156 */
157 AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31,
158
159 /**
160 * Corresponding formats:
161 * Vulkan: VK_FORMAT_D24_UNORM_S8_UINT
162 * OpenGL ES: GL_DEPTH24_STENCIL8
163 */
164 AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT = 0x32,
165
166 /**
167 * Corresponding formats:
168 * Vulkan: VK_FORMAT_D32_SFLOAT
169 * OpenGL ES: GL_DEPTH_COMPONENT32F
170 */
171 AHARDWAREBUFFER_FORMAT_D32_FLOAT = 0x33,
172
173 /**
174 * Corresponding formats:
175 * Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT
176 * OpenGL ES: GL_DEPTH32F_STENCIL8
177 */
178 AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT = 0x34,
179
180 /**
181 * Corresponding formats:
182 * Vulkan: VK_FORMAT_S8_UINT
183 * OpenGL ES: GL_STENCIL_INDEX8
184 */
185 AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35,
186
187 /**
188 * YUV 420 888 format.
189 * Must have an even width and height. Can be accessed in OpenGL
190 * shaders through an external sampler. Does not support mip-maps
191 * cube-maps or multi-layered textures.
192 */
193 AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23,
194
195 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
196 };
197 // clang-format on
198
199 namespace
200 {
201
202 // In the Android system:
203 // - AHardwareBuffer is essentially a typedef of GraphicBuffer. Conversion functions simply
204 // reinterpret_cast.
205 // - GraphicBuffer inherits from two base classes, ANativeWindowBuffer and RefBase.
206 //
207 // GraphicBuffer implements a getter for ANativeWindowBuffer (getNativeBuffer) by static_casting
208 // itself to its base class ANativeWindowBuffer. The offset of the ANativeWindowBuffer pointer
209 // from the GraphicBuffer pointer is 16 bytes. This is likely due to two pointers: The vtable of
210 // GraphicBuffer and the one pointer member of the RefBase class.
211 //
212 // This is not future proof at all. We need to look into getting utilities added to Android to
213 // perform this cast for us.
214 constexpr int kAHardwareBufferToANativeWindowBufferOffset = static_cast<int>(sizeof(void *)) * 2;
215
216 template <typename T1, typename T2>
offsetPointer(T2 * ptr,int bytes)217 T1 *offsetPointer(T2 *ptr, int bytes)
218 {
219 return reinterpret_cast<T1 *>(reinterpret_cast<intptr_t>(ptr) + bytes);
220 }
221
getPixelFormatInfo(int pixelFormat,bool * isYUV)222 GLenum getPixelFormatInfo(int pixelFormat, bool *isYUV)
223 {
224 *isYUV = false;
225 switch (pixelFormat)
226 {
227 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
228 return GL_RGBA8;
229 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
230 return GL_RGB8;
231 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
232 return GL_RGB8;
233 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
234 return GL_RGB565;
235 case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
236 return GL_BGRA8_EXT;
237 case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM:
238 return GL_RGB5_A1;
239 case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM:
240 return GL_RGBA4;
241 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
242 return GL_RGBA16F;
243 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
244 return GL_RGB10_A2;
245 case AHARDWAREBUFFER_FORMAT_BLOB:
246 return GL_NONE;
247 case AHARDWAREBUFFER_FORMAT_D16_UNORM:
248 return GL_DEPTH_COMPONENT16;
249 case AHARDWAREBUFFER_FORMAT_D24_UNORM:
250 return GL_DEPTH_COMPONENT24;
251 case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
252 return GL_DEPTH24_STENCIL8;
253 case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
254 return GL_DEPTH_COMPONENT32F;
255 case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
256 return GL_DEPTH32F_STENCIL8;
257 case AHARDWAREBUFFER_FORMAT_S8_UINT:
258 return GL_STENCIL_INDEX8;
259 case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
260 *isYUV = true;
261 return GL_RGB8;
262 default:
263 // Treat unknown formats as RGB. They are vendor-specific YUV formats that would sample
264 // as RGB.
265 WARN() << "Unknown pixelFormat: " << pixelFormat << ". Treating as RGB8";
266 *isYUV = true;
267 return GL_RGB8;
268 }
269 }
270
271 } // anonymous namespace
272
273 namespace angle
274 {
275
276 namespace android
277 {
278
ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)279 ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)
280 {
281 return reinterpret_cast<ANativeWindowBuffer *>(clientBuffer);
282 }
283
GetAHBUsage(int eglNativeBufferUsage)284 uint64_t GetAHBUsage(int eglNativeBufferUsage)
285 {
286 uint64_t ahbUsage = 0;
287 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
288 if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID)
289 {
290 ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
291 }
292 if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID)
293 {
294 ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
295 }
296 if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)
297 {
298 ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
299 }
300 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
301 return ahbUsage;
302 }
303
CreateEGLClientBufferFromAHardwareBuffer(int width,int height,int depth,int androidFormat,int usage)304 EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width,
305 int height,
306 int depth,
307 int androidFormat,
308 int usage)
309 {
310 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
311
312 // The height and width are number of pixels of size format
313 AHardwareBuffer_Desc aHardwareBufferDescription = {};
314 aHardwareBufferDescription.width = static_cast<uint32_t>(width);
315 aHardwareBufferDescription.height = static_cast<uint32_t>(height);
316 aHardwareBufferDescription.layers = static_cast<uint32_t>(depth);
317 aHardwareBufferDescription.format = androidFormat;
318 aHardwareBufferDescription.usage = GetAHBUsage(usage);
319
320 // Allocate memory from Android Hardware Buffer
321 AHardwareBuffer *aHardwareBuffer = nullptr;
322 int res = AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer);
323 if (res != 0)
324 {
325 return nullptr;
326 }
327
328 return AHardwareBufferToClientBuffer(aHardwareBuffer);
329 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
330 return nullptr;
331 }
332
GetANativeWindowBufferProperties(const ANativeWindowBuffer * buffer,int * width,int * height,int * depth,int * pixelFormat)333 void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
334 int *width,
335 int *height,
336 int *depth,
337 int *pixelFormat)
338 {
339 *width = buffer->width;
340 *height = buffer->height;
341 *depth = static_cast<int>(buffer->layerCount);
342 *height = buffer->height;
343 *pixelFormat = buffer->format;
344 }
345
NativePixelFormatToGLInternalFormat(int pixelFormat)346 GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
347 {
348 bool isYuv = false;
349 return getPixelFormatInfo(pixelFormat, &isYuv);
350 }
351
GLInternalFormatToNativePixelFormat(GLenum internalFormat)352 int GLInternalFormatToNativePixelFormat(GLenum internalFormat)
353 {
354 switch (internalFormat)
355 {
356 case GL_RGBA8:
357 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
358 case GL_RGB8:
359 return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
360 case GL_RGB565:
361 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
362 case GL_BGRA8_EXT:
363 return AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
364 case GL_RGB5_A1:
365 return AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM;
366 case GL_RGBA4:
367 return AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM;
368 case GL_RGBA16F:
369 return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
370 case GL_RGB10_A2:
371 return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
372 case GL_NONE:
373 return AHARDWAREBUFFER_FORMAT_BLOB;
374 case GL_DEPTH_COMPONENT16:
375 return AHARDWAREBUFFER_FORMAT_D16_UNORM;
376 case GL_DEPTH_COMPONENT24:
377 return AHARDWAREBUFFER_FORMAT_D24_UNORM;
378 case GL_DEPTH24_STENCIL8:
379 return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT;
380 case GL_DEPTH_COMPONENT32F:
381 return AHARDWAREBUFFER_FORMAT_D32_FLOAT;
382 case GL_DEPTH32F_STENCIL8:
383 return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT;
384 case GL_STENCIL_INDEX8:
385 return AHARDWAREBUFFER_FORMAT_S8_UINT;
386 default:
387 WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0";
388 return 0;
389 }
390 }
391
NativePixelFormatIsYUV(int pixelFormat)392 bool NativePixelFormatIsYUV(int pixelFormat)
393 {
394 bool isYuv = false;
395 getPixelFormatInfo(pixelFormat, &isYuv);
396 return isYuv;
397 }
398
ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer * windowBuffer)399 AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer *windowBuffer)
400 {
401 return offsetPointer<AHardwareBuffer>(windowBuffer,
402 -kAHardwareBufferToANativeWindowBufferOffset);
403 }
404
AHardwareBufferToClientBuffer(const AHardwareBuffer * hardwareBuffer)405 EGLClientBuffer AHardwareBufferToClientBuffer(const AHardwareBuffer *hardwareBuffer)
406 {
407 return offsetPointer<EGLClientBuffer>(hardwareBuffer,
408 kAHardwareBufferToANativeWindowBufferOffset);
409 }
410
ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)411 AHardwareBuffer *ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)
412 {
413 return offsetPointer<AHardwareBuffer>(clientBuffer,
414 -kAHardwareBufferToANativeWindowBufferOffset);
415 }
416 } // namespace android
417 } // namespace angle
418