• 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 #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     AHARDWAREBUFFER_FORMAT_YV12                     = 0x32315659
198 };
199 // clang-format on
200 
201 namespace
202 {
203 
204 // In the Android system:
205 // - AHardwareBuffer is essentially a typedef of GraphicBuffer. Conversion functions simply
206 // reinterpret_cast.
207 // - GraphicBuffer inherits from two base classes, ANativeWindowBuffer and RefBase.
208 //
209 // GraphicBuffer implements a getter for ANativeWindowBuffer (getNativeBuffer) by static_casting
210 // itself to its base class ANativeWindowBuffer. The offset of the ANativeWindowBuffer pointer
211 // from the GraphicBuffer pointer is 16 bytes. This is likely due to two pointers: The vtable of
212 // GraphicBuffer and the one pointer member of the RefBase class.
213 //
214 // This is not future proof at all. We need to look into getting utilities added to Android to
215 // perform this cast for us.
216 constexpr int kAHardwareBufferToANativeWindowBufferOffset = static_cast<int>(sizeof(void *)) * 2;
217 
218 template <typename T1, typename T2>
offsetPointer(T2 * ptr,int bytes)219 T1 *offsetPointer(T2 *ptr, int bytes)
220 {
221     return reinterpret_cast<T1 *>(reinterpret_cast<intptr_t>(ptr) + bytes);
222 }
223 
getPixelFormatInfo(int pixelFormat,bool * isYUV)224 GLenum getPixelFormatInfo(int pixelFormat, bool *isYUV)
225 {
226     *isYUV = false;
227     switch (pixelFormat)
228     {
229         case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
230             return GL_RGBA8;
231         case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
232             return GL_RGB8;
233         case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
234             return GL_RGB8;
235         case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
236             return GL_RGB565;
237         case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
238             return GL_BGRA8_EXT;
239         case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM:
240             return GL_RGB5_A1;
241         case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM:
242             return GL_RGBA4;
243         case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
244             return GL_RGBA16F;
245         case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
246             return GL_RGB10_A2;
247         case AHARDWAREBUFFER_FORMAT_BLOB:
248             return GL_NONE;
249         case AHARDWAREBUFFER_FORMAT_D16_UNORM:
250             return GL_DEPTH_COMPONENT16;
251         case AHARDWAREBUFFER_FORMAT_D24_UNORM:
252             return GL_DEPTH_COMPONENT24;
253         case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
254             return GL_DEPTH24_STENCIL8;
255         case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
256             return GL_DEPTH_COMPONENT32F;
257         case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
258             return GL_DEPTH32F_STENCIL8;
259         case AHARDWAREBUFFER_FORMAT_S8_UINT:
260             return GL_STENCIL_INDEX8;
261         case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
262         case AHARDWAREBUFFER_FORMAT_YV12:
263             *isYUV = true;
264             return GL_RGB8;
265         default:
266             // Treat unknown formats as RGB. They are vendor-specific YUV formats that would sample
267             // as RGB.
268             WARN() << "Unknown pixelFormat: " << pixelFormat << ". Treating as RGB8";
269             *isYUV = true;
270             return GL_RGB8;
271     }
272 }
273 
274 }  // anonymous namespace
275 
276 namespace angle
277 {
278 
279 namespace android
280 {
281 
ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)282 ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)
283 {
284     return reinterpret_cast<ANativeWindowBuffer *>(clientBuffer);
285 }
286 
GetAHBUsage(int eglNativeBufferUsage)287 uint64_t GetAHBUsage(int eglNativeBufferUsage)
288 {
289     uint64_t ahbUsage = 0;
290 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
291     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID)
292     {
293         ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
294     }
295     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID)
296     {
297         ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
298     }
299     if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)
300     {
301         ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
302     }
303 #endif  // ANGLE_AHARDWARE_BUFFER_SUPPORT
304     return ahbUsage;
305 }
306 
CreateEGLClientBufferFromAHardwareBuffer(int width,int height,int depth,int androidFormat,int usage)307 EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width,
308                                                          int height,
309                                                          int depth,
310                                                          int androidFormat,
311                                                          int usage)
312 {
313 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
314 
315     // The height and width are number of pixels of size format
316     AHardwareBuffer_Desc aHardwareBufferDescription = {};
317     aHardwareBufferDescription.width                = static_cast<uint32_t>(width);
318     aHardwareBufferDescription.height               = static_cast<uint32_t>(height);
319     aHardwareBufferDescription.layers               = static_cast<uint32_t>(depth);
320     aHardwareBufferDescription.format               = androidFormat;
321     aHardwareBufferDescription.usage                = GetAHBUsage(usage);
322 
323     // Allocate memory from Android Hardware Buffer
324     AHardwareBuffer *aHardwareBuffer = nullptr;
325     int res = AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer);
326     if (res != 0)
327     {
328         return nullptr;
329     }
330 
331     return AHardwareBufferToClientBuffer(aHardwareBuffer);
332 #else
333     return nullptr;
334 #endif  // ANGLE_AHARDWARE_BUFFER_SUPPORT
335 }
336 
GetANativeWindowBufferProperties(const ANativeWindowBuffer * buffer,int * width,int * height,int * depth,int * pixelFormat,uint64_t * usage)337 void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
338                                       int *width,
339                                       int *height,
340                                       int *depth,
341                                       int *pixelFormat,
342                                       uint64_t *usage)
343 {
344     *width       = buffer->width;
345     *height      = buffer->height;
346     *depth       = static_cast<int>(buffer->layerCount);
347     *height      = buffer->height;
348     *pixelFormat = buffer->format;
349     *usage       = buffer->usage;
350 }
351 
NativePixelFormatToGLInternalFormat(int pixelFormat)352 GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
353 {
354     bool isYuv = false;
355     return getPixelFormatInfo(pixelFormat, &isYuv);
356 }
357 
GLInternalFormatToNativePixelFormat(GLenum internalFormat)358 int GLInternalFormatToNativePixelFormat(GLenum internalFormat)
359 {
360     switch (internalFormat)
361     {
362         case GL_RGBA8:
363             return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
364         case GL_RGB8:
365             return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
366         case GL_RGB565:
367             return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
368         case GL_BGRA8_EXT:
369             return AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
370         case GL_RGB5_A1:
371             return AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM;
372         case GL_RGBA4:
373             return AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM;
374         case GL_RGBA16F:
375             return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
376         case GL_RGB10_A2:
377             return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
378         case GL_NONE:
379             return AHARDWAREBUFFER_FORMAT_BLOB;
380         case GL_DEPTH_COMPONENT16:
381             return AHARDWAREBUFFER_FORMAT_D16_UNORM;
382         case GL_DEPTH_COMPONENT24:
383             return AHARDWAREBUFFER_FORMAT_D24_UNORM;
384         case GL_DEPTH24_STENCIL8:
385             return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT;
386         case GL_DEPTH_COMPONENT32F:
387             return AHARDWAREBUFFER_FORMAT_D32_FLOAT;
388         case GL_DEPTH32F_STENCIL8:
389             return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT;
390         case GL_STENCIL_INDEX8:
391             return AHARDWAREBUFFER_FORMAT_S8_UINT;
392         default:
393             WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0";
394             return 0;
395     }
396 }
397 
NativePixelFormatIsYUV(int pixelFormat)398 bool NativePixelFormatIsYUV(int pixelFormat)
399 {
400     bool isYuv = false;
401     getPixelFormatInfo(pixelFormat, &isYuv);
402     return isYuv;
403 }
404 
ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer * windowBuffer)405 AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer *windowBuffer)
406 {
407     return offsetPointer<AHardwareBuffer>(windowBuffer,
408                                           -kAHardwareBufferToANativeWindowBufferOffset);
409 }
410 
AHardwareBufferToClientBuffer(const AHardwareBuffer * hardwareBuffer)411 EGLClientBuffer AHardwareBufferToClientBuffer(const AHardwareBuffer *hardwareBuffer)
412 {
413     return offsetPointer<EGLClientBuffer>(hardwareBuffer,
414                                           kAHardwareBufferToANativeWindowBufferOffset);
415 }
416 
ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)417 AHardwareBuffer *ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer)
418 {
419     return offsetPointer<AHardwareBuffer>(clientBuffer,
420                                           -kAHardwareBufferToANativeWindowBufferOffset);
421 }
422 }  // namespace android
423 }  // namespace angle
424