1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package androidx.opengl 17 18 import android.hardware.HardwareBuffer 19 import android.opengl.EGLDisplay 20 import android.os.Build 21 import androidx.annotation.IntDef 22 import androidx.annotation.RequiresApi 23 import androidx.annotation.RestrictTo 24 import androidx.graphics.opengl.egl.EGLConfigAttributes 25 import androidx.graphics.utils.JniVisible 26 import androidx.hardware.SyncFenceCompat 27 import androidx.hardware.SyncFenceV19 28 import androidx.opengl.EGLExt.Companion.eglCreateSyncKHR 29 30 /** Utility class that provides some helper methods for interacting EGL Extension APIs */ 31 class EGLExt private constructor() { 32 33 companion object { 34 35 /** 36 * Determines if applications can query the age of the back buffer contents for an EGL 37 * surface as the number of frames elapsed since the contents were recently defined 38 * 39 * See: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_buffer_age.txt 40 */ 41 const val EGL_EXT_BUFFER_AGE = "EGL_EXT_buffer_age" 42 43 /** 44 * Allows for efficient partial updates to an area of a **buffer** that has changed since 45 * the last time the buffer was used 46 * 47 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_partial_update.txt 48 */ 49 const val EGL_KHR_PARTIAL_UPDATE = "EGL_KHR_partial_update" 50 51 /** 52 * Allows for efficient partial updates to an area of a **surface** that changes between 53 * frames for the surface. This relates to the differences between two buffers, the current 54 * back buffer and the current front buffer. 55 * 56 * See: 57 * https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt 58 */ 59 const val EGL_KHR_SWAP_BUFFERS_WITH_DAMAGE = "EGL_KHR_swap_buffers_with_damage" 60 61 /** 62 * Determines whether to use sRGB format default framebuffers to render sRGB content to 63 * display devices. Supports creation of EGLSurfaces which will be rendered to in sRGB by 64 * OpenGL contexts supporting that capability. 65 * 66 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_gl_colorspace.txt 67 */ 68 const val EGL_KHR_GL_COLORSPACE = "EGL_KHR_gl_colorspace" 69 70 /** 71 * Determines whether creation of GL and ES contexts without an EGLConfig is allowed 72 * 73 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_no_config_context.txt 74 */ 75 const val EGL_KHR_NO_CONFIG_CONTEXT = "EGL_KHR_no_config_context" 76 77 /** 78 * Determines whether floating point RGBA components are supported 79 * 80 * See: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_pixel_format_float.txt 81 */ 82 const val EGL_EXT_PIXEL_FORMAT_FLOAT = "EGL_EXT_pixel_format_float" 83 84 /** 85 * Determines whether extended sRGB color spaces are supported options for EGL Surfaces 86 * 87 * See: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_gl_colorspace_scrgb.txt 88 */ 89 const val EGL_EXT_GL_COLORSPACE_SCRGB = "EGL_EXT_gl_colorspace_scrgb" 90 91 /** 92 * Determines whether the underlying platform can support rendering framebuffers in the 93 * non-linear Display-P3 color space 94 * 95 * See: 96 * https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_gl_colorspace_display_p3_passthrough.txt 97 */ 98 const val EGL_EXT_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH = 99 "EGL_EXT_gl_colorspace_display_p3_passthrough" 100 101 /** 102 * Determines whether the platform framebuffers support rendering in a larger color gamut 103 * specified in the BT.2020 color space 104 * 105 * See: 106 * https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_gl_colorspace_bt2020_linear.txt 107 */ 108 const val EGL_EXT_GL_COLORSPACE_BT2020_PQ = "EGL_EXT_gl_colorspace_bt2020_pq" 109 110 /** 111 * Determines whether an EGLContext can be created with a priority hint. Not all 112 * implementations are guaranteed to honor the hint. 113 * 114 * See: https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt 115 */ 116 const val EGL_IMG_CONTEXT_PRIORITY = "EGL_IMG_context_priority" 117 118 /** 119 * Determines whether creation of an EGL Context without a surface is supported. This is 120 * useful for applications that only want to render to client API targets (such as OpenGL 121 * framebuffer objects) and avoid the need to a throw-away EGL surface just to get a current 122 * context. 123 * 124 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_surfaceless_context.txt 125 */ 126 const val EGL_KHR_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context" 127 128 /** 129 * Determines whether sync objects are supported. Sync objects are synchronization 130 * primitives that represent events whose completion can be tested or waited upon. 131 * 132 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 133 */ 134 const val EGL_KHR_FENCE_SYNC = "EGL_KHR_fence_sync" 135 136 /** 137 * Determines whether waiting for signaling of sync objects is supported. This form of wait 138 * does not necessarily block the application thread which issued the wait. Therefore 139 * applications may continue to issue commands to the client API or perform other work in 140 * parallel leading to increased performance. 141 * 142 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_wait_sync.txt 143 */ 144 const val EGL_KHR_WAIT_SYNC = "EGL_KHR_wait_sync" 145 146 /** 147 * Determines whether creation of platform specific sync objects are supported. These 148 * objects that are associated with a native synchronization fence object using a file 149 * descriptor. 150 * 151 * See: 152 * https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_native_fence_sync.txt 153 */ 154 const val EGL_ANDROID_NATIVE_FENCE_SYNC = "EGL_ANDROID_native_fence_sync" 155 156 /** 157 * Enables using an Android window buffer (struct ANativeWindowBuffer) as an EGLImage source 158 * 159 * See: 160 * https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_image_native_buffer.txt 161 */ 162 const val EGL_ANDROID_IMAGE_NATIVE_BUFFER = "EGL_ANDROID_image_native_buffer" 163 164 /** 165 * Extension for supporting a new EGL resource type that is suitable for sharing 2D arrays 166 * of image data between client APIs, the EGLImage. Although the intended purpose is sharing 167 * 2D image data, the underlying interface makes no assumptions about the format or purpose 168 * of the resource being shared, leaving those decisions to the application and associated 169 * client APIs. 170 * 171 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_image_base.txt 172 */ 173 const val EGL_KHR_IMAGE_BASE = "EGL_KHR_image_base" 174 175 /** 176 * Extension that allows creating an EGLClientBuffer from an Android [HardwareBuffer] object 177 * which can later be used to create an [EGLImageKHR] instance. See: 178 * https://registry.khronos.org/EGL/extensions/ANDROID/EGL_ANDROID_get_native_client_buffer.txt 179 */ 180 const val EGL_ANDROID_CLIENT_BUFFER = "EGL_ANDROID_get_native_client_buffer" 181 182 /** 183 * Extension that defines a new EGL resource type that is suitable for sharing 2D arrays of 184 * image data between client APIs, the EGLImage, and allows creating EGLImages from EGL 185 * native pixmaps. 186 * 187 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_image.txt 188 */ 189 const val EGL_KHR_IMAGE = "EGL_KHR_image" 190 191 /** Specifies the types of attributes that can be queried in [eglGetSyncAttribKHR] */ 192 @RestrictTo(RestrictTo.Scope.LIBRARY) 193 @IntDef(value = [EGL_SYNC_TYPE_KHR, EGL_SYNC_STATUS_KHR, EGL_SYNC_CONDITION_KHR]) 194 annotation class EGLSyncAttribute 195 196 /** 197 * Attribute that can be queried in [eglGetSyncAttribKHR]. The results can be either 198 * [EGL_SYNC_FENCE_KHR] or [EGL_SYNC_NATIVE_FENCE_ANDROID]. 199 * 200 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 201 */ 202 const val EGL_SYNC_TYPE_KHR = 0x30F7 203 204 /** 205 * Attribute that can be queried in [eglGetSyncAttribKHR]. The results can be either 206 * [EGL_SIGNALED_KHR] or [EGL_UNSIGNALED_KHR] representing whether or not the sync object 207 * has been signalled or not. This can be queried on all sync object types. 208 * 209 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 210 */ 211 const val EGL_SYNC_STATUS_KHR = 0x30F1 212 213 /** 214 * Attribute that can be queried in [eglGetSyncAttribKHR]. This attribute can only be 215 * queried on sync objects of the type [EGL_SYNC_FENCE_KHR]. 216 * 217 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 218 */ 219 const val EGL_SYNC_CONDITION_KHR = 0x30F8 220 221 /** 222 * Return value when [eglGetSyncAttribKHR] is called with [EGL_SYNC_STATUS_KHR] indicating 223 * that the sync object has already been signalled. 224 * 225 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 226 */ 227 const val EGL_SIGNALED_KHR = 0x30F2 228 229 /** 230 * Return value when [eglGetSyncAttribKHR] is called with [EGL_SYNC_STATUS_KHR] indicating 231 * that the sync object has not yet been signalled. 232 * 233 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 234 */ 235 const val EGL_UNSIGNALED_KHR = 0x30F3 236 237 /** 238 * Return value when [eglGetSyncAttribKHR] is called with [EGL_SYNC_CONDITION_KHR]. This 239 * indicates that the sync object will signal on the condition of the completion of the 240 * fence command on the corresponding sync object and all preceding commands in th EGL 241 * client API's command stream. 242 */ 243 const val EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR = 0x30F0 244 245 /** Specifies the type of fence to create in [eglCreateSyncKHR] */ 246 @RestrictTo(RestrictTo.Scope.LIBRARY) 247 @IntDef(value = [EGL_SYNC_FENCE_KHR, EGL_SYNC_NATIVE_FENCE_ANDROID]) 248 annotation class EGLFenceType 249 250 /** 251 * Create an EGL fence sync object for signalling one time events. The fence object created 252 * is not associated with the Android Sync fence object and is not recommended for waiting 253 * for events in a portable manner across Android/EGL boundaries but rather other EGL 254 * primitives. 255 * 256 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 257 */ 258 const val EGL_SYNC_FENCE_KHR = 0x30F9 259 260 /** 261 * This extension enables the creation of EGL fence sync objects that are associated with a 262 * native synchronization fence object that is referenced using a file descriptor. These EGL 263 * fence sync objects have nearly identical semantics to those defined by the KHR_fence_sync 264 * extension, except that they have an additional attribute storing the file descriptor 265 * referring to the native fence object. This differs from EGL_SYNC_FENCE_KHR as the fence 266 * sync object is associated with an Android Sync HAL fence object. 267 * 268 * This extension assumes the existence of a native fence synchronization object that 269 * behaves similarly to an EGL fence sync object. These native objects must have a signal 270 * status like that of an EGLSyncKHR object that indicates whether the fence has ever been 271 * signaled. Once signaled the native object's signal status may not change again. 272 * 273 * See: 274 * https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_native_fence_sync.txt 275 */ 276 const val EGL_SYNC_NATIVE_FENCE_ANDROID = 0x3144 277 278 /** 279 * Value that can be sent as the timeoutNanos parameter of [eglClientWaitSyncKHR] indicating 280 * that waiting on the sync object to signal will never time out. 281 */ 282 // Note EGL has EGL_FOREVER_KHR defined as 0xFFFFFFFFFFFFFFFFuL. However, Java does not 283 // support unsigned long types. So use -1 as the constant value here as it will be casted 284 // as an EGLTimeKHR type which is uint64 in the corresponding JNI method 285 const val EGL_FOREVER_KHR = -1L 286 287 /** Specifies various return values for the [eglClientWaitSyncKHR] method */ 288 @RestrictTo(RestrictTo.Scope.LIBRARY) 289 @Target(AnnotationTarget.TYPE) 290 @IntDef(value = [EGL_CONDITION_SATISFIED_KHR, EGL_TIMEOUT_EXPIRED_KHR, EGL_FALSE]) 291 annotation class EGLClientWaitResult 292 293 /** 294 * Return value used in [eglClientWaitSyncKHR] to indicate that the specified timeout period 295 * had expired before a sync object was signalled. 296 */ 297 const val EGL_TIMEOUT_EXPIRED_KHR = 0x30F5 298 299 /** 300 * Return value used in [eglClientWaitSyncKHR] to indicate that the sync object had 301 * signalled before the timeout expired. This includes the case where the sync object had 302 * already signalled before [eglClientWaitSyncKHR] was called. 303 */ 304 const val EGL_CONDITION_SATISFIED_KHR = 0x30F6 305 306 /** 307 * Accepted in the flags parameter of [eglClientWaitSyncKHR]. This will implicitly ensure 308 * pending commands are flushed to prevent [eglClientWaitSyncKHR] from potentially blocking 309 * forever. See [eglClientWaitSyncKHR] for details. 310 */ 311 const val EGL_SYNC_FLUSH_COMMANDS_BIT_KHR = 0x0001 312 313 /** Constant indicating true within EGL. This is often returned in success cases. */ 314 const val EGL_TRUE = 1 315 316 /** Constant indicating false within EGL. This is often returned in failure cases. */ 317 const val EGL_FALSE = 0 318 319 /** 320 * Creates an EGLImage from the provided [HardwareBuffer]. This handles internally creating 321 * an EGLClientBuffer and an [EGLImageKHR] from the client buffer. 322 * 323 * When this [EGLImageKHR] instance is no longer necessary, consumers should be sure to call 324 * the corresponding method [eglDestroyImageKHR] to deallocate the resource. 325 * 326 * @param eglDisplay EGLDisplay connection associated with the EGLImage to create 327 * @param hardwareBuffer Backing [HardwareBuffer] for the generated EGLImage instance 328 * @return an [EGLImageKHR] instance representing the [EGLImageKHR] created from the 329 * HardwareBuffer. Because this is created internally through EGL's eglCreateImageKR 330 * method, this has the KHR suffix. 331 * 332 * This can return null if the EGL_ANDROID_image_native_buffer and EGL_KHR_image_base 333 * extensions are not supported or if allocation of the buffer fails. 334 * 335 * See 336 * www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_get_native_client_buffer.txt 337 */ 338 @JvmStatic 339 @RequiresApi(Build.VERSION_CODES.O) eglCreateImageFromHardwareBuffernull340 fun eglCreateImageFromHardwareBuffer( 341 eglDisplay: EGLDisplay, 342 hardwareBuffer: HardwareBuffer 343 ): EGLImageKHR? { 344 val handle = 345 EGLBindings.nCreateImageFromHardwareBuffer(eglDisplay.nativeHandle, hardwareBuffer) 346 return if (handle == 0L) { 347 null 348 } else { 349 EGLImageKHR(handle) 350 } 351 } 352 353 /** 354 * Destroy the given [EGLImageKHR] instance. Once destroyed, the image may not be used to 355 * create any additional [EGLImageKHR] target resources within any client API contexts, 356 * although existing [EGLImageKHR] siblings may continue to be used. `True` is returned if 357 * DestroyImageKHR succeeds, `false` indicates failure. This can return `false` if the 358 * [EGLImageKHR] is not associated with the default display. 359 * 360 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_image_base.txt 361 * 362 * @param eglDisplay EGLDisplay that this EGLImage is connected to 363 * @param image EGLImageKHR to be destroyed 364 * @return True if the destruction of the EGLImageKHR object was successful, false otherwise 365 */ 366 @JvmStatic eglDestroyImageKHRnull367 fun eglDestroyImageKHR(eglDisplay: EGLDisplay, image: EGLImageKHR): Boolean = 368 EGLBindings.nDestroyImageKHR(eglDisplay.nativeHandle, image.nativeHandle) 369 370 /** 371 * Upload a given EGLImage to the currently bound GLTexture 372 * 373 * This method requires either of the following EGL extensions to be supported: 374 * EGL_KHR_image_base or EGL_KHR_image 375 * 376 * See: https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt 377 */ 378 @JvmStatic 379 @Suppress("AcronymName") 380 fun glEGLImageTargetTexture2DOES(target: Int, image: EGLImageKHR) { 381 EGLBindings.nImageTargetTexture2DOES(target, image.nativeHandle) 382 } 383 384 /** 385 * Creates a sync object of the specified type associated with the specified display, and 386 * returns a handle to the new object. The configuration of the returned [EGLSyncKHR] object 387 * is specified by the provided attributes. 388 * 389 * Consumers should ensure that the EGL_KHR_fence_sync EGL extension is supported before 390 * invoking this method otherwise a null EGLSyncFenceKHR object is returned. 391 * 392 * Additionally when the [EGLSyncKHR] instance is no longer necessary, consumers are 393 * encouraged to call [eglDestroySyncKHR] to deallocate this resource. 394 * 395 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 396 * 397 * @param eglDisplay EGLDisplay to associate the sync object with 398 * @param type Indicates the type of sync object that is returned 399 * @param attributes Specifies the configuration of the sync object returned 400 * @return the EGLSyncKHR object to be used as a fence or null if this extension is not 401 * supported 402 */ 403 @JvmStatic eglCreateSyncKHRnull404 fun eglCreateSyncKHR( 405 eglDisplay: EGLDisplay, 406 @EGLFenceType type: Int, 407 attributes: EGLConfigAttributes? 408 ): EGLSyncKHR? { 409 val handle = 410 EGLBindings.nCreateSyncKHR(eglDisplay.nativeHandle, type, attributes?.attrs) 411 return if (handle == 0L) { 412 null 413 } else { 414 EGLSyncKHR(handle) 415 } 416 } 417 418 /** 419 * Query attributes of the provided sync object. Accepted attributes to query depend on the 420 * type of sync object. If no errors are generated, this returns true and the value of the 421 * queried attribute is stored in the value array at the offset position. If this method 422 * returns false, the provided value array is unmodified. 423 * 424 * See: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 425 * 426 * @param eglDisplay EGLDisplay to associate the sync object with 427 * @param sync EGLSyncKHR object to query attributes 428 * @param attribute Corresponding EGLSyncKHR attribute to query on [sync] 429 * @param value Integer array used to store the result of the query 430 * @param offset Index within the value array to store the result of the attribute query 431 * @return True if the attribute was queried successfully, false otherwise. Failure cases 432 * include attempting to call this method on an invalid sync object, or the display 433 * provided not matching the display that was used to create this sync object. 434 * Additionally if the queried attribute is not supported for the sync object, false is 435 * returned. 436 */ 437 @JvmStatic eglGetSyncAttribKHRnull438 fun eglGetSyncAttribKHR( 439 eglDisplay: EGLDisplay, 440 sync: EGLSyncKHR, 441 @EGLSyncAttribute attribute: Int, 442 value: IntArray, 443 offset: Int 444 ): Boolean = 445 EGLBindings.nGetSyncAttribKHR( 446 eglDisplay.nativeHandle, 447 sync.nativeHandle, 448 attribute, 449 value, 450 offset 451 ) 452 453 /** 454 * Blocks the calling thread until the specified sync object is signalled or until 455 * [timeoutNanos] nanoseconds have passed. More than one [eglClientWaitSyncKHR] may be 456 * outstanding on the same [sync] at any given time. When there are multiple threads blocked 457 * on the same [sync] and the [sync] object has signalled, all such threads are released, 458 * but the order in which they are released is not defined. 459 * 460 * If the value of [timeoutNanos] is zero, then [eglClientWaitSyncKHR] simply tests the 461 * current status of sync. If the value of [timeoutNanos] is the special value 462 * [EGL_FOREVER_KHR], then [eglClientWaitSyncKHR] does not time out. For all other values, 463 * [timeoutNanos] is adjusted to the closest value allowed by the implementation-dependent 464 * timeout accuracy, which may be substantially longer than one nanosecond. 465 * 466 * [eglClientWaitSyncKHR] returns one of three status values describing the reason for 467 * returning. A return value of [EGL_TIMEOUT_EXPIRED_KHR] indicates that the specified 468 * timeout period expired before [sync] was signalled, or if [timeoutNanos] is zero, 469 * indicates that [sync] is not signaled. A return value of [EGL_CONDITION_SATISFIED_KHR] 470 * indicates that [sync] was signaled before the timeout expired, which includes the case 471 * when [sync] was already signaled when [eglClientWaitSyncKHR] was called. If an error 472 * occurs then an error is generated and [EGL_FALSE] is returned. 473 * 474 * If the sync object being blocked upon will not be signaled in finite time (for example by 475 * an associated fence command issued previously, but not yet flushed to the graphics 476 * pipeline), then [eglClientWaitSyncKHR] may wait forever. To help prevent this behavior, 477 * if the [EGL_SYNC_FLUSH_COMMANDS_BIT_KHR] is set on the flags parameter and the [sync] is 478 * unsignaled when [eglClientWaitSyncKHR] is called, then the equivalent flush will be 479 * performed for the current EGL context before blocking on sync. If no context is current 480 * bound for the API, the [EGL_SYNC_FLUSH_COMMANDS_BIT_KHR] bit is ignored. 481 * 482 * @param eglDisplay EGLDisplay to associate the sync object with 483 * @param sync EGLSyncKHR object to wait on 484 * @param flags Optional flags to provide to handle flushing of pending commands 485 * @param timeoutNanos Optional timeout value to wait before this method returns, measured 486 * in nanoseconds. This value is always consumed as an unsigned long value so even 487 * negative values will be converted to their unsigned equivalent. 488 * @return Result code indicating the status of the wait request. Either 489 * [EGL_CONDITION_SATISFIED_KHR], if the sync did signal within the specified timeout, 490 * [EGL_TIMEOUT_EXPIRED_KHR] if the sync did not signal within the specified timeout, or 491 * [EGL_FALSE] if an error occurs. 492 */ 493 @JvmStatic 494 fun eglClientWaitSyncKHR( 495 eglDisplay: EGLDisplay, 496 sync: EGLSyncKHR, 497 flags: Int, 498 timeoutNanos: Long 499 ): @EGLClientWaitResult Int = 500 EGLBindings.nClientWaitSyncKHR( 501 eglDisplay.nativeHandle, 502 sync.nativeHandle, 503 flags, 504 timeoutNanos 505 ) 506 507 /** 508 * Creates a native synchronization fence referenced through a file descriptor that is 509 * associated with an EGL fence sync object. 510 * 511 * See: 512 * https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_native_fence_sync.txt 513 * 514 * @param display The EGLDisplay connection 515 * @param sync The EGLSyncKHR to fetch the [SyncFenceCompat] from 516 * @return A [SyncFenceCompat] representing the native fence. If [sync] is not a valid sync 517 * object for [display], an invalid [SyncFenceCompat] instance is returned and an 518 * EGL_BAD_PARAMETER error is generated. If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute 519 * of [sync] is EGL_NO_NATIVE_FENCE_FD_ANDROID, an invalid [SyncFenceCompat] is returned 520 * and an EGL_BAD_PARAMETER error is generated. If [display] does not match the display 521 * passed to [eglCreateSyncKHR] when [sync] was created, the behavior is undefined. 522 */ 523 @JvmStatic 524 @Suppress("AcronymName") 525 internal fun eglDupNativeFenceFDANDROID( 526 display: EGLDisplay, 527 sync: EGLSyncKHR 528 ): SyncFenceCompat { 529 val fd = EGLBindings.nDupNativeFenceFDANDROID(display.nativeHandle, sync.nativeHandle) 530 return if (fd >= 0) { 531 SyncFenceCompat(SyncFenceV19(fd)) 532 } else { 533 SyncFenceCompat(SyncFenceV19(-1)) 534 } 535 } 536 537 /** 538 * Destroys the given sync object associated with the specified display 539 * 540 * Consumers should ensure that the EGL_KHR_fence_sync EGL extension is supported before 541 * invoking this method otherwise a null EGLSyncFenceKHR object is returned. See: 542 * https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_fence_sync.txt 543 * 544 * @param eglDisplay EGLDisplay instance associated with the fence 545 * @param eglSync Fence object to be destroyed 546 * @return true if the EGLSyncKHR object was destroyed successfully false otherwise. This 547 * can return false if the sync object is not a valid sync object for the provided display 548 * or if the display provided in this method does not match the display used to create 549 * this sync in eglCreateSyncKHR. 550 */ 551 @JvmStatic eglDestroySyncKHRnull552 fun eglDestroySyncKHR(eglDisplay: EGLDisplay, eglSync: EGLSyncKHR): Boolean = 553 EGLBindings.nDestroySyncKHR(eglDisplay.nativeHandle, eglSync.nativeHandle) 554 555 /** 556 * Returns a set of supported supported extensions from a space separated string that 557 * represents the set of OpenGL extensions supported 558 */ 559 @JvmStatic 560 fun parseExtensions(queryString: String): Set<String> = 561 HashSet<String>().apply { addAll(queryString.split(' ')) } 562 } 563 } 564 565 /** 566 * Helper class to configure JNI bindings to be invoked within the EGLUtils public API. This class 567 * is provided to separate responsibilities of jni method registration and helps to avoid synthetic 568 * accessor warnings 569 */ 570 @JniVisible 571 internal class EGLBindings { 572 companion object { 573 @JvmStatic 574 @JniVisible nCreateImageFromHardwareBuffernull575 external fun nCreateImageFromHardwareBuffer( 576 eglDisplayPtr: Long, 577 hardwareBuffer: HardwareBuffer 578 ): Long 579 580 // Note this API is explicitly a GL API and not an EGL API which is the reason 581 // why this has the GL prefix vs EGL 582 @JvmStatic @JniVisible external fun nImageTargetTexture2DOES(target: Int, eglImagePtr: Long) 583 584 @JvmStatic 585 @JniVisible 586 external fun nDupNativeFenceFDANDROID(eglDisplayPtr: Long, syncPtr: Long): Int 587 588 @JvmStatic 589 @JniVisible 590 external fun nCreateSyncKHR(eglDisplayPtr: Long, type: Int, attrs: IntArray?): Long 591 592 @JvmStatic 593 @JniVisible 594 external fun nGetSyncAttribKHR( 595 eglDisplayPtr: Long, 596 syncPtr: Long, 597 attrib: Int, 598 result: IntArray, 599 offset: Int 600 ): Boolean 601 602 @JvmStatic 603 @JniVisible 604 external fun nClientWaitSyncKHR( 605 eglDisplayPtr: Long, 606 syncPtr: Long, 607 flags: Int, 608 timeout: Long 609 ): Int 610 611 @JvmStatic 612 @JniVisible 613 external fun nDestroySyncKHR(eglDisplayPtr: Long, syncPtr: Long): Boolean 614 615 @JvmStatic 616 @JniVisible 617 external fun nDestroyImageKHR(eglDisplayPtr: Long, eglImagePtr: Long): Boolean 618 619 @JvmStatic @JniVisible external fun nSupportsEglGetNativeClientBufferAndroid(): Boolean 620 621 @JvmStatic @JniVisible external fun nSupportsDupNativeFenceFDANDROID(): Boolean 622 623 @JvmStatic @JniVisible external fun nSupportsEglCreateImageKHR(): Boolean 624 625 @JvmStatic @JniVisible external fun nSupportsEglDestroyImageKHR(): Boolean 626 627 @JvmStatic @JniVisible external fun nSupportsGlImageTargetTexture2DOES(): Boolean 628 629 @JvmStatic @JniVisible external fun nSupportsEglCreateSyncKHR(): Boolean 630 631 @JvmStatic @JniVisible external fun nSupportsEglGetSyncAttribKHR(): Boolean 632 633 @JvmStatic @JniVisible external fun nSupportsEglClientWaitSyncKHR(): Boolean 634 635 @JvmStatic @JniVisible external fun nSupportsEglDestroySyncKHR(): Boolean 636 637 @JvmStatic 638 @JniVisible 639 external fun nEqualToNativeForeverTimeout(timeoutNanos: Long): Boolean 640 641 init { 642 System.loadLibrary("graphics-core") 643 } 644 } 645 } 646