diff options
Diffstat (limited to 'opengl')
72 files changed, 5945 insertions, 2488 deletions
diff --git a/opengl/include/EGL/Platform.h b/opengl/include/EGL/Platform.h new file mode 100644 index 0000000000..f2b501cdec --- /dev/null +++ b/opengl/include/EGL/Platform.h @@ -0,0 +1,338 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Platform.h: The public interface ANGLE exposes to the API layer, for +// doing platform-specific tasks like gathering data, or for tracing. + +#ifndef ANGLE_PLATFORM_H +#define ANGLE_PLATFORM_H + +#include <stdint.h> +#include <array> + +#define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x3482 + +#if defined(_WIN32) +# if !defined(LIBANGLE_IMPLEMENTATION) +# define ANGLE_PLATFORM_EXPORT __declspec(dllimport) +# else +# define ANGLE_PLATFORM_EXPORT __declspec(dllexport) +# endif +#elif defined(__GNUC__) || defined(__clang__) +# define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default"))) +#endif +#if !defined(ANGLE_PLATFORM_EXPORT) +# define ANGLE_PLATFORM_EXPORT +#endif + +#if defined(_WIN32) +# define ANGLE_APIENTRY __stdcall +#else +# define ANGLE_APIENTRY +#endif + +namespace angle +{ +struct WorkaroundsD3D; +struct FeaturesVk; +using TraceEventHandle = uint64_t; +using EGLDisplayType = void *; +struct PlatformMethods; + +// Use a C-like API to not trigger undefined calling behaviour. +// Avoid using decltype here to work around sanitizer limitations. +// TODO(jmadill): Use decltype here if/when UBSAN is fixed. + +// System -------------------------------------------------------------- + +// Wall clock time in seconds since the epoch. +// TODO(jmadill): investigate using an ANGLE internal time library +using CurrentTimeFunc = double (*)(PlatformMethods *platform); +inline double DefaultCurrentTime(PlatformMethods *platform) +{ + return 0.0; +} + +// Monotonically increasing time in seconds from an arbitrary fixed point in the past. +// This function is expected to return at least millisecond-precision values. For this reason, +// it is recommended that the fixed point be no further in the past than the epoch. +using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform); +inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform) +{ + return 0.0; +} + +// Logging ------------------------------------------------------------ + +// Log an error message within the platform implementation. +using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage); +inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage) +{ +} + +// Log a warning message within the platform implementation. +using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage); +inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage) +{ +} + +// Log an info message within the platform implementation. +using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage); +inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage) +{ +} + +// Tracing -------- + +// Get a pointer to the enabled state of the given trace category. The +// embedder can dynamically change the enabled state as trace event +// recording is started and stopped by the application. Only long-lived +// literal strings should be given as the category name. The implementation +// expects the returned pointer to be held permanently in a local static. If +// the unsigned char is non-zero, tracing is enabled. If tracing is enabled, +// addTraceEvent is expected to be called by the trace event macros. +using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform, + const char *categoryName); +inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform, + const char *categoryName) +{ + return nullptr; +} + +// +// Add a trace event to the platform tracing system. Depending on the actual +// enabled state, this event may be recorded or dropped. +// - phase specifies the type of event: +// - BEGIN ('B'): Marks the beginning of a scoped event. +// - END ('E'): Marks the end of a scoped event. +// - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't +// need a matching END event. Instead, at the end of the scope, +// updateTraceEventDuration() must be called with the TraceEventHandle +// returned from addTraceEvent(). +// - INSTANT ('I'): Standalone, instantaneous event. +// - START ('S'): Marks the beginning of an asynchronous event (the end +// event can occur in a different scope or thread). The id parameter is +// used to match START/FINISH pairs. +// - FINISH ('F'): Marks the end of an asynchronous event. +// - COUNTER ('C'): Used to trace integer quantities that change over +// time. The argument values are expected to be of type int. +// - METADATA ('M'): Reserved for internal use. +// - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag. +// - name is the name of the event. Also used to match BEGIN/END and +// START/FINISH pairs. +// - id optionally allows events of the same name to be distinguished from +// each other. For example, to trace the construction and destruction of +// objects, specify the pointer as the id parameter. +// - timestamp should be a time value returned from monotonicallyIncreasingTime. +// - numArgs specifies the number of elements in argNames, argTypes, and +// argValues. +// - argNames is the array of argument names. Use long-lived literal strings +// or specify the COPY flag. +// - argTypes is the array of argument types: +// - BOOL (1): bool +// - UINT (2): unsigned long long +// - INT (3): long long +// - DOUBLE (4): double +// - POINTER (5): void* +// - STRING (6): char* (long-lived null-terminated char* string) +// - COPY_STRING (7): char* (temporary null-terminated char* string) +// - CONVERTABLE (8): WebConvertableToTraceFormat +// - argValues is the array of argument values. Each value is the unsigned +// long long member of a union of all supported types. +// - flags can be 0 or one or more of the following, ORed together: +// - COPY (0x1): treat all strings (name, argNames and argValues of type +// string) as temporary so that they will be copied by addTraceEvent. +// - HAS_ID (0x2): use the id argument to uniquely identify the event for +// matching with other events of the same name. +// - MANGLE_ID (0x4): specify this flag if the id parameter is the value +// of a pointer. +using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform, + char phase, + const unsigned char *categoryEnabledFlag, + const char *name, + unsigned long long id, + double timestamp, + int numArgs, + const char **argNames, + const unsigned char *argTypes, + const unsigned long long *argValues, + unsigned char flags); +inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform, + char phase, + const unsigned char *categoryEnabledFlag, + const char *name, + unsigned long long id, + double timestamp, + int numArgs, + const char **argNames, + const unsigned char *argTypes, + const unsigned long long *argValues, + unsigned char flags) +{ + return 0; +} + +// Set the duration field of a COMPLETE trace event. +using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform, + const unsigned char *categoryEnabledFlag, + const char *name, + angle::TraceEventHandle eventHandle); +inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform, + const unsigned char *categoryEnabledFlag, + const char *name, + angle::TraceEventHandle eventHandle) +{ +} + +// Callbacks for reporting histogram data. +// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 +// would do. +using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform, + const char *name, + int sample, + int min, + int max, + int bucketCount); +inline void DefaultHistogramCustomCounts(PlatformMethods *platform, + const char *name, + int sample, + int min, + int max, + int bucketCount) +{ +} +// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample +// value. +using HistogramEnumerationFunc = void (*)(PlatformMethods *platform, + const char *name, + int sample, + int boundaryValue); +inline void DefaultHistogramEnumeration(PlatformMethods *platform, + const char *name, + int sample, + int boundaryValue) +{ +} +// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets. +using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample); +inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample) +{ +} +// Boolean histograms track two-state variables. +using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample); +inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample) +{ +} + +// Allows us to programatically override ANGLE's default workarounds for testing purposes. +using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform, + angle::WorkaroundsD3D *workaroundsD3D); +inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform, + angle::WorkaroundsD3D *workaroundsD3D) +{ +} + +using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform, + angle::FeaturesVk *workaroundsVulkan); +inline void DefaultOverrideFeaturesVk(PlatformMethods *platform, + angle::FeaturesVk *workaroundsVulkan) +{ +} + +// Callback on a successful program link with the program binary. Can be used to store +// shaders to disk. Keys are a 160-bit SHA-1 hash. +using ProgramKeyType = std::array<uint8_t, 20>; +using CacheProgramFunc = void (*)(PlatformMethods *platform, + const ProgramKeyType &key, + size_t programSize, + const uint8_t *programBytes); +inline void DefaultCacheProgram(PlatformMethods *platform, + const ProgramKeyType &key, + size_t programSize, + const uint8_t *programBytes) +{ +} + +// Platform methods are enumerated here once. +#define ANGLE_PLATFORM_OP(OP) \ + OP(currentTime, CurrentTime) \ + OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \ + OP(logError, LogError) \ + OP(logWarning, LogWarning) \ + OP(logInfo, LogInfo) \ + OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \ + OP(addTraceEvent, AddTraceEvent) \ + OP(updateTraceEventDuration, UpdateTraceEventDuration) \ + OP(histogramCustomCounts, HistogramCustomCounts) \ + OP(histogramEnumeration, HistogramEnumeration) \ + OP(histogramSparse, HistogramSparse) \ + OP(histogramBoolean, HistogramBoolean) \ + OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \ + OP(overrideFeaturesVk, OverrideFeaturesVk) \ + OP(cacheProgram, CacheProgram) + +#define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName; + +struct ANGLE_PLATFORM_EXPORT PlatformMethods +{ + PlatformMethods() {} + + // User data pointer for any implementation specific members. Put it at the start of the + // platform structure so it doesn't become overwritten if one version of the platform + // adds or removes new members. + void *context = 0; + + ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF); +}; + +#undef ANGLE_PLATFORM_METHOD_DEF + +// Subtract one to account for the context pointer. +constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1; + +#define ANGLE_PLATFORM_METHOD_STRING(Name) #Name +#define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name), + +constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = { + ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)}; + +#undef ANGLE_PLATFORM_METHOD_STRING2 +#undef ANGLE_PLATFORM_METHOD_STRING + +} // namespace angle + +extern "C" { + +// Gets the platform methods on the passed-in EGL display. If the method name signature does not +// match the compiled signature for this ANGLE, false is returned. On success true is returned. +// The application should set any platform methods it cares about on the returned pointer. +// If display is not valid, behaviour is undefined. + +ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display, + const char *const methodNames[], + unsigned int methodNameCount, + void *context, + void *platformMethodsOut); + +// Sets the platform methods back to their defaults. +// If display is not valid, behaviour is undefined. +ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display); + +} // extern "C" + +namespace angle +{ +typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType, + const char *const *, + unsigned int, + void *, + void *); +typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType); +} // namespace angle + +// This function is not exported +angle::PlatformMethods *ANGLEPlatformCurrent(); + +#endif // ANGLE_PLATFORM_H diff --git a/opengl/include/EGL/egl.h b/opengl/include/EGL/egl.h index 93a3965cfc..c9e8b7c52c 100644 --- a/opengl/include/EGL/egl.h +++ b/opengl/include/EGL/egl.h @@ -33,12 +33,12 @@ extern "C" { ** used to make the header, and the header can be found at ** http://www.khronos.org/registry/egl ** -** Khronos $Git commit SHA1: a732b061e7 $ on $Git commit date: 2017-06-17 23:27:53 +0100 $ +** Khronos $Git commit SHA1: bae3518c48 $ on $Git commit date: 2018-05-17 10:56:57 -0700 $ */ #include <EGL/eglplatform.h> -/* Generated on date 20170627 */ +/* Generated on date 20180517 */ /* Generated C header for: * API: egl @@ -235,10 +235,66 @@ EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void); EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); #endif /* EGL_VERSION_1_4 */ -/* This version of Android does not yet support EGL 1.5, but the following - * portion of EGL 1.5 is included in order to support portions of "eglext.h". - */ +#ifndef EGL_VERSION_1_5 +#define EGL_VERSION_1_5 1 +typedef void *EGLSync; typedef intptr_t EGLAttrib; +typedef khronos_utime_nanoseconds_t EGLTime; +typedef void *EGLImage; +#define EGL_CONTEXT_MAJOR_VERSION 0x3098 +#define EGL_CONTEXT_MINOR_VERSION 0x30FB +#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD +#define EGL_NO_RESET_NOTIFICATION 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2 +#define EGL_OPENGL_ES3_BIT 0x00000040 +#define EGL_CL_EVENT_HANDLE 0x309C +#define EGL_SYNC_CL_EVENT 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 +#define EGL_SYNC_TYPE 0x30F7 +#define EGL_SYNC_STATUS 0x30F1 +#define EGL_SYNC_CONDITION 0x30F8 +#define EGL_SIGNALED 0x30F2 +#define EGL_UNSIGNALED 0x30F3 +#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 +#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull +#define EGL_TIMEOUT_EXPIRED 0x30F5 +#define EGL_CONDITION_SATISFIED 0x30F6 +#define EGL_NO_SYNC EGL_CAST(EGLSync,0) +#define EGL_SYNC_FENCE 0x30F9 +#define EGL_GL_COLORSPACE 0x309D +#define EGL_GL_COLORSPACE_SRGB 0x3089 +#define EGL_GL_COLORSPACE_LINEAR 0x308A +#define EGL_GL_RENDERBUFFER 0x30B9 +#define EGL_GL_TEXTURE_2D 0x30B1 +#define EGL_GL_TEXTURE_LEVEL 0x30BC +#define EGL_GL_TEXTURE_3D 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET 0x30BD +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +#define EGL_IMAGE_PRESERVED 0x30D2 +#define EGL_NO_IMAGE EGL_CAST(EGLImage,0) +EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image); +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags); +#endif /* EGL_VERSION_1_5 */ #ifdef __cplusplus } diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 44f4dbc929..501bf58531 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -28,17 +28,17 @@ extern "C" { ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ /* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts +** This header is generated from the Khronos EGL XML API Registry. +** The current version of the Registry, generator scripts ** used to make the header, and the header can be found at ** http://www.khronos.org/registry/egl ** -** Khronos $Git commit SHA1: feaaeb19e1 $ on $Git commit date: 2018-02-26 20:49:02 -0800 $ +** Khronos $Git commit SHA1: 726475c203 $ on $Git commit date: 2018-10-03 23:51:49 -0700 $ */ #include <EGL/eglplatform.h> -#define EGL_EGLEXT_VERSION 20180228 +#define EGL_EGLEXT_VERSION 20181204 /* Generated C header for: * API: egl @@ -618,6 +618,16 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #define EGL_EXT_client_extensions 1 #endif /* EGL_EXT_client_extensions */ +#ifndef EGL_EXT_client_sync +#define EGL_EXT_client_sync 1 +#define EGL_SYNC_CLIENT_EXT 0x3364 +#define EGL_SYNC_CLIENT_SIGNAL_EXT 0x3365 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCLIENTSIGNALSYNCEXTPROC) (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglClientSignalSyncEXT (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_EXT_client_sync */ + #ifndef EGL_EXT_compositor #define EGL_EXT_compositor 1 #define EGL_PRIMARY_COMPOSITOR_CONTEXT_EXT 0x3460 @@ -671,6 +681,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a #ifndef EGL_EXT_device_drm #define EGL_EXT_device_drm 1 #define EGL_DRM_DEVICE_FILE_EXT 0x3233 +#define EGL_DRM_MASTER_FD_EXT 0x333C #endif /* EGL_EXT_device_drm */ #ifndef EGL_EXT_device_enumeration @@ -706,6 +717,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a #define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362 #endif /* EGL_EXT_gl_colorspace_display_p3_linear */ +#ifndef EGL_EXT_gl_colorspace_display_p3_passthrough +#define EGL_EXT_gl_colorspace_display_p3_passthrough 1 +#define EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490 +#endif /* EGL_EXT_gl_colorspace_display_p3_passthrough */ + #ifndef EGL_EXT_gl_colorspace_scrgb #define EGL_EXT_gl_colorspace_scrgb 1 #define EGL_GL_COLORSPACE_SCRGB_EXT 0x3351 @@ -903,6 +919,14 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSu #endif #endif /* EGL_EXT_swap_buffers_with_damage */ +#ifndef EGL_EXT_sync_reuse +#define EGL_EXT_sync_reuse 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNSIGNALSYNCEXTPROC) (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglUnsignalSyncEXT (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_EXT_sync_reuse */ + #ifndef EGL_EXT_yuv_surface #define EGL_EXT_yuv_surface 1 #define EGL_YUV_ORDER_EXT 0x3301 @@ -1147,6 +1171,14 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDi #define EGL_STREAM_FIFO_SYNCHRONOUS_NV 0x3336 #endif /* EGL_NV_stream_fifo_synchronous */ +#ifndef EGL_NV_stream_flush +#define EGL_NV_stream_flush 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMFLUSHNVPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamFlushNV (EGLDisplay dpy, EGLStreamKHR stream); +#endif +#endif /* EGL_NV_stream_flush */ + #ifndef EGL_NV_stream_frame_limits #define EGL_NV_stream_frame_limits 1 #define EGL_PRODUCER_MAX_FRAME_HINT_NV 0x3337 @@ -1285,17 +1317,6 @@ EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); #define EGL_NATIVE_SURFACE_TIZEN 0x32A1 #endif /* EGL_TIZEN_image_native_surface */ -/* This is a private Android extension that does not exist in the EGL registry, - * formerly used to work around a hardware issue on Nexus 4. It is deprecated - * and unimplemented. It has been added to this header manually. */ -#ifndef EGL_ANDROID_image_crop -#define EGL_ANDROID_image_crop 1 -#define EGL_IMAGE_CROP_LEFT_ANDROID 0x3148 -#define EGL_IMAGE_CROP_TOP_ANDROID 0x3149 -#define EGL_IMAGE_CROP_RIGHT_ANDROID 0x314A -#define EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B -#endif - #ifdef __cplusplus } #endif diff --git a/opengl/include/EGL/eglext_angle.h b/opengl/include/EGL/eglext_angle.h new file mode 100644 index 0000000000..0556ea1342 --- /dev/null +++ b/opengl/include/EGL/eglext_angle.h @@ -0,0 +1,191 @@ +// +// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// eglext_angle.h: ANGLE modifications to the eglext.h header file. +// Currently we don't include this file directly, we patch eglext.h +// to include it implicitly so it is visible throughout our code. + +#ifndef INCLUDE_EGL_EGLEXT_ANGLE_ +#define INCLUDE_EGL_EGLEXT_ANGLE_ + +// clang-format off + +#ifndef EGL_ANGLE_robust_resource_initialization +#define EGL_ANGLE_robust_resource_initialization 1 +#define EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453 +#endif /* EGL_ANGLE_robust_resource_initialization */ + +#ifndef EGL_ANGLE_keyed_mutex +#define EGL_ANGLE_keyed_mutex 1 +#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2 +#endif /* EGL_ANGLE_keyed_mutex */ + +#ifndef EGL_ANGLE_d3d_texture_client_buffer +#define EGL_ANGLE_d3d_texture_client_buffer 1 +#define EGL_D3D_TEXTURE_ANGLE 0x33A3 +#endif /* EGL_ANGLE_d3d_texture_client_buffer */ + +#ifndef EGL_ANGLE_software_display +#define EGL_ANGLE_software_display 1 +#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1) +#endif /* EGL_ANGLE_software_display */ + +#ifndef EGL_ANGLE_direct3d_display +#define EGL_ANGLE_direct3d_display 1 +#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) +#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) +#endif /* EGL_ANGLE_direct3d_display */ + +#ifndef EGL_ANGLE_direct_composition +#define EGL_ANGLE_direct_composition 1 +#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5 +#endif /* EGL_ANGLE_direct_composition */ + +#ifndef EGL_ANGLE_platform_angle +#define EGL_ANGLE_platform_angle 1 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE 0x3451 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x345E +#endif /* EGL_ANGLE_platform_angle */ + +#ifndef EGL_ANGLE_platform_angle_d3d +#define EGL_ANGLE_platform_angle_d3d 1 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE 0x320B +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE 0x320C +#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F +#endif /* EGL_ANGLE_platform_angle_d3d */ + +#ifndef EGL_ANGLE_platform_angle_opengl +#define EGL_ANGLE_platform_angle_opengl 1 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E +#define EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE 0x3480 +#endif /* EGL_ANGLE_platform_angle_opengl */ + +#ifndef EGL_ANGLE_platform_angle_null +#define EGL_ANGLE_platform_angle_null 1 +#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE +#endif /* EGL_ANGLE_platform_angle_null */ + +#ifndef EGL_ANGLE_platform_angle_vulkan +#define EGL_ANGLE_platform_angle_vulkan 1 +#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 +#endif /* EGL_ANGLE_platform_angle_vulkan */ + +#ifndef EGL_ANGLE_platform_angle_context_virtualization +#define EGL_ANGLE_platform_angle_context_virtualization 1 +#define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481 +#endif /* EGL_ANGLE_platform_angle_context_virtualization */ + +#ifndef EGL_ANGLE_x11_visual +#define EGL_ANGLE_x11_visual +#define EGL_X11_VISUAL_ID_ANGLE 0x33A3 +#endif /* EGL_ANGLE_x11_visual */ + +#ifndef EGL_ANGLE_flexible_surface_compatibility +#define EGL_ANGLE_flexible_surface_compatibility 1 +#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 +#endif /* EGL_ANGLE_flexible_surface_compatibility */ + +#ifndef EGL_ANGLE_surface_orientation +#define EGL_ANGLE_surface_orientation +#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7 +#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8 +#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001 +#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002 +#endif /* EGL_ANGLE_surface_orientation */ + +#ifndef EGL_ANGLE_experimental_present_path +#define EGL_ANGLE_experimental_present_path +#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4 +#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9 +#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA +#endif /* EGL_ANGLE_experimental_present_path */ + +#ifndef EGL_ANGLE_stream_producer_d3d_texture +#define EGL_ANGLE_stream_producer_d3d_texture +#define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB +typedef EGLBoolean(EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +typedef EGLBoolean(EGLAPIENTRYP PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglCreateStreamProducerD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_ANGLE_stream_producer_d3d_texture */ + +#ifndef EGL_ANGLE_create_context_webgl_compatibility +#define EGL_ANGLE_create_context_webgl_compatibility 1 +#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC +#endif /* EGL_ANGLE_create_context_webgl_compatibility */ + +#ifndef EGL_ANGLE_display_texture_share_group +#define EGL_ANGLE_display_texture_share_group 1 +#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF +#endif /* EGL_ANGLE_display_texture_share_group */ + +#ifndef EGL_CHROMIUM_create_context_bind_generates_resource +#define EGL_CHROMIUM_create_context_bind_generates_resource 1 +#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x33AD +#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */ + +#ifndef EGL_ANGLE_create_context_client_arrays +#define EGL_ANGLE_create_context_client_arrays 1 +#define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452 +#endif /* EGL_ANGLE_create_context_client_arrays */ + +#ifndef EGL_ANGLE_device_creation +#define EGL_ANGLE_device_creation 1 +typedef EGLDeviceEXT(EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list); +typedef EGLBoolean(EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE(EGLint device_type, void *native_device, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE(EGLDeviceEXT device); +#endif +#endif /* EGL_ANGLE_device_creation */ + +#ifndef EGL_ANGLE_program_cache_control +#define EGL_ANGLE_program_cache_control 1 +#define EGL_PROGRAM_CACHE_SIZE_ANGLE 0x3455 +#define EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE 0x3456 +#define EGL_PROGRAM_CACHE_RESIZE_ANGLE 0x3457 +#define EGL_PROGRAM_CACHE_TRIM_ANGLE 0x3458 +#define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459 +typedef EGLint (EGLAPIENTRYP PFNEGLPROGRAMCACHEGETATTRIBANGLEPROC) (EGLDisplay dpy, EGLenum attrib); +typedef void (EGLAPIENTRYP PFNEGLPROGRAMCACHEQUERYANGLEPROC) (EGLDisplay dpy, EGLint index, void *key, EGLint *keysize, void *binary, EGLint *binarysize); +typedef void (EGLAPIENTRYP PFNEGPROGRAMCACHELPOPULATEANGLEPROC) (EGLDisplay dpy, const void *key, EGLint keysize, const void *binary, EGLint binarysize); +typedef EGLint (EGLAPIENTRYP PFNEGLPROGRAMCACHERESIZEANGLEPROC) (EGLDisplay dpy, EGLint limit, EGLenum mode); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib); +EGLAPI void EGLAPIENTRY eglProgramCacheQueryANGLE(EGLDisplay dpy, EGLint index, void *key, EGLint *keysize, void *binary, EGLint *binarysize); +EGLAPI void EGLAPIENTRY eglProgramCachePopulateANGLE(EGLDisplay dpy, const void *key, EGLint keysize, const void *binary, EGLint binarysize); +EGLAPI EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode); +#endif +#endif /* EGL_ANGLE_program_cache_control */ + +#ifndef EGL_ANGLE_iosurface_client_buffer +#define EGL_ANGLE_iosurface_client_buffer 1 +#define EGL_IOSURFACE_ANGLE 0x3454 +#define EGL_IOSURFACE_PLANE_ANGLE 0x345A +#define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B +#define EGL_TEXTURE_TYPE_ANGLE 0x345C +#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D +#endif /* EGL_ANGLE_iosurface_client_buffer */ + +#ifndef EGL_ANGLE_create_context_extensions_enabled +#define EGL_ANGLE_create_context_extensions_enabled 1 +#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F +#endif /* EGL_ANGLE_create_context_extensions_enabled */ + +// clang-format on + +#endif // INCLUDE_EGL_EGLEXT_ANGLE_ diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h index c77c3338de..0bc2cb9a74 100644 --- a/opengl/include/EGL/eglplatform.h +++ b/opengl/include/EGL/eglplatform.h @@ -77,12 +77,24 @@ typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; typedef HWND EGLNativeWindowType; -#elif defined(__APPLE__) || defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ typedef int EGLNativeDisplayType; typedef void *EGLNativeWindowType; typedef void *EGLNativePixmapType; +#elif defined(WL_EGL_PLATFORM) + +typedef struct wl_display *EGLNativeDisplayType; +typedef struct wl_egl_pixmap *EGLNativePixmapType; +typedef struct wl_egl_window *EGLNativeWindowType; + +#elif defined(__GBM__) + +typedef struct gbm_device *EGLNativeDisplayType; +typedef struct gbm_bo *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + #elif defined(__ANDROID__) || defined(ANDROID) struct ANativeWindow; @@ -92,7 +104,13 @@ typedef struct ANativeWindow* EGLNativeWindowType; typedef struct egl_native_pixmap_t* EGLNativePixmapType; typedef void* EGLNativeDisplayType; -#elif defined(__unix__) +#elif defined(USE_OZONE) + +typedef intptr_t EGLNativeDisplayType; +typedef intptr_t EGLNativeWindowType; +typedef intptr_t EGLNativePixmapType; + +#elif defined(__unix__) || defined(USE_X11) /* X11 (tentative) */ #include <X11/Xlib.h> @@ -102,6 +120,20 @@ typedef Display *EGLNativeDisplayType; typedef Pixmap EGLNativePixmapType; typedef Window EGLNativeWindowType; +#elif defined(__APPLE__) + +typedef int EGLNativeDisplayType; +typedef void *EGLNativeWindowType; +typedef void *EGLNativePixmapType; + +#elif defined(__HAIKU__) + +#include <kernel/image.h> + +typedef void *EGLNativeDisplayType; +typedef khronos_uintptr_t EGLNativePixmapType; +typedef khronos_uintptr_t EGLNativeWindowType; + #else #error "Platform not recognized" #endif diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp index d43c1648be..c0bace8486 100644 --- a/opengl/libs/Android.bp +++ b/opengl/libs/Android.bp @@ -140,16 +140,22 @@ cc_library_shared { "EGL/egl_cache.cpp", "EGL/egl_display.cpp", "EGL/egl_object.cpp", + "EGL/egl_layers.cpp", "EGL/egl.cpp", "EGL/eglApi.cpp", + "EGL/egl_platform_entries.cpp", "EGL/Loader.cpp", + "EGL/egl_angle_platform.cpp", ], shared_libs: [ "libvndksupport", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", + "libbase", "libhidlbase", "libhidltransport", + "libnativebridge_lazy", + "libnativeloader_lazy", "libutils", ], static_libs: [ @@ -191,6 +197,7 @@ cc_library_shared { defaults: ["gles_libs_defaults"], srcs: ["GLES_CM/gl.cpp"], cflags: ["-DLOG_TAG=\"libGLESv1\""], + version_script: "libGLESv1_CM.map.txt", } //############################################################################## diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp index b3752f5bcc..74c4d7d07a 100644 --- a/opengl/libs/EGL/BlobCache.cpp +++ b/opengl/libs/EGL/BlobCache.cpp @@ -79,7 +79,7 @@ void BlobCache::set(const void* key, size_t keySize, const void* value, } std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false)); - CacheEntry dummyEntry(dummyKey, NULL); + CacheEntry dummyEntry(dummyKey, nullptr); while (true) { auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry); @@ -139,7 +139,7 @@ size_t BlobCache::get(const void* key, size_t keySize, void* value, return 0; } std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false)); - CacheEntry dummyEntry(dummyKey, NULL); + CacheEntry dummyEntry(dummyKey, nullptr); auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry); if (index == mCacheEntries.end() || dummyEntry < *index) { ALOGV("get: no cache entry found for key of size %zu", keySize); @@ -308,7 +308,7 @@ BlobCache::Blob::Blob(const void* data, size_t size, bool copyData) : mData(copyData ? malloc(size) : data), mSize(size), mOwnsData(copyData) { - if (data != NULL && copyData) { + if (data != nullptr && copyData) { memcpy(const_cast<void*>(mData), data, size); } } diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h index 1f5d5357e6..e5c5e5bc25 100644 --- a/opengl/libs/EGL/BlobCache.h +++ b/opengl/libs/EGL/BlobCache.h @@ -97,6 +97,10 @@ public: // int unflatten(void const* buffer, size_t size); + // clear flushes out all contents of the cache then the BlobCache, leaving + // it in an empty state. + void clear() { mCacheEntries.clear(); } + protected: // mMaxTotalSize is the maximum size that all cache entries can occupy. This // includes space for both keys and values. When a call to BlobCache::set diff --git a/opengl/libs/EGL/BlobCache_test.cpp b/opengl/libs/EGL/BlobCache_test.cpp index edbaaf090d..cf67cf443b 100644 --- a/opengl/libs/EGL/BlobCache_test.cpp +++ b/opengl/libs/EGL/BlobCache_test.cpp @@ -97,7 +97,7 @@ TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) { TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) { mBC->set("abcd", 4, "efgh", 4); - ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0)); + ASSERT_EQ(size_t(4), mBC->get("abcd", 4, nullptr, 0)); } TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) { @@ -169,7 +169,7 @@ TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) { } mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE); - ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0)); + ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, nullptr, 0)); } TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) { @@ -219,7 +219,7 @@ TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) { } mBC->set(key, MAX_KEY_SIZE, buf, bufSize); - ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0)); + ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, nullptr, 0)); } TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) { @@ -237,7 +237,7 @@ TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) { int numCached = 0; for (int i = 0; i < 256; i++) { uint8_t k = i; - if (mBC->get(&k, 1, NULL, 0) == 1) { + if (mBC->get(&k, 1, nullptr, 0) == 1) { numCached++; } } @@ -260,7 +260,7 @@ TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) { int numCached = 0; for (int i = 0; i < maxEntries+1; i++) { uint8_t k = i; - if (mBC->get(&k, 1, NULL, 0) == 1) { + if (mBC->get(&k, 1, nullptr, 0) == 1) { numCached++; } } diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp index 79237159bf..cc42ac7fef 100644 --- a/opengl/libs/EGL/FileBlobCache.cpp +++ b/opengl/libs/EGL/FileBlobCache.cpp @@ -77,7 +77,7 @@ FileBlobCache::FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxT return; } - uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize, + uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE, fd, 0)); if (buf == MAP_FAILED) { ALOGE("error mmaping cache file: %s (%d)", strerror(errno), diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index 91a34558aa..259242b459 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -17,7 +17,7 @@ //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include "Loader.h" +#include <EGL/Loader.h> #include <string> @@ -27,18 +27,17 @@ #include <android/dlext.h> #include <cutils/properties.h> #include <log/log.h> +#include <utils/Timers.h> #ifndef __ANDROID_VNDK__ #include <graphicsenv/GraphicsEnv.h> #endif #include <vndksupport/linker.h> +#include "egl_platform_entries.h" #include "egl_trace.h" #include "egldefs.h" - -extern "C" { - android_namespace_t* android_get_exported_namespace(const char*); -} +#include <EGL/eglext_angle.h> // ---------------------------------------------------------------------------- namespace android { @@ -129,7 +128,7 @@ Loader::driver_t::driver_t(void* gles) { dso[0] = gles; for (size_t i=1 ; i<NELEM(dso) ; i++) - dso[i] = 0; + dso[i] = nullptr; } Loader::driver_t::~driver_t() @@ -137,7 +136,7 @@ Loader::driver_t::~driver_t() for (size_t i=0 ; i<NELEM(dso) ; i++) { if (dso[i]) { dlclose(dso[i]); - dso[i] = 0; + dso[i] = nullptr; } } } @@ -163,7 +162,7 @@ int Loader::driver_t::set(void* hnd, int32_t api) // ---------------------------------------------------------------------------- Loader::Loader() - : getProcAddress(NULL) + : getProcAddress(nullptr) { } @@ -219,16 +218,26 @@ static void setEmulatorGlesValue(void) { void* Loader::open(egl_connection_t* cnx) { ATRACE_CALL(); + const nsecs_t openTime = systemTime(); void* dso; - driver_t* hnd = 0; + driver_t* hnd = nullptr; setEmulatorGlesValue(); + // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries. + if (android::GraphicsEnv::getInstance().shouldUseAngle()) { + cnx->shouldUseAngle = true; + } else { + cnx->shouldUseAngle = false; + } + dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2); if (dso) { hnd = new driver_t(dso); } else { + android::GraphicsEnv::getInstance().clearDriverLoadingInfo( + android::GraphicsEnv::Api::API_GL); // Always load EGL first dso = load_driver("EGL", cnx, EGL); if (dso) { @@ -238,29 +247,53 @@ void* Loader::open(egl_connection_t* cnx) } } + if (!hnd) { + android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, + false, systemTime() - openTime); + } + LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation"); cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so"); cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so"); cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so"); + if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) { + android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, + false, systemTime() - openTime); + } + LOG_ALWAYS_FATAL_IF(!cnx->libEgl, "couldn't load system EGL wrapper libraries"); LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1, "couldn't load system OpenGL ES wrapper libraries"); + android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, true, + systemTime() - openTime); + return (void*)hnd; } -void Loader::close(void* driver) +void Loader::close(egl_connection_t* cnx) { - driver_t* hnd = (driver_t*)driver; + driver_t* hnd = (driver_t*) cnx->dso; delete hnd; + cnx->dso = nullptr; + + cnx->shouldUseAngle = false; + cnx->angleDecided = false; + cnx->useAngle = false; + + if (cnx->vendorEGL) { + dlclose(cnx->vendorEGL); + cnx->vendorEGL = nullptr; + } } void Loader::init_api(void* dso, char const * const * api, + char const * const * ref_api, __eglMustCastToProperFunctionPointerType* curr, getProcAddressType getProcAddress) { @@ -270,13 +303,22 @@ void Loader::init_api(void* dso, char scrap[SIZE]; while (*api) { char const * name = *api; + if (ref_api) { + char const * ref_name = *ref_api; + if (std::strcmp(name, ref_name) != 0) { + *curr++ = nullptr; + ref_api++; + continue; + } + } + __eglMustCastToProperFunctionPointerType f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { + if (f == nullptr) { // couldn't find the entry-point, use eglGetProcAddress() f = getProcAddress(name); } - if (f == NULL) { + if (f == nullptr) { // Try without the OES postfix ssize_t index = ssize_t(strlen(name)) - 3; if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) { @@ -286,7 +328,7 @@ void Loader::init_api(void* dso, //ALOGD_IF(f, "found <%s> instead", scrap); } } - if (f == NULL) { + if (f == nullptr) { // Try with the OES postfix ssize_t index = ssize_t(strlen(name)) - 3; if (index>0 && strcmp(name+index, "OES")) { @@ -295,7 +337,7 @@ void Loader::init_api(void* dso, //ALOGD_IF(f, "found <%s> instead", scrap); } } - if (f == NULL) { + if (f == nullptr) { //ALOGD("%s", name); f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; @@ -314,6 +356,7 @@ void Loader::init_api(void* dso, } *curr++ = f; api++; + if (ref_api) ref_api++; } } @@ -406,9 +449,9 @@ static void* load_system_driver(const char* kind) { } DIR* d = opendir(search); - if (d != NULL) { + if (d != nullptr) { struct dirent* e; - while ((e = readdir(d)) != NULL) { + while ((e = readdir(d)) != nullptr) { if (e->d_type == DT_DIR) { continue; } @@ -434,7 +477,7 @@ static void* load_system_driver(const char* kind) { std::string absolutePath = MatchFile::find(kind); if (absolutePath.empty()) { // this happens often, we don't want to log an error - return 0; + return nullptr; } const char* const driver_absolute_path = absolutePath.c_str(); @@ -444,10 +487,10 @@ static void* load_system_driver(const char* kind) { // sphal namespace. void* dso = do_android_load_sphal_library(driver_absolute_path, RTLD_NOW | RTLD_LOCAL); - if (dso == 0) { + if (dso == nullptr) { const char* err = dlerror(); ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown"); - return 0; + return nullptr; } ALOGD("loaded %s", driver_absolute_path); @@ -455,6 +498,81 @@ static void* load_system_driver(const char* kind) { return dso; } +static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns) { + const android_dlextinfo dlextinfo = { + .flags = ANDROID_DLEXT_USE_NAMESPACE, + .library_namespace = ns, + }; + + std::string name = std::string("lib") + kind + "_angle.so"; + + void* so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo); + + if (so) { + ALOGD("dlopen_ext from APK (%s) success at %p", name.c_str(), so); + return so; + } else { + ALOGE("dlopen_ext(\"%s\") failed: %s", name.c_str(), dlerror()); + } + + return nullptr; +} + +static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) { + // Only attempt to load ANGLE libs + if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0) { + return nullptr; + } + + void* so = nullptr; + + if ((cnx->shouldUseAngle) || android::GraphicsEnv::getInstance().shouldUseAngle()) { + so = load_angle_from_namespace(kind, ns); + cnx->shouldUseAngle = true; + } else { + cnx->shouldUseAngle = false; + } + + if (so) { + ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind, + android::GraphicsEnv::getInstance().getAngleAppName().c_str()); + cnx->useAngle = true; + + char prop[PROPERTY_VALUE_MAX]; + + property_get("debug.hwui.renderer", prop, "UNSET"); + ALOGV("Skia's renderer set to %s", prop); + + EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; + property_get("debug.angle.backend", prop, "0"); + switch (atoi(prop)) { + case 1: + ALOGV("%s: Requesting OpenGLES back-end", __FUNCTION__); + angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE; + break; + case 2: + ALOGV("%s: Requesting Vulkan back-end", __FUNCTION__); + angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; + break; + default: + break; + } + + cnx->angleBackend = angleBackendDefault; + if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) { + // Find and load vendor libEGL for ANGLE's GL back-end to use. + cnx->vendorEGL = load_system_driver("EGL"); + } + } else { + ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind, + android::GraphicsEnv::getInstance().getAngleAppName().c_str()); + cnx->useAngle = false; + } + cnx->angleDecided = true; + + return so; +} + static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = { "ro.hardware.egl", "ro.board.platform", @@ -486,16 +604,26 @@ void *Loader::load_driver(const char* kind, ATRACE_CALL(); void* dso = nullptr; -#ifndef __ANDROID_VNDK__ - android_namespace_t* ns = android_getDriverNamespace(); + android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace(); if (ns) { - dso = load_updated_driver(kind, ns); + android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE); + dso = load_angle(kind, ns, cnx); + } +#ifndef __ANDROID_VNDK__ + if (!dso) { + android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace(); + if (ns) { + android::GraphicsEnv::getInstance().setDriverToLoad( + android::GraphicsEnv::Driver::GL_UPDATED); + dso = load_updated_driver(kind, ns); + } } #endif if (!dso) { + android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL); dso = load_system_driver(kind); if (!dso) - return NULL; + return nullptr; } if (mask & EGL) { @@ -512,11 +640,11 @@ void *Loader::load_driver(const char* kind, char const * name = *api; __eglMustCastToProperFunctionPointerType f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { + if (f == nullptr) { // couldn't find the entry-point, use eglGetProcAddress() f = getProcAddress(name); - if (f == NULL) { - f = (__eglMustCastToProperFunctionPointerType)0; + if (f == nullptr) { + f = (__eglMustCastToProperFunctionPointerType)nullptr; } } *curr++ = f; @@ -525,14 +653,14 @@ void *Loader::load_driver(const char* kind, } if (mask & GLESv1_CM) { - init_api(dso, gl_names, + init_api(dso, gl_names_1, gl_names, (__eglMustCastToProperFunctionPointerType*) &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl, getProcAddress); } if (mask & GLESv2) { - init_api(dso, gl_names, + init_api(dso, gl_names, nullptr, (__eglMustCastToProperFunctionPointerType*) &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl, getProcAddress); diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h index 6a32bb3066..392887d42c 100644 --- a/opengl/libs/EGL/Loader.h +++ b/opengl/libs/EGL/Loader.h @@ -29,11 +29,12 @@ struct egl_connection_t; class Loader { typedef __eglMustCastToProperFunctionPointerType (* getProcAddressType)(const char*); - + enum { EGL = 0x01, GLESv1_CM = 0x02, - GLESv2 = 0x04 + GLESv2 = 0x04, + PLATFORM = 0x08 }; struct driver_t { explicit driver_t(void* gles); @@ -42,25 +43,26 @@ class Loader { int set(void* hnd, int32_t api); void* dso[3]; }; - + getProcAddressType getProcAddress; public: static Loader& getInstance(); ~Loader(); - + void* open(egl_connection_t* cnx); - void close(void* driver); - + void close(egl_connection_t* cnx); + private: Loader(); void *load_driver(const char* kind, egl_connection_t* cnx, uint32_t mask); static __attribute__((noinline)) - void init_api(void* dso, - char const * const * api, - __eglMustCastToProperFunctionPointerType* curr, - getProcAddressType getProcAddress); + void init_api(void* dso, + char const * const * api, + char const * const * ref_api, + __eglMustCastToProperFunctionPointerType* curr, + getProcAddressType getProcAddress); }; // ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index f53cf3f8cc..8870d5f571 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -30,11 +30,10 @@ #include "egl_tls.h" #include "egl_display.h" #include "egl_object.h" +#include "egl_layers.h" #include "CallStack.h" #include "Loader.h" -typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer; - // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- @@ -89,22 +88,22 @@ static int sEarlyInitState = pthread_once(&once_control, &early_egl_init); egl_display_ptr validate_display(EGLDisplay dpy) { egl_display_ptr dp = get_display(dpy); if (!dp) - return setError(EGL_BAD_DISPLAY, egl_display_ptr(NULL)); + return setError(EGL_BAD_DISPLAY, egl_display_ptr(nullptr)); if (!dp->isReady()) - return setError(EGL_NOT_INITIALIZED, egl_display_ptr(NULL)); + return setError(EGL_NOT_INITIALIZED, egl_display_ptr(nullptr)); return dp; } egl_display_ptr validate_display_connection(EGLDisplay dpy, egl_connection_t*& cnx) { - cnx = NULL; + cnx = nullptr; egl_display_ptr dp = validate_display(dpy); if (!dp) return dp; cnx = &gEGLImpl; - if (cnx->dso == 0) { - return setError(EGL_BAD_CONFIG, egl_display_ptr(NULL)); + if (cnx->dso == nullptr) { + return setError(EGL_BAD_CONFIG, egl_display_ptr(nullptr)); } return dp; } @@ -117,14 +116,14 @@ const GLubyte * egl_get_string_for_current_context(GLenum name) { EGLContext context = egl_tls_t::getContext(); if (context == EGL_NO_CONTEXT) - return NULL; + return nullptr; egl_context_t const * const c = get_context(context); - if (c == NULL) // this should never happen, by construction - return NULL; + if (c == nullptr) // this should never happen, by construction + return nullptr; if (name != GL_EXTENSIONS) - return NULL; + return nullptr; return (const GLubyte *)c->gl_extensions.c_str(); } @@ -135,19 +134,19 @@ const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) { EGLContext context = egl_tls_t::getContext(); if (context == EGL_NO_CONTEXT) - return NULL; + return nullptr; egl_context_t const * const c = get_context(context); - if (c == NULL) // this should never happen, by construction - return NULL; + if (c == nullptr) // this should never happen, by construction + return nullptr; if (name != GL_EXTENSIONS) - return NULL; + return nullptr; // if index is out of bounds, assume it will be in the default // implementation too, so we don't have to generate a GL error here if (index >= c->tokenized_gl_extensions.size()) - return NULL; + return nullptr; return (const GLubyte *)c->tokenized_gl_extensions[index].c_str(); } @@ -161,12 +160,16 @@ GLint egl_get_num_extensions_for_current_context() { return -1; egl_context_t const * const c = get_context(context); - if (c == NULL) // this should never happen, by construction + if (c == nullptr) // this should never happen, by construction return -1; return (GLint)c->tokenized_gl_extensions.size(); } +egl_connection_t* egl_get_connection() { + return &gEGLImpl; +} + // ---------------------------------------------------------------------------- // this mutex protects: @@ -184,7 +187,7 @@ static EGLBoolean egl_init_drivers_locked() { // dynamically load our EGL implementation egl_connection_t* cnx = &gEGLImpl; - if (cnx->dso == 0) { + if (cnx->dso == nullptr) { cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX]; cnx->hooks[egl_connection_t::GLESv2_INDEX] = @@ -192,6 +195,14 @@ static EGLBoolean egl_init_drivers_locked() { cnx->dso = loader.open(cnx); } + // Check to see if any layers are enabled and route functions through them + if (cnx->dso) { + // Layers can be enabled long after the drivers have been loaded. + // They will only be initialized once. + LayerLoader& layer_loader(LayerLoader::getInstance()); + layer_loader.InitLayers(cnx); + } + return cnx->dso ? EGL_TRUE : EGL_FALSE; } @@ -249,12 +260,22 @@ void setGlThreadSpecific(gl_hooks_t const *value) { char const * const gl_names[] = { #include "../entries.in" - NULL + nullptr +}; + +char const * const gl_names_1[] = { + #include "../entries_gles1.in" + nullptr }; char const * const egl_names[] = { #include "egl_entries.in" - NULL + nullptr +}; + +char const * const platform_names[] = { + #include "platform_entries.in" + nullptr }; #undef GL_ENTRY diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 36deedcb85..29a966d348 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -1,5 +1,5 @@ /* - ** Copyright 2007, The Android Open Source Project + ** Copyright 2018, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -16,1170 +16,225 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <ctype.h> -#include <dlfcn.h> -#include <stdlib.h> -#include <string.h> - -#include <hardware/gralloc1.h> - #include <EGL/egl.h> #include <EGL/eglext.h> -#include <android/hardware_buffer.h> -#include <private/android/AHardwareBufferHelpers.h> - -#include <cutils/compiler.h> -#include <cutils/properties.h> -#include <log/log.h> - -#include <condition_variable> -#include <deque> -#include <mutex> -#include <unordered_map> -#include <string> -#include <thread> - #include "../egl_impl.h" -#include "egl_display.h" -#include "egl_object.h" +#include "egl_layers.h" +#include "egl_platform_entries.h" #include "egl_tls.h" #include "egl_trace.h" using namespace android; -// ---------------------------------------------------------------------------- - namespace android { -using nsecs_t = int64_t; - -struct extention_map_t { - const char* name; - __eglMustCastToProperFunctionPointerType address; -}; - -/* - * This is the list of EGL extensions exposed to applications. - * - * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL - * wrapper and are always available. - * - * The rest (gExtensionString) depend on support in the EGL driver, and are - * only available if the driver supports them. However, some of these must be - * supported because they are used by the Android system itself; these are - * listed as mandatory below and are required by the CDD. The system *assumes* - * the mandatory extensions are present and may not function properly if some - * are missing. - * - * NOTE: Both strings MUST have a single space as the last character. - */ - -extern char const * const gBuiltinExtensionString; -extern char const * const gExtensionString; - -// clang-format off -// Extensions implemented by the EGL wrapper. -char const * const gBuiltinExtensionString = - "EGL_KHR_get_all_proc_addresses " - "EGL_ANDROID_presentation_time " - "EGL_KHR_swap_buffers_with_damage " - "EGL_ANDROID_get_native_client_buffer " - "EGL_ANDROID_front_buffer_auto_refresh " - "EGL_ANDROID_get_frame_timestamps " - "EGL_EXT_surface_SMPTE2086_metadata " - "EGL_EXT_surface_CTA861_3_metadata " - ; - -// Whitelist of extensions exposed to applications if implemented in the vendor driver. -char const * const gExtensionString = - "EGL_KHR_image " // mandatory - "EGL_KHR_image_base " // mandatory - "EGL_EXT_image_gl_colorspace " - "EGL_KHR_image_pixmap " - "EGL_KHR_lock_surface " - "EGL_KHR_gl_colorspace " - "EGL_KHR_gl_texture_2D_image " - "EGL_KHR_gl_texture_3D_image " - "EGL_KHR_gl_texture_cubemap_image " - "EGL_KHR_gl_renderbuffer_image " - "EGL_KHR_reusable_sync " - "EGL_KHR_fence_sync " - "EGL_KHR_create_context " - "EGL_KHR_config_attribs " - "EGL_KHR_surfaceless_context " - "EGL_KHR_stream " - "EGL_KHR_stream_fifo " - "EGL_KHR_stream_producer_eglsurface " - "EGL_KHR_stream_consumer_gltexture " - "EGL_KHR_stream_cross_process_fd " - "EGL_EXT_create_context_robustness " - "EGL_NV_system_time " - "EGL_ANDROID_image_native_buffer " // mandatory - "EGL_KHR_wait_sync " // strongly recommended - "EGL_ANDROID_recordable " // mandatory - "EGL_KHR_partial_update " // strongly recommended - "EGL_EXT_pixel_format_float " - "EGL_EXT_buffer_age " // strongly recommended with partial_update - "EGL_KHR_create_context_no_error " - "EGL_KHR_mutable_render_buffer " - "EGL_EXT_yuv_surface " - "EGL_EXT_protected_content " - "EGL_IMG_context_priority " - "EGL_KHR_no_config_context " - ; -// clang-format on - -// extensions not exposed to applications but used by the ANDROID system -// "EGL_ANDROID_blob_cache " // strongly recommended -// "EGL_IMG_hibernate_process " // optional -// "EGL_ANDROID_native_fence_sync " // strongly recommended -// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 -// "EGL_ANDROID_image_crop " // optional - -/* - * EGL Extensions entry-points exposed to 3rd party applications - * (keep in sync with gExtensionString above) - * - */ -static const extention_map_t sExtensionMap[] = { - // EGL_KHR_lock_surface - { "eglLockSurfaceKHR", - (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, - { "eglUnlockSurfaceKHR", - (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, - - // EGL_KHR_image, EGL_KHR_image_base - { "eglCreateImageKHR", - (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, - { "eglDestroyImageKHR", - (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, - - // EGL_KHR_reusable_sync, EGL_KHR_fence_sync - { "eglCreateSyncKHR", - (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, - { "eglDestroySyncKHR", - (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, - { "eglClientWaitSyncKHR", - (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, - { "eglSignalSyncKHR", - (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, - { "eglGetSyncAttribKHR", - (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, - - // EGL_NV_system_time - { "eglGetSystemTimeFrequencyNV", - (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, - { "eglGetSystemTimeNV", - (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, - - // EGL_KHR_wait_sync - { "eglWaitSyncKHR", - (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, - - // EGL_ANDROID_presentation_time - { "eglPresentationTimeANDROID", - (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, - - // EGL_KHR_swap_buffers_with_damage - { "eglSwapBuffersWithDamageKHR", - (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, - - // EGL_ANDROID_get_native_client_buffer - { "eglGetNativeClientBufferANDROID", - (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID }, - - // EGL_KHR_partial_update - { "eglSetDamageRegionKHR", - (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, - - { "eglCreateStreamKHR", - (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR }, - { "eglDestroyStreamKHR", - (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR }, - { "eglStreamAttribKHR", - (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR }, - { "eglQueryStreamKHR", - (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR }, - { "eglQueryStreamu64KHR", - (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR }, - { "eglQueryStreamTimeKHR", - (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR }, - { "eglCreateStreamProducerSurfaceKHR", - (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR }, - { "eglStreamConsumerGLTextureExternalKHR", - (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR }, - { "eglStreamConsumerAcquireKHR", - (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR }, - { "eglStreamConsumerReleaseKHR", - (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR }, - { "eglGetStreamFileDescriptorKHR", - (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR }, - { "eglCreateStreamFromFileDescriptorKHR", - (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, - - // EGL_ANDROID_get_frame_timestamps - { "eglGetNextFrameIdANDROID", - (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID }, - { "eglGetCompositorTimingANDROID", - (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID }, - { "eglGetCompositorTimingSupportedANDROID", - (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID }, - { "eglGetFrameTimestampsANDROID", - (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, - { "eglGetFrameTimestampSupportedANDROID", - (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID }, - - // EGL_ANDROID_native_fence_sync - { "eglDupNativeFenceFDANDROID", - (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID }, -}; - -/* - * These extensions entry-points should not be exposed to applications. - * They're used internally by the Android EGL layer. - */ -#define FILTER_EXTENSIONS(procname) \ - (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ - !strcmp((procname), "eglHibernateProcessIMG") || \ - !strcmp((procname), "eglAwakenProcessIMG")) - -// accesses protected by sExtensionMapMutex -static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; - -static int sGLExtentionSlot = 0; -static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; - -static void(*findProcAddress(const char* name, - const extention_map_t* map, size_t n))() { - for (uint32_t i=0 ; i<n ; i++) { - if (!strcmp(name, map[i].name)) { - return map[i].address; - } - } - return NULL; -} - -// ---------------------------------------------------------------------------- - -extern void setGLHooksThreadSpecific(gl_hooks_t const *value); extern EGLBoolean egl_init_drivers(); -extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; -extern gl_hooks_t gHooksTrace; - -} // namespace android; +} // namespace android -// ---------------------------------------------------------------------------- - -static inline void clearError() { egl_tls_t::clearError(); } -static inline EGLContext getContext() { return egl_tls_t::getContext(); } - -// ---------------------------------------------------------------------------- +static inline void clearError() { + egl_tls_t::clearError(); +} -EGLDisplay eglGetDisplay(EGLNativeDisplayType display) -{ +EGLDisplay eglGetDisplay(EGLNativeDisplayType display) { ATRACE_CALL(); clearError(); - uintptr_t index = reinterpret_cast<uintptr_t>(display); - if (index >= NUM_DISPLAYS) { - return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); - } - if (egl_init_drivers() == EGL_FALSE) { return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); } - EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); - return dpy; + // Call down the chain, which usually points directly to the impl + // but may also be routed through layers + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetDisplay(display); } -// ---------------------------------------------------------------------------- -// Initialization -// ---------------------------------------------------------------------------- - -EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) -{ +EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display, + const EGLAttrib* attrib_list) { + ATRACE_CALL(); clearError(); - egl_display_ptr dp = get_display(dpy); - if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - - EGLBoolean res = dp->initialize(major, minor); + if (egl_init_drivers() == EGL_FALSE) { + return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); + } - return res; + // Call down the chain, which usually points directly to the impl + // but may also be routed through layers + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetPlatformDisplay(platform, display, attrib_list); } -EGLBoolean eglTerminate(EGLDisplay dpy) -{ - // NOTE: don't unload the drivers b/c some APIs can be called - // after eglTerminate() has been called. eglTerminate() only - // terminates an EGLDisplay, not a EGL itself. - +EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { clearError(); - egl_display_ptr dp = get_display(dpy); - if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - - EGLBoolean res = dp->terminate(); - - return res; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglInitialize(dpy, major, minor); } -// ---------------------------------------------------------------------------- -// configuration -// ---------------------------------------------------------------------------- - -EGLBoolean eglGetConfigs( EGLDisplay dpy, - EGLConfig *configs, - EGLint config_size, EGLint *num_config) -{ +EGLBoolean eglTerminate(EGLDisplay dpy) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - if (num_config==0) { - return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); - } - - EGLBoolean res = EGL_FALSE; - *num_config = 0; - egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso) { - res = cnx->egl.eglGetConfigs( - dp->disp.dpy, configs, config_size, num_config); - } - - return res; + return cnx->platform.eglTerminate(dpy); } -EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, - EGLConfig *configs, EGLint config_size, - EGLint *num_config) -{ +EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, + EGLint* num_config) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - if (num_config==0) { - return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); - } - - EGLBoolean res = EGL_FALSE; - *num_config = 0; - - egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso) { - if (attrib_list) { - char value[PROPERTY_VALUE_MAX]; - property_get("debug.egl.force_msaa", value, "false"); - - if (!strcmp(value, "true")) { - size_t attribCount = 0; - EGLint attrib = attrib_list[0]; - - // Only enable MSAA if the context is OpenGL ES 2.0 and - // if no caveat is requested - const EGLint *attribRendererable = NULL; - const EGLint *attribCaveat = NULL; - - // Count the number of attributes and look for - // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT - while (attrib != EGL_NONE) { - attrib = attrib_list[attribCount]; - switch (attrib) { - case EGL_RENDERABLE_TYPE: - attribRendererable = &attrib_list[attribCount]; - break; - case EGL_CONFIG_CAVEAT: - attribCaveat = &attrib_list[attribCount]; - break; - default: - break; - } - attribCount++; - } - - if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && - (!attribCaveat || attribCaveat[1] != EGL_NONE)) { - - // Insert 2 extra attributes to force-enable MSAA 4x - EGLint aaAttribs[attribCount + 4]; - aaAttribs[0] = EGL_SAMPLE_BUFFERS; - aaAttribs[1] = 1; - aaAttribs[2] = EGL_SAMPLES; - aaAttribs[3] = 4; - - memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); - - EGLint numConfigAA; - EGLBoolean resAA = cnx->egl.eglChooseConfig( - dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); - - if (resAA == EGL_TRUE && numConfigAA > 0) { - ALOGD("Enabling MSAA 4x"); - *num_config = numConfigAA; - return resAA; - } - } - } - } - - res = cnx->egl.eglChooseConfig( - dp->disp.dpy, attrib_list, configs, config_size, num_config); - } - return res; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetConfigs(dpy, configs, config_size, num_config); } -EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, - EGLint attribute, EGLint *value) -{ +EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, + EGLint config_size, EGLint* num_config) { clearError(); - egl_connection_t* cnx = NULL; - const egl_display_ptr dp = validate_display_connection(dpy, cnx); - if (!dp) return EGL_FALSE; - - return cnx->egl.eglGetConfigAttrib( - dp->disp.dpy, config, attribute, value); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglChooseConfig(dpy, attrib_list, configs, config_size, num_config); } -// ---------------------------------------------------------------------------- -// surfaces -// ---------------------------------------------------------------------------- +EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) { + clearError(); -// Translates EGL color spaces to Android data spaces. -static android_dataspace dataSpaceFromEGLColorSpace(EGLint colorspace) { - if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { - return HAL_DATASPACE_UNKNOWN; - } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { - return HAL_DATASPACE_SRGB; - } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) { - return HAL_DATASPACE_DISPLAY_P3; - } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) { - return HAL_DATASPACE_DISPLAY_P3_LINEAR; - } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) { - return HAL_DATASPACE_V0_SCRGB; - } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) { - return HAL_DATASPACE_V0_SCRGB_LINEAR; - } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) { - return HAL_DATASPACE_BT2020_LINEAR; - } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) { - return HAL_DATASPACE_BT2020_PQ; - } - return HAL_DATASPACE_UNKNOWN; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetConfigAttrib(dpy, config, attribute, value); } -// Get the colorspace value that should be reported from queries. When the colorspace -// is unknown (no attribute passed), default to reporting LINEAR. -static EGLint getReportedColorSpace(EGLint colorspace) { - return colorspace == EGL_UNKNOWN ? EGL_GL_COLORSPACE_LINEAR_KHR : colorspace; -} +EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, + const EGLint* attrib_list) { + clearError(); -// Returns a list of color spaces understood by the vendor EGL driver. -static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp) { - std::vector<EGLint> colorSpaces; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreateWindowSurface(dpy, config, window, attrib_list); +} - // sRGB and linear are always supported when color space support is present. - colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR); - colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR); +EGLSurface eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window, + const EGLAttrib* attrib_list) { + clearError(); - if (findExtension(dp->disp.queryString.extensions, - "EGL_EXT_gl_colorspace_display_p3")) { - colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT); - } - if (findExtension(dp->disp.queryString.extensions, - "EGL_EXT_gl_colorspace_scrgb")) { - colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT); - } - if (findExtension(dp->disp.queryString.extensions, - "EGL_EXT_gl_colorspace_scrgb_linear")) { - colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT); - } - if (findExtension(dp->disp.queryString.extensions, - "EGL_EXT_gl_colorspace_bt2020_linear")) { - colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT); - } - if (findExtension(dp->disp.queryString.extensions, - "EGL_EXT_gl_colorspace_bt2020_pq")) { - colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT); - } - if (findExtension(dp->disp.queryString.extensions, - "EGL_EXT_gl_colorspace_display_p3_linear")) { - colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT); - } - return colorSpaces; -} - -// Cleans up color space related parameters that the driver does not understand. -// If there is no color space attribute in attrib_list, colorSpace is left -// unmodified. -static EGLBoolean processAttributes(egl_display_ptr dp, NativeWindowType window, - const EGLint* attrib_list, EGLint* colorSpace, - std::vector<EGLint>* strippedAttribList) { - for (const EGLint* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) { - bool copyAttribute = true; - if (attr[0] == EGL_GL_COLORSPACE_KHR) { - switch (attr[1]) { - case EGL_GL_COLORSPACE_LINEAR_KHR: - case EGL_GL_COLORSPACE_SRGB_KHR: - case EGL_GL_COLORSPACE_DISPLAY_P3_EXT: - case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT: - case EGL_GL_COLORSPACE_SCRGB_EXT: - case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT: - case EGL_GL_COLORSPACE_BT2020_PQ_EXT: - case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT: - // Fail immediately if the driver doesn't have color space support at all. - if (!dp->hasColorSpaceSupport) return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - break; - default: - // BAD_ATTRIBUTE if attr is not any of the EGL_GL_COLORSPACE_* - return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - *colorSpace = attr[1]; - - // Strip the attribute if the driver doesn't understand it. - copyAttribute = false; - std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp); - for (auto driverColorSpace : driverColorSpaces) { - if (attr[1] == driverColorSpace) { - copyAttribute = true; - break; - } - } - - // If the driver doesn't understand it, we should map sRGB-encoded P3 to - // sRGB rather than just dropping the colorspace on the floor. - // For this format, the driver is expected to apply the sRGB - // transfer function during framebuffer operations. - if (!copyAttribute && attr[1] == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) { - strippedAttribList->push_back(attr[0]); - strippedAttribList->push_back(EGL_GL_COLORSPACE_SRGB_KHR); - } - } - if (copyAttribute) { - strippedAttribList->push_back(attr[0]); - strippedAttribList->push_back(attr[1]); - } - } - // Terminate the attribute list. - strippedAttribList->push_back(EGL_NONE); - - // If the passed color space has wide color gamut, check whether the target native window - // supports wide color. - const bool colorSpaceIsNarrow = - *colorSpace == EGL_GL_COLORSPACE_SRGB_KHR || - *colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR || - *colorSpace == EGL_UNKNOWN; - if (window && !colorSpaceIsNarrow) { - bool windowSupportsWideColor = true; - // Ordinarily we'd put a call to native_window_get_wide_color_support - // at the beginning of the function so that we'll have the - // result when needed elsewhere in the function. - // However, because eglCreateWindowSurface is called by SurfaceFlinger and - // SurfaceFlinger is required to answer the call below we would - // end up in a deadlock situation. By moving the call to only happen - // if the application has specifically asked for wide-color we avoid - // the deadlock with SurfaceFlinger since it will not ask for a - // wide-color surface. - int err = native_window_get_wide_color_support(window, &windowSupportsWideColor); - - if (err) { - ALOGE("processAttributes: invalid window (win=%p) " - "failed (%#x) (already connected to another API?)", - window, err); - return setError(EGL_BAD_NATIVE_WINDOW, EGL_FALSE); - } - if (!windowSupportsWideColor) { - // Application has asked for a wide-color colorspace but - // wide-color support isn't available on the display the window is on. - return setError(EGL_BAD_MATCH, EGL_FALSE); - } - } - return true; -} - -// Gets the native pixel format corrsponding to the passed EGLConfig. -void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, - android_pixel_format* format) { - // Set the native window's buffers format to match what this config requests. - // Whether to use sRGB gamma is not part of the EGLconfig, but is part - // of our native format. So if sRGB gamma is requested, we have to - // modify the EGLconfig's format before setting the native window's - // format. - - EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; - cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType); - - EGLint a = 0; - EGLint r, g, b; - r = g = b = 0; - cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r); - cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g); - cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b); - cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a); - EGLint colorDepth = r + g + b; - - // Today, the driver only understands sRGB and linear on 888X - // formats. Strip other colorspaces from the attribute list and - // only use them to set the dataspace via - // native_window_set_buffers_dataspace - // if pixel format is RGBX 8888 - // TBD: Can test for future extensions that indicate that driver - // handles requested color space and we can let it through. - // allow SRGB and LINEAR. All others need to be stripped. - // else if 565, 4444 - // TBD: Can we assume these are supported if 8888 is? - // else if FP16 or 1010102 - // strip colorspace from attribs. - // endif - if (a == 0) { - if (colorDepth <= 16) { - *format = HAL_PIXEL_FORMAT_RGB_565; - } else { - if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { - if (colorDepth > 24) { - *format = HAL_PIXEL_FORMAT_RGBA_1010102; - } else { - *format = HAL_PIXEL_FORMAT_RGBX_8888; - } - } else { - *format = HAL_PIXEL_FORMAT_RGBA_FP16; - } - } - } else { - if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { - if (colorDepth > 24) { - *format = HAL_PIXEL_FORMAT_RGBA_1010102; - } else { - *format = HAL_PIXEL_FORMAT_RGBA_8888; - } - } else { - *format = HAL_PIXEL_FORMAT_RGBA_FP16; - } - } + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreatePlatformWindowSurface(dpy, config, native_window, attrib_list); } -EGLBoolean sendSurfaceMetadata(egl_surface_t* s) { - android_smpte2086_metadata smpteMetadata; - if (s->getSmpte2086Metadata(smpteMetadata)) { - int err = - native_window_set_buffers_smpte2086_metadata(s->getNativeWindow(), &smpteMetadata); - s->resetSmpte2086Metadata(); - if (err != 0) { - ALOGE("error setting native window smpte2086 metadata: %s (%d)", - strerror(-err), err); - return EGL_FALSE; - } - } - android_cta861_3_metadata cta8613Metadata; - if (s->getCta8613Metadata(cta8613Metadata)) { - int err = - native_window_set_buffers_cta861_3_metadata(s->getNativeWindow(), &cta8613Metadata); - s->resetCta8613Metadata(); - if (err != 0) { - ALOGE("error setting native window CTS 861.3 metadata: %s (%d)", - strerror(-err), err); - return EGL_FALSE; - } - } - return EGL_TRUE; -} - -EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, - NativeWindowType window, - const EGLint *attrib_list) -{ - const EGLint *origAttribList = attrib_list; - clearError(); - - egl_connection_t* cnx = NULL; - egl_display_ptr dp = validate_display_connection(dpy, cnx); - if (dp) { - if (!window) { - return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } - - int value = 0; - window->query(window, NATIVE_WINDOW_IS_VALID, &value); - if (!value) { - return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } - - int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - if (result < 0) { - ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " - "failed (%#x) (already connected to another API?)", - window, result); - return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - } - - EGLDisplay iDpy = dp->disp.dpy; - android_pixel_format format; - getNativePixelFormat(iDpy, cnx, config, &format); - - // now select correct colorspace and dataspace based on user's attribute list - EGLint colorSpace = EGL_UNKNOWN; - std::vector<EGLint> strippedAttribList; - if (!processAttributes(dp, window, attrib_list, &colorSpace, - &strippedAttribList)) { - ALOGE("error invalid colorspace: %d", colorSpace); - native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); - return EGL_NO_SURFACE; - } - attrib_list = strippedAttribList.data(); - - { - int err = native_window_set_buffers_format(window, format); - if (err != 0) { - ALOGE("error setting native window pixel format: %s (%d)", - strerror(-err), err); - native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); - return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } - } - - android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace); - // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN. HAL_DATASPACE_UNKNOWN - // is the default value, but it may have changed at this point. - int err = native_window_set_buffers_data_space(window, dataSpace); - if (err != 0) { - ALOGE("error setting native window pixel dataSpace: %s (%d)", - strerror(-err), err); - native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); - return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } - - // the EGL spec requires that a new EGLSurface default to swap interval - // 1, so explicitly set that on the window here. - ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); - anw->setSwapInterval(anw, 1); - - EGLSurface surface = cnx->egl.eglCreateWindowSurface( - iDpy, config, window, attrib_list); - if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = - new egl_surface_t(dp.get(), config, window, surface, - getReportedColorSpace(colorSpace), cnx); - return s; - } - - // EGLSurface creation failed - native_window_set_buffers_format(window, 0); - native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); - } - return EGL_NO_SURFACE; -} - -EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, - NativePixmapType pixmap, - const EGLint *attrib_list) -{ - clearError(); - - egl_connection_t* cnx = NULL; - egl_display_ptr dp = validate_display_connection(dpy, cnx); - if (dp) { - EGLDisplay iDpy = dp->disp.dpy; - android_pixel_format format; - getNativePixelFormat(iDpy, cnx, config, &format); - - // now select a corresponding sRGB format if needed - EGLint colorSpace = EGL_UNKNOWN; - std::vector<EGLint> strippedAttribList; - if (!processAttributes(dp, nullptr, attrib_list, &colorSpace, - &strippedAttribList)) { - ALOGE("error invalid colorspace: %d", colorSpace); - return EGL_NO_SURFACE; - } - attrib_list = strippedAttribList.data(); - - EGLSurface surface = cnx->egl.eglCreatePixmapSurface( - dp->disp.dpy, config, pixmap, attrib_list); - if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = - new egl_surface_t(dp.get(), config, NULL, surface, - getReportedColorSpace(colorSpace), cnx); - return s; - } - } - return EGL_NO_SURFACE; -} - -EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list) -{ - clearError(); - - egl_connection_t* cnx = NULL; - egl_display_ptr dp = validate_display_connection(dpy, cnx); - if (dp) { - EGLDisplay iDpy = dp->disp.dpy; - android_pixel_format format; - getNativePixelFormat(iDpy, cnx, config, &format); - - // Select correct colorspace based on user's attribute list - EGLint colorSpace = EGL_UNKNOWN; - std::vector<EGLint> strippedAttribList; - if (!processAttributes(dp, nullptr, attrib_list, &colorSpace, - &strippedAttribList)) { - ALOGE("error invalid colorspace: %d", colorSpace); - return EGL_NO_SURFACE; - } - attrib_list = strippedAttribList.data(); - - EGLSurface surface = cnx->egl.eglCreatePbufferSurface( - dp->disp.dpy, config, attrib_list); - if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = - new egl_surface_t(dp.get(), config, NULL, surface, - getReportedColorSpace(colorSpace), cnx); - return s; - } - } - return EGL_NO_SURFACE; +EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, + const EGLint* attrib_list) { + clearError(); + + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreatePixmapSurface(dpy, config, pixmap, attrib_list); } -EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) -{ +EGLSurface eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap, + const EGLAttrib* attrib_list) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list); +} - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) { + clearError(); - egl_surface_t * const s = get_surface(surface); - EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); - if (result == EGL_TRUE) { - _s.terminate(); - } - return result; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreatePbufferSurface(dpy, config, attrib_list); } -EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, - EGLint attribute, EGLint *value) -{ +EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglDestroySurface(dpy, surface); +} - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value) { + clearError(); - egl_surface_t const * const s = get_surface(surface); - if (s->getColorSpaceAttribute(attribute, value)) { - return EGL_TRUE; - } else if (s->getSmpte2086Attribute(attribute, value)) { - return EGL_TRUE; - } else if (s->getCta8613Attribute(attribute, value)) { - return EGL_TRUE; - } - return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglQuerySurface(dpy, surface, attribute, value); } void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { ATRACE_CALL(); clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return; - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - setError(EGL_BAD_SURFACE, EGL_FALSE); - } + egl_connection_t* const cnx = &gEGLImpl; + cnx->platform.eglBeginFrame(dpy, surface); } -// ---------------------------------------------------------------------------- -// Contexts -// ---------------------------------------------------------------------------- +EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, + const EGLint* attrib_list) { + clearError(); -EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list) -{ - clearError(); - - egl_connection_t* cnx = NULL; - const egl_display_ptr dp = validate_display_connection(dpy, cnx); - if (dp) { - if (share_list != EGL_NO_CONTEXT) { - if (!ContextRef(dp.get(), share_list).get()) { - return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); - } - egl_context_t* const c = get_context(share_list); - share_list = c->context; - } - EGLContext context = cnx->egl.eglCreateContext( - dp->disp.dpy, config, share_list, attrib_list); - if (context != EGL_NO_CONTEXT) { - // figure out if it's a GLESv1 or GLESv2 - int version = 0; - if (attrib_list) { - while (*attrib_list != EGL_NONE) { - GLint attr = *attrib_list++; - GLint value = *attrib_list++; - if (attr == EGL_CONTEXT_CLIENT_VERSION) { - if (value == 1) { - version = egl_connection_t::GLESv1_INDEX; - } else if (value == 2 || value == 3) { - version = egl_connection_t::GLESv2_INDEX; - } - } - }; - } - egl_context_t* c = new egl_context_t(dpy, context, config, cnx, - version); - return c; - } - } - return EGL_NO_CONTEXT; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreateContext(dpy, config, share_list, attrib_list); } -EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) -{ +EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) - return EGL_FALSE; - - ContextRef _c(dp.get(), ctx); - if (!_c.get()) - return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); - - egl_context_t * const c = get_context(ctx); - EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); - if (result == EGL_TRUE) { - _c.terminate(); - } - return result; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglDestroyContext(dpy, ctx); } -EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, - EGLSurface read, EGLContext ctx) -{ +EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { clearError(); - egl_display_ptr dp = validate_display(dpy); - if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - - // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not - // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is - // a valid but uninitialized display. - if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || - (draw != EGL_NO_SURFACE) ) { - if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); - } - - // get a reference to the object passed in - ContextRef _c(dp.get(), ctx); - SurfaceRef _d(dp.get(), draw); - SurfaceRef _r(dp.get(), read); - - // validate the context (if not EGL_NO_CONTEXT) - if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { - // EGL_NO_CONTEXT is valid - return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); - } - - // these are the underlying implementation's object - EGLContext impl_ctx = EGL_NO_CONTEXT; - EGLSurface impl_draw = EGL_NO_SURFACE; - EGLSurface impl_read = EGL_NO_SURFACE; - - // these are our objects structs passed in - egl_context_t * c = NULL; - egl_surface_t const * d = NULL; - egl_surface_t const * r = NULL; - - // these are the current objects structs - egl_context_t * cur_c = get_context(getContext()); - - if (ctx != EGL_NO_CONTEXT) { - c = get_context(ctx); - impl_ctx = c->context; - } else { - // no context given, use the implementation of the current context - if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { - // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); - return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE); - } - if (cur_c == NULL) { - // no current context - // not an error, there is just no current context. - return EGL_TRUE; - } - } - - // retrieve the underlying implementation's draw EGLSurface - if (draw != EGL_NO_SURFACE) { - if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - d = get_surface(draw); - impl_draw = d->surface; - } - - // retrieve the underlying implementation's read EGLSurface - if (read != EGL_NO_SURFACE) { - if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - r = get_surface(read); - impl_read = r->surface; - } - - - EGLBoolean result = dp->makeCurrent(c, cur_c, - draw, read, ctx, - impl_draw, impl_read, impl_ctx); - - if (result == EGL_TRUE) { - if (c) { - setGLHooksThreadSpecific(c->cnx->hooks[c->version]); - egl_tls_t::setContext(ctx); - _c.acquire(); - _r.acquire(); - _d.acquire(); - } else { - setGLHooksThreadSpecific(&gHooksNoContext); - egl_tls_t::setContext(EGL_NO_CONTEXT); - } - } else { - // this will ALOGE the error - egl_connection_t* const cnx = &gEGLImpl; - result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE); - } - return result; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglMakeCurrent(dpy, draw, read, ctx); } - -EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, - EGLint attribute, EGLint *value) -{ +EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - ContextRef _c(dp.get(), ctx); - if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); - - egl_context_t * const c = get_context(ctx); - return c->cnx->egl.eglQueryContext( - dp->disp.dpy, c->context, attribute, value); - + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglQueryContext(dpy, ctx, attribute, value); } -EGLContext eglGetCurrentContext(void) -{ - // could be called before eglInitialize(), but we wouldn't have a context - // then, and this function would correctly return EGL_NO_CONTEXT. - +EGLContext eglGetCurrentContext(void) { clearError(); - EGLContext ctx = getContext(); - return ctx; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetCurrentContext(); } -EGLSurface eglGetCurrentSurface(EGLint readdraw) -{ - // could be called before eglInitialize(), but we wouldn't have a context - // then, and this function would correctly return EGL_NO_SURFACE. - +EGLSurface eglGetCurrentSurface(EGLint readdraw) { clearError(); - EGLContext ctx = getContext(); - if (ctx) { - egl_context_t const * const c = get_context(ctx); - if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); - switch (readdraw) { - case EGL_READ: return c->read; - case EGL_DRAW: return c->draw; - default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); - } - } - return EGL_NO_SURFACE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetCurrentSurface(readdraw); } -EGLDisplay eglGetCurrentDisplay(void) -{ - // could be called before eglInitialize(), but we wouldn't have a context - // then, and this function would correctly return EGL_NO_DISPLAY. - +EGLDisplay eglGetCurrentDisplay(void) { clearError(); - EGLContext ctx = getContext(); - if (ctx) { - egl_context_t const * const c = get_context(ctx); - if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); - return c->dpy; - } - return EGL_NO_DISPLAY; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetCurrentDisplay(); } -EGLBoolean eglWaitGL(void) -{ +EGLBoolean eglWaitGL(void) { clearError(); egl_connection_t* const cnx = &gEGLImpl; - if (!cnx->dso) - return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); - - return cnx->egl.eglWaitGL(); + return cnx->platform.eglWaitGL(); } -EGLBoolean eglWaitNative(EGLint engine) -{ +EGLBoolean eglWaitNative(EGLint engine) { clearError(); egl_connection_t* const cnx = &gEGLImpl; - if (!cnx->dso) - return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); - - return cnx->egl.eglWaitNative(engine); + return cnx->platform.eglWaitNative(engine); } -EGLint eglGetError(void) -{ - EGLint err = EGL_SUCCESS; +EGLint eglGetError(void) { egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso) { - err = cnx->egl.eglGetError(); - } - if (err == EGL_SUCCESS) { - err = egl_tls_t::getError(); - } - return err; -} - -static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( - const char* procname) { - const egl_connection_t* cnx = &gEGLImpl; - void* proc = NULL; - - proc = dlsym(cnx->libEgl, procname); - if (proc) return (__eglMustCastToProperFunctionPointerType)proc; - - proc = dlsym(cnx->libGles2, procname); - if (proc) return (__eglMustCastToProperFunctionPointerType)proc; - - proc = dlsym(cnx->libGles1, procname); - if (proc) return (__eglMustCastToProperFunctionPointerType)proc; - - return NULL; + return cnx->platform.eglGetError(); } -__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) -{ +__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char* procname) { // eglGetProcAddress() could be the very first function called // in which case we must make sure we've initialized ourselves, this // happens the first time egl_get_display() is called. @@ -1188,431 +243,98 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) if (egl_init_drivers() == EGL_FALSE) { setError(EGL_BAD_PARAMETER, NULL); - return NULL; - } - - if (FILTER_EXTENSIONS(procname)) { - return NULL; - } - - __eglMustCastToProperFunctionPointerType addr; - addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); - if (addr) return addr; - - addr = findBuiltinWrapper(procname); - if (addr) return addr; - - // this protects accesses to sGLExtentionMap and sGLExtentionSlot - pthread_mutex_lock(&sExtensionMapMutex); - - /* - * Since eglGetProcAddress() is not associated to anything, it needs - * to return a function pointer that "works" regardless of what - * the current context is. - * - * For this reason, we return a "forwarder", a small stub that takes - * care of calling the function associated with the context - * currently bound. - * - * We first look for extensions we've already resolved, if we're seeing - * this extension for the first time, we go through all our - * implementations and call eglGetProcAddress() and record the - * result in the appropriate implementation hooks and return the - * address of the forwarder corresponding to that hook set. - * - */ - - const std::string name(procname); - - auto& extentionMap = sGLExtentionMap; - auto pos = extentionMap.find(name); - addr = (pos != extentionMap.end()) ? pos->second : nullptr; - const int slot = sGLExtentionSlot; - - ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, - "no more slots for eglGetProcAddress(\"%s\")", - procname); - - if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { - bool found = false; - - egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglGetProcAddress) { - // Extensions are independent of the bound context - addr = - cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = - cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = - cnx->egl.eglGetProcAddress(procname); - if (addr) found = true; - } - - if (found) { - addr = gExtensionForwarders[slot]; - extentionMap[name] = addr; - sGLExtentionSlot++; - } - } - - pthread_mutex_unlock(&sExtensionMapMutex); - return addr; -} - -class FrameCompletionThread { -public: - - static void queueSync(EGLSyncKHR sync) { - static FrameCompletionThread thread; - - char name[64]; - - std::lock_guard<std::mutex> lock(thread.mMutex); - snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued); - ATRACE_NAME(name); - - thread.mQueue.push_back(sync); - thread.mCondition.notify_one(); - thread.mFramesQueued++; - ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size())); - } - -private: - - FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) { - std::thread thread(&FrameCompletionThread::loop, this); - thread.detach(); - } - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wmissing-noreturn" - void loop() { - while (true) { - threadLoop(); - } - } -#pragma clang diagnostic pop - - void threadLoop() { - EGLSyncKHR sync; - uint32_t frameNum; - { - std::unique_lock<std::mutex> lock(mMutex); - while (mQueue.empty()) { - mCondition.wait(lock); - } - sync = mQueue[0]; - frameNum = mFramesCompleted; - } - EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - { - char name[64]; - snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum); - ATRACE_NAME(name); - - EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); - if (result == EGL_FALSE) { - ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); - } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { - ALOGE("FrameCompletion: timeout waiting for fence"); - } - eglDestroySyncKHR(dpy, sync); - } - { - std::lock_guard<std::mutex> lock(mMutex); - mQueue.pop_front(); - mFramesCompleted++; - ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size())); - } + return nullptr; } - uint32_t mFramesQueued; - uint32_t mFramesCompleted; - std::deque<EGLSyncKHR> mQueue; - std::condition_variable mCondition; - std::mutex mMutex; -}; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetProcAddress(procname); +} -EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, - EGLint *rects, EGLint n_rects) -{ +EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, EGLint* rects, + EGLint n_rects) { ATRACE_CALL(); clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - SurfaceRef _s(dp.get(), draw); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - - egl_surface_t* const s = get_surface(draw); - - if (CC_UNLIKELY(dp->traceGpuCompletion)) { - EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); - if (sync != EGL_NO_SYNC_KHR) { - FrameCompletionThread::queueSync(sync); - } - } - - if (CC_UNLIKELY(dp->finishOnSwap)) { - uint32_t pixel; - egl_context_t * const c = get_context( egl_tls_t::getContext() ); - if (c) { - // glReadPixels() ensures that the frame is complete - s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, - GL_RGBA,GL_UNSIGNED_BYTE,&pixel); - } - } - - if (!sendSurfaceMetadata(s)) { - native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL); - return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE); - } - - if (n_rects == 0) { - return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); - } - - std::vector<android_native_rect_t> androidRects((size_t)n_rects); - for (int r = 0; r < n_rects; ++r) { - int offset = r * 4; - int x = rects[offset]; - int y = rects[offset + 1]; - int width = rects[offset + 2]; - int height = rects[offset + 3]; - android_native_rect_t androidRect; - androidRect.left = x; - androidRect.top = y + height; - androidRect.right = x + width; - androidRect.bottom = y; - androidRects.push_back(androidRect); - } - native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size()); - - if (s->cnx->egl.eglSwapBuffersWithDamageKHR) { - return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface, - rects, n_rects); - } else { - return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); - } -} - -EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) -{ - return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglSwapBuffersWithDamageKHR(dpy, draw, rects, n_rects); } -EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, - NativePixmapType target) -{ +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { + ATRACE_CALL(); clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - - egl_surface_t const * const s = get_surface(surface); - return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglSwapBuffers(dpy, surface); } -const char* eglQueryString(EGLDisplay dpy, EGLint name) -{ +EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) { clearError(); - // Generate an error quietly when client extensions (as defined by - // EGL_EXT_client_extensions) are queried. We do not want to rely on - // validate_display to generate the error as validate_display would log - // the error, which can be misleading. - // - // If we want to support EGL_EXT_client_extensions later, we can return - // the client extension string here instead. - if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) - return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0); - - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return (const char *) NULL; - - switch (name) { - case EGL_VENDOR: - return dp->getVendorString(); - case EGL_VERSION: - return dp->getVersionString(); - case EGL_EXTENSIONS: - return dp->getExtensionString(); - case EGL_CLIENT_APIS: - return dp->getClientApiString(); - default: - break; - } - return setError(EGL_BAD_PARAMETER, (const char *)0); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCopyBuffers(dpy, surface, target); } -extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) -{ +const char* eglQueryString(EGLDisplay dpy, EGLint name) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return (const char *) NULL; - - switch (name) { - case EGL_VENDOR: - return dp->disp.queryString.vendor; - case EGL_VERSION: - return dp->disp.queryString.version; - case EGL_EXTENSIONS: - return dp->disp.queryString.extensions; - case EGL_CLIENT_APIS: - return dp->disp.queryString.clientApi; - default: - break; - } - return setError(EGL_BAD_PARAMETER, (const char *)0); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglQueryString(dpy, name); } -// ---------------------------------------------------------------------------- -// EGL 1.1 -// ---------------------------------------------------------------------------- - -EGLBoolean eglSurfaceAttrib( - EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) -{ +extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - - egl_surface_t * const s = get_surface(surface); - - if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) { - if (!s->getNativeWindow()) { - setError(EGL_BAD_SURFACE, EGL_FALSE); - } - int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0); - return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - if (attribute == EGL_TIMESTAMPS_ANDROID) { - if (!s->getNativeWindow()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0); - return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - if (s->setSmpte2086Attribute(attribute, value)) { - return EGL_TRUE; - } else if (s->setCta8613Attribute(attribute, value)) { - return EGL_TRUE; - } else if (s->cnx->egl.eglSurfaceAttrib) { - return s->cnx->egl.eglSurfaceAttrib( - dp->disp.dpy, s->surface, attribute, value); - } - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglQueryStringImplementationANDROID(dpy, name); } -EGLBoolean eglBindTexImage( - EGLDisplay dpy, EGLSurface surface, EGLint buffer) -{ +EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - - egl_surface_t const * const s = get_surface(surface); - if (s->cnx->egl.eglBindTexImage) { - return s->cnx->egl.eglBindTexImage( - dp->disp.dpy, s->surface, buffer); - } - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglSurfaceAttrib(dpy, surface, attribute, value); } -EGLBoolean eglReleaseTexImage( - EGLDisplay dpy, EGLSurface surface, EGLint buffer) -{ +EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - - egl_surface_t const * const s = get_surface(surface); - if (s->cnx->egl.eglReleaseTexImage) { - return s->cnx->egl.eglReleaseTexImage( - dp->disp.dpy, s->surface, buffer); - } - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglBindTexImage(dpy, surface, buffer); } -EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) -{ +EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean res = EGL_TRUE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglSwapInterval) { - res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); - } - - return res; + return cnx->platform.eglReleaseTexImage(dpy, surface, buffer); } +EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) { + clearError(); -// ---------------------------------------------------------------------------- -// EGL 1.2 -// ---------------------------------------------------------------------------- + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglSwapInterval(dpy, interval); +} -EGLBoolean eglWaitClient(void) -{ +EGLBoolean eglWaitClient(void) { clearError(); egl_connection_t* const cnx = &gEGLImpl; - if (!cnx->dso) - return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); - - EGLBoolean res; - if (cnx->egl.eglWaitClient) { - res = cnx->egl.eglWaitClient(); - } else { - res = cnx->egl.eglWaitGL(); - } - return res; + return cnx->platform.eglWaitClient(); } -EGLBoolean eglBindAPI(EGLenum api) -{ +EGLBoolean eglBindAPI(EGLenum api) { clearError(); if (egl_init_drivers() == EGL_FALSE) { return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); } - // bind this API on all EGLs - EGLBoolean res = EGL_TRUE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglBindAPI) { - res = cnx->egl.eglBindAPI(api); - } - return res; + return cnx->platform.eglBindAPI(api); } -EGLenum eglQueryAPI(void) -{ +EGLenum eglQueryAPI(void) { clearError(); if (egl_init_drivers() == EGL_FALSE) { @@ -1620,824 +342,324 @@ EGLenum eglQueryAPI(void) } egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglQueryAPI) { - return cnx->egl.eglQueryAPI(); - } - - // or, it can only be OpenGL ES - return EGL_OPENGL_ES_API; + return cnx->platform.eglQueryAPI(); } -EGLBoolean eglReleaseThread(void) -{ +EGLBoolean eglReleaseThread(void) { clearError(); egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglReleaseThread) { - cnx->egl.eglReleaseThread(); - } - - // If there is context bound to the thread, release it - egl_display_t::loseCurrent(get_context(getContext())); - - egl_tls_t::clearTLS(); - return EGL_TRUE; + return cnx->platform.eglReleaseThread(); } -EGLSurface eglCreatePbufferFromClientBuffer( - EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list) -{ +EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint* attrib_list) { clearError(); - egl_connection_t* cnx = NULL; - const egl_display_ptr dp = validate_display_connection(dpy, cnx); - if (!dp) return EGL_FALSE; - if (cnx->egl.eglCreatePbufferFromClientBuffer) { - return cnx->egl.eglCreatePbufferFromClientBuffer( - dp->disp.dpy, buftype, buffer, config, attrib_list); - } - return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, + attrib_list); } -// ---------------------------------------------------------------------------- -// EGL_EGLEXT_VERSION 3 -// ---------------------------------------------------------------------------- - -EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, - const EGLint *attrib_list) -{ +EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglLockSurfaceKHR(dpy, surface, attrib_list); +} - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) { + clearError(); - egl_surface_t const * const s = get_surface(surface); - if (s->cnx->egl.eglLockSurfaceKHR) { - return s->cnx->egl.eglLockSurfaceKHR( - dp->disp.dpy, s->surface, attrib_list); - } - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglUnlockSurfaceKHR(dpy, surface); } -EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) -{ +EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint* attrib_list) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); +} - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +EGLImage eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, + const EGLAttrib* attrib_list) { + clearError(); - egl_surface_t const * const s = get_surface(surface); - if (s->cnx->egl.eglUnlockSurfaceKHR) { - return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); - } - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreateImage(dpy, ctx, target, buffer, attrib_list); } -EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, - EGLClientBuffer buffer, const EGLint *attrib_list) -{ - clearError(); - - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_IMAGE_KHR; - - ContextRef _c(dp.get(), ctx); - egl_context_t * const c = _c.get(); - - // Temporary hack: eglImageCreateKHR should accept EGL_GL_COLORSPACE_LINEAR_KHR, - // EGL_GL_COLORSPACE_SRGB_KHR and EGL_GL_COLORSPACE_DEFAULT_EXT if - // EGL_EXT_image_gl_colorspace is supported, but some drivers don't like - // the DEFAULT value and generate an error. - std::vector<EGLint> strippedAttribList; - for (const EGLint *attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) { - if (attr[0] == EGL_GL_COLORSPACE_KHR && - dp->haveExtension("EGL_EXT_image_gl_colorspace")) { - if (attr[1] != EGL_GL_COLORSPACE_LINEAR_KHR && - attr[1] != EGL_GL_COLORSPACE_SRGB_KHR) { - continue; - } - } - strippedAttribList.push_back(attr[0]); - strippedAttribList.push_back(attr[1]); - } - strippedAttribList.push_back(EGL_NONE); +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) { + clearError(); - EGLImageKHR result = EGL_NO_IMAGE_KHR; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglCreateImageKHR) { - result = cnx->egl.eglCreateImageKHR( - dp->disp.dpy, - c ? c->context : EGL_NO_CONTEXT, - target, buffer, strippedAttribList.data()); - } - return result; + return cnx->platform.eglDestroyImageKHR(dpy, img); } -EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) -{ +EGLBoolean eglDestroyImage(EGLDisplay dpy, EGLImageKHR img) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglDestroyImageKHR) { - result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); - } - return result; + return cnx->platform.eglDestroyImage(dpy, img); } // ---------------------------------------------------------------------------- // EGL_EGLEXT_VERSION 5 // ---------------------------------------------------------------------------- - -EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) -{ +EGLSyncKHR eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_SYNC_KHR; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreateSync(dpy, type, attrib_list); +} + +EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) { + clearError(); - EGLSyncKHR result = EGL_NO_SYNC_KHR; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglCreateSyncKHR) { - result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); - } - return result; + return cnx->platform.eglCreateSyncKHR(dpy, type, attrib_list); } -EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) -{ +EGLBoolean eglDestroySync(EGLDisplay dpy, EGLSyncKHR sync) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglDestroySync(dpy, sync); +} + +EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) { + clearError(); - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglDestroySyncKHR) { - result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); - } - return result; + return cnx->platform.eglDestroySyncKHR(dpy, sync); } EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglSignalSyncKHR) { - result = cnx->egl.eglSignalSyncKHR( - dp->disp.dpy, sync, mode); - } - return result; + return cnx->platform.eglSignalSyncKHR(dpy, sync, mode); } -EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, - EGLint flags, EGLTimeKHR timeout) -{ +EGLint eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTimeKHR timeout) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLint result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { - result = cnx->egl.eglClientWaitSyncKHR( - dp->disp.dpy, sync, flags, timeout); - } - return result; + return cnx->platform.eglClientWaitSyncKHR(dpy, sync, flags, timeout); } -EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, - EGLint attribute, EGLint *value) -{ +EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { - result = cnx->egl.eglGetSyncAttribKHR( - dp->disp.dpy, sync, attribute, value); - } - return result; + return cnx->platform.eglClientWaitSyncKHR(dpy, sync, flags, timeout); } -EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list) -{ +EGLBoolean eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_STREAM_KHR; - - EGLStreamKHR result = EGL_NO_STREAM_KHR; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglCreateStreamKHR) { - result = cnx->egl.eglCreateStreamKHR( - dp->disp.dpy, attrib_list); - } - return result; + return cnx->platform.eglGetSyncAttrib(dpy, sync, attribute, value); } -EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) -{ +EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint* value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglDestroyStreamKHR) { - result = cnx->egl.eglDestroyStreamKHR( - dp->disp.dpy, stream); - } - return result; + return cnx->platform.eglGetSyncAttribKHR(dpy, sync, attribute, value); } -EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, - EGLenum attribute, EGLint value) -{ +EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglStreamAttribKHR) { - result = cnx->egl.eglStreamAttribKHR( - dp->disp.dpy, stream, attribute, value); - } - return result; + return cnx->platform.eglCreateStreamKHR(dpy, attrib_list); } -EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, - EGLenum attribute, EGLint *value) -{ +EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglQueryStreamKHR) { - result = cnx->egl.eglQueryStreamKHR( - dp->disp.dpy, stream, attribute, value); - } - return result; + return cnx->platform.eglDestroyStreamKHR(dpy, stream); } -EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, - EGLenum attribute, EGLuint64KHR *value) -{ +EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, + EGLint value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) { - result = cnx->egl.eglQueryStreamu64KHR( - dp->disp.dpy, stream, attribute, value); - } - return result; + return cnx->platform.eglStreamAttribKHR(dpy, stream, attribute, value); } -EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, - EGLenum attribute, EGLTimeKHR *value) -{ +EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, + EGLint* value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) { - result = cnx->egl.eglQueryStreamTimeKHR( - dp->disp.dpy, stream, attribute, value); - } - return result; + return cnx->platform.eglQueryStreamKHR(dpy, stream, attribute, value); } -EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, - EGLStreamKHR stream, const EGLint *attrib_list) -{ +EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, + EGLuint64KHR* value) { clearError(); - egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_SURFACE; - egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) { - EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR( - dp->disp.dpy, config, stream, attrib_list); - if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, - EGL_GL_COLORSPACE_LINEAR_KHR, cnx); - return s; - } - } - return EGL_NO_SURFACE; + return cnx->platform.eglQueryStreamu64KHR(dpy, stream, attribute, value); } -EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, - EGLStreamKHR stream) -{ +EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, + EGLTimeKHR* value) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) { - result = cnx->egl.eglStreamConsumerGLTextureExternalKHR( - dp->disp.dpy, stream); - } - return result; + return cnx->platform.eglQueryStreamTimeKHR(dpy, stream, attribute, value); } -EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy, - EGLStreamKHR stream) -{ +EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, + const EGLint* attrib_list) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) { - result = cnx->egl.eglStreamConsumerAcquireKHR( - dp->disp.dpy, stream); - } - return result; + return cnx->platform.eglCreateStreamProducerSurfaceKHR(dpy, config, stream, attrib_list); } -EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy, - EGLStreamKHR stream) -{ +EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - - EGLBoolean result = EGL_FALSE; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) { - result = cnx->egl.eglStreamConsumerReleaseKHR( - dp->disp.dpy, stream); - } - return result; + return cnx->platform.eglStreamConsumerGLTextureExternalKHR(dpy, stream); } -EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR( - EGLDisplay dpy, EGLStreamKHR stream) -{ +EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR; - - EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) { - result = cnx->egl.eglGetStreamFileDescriptorKHR( - dp->disp.dpy, stream); - } - return result; + return cnx->platform.eglStreamConsumerAcquireKHR(dpy, stream); } -EGLStreamKHR eglCreateStreamFromFileDescriptorKHR( - EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor) -{ +EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_STREAM_KHR; - - EGLStreamKHR result = EGL_NO_STREAM_KHR; egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) { - result = cnx->egl.eglCreateStreamFromFileDescriptorKHR( - dp->disp.dpy, file_descriptor); - } - return result; + return cnx->platform.eglStreamConsumerReleaseKHR(dpy, stream); } -// ---------------------------------------------------------------------------- -// EGL_EGLEXT_VERSION 15 -// ---------------------------------------------------------------------------- - -EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { +EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(EGLDisplay dpy, EGLStreamKHR stream) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_FALSE; - EGLint result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglWaitSyncKHR) { - result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); - } - return result; + return cnx->platform.eglGetStreamFileDescriptorKHR(dpy, stream); } -// ---------------------------------------------------------------------------- -// ANDROID extensions -// ---------------------------------------------------------------------------- - -EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) -{ +EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(EGLDisplay dpy, + EGLNativeFileDescriptorKHR file_descriptor) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglCreateStreamFromFileDescriptorKHR(dpy, file_descriptor); +} - EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; +EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { + clearError(); egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { - result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); - } - return result; + return cnx->platform.eglWaitSyncKHR(dpy, sync, flags); } -EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, - EGLnsecsANDROID time) -{ +EGLBoolean eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) { clearError(); + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglWaitSync(dpy, sync, flags); +} - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return EGL_FALSE; - } +EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) { + clearError(); - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - setError(EGL_BAD_SURFACE, EGL_FALSE); - return EGL_FALSE; - } + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglDupNativeFenceFDANDROID(dpy, sync); +} - egl_surface_t const * const s = get_surface(surface); - native_window_set_buffers_timestamp(s->getNativeWindow(), time); +EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time) { + clearError(); - return EGL_TRUE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglPresentationTimeANDROID(dpy, surface, time); } -EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) { +EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer* buffer) { clearError(); - // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus - // this function cannot be implemented when this libEGL is built for - // vendors. -#ifndef __ANDROID_VNDK__ - if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); - return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer)); -#else - return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); -#endif + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetNativeClientBufferANDROID(buffer); } -// ---------------------------------------------------------------------------- -// NVIDIA extensions -// ---------------------------------------------------------------------------- -EGLuint64NV eglGetSystemTimeFrequencyNV() -{ +EGLuint64NV eglGetSystemTimeFrequencyNV() { clearError(); if (egl_init_drivers() == EGL_FALSE) { return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE); } - EGLuint64NV ret = 0; egl_connection_t* const cnx = &gEGLImpl; - - if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { - return cnx->egl.eglGetSystemTimeFrequencyNV(); - } - - return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0); + return cnx->platform.eglGetSystemTimeFrequencyNV(); } -EGLuint64NV eglGetSystemTimeNV() -{ +EGLuint64NV eglGetSystemTimeNV() { clearError(); if (egl_init_drivers() == EGL_FALSE) { return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE); } - EGLuint64NV ret = 0; egl_connection_t* const cnx = &gEGLImpl; - - if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { - return cnx->egl.eglGetSystemTimeNV(); - } - - return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0); + return cnx->platform.eglGetSystemTimeNV(); } -// ---------------------------------------------------------------------------- -// Partial update extension -// ---------------------------------------------------------------------------- -EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, - EGLint *rects, EGLint n_rects) -{ +EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, EGLint* rects, + EGLint n_rects) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - setError(EGL_BAD_DISPLAY, EGL_FALSE); - return EGL_FALSE; - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - setError(EGL_BAD_SURFACE, EGL_FALSE); - return EGL_FALSE; - } - - egl_surface_t const * const s = get_surface(surface); - if (s->cnx->egl.eglSetDamageRegionKHR) { - return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface, - rects, n_rects); - } - - return EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglSetDamageRegionKHR(dpy, surface, rects, n_rects); } -EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, - EGLuint64KHR *frameId) { +EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR* frameId) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - egl_surface_t const * const s = get_surface(surface); - - if (!s->getNativeWindow()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - uint64_t nextFrameId = 0; - int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId); - - if (ret != 0) { - // This should not happen. Return an error that is not in the spec - // so it's obvious something is very wrong. - ALOGE("eglGetNextFrameId: Unexpected error."); - return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); - } - - *frameId = nextFrameId; - return EGL_TRUE; + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetNextFrameIdANDROID(dpy, surface, frameId); } -EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, - EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values) -{ +EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, + const EGLint* names, EGLnsecsANDROID* values) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - egl_surface_t const * const s = get_surface(surface); - - if (!s->getNativeWindow()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - nsecs_t* compositeDeadline = nullptr; - nsecs_t* compositeInterval = nullptr; - nsecs_t* compositeToPresentLatency = nullptr; - - for (int i = 0; i < numTimestamps; i++) { - switch (names[i]) { - case EGL_COMPOSITE_DEADLINE_ANDROID: - compositeDeadline = &values[i]; - break; - case EGL_COMPOSITE_INTERVAL_ANDROID: - compositeInterval = &values[i]; - break; - case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: - compositeToPresentLatency = &values[i]; - break; - default: - return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); - } - } - - int ret = native_window_get_compositor_timing(s->getNativeWindow(), - compositeDeadline, compositeInterval, compositeToPresentLatency); - - switch (ret) { - case 0: - return EGL_TRUE; - case -ENOSYS: - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - default: - // This should not happen. Return an error that is not in the spec - // so it's obvious something is very wrong. - ALOGE("eglGetCompositorTiming: Unexpected error."); - return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); - } + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetCompositorTimingANDROID(dpy, surface, numTimestamps, names, values); } -EGLBoolean eglGetCompositorTimingSupportedANDROID( - EGLDisplay dpy, EGLSurface surface, EGLint name) -{ +EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint name) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - egl_surface_t const * const s = get_surface(surface); - - ANativeWindow* window = s->getNativeWindow(); - if (!window) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - switch (name) { - case EGL_COMPOSITE_DEADLINE_ANDROID: - case EGL_COMPOSITE_INTERVAL_ANDROID: - case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: - return EGL_TRUE; - default: - return EGL_FALSE; - } + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetCompositorTimingSupportedANDROID(dpy, surface, name); } -EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, - EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, - EGLnsecsANDROID *values) -{ +EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, + EGLint numTimestamps, const EGLint* timestamps, + EGLnsecsANDROID* values) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - egl_surface_t const * const s = get_surface(surface); - - if (!s->getNativeWindow()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - nsecs_t* requestedPresentTime = nullptr; - nsecs_t* acquireTime = nullptr; - nsecs_t* latchTime = nullptr; - nsecs_t* firstRefreshStartTime = nullptr; - nsecs_t* gpuCompositionDoneTime = nullptr; - nsecs_t* lastRefreshStartTime = nullptr; - nsecs_t* displayPresentTime = nullptr; - nsecs_t* dequeueReadyTime = nullptr; - nsecs_t* releaseTime = nullptr; - - for (int i = 0; i < numTimestamps; i++) { - switch (timestamps[i]) { - case EGL_REQUESTED_PRESENT_TIME_ANDROID: - requestedPresentTime = &values[i]; - break; - case EGL_RENDERING_COMPLETE_TIME_ANDROID: - acquireTime = &values[i]; - break; - case EGL_COMPOSITION_LATCH_TIME_ANDROID: - latchTime = &values[i]; - break; - case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: - firstRefreshStartTime = &values[i]; - break; - case EGL_LAST_COMPOSITION_START_TIME_ANDROID: - lastRefreshStartTime = &values[i]; - break; - case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: - gpuCompositionDoneTime = &values[i]; - break; - case EGL_DISPLAY_PRESENT_TIME_ANDROID: - displayPresentTime = &values[i]; - break; - case EGL_DEQUEUE_READY_TIME_ANDROID: - dequeueReadyTime = &values[i]; - break; - case EGL_READS_DONE_TIME_ANDROID: - releaseTime = &values[i]; - break; - default: - return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); - } - } - - int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId, - requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime, - lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime, - dequeueReadyTime, releaseTime); - - switch (ret) { - case 0: - return EGL_TRUE; - case -ENOENT: - return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE); - case -ENOSYS: - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - case -EINVAL: - return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); - default: - // This should not happen. Return an error that is not in the spec - // so it's obvious something is very wrong. - ALOGE("eglGetFrameTimestamps: Unexpected error."); - return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); - } + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetFrameTimestampsANDROID(dpy, surface, frameId, numTimestamps, + timestamps, values); } -EGLBoolean eglGetFrameTimestampSupportedANDROID( - EGLDisplay dpy, EGLSurface surface, EGLint timestamp) -{ +EGLBoolean eglGetFrameTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, + EGLint timestamp) { clearError(); - const egl_display_ptr dp = validate_display(dpy); - if (!dp) { - return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); - } - - SurfaceRef _s(dp.get(), surface); - if (!_s.get()) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - egl_surface_t const * const s = get_surface(surface); - - ANativeWindow* window = s->getNativeWindow(); - if (!window) { - return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); - } - - switch (timestamp) { - case EGL_COMPOSITE_DEADLINE_ANDROID: - case EGL_COMPOSITE_INTERVAL_ANDROID: - case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: - case EGL_REQUESTED_PRESENT_TIME_ANDROID: - case EGL_RENDERING_COMPLETE_TIME_ANDROID: - case EGL_COMPOSITION_LATCH_TIME_ANDROID: - case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: - case EGL_LAST_COMPOSITION_START_TIME_ANDROID: - case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: - case EGL_DEQUEUE_READY_TIME_ANDROID: - case EGL_READS_DONE_TIME_ANDROID: - return EGL_TRUE; - case EGL_DISPLAY_PRESENT_TIME_ANDROID: { - int value = 0; - window->query(window, - NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value); - return value == 0 ? EGL_FALSE : EGL_TRUE; - } - default: - return EGL_FALSE; - } + egl_connection_t* const cnx = &gEGLImpl; + return cnx->platform.eglGetFrameTimestampSupportedANDROID(dpy, surface, timestamp); } diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp new file mode 100644 index 0000000000..00caff222b --- /dev/null +++ b/opengl/libs/EGL/egl_angle_platform.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__ANDROID__) + +#include <cutils/properties.h> +#include "Loader.h" +#include "egl_angle_platform.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#include <EGL/Platform.h> +#pragma GCC diagnostic pop + +#include <android/dlext.h> +#include <dlfcn.h> +#include <graphicsenv/GraphicsEnv.h> +#include <time.h> +#include <log/log.h> + +namespace angle { + +static GetDisplayPlatformFunc angleGetDisplayPlatform = nullptr; +static ResetDisplayPlatformFunc angleResetDisplayPlatform = nullptr; + +static time_t startTime = time(nullptr); + +static const unsigned char* getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/, + const char* /*categoryName*/) { + // Returning ptr to 'g' (non-zero) to ALWAYS enable tracing initially. + // This ptr is what will be passed into "category_group_enabled" of addTraceEvent + static const unsigned char traceEnabled = 'g'; + return &traceEnabled; +} + +static double monotonicallyIncreasingTime(PlatformMethods* /*platform*/) { + return difftime(time(nullptr), startTime); +} + +static void logError(PlatformMethods* /*platform*/, const char* errorMessage) { + ALOGE("ANGLE Error:%s", errorMessage); +} + +static void logWarning(PlatformMethods* /*platform*/, const char* warningMessage) { + ALOGW("ANGLE Warn:%s", warningMessage); +} + +static void logInfo(PlatformMethods* /*platform*/, const char* infoMessage) { + ALOGD("ANGLE Info:%s", infoMessage); +} + +static TraceEventHandle addTraceEvent( + PlatformMethods* /**platform*/, char phase, const unsigned char* /*category_group_enabled*/, + const char* name, unsigned long long /*id*/, double /*timestamp*/, int /*num_args*/, + const char** /*arg_names*/, const unsigned char* /*arg_types*/, + const unsigned long long* /*arg_values*/, unsigned char /*flags*/) { + switch (phase) { + case 'B': { + ATRACE_BEGIN(name); + break; + } + case 'E': { + ATRACE_END(); + break; + } + case 'I': { + ATRACE_NAME(name); + break; + } + default: + // Could handle other event types here + break; + } + // Return any non-zero handle to avoid assert in ANGLE + TraceEventHandle result = 1.0; + return result; +} + +static void assignAnglePlatformMethods(PlatformMethods* platformMethods) { + platformMethods->addTraceEvent = addTraceEvent; + platformMethods->getTraceCategoryEnabledFlag = getTraceCategoryEnabledFlag; + platformMethods->monotonicallyIncreasingTime = monotonicallyIncreasingTime; + platformMethods->logError = logError; + platformMethods->logWarning = logWarning; + platformMethods->logInfo = logInfo; +} + +// Initialize function ptrs for ANGLE PlatformMethods struct, used for systrace +bool initializeAnglePlatform(EGLDisplay dpy) { + // Since we're inside libEGL, use dlsym to lookup fptr for ANGLEGetDisplayPlatform + android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace(); + const android_dlextinfo dlextinfo = { + .flags = ANDROID_DLEXT_USE_NAMESPACE, + .library_namespace = ns, + }; + void* so = android_dlopen_ext("libGLESv2_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo); + angleGetDisplayPlatform = + reinterpret_cast<GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform")); + + if (!angleGetDisplayPlatform) { + ALOGE("dlsym lookup of ANGLEGetDisplayPlatform in libEGL_angle failed!"); + return false; + } + + angleResetDisplayPlatform = + reinterpret_cast<ResetDisplayPlatformFunc>( + eglGetProcAddress("ANGLEResetDisplayPlatform")); + + PlatformMethods* platformMethods = nullptr; + if (!((angleGetDisplayPlatform)(dpy, g_PlatformMethodNames, + g_NumPlatformMethods, nullptr, + &platformMethods))) { + ALOGE("ANGLEGetDisplayPlatform call failed!"); + return false; + } + if (platformMethods) { + assignAnglePlatformMethods(platformMethods); + } else { + ALOGE("In initializeAnglePlatform() platformMethods struct ptr is NULL. Not assigning " + "tracing function ptrs!"); + } + return true; +} + +void resetAnglePlatform(EGLDisplay dpy) { + if (angleResetDisplayPlatform) { + angleResetDisplayPlatform(dpy); + } +} + +}; // namespace angle + +#endif // __ANDROID__ diff --git a/opengl/libs/EGL/egl_angle_platform.h b/opengl/libs/EGL/egl_angle_platform.h new file mode 100644 index 0000000000..6c24aa5418 --- /dev/null +++ b/opengl/libs/EGL/egl_angle_platform.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#if defined(__ANDROID__) + +#include "egldefs.h" + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include "egl_trace.h" + +namespace angle { + +bool initializeAnglePlatform(EGLDisplay dpy); +void resetAnglePlatform(EGLDisplay dpy); + +}; // namespace angle + +#endif // __ANDROID__ diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp index ec548f3121..bcf496164b 100644 --- a/opengl/libs/EGL/egl_cache.cpp +++ b/opengl/libs/EGL/egl_cache.cpp @@ -95,7 +95,7 @@ void egl_cache_t::initialize(egl_display_t *display) { reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>( cnx->egl.eglGetProcAddress( "eglSetBlobCacheFuncsANDROID")); - if (eglSetBlobCacheFuncsANDROID == NULL) { + if (eglSetBlobCacheFuncsANDROID == nullptr) { ALOGE("EGL_ANDROID_blob_cache advertised, " "but unable to get eglSetBlobCacheFuncsANDROID"); return; @@ -119,7 +119,7 @@ void egl_cache_t::terminate() { if (mBlobCache) { mBlobCache->writeToFile(); } - mBlobCache = NULL; + mBlobCache = nullptr; } void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 2aec249aa5..c100db7c2a 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -21,14 +21,19 @@ #include "../egl_impl.h" +#include <EGL/eglext_angle.h> #include <private/EGL/display.h> +#include <cutils/properties.h> +#include "Loader.h" +#include "egl_angle_platform.h" #include "egl_cache.h" #include "egl_object.h" #include "egl_tls.h" -#include "egl_trace.h" -#include "Loader.h" -#include <cutils/properties.h> + +#include <android/dlext.h> +#include <dlfcn.h> +#include <graphicsenv/GraphicsEnv.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <configstore/Utils.h> @@ -41,7 +46,8 @@ namespace android { // ---------------------------------------------------------------------------- static char const * const sVendorString = "Android"; -static char const * const sVersionString = "1.4 Android META-EGL"; +static char const* const sVersionString14 = "1.4 Android META-EGL"; +static char const* const sVersionString15 = "1.5 Android META-EGL"; static char const * const sClientApiString = "OpenGL_ES"; extern char const * const gBuiltinExtensionString; @@ -114,15 +120,91 @@ bool egl_display_t::getObject(egl_object_t* object) const { return false; } -EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) { +EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp, + const EGLAttrib* attrib_list) { if (uintptr_t(disp) >= NUM_DISPLAYS) - return NULL; + return nullptr; + + return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list); +} + +static bool addAnglePlatformAttributes(egl_connection_t* const cnx, + std::vector<EGLAttrib>& attrs) { + intptr_t vendorEGL = (intptr_t)cnx->vendorEGL; + + attrs.reserve(4 * 2); + + attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); + attrs.push_back(cnx->angleBackend); + + switch (cnx->angleBackend) { + case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: + ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__); + char prop[PROPERTY_VALUE_MAX]; + property_get("debug.angle.validation", prop, "0"); + attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE); + attrs.push_back(atoi(prop)); + break; + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: + ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__); + break; + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__); + // NOTE: This is only valid if the backend is OpenGL + attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE); + attrs.push_back(vendorEGL); + break; + default: + ALOGV("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend); + break; + } + attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE); + attrs.push_back(EGL_FALSE); - return sDisplay[uintptr_t(disp)].getDisplay(disp); + return true; } -EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) { +static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx, + const EGLAttrib* attrib_list, EGLint* error) { + EGLDisplay dpy = EGL_NO_DISPLAY; + *error = EGL_NONE; + + if (cnx->egl.eglGetPlatformDisplay) { + std::vector<EGLAttrib> attrs; + if (attrib_list) { + for (const EGLAttrib* attr = attrib_list; *attr != EGL_NONE; attr += 2) { + attrs.push_back(attr[0]); + attrs.push_back(attr[1]); + } + } + + if (!addAnglePlatformAttributes(cnx, attrs)) { + ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display); + *error = EGL_BAD_PARAMETER; + return EGL_NO_DISPLAY; + } + attrs.push_back(EGL_NONE); + + dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), + attrs.data()); + if (dpy == EGL_NO_DISPLAY) { + ALOGE("eglGetPlatformDisplay failed!"); + } else { + if (!angle::initializeAnglePlatform(dpy)) { + ALOGE("initializeAnglePlatform failed!"); + } + } + } else { + ALOGE("eglGetDisplay(%p) failed: Unable to look up eglGetPlatformDisplay from ANGLE", + display); + } + + return dpy; +} +EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display, + const EGLAttrib* attrib_list) { std::lock_guard<std::mutex> _l(lock); ATRACE_CALL(); @@ -131,11 +213,37 @@ EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) { egl_connection_t* const cnx = &gEGLImpl; if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) { - EGLDisplay dpy = cnx->egl.eglGetDisplay(display); + EGLDisplay dpy = EGL_NO_DISPLAY; + + if (cnx->useAngle) { + EGLint error; + dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error); + if (error != EGL_NONE) { + return setError(error, dpy); + } + } + if (dpy == EGL_NO_DISPLAY) { + // NOTE: eglGetPlatformDisplay with a empty attribute list + // behaves the same as eglGetDisplay + if (cnx->egl.eglGetPlatformDisplay) { + dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANDROID_KHR, display, + attrib_list); + } + + // It is possible that eglGetPlatformDisplay does not have a + // working implementation for Android platform; in that case, + // one last fallback to eglGetDisplay + if(dpy == EGL_NO_DISPLAY) { + if (attrib_list) { + ALOGW("getPlatformDisplay: unexpected attribute list, attributes ignored"); + } + dpy = cnx->egl.eglGetDisplay(display); + } + } + disp.dpy = dpy; if (dpy == EGL_NO_DISPLAY) { - loader.close(cnx->dso); - cnx->dso = NULL; + loader.close(cnx); } } @@ -148,13 +256,20 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { std::unique_lock<std::mutex> _l(refLock); refs++; if (refs > 1) { - if (major != NULL) - *major = VERSION_MAJOR; - if (minor != NULL) - *minor = VERSION_MINOR; + // We don't know what to report until we know what the + // driver supports. Make sure we are initialized before + // returning the version info. while(!eglIsInitialized) { refCond.wait(_l); } + egl_connection_t* const cnx = &gEGLImpl; + + // TODO: If device doesn't provide 1.4 or 1.5 then we'll be + // changing the behavior from the past where we always advertise + // version 1.4. May need to check that revision is valid + // before using cnx->major & cnx->minor + if (major != nullptr) *major = cnx->major; + if (minor != nullptr) *minor = cnx->minor; return EGL_TRUE; } while(eglIsInitialized) { @@ -201,7 +316,52 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { // the query strings are per-display mVendorString = sVendorString; - mVersionString = sVersionString; + mVersionString.clear(); + cnx->driverVersion = EGL_MAKE_VERSION(1, 4, 0); + if ((cnx->major == 1) && (cnx->minor == 5)) { + mVersionString = sVersionString15; + cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0); + } else if ((cnx->major == 1) && (cnx->minor == 4)) { + mVersionString = sVersionString14; + // Extensions needed for an EGL 1.4 implementation to be + // able to support EGL 1.5 functionality + std::vector<const char*> egl15extensions = { + "EGL_EXT_client_extensions", + // "EGL_EXT_platform_base", // implemented by EGL runtime + "EGL_KHR_image_base", + "EGL_KHR_fence_sync", + "EGL_KHR_wait_sync", + "EGL_KHR_create_context", + "EGL_EXT_create_context_robustness", + "EGL_KHR_gl_colorspace", + "EGL_ANDROID_native_fence_sync", + }; + bool extensionsFound = true; + for (const auto& name : egl15extensions) { + extensionsFound &= findExtension(disp.queryString.extensions, name); + ALOGV("Extension %s: %s", name, + findExtension(disp.queryString.extensions, name) ? "Found" : "Missing"); + } + // NOTE: From the spec: + // Creation of fence sync objects requires support from the bound + // client API, and will not succeed unless the client API satisfies: + // client API is OpenGL ES, and either the OpenGL ES version is 3.0 + // or greater, or the GL_OES_EGL_sync extension is supported. + // We don't have a way to check the GL_EXTENSIONS string at this + // point in the code, assume that GL_OES_EGL_sync is supported + // because EGL_KHR_fence_sync is supported (as verified above). + if (extensionsFound) { + // Have everything needed to emulate EGL 1.5 so report EGL 1.5 + // to the application. + mVersionString = sVersionString15; + cnx->major = 1; + cnx->minor = 5; + } + } + if (mVersionString.empty()) { + ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor); + mVersionString = sVersionString14; + } mClientApiString = sClientApiString; mExtensionString = gBuiltinExtensionString; @@ -218,7 +378,8 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { if (wideColorBoardConfig && hasColorSpaceSupport) { mExtensionString.append( "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear " - "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 "); + "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 " + "EGL_EXT_gl_colorspace_display_p3_passthrough "); } bool hasHdrBoardConfig = @@ -240,12 +401,6 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { if (len) { // NOTE: we could avoid the copy if we had strnstr. const std::string ext(start, len); - // Temporary hack: Adreno 530 driver exposes this extension under the draft - // KHR name, but during Khronos review it was decided to demote it to EXT. - if (ext == "EGL_EXT_image_gl_colorspace" && - findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) { - mExtensionString.append("EGL_EXT_image_gl_colorspace "); - } if (findExtension(disp.queryString.extensions, ext.c_str(), len)) { mExtensionString.append(ext + " "); } @@ -268,10 +423,12 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { traceGpuCompletion = true; } - if (major != NULL) - *major = VERSION_MAJOR; - if (minor != NULL) - *minor = VERSION_MINOR; + // TODO: If device doesn't provide 1.4 or 1.5 then we'll be + // changing the behavior from the past where we always advertise + // version 1.4. May need to check that revision is valid + // before using cnx->major & cnx->minor + if (major != nullptr) *major = cnx->major; + if (minor != nullptr) *minor = cnx->minor; } { // scope for refLock @@ -311,6 +468,10 @@ EGLBoolean egl_display_t::terminate() { egl_connection_t* const cnx = &gEGLImpl; if (cnx->dso && disp.state == egl_display_t::INITIALIZED) { + // If we're using ANGLE reset any custom DisplayPlatform + if (cnx->useAngle) { + angle::resetAnglePlatform(disp.dpy); + } if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) { ALOGW("eglTerminate(%p) failed (%s)", disp.dpy, egl_tls_t::egl_strerror(cnx->egl.eglGetError())); @@ -361,8 +522,8 @@ void egl_display_t::loseCurrentImpl(egl_context_t * cur_c) // by construction, these are either 0 or valid (possibly terminated) // it should be impossible for these to be invalid ContextRef _cur_c(cur_c); - SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL); - SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL); + SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr); + SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr); { // scope for the lock std::lock_guard<std::mutex> _l(lock); @@ -387,8 +548,8 @@ EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c, // by construction, these are either 0 or valid (possibly terminated) // it should be impossible for these to be invalid ContextRef _cur_c(cur_c); - SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL); - SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL); + SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr); + SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr); { // scope for the lock std::lock_guard<std::mutex> _l(lock); diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h index 79a9f082a6..36856b79fe 100644 --- a/opengl/libs/EGL/egl_display.h +++ b/opengl/libs/EGL/egl_display.h @@ -49,6 +49,7 @@ bool findExtension(const char* exts, const char* name, size_t nameLen = 0); class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes static egl_display_t sDisplay[NUM_DISPLAYS]; EGLDisplay getDisplay(EGLNativeDisplayType display); + EGLDisplay getPlatformDisplay(EGLNativeDisplayType display, const EGLAttrib* attrib_list); void loseCurrentImpl(egl_context_t * cur_c); public: @@ -72,7 +73,7 @@ public: bool getObject(egl_object_t* object) const; static egl_display_t* get(EGLDisplay dpy); - static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp); + static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp, const EGLAttrib* attrib_list); EGLBoolean makeCurrent(egl_context_t* c, egl_context_t* cur_c, EGLSurface draw, EGLSurface read, EGLContext ctx, @@ -160,7 +161,7 @@ public: const egl_display_t* get() const { return mDpy; } egl_display_t* get() { return mDpy; } - operator bool() const { return mDpy != NULL; } + operator bool() const { return mDpy != nullptr; } private: egl_display_t* mDpy; diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in index b587a16203..2921d512f1 100644 --- a/opengl/libs/EGL/egl_entries.in +++ b/opengl/libs/EGL/egl_entries.in @@ -44,6 +44,18 @@ EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGL /* EGL 1.4 */ +/* EGL 1.5 */ +EGL_ENTRY(EGLImage, eglCreateImage, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLAttrib *) +EGL_ENTRY(EGLBoolean, eglDestroyImage, EGLDisplay, EGLImage) +EGL_ENTRY(EGLDisplay, eglGetPlatformDisplay, EGLenum, void *, const EGLAttrib *) +EGL_ENTRY(EGLSurface, eglCreatePlatformWindowSurface, EGLDisplay, EGLConfig, void *, const EGLAttrib *) +EGL_ENTRY(EGLSurface, eglCreatePlatformPixmapSurface, EGLDisplay, EGLConfig, void *, const EGLAttrib *) +EGL_ENTRY(EGLSyncKHR, eglCreateSync, EGLDisplay, EGLenum, const EGLAttrib *) +EGL_ENTRY(EGLBoolean, eglDestroySync, EGLDisplay, EGLSync) +EGL_ENTRY(EGLint, eglClientWaitSync, EGLDisplay, EGLSync, EGLint, EGLTimeKHR) +EGL_ENTRY(EGLBoolean, eglGetSyncAttrib, EGLDisplay, EGLSync, EGLint, EGLAttrib *) +EGL_ENTRY(EGLBoolean, eglWaitSync, EGLDisplay, EGLSync, EGLint) + /* EGL_EGLEXT_VERSION 3 */ EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint *) @@ -75,6 +87,10 @@ EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR) EGL_ENTRY(EGLint, eglWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint) +/* EGL_EGLEXT_VERSION 20170627 */ +EGL_ENTRY(EGLSurface, eglCreatePlatformWindowSurfaceEXT, EGLDisplay, EGLConfig, void *, const EGLint *) +EGL_ENTRY(EGLSurface, eglCreatePlatformPixmapSurfaceEXT, EGLDisplay, EGLConfig, void *, const EGLint *) + /* ANDROID extensions */ EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp new file mode 100644 index 0000000000..f936ac0efd --- /dev/null +++ b/opengl/libs/EGL/egl_layers.cpp @@ -0,0 +1,436 @@ +/* + ** Copyright 2018, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include "egl_layers.h" + +#include <EGL/egl.h> +#include <android-base/file.h> +#include <android-base/strings.h> +#include <android/dlext.h> +#include <cutils/properties.h> +#include <dlfcn.h> +#include <graphicsenv/GraphicsEnv.h> +#include <log/log.h> +#include <nativebridge/native_bridge.h> +#include <nativeloader/native_loader.h> +#include <sys/prctl.h> + +namespace android { + +// GLES Layers +// +// - Layer discovery - +// 1. Check for debug layer list from GraphicsEnv +// 2. If none enabled, check system properties +// +// - Layer initializing - +// TODO: ADD DETAIL ABOUT NEW INTERFACES +// - InitializeLayer (provided by layer, called by loader) +// - GetLayerProcAddress (provided by layer, called by loader) +// - getNextLayerProcAddress (provided by loader, called by layer) +// +// 1. Walk through defs for egl and each gl version +// 2. Call GetLayerProcAddress passing the name and the target hook entry point +// - This tells the layer the next point in the chain it should call +// 3. Replace the hook with the layer's entry point +// - All entryoints will be present, anything unsupported by the driver will +// have gl_unimplemented +// +// - Extension layering - +// Not all functions are known to Android, so libEGL handles extensions. +// They are looked up by applications using eglGetProcAddress +// Layers can look them up with getNextLayerProcAddress + +const int kFuncCount = sizeof(platform_impl_t) / sizeof(char*) + sizeof(egl_t) / sizeof(char*) + + sizeof(gl_hooks_t) / sizeof(char*); + +typedef struct FunctionTable { + EGLFuncPointer x[kFuncCount]; + EGLFuncPointer& operator[](int i) { return x[i]; } +} FunctionTable; + +// TODO: Move these to class +std::unordered_map<std::string, int> func_indices; +// func_indices.reserve(kFuncCount); + +std::unordered_map<int, std::string> func_names; +// func_names.reserve(kFuncCount); + +std::vector<FunctionTable> layer_functions; + +const void* getNextLayerProcAddress(void* layer_id, const char* name) { + // Use layer_id to find funcs for layer below current + // This is the same key provided in InitializeLayer + auto next_layer_funcs = reinterpret_cast<FunctionTable*>(layer_id); + EGLFuncPointer val; + + if (func_indices.find(name) == func_indices.end()) { + // No entry for this function - it is an extension + // call down the GPA chain directly to the impl + ALOGV("getNextLayerProcAddress servicing %s", name); + + // Look up which GPA we should use + int gpaIndex = func_indices["eglGetProcAddress"]; + EGLFuncPointer gpaNext = (*next_layer_funcs)[gpaIndex]; + + ALOGV("Calling down the GPA chain (%llu) for %s", (unsigned long long)gpaNext, name); + + // Call it for the requested function + typedef void* (*PFNEGLGETPROCADDRESSPROC)(const char*); + PFNEGLGETPROCADDRESSPROC next = reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(gpaNext); + + val = reinterpret_cast<EGLFuncPointer>(next(name)); + ALOGV("Got back %llu for %s", (unsigned long long)val, name); + + // We should store it now, but to do that, we need to move func_idx to the class so we can + // increment it separately + // TODO: Move func_idx to class and store the result of GPA + return reinterpret_cast<void*>(val); + } + + // int index = func_indices[name]; + // val = (*next_layer_funcs)[index]; + // return reinterpret_cast<void*>(val); + return reinterpret_cast<void*>((*next_layer_funcs)[func_indices[name]]); +} + +void SetupFuncMaps(FunctionTable& functions, char const* const* entries, EGLFuncPointer* curr, + int& func_idx) { + while (*entries) { + const char* name = *entries; + + // Some names overlap, only fill with initial entry + // This does mean that some indices will not be used + if (func_indices.find(name) == func_indices.end()) { + func_names[func_idx] = name; + func_indices[name] = func_idx; + } + + // Populate layer_functions once with initial value + // These values will arrive in priority order, starting with platform entries + if (functions[func_idx] == nullptr) { + functions[func_idx] = *curr; + } + + entries++; + curr++; + func_idx++; + } +} + +LayerLoader& LayerLoader::getInstance() { + // This function is mutex protected in egl_init_drivers_locked and eglGetProcAddressImpl + static LayerLoader layer_loader; + + if (!layer_loader.layers_loaded_) layer_loader.LoadLayers(); + + return layer_loader; +} + +const char kSystemLayerLibraryDir[] = "/data/local/debug/gles"; + +std::string LayerLoader::GetDebugLayers() { + // Layers can be specified at the Java level in GraphicsEnvironemnt + // gpu_debug_layers_gles = layer1:layer2:layerN + std::string debug_layers = android::GraphicsEnv::getInstance().getDebugLayersGLES(); + + if (debug_layers.empty()) { + // Only check system properties if Java settings are empty + char prop[PROPERTY_VALUE_MAX]; + property_get("debug.gles.layers", prop, ""); + debug_layers = prop; + } + + return debug_layers; +} + +EGLFuncPointer LayerLoader::ApplyLayer(layer_setup_func layer_setup, const char* name, + EGLFuncPointer next) { + // Walk through our list of LayerSetup functions (they will already be in reverse order) to + // build up a call chain from the driver + + EGLFuncPointer layer_entry = next; + + layer_entry = layer_setup(name, layer_entry); + + if (next != layer_entry) { + ALOGV("We succeeded, replacing hook (%llu) with layer entry (%llu), for %s", + (unsigned long long)next, (unsigned long long)layer_entry, name); + } + + return layer_entry; +} + +EGLFuncPointer LayerLoader::ApplyLayers(const char* name, EGLFuncPointer next) { + if (!layers_loaded_ || layer_setup_.empty()) return next; + + ALOGV("ApplyLayers called for %s with next (%llu), current_layer_ (%i)", name, + (unsigned long long)next, current_layer_); + + EGLFuncPointer val = next; + + // Only ApplyLayers for layers that have been setup, not all layers yet + for (unsigned i = 0; i < current_layer_; i++) { + ALOGV("ApplyLayers: Calling ApplyLayer with i = %i for %s with next (%llu)", i, name, + (unsigned long long)next); + val = ApplyLayer(layer_setup_[i], name, val); + } + + ALOGV("ApplyLayers returning %llu for %s", (unsigned long long)val, name); + + return val; +} + +void LayerLoader::LayerPlatformEntries(layer_setup_func layer_setup, EGLFuncPointer* curr, + char const* const* entries) { + while (*entries) { + char const* name = *entries; + + EGLFuncPointer prev = *curr; + + // Pass the existing entry point into the layer, replace the call with return value + *curr = ApplyLayer(layer_setup, name, *curr); + + if (prev != *curr) { + ALOGV("LayerPlatformEntries: Replaced (%llu) with platform entry (%llu), for %s", + (unsigned long long)prev, (unsigned long long)*curr, name); + } else { + ALOGV("LayerPlatformEntries: No change(%llu) for %s, which means layer did not " + "intercept", + (unsigned long long)prev, name); + } + + curr++; + entries++; + } +} + +void LayerLoader::LayerDriverEntries(layer_setup_func layer_setup, EGLFuncPointer* curr, + char const* const* entries) { + while (*entries) { + char const* name = *entries; + EGLFuncPointer prev = *curr; + + // Only apply layers to driver entries if not handled by the platform + if (FindPlatformImplAddr(name) == nullptr) { + // Pass the existing entry point into the layer, replace the call with return value + *curr = ApplyLayer(layer_setup, name, *prev); + + if (prev != *curr) { + ALOGV("LayerDriverEntries: Replaced (%llu) with platform entry (%llu), for %s", + (unsigned long long)prev, (unsigned long long)*curr, name); + } + + } else { + ALOGV("LayerDriverEntries: Skipped (%llu) for %s", (unsigned long long)prev, name); + } + + curr++; + entries++; + } +} + +bool LayerLoader::Initialized() { + return initialized_; +} + +void LayerLoader::InitLayers(egl_connection_t* cnx) { + if (!layers_loaded_) return; + + if (initialized_) return; + + if (layer_setup_.empty()) { + initialized_ = true; + return; + } + + // Include the driver in layer_functions + layer_functions.resize(layer_setup_.size() + 1); + + // Walk through the initial lists and create layer_functions[0] + int func_idx = 0; + char const* const* entries; + EGLFuncPointer* curr; + + entries = platform_names; + curr = reinterpret_cast<EGLFuncPointer*>(&cnx->platform); + SetupFuncMaps(layer_functions[0], entries, curr, func_idx); + ALOGV("InitLayers: func_idx after platform_names: %i", func_idx); + + entries = egl_names; + curr = reinterpret_cast<EGLFuncPointer*>(&cnx->egl); + SetupFuncMaps(layer_functions[0], entries, curr, func_idx); + ALOGV("InitLayers: func_idx after egl_names: %i", func_idx); + + entries = gl_names; + curr = reinterpret_cast<EGLFuncPointer*>(&cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl); + SetupFuncMaps(layer_functions[0], entries, curr, func_idx); + ALOGV("InitLayers: func_idx after gl_names: %i", func_idx); + + // Walk through each layer's entry points per API, starting just above the driver + for (current_layer_ = 0; current_layer_ < layer_setup_.size(); current_layer_++) { + // Init the layer with a key that points to layer just below it + layer_init_[current_layer_](reinterpret_cast<void*>(&layer_functions[current_layer_]), + reinterpret_cast<PFNEGLGETNEXTLAYERPROCADDRESSPROC>( + getNextLayerProcAddress)); + + // Check functions implemented by the platform + func_idx = 0; + entries = platform_names; + curr = reinterpret_cast<EGLFuncPointer*>(&cnx->platform); + LayerPlatformEntries(layer_setup_[current_layer_], curr, entries); + + // Populate next function table after layers have been applied + SetupFuncMaps(layer_functions[current_layer_ + 1], entries, curr, func_idx); + + // EGL + entries = egl_names; + curr = reinterpret_cast<EGLFuncPointer*>(&cnx->egl); + LayerDriverEntries(layer_setup_[current_layer_], curr, entries); + + // Populate next function table after layers have been applied + SetupFuncMaps(layer_functions[current_layer_ + 1], entries, curr, func_idx); + + // GLES 2+ + // NOTE: We route calls to GLESv2 hooks, not GLESv1, so layering does not support GLES 1.x + // If it were added in the future, a different layer initialization model would be needed, + // that defers loading GLES entrypoints until after eglMakeCurrent, so two phase + // initialization. + entries = gl_names; + curr = reinterpret_cast<EGLFuncPointer*>(&cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl); + LayerDriverEntries(layer_setup_[current_layer_], curr, entries); + + // Populate next function table after layers have been applied + SetupFuncMaps(layer_functions[current_layer_ + 1], entries, curr, func_idx); + } + + // We only want to apply layers once + initialized_ = true; +} + +void LayerLoader::LoadLayers() { + std::string debug_layers = GetDebugLayers(); + + // If no layers are specified, we're done + if (debug_layers.empty()) return; + + // Only enable the system search path for non-user builds + std::string system_path; + if (property_get_bool("ro.debuggable", false) && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { + system_path = kSystemLayerLibraryDir; + } + + ALOGI("Debug layer list: %s", debug_layers.c_str()); + std::vector<std::string> layers = android::base::Split(debug_layers, ":"); + + // Load the layers in reverse order so we start with the driver's entrypoint and work our way up + for (int32_t i = layers.size() - 1; i >= 0; i--) { + // Check each layer path for the layer + std::vector<std::string> paths = + android::base::Split(android::GraphicsEnv::getInstance().getLayerPaths().c_str(), + ":"); + + if (!system_path.empty()) { + // Prepend the system paths so they override other layers + auto it = paths.begin(); + paths.insert(it, system_path); + } + + bool layer_found = false; + for (uint32_t j = 0; j < paths.size() && !layer_found; j++) { + std::string layer; + + ALOGI("Searching %s for GLES layers", paths[j].c_str()); + + // Realpath will return null for non-existent files + android::base::Realpath(paths[j] + "/" + layers[i], &layer); + + if (!layer.empty()) { + layer_found = true; + ALOGI("GLES layer found: %s", layer.c_str()); + + // Load the layer + // + // TODO: This code is common with Vulkan loader, refactor + // + // Libraries in the system layer library dir can't be loaded into + // the application namespace. That causes compatibility problems, since + // any symbol dependencies will be resolved by system libraries. They + // can't safely use libc++_shared, for example. Which is one reason + // (among several) we only allow them in non-user builds. + void* handle = nullptr; + auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace(); + if (app_namespace && !android::base::StartsWith(layer, kSystemLayerLibraryDir)) { + bool native_bridge = false; + char* error_message = nullptr; + handle = OpenNativeLibraryInNamespace( + app_namespace, layer.c_str(), &native_bridge, &error_message); + if (!handle) { + ALOGE("Failed to load layer %s with error: %s", layer.c_str(), + error_message); + android::NativeLoaderFreeErrorMessage(error_message); + return; + } + + } else { + handle = dlopen(layer.c_str(), RTLD_NOW | RTLD_LOCAL); + } + + if (handle) { + ALOGV("Loaded layer handle (%llu) for layer %s", (unsigned long long)handle, + layers[i].c_str()); + } else { + // If the layer is found but can't be loaded, try setenforce 0 + const char* dlsym_error = dlerror(); + ALOGE("Failed to load layer %s with error: %s", layer.c_str(), dlsym_error); + return; + } + + // Find the layer's Initialize function + std::string init_func = "InitializeLayer"; + ALOGV("Looking for entrypoint %s", init_func.c_str()); + + layer_init_func LayerInit = + reinterpret_cast<layer_init_func>(dlsym(handle, init_func.c_str())); + if (LayerInit) { + ALOGV("Found %s for layer %s", init_func.c_str(), layer.c_str()); + layer_init_.push_back(LayerInit); + } else { + ALOGE("Failed to dlsym %s for layer %s", init_func.c_str(), layer.c_str()); + return; + } + + // Find the layer's setup function + std::string setup_func = "GetLayerProcAddress"; + ALOGV("Looking for entrypoint %s", setup_func.c_str()); + + layer_setup_func LayerSetup = + reinterpret_cast<layer_setup_func>(dlsym(handle, setup_func.c_str())); + if (LayerSetup) { + ALOGV("Found %s for layer %s", setup_func.c_str(), layer.c_str()); + layer_setup_.push_back(LayerSetup); + } else { + ALOGE("Failed to dlsym %s for layer %s", setup_func.c_str(), layer.c_str()); + return; + } + } + } + } + // Track this so we only attempt to load these once + layers_loaded_ = true; +} + +} // namespace android diff --git a/opengl/libs/EGL/egl_layers.h b/opengl/libs/EGL/egl_layers.h new file mode 100644 index 0000000000..e401b448cf --- /dev/null +++ b/opengl/libs/EGL/egl_layers.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EGL_LAYERS_H +#define ANDROID_EGL_LAYERS_H + +#include <string> +#include <unordered_map> +#include <vector> + +#include <EGL/egldefs.h> + +#include "egl_platform_entries.h" + +typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer; + +namespace android { + +class LayerLoader { +public: + static LayerLoader& getInstance(); + ~LayerLoader(){}; + + typedef void* (*PFNEGLGETNEXTLAYERPROCADDRESSPROC)(void*, const char*); + typedef EGLFuncPointer (*layer_init_func)( + const void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address); + typedef EGLFuncPointer (*layer_setup_func)(const char* name, EGLFuncPointer next); + + void LoadLayers(); + void InitLayers(egl_connection_t*); + void LayerPlatformEntries(layer_setup_func layer_setup, EGLFuncPointer*, char const* const*); + void LayerDriverEntries(layer_setup_func layer_setup, EGLFuncPointer*, char const* const*); + bool Initialized(); + std::string GetDebugLayers(); + + EGLFuncPointer GetGpaNext(unsigned i); + EGLFuncPointer ApplyLayer(layer_setup_func layer_setup, const char* name, EGLFuncPointer next); + EGLFuncPointer ApplyLayers(const char* name, EGLFuncPointer next); + + std::vector<layer_init_func> layer_init_; + std::vector<layer_setup_func> layer_setup_; + +private: + LayerLoader() : layers_loaded_(false), initialized_(false), current_layer_(0){}; + bool layers_loaded_; + bool initialized_; + unsigned current_layer_; +}; + +}; // namespace android + +#endif // ANDROID_EGL_LAYERS_H diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp index f879254f76..ff4fe2dd9c 100644 --- a/opengl/libs/EGL/egl_object.cpp +++ b/opengl/libs/EGL/egl_object.cpp @@ -81,14 +81,14 @@ egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWind } egl_surface_t::~egl_surface_t() { - if (win != NULL) { + if (win != nullptr) { disconnect(); win->decStrong(this); } } void egl_surface_t::disconnect() { - if (win != NULL && connected) { + if (win != nullptr && connected) { native_window_set_buffers_format(win, 0); if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) { ALOGW("EGLNativeWindowType %p disconnect failed", win); @@ -281,12 +281,12 @@ void egl_surface_t::terminate() { egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config, egl_connection_t const* cnx, int version) : egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context), - config(config), read(0), draw(0), cnx(cnx), version(version) { + config(config), read(nullptr), draw(nullptr), cnx(cnx), version(version) { } void egl_context_t::onLooseCurrent() { - read = NULL; - draw = NULL; + read = nullptr; + draw = nullptr; } void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) { diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h index 4e1de5cec4..fb2bdf4c51 100644 --- a/opengl/libs/EGL/egl_object.h +++ b/opengl/libs/EGL/egl_object.h @@ -67,7 +67,7 @@ public: public: ~LocalRef(); explicit LocalRef(egl_object_t* rhs); - explicit LocalRef(egl_display_t const* display, T o) : ref(0) { + explicit LocalRef(egl_display_t const* display, T o) : ref(nullptr) { egl_object_t* native = reinterpret_cast<N*>(o); if (o && egl_object_t::get(display, native)) { ref = native; diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp new file mode 100644 index 0000000000..872631f048 --- /dev/null +++ b/opengl/libs/EGL/egl_platform_entries.cpp @@ -0,0 +1,2715 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "egl_platform_entries.h" + +#include <ctype.h> +#include <dlfcn.h> +#include <stdlib.h> +#include <string.h> + +#include <hardware/gralloc1.h> + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <EGL/eglext_angle.h> + +#include <android/hardware_buffer.h> +#include <android-base/strings.h> +#include <graphicsenv/GraphicsEnv.h> +#include <private/android/AHardwareBufferHelpers.h> + +#include <cutils/compiler.h> +#include <cutils/properties.h> +#include <log/log.h> + +#include <condition_variable> +#include <deque> +#include <mutex> +#include <unordered_map> +#include <string> +#include <thread> + +#include "../egl_impl.h" + +#include "egl_display.h" +#include "egl_object.h" +#include "egl_layers.h" +#include "egl_tls.h" +#include "egl_trace.h" + +using namespace android; + +// ---------------------------------------------------------------------------- + +namespace android { + +using nsecs_t = int64_t; + +struct extention_map_t { + const char* name; + __eglMustCastToProperFunctionPointerType address; +}; + +/* + * This is the list of EGL extensions exposed to applications. + * + * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL + * wrapper and are always available. + * + * The rest (gExtensionString) depend on support in the EGL driver, and are + * only available if the driver supports them. However, some of these must be + * supported because they are used by the Android system itself; these are + * listed as mandatory below and are required by the CDD. The system *assumes* + * the mandatory extensions are present and may not function properly if some + * are missing. + * + * NOTE: Both strings MUST have a single space as the last character. + */ + +extern char const * const gBuiltinExtensionString; +extern char const * const gExtensionString; + +// clang-format off +// Extensions implemented by the EGL wrapper. +char const * const gBuiltinExtensionString = + "EGL_KHR_get_all_proc_addresses " + "EGL_ANDROID_presentation_time " + "EGL_KHR_swap_buffers_with_damage " + "EGL_ANDROID_get_native_client_buffer " + "EGL_ANDROID_front_buffer_auto_refresh " + "EGL_ANDROID_get_frame_timestamps " + "EGL_EXT_surface_SMPTE2086_metadata " + "EGL_EXT_surface_CTA861_3_metadata " + ; + +// Whitelist of extensions exposed to applications if implemented in the vendor driver. +char const * const gExtensionString = + "EGL_KHR_image " // mandatory + "EGL_KHR_image_base " // mandatory + "EGL_EXT_image_gl_colorspace " + "EGL_KHR_image_pixmap " + "EGL_KHR_lock_surface " + "EGL_KHR_gl_colorspace " + "EGL_KHR_gl_texture_2D_image " + "EGL_KHR_gl_texture_3D_image " + "EGL_KHR_gl_texture_cubemap_image " + "EGL_KHR_gl_renderbuffer_image " + "EGL_KHR_reusable_sync " + "EGL_KHR_fence_sync " + "EGL_KHR_create_context " + "EGL_KHR_config_attribs " + "EGL_KHR_surfaceless_context " + "EGL_KHR_stream " + "EGL_KHR_stream_fifo " + "EGL_KHR_stream_producer_eglsurface " + "EGL_KHR_stream_consumer_gltexture " + "EGL_KHR_stream_cross_process_fd " + "EGL_EXT_create_context_robustness " + "EGL_NV_system_time " + "EGL_ANDROID_image_native_buffer " // mandatory + "EGL_KHR_wait_sync " // strongly recommended + "EGL_ANDROID_recordable " // mandatory + "EGL_KHR_partial_update " // strongly recommended + "EGL_EXT_pixel_format_float " + "EGL_EXT_buffer_age " // strongly recommended with partial_update + "EGL_KHR_create_context_no_error " + "EGL_KHR_mutable_render_buffer " + "EGL_EXT_yuv_surface " + "EGL_EXT_protected_content " + "EGL_IMG_context_priority " + "EGL_KHR_no_config_context " + ; + +char const * const gClientExtensionString = + "EGL_EXT_client_extensions " + "EGL_KHR_platform_android " + "EGL_ANGLE_platform_angle"; +// clang-format on + +// extensions not exposed to applications but used by the ANDROID system +// "EGL_ANDROID_blob_cache " // strongly recommended +// "EGL_IMG_hibernate_process " // optional +// "EGL_ANDROID_native_fence_sync " // strongly recommended +// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 + +/* + * EGL Extensions entry-points exposed to 3rd party applications + * (keep in sync with gExtensionString above) + * + */ +static const extention_map_t sExtensionMap[] = { + // EGL_KHR_lock_surface + { "eglLockSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, + { "eglUnlockSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, + + // EGL_KHR_image, EGL_KHR_image_base + { "eglCreateImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, + { "eglDestroyImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, + + // EGL_KHR_reusable_sync, EGL_KHR_fence_sync + { "eglCreateSyncKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, + { "eglDestroySyncKHR", + (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, + { "eglClientWaitSyncKHR", + (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, + { "eglSignalSyncKHR", + (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, + { "eglGetSyncAttribKHR", + (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, + + // EGL_NV_system_time + { "eglGetSystemTimeFrequencyNV", + (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, + { "eglGetSystemTimeNV", + (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, + + // EGL_KHR_wait_sync + { "eglWaitSyncKHR", + (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, + + // EGL_ANDROID_presentation_time + { "eglPresentationTimeANDROID", + (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, + + // EGL_KHR_swap_buffers_with_damage + { "eglSwapBuffersWithDamageKHR", + (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, + + // EGL_ANDROID_get_native_client_buffer + { "eglGetNativeClientBufferANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID }, + + // EGL_KHR_partial_update + { "eglSetDamageRegionKHR", + (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, + + { "eglCreateStreamKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR }, + { "eglDestroyStreamKHR", + (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR }, + { "eglStreamAttribKHR", + (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR }, + { "eglQueryStreamKHR", + (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR }, + { "eglQueryStreamu64KHR", + (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR }, + { "eglQueryStreamTimeKHR", + (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR }, + { "eglCreateStreamProducerSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR }, + { "eglStreamConsumerGLTextureExternalKHR", + (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR }, + { "eglStreamConsumerAcquireKHR", + (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR }, + { "eglStreamConsumerReleaseKHR", + (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR }, + { "eglGetStreamFileDescriptorKHR", + (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR }, + { "eglCreateStreamFromFileDescriptorKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, + + // EGL_ANDROID_get_frame_timestamps + { "eglGetNextFrameIdANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID }, + { "eglGetCompositorTimingANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID }, + { "eglGetCompositorTimingSupportedANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID }, + { "eglGetFrameTimestampsANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, + { "eglGetFrameTimestampSupportedANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID }, + + // EGL_ANDROID_native_fence_sync + { "eglDupNativeFenceFDANDROID", + (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID }, +}; + +/* + * These extensions entry-points should not be exposed to applications. + * They're used internally by the Android EGL layer. + */ +#define FILTER_EXTENSIONS(procname) \ + (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ + !strcmp((procname), "eglHibernateProcessIMG") || \ + !strcmp((procname), "eglAwakenProcessIMG")) + +// accesses protected by sExtensionMapMutex +static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; + +static int sGLExtentionSlot = 0; +static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; + +static void(*findProcAddress(const char* name, + const extention_map_t* map, size_t n))() { + for (uint32_t i=0 ; i<n ; i++) { + if (!strcmp(name, map[i].name)) { + return map[i].address; + } + } + return nullptr; +} + +// ---------------------------------------------------------------------------- + +extern void setGLHooksThreadSpecific(gl_hooks_t const *value); +extern EGLBoolean egl_init_drivers(); +extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; +extern gl_hooks_t gHooksTrace; + +// ---------------------------------------------------------------------------- + +static inline EGLContext getContext() { return egl_tls_t::getContext(); } + +// ---------------------------------------------------------------------------- + +static EGLDisplay eglGetPlatformDisplayTmpl(EGLenum platform, EGLNativeDisplayType display, + const EGLAttrib* attrib_list) { + if (platform != EGL_PLATFORM_ANDROID_KHR) { + return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); + } + + uintptr_t index = reinterpret_cast<uintptr_t>(display); + if (index >= NUM_DISPLAYS) { + return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); + } + + EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display, attrib_list); + return dpy; +} + +EGLDisplay eglGetDisplayImpl(EGLNativeDisplayType display) { + return eglGetPlatformDisplayTmpl(EGL_PLATFORM_ANDROID_KHR, display, nullptr); +} + +EGLDisplay eglGetPlatformDisplayImpl(EGLenum platform, void* native_display, + const EGLAttrib* attrib_list) { + return eglGetPlatformDisplayTmpl(platform, static_cast<EGLNativeDisplayType>(native_display), + attrib_list); +} + +// ---------------------------------------------------------------------------- +// Initialization +// ---------------------------------------------------------------------------- + +EGLBoolean eglInitializeImpl(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + egl_display_ptr dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + + EGLBoolean res = dp->initialize(major, minor); + + return res; +} + +EGLBoolean eglTerminateImpl(EGLDisplay dpy) +{ + // NOTE: don't unload the drivers b/c some APIs can be called + // after eglTerminate() has been called. eglTerminate() only + // terminates an EGLDisplay, not a EGL itself. + + egl_display_ptr dp = get_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + + EGLBoolean res = dp->terminate(); + + return res; +} + +// ---------------------------------------------------------------------------- +// configuration +// ---------------------------------------------------------------------------- + +EGLBoolean eglGetConfigsImpl(EGLDisplay dpy, + EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + if (num_config==nullptr) { + return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); + } + + EGLBoolean res = EGL_FALSE; + *num_config = 0; + + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso) { + res = cnx->egl.eglGetConfigs( + dp->disp.dpy, configs, config_size, num_config); + } + + return res; +} + +EGLBoolean eglChooseConfigImpl( EGLDisplay dpy, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, + EGLint *num_config) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + if (num_config==nullptr) { + return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); + } + + EGLBoolean res = EGL_FALSE; + *num_config = 0; + + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso) { + if (attrib_list) { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.egl.force_msaa", value, "false"); + + if (!strcmp(value, "true")) { + size_t attribCount = 0; + EGLint attrib = attrib_list[0]; + + // Only enable MSAA if the context is OpenGL ES 2.0 and + // if no caveat is requested + const EGLint *attribRendererable = nullptr; + const EGLint *attribCaveat = nullptr; + + // Count the number of attributes and look for + // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT + while (attrib != EGL_NONE) { + attrib = attrib_list[attribCount]; + switch (attrib) { + case EGL_RENDERABLE_TYPE: + attribRendererable = &attrib_list[attribCount]; + break; + case EGL_CONFIG_CAVEAT: + attribCaveat = &attrib_list[attribCount]; + break; + default: + break; + } + attribCount++; + } + + if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && + (!attribCaveat || attribCaveat[1] != EGL_NONE)) { + + // Insert 2 extra attributes to force-enable MSAA 4x + EGLint aaAttribs[attribCount + 4]; + aaAttribs[0] = EGL_SAMPLE_BUFFERS; + aaAttribs[1] = 1; + aaAttribs[2] = EGL_SAMPLES; + aaAttribs[3] = 4; + + memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); + + EGLint numConfigAA; + EGLBoolean resAA = cnx->egl.eglChooseConfig( + dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); + + if (resAA == EGL_TRUE && numConfigAA > 0) { + ALOGD("Enabling MSAA 4x"); + *num_config = numConfigAA; + return resAA; + } + } + } + } + + res = cnx->egl.eglChooseConfig( + dp->disp.dpy, attrib_list, configs, config_size, num_config); + } + return res; +} + +EGLBoolean eglGetConfigAttribImpl(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value) +{ + egl_connection_t* cnx = nullptr; + const egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (!dp) return EGL_FALSE; + + return cnx->egl.eglGetConfigAttrib( + dp->disp.dpy, config, attribute, value); +} + +// ---------------------------------------------------------------------------- +// surfaces +// ---------------------------------------------------------------------------- + +// Translates EGL color spaces to Android data spaces. +static android_dataspace dataSpaceFromEGLColorSpace(EGLint colorspace) { + if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { + return HAL_DATASPACE_UNKNOWN; + } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { + return HAL_DATASPACE_V0_SRGB; + } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) { + return HAL_DATASPACE_DISPLAY_P3; + } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) { + return HAL_DATASPACE_DISPLAY_P3_LINEAR; + } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT) { + return HAL_DATASPACE_DISPLAY_P3; + } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) { + return HAL_DATASPACE_V0_SCRGB; + } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) { + return HAL_DATASPACE_V0_SCRGB_LINEAR; + } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) { + return HAL_DATASPACE_BT2020_LINEAR; + } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) { + return HAL_DATASPACE_BT2020_PQ; + } + return HAL_DATASPACE_UNKNOWN; +} + +// Get the colorspace value that should be reported from queries. When the colorspace +// is unknown (no attribute passed), default to reporting LINEAR. +static EGLint getReportedColorSpace(EGLint colorspace) { + return colorspace == EGL_UNKNOWN ? EGL_GL_COLORSPACE_LINEAR_KHR : colorspace; +} + +// Returns a list of color spaces understood by the vendor EGL driver. +static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp) { + std::vector<EGLint> colorSpaces; + + // sRGB and linear are always supported when color space support is present. + colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR); + colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR); + + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT); + } + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_scrgb")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT); + } + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_scrgb_linear")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT); + } + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_linear")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT); + } + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_bt2020_pq")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT); + } + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_linear")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT); + } + if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_passthrough")) { + colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT); + } + return colorSpaces; +} + +// Cleans up color space related parameters that the driver does not understand. +// If there is no color space attribute in attrib_list, colorSpace is left +// unmodified. +template <typename AttrType> +static EGLBoolean processAttributes(egl_display_ptr dp, ANativeWindow* window, + const AttrType* attrib_list, EGLint* colorSpace, + std::vector<AttrType>* strippedAttribList) { + for (const AttrType* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) { + bool copyAttribute = true; + if (attr[0] == EGL_GL_COLORSPACE_KHR) { + switch (attr[1]) { + case EGL_GL_COLORSPACE_LINEAR_KHR: + case EGL_GL_COLORSPACE_SRGB_KHR: + case EGL_GL_COLORSPACE_DISPLAY_P3_EXT: + case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT: + case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT: + case EGL_GL_COLORSPACE_SCRGB_EXT: + case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT: + case EGL_GL_COLORSPACE_BT2020_PQ_EXT: + case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT: + // Fail immediately if the driver doesn't have color space support at all. + if (!dp->hasColorSpaceSupport) return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + break; + default: + // BAD_ATTRIBUTE if attr is not any of the EGL_GL_COLORSPACE_* + return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + *colorSpace = static_cast<EGLint>(attr[1]); + + // Strip the attribute if the driver doesn't understand it. + copyAttribute = false; + std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp); + for (auto driverColorSpace : driverColorSpaces) { + if (static_cast<EGLint>(attr[1]) == driverColorSpace) { + copyAttribute = true; + break; + } + } + + // If the driver doesn't understand it, we should map sRGB-encoded P3 to + // sRGB rather than just dropping the colorspace on the floor. + // For this format, the driver is expected to apply the sRGB + // transfer function during framebuffer operations. + if (!copyAttribute && attr[1] == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) { + strippedAttribList->push_back(attr[0]); + strippedAttribList->push_back(EGL_GL_COLORSPACE_SRGB_KHR); + } + } + if (copyAttribute) { + strippedAttribList->push_back(attr[0]); + strippedAttribList->push_back(attr[1]); + } + } + // Terminate the attribute list. + strippedAttribList->push_back(EGL_NONE); + + // If the passed color space has wide color gamut, check whether the target native window + // supports wide color. + const bool colorSpaceIsNarrow = *colorSpace == EGL_GL_COLORSPACE_SRGB_KHR || + *colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR || *colorSpace == EGL_UNKNOWN; + if (window && !colorSpaceIsNarrow) { + bool windowSupportsWideColor = true; + // Ordinarily we'd put a call to native_window_get_wide_color_support + // at the beginning of the function so that we'll have the + // result when needed elsewhere in the function. + // However, because eglCreateWindowSurface is called by SurfaceFlinger and + // SurfaceFlinger is required to answer the call below we would + // end up in a deadlock situation. By moving the call to only happen + // if the application has specifically asked for wide-color we avoid + // the deadlock with SurfaceFlinger since it will not ask for a + // wide-color surface. + int err = native_window_get_wide_color_support(window, &windowSupportsWideColor); + + if (err) { + ALOGE("processAttributes: invalid window (win=%p) " + "failed (%#x) (already connected to another API?)", + window, err); + return setError(EGL_BAD_NATIVE_WINDOW, EGL_FALSE); + } + if (!windowSupportsWideColor) { + // Application has asked for a wide-color colorspace but + // wide-color support isn't available on the display the window is on. + return setError(EGL_BAD_MATCH, EGL_FALSE); + } + } + return true; +} + +// Note: This only works for existing GLenum's that are all 32bits. +// If you have 64bit attributes (e.g. pointers) you shouldn't be calling this. +void convertAttribs(const EGLAttrib* attribList, std::vector<EGLint>& newList) { + for (const EGLAttrib* attr = attribList; attr && attr[0] != EGL_NONE; attr += 2) { + newList.push_back(static_cast<EGLint>(attr[0])); + newList.push_back(static_cast<EGLint>(attr[1])); + } + newList.push_back(EGL_NONE); +} + +// Gets the native pixel format corrsponding to the passed EGLConfig. +void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, + android_pixel_format* format) { + // Set the native window's buffers format to match what this config requests. + // Whether to use sRGB gamma is not part of the EGLconfig, but is part + // of our native format. So if sRGB gamma is requested, we have to + // modify the EGLconfig's format before setting the native window's + // format. + + EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; + cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType); + + EGLint a = 0; + EGLint r, g, b; + r = g = b = 0; + cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r); + cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g); + cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b); + cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a); + EGLint colorDepth = r + g + b; + + // Today, the driver only understands sRGB and linear on 888X + // formats. Strip other colorspaces from the attribute list and + // only use them to set the dataspace via + // native_window_set_buffers_dataspace + // if pixel format is RGBX 8888 + // TBD: Can test for future extensions that indicate that driver + // handles requested color space and we can let it through. + // allow SRGB and LINEAR. All others need to be stripped. + // else if 565, 4444 + // TBD: Can we assume these are supported if 8888 is? + // else if FP16 or 1010102 + // strip colorspace from attribs. + // endif + if (a == 0) { + if (colorDepth <= 16) { + *format = HAL_PIXEL_FORMAT_RGB_565; + } else { + if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { + if (colorDepth > 24) { + *format = HAL_PIXEL_FORMAT_RGBA_1010102; + } else { + *format = HAL_PIXEL_FORMAT_RGBX_8888; + } + } else { + *format = HAL_PIXEL_FORMAT_RGBA_FP16; + } + } + } else { + if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { + if (colorDepth > 24) { + *format = HAL_PIXEL_FORMAT_RGBA_1010102; + } else { + *format = HAL_PIXEL_FORMAT_RGBA_8888; + } + } else { + *format = HAL_PIXEL_FORMAT_RGBA_FP16; + } + } +} + +EGLBoolean sendSurfaceMetadata(egl_surface_t* s) { + android_smpte2086_metadata smpteMetadata; + if (s->getSmpte2086Metadata(smpteMetadata)) { + int err = + native_window_set_buffers_smpte2086_metadata(s->getNativeWindow(), &smpteMetadata); + s->resetSmpte2086Metadata(); + if (err != 0) { + ALOGE("error setting native window smpte2086 metadata: %s (%d)", strerror(-err), err); + return EGL_FALSE; + } + } + android_cta861_3_metadata cta8613Metadata; + if (s->getCta8613Metadata(cta8613Metadata)) { + int err = + native_window_set_buffers_cta861_3_metadata(s->getNativeWindow(), &cta8613Metadata); + s->resetCta8613Metadata(); + if (err != 0) { + ALOGE("error setting native window CTS 861.3 metadata: %s (%d)", strerror(-err), err); + return EGL_FALSE; + } + } + return EGL_TRUE; +} + +template <typename AttrType, typename CreateFuncType> +EGLSurface eglCreateWindowSurfaceTmpl(egl_display_ptr dp, egl_connection_t* cnx, EGLConfig config, + ANativeWindow* window, const AttrType* attrib_list, + CreateFuncType createWindowSurfaceFunc) { + const AttrType* origAttribList = attrib_list; + + if (!window) { + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + + int value = 0; + window->query(window, NATIVE_WINDOW_IS_VALID, &value); + if (!value) { + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + + // NOTE: When using Vulkan backend, the Vulkan runtime makes all the + // native_window_* calls, so don't do them here. + if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) { + int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); + if (result < 0) { + ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " + "failed (%#x) (already connected to another API?)", + window, result); + return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + } + + EGLDisplay iDpy = dp->disp.dpy; + android_pixel_format format; + getNativePixelFormat(iDpy, cnx, config, &format); + + // now select correct colorspace and dataspace based on user's attribute list + EGLint colorSpace = EGL_UNKNOWN; + std::vector<AttrType> strippedAttribList; + if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) { + ALOGE("error invalid colorspace: %d", colorSpace); + if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) { + native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); + } + return EGL_NO_SURFACE; + } + attrib_list = strippedAttribList.data(); + + if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) { + int err = native_window_set_buffers_format(window, format); + if (err != 0) { + ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err); + native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + + android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace); + // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN. + // HAL_DATASPACE_UNKNOWN is the default value, but it may have changed + // at this point. + err = native_window_set_buffers_data_space(window, dataSpace); + if (err != 0) { + ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err); + native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + } + + // the EGL spec requires that a new EGLSurface default to swap interval + // 1, so explicitly set that on the window here. + window->setSwapInterval(window, 1); + + EGLSurface surface = createWindowSurfaceFunc(iDpy, config, window, attrib_list); + if (surface != EGL_NO_SURFACE) { + egl_surface_t* s = new egl_surface_t(dp.get(), config, window, surface, + getReportedColorSpace(colorSpace), cnx); + return s; + } + + // EGLSurface creation failed + if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) { + native_window_set_buffers_format(window, 0); + native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); + } + return EGL_NO_SURFACE; +} + +typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, + NativeWindowType window, + const EGLint* attrib_list); +typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)( + EGLDisplay dpy, EGLConfig config, void* native_window, const EGLAttrib* attrib_list); + +EGLSurface eglCreateWindowSurfaceImpl(EGLDisplay dpy, EGLConfig config, NativeWindowType window, + const EGLint* attrib_list) { + egl_connection_t* cnx = NULL; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { + return eglCreateWindowSurfaceTmpl< + EGLint, PFNEGLCREATEWINDOWSURFACEPROC>(dp, cnx, config, window, attrib_list, + cnx->egl.eglCreateWindowSurface); + } + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePlatformWindowSurfaceImpl(EGLDisplay dpy, EGLConfig config, void* native_window, + const EGLAttrib* attrib_list) { + egl_connection_t* cnx = NULL; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglCreatePlatformWindowSurface) { + return eglCreateWindowSurfaceTmpl<EGLAttrib, PFNEGLCREATEPLATFORMWINDOWSURFACEPROC>( + dp, cnx, config, static_cast<ANativeWindow*>(native_window), attrib_list, + cnx->egl.eglCreatePlatformWindowSurface); + } + // driver doesn't support native function, return EGL_BAD_DISPLAY + ALOGE("Driver indicates EGL 1.5 support, but does not have " + "eglCreatePlatformWindowSurface"); + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + } + + std::vector<EGLint> convertedAttribs; + convertAttribs(attrib_list, convertedAttribs); + if (cnx->egl.eglCreatePlatformWindowSurfaceEXT) { + return eglCreateWindowSurfaceTmpl<EGLint, PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>( + dp, cnx, config, static_cast<ANativeWindow*>(native_window), + convertedAttribs.data(), cnx->egl.eglCreatePlatformWindowSurfaceEXT); + } else { + return eglCreateWindowSurfaceTmpl< + EGLint, PFNEGLCREATEWINDOWSURFACEPROC>(dp, cnx, config, + static_cast<ANativeWindow*>( + native_window), + convertedAttribs.data(), + cnx->egl.eglCreateWindowSurface); + } + } + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePlatformPixmapSurfaceImpl(EGLDisplay dpy, EGLConfig /*config*/, + void* /*native_pixmap*/, + const EGLAttrib* /*attrib_list*/) { + // Per EGL_KHR_platform_android: + // It is not valid to call eglCreatePlatformPixmapSurface with a <dpy> that + // belongs to the Android platform. Any such call fails and generates + // an EGL_BAD_PARAMETER error. + + egl_connection_t* cnx = NULL; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { + return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePixmapSurfaceImpl(EGLDisplay dpy, EGLConfig /*config*/, + NativePixmapType /*pixmap*/, const EGLint* /*attrib_list*/) { + egl_connection_t* cnx = nullptr; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { + return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePbufferSurfaceImpl(EGLDisplay dpy, EGLConfig config, + const EGLint* attrib_list) { + egl_connection_t* cnx = nullptr; + egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { + EGLDisplay iDpy = dp->disp.dpy; + android_pixel_format format; + getNativePixelFormat(iDpy, cnx, config, &format); + + // Select correct colorspace based on user's attribute list + EGLint colorSpace = EGL_UNKNOWN; + std::vector<EGLint> strippedAttribList; + if (!processAttributes(dp, nullptr, attrib_list, &colorSpace, &strippedAttribList)) { + ALOGE("error invalid colorspace: %d", colorSpace); + return EGL_NO_SURFACE; + } + attrib_list = strippedAttribList.data(); + + EGLSurface surface = cnx->egl.eglCreatePbufferSurface(dp->disp.dpy, config, attrib_list); + if (surface != EGL_NO_SURFACE) { + egl_surface_t* s = new egl_surface_t(dp.get(), config, nullptr, surface, + getReportedColorSpace(colorSpace), cnx); + return s; + } + } + return EGL_NO_SURFACE; +} + +EGLBoolean eglDestroySurfaceImpl(EGLDisplay dpy, EGLSurface surface) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t* const s = get_surface(surface); + EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); + if (result == EGL_TRUE) { + _s.terminate(); + } + return result; +} + +EGLBoolean eglQuerySurfaceImpl(EGLDisplay dpy, EGLSurface surface, EGLint attribute, + EGLint* value) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t const* const s = get_surface(surface); + if (s->getColorSpaceAttribute(attribute, value)) { + return EGL_TRUE; + } else if (s->getSmpte2086Attribute(attribute, value)) { + return EGL_TRUE; + } else if (s->getCta8613Attribute(attribute, value)) { + return EGL_TRUE; + } + return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value); +} + +void EGLAPI eglBeginFrameImpl(EGLDisplay dpy, EGLSurface surface) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return; + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + setError(EGL_BAD_SURFACE, EGL_FALSE); + } +} + +// ---------------------------------------------------------------------------- +// Contexts +// ---------------------------------------------------------------------------- + +EGLContext eglCreateContextImpl(EGLDisplay dpy, EGLConfig config, + EGLContext share_list, const EGLint *attrib_list) +{ + egl_connection_t* cnx = nullptr; + const egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (dp) { + if (share_list != EGL_NO_CONTEXT) { + if (!ContextRef(dp.get(), share_list).get()) { + return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); + } + egl_context_t* const c = get_context(share_list); + share_list = c->context; + } + // b/111083885 - If we are presenting EGL 1.4 interface to apps + // error out on robust access attributes that are invalid + // in EGL 1.4 as the driver may be fine with them but dEQP expects + // tests to fail according to spec. + if (attrib_list && (cnx->driverVersion < EGL_MAKE_VERSION(1, 5, 0))) { + const EGLint* attrib_ptr = attrib_list; + while (*attrib_ptr != EGL_NONE) { + GLint attr = *attrib_ptr++; + GLint value = *attrib_ptr++; + if (attr == EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR) { + // We are GL ES context with EGL 1.4, this is an invalid + // attribute + return setError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + } + }; + } + EGLContext context = cnx->egl.eglCreateContext( + dp->disp.dpy, config, share_list, attrib_list); + if (context != EGL_NO_CONTEXT) { + // figure out if it's a GLESv1 or GLESv2 + int version = 0; + if (attrib_list) { + while (*attrib_list != EGL_NONE) { + GLint attr = *attrib_list++; + GLint value = *attrib_list++; + if (attr == EGL_CONTEXT_CLIENT_VERSION) { + if (value == 1) { + version = egl_connection_t::GLESv1_INDEX; + } else if (value == 2 || value == 3) { + version = egl_connection_t::GLESv2_INDEX; + } + } + }; + } + egl_context_t* c = new egl_context_t(dpy, context, config, cnx, + version); + return c; + } + } + return EGL_NO_CONTEXT; +} + +EGLBoolean eglDestroyContextImpl(EGLDisplay dpy, EGLContext ctx) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) + return EGL_FALSE; + + ContextRef _c(dp.get(), ctx); + if (!_c.get()) + return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); + + egl_context_t * const c = get_context(ctx); + EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); + if (result == EGL_TRUE) { + _c.terminate(); + } + return result; +} + +EGLBoolean eglMakeCurrentImpl( EGLDisplay dpy, EGLSurface draw, + EGLSurface read, EGLContext ctx) +{ + egl_display_ptr dp = validate_display(dpy); + if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + + // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not + // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is + // a valid but uninitialized display. + if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || + (draw != EGL_NO_SURFACE) ) { + if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); + } + + // get a reference to the object passed in + ContextRef _c(dp.get(), ctx); + SurfaceRef _d(dp.get(), draw); + SurfaceRef _r(dp.get(), read); + + // validate the context (if not EGL_NO_CONTEXT) + if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { + // EGL_NO_CONTEXT is valid + return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); + } + + // these are the underlying implementation's object + EGLContext impl_ctx = EGL_NO_CONTEXT; + EGLSurface impl_draw = EGL_NO_SURFACE; + EGLSurface impl_read = EGL_NO_SURFACE; + + // these are our objects structs passed in + egl_context_t * c = nullptr; + egl_surface_t const * d = nullptr; + egl_surface_t const * r = nullptr; + + // these are the current objects structs + egl_context_t * cur_c = get_context(getContext()); + + if (ctx != EGL_NO_CONTEXT) { + c = get_context(ctx); + impl_ctx = c->context; + } else { + // no context given, use the implementation of the current context + if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { + // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); + return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE); + } + if (cur_c == nullptr) { + // no current context + // not an error, there is just no current context. + return EGL_TRUE; + } + } + + // retrieve the underlying implementation's draw EGLSurface + if (draw != EGL_NO_SURFACE) { + if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + d = get_surface(draw); + impl_draw = d->surface; + } + + // retrieve the underlying implementation's read EGLSurface + if (read != EGL_NO_SURFACE) { + if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + r = get_surface(read); + impl_read = r->surface; + } + + + EGLBoolean result = dp->makeCurrent(c, cur_c, + draw, read, ctx, + impl_draw, impl_read, impl_ctx); + + if (result == EGL_TRUE) { + if (c) { + setGLHooksThreadSpecific(c->cnx->hooks[c->version]); + egl_tls_t::setContext(ctx); + _c.acquire(); + _r.acquire(); + _d.acquire(); + } else { + setGLHooksThreadSpecific(&gHooksNoContext); + egl_tls_t::setContext(EGL_NO_CONTEXT); + } + } else { + // this will ALOGE the error + egl_connection_t* const cnx = &gEGLImpl; + result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE); + } + return result; +} + +EGLBoolean eglQueryContextImpl( EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint *value) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + ContextRef _c(dp.get(), ctx); + if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); + + egl_context_t * const c = get_context(ctx); + return c->cnx->egl.eglQueryContext( + dp->disp.dpy, c->context, attribute, value); + +} + +EGLContext eglGetCurrentContextImpl(void) +{ + // could be called before eglInitialize(), but we wouldn't have a context + // then, and this function would correctly return EGL_NO_CONTEXT. + EGLContext ctx = getContext(); + return ctx; +} + +EGLSurface eglGetCurrentSurfaceImpl(EGLint readdraw) +{ + // could be called before eglInitialize(), but we wouldn't have a context + // then, and this function would correctly return EGL_NO_SURFACE. + + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); + switch (readdraw) { + case EGL_READ: return c->read; + case EGL_DRAW: return c->draw; + default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + } + return EGL_NO_SURFACE; +} + +EGLDisplay eglGetCurrentDisplayImpl(void) +{ + // could be called before eglInitialize(), but we wouldn't have a context + // then, and this function would correctly return EGL_NO_DISPLAY. + + EGLContext ctx = getContext(); + if (ctx) { + egl_context_t const * const c = get_context(ctx); + if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); + return c->dpy; + } + return EGL_NO_DISPLAY; +} + +EGLBoolean eglWaitGLImpl(void) +{ + egl_connection_t* const cnx = &gEGLImpl; + if (!cnx->dso) + return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); + + return cnx->egl.eglWaitGL(); +} + +EGLBoolean eglWaitNativeImpl(EGLint engine) +{ + egl_connection_t* const cnx = &gEGLImpl; + if (!cnx->dso) + return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); + + return cnx->egl.eglWaitNative(engine); +} + +EGLint eglGetErrorImpl(void) +{ + EGLint err = EGL_SUCCESS; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso) { + err = cnx->egl.eglGetError(); + } + if (err == EGL_SUCCESS) { + err = egl_tls_t::getError(); + } + return err; +} + +static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( + const char* procname) { + const egl_connection_t* cnx = &gEGLImpl; + void* proc = nullptr; + + proc = dlsym(cnx->libEgl, procname); + if (proc) return (__eglMustCastToProperFunctionPointerType)proc; + + proc = dlsym(cnx->libGles2, procname); + if (proc) return (__eglMustCastToProperFunctionPointerType)proc; + + proc = dlsym(cnx->libGles1, procname); + if (proc) return (__eglMustCastToProperFunctionPointerType)proc; + + return nullptr; +} + +__eglMustCastToProperFunctionPointerType eglGetProcAddressImpl(const char *procname) +{ + if (FILTER_EXTENSIONS(procname)) { + return nullptr; + } + + __eglMustCastToProperFunctionPointerType addr; + addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); + if (addr) return addr; + + addr = findBuiltinWrapper(procname); + if (addr) return addr; + + // this protects accesses to sGLExtentionMap and sGLExtentionSlot + pthread_mutex_lock(&sExtensionMapMutex); + + /* + * Since eglGetProcAddress() is not associated to anything, it needs + * to return a function pointer that "works" regardless of what + * the current context is. + * + * For this reason, we return a "forwarder", a small stub that takes + * care of calling the function associated with the context + * currently bound. + * + * We first look for extensions we've already resolved, if we're seeing + * this extension for the first time, we go through all our + * implementations and call eglGetProcAddress() and record the + * result in the appropriate implementation hooks and return the + * address of the forwarder corresponding to that hook set. + * + */ + + const std::string name(procname); + + auto& extentionMap = sGLExtentionMap; + auto pos = extentionMap.find(name); + addr = (pos != extentionMap.end()) ? pos->second : nullptr; + const int slot = sGLExtentionSlot; + + ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, + "no more slots for eglGetProcAddress(\"%s\")", + procname); + + egl_connection_t* const cnx = &gEGLImpl; + LayerLoader& layer_loader(LayerLoader::getInstance()); + + if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { + + if (cnx->dso && cnx->egl.eglGetProcAddress) { + + // Extensions are independent of the bound context + addr = cnx->egl.eglGetProcAddress(procname); + if (addr) { + + // purposefully track the bottom of the stack in extensionMap + extentionMap[name] = addr; + + // Apply layers + addr = layer_loader.ApplyLayers(procname, addr); + + // Track the top most entry point + cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = + cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr; + addr = gExtensionForwarders[slot]; + sGLExtentionSlot++; + } + } + + } else if (slot < MAX_NUMBER_OF_GL_EXTENSIONS) { + + // We've seen this func before, but we tracked the bottom, so re-apply layers + // More layers might have been enabled + addr = layer_loader.ApplyLayers(procname, addr); + + // Track the top most entry point + cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = + cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr; + addr = gExtensionForwarders[slot]; + } + + pthread_mutex_unlock(&sExtensionMapMutex); + return addr; +} + +class FrameCompletionThread { +public: + + static void queueSync(EGLSyncKHR sync) { + static FrameCompletionThread thread; + + char name[64]; + + std::lock_guard<std::mutex> lock(thread.mMutex); + snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued); + ATRACE_NAME(name); + + thread.mQueue.push_back(sync); + thread.mCondition.notify_one(); + thread.mFramesQueued++; + ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size())); + } + +private: + + FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) { + std::thread thread(&FrameCompletionThread::loop, this); + thread.detach(); + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-noreturn" + void loop() { + while (true) { + threadLoop(); + } + } +#pragma clang diagnostic pop + + void threadLoop() { + EGLSyncKHR sync; + uint32_t frameNum; + { + std::unique_lock<std::mutex> lock(mMutex); + while (mQueue.empty()) { + mCondition.wait(lock); + } + sync = mQueue[0]; + frameNum = mFramesCompleted; + } + EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + { + char name[64]; + snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum); + ATRACE_NAME(name); + + EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); + if (result == EGL_FALSE) { + ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); + } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { + ALOGE("FrameCompletion: timeout waiting for fence"); + } + eglDestroySyncKHR(dpy, sync); + } + { + std::lock_guard<std::mutex> lock(mMutex); + mQueue.pop_front(); + mFramesCompleted++; + ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size())); + } + } + + uint32_t mFramesQueued; + uint32_t mFramesCompleted; + std::deque<EGLSyncKHR> mQueue; + std::condition_variable mCondition; + std::mutex mMutex; +}; + +EGLBoolean eglSwapBuffersWithDamageKHRImpl(EGLDisplay dpy, EGLSurface draw, + EGLint *rects, EGLint n_rects) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), draw); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t* const s = get_surface(draw); + + if (CC_UNLIKELY(dp->traceGpuCompletion)) { + EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr); + if (sync != EGL_NO_SYNC_KHR) { + FrameCompletionThread::queueSync(sync); + } + } + + if (CC_UNLIKELY(dp->finishOnSwap)) { + uint32_t pixel; + egl_context_t * const c = get_context( egl_tls_t::getContext() ); + if (c) { + // glReadPixels() ensures that the frame is complete + s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, + GL_RGBA,GL_UNSIGNED_BYTE,&pixel); + } + } + + if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) { + if (!sendSurfaceMetadata(s)) { + native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL); + return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE); + } + } + + if (n_rects == 0) { + return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); + } + + std::vector<android_native_rect_t> androidRects((size_t)n_rects); + for (int r = 0; r < n_rects; ++r) { + int offset = r * 4; + int x = rects[offset]; + int y = rects[offset + 1]; + int width = rects[offset + 2]; + int height = rects[offset + 3]; + android_native_rect_t androidRect; + androidRect.left = x; + androidRect.top = y + height; + androidRect.right = x + width; + androidRect.bottom = y; + androidRects.push_back(androidRect); + } + if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) { + native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), + androidRects.size()); + } + + if (s->cnx->egl.eglSwapBuffersWithDamageKHR) { + return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface, + rects, n_rects); + } else { + return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); + } +} + +EGLBoolean eglSwapBuffersImpl(EGLDisplay dpy, EGLSurface surface) +{ + return eglSwapBuffersWithDamageKHRImpl(dpy, surface, nullptr, 0); +} + +EGLBoolean eglCopyBuffersImpl( EGLDisplay dpy, EGLSurface surface, + NativePixmapType target) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t const * const s = get_surface(surface); + return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); +} + +const char* eglQueryStringImpl(EGLDisplay dpy, EGLint name) +{ + if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { + // Return list of client extensions + return gClientExtensionString; + } + + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return (const char *) nullptr; + + switch (name) { + case EGL_VENDOR: + return dp->getVendorString(); + case EGL_VERSION: + return dp->getVersionString(); + case EGL_EXTENSIONS: + return dp->getExtensionString(); + case EGL_CLIENT_APIS: + return dp->getClientApiString(); + default: + break; + } + return setError(EGL_BAD_PARAMETER, (const char *)nullptr); +} + +EGLAPI const char* eglQueryStringImplementationANDROIDImpl(EGLDisplay dpy, EGLint name) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return (const char *) nullptr; + + switch (name) { + case EGL_VENDOR: + return dp->disp.queryString.vendor; + case EGL_VERSION: + return dp->disp.queryString.version; + case EGL_EXTENSIONS: + return dp->disp.queryString.extensions; + case EGL_CLIENT_APIS: + return dp->disp.queryString.clientApi; + default: + break; + } + return setError(EGL_BAD_PARAMETER, (const char *)nullptr); +} + +// ---------------------------------------------------------------------------- +// EGL 1.1 +// ---------------------------------------------------------------------------- + +EGLBoolean eglSurfaceAttribImpl( + EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t * const s = get_surface(surface); + + if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) { + if (!s->getNativeWindow()) { + setError(EGL_BAD_SURFACE, EGL_FALSE); + } + int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0); + return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + if (attribute == EGL_TIMESTAMPS_ANDROID) { + if (!s->getNativeWindow()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0); + return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + if (s->setSmpte2086Attribute(attribute, value)) { + return EGL_TRUE; + } else if (s->setCta8613Attribute(attribute, value)) { + return EGL_TRUE; + } else if (s->cnx->egl.eglSurfaceAttrib) { + return s->cnx->egl.eglSurfaceAttrib( + dp->disp.dpy, s->surface, attribute, value); + } + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +} + +EGLBoolean eglBindTexImageImpl( + EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->egl.eglBindTexImage) { + return s->cnx->egl.eglBindTexImage( + dp->disp.dpy, s->surface, buffer); + } + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +} + +EGLBoolean eglReleaseTexImageImpl( + EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->egl.eglReleaseTexImage) { + return s->cnx->egl.eglReleaseTexImage( + dp->disp.dpy, s->surface, buffer); + } + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); +} + +EGLBoolean eglSwapIntervalImpl(EGLDisplay dpy, EGLint interval) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean res = EGL_TRUE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglSwapInterval) { + res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); + } + + return res; +} + + +// ---------------------------------------------------------------------------- +// EGL 1.2 +// ---------------------------------------------------------------------------- + +EGLBoolean eglWaitClientImpl(void) +{ + egl_connection_t* const cnx = &gEGLImpl; + if (!cnx->dso) + return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); + + EGLBoolean res; + if (cnx->egl.eglWaitClient) { + res = cnx->egl.eglWaitClient(); + } else { + res = cnx->egl.eglWaitGL(); + } + return res; +} + +EGLBoolean eglBindAPIImpl(EGLenum api) +{ + // bind this API on all EGLs + EGLBoolean res = EGL_TRUE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglBindAPI) { + res = cnx->egl.eglBindAPI(api); + } + return res; +} + +EGLenum eglQueryAPIImpl(void) +{ + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglQueryAPI) { + return cnx->egl.eglQueryAPI(); + } + + // or, it can only be OpenGL ES + return EGL_OPENGL_ES_API; +} + +EGLBoolean eglReleaseThreadImpl(void) +{ + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglReleaseThread) { + cnx->egl.eglReleaseThread(); + } + + // If there is context bound to the thread, release it + egl_display_t::loseCurrent(get_context(getContext())); + + egl_tls_t::clearTLS(); + return EGL_TRUE; +} + +EGLSurface eglCreatePbufferFromClientBufferImpl( + EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint *attrib_list) +{ + egl_connection_t* cnx = nullptr; + const egl_display_ptr dp = validate_display_connection(dpy, cnx); + if (!dp) return EGL_FALSE; + if (cnx->egl.eglCreatePbufferFromClientBuffer) { + return cnx->egl.eglCreatePbufferFromClientBuffer( + dp->disp.dpy, buftype, buffer, config, attrib_list); + } + return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); +} + +// ---------------------------------------------------------------------------- +// EGL_EGLEXT_VERSION 3 +// ---------------------------------------------------------------------------- + +EGLBoolean eglLockSurfaceKHRImpl(EGLDisplay dpy, EGLSurface surface, + const EGLint *attrib_list) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->egl.eglLockSurfaceKHR) { + return s->cnx->egl.eglLockSurfaceKHR( + dp->disp.dpy, s->surface, attrib_list); + } + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); +} + +EGLBoolean eglUnlockSurfaceKHRImpl(EGLDisplay dpy, EGLSurface surface) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->egl.eglUnlockSurfaceKHR) { + return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); + } + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); +} + +// Note: EGLImageKHR and EGLImage are the same thing so no need +// to templatize that. +template <typename AttrType, typename FuncType> +EGLImageKHR eglCreateImageTmpl(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const AttrType* attrib_list, + FuncType eglCreateImageFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_IMAGE_KHR; + + ContextRef _c(dp.get(), ctx); + egl_context_t* const c = _c.get(); + + EGLImageKHR result = EGL_NO_IMAGE_KHR; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && eglCreateImageFunc) { + result = eglCreateImageFunc(dp->disp.dpy, c ? c->context : EGL_NO_CONTEXT, target, buffer, + attrib_list); + } + return result; +} + +typedef EGLImage(EGLAPIENTRYP PFNEGLCREATEIMAGE)(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, + const EGLAttrib* attrib_list); + +EGLImageKHR eglCreateImageKHRImpl(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint* attrib_list) { + return eglCreateImageTmpl<EGLint, PFNEGLCREATEIMAGEKHRPROC>(dpy, ctx, target, buffer, + attrib_list, + gEGLImpl.egl.eglCreateImageKHR); +} + +EGLImage eglCreateImageImpl(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, + const EGLAttrib* attrib_list) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglCreateImage) { + return eglCreateImageTmpl<EGLAttrib, PFNEGLCREATEIMAGE>(dpy, ctx, target, buffer, + attrib_list, + cnx->egl.eglCreateImage); + } + // driver doesn't support native function, return EGL_BAD_DISPLAY + ALOGE("Driver indicates EGL 1.5 support, but does not have eglCreateImage"); + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE); + } + + std::vector<EGLint> convertedAttribs; + convertAttribs(attrib_list, convertedAttribs); + return eglCreateImageTmpl<EGLint, PFNEGLCREATEIMAGEKHRPROC>(dpy, ctx, target, buffer, + convertedAttribs.data(), + gEGLImpl.egl.eglCreateImageKHR); +} + +EGLBoolean eglDestroyImageTmpl(EGLDisplay dpy, EGLImageKHR img, + PFNEGLDESTROYIMAGEKHRPROC destroyImageFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && destroyImageFunc) { + result = destroyImageFunc(dp->disp.dpy, img); + } + return result; +} + +EGLBoolean eglDestroyImageKHRImpl(EGLDisplay dpy, EGLImageKHR img) { + return eglDestroyImageTmpl(dpy, img, gEGLImpl.egl.eglDestroyImageKHR); +} + +EGLBoolean eglDestroyImageImpl(EGLDisplay dpy, EGLImageKHR img) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglDestroyImage) { + return eglDestroyImageTmpl(dpy, img, gEGLImpl.egl.eglDestroyImage); + } + // driver doesn't support native function, return EGL_BAD_DISPLAY + ALOGE("Driver indicates EGL 1.5 support, but does not have eglDestroyImage"); + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + return eglDestroyImageTmpl(dpy, img, gEGLImpl.egl.eglDestroyImageKHR); +} + +// ---------------------------------------------------------------------------- +// EGL_EGLEXT_VERSION 5 +// ---------------------------------------------------------------------------- + +// NOTE: EGLSyncKHR and EGLSync are identical, no need to templatize +template <typename AttrType, typename FuncType> +EGLSyncKHR eglCreateSyncTmpl(EGLDisplay dpy, EGLenum type, const AttrType* attrib_list, + FuncType eglCreateSyncFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_SYNC_KHR; + + egl_connection_t* const cnx = &gEGLImpl; + EGLSyncKHR result = EGL_NO_SYNC_KHR; + if (cnx->dso && eglCreateSyncFunc) { + result = eglCreateSyncFunc(dp->disp.dpy, type, attrib_list); + } + return result; +} + +typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATESYNC)(EGLDisplay dpy, EGLenum type, + const EGLAttrib* attrib_list); + +EGLSyncKHR eglCreateSyncKHRImpl(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) { + return eglCreateSyncTmpl<EGLint, PFNEGLCREATESYNCKHRPROC>(dpy, type, attrib_list, + gEGLImpl.egl.eglCreateSyncKHR); +} + +EGLSync eglCreateSyncImpl(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglCreateSync) { + return eglCreateSyncTmpl<EGLAttrib, PFNEGLCREATESYNC>(dpy, type, attrib_list, + cnx->egl.eglCreateSync); + } + // driver doesn't support native function, return EGL_BAD_DISPLAY + ALOGE("Driver indicates EGL 1.5 support, but does not have eglCreateSync"); + return setError(EGL_BAD_DISPLAY, EGL_NO_SYNC); + } + + std::vector<EGLint> convertedAttribs; + convertAttribs(attrib_list, convertedAttribs); + return eglCreateSyncTmpl<EGLint, PFNEGLCREATESYNCKHRPROC>(dpy, type, convertedAttribs.data(), + cnx->egl.eglCreateSyncKHR); +} + +EGLBoolean eglDestroySyncTmpl(EGLDisplay dpy, EGLSyncKHR sync, + PFNEGLDESTROYSYNCKHRPROC eglDestroySyncFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && eglDestroySyncFunc) { + result = eglDestroySyncFunc(dp->disp.dpy, sync); + } + return result; +} + +EGLBoolean eglDestroySyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync) { + return eglDestroySyncTmpl(dpy, sync, gEGLImpl.egl.eglDestroySyncKHR); +} + +EGLBoolean eglDestroySyncImpl(EGLDisplay dpy, EGLSyncKHR sync) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglDestroySync) { + return eglDestroySyncTmpl(dpy, sync, cnx->egl.eglDestroySync); + } + ALOGE("Driver indicates EGL 1.5 support, but does not have eglDestroySync"); + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + return eglDestroySyncTmpl(dpy, sync, cnx->egl.eglDestroySyncKHR); +} + +EGLBoolean eglSignalSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && gEGLImpl.egl.eglSignalSyncKHR) { + result = gEGLImpl.egl.eglSignalSyncKHR(dp->disp.dpy, sync, mode); + } + return result; +} + +EGLint eglClientWaitSyncTmpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout, + PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLint result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && eglClientWaitSyncFunc) { + result = eglClientWaitSyncFunc(dp->disp.dpy, sync, flags, timeout); + } + return result; +} + +EGLint eglClientWaitSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) { + egl_connection_t* const cnx = &gEGLImpl; + return eglClientWaitSyncTmpl(dpy, sync, flags, timeout, cnx->egl.eglClientWaitSyncKHR); +} + +EGLint eglClientWaitSyncImpl(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTimeKHR timeout) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglClientWaitSync) { + return eglClientWaitSyncTmpl(dpy, sync, flags, timeout, cnx->egl.eglClientWaitSync); + } + ALOGE("Driver indicates EGL 1.5 support, but does not have eglClientWaitSync"); + return setError(EGL_BAD_DISPLAY, (EGLint)EGL_FALSE); + } + + return eglClientWaitSyncTmpl(dpy, sync, flags, timeout, cnx->egl.eglClientWaitSyncKHR); +} + +template <typename AttrType, typename FuncType> +EGLBoolean eglGetSyncAttribTmpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, AttrType* value, + FuncType eglGetSyncAttribFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && eglGetSyncAttribFunc) { + result = eglGetSyncAttribFunc(dp->disp.dpy, sync, attribute, value); + } + return result; +} + +typedef EGLBoolean(EGLAPIENTRYP PFNEGLGETSYNCATTRIB)(EGLDisplay dpy, EGLSync sync, EGLint attribute, + EGLAttrib* value); + +EGLBoolean eglGetSyncAttribImpl(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglGetSyncAttrib) { + return eglGetSyncAttribTmpl<EGLAttrib, PFNEGLGETSYNCATTRIB>(dpy, sync, attribute, value, + cnx->egl.eglGetSyncAttrib); + } + ALOGE("Driver indicates EGL 1.5 support, but does not have eglGetSyncAttrib"); + return setError(EGL_BAD_DISPLAY, (EGLint)EGL_FALSE); + } + + // Fallback to KHR, ask for EGLint attribute and cast back to EGLAttrib + EGLint attribValue; + EGLBoolean ret = + eglGetSyncAttribTmpl<EGLint, PFNEGLGETSYNCATTRIBKHRPROC>(dpy, sync, attribute, + &attribValue, + gEGLImpl.egl + .eglGetSyncAttribKHR); + if (ret) { + *value = static_cast<EGLAttrib>(attribValue); + } + return ret; +} + +EGLBoolean eglGetSyncAttribKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, + EGLint* value) { + return eglGetSyncAttribTmpl<EGLint, PFNEGLGETSYNCATTRIBKHRPROC>(dpy, sync, attribute, value, + gEGLImpl.egl + .eglGetSyncAttribKHR); +} + +EGLStreamKHR eglCreateStreamKHRImpl(EGLDisplay dpy, const EGLint *attrib_list) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_STREAM_KHR; + + EGLStreamKHR result = EGL_NO_STREAM_KHR; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglCreateStreamKHR) { + result = cnx->egl.eglCreateStreamKHR( + dp->disp.dpy, attrib_list); + } + return result; +} + +EGLBoolean eglDestroyStreamKHRImpl(EGLDisplay dpy, EGLStreamKHR stream) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglDestroyStreamKHR) { + result = cnx->egl.eglDestroyStreamKHR( + dp->disp.dpy, stream); + } + return result; +} + +EGLBoolean eglStreamAttribKHRImpl(EGLDisplay dpy, EGLStreamKHR stream, + EGLenum attribute, EGLint value) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglStreamAttribKHR) { + result = cnx->egl.eglStreamAttribKHR( + dp->disp.dpy, stream, attribute, value); + } + return result; +} + +EGLBoolean eglQueryStreamKHRImpl(EGLDisplay dpy, EGLStreamKHR stream, + EGLenum attribute, EGLint *value) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglQueryStreamKHR) { + result = cnx->egl.eglQueryStreamKHR( + dp->disp.dpy, stream, attribute, value); + } + return result; +} + +EGLBoolean eglQueryStreamu64KHRImpl(EGLDisplay dpy, EGLStreamKHR stream, + EGLenum attribute, EGLuint64KHR *value) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) { + result = cnx->egl.eglQueryStreamu64KHR( + dp->disp.dpy, stream, attribute, value); + } + return result; +} + +EGLBoolean eglQueryStreamTimeKHRImpl(EGLDisplay dpy, EGLStreamKHR stream, + EGLenum attribute, EGLTimeKHR *value) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) { + result = cnx->egl.eglQueryStreamTimeKHR( + dp->disp.dpy, stream, attribute, value); + } + return result; +} + +EGLSurface eglCreateStreamProducerSurfaceKHRImpl(EGLDisplay dpy, EGLConfig config, + EGLStreamKHR stream, const EGLint *attrib_list) +{ + egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_SURFACE; + + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) { + EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR( + dp->disp.dpy, config, stream, attrib_list); + if (surface != EGL_NO_SURFACE) { + egl_surface_t* s = new egl_surface_t(dp.get(), config, nullptr, surface, + EGL_GL_COLORSPACE_LINEAR_KHR, cnx); + return s; + } + } + return EGL_NO_SURFACE; +} + +EGLBoolean eglStreamConsumerGLTextureExternalKHRImpl(EGLDisplay dpy, + EGLStreamKHR stream) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) { + result = cnx->egl.eglStreamConsumerGLTextureExternalKHR( + dp->disp.dpy, stream); + } + return result; +} + +EGLBoolean eglStreamConsumerAcquireKHRImpl(EGLDisplay dpy, + EGLStreamKHR stream) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) { + result = cnx->egl.eglStreamConsumerAcquireKHR( + dp->disp.dpy, stream); + } + return result; +} + +EGLBoolean eglStreamConsumerReleaseKHRImpl(EGLDisplay dpy, + EGLStreamKHR stream) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + + EGLBoolean result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) { + result = cnx->egl.eglStreamConsumerReleaseKHR( + dp->disp.dpy, stream); + } + return result; +} + +EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHRImpl( + EGLDisplay dpy, EGLStreamKHR stream) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR; + + EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) { + result = cnx->egl.eglGetStreamFileDescriptorKHR( + dp->disp.dpy, stream); + } + return result; +} + +EGLStreamKHR eglCreateStreamFromFileDescriptorKHRImpl( + EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_STREAM_KHR; + + EGLStreamKHR result = EGL_NO_STREAM_KHR; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) { + result = cnx->egl.eglCreateStreamFromFileDescriptorKHR( + dp->disp.dpy, file_descriptor); + } + return result; +} + +// ---------------------------------------------------------------------------- +// EGL_EGLEXT_VERSION 15 +// ---------------------------------------------------------------------------- + +// Need to template function type because return type is different +template <typename ReturnType, typename FuncType> +ReturnType eglWaitSyncTmpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, + FuncType eglWaitSyncFunc) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_FALSE; + ReturnType result = EGL_FALSE; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && eglWaitSyncFunc) { + result = eglWaitSyncFunc(dp->disp.dpy, sync, flags); + } + return result; +} + +typedef EGLBoolean(EGLAPIENTRYP PFNEGLWAITSYNC)(EGLDisplay dpy, EGLSync sync, EGLint flags); + +EGLint eglWaitSyncKHRImpl(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { + egl_connection_t* const cnx = &gEGLImpl; + return eglWaitSyncTmpl<EGLint, PFNEGLWAITSYNCKHRPROC>(dpy, sync, flags, + cnx->egl.eglWaitSyncKHR); +} + +EGLBoolean eglWaitSyncImpl(EGLDisplay dpy, EGLSync sync, EGLint flags) { + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->driverVersion >= EGL_MAKE_VERSION(1, 5, 0)) { + if (cnx->egl.eglWaitSync) { + return eglWaitSyncTmpl<EGLBoolean, PFNEGLWAITSYNC>(dpy, sync, flags, + cnx->egl.eglWaitSync); + } + return setError(EGL_BAD_DISPLAY, (EGLint)EGL_FALSE); + } + + return static_cast<EGLBoolean>( + eglWaitSyncTmpl<EGLint, PFNEGLWAITSYNCKHRPROC>(dpy, sync, flags, + cnx->egl.eglWaitSyncKHR)); +} + +// ---------------------------------------------------------------------------- +// ANDROID extensions +// ---------------------------------------------------------------------------- + +EGLint eglDupNativeFenceFDANDROIDImpl(EGLDisplay dpy, EGLSyncKHR sync) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; + + EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; + egl_connection_t* const cnx = &gEGLImpl; + if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { + result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); + } + return result; +} + +EGLBoolean eglPresentationTimeANDROIDImpl(EGLDisplay dpy, EGLSurface surface, + EGLnsecsANDROID time) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return EGL_FALSE; + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + setError(EGL_BAD_SURFACE, EGL_FALSE); + return EGL_FALSE; + } + + egl_surface_t const * const s = get_surface(surface); + native_window_set_buffers_timestamp(s->getNativeWindow(), time); + + return EGL_TRUE; +} + +EGLClientBuffer eglGetNativeClientBufferANDROIDImpl(const AHardwareBuffer *buffer) { + // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus + // this function cannot be implemented when this libEGL is built for + // vendors. +#ifndef __ANDROID_VNDK__ + if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer) nullptr); + return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer)); +#else + return setError(EGL_BAD_PARAMETER, (EGLClientBuffer) nullptr); +#endif +} + +// ---------------------------------------------------------------------------- +// NVIDIA extensions +// ---------------------------------------------------------------------------- +EGLuint64NV eglGetSystemTimeFrequencyNVImpl() +{ + EGLuint64NV ret = 0; + egl_connection_t* const cnx = &gEGLImpl; + + if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { + return cnx->egl.eglGetSystemTimeFrequencyNV(); + } + + return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0); +} + +EGLuint64NV eglGetSystemTimeNVImpl() +{ + EGLuint64NV ret = 0; + egl_connection_t* const cnx = &gEGLImpl; + + if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { + return cnx->egl.eglGetSystemTimeNV(); + } + + return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0); +} + +// ---------------------------------------------------------------------------- +// Partial update extension +// ---------------------------------------------------------------------------- +EGLBoolean eglSetDamageRegionKHRImpl(EGLDisplay dpy, EGLSurface surface, + EGLint *rects, EGLint n_rects) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + setError(EGL_BAD_DISPLAY, EGL_FALSE); + return EGL_FALSE; + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + setError(EGL_BAD_SURFACE, EGL_FALSE); + return EGL_FALSE; + } + + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->egl.eglSetDamageRegionKHR) { + return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface, + rects, n_rects); + } + + return EGL_FALSE; +} + +EGLBoolean eglGetNextFrameIdANDROIDImpl(EGLDisplay dpy, EGLSurface surface, + EGLuint64KHR *frameId) { + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + if (!s->getNativeWindow()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + uint64_t nextFrameId = 0; + int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId); + + if (ret != 0) { + // This should not happen. Return an error that is not in the spec + // so it's obvious something is very wrong. + ALOGE("eglGetNextFrameId: Unexpected error."); + return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); + } + + *frameId = nextFrameId; + return EGL_TRUE; +} + +EGLBoolean eglGetCompositorTimingANDROIDImpl(EGLDisplay dpy, EGLSurface surface, + EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + if (!s->getNativeWindow()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + nsecs_t* compositeDeadline = nullptr; + nsecs_t* compositeInterval = nullptr; + nsecs_t* compositeToPresentLatency = nullptr; + + for (int i = 0; i < numTimestamps; i++) { + switch (names[i]) { + case EGL_COMPOSITE_DEADLINE_ANDROID: + compositeDeadline = &values[i]; + break; + case EGL_COMPOSITE_INTERVAL_ANDROID: + compositeInterval = &values[i]; + break; + case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: + compositeToPresentLatency = &values[i]; + break; + default: + return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); + } + } + + int ret = native_window_get_compositor_timing(s->getNativeWindow(), + compositeDeadline, compositeInterval, compositeToPresentLatency); + + switch (ret) { + case 0: + return EGL_TRUE; + case -ENOSYS: + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + default: + // This should not happen. Return an error that is not in the spec + // so it's obvious something is very wrong. + ALOGE("eglGetCompositorTiming: Unexpected error."); + return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); + } +} + +EGLBoolean eglGetCompositorTimingSupportedANDROIDImpl( + EGLDisplay dpy, EGLSurface surface, EGLint name) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + ANativeWindow* window = s->getNativeWindow(); + if (!window) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + switch (name) { + case EGL_COMPOSITE_DEADLINE_ANDROID: + case EGL_COMPOSITE_INTERVAL_ANDROID: + case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: + return EGL_TRUE; + default: + return EGL_FALSE; + } +} + +EGLBoolean eglGetFrameTimestampsANDROIDImpl(EGLDisplay dpy, EGLSurface surface, + EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, + EGLnsecsANDROID *values) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + if (!s->getNativeWindow()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + nsecs_t* requestedPresentTime = nullptr; + nsecs_t* acquireTime = nullptr; + nsecs_t* latchTime = nullptr; + nsecs_t* firstRefreshStartTime = nullptr; + nsecs_t* gpuCompositionDoneTime = nullptr; + nsecs_t* lastRefreshStartTime = nullptr; + nsecs_t* displayPresentTime = nullptr; + nsecs_t* dequeueReadyTime = nullptr; + nsecs_t* releaseTime = nullptr; + + for (int i = 0; i < numTimestamps; i++) { + switch (timestamps[i]) { + case EGL_REQUESTED_PRESENT_TIME_ANDROID: + requestedPresentTime = &values[i]; + break; + case EGL_RENDERING_COMPLETE_TIME_ANDROID: + acquireTime = &values[i]; + break; + case EGL_COMPOSITION_LATCH_TIME_ANDROID: + latchTime = &values[i]; + break; + case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: + firstRefreshStartTime = &values[i]; + break; + case EGL_LAST_COMPOSITION_START_TIME_ANDROID: + lastRefreshStartTime = &values[i]; + break; + case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: + gpuCompositionDoneTime = &values[i]; + break; + case EGL_DISPLAY_PRESENT_TIME_ANDROID: + displayPresentTime = &values[i]; + break; + case EGL_DEQUEUE_READY_TIME_ANDROID: + dequeueReadyTime = &values[i]; + break; + case EGL_READS_DONE_TIME_ANDROID: + releaseTime = &values[i]; + break; + default: + return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); + } + } + + int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId, + requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime, + lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime, + dequeueReadyTime, releaseTime); + + switch (ret) { + case 0: + return EGL_TRUE; + case -ENOENT: + return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE); + case -ENOSYS: + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + case -EINVAL: + return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); + default: + // This should not happen. Return an error that is not in the spec + // so it's obvious something is very wrong. + ALOGE("eglGetFrameTimestamps: Unexpected error."); + return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); + } +} + +EGLBoolean eglGetFrameTimestampSupportedANDROIDImpl( + EGLDisplay dpy, EGLSurface surface, EGLint timestamp) +{ + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + ANativeWindow* window = s->getNativeWindow(); + if (!window) { + return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); + } + + switch (timestamp) { + case EGL_COMPOSITE_DEADLINE_ANDROID: + case EGL_COMPOSITE_INTERVAL_ANDROID: + case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: + case EGL_REQUESTED_PRESENT_TIME_ANDROID: + case EGL_RENDERING_COMPLETE_TIME_ANDROID: + case EGL_COMPOSITION_LATCH_TIME_ANDROID: + case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: + case EGL_LAST_COMPOSITION_START_TIME_ANDROID: + case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: + case EGL_DEQUEUE_READY_TIME_ANDROID: + case EGL_READS_DONE_TIME_ANDROID: + return EGL_TRUE; + case EGL_DISPLAY_PRESENT_TIME_ANDROID: { + int value = 0; + window->query(window, + NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value); + return value == 0 ? EGL_FALSE : EGL_TRUE; + } + default: + return EGL_FALSE; + } +} + +const GLubyte * glGetStringImpl(GLenum name) { + const GLubyte * ret = egl_get_string_for_current_context(name); + if (ret == NULL) { + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; + if(_c) ret = _c->glGetString(name); + } + return ret; +} + +const GLubyte * glGetStringiImpl(GLenum name, GLuint index) { + const GLubyte * ret = egl_get_string_for_current_context(name, index); + if (ret == NULL) { + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; + if(_c) ret = _c->glGetStringi(name, index); + } + return ret; +} + +void glGetBooleanvImpl(GLenum pname, GLboolean * data) { + if (pname == GL_NUM_EXTENSIONS) { + int num_exts = egl_get_num_extensions_for_current_context(); + if (num_exts >= 0) { + *data = num_exts > 0 ? GL_TRUE : GL_FALSE; + return; + } + } + + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; + if (_c) _c->glGetBooleanv(pname, data); +} + +void glGetFloatvImpl(GLenum pname, GLfloat * data) { + if (pname == GL_NUM_EXTENSIONS) { + int num_exts = egl_get_num_extensions_for_current_context(); + if (num_exts >= 0) { + *data = (GLfloat)num_exts; + return; + } + } + + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; + if (_c) _c->glGetFloatv(pname, data); +} + +void glGetIntegervImpl(GLenum pname, GLint * data) { + if (pname == GL_NUM_EXTENSIONS) { + int num_exts = egl_get_num_extensions_for_current_context(); + if (num_exts >= 0) { + *data = (GLint)num_exts; + return; + } + } + + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; + if (_c) _c->glGetIntegerv(pname, data); +} + +void glGetInteger64vImpl(GLenum pname, GLint64 * data) { + if (pname == GL_NUM_EXTENSIONS) { + int num_exts = egl_get_num_extensions_for_current_context(); + if (num_exts >= 0) { + *data = (GLint64)num_exts; + return; + } + } + + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; + if (_c) _c->glGetInteger64v(pname, data); +} + +struct implementation_map_t { + const char* name; + EGLFuncPointer address; +}; + +static const implementation_map_t sPlatformImplMap[] = { + // clang-format off + { "eglGetDisplay", (EGLFuncPointer)&eglGetDisplayImpl }, + { "eglGetPlatformDisplay", (EGLFuncPointer)&eglGetPlatformDisplayImpl }, + { "eglInitialize", (EGLFuncPointer)&eglInitializeImpl }, + { "eglTerminate", (EGLFuncPointer)&eglTerminateImpl }, + { "eglGetConfigs", (EGLFuncPointer)&eglGetConfigsImpl }, + { "eglChooseConfig", (EGLFuncPointer)&eglChooseConfigImpl }, + { "eglGetConfigAttrib", (EGLFuncPointer)&eglGetConfigAttribImpl }, + { "eglCreateWindowSurface", (EGLFuncPointer)&eglCreateWindowSurfaceImpl }, + { "eglCreatePixmapSurface", (EGLFuncPointer)&eglCreatePixmapSurfaceImpl }, + { "eglCreatePlatformWindowSurface", (EGLFuncPointer)&eglCreatePlatformWindowSurfaceImpl }, + { "eglCreatePlatformPixmapSurface", (EGLFuncPointer)&eglCreatePlatformPixmapSurfaceImpl }, + { "eglCreatePbufferSurface", (EGLFuncPointer)&eglCreatePbufferSurfaceImpl }, + { "eglDestroySurface", (EGLFuncPointer)&eglDestroySurfaceImpl }, + { "eglQuerySurface", (EGLFuncPointer)&eglQuerySurfaceImpl }, + { "eglBeginFrame", (EGLFuncPointer)&eglBeginFrameImpl }, + { "eglCreateContext", (EGLFuncPointer)&eglCreateContextImpl }, + { "eglDestroyContext", (EGLFuncPointer)&eglDestroyContextImpl }, + { "eglMakeCurrent", (EGLFuncPointer)&eglMakeCurrentImpl }, + { "eglQueryContext", (EGLFuncPointer)&eglQueryContextImpl }, + { "eglGetCurrentContext", (EGLFuncPointer)&eglGetCurrentContextImpl }, + { "eglGetCurrentSurface", (EGLFuncPointer)&eglGetCurrentSurfaceImpl }, + { "eglGetCurrentDisplay", (EGLFuncPointer)&eglGetCurrentDisplayImpl }, + { "eglWaitGL", (EGLFuncPointer)&eglWaitGLImpl }, + { "eglWaitNative", (EGLFuncPointer)&eglWaitNativeImpl }, + { "eglGetError", (EGLFuncPointer)&eglGetErrorImpl }, + { "eglSwapBuffersWithDamageKHR", (EGLFuncPointer)&eglSwapBuffersWithDamageKHRImpl }, + { "eglGetProcAddress", (EGLFuncPointer)&eglGetProcAddressImpl }, + { "eglSwapBuffers", (EGLFuncPointer)&eglSwapBuffersImpl }, + { "eglCopyBuffers", (EGLFuncPointer)&eglCopyBuffersImpl }, + { "eglQueryString", (EGLFuncPointer)&eglQueryStringImpl }, + { "eglQueryStringImplementationANDROID", (EGLFuncPointer)&eglQueryStringImplementationANDROIDImpl }, + { "eglSurfaceAttrib", (EGLFuncPointer)&eglSurfaceAttribImpl }, + { "eglBindTexImage", (EGLFuncPointer)&eglBindTexImageImpl }, + { "eglReleaseTexImage", (EGLFuncPointer)&eglReleaseTexImageImpl }, + { "eglSwapInterval", (EGLFuncPointer)&eglSwapIntervalImpl }, + { "eglWaitClient", (EGLFuncPointer)&eglWaitClientImpl }, + { "eglBindAPI", (EGLFuncPointer)&eglBindAPIImpl }, + { "eglQueryAPI", (EGLFuncPointer)&eglQueryAPIImpl }, + { "eglReleaseThread", (EGLFuncPointer)&eglReleaseThreadImpl }, + { "eglCreatePbufferFromClientBuffer", (EGLFuncPointer)&eglCreatePbufferFromClientBufferImpl }, + { "eglLockSurfaceKHR", (EGLFuncPointer)&eglLockSurfaceKHRImpl }, + { "eglUnlockSurfaceKHR", (EGLFuncPointer)&eglUnlockSurfaceKHRImpl }, + { "eglCreateImageKHR", (EGLFuncPointer)&eglCreateImageKHRImpl }, + { "eglDestroyImageKHR", (EGLFuncPointer)&eglDestroyImageKHRImpl }, + { "eglCreateImage", (EGLFuncPointer)&eglCreateImageImpl }, + { "eglDestroyImage", (EGLFuncPointer)&eglDestroyImageImpl }, + { "eglCreateSync", (EGLFuncPointer)&eglCreateSyncImpl }, + { "eglDestroySync", (EGLFuncPointer)&eglDestroySyncImpl }, + { "eglClientWaitSync", (EGLFuncPointer)&eglClientWaitSyncImpl }, + { "eglGetSyncAttrib", (EGLFuncPointer)&eglGetSyncAttribImpl }, + { "eglCreateSyncKHR", (EGLFuncPointer)&eglCreateSyncKHRImpl }, + { "eglDestroySyncKHR", (EGLFuncPointer)&eglDestroySyncKHRImpl }, + { "eglSignalSyncKHR", (EGLFuncPointer)&eglSignalSyncKHRImpl }, + { "eglClientWaitSyncKHR", (EGLFuncPointer)&eglClientWaitSyncKHRImpl }, + { "eglGetSyncAttribKHR", (EGLFuncPointer)&eglGetSyncAttribKHRImpl }, + { "eglCreateStreamKHR", (EGLFuncPointer)&eglCreateStreamKHRImpl }, + { "eglDestroyStreamKHR", (EGLFuncPointer)&eglDestroyStreamKHRImpl }, + { "eglStreamAttribKHR", (EGLFuncPointer)&eglStreamAttribKHRImpl }, + { "eglQueryStreamKHR", (EGLFuncPointer)&eglQueryStreamKHRImpl }, + { "eglQueryStreamu64KHR", (EGLFuncPointer)&eglQueryStreamu64KHRImpl }, + { "eglQueryStreamTimeKHR", (EGLFuncPointer)&eglQueryStreamTimeKHRImpl }, + { "eglCreateStreamProducerSurfaceKHR", (EGLFuncPointer)&eglCreateStreamProducerSurfaceKHRImpl }, + { "eglStreamConsumerGLTextureExternalKHR", (EGLFuncPointer)&eglStreamConsumerGLTextureExternalKHRImpl }, + { "eglStreamConsumerAcquireKHR", (EGLFuncPointer)&eglStreamConsumerAcquireKHRImpl }, + { "eglStreamConsumerReleaseKHR", (EGLFuncPointer)&eglStreamConsumerReleaseKHRImpl }, + { "eglGetStreamFileDescriptorKHR", (EGLFuncPointer)&eglGetStreamFileDescriptorKHRImpl }, + { "eglCreateStreamFromFileDescriptorKHR", (EGLFuncPointer)&eglCreateStreamFromFileDescriptorKHRImpl }, + { "eglWaitSync", (EGLFuncPointer)&eglWaitSyncImpl }, + { "eglWaitSyncKHR", (EGLFuncPointer)&eglWaitSyncKHRImpl }, + { "eglDupNativeFenceFDANDROID", (EGLFuncPointer)&eglDupNativeFenceFDANDROIDImpl }, + { "eglPresentationTimeANDROID", (EGLFuncPointer)&eglPresentationTimeANDROIDImpl }, + { "eglGetNativeClientBufferANDROID", (EGLFuncPointer)&eglGetNativeClientBufferANDROIDImpl }, + { "eglGetSystemTimeFrequencyNV", (EGLFuncPointer)&eglGetSystemTimeFrequencyNVImpl }, + { "eglGetSystemTimeNV", (EGLFuncPointer)&eglGetSystemTimeNVImpl }, + { "eglSetDamageRegionKHR", (EGLFuncPointer)&eglSetDamageRegionKHRImpl }, + { "eglGetNextFrameIdANDROID", (EGLFuncPointer)&eglGetNextFrameIdANDROIDImpl }, + { "eglGetCompositorTimingANDROID", (EGLFuncPointer)&eglGetCompositorTimingANDROIDImpl }, + { "eglGetCompositorTimingSupportedANDROID", (EGLFuncPointer)&eglGetCompositorTimingSupportedANDROIDImpl }, + { "eglGetFrameTimestampsANDROID", (EGLFuncPointer)&eglGetFrameTimestampsANDROIDImpl }, + { "eglGetFrameTimestampSupportedANDROID", (EGLFuncPointer)&eglGetFrameTimestampSupportedANDROIDImpl }, + { "glGetString", (EGLFuncPointer)&glGetStringImpl }, + { "glGetStringi", (EGLFuncPointer)&glGetStringiImpl }, + { "glGetBooleanv", (EGLFuncPointer)&glGetBooleanvImpl }, + { "glGetFloatv", (EGLFuncPointer)&glGetFloatvImpl }, + { "glGetIntegerv", (EGLFuncPointer)&glGetIntegervImpl }, + { "glGetInteger64v", (EGLFuncPointer)&glGetInteger64vImpl }, + // clang-format on +}; + +EGLFuncPointer FindPlatformImplAddr(const char* name) +{ + static const bool DEBUG = false; + + if (name == nullptr) { + ALOGV("FindPlatformImplAddr called with null name"); + return nullptr; + } + + for (int i = 0; i < NELEM(sPlatformImplMap); i++) { + if (sPlatformImplMap[i].name == nullptr) { + ALOGV("FindPlatformImplAddr found nullptr for sPlatformImplMap[%i].name (%s)", i, name); + return nullptr; + } + if (!strcmp(name, sPlatformImplMap[i].name)) { + ALOGV("FindPlatformImplAddr found %llu for sPlatformImplMap[%i].address (%s)", (unsigned long long)sPlatformImplMap[i].address, i, name); + return sPlatformImplMap[i].address; + } + } + + ALOGV("FindPlatformImplAddr did not find an entry for %s", name); + return nullptr; +} +} // namespace android diff --git a/opengl/libs/EGL/egl_platform_entries.h b/opengl/libs/EGL/egl_platform_entries.h new file mode 100644 index 0000000000..85b1db3fae --- /dev/null +++ b/opengl/libs/EGL/egl_platform_entries.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EGLAPI_H +#define ANDROID_EGLAPI_H + +#include <EGL/egl.h> + +typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer; + +namespace android { + +EGLint eglGetErrorImpl(); +EGLFuncPointer FindPlatformImplAddr(const char* name); + +}; // namespace android + +#endif // ANDROID_EGLAPI_H + diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp index 8508c5fe9d..aaecb62194 100644 --- a/opengl/libs/EGL/egl_tls.cpp +++ b/opengl/libs/EGL/egl_tls.cpp @@ -21,6 +21,7 @@ #include <cutils/properties.h> #include <log/log.h> #include "CallStack.h" +#include "egl_platform_entries.h" namespace android { @@ -28,7 +29,7 @@ pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED; pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT; egl_tls_t::egl_tls_t() - : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(true) { + : error(EGL_SUCCESS), ctx(nullptr), logCallWithNoContext(true) { } const char *egl_tls_t::egl_strerror(EGLint err) { @@ -55,13 +56,38 @@ const char *egl_tls_t::egl_strerror(EGLint err) { void egl_tls_t::validateTLSKey() { struct TlsKeyInitializer { - static void create() { - pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread); - } + static void create() { pthread_key_create(&sKey, destructTLSData); } }; pthread_once(&sOnceKey, TlsKeyInitializer::create); } +void egl_tls_t::destructTLSData(void* data) { + egl_tls_t* tls = static_cast<egl_tls_t*>(data); + if (!tls) return; + + // Several things in the call tree of eglReleaseThread expect to be able to get the current + // thread state directly from TLS. That's a problem because Bionic has already cleared our + // TLS pointer before calling this function (pthread_getspecific(sKey) will return nullptr). + // Instead the data is passed as our parameter. + // + // Ideally we'd refactor this so we have thin wrappers that retrieve thread state from TLS and + // then pass it as a parameter (or 'this' pointer) to functions that do the real work without + // touching TLS. Then from here we could just call those implementation functions with the the + // TLS data we just received as a parameter. + // + // But that's a fairly invasive refactoring, so to do this robustly in the short term we just + // put the data *back* in TLS and call the top-level eglReleaseThread. It and it's call tree + // will retrieve the value from TLS, and then finally clear the TLS data. Bionic explicitly + // tolerates re-setting the value that it's currently trying to destruct (see + // pthread_key_clean_all()). Even if we forgot to clear the restored TLS data, bionic would + // call the destructor again, but eventually gives up and just leaks the data rather than + // enter an infinite loop. + pthread_setspecific(sKey, tls); + eglReleaseThread(); + ALOGE_IF(pthread_getspecific(sKey) != nullptr, + "EGL TLS data still exists after eglReleaseThread"); +} + void egl_tls_t::setErrorEtcImpl( const char* caller, int line, EGLint error, bool quiet) { validateTLSKey(); @@ -92,7 +118,7 @@ bool egl_tls_t::logNoContextCall() { egl_tls_t* egl_tls_t::getTLS() { egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); - if (tls == 0) { + if (tls == nullptr) { tls = new egl_tls_t; pthread_setspecific(sKey, tls); } @@ -103,7 +129,7 @@ void egl_tls_t::clearTLS() { if (sKey != TLS_KEY_NOT_INITIALIZED) { egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey); if (tls) { - pthread_setspecific(sKey, 0); + pthread_setspecific(sKey, nullptr); delete tls; } } @@ -112,7 +138,7 @@ void egl_tls_t::clearTLS() { void egl_tls_t::clearError() { // This must clear the error from all the underlying EGL implementations as // well as the EGL wrapper layer. - eglGetError(); + android::eglGetErrorImpl(); } EGLint egl_tls_t::getError() { diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h index 9feae681bd..86a375c002 100644 --- a/opengl/libs/EGL/egl_tls.h +++ b/opengl/libs/EGL/egl_tls.h @@ -38,6 +38,7 @@ class egl_tls_t { egl_tls_t(); static void validateTLSKey(); + static void destructTLSData(void* data); static void setErrorEtcImpl( const char* caller, int line, EGLint error, bool quiet); diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h index 985827655a..9e112cc034 100644 --- a/opengl/libs/EGL/egldefs.h +++ b/opengl/libs/EGL/egldefs.h @@ -18,9 +18,13 @@ #define ANDROID_EGLDEFS_H #include "../hooks.h" +#include "egl_platform_entries.h" + +#include <log/log.h> #define VERSION_MAJOR 1 #define VERSION_MINOR 4 +#define EGL_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch)) // ---------------------------------------------------------------------------- namespace android { @@ -31,23 +35,54 @@ const unsigned int NUM_DISPLAYS = 1; // ---------------------------------------------------------------------------- +extern char const * const platform_names[]; + +// clang-format off struct egl_connection_t { enum { GLESv1_INDEX = 0, GLESv2_INDEX = 1 }; - inline egl_connection_t() : dso(0) { } + inline egl_connection_t() : dso(nullptr) { + + char const* const* entries = platform_names; + EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform); + while (*entries) { + const char* name = *entries; + EGLFuncPointer f = FindPlatformImplAddr(name); + + if (f == nullptr) { + // If no entry found, update the lookup table: sPlatformImplMap + ALOGE("No entry found in platform lookup table for %s", name); + } + + *curr++ = f; + entries++; + } + } + void * dso; gl_hooks_t * hooks[2]; EGLint major; EGLint minor; + EGLint driverVersion; egl_t egl; + // Functions implemented or redirected by platform libraries + platform_impl_t platform; + void* libEgl; void* libGles1; void* libGles2; + + bool shouldUseAngle; // Should we attempt to load ANGLE + bool angleDecided; // Have we tried to load ANGLE + bool useAngle; // Was ANGLE successfully loaded + EGLint angleBackend; + void* vendorEGL; }; +// clang-format on // ---------------------------------------------------------------------------- @@ -58,6 +93,7 @@ extern "C" void gl_unimplemented(); extern "C" void gl_noop(); extern char const * const gl_names[]; +extern char const * const gl_names_1[]; extern char const * const egl_names[]; extern egl_connection_t gEGLImpl; diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp index f7fde9625f..65f50f54fb 100644 --- a/opengl/libs/GLES2/gl2.cpp +++ b/opengl/libs/GLES2/gl2.cpp @@ -301,71 +301,31 @@ extern "C" { } const GLubyte * glGetString(GLenum name) { - const GLubyte * ret = egl_get_string_for_current_context(name); - if (ret == NULL) { - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; - if(_c) ret = _c->glGetString(name); - } - return ret; + egl_connection_t* const cnx = egl_get_connection(); + return cnx->platform.glGetString(name); } const GLubyte * glGetStringi(GLenum name, GLuint index) { - const GLubyte * ret = egl_get_string_for_current_context(name, index); - if (ret == NULL) { - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; - if(_c) ret = _c->glGetStringi(name, index); - } - return ret; + egl_connection_t* const cnx = egl_get_connection(); + return cnx->platform.glGetStringi(name, index); } void glGetBooleanv(GLenum pname, GLboolean * data) { - if (pname == GL_NUM_EXTENSIONS) { - int num_exts = egl_get_num_extensions_for_current_context(); - if (num_exts >= 0) { - *data = num_exts > 0 ? GL_TRUE : GL_FALSE; - return; - } - } - - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; - if (_c) _c->glGetBooleanv(pname, data); + egl_connection_t* const cnx = egl_get_connection(); + return cnx->platform.glGetBooleanv(pname, data); } void glGetFloatv(GLenum pname, GLfloat * data) { - if (pname == GL_NUM_EXTENSIONS) { - int num_exts = egl_get_num_extensions_for_current_context(); - if (num_exts >= 0) { - *data = (GLfloat)num_exts; - return; - } - } - - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; - if (_c) _c->glGetFloatv(pname, data); + egl_connection_t* const cnx = egl_get_connection(); + return cnx->platform.glGetFloatv(pname, data); } void glGetIntegerv(GLenum pname, GLint * data) { - if (pname == GL_NUM_EXTENSIONS) { - int num_exts = egl_get_num_extensions_for_current_context(); - if (num_exts >= 0) { - *data = (GLint)num_exts; - return; - } - } - - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; - if (_c) _c->glGetIntegerv(pname, data); + egl_connection_t* const cnx = egl_get_connection(); + return cnx->platform.glGetIntegerv(pname, data); } void glGetInteger64v(GLenum pname, GLint64 * data) { - if (pname == GL_NUM_EXTENSIONS) { - int num_exts = egl_get_num_extensions_for_current_context(); - if (num_exts >= 0) { - *data = (GLint64)num_exts; - return; - } - } - - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; - if (_c) _c->glGetInteger64v(pname, data); + egl_connection_t* const cnx = egl_get_connection(); + return cnx->platform.glGetInteger64v(pname, data); } diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h index a8855efa57..0af050175b 100644 --- a/opengl/libs/egl_impl.h +++ b/opengl/libs/egl_impl.h @@ -21,15 +21,18 @@ #include <EGL/eglext.h> #include <EGL/eglplatform.h> +#include "EGL/egldefs.h" #include "hooks.h" // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- + EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name); EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index); EGLAPI GLint egl_get_num_extensions_for_current_context(); +EGLAPI egl_connection_t* egl_get_connection(); // ---------------------------------------------------------------------------- }; // namespace android diff --git a/opengl/libs/entries_gles1.in b/opengl/libs/entries_gles1.in new file mode 100644 index 0000000000..c9be593dd9 --- /dev/null +++ b/opengl/libs/entries_gles1.in @@ -0,0 +1,298 @@ +GL_ENTRY(void, glActiveTexture, GLenum texture) +GL_ENTRY(void, glAlphaFunc, GLenum func, GLfloat ref) +GL_ENTRY(void, glAlphaFuncx, GLenum func, GLfixed ref) +GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLfixed ref) +GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer) +GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer) +GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer) +GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture) +GL_ENTRY(void, glBindVertexArrayOES, GLuint array) +GL_ENTRY(void, glBlendEquationOES, GLenum mode) +GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha) +GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor) +GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) +GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) +GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target) +GL_ENTRY(void, glClear, GLbitfield mask) +GL_ENTRY(void, glClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +GL_ENTRY(void, glClearColorx, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +GL_ENTRY(void, glClearColorxOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +GL_ENTRY(void, glClearDepthf, GLfloat d) +GL_ENTRY(void, glClearDepthfOES, GLclampf depth) +GL_ENTRY(void, glClearDepthx, GLfixed depth) +GL_ENTRY(void, glClearDepthxOES, GLfixed depth) +GL_ENTRY(void, glClearStencil, GLint s) +GL_ENTRY(void, glClientActiveTexture, GLenum texture) +GL_ENTRY(GLenum, glClientWaitSyncAPPLE, GLsync sync, GLbitfield flags, GLuint64 timeout) +GL_ENTRY(void, glClipPlanef, GLenum p, const GLfloat *eqn) +GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat *eqn) +GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation) +GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation) +GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed *eqn) +GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation) +GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const void *pointer) +GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) +GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) +GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glCopyTextureLevelsAPPLE, GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount) +GL_ENTRY(void, glCullFace, GLenum mode) +GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex) +GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers) +GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences) +GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint *framebuffers) +GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint *renderbuffers) +GL_ENTRY(void, glDeleteSyncAPPLE, GLsync sync) +GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures) +GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays) +GL_ENTRY(void, glDepthFunc, GLenum func) +GL_ENTRY(void, glDepthMask, GLboolean flag) +GL_ENTRY(void, glDepthRangef, GLfloat n, GLfloat f) +GL_ENTRY(void, glDepthRangefOES, GLclampf n, GLclampf f) +GL_ENTRY(void, glDepthRangex, GLfixed n, GLfixed f) +GL_ENTRY(void, glDepthRangexOES, GLfixed n, GLfixed f) +GL_ENTRY(void, glDisable, GLenum cap) +GL_ENTRY(void, glDisableClientState, GLenum array) +GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl) +GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments) +GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count) +GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void *indices) +GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) +GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords) +GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height) +GL_ENTRY(void, glDrawTexivOES, const GLint *coords) +GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) +GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords) +GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) +GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords) +GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image) +GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image) +GL_ENTRY(void, glEnable, GLenum cap) +GL_ENTRY(void, glEnableClientState, GLenum array) +GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl) +GL_ENTRY(void, glEndTilingQCOM, GLbitfield preserveMask) +GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, void **params) +GL_ENTRY(void, glExtGetBuffersQCOM, GLuint *buffers, GLint maxBuffers, GLint *numBuffers) +GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers) +GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar *source, GLint *length) +GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms) +GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers) +GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders) +GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params) +GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels) +GL_ENTRY(void, glExtGetTexturesQCOM, GLuint *textures, GLint maxTextures, GLint *numTextures) +GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program) +GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param) +GL_ENTRY(GLsync, glFenceSyncAPPLE, GLenum condition, GLbitfield flags) +GL_ENTRY(void, glFinish, void) +GL_ENTRY(void, glFinishFenceNV, GLuint fence) +GL_ENTRY(void, glFlush, void) +GL_ENTRY(void, glFlushMappedBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length) +GL_ENTRY(void, glFogf, GLenum pname, GLfloat param) +GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glFogx, GLenum pname, GLfixed param) +GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param) +GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *param) +GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *param) +GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +GL_ENTRY(void, glFramebufferTexture2DMultisampleEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) +GL_ENTRY(void, glFramebufferTexture2DMultisampleIMG, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) +GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +GL_ENTRY(void, glFrontFace, GLenum mode) +GL_ENTRY(void, glFrustumf, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) +GL_ENTRY(void, glFrustumfOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) +GL_ENTRY(void, glFrustumx, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) +GL_ENTRY(void, glFrustumxOES, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) +GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers) +GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences) +GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint *framebuffers) +GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint *renderbuffers) +GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures) +GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays) +GL_ENTRY(void, glGenerateMipmapOES, GLenum target) +GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *data) +GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params) +GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void **params) +GL_ENTRY(void, glGetClipPlanef, GLenum plane, GLfloat *equation) +GL_ENTRY(void, glGetClipPlanefOES, GLenum plane, GLfloat *equation) +GL_ENTRY(void, glGetClipPlanex, GLenum plane, GLfixed *equation) +GL_ENTRY(void, glGetClipPlanexOES, GLenum plane, GLfixed *equation) +GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString) +GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls) +GL_ENTRY(GLenum, glGetError, void) +GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params) +GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *data) +GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint *params) +GL_ENTRY(GLenum, glGetGraphicsResetStatusEXT, void) +GL_ENTRY(void, glGetInteger64vAPPLE, GLenum pname, GLint64 *params) +GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *data) +GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetPointerv, GLenum pname, void **params) +GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint *params) +GL_ENTRY(const GLubyte *, glGetString, GLenum name) +GL_ENTRY(void, glGetSyncivAPPLE, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) +GL_ENTRY(void, glGetTexEnvfv, GLenum target, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetTexEnviv, GLenum target, GLenum pname, GLint *params) +GL_ENTRY(void, glGetTexEnvxv, GLenum target, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexEnvxvOES, GLenum target, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params) +GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params) +GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params) +GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params) +GL_ENTRY(void, glGetnUniformfvEXT, GLuint program, GLint location, GLsizei bufSize, GLfloat *params) +GL_ENTRY(void, glGetnUniformivEXT, GLuint program, GLint location, GLsizei bufSize, GLint *params) +GL_ENTRY(void, glHint, GLenum target, GLenum mode) +GL_ENTRY(void, glInsertEventMarkerEXT, GLsizei length, const GLchar *marker) +GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer) +GL_ENTRY(GLboolean, glIsEnabled, GLenum cap) +GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence) +GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer) +GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer) +GL_ENTRY(GLboolean, glIsSyncAPPLE, GLsync sync) +GL_ENTRY(GLboolean, glIsTexture, GLuint texture) +GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array) +GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param) +GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *param) +GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *param) +GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param) +GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param) +GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glLineWidth, GLfloat width) +GL_ENTRY(void, glLineWidthx, GLfixed width) +GL_ENTRY(void, glLineWidthxOES, GLfixed width) +GL_ENTRY(void, glLoadIdentity, void) +GL_ENTRY(void, glLoadMatrixf, const GLfloat *m) +GL_ENTRY(void, glLoadMatrixx, const GLfixed *m) +GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m) +GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void) +GL_ENTRY(void, glLogicOp, GLenum opcode) +GL_ENTRY(void *, glMapBufferOES, GLenum target, GLenum access) +GL_ENTRY(void *, glMapBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param) +GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param) +GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param) +GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *param) +GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *param) +GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const void *pointer) +GL_ENTRY(void, glMatrixMode, GLenum mode) +GL_ENTRY(void, glMultMatrixf, const GLfloat *m) +GL_ENTRY(void, glMultMatrixx, const GLfixed *m) +GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m) +GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) +GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount) +GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +GL_ENTRY(void, glMultiTexCoord4x, GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +GL_ENTRY(void, glMultiTexCoord4xOES, GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz) +GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz) +GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz) +GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const void *pointer) +GL_ENTRY(void, glOrthof, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) +GL_ENTRY(void, glOrthofOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) +GL_ENTRY(void, glOrthox, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) +GL_ENTRY(void, glOrthoxOES, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) +GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param) +GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param) +GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param) +GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param) +GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glPointSize, GLfloat size) +GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const void *pointer) +GL_ENTRY(void, glPointSizex, GLfixed size) +GL_ENTRY(void, glPointSizexOES, GLfixed size) +GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units) +GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units) +GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units) +GL_ENTRY(void, glPopGroupMarkerEXT, void) +GL_ENTRY(void, glPopMatrix, void) +GL_ENTRY(void, glPushGroupMarkerEXT, GLsizei length, const GLchar *marker) +GL_ENTRY(void, glPushMatrix, void) +GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed *mantissa, GLint *exponent) +GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) +GL_ENTRY(void, glReadnPixelsEXT, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) +GL_ENTRY(void, glRenderbufferStorageMultisampleAPPLE, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glRenderbufferStorageMultisampleEXT, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glRenderbufferStorageMultisampleIMG, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glResolveMultisampleFramebufferAPPLE, void) +GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glSampleCoverage, GLfloat value, GLboolean invert) +GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert) +GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert) +GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition) +GL_ENTRY(void, glShadeModel, GLenum mode) +GL_ENTRY(void, glStartTilingQCOM, GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) +GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask) +GL_ENTRY(void, glStencilMask, GLuint mask) +GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass) +GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence) +GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const void *pointer) +GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param) +GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params) +GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param) +GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params) +GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) +GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params) +GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param) +GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params) +GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param) +GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params) +GL_ENTRY(void, glTexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) +GL_ENTRY(void, glTexStorage2DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glTexStorage3DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) +GL_ENTRY(void, glTextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) +GL_ENTRY(void, glTextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glTextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z) +GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target) +GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const void *pointer) +GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glWaitSyncAPPLE, GLsync sync, GLbitfield flags, GLuint64 timeout) +GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const void *pointer) diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h index 81dbe0e34b..63a0e140cc 100644 --- a/opengl/libs/hooks.h +++ b/opengl/libs/hooks.h @@ -59,6 +59,10 @@ namespace android { #define GL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__); #define EGL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__); +struct platform_impl_t { + #include "platform_entries.in" +}; + struct egl_t { #include "EGL/egl_entries.in" }; diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt index fa26e33f39..b2d795745f 100644 --- a/opengl/libs/libEGL.map.txt +++ b/opengl/libs/libEGL.map.txt @@ -3,23 +3,30 @@ LIBEGL { eglBindAPI; eglBindTexImage; eglChooseConfig; + eglClientWaitSync; # introduced=29 eglClientWaitSyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21 eglCopyBuffers; eglCreateContext; + eglCreateImage; # introduced=29 eglCreateImageKHR; eglCreateNativeClientBufferANDROID; # introduced=24 eglCreatePbufferFromClientBuffer; eglCreatePbufferSurface; eglCreatePixmapSurface; + eglCreatePlatformPixmapSurface; # introduced=29 + eglCreatePlatformWindowSurface; # introduced=29 eglCreateStreamFromFileDescriptorKHR; # introduced=23 eglCreateStreamKHR; # introduced=23 eglCreateStreamProducerSurfaceKHR; # introduced=23 + eglCreateSync; # introduced=29 eglCreateSyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21 eglCreateWindowSurface; eglDestroyContext; + eglDestroyImage; # introduced=29 eglDestroyImageKHR; eglDestroyStreamKHR; # introduced=23 eglDestroySurface; + eglDestroySync; # introduced=29 eglDestroySyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21 eglDupNativeFenceFDANDROID; # vndk eglGetConfigAttrib; @@ -30,8 +37,10 @@ LIBEGL { eglGetDisplay; eglGetError; eglGetNativeClientBufferANDROID; # introduced=26 + eglGetPlatformDisplay; # introduced=29 eglGetProcAddress; eglGetStreamFileDescriptorKHR; # introduced=23 + eglGetSyncAttrib; # introduced=29 eglGetSyncAttribKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21 eglGetSystemTimeFrequencyNV; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21 eglGetSystemTimeNV; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21 @@ -64,6 +73,7 @@ LIBEGL { eglWaitClient; eglWaitGL; eglWaitNative; + eglWaitSync; # introduced=29 eglWaitSyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21 local: *; diff --git a/opengl/libs/platform_entries.in b/opengl/libs/platform_entries.in new file mode 100644 index 0000000000..46734112d3 --- /dev/null +++ b/opengl/libs/platform_entries.in @@ -0,0 +1,86 @@ +EGL_ENTRY(EGLDisplay, eglGetDisplay, EGLNativeDisplayType) +EGL_ENTRY(EGLDisplay, eglGetPlatformDisplay, EGLenum, EGLNativeDisplayType, const EGLAttrib*) +EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*) +EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay) +EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*) +EGL_ENTRY(EGLBoolean, eglChooseConfig, EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*) +EGL_ENTRY(EGLBoolean, eglGetConfigAttrib, EGLDisplay, EGLConfig, EGLint, EGLint*) +EGL_ENTRY(EGLSurface, eglCreateWindowSurface, EGLDisplay, EGLConfig, NativeWindowType, const EGLint*) +EGL_ENTRY(EGLSurface, eglCreatePlatformWindowSurface, EGLDisplay, EGLConfig, void*, const EGLAttrib*) +EGL_ENTRY(EGLSurface, eglCreatePixmapSurface, EGLDisplay, EGLConfig, NativePixmapType, const EGLint*) +EGL_ENTRY(EGLSurface, eglCreatePlatformPixmapSurface, EGLDisplay, EGLConfig, void*, const EGLAttrib*) +EGL_ENTRY(EGLSurface, eglCreatePbufferSurface, EGLDisplay, EGLConfig, const EGLint*) +EGL_ENTRY(EGLBoolean, eglDestroySurface, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLBoolean, eglQuerySurface, EGLDisplay, EGLSurface, EGLint, EGLint*) +EGL_ENTRY(void, eglBeginFrame, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLContext, eglCreateContext, EGLDisplay, EGLConfig, EGLContext, const EGLint*) +EGL_ENTRY(EGLBoolean, eglDestroyContext, EGLDisplay, EGLContext) +EGL_ENTRY(EGLBoolean, eglMakeCurrent, EGLDisplay, EGLSurface, EGLSurface, EGLContext) +EGL_ENTRY(EGLBoolean, eglQueryContext, EGLDisplay, EGLContext, EGLint, EGLint*) +EGL_ENTRY(EGLContext, eglGetCurrentContext, void) +EGL_ENTRY(EGLSurface, eglGetCurrentSurface, EGLint) +EGL_ENTRY(EGLDisplay, eglGetCurrentDisplay, void) +EGL_ENTRY(EGLBoolean, eglWaitGL, void) +EGL_ENTRY(EGLBoolean, eglWaitNative, EGLint) +EGL_ENTRY(EGLint, eglGetError, void) +EGL_ENTRY(__eglMustCastToProperFunctionPointerType, eglGetProcAddress, const char*) +EGL_ENTRY(EGLBoolean, eglSwapBuffersWithDamageKHR, EGLDisplay, EGLSurface, EGLint*, EGLint) +EGL_ENTRY(EGLBoolean, eglSwapBuffers, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLBoolean, eglCopyBuffers, EGLDisplay, EGLSurface, NativePixmapType) +EGL_ENTRY(const char*, eglQueryString, EGLDisplay, EGLint) +EGL_ENTRY(const char*, eglQueryStringImplementationANDROID, EGLDisplay, EGLint) +EGL_ENTRY(EGLBoolean, eglSurfaceAttrib, EGLDisplay, EGLSurface, EGLint, EGLint) +EGL_ENTRY(EGLBoolean, eglBindTexImage, EGLDisplay, EGLSurface, EGLint) +EGL_ENTRY(EGLBoolean, eglReleaseTexImage, EGLDisplay, EGLSurface, EGLint) +EGL_ENTRY(EGLBoolean, eglSwapInterval, EGLDisplay, EGLint) +EGL_ENTRY(EGLBoolean, eglWaitClient, void) +EGL_ENTRY(EGLBoolean, eglBindAPI, EGLenum) +EGL_ENTRY(EGLenum, eglQueryAPI, void) +EGL_ENTRY(EGLBoolean, eglReleaseThread, void) +EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGLClientBuffer, EGLConfig, const EGLint*) +EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint*) +EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface) +EGL_ENTRY(EGLImage, eglCreateImage, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLAttrib*) +EGL_ENTRY(EGLBoolean, eglDestroyImage, EGLDisplay, EGLImage) +EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*) +EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR) +EGL_ENTRY(EGLSync, eglCreateSync, EGLDisplay, EGLenum, const EGLAttrib*) +EGL_ENTRY(EGLBoolean, eglDestroySync, EGLDisplay, EGLSync) +EGL_ENTRY(EGLint, eglClientWaitSync, EGLDisplay, EGLSync, EGLint, EGLTimeKHR) +EGL_ENTRY(EGLBoolean, eglGetSyncAttrib, EGLDisplay, EGLSyncKHR, EGLint, EGLAttrib*) +EGL_ENTRY(EGLSyncKHR, eglCreateSyncKHR, EGLDisplay, EGLenum, const EGLint*) +EGL_ENTRY(EGLBoolean, eglDestroySyncKHR, EGLDisplay, EGLSyncKHR) +EGL_ENTRY(EGLBoolean, eglSignalSyncKHR, EGLDisplay, EGLSyncKHR, EGLenum) +EGL_ENTRY(EGLint, eglClientWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint, EGLTimeKHR) +EGL_ENTRY(EGLBoolean, eglGetSyncAttribKHR, EGLDisplay, EGLSyncKHR, EGLint, EGLint*) +EGL_ENTRY(EGLStreamKHR, eglCreateStreamKHR, EGLDisplay, const EGLint*) +EGL_ENTRY(EGLBoolean, eglDestroyStreamKHR, EGLDisplay, EGLStreamKHR) +EGL_ENTRY(EGLBoolean, eglStreamAttribKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint) +EGL_ENTRY(EGLBoolean, eglQueryStreamKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint*) +EGL_ENTRY(EGLBoolean, eglQueryStreamu64KHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLuint64KHR*) +EGL_ENTRY(EGLBoolean, eglQueryStreamTimeKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLTimeKHR*) +EGL_ENTRY(EGLSurface, eglCreateStreamProducerSurfaceKHR, EGLDisplay, EGLConfig, EGLStreamKHR, const EGLint*) +EGL_ENTRY(EGLBoolean, eglStreamConsumerGLTextureExternalKHR, EGLDisplay, EGLStreamKHR) +EGL_ENTRY(EGLBoolean, eglStreamConsumerAcquireKHR, EGLDisplay, EGLStreamKHR) +EGL_ENTRY(EGLBoolean, eglStreamConsumerReleaseKHR, EGLDisplay, EGLStreamKHR) +EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGLDisplay, EGLStreamKHR) +EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR) +EGL_ENTRY(EGLint, eglWaitSync, EGLDisplay, EGLSync, EGLint) +EGL_ENTRY(EGLint, eglWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint) +EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR) +EGL_ENTRY(EGLBoolean, eglPresentationTimeANDROID, EGLDisplay, EGLSurface, EGLnsecsANDROID) +EGL_ENTRY(EGLClientBuffer, eglGetNativeClientBufferANDROID, const AHardwareBuffer*) +EGL_ENTRY(EGLuint64NV, eglGetSystemTimeFrequencyNV, void) +EGL_ENTRY(EGLuint64NV, eglGetSystemTimeNV, void) +EGL_ENTRY(EGLBoolean, eglSetDamageRegionKHR, EGLDisplay, EGLSurface, EGLint*, EGLint) +EGL_ENTRY(EGLBoolean, eglGetNextFrameIdANDROID, EGLDisplay, EGLSurface, EGLuint64KHR*) +EGL_ENTRY(EGLBoolean, eglGetCompositorTimingANDROID, EGLDisplay, EGLSurface, EGLint, const EGLint*, EGLnsecsANDROID*) +EGL_ENTRY(EGLBoolean, eglGetCompositorTimingSupportedANDROID, EGLDisplay, EGLSurface, EGLint) +EGL_ENTRY(EGLBoolean, eglGetFrameTimestampsANDROID, EGLDisplay, EGLSurface, EGLuint64KHR, EGLint, const EGLint*, EGLnsecsANDROID*) +EGL_ENTRY(EGLBoolean, eglGetFrameTimestampSupportedANDROID, EGLDisplay, EGLSurface, EGLint) +GL_ENTRY(const GLubyte*, glGetString, GLenum) +GL_ENTRY(const GLubyte*, glGetStringi, GLenum, GLuint) +GL_ENTRY(void, glGetBooleanv, GLenum, GLboolean*) +GL_ENTRY(void, glGetFloatv, GLenum, GLfloat*) +GL_ENTRY(void, glGetIntegerv, GLenum, GLint*) +GL_ENTRY(void, glGetInteger64v, GLenum, GLint64*) diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles deleted file mode 100755 index feef3186a8..0000000000 --- a/opengl/libs/tools/genfiles +++ /dev/null @@ -1,50 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2008 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Force a specific locale for sorting to avoid irrelevant differences -# in the generated files that could hide real differences. -export LC_ALL=POSIX - -./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in -./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in -./glapigen ../../include/GLES3/gl3.h > ../GLES2/gl2_api.in -./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in - -./glentrygen ../../include/GLES/gl.h > /tmp/gl_entries.in -./glentrygen ../../include/GLES/glext.h > /tmp/glext_entries.in -./glentrygen ../../include/GLES3/gl3.h > /tmp/gl2_entries.in -./glentrygen ../../include/GLES2/gl2ext.h > /tmp/gl2ext_entries.in - -# The awk command removes lines with the same function name as an earlier -# line, even if the rest of the line differs. Although signatures of -# functions with the same name should be the same, the different versions -# have some irrelevant whitespace and parameter name differences. -cat /tmp/gl_entries.in \ - /tmp/glext_entries.in \ - /tmp/gl2_entries.in \ - /tmp/gl2ext_entries.in \ - | sort -t, -k2 \ - | awk -F, '!_[$2]++' \ - > ../entries.in - -cat ../../include/GLES/gl.h \ - ../../include/GLES/glext.h \ - ../../include/GLES2/gl2ext.h \ - ../../include/GLES3/gl3.h \ - | ./glenumsgen \ - | sort \ - > ../enums.in - diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen deleted file mode 100755 index 4d8334f90f..0000000000 --- a/opengl/libs/tools/glapigen +++ /dev/null @@ -1,76 +0,0 @@ -#! /usr/bin/perl -# -# Copyright (C) 2008 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -use strict; - -sub rtrim($) -{ - my $string = shift; - $string =~ s/\s+$//; - return $string; -} - -while (my $line = <>) { - next if $line =~ /^\//; - next if $line =~ /^#/; - next if $line =~ /^\s*$/; - if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { - next; - } - my $type = rtrim($2); - my $name = $3; - my $args = $4; - - #printf("%s", $line); - - my $prefix = ""; - if ($name eq "glGetString") { - $prefix = "__"; - } - - printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args); - - printf(" {\n"); - if ($type eq "void") { - printf(" CALL_GL_API(%s", $name); - } else { - printf(" CALL_GL_API_RETURN(%s", $name); - } - my @args = split ',', $args; - my $len = scalar(@args); - for (my $num = 0; $num < $len; $num++) { - if ($args[$num] ne "void") { - print ", "; - # - # extract the name from the parameter - # type name - # const type *name - # type *name - # type name[4] - # - if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) { - printf("%s", $2); - } - } - } - printf(");\n"); - printf("}\n"); -} - - - - - diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen deleted file mode 100755 index 170f04131a..0000000000 --- a/opengl/libs/tools/glentrygen +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/perl -# -# Copyright (C) 2008 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -use strict; - -sub rtrim($) -{ - my $string = shift; - $string =~ s/\s+$//; - return $string; -} - -while (my $line = <>) { - next if $line =~ /^\//; - next if $line =~ /^#/; - next if $line =~ /^\s*$/; - if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { - next; - } - my $type = rtrim($2); - my $name = $3; - my $args = $4; - - printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args); -} diff --git a/opengl/libs/tools/glenumsgen b/opengl/libs/tools/glenumsgen deleted file mode 100755 index 2ae5fbfa25..0000000000 --- a/opengl/libs/tools/glenumsgen +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/perl -# -# Copyright (C) 2010 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -use strict; - -my %enumHash = (); - -while (my $line = <STDIN>) { - next if $line =~ /^\//; - # Skip bitfield definitions. - next if $line =~ /_BIT(\d+_|\s+)/; - if ($line !~ /^#define\s+(\S+)\s+(0x\S+)/) { - next; - } - my $enumName = $1; - my $enumValue = $2; - next if exists($enumHash { $enumValue }); - $enumHash { $enumValue } = $enumName; - printf("GL_ENUM(%s,%s)\n", $enumValue, $enumName); -} - - - - - diff --git a/opengl/specs/README b/opengl/specs/README index fdafb1bffb..6d597d5519 100644 --- a/opengl/specs/README +++ b/opengl/specs/README @@ -19,10 +19,7 @@ Khronos. 0x3145 EGL_SYNC_NATIVE_FENCE_FD_ANDROID (EGL_ANDROID_native_fence_sync) 0x3146 EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID (EGL_ANDROID_native_fence_sync) 0x3147 EGL_FRAMEBUFFER_TARGET_ANDROID (EGL_ANDROID_framebuffer_target) -0x3148 EGL_IMAGE_CROP_LEFT_ANDROID (EGL_ANDROID_image_crop) -0x3149 EGL_IMAGE_CROP_TOP_ANDROID (EGL_ANDROID_image_crop) -0x314A EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop) -0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop) +0x3148 - 0x314B previously used by the undocumented, deprecated extension EGL_ANDROID_image_crop 0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh) 0x314D EGL_GL_COLORSPACE_DEFAULT_EXT (EGL_EXT_image_gl_colorspace) 0x314E - 0x314F (unused) diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp index 459b1356b8..cca91c3a6f 100644 --- a/opengl/tests/EGLTest/EGL_test.cpp +++ b/opengl/tests/EGLTest/EGL_test.cpp @@ -217,6 +217,7 @@ TEST_F(EGLTest, EGLDisplayP3) { // Test that display-p3 extensions exist ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3")); ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear")); + ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough")); // Use 8-bit to keep forcus on Display-P3 aspect EGLint attrs[] = { @@ -289,6 +290,59 @@ TEST_F(EGLTest, EGLDisplayP3) { EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); } +TEST_F(EGLTest, EGLDisplayP3Passthrough) { + EGLConfig config; + EGLBoolean success; + + if (!hasWideColorDisplay) { + // skip this test if device does not have wide-color display + std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl; + return; + } + + // Test that display-p3 extensions exist + ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3")); + ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear")); + ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough")); + + get8BitConfig(config); + + struct DummyConsumer : public BnConsumerListener { + void onFrameAvailable(const BufferItem& /* item */) override {} + void onBuffersReleased() override {} + void onSidebandStreamChanged() override {} + }; + + // Create a EGLSurface + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + consumer->consumerConnect(new DummyConsumer, false); + sp<Surface> mSTC = new Surface(producer); + sp<ANativeWindow> mANW = mSTC; + EGLint winAttrs[] = { + // clang-format off + EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT, + EGL_NONE, EGL_NONE + // clang-format on + }; + + EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_SURFACE, eglSurface); + + android_dataspace dataspace = + static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get())); + ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3); + + EGLint value; + success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value); + ASSERT_EQ(EGL_UNSIGNED_TRUE, success); + ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT, value); + + EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); +} + TEST_F(EGLTest, EGLDisplayP31010102) { EGLint numConfigs; EGLConfig config; @@ -303,6 +357,7 @@ TEST_F(EGLTest, EGLDisplayP31010102) { // Test that display-p3 extensions exist ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3")); ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear")); + ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough")); // Use 8-bit to keep forcus on Display-P3 aspect EGLint attrs[] = { diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp index 2b76279801..a0bd4e2409 100644 --- a/opengl/tests/lib/WindowSurface.cpp +++ b/opengl/tests/lib/WindowSurface.cpp @@ -34,8 +34,12 @@ WindowSurface::WindowSurface() { } // Get main display parameters. - sp<IBinder> mainDpy = SurfaceComposerClient::getBuiltInDisplay( - ISurfaceComposer::eDisplayIdMain); + const auto mainDpy = SurfaceComposerClient::getInternalDisplayToken(); + if (mainDpy == nullptr) { + fprintf(stderr, "ERROR: no display\n"); + return; + } + DisplayInfo mainDpyInfo; err = SurfaceComposerClient::getDisplayInfo(mainDpy, &mainDpyInfo); if (err != NO_ERROR) { @@ -57,7 +61,7 @@ WindowSurface::WindowSurface() { sp<SurfaceControl> sc = surfaceComposerClient->createSurface( String8("Benchmark"), width, height, PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque); - if (sc == NULL || !sc->isValid()) { + if (sc == nullptr || !sc->isValid()) { fprintf(stderr, "Failed to create SurfaceControl\n"); return; } diff --git a/opengl/tests/lib/glTestLib.cpp b/opengl/tests/lib/glTestLib.cpp index 213dffd50f..290d7a0de2 100644 --- a/opengl/tests/lib/glTestLib.cpp +++ b/opengl/tests/lib/glTestLib.cpp @@ -37,7 +37,7 @@ void glTestPrintGLString(const char *name, GLenum s) { const char *v = (const char *) glGetString(s); - if (v == NULL) { + if (v == nullptr) { testPrintI("GL %s unknown", name); } else { testPrintI("GL %s = %s", name, v); diff --git a/opengl/tests/lib/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h index 9dc6bcf56a..cfa378f354 100644 --- a/opengl/tests/lib/include/EGLUtils.h +++ b/opengl/tests/lib/include/EGLUtils.h @@ -100,11 +100,11 @@ status_t EGLUtils::selectConfigForPixelFormat( if (!attrs) return BAD_VALUE; - if (outConfig == NULL) + if (outConfig == nullptr) return BAD_VALUE; // Get all the "potential match" configs... - if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE) + if (eglGetConfigs(dpy, nullptr, 0, &numConfigs) == EGL_FALSE) return BAD_VALUE; std::vector<EGLConfig> configs(numConfigs); @@ -113,7 +113,7 @@ status_t EGLUtils::selectConfigForPixelFormat( } int i; - EGLConfig config = NULL; + EGLConfig config = nullptr; for (i=0 ; i<n ; i++) { EGLint nativeVisualId = 0; eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId); @@ -243,7 +243,7 @@ String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) { EGLint numConfig = 0; - EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig); + EGLint returnVal = eglGetConfigs(dpy, nullptr, 0, &numConfig); msg.append(checkEglError("eglGetConfigs", returnVal)); if (!returnVal) { return false; @@ -280,6 +280,8 @@ String8 EGLUtils::decodeColorSpace(EGLint colorSpace) { return String8("EGL_GL_COLORSPACE_SRGB_KHR"); case EGL_GL_COLORSPACE_DISPLAY_P3_EXT: return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT"); + case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT: + return String8("EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"); case EGL_GL_COLORSPACE_LINEAR_KHR: return String8("EGL_GL_COLORSPACE_LINEAR_KHR"); default: diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen index f9e96eacb6..da9bb49495 100755 --- a/opengl/tools/glgen/gen +++ b/opengl/tools/glgen/gen @@ -90,9 +90,14 @@ fi rm src/*.class +# Add UnsupportedAppUsage.java to known sources. +mkdir -p out/android/annotation +cp ../../../../base/core/java/android/annotation/UnsupportedAppUsage.java out/android/annotation + pushd out > /dev/null mkdir classes javac -d classes android/opengl/EGL14.java \ + android/opengl/EGL15.java \ android/opengl/EGLExt.java \ com/google/android/gles_jni/GLImpl.java \ javax/microedition/khronos/opengles/GL10.java \ @@ -108,7 +113,8 @@ javac -d classes android/opengl/EGL14.java \ android/opengl/GLES30.java \ android/opengl/GLES31.java \ android/opengl/GLES31Ext.java \ - android/opengl/GLES32.java + android/opengl/GLES32.java \ + android/annotation/UnsupportedAppUsage.java popd > /dev/null JAVA_RESULT=$? if [ $JAVA_RESULT -ne 0 ]; then @@ -141,7 +147,7 @@ compareGenerated() { echo SAID_PLEASE=1 fi - echo " cp $2/$3 $1" + echo " cp $2/$3 $1/$3" echo " (cd $1; git add $3)" KEEP_GENERATED=1 fi @@ -155,13 +161,13 @@ do compareGenerated ../../../../base/opengl/java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x done -for x in EGL14 EGLExt GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30 GLES31 GLES31Ext GLES32 +for x in EGL14 EGL15 EGLExt GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30 GLES31 GLES31Ext GLES32 do compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java compareGenerated ../../../../base/core/jni generated/C android_opengl_${x}.cpp done -for x in EGLConfig EGLContext EGLDisplay EGLObjectHandle EGLSurface +for x in EGLConfig EGLContext EGLDisplay EGLObjectHandle EGLSurface EGLImage EGLSync do compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java done diff --git a/opengl/tools/glgen/specs/egl/EGL15.spec b/opengl/tools/glgen/specs/egl/EGL15.spec new file mode 100644 index 0000000000..e0aad30f3c --- /dev/null +++ b/opengl/tools/glgen/specs/egl/EGL15.spec @@ -0,0 +1,14 @@ +EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list ) +EGLBoolean eglDestroySync ( EGLDisplay dpy, EGLSync sync ) +EGLint eglClientWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout ) +EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value ) +// NOTE: native_display isn't actually an EGLAttrib. Using EGLAttrib +// so that the generate creates mostly correct code (do not want a buffer) +// have to manually change cast to (void *) in generated code that calls +// the native function. +EGLDisplay eglGetPlatformDisplay ( EGLenum platform, EGLAttrib native_display, const EGLAttrib *attrib_list ) +EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list ) +EGLSurface eglCreatePlatformPixmapSurface ( EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list ) +EGLBoolean eglWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags ) +EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list ) +EGLBoolean eglDestroyImage ( EGLDisplay dpy, EGLImage image ) diff --git a/opengl/tools/glgen/specs/egl/checks.spec b/opengl/tools/glgen/specs/egl/checks.spec index ae531eef78..e2bae482d5 100644 --- a/opengl/tools/glgen/specs/egl/checks.spec +++ b/opengl/tools/glgen/specs/egl/checks.spec @@ -11,3 +11,5 @@ eglQuerySurface check value 1 //STUB function: eglCreatePbufferFromClientBuffer nullAllowed attrib_list sentinel attrib_list EGL_NONE eglCreateContext sentinel attrib_list EGL_NONE eglQueryContext check value 1 +//unsupported: eglCreatePlatformPixmapSurface nullAllowed attrib_list sentinel attrib_list EGL_NONE +eglCreatePlatformPixmapSurface unsupported diff --git a/opengl/tools/glgen/src/CType.java b/opengl/tools/glgen/src/CType.java index aba98afb95..b1f8e0580d 100644 --- a/opengl/tools/glgen/src/CType.java +++ b/opengl/tools/glgen/src/CType.java @@ -57,7 +57,9 @@ public class CType { if(baseType.equals("EGLContext") || baseType.equals("EGLConfig") || baseType.equals("EGLSurface") - || baseType.equals("EGLDisplay")) { + || baseType.equals("EGLDisplay") + || baseType.equals("EGLImage") + || baseType.equals("EGLSync")) { return true; } return false; diff --git a/opengl/tools/glgen/src/GenerateEGL.java b/opengl/tools/glgen/src/GenerateEGL.java index 2ef3970299..57958c6ef2 100644 --- a/opengl/tools/glgen/src/GenerateEGL.java +++ b/opengl/tools/glgen/src/GenerateEGL.java @@ -84,7 +84,7 @@ public class GenerateEGL { ParameterChecker checker = new ParameterChecker(checksReader); - for(String suffix: new String[] {"EGL14", "EGLExt"}) { + for(String suffix: new String[] {"EGL14", "EGL15", "EGLExt"}) { BufferedReader specReader = new BufferedReader(new FileReader( "specs/egl/" + suffix + ".spec")); String egljFilename = "android/opengl/" + suffix + ".java"; diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java index 7f08503fa6..0b4401ad99 100644 --- a/opengl/tools/glgen/src/JType.java +++ b/opengl/tools/glgen/src/JType.java @@ -60,12 +60,16 @@ public class JType { typeMapping.put(new CType("EGLNativeDisplayType"), new JType("long")); typeMapping.put(new CType("EGLClientBuffer"), new JType("long")); typeMapping.put(new CType("EGLnsecsANDROID"), new JType("long")); + typeMapping.put(new CType("EGLAttrib"), new JType("long")); + typeMapping.put(new CType("EGLTime"), new JType("long")); // EGL nonprimitive types typeMapping.put(new CType("EGLConfig"), new JType("EGLConfig", true, false)); typeMapping.put(new CType("EGLContext"), new JType("EGLContext", true, false)); typeMapping.put(new CType("EGLDisplay"), new JType("EGLDisplay", true, false)); typeMapping.put(new CType("EGLSurface"), new JType("EGLSurface", true, false)); + typeMapping.put(new CType("EGLImage"), new JType("EGLImage", true, false)); + typeMapping.put(new CType("EGLSync"), new JType("EGLSync", true, false)); // Untyped pointers map to untyped Buffers @@ -139,6 +143,8 @@ public class JType { arrayTypeMapping.put(new CType("EGLint", true, true), new JType("int", false, true)); arrayTypeMapping.put(new CType("EGLConfig", false, true), new JType("EGLConfig", true, true)); arrayTypeMapping.put(new CType("EGLConfig", true, true), new JType("EGLConfig", true, true)); + arrayTypeMapping.put(new CType("EGLAttrib", false, true), new JType("long", false, true)); + arrayTypeMapping.put(new CType("EGLAttrib", true, true), new JType("long", false, true)); } diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java index e8691bb7f8..9c80212011 100644 --- a/opengl/tools/glgen/src/JniCodeEmitter.java +++ b/opengl/tools/glgen/src/JniCodeEmitter.java @@ -103,6 +103,12 @@ public class JniCodeEmitter { if (cfunc.hasEGLHandleArg()) { return; } + // eglGetPlatformDisplay does not have any EGLHandleArgs + // but we do not want to create IOBuffers of this, so + // exit + if (cfunc.getName().equals("eglGetPlatformDisplay")) { + return; + } } jfunc = JFunc.convert(cfunc, false); @@ -769,6 +775,19 @@ public class JniCodeEmitter { } } + String getJniDefaultReturn(JType jType) { + if (jType.isPrimitive()) { + String baseType = jType.getBaseType(); + if (baseType.equals("boolean")) { + return "JNI_FALSE"; + } else { + return "(" + getJniType(jType) + ")0"; + } + } else { + return "nullptr"; + } + } + String getJniMangledName(String name) { name = name.replaceAll("_", "_1"); name = name.replaceAll(";", "_2"); @@ -937,15 +956,15 @@ public class JniCodeEmitter { "jniThrowException(_env, \"java/lang/UnsupportedOperationException\","); out.println(indent + " \"" + cfunc.getName() + "\");"); - if (!isVoid) { - String retval = getErrorReturnValue(cfunc); + if (isVoid) { + out.println(indent + "return;"); + } else { if (cfunc.getType().isEGLHandle()) { String baseType = cfunc.getType().getBaseType().toLowerCase(); - out.println(indent + - "return toEGLHandle(_env, " + baseType + "Class, " + - baseType + "Constructor, " + retval + ");"); + out.println(indent + indent + "return nullptr;"); } else { - out.println(indent + "return " + retval + ";"); + out.println(indent + indent + "return " + + getJniDefaultReturn(jfunc.getType()) + ";"); } } out.println("}"); @@ -1589,8 +1608,17 @@ public class JniCodeEmitter { out.println(indent + "if (_exception) {"); out.println(indent + indent + "jniThrowException(_env, _exceptionType, _exceptionMessage);"); - out.println(indent + "}"); + if (!isVoid) { + if (cfunc.getType().isEGLHandle()) { + String baseType = cfunc.getType().getBaseType().toLowerCase(); + out.println(indent + indent + "return nullptr;"); + } else { + out.println(indent + indent + "return " + + getJniDefaultReturn(jfunc.getType()) + ";"); + } + } + out.println(indent + "}"); } diff --git a/opengl/tools/glgen/static/egl/EGLImage.java b/opengl/tools/glgen/static/egl/EGLImage.java new file mode 100644 index 0000000000..731ce72aa0 --- /dev/null +++ b/opengl/tools/glgen/static/egl/EGLImage.java @@ -0,0 +1,37 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.opengl; + +/** + * Wrapper class for native EGLImage objects. + * + */ +public class EGLImage extends EGLObjectHandle { + private EGLImage(long handle) { + super(handle); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EGLImage)) return false; + + EGLImage that = (EGLImage) o; + return getNativeHandle() == that.getNativeHandle(); + } +} diff --git a/opengl/tools/glgen/static/egl/EGLSync.java b/opengl/tools/glgen/static/egl/EGLSync.java new file mode 100644 index 0000000000..472f9e7125 --- /dev/null +++ b/opengl/tools/glgen/static/egl/EGLSync.java @@ -0,0 +1,37 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.opengl; + +/** + * Wrapper class for native EGLSync objects. + * + */ +public class EGLSync extends EGLObjectHandle { + private EGLSync(long handle) { + super(handle); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EGLSync)) return false; + + EGLSync that = (EGLSync) o; + return getNativeHandle() == that.getNativeHandle(); + } +} diff --git a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if index f3bf220bf9..12728f588f 100644 --- a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if +++ b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if @@ -18,6 +18,7 @@ package android.opengl; +import android.annotation.UnsupportedAppUsage; import android.graphics.SurfaceTexture; import android.view.Surface; import android.view.SurfaceView; diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp index f90e3ec590..93203fd529 100644 --- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp +++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp @@ -35,8 +35,6 @@ #include <ui/ANativeObjectBase.h> -static int initialized = 0; - static jclass egldisplayClass; static jclass eglcontextClass; static jclass eglsurfaceClass; @@ -107,6 +105,7 @@ fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) { if (obj == NULL){ jniThrowException(_env, "java/lang/IllegalArgumentException", "Object is set to null."); + return nullptr; } jlong handle = _env->CallLongMethod(obj, mid); diff --git a/opengl/tools/glgen/stubs/egl/EGL15Header.java-if b/opengl/tools/glgen/stubs/egl/EGL15Header.java-if new file mode 100644 index 0000000000..859380f6fc --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/EGL15Header.java-if @@ -0,0 +1,78 @@ +/* +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.opengl; + +/** + * EGL 1.5 + * + */ +public final class EGL15 { + + private EGL15() {}; + + public static final int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT = 0x00000001; + public static final int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT = 0x00000002; + public static final int EGL_OPENGL_ES3_BIT = 0x00000040; + public static final int EGL_SYNC_FLUSH_COMMANDS_BIT = 0x0001; + public static final int EGL_GL_COLORSPACE_SRGB = 0x3089; + public static final int EGL_GL_COLORSPACE_LINEAR = 0x308A; + public static final int EGL_CONTEXT_MAJOR_VERSION = 0x3098; + public static final int EGL_CL_EVENT_HANDLE = 0x309C; + public static final int EGL_GL_COLORSPACE = 0x309D; + public static final int EGL_GL_TEXTURE_2D = 0x30B1; + public static final int EGL_GL_TEXTURE_3D = 0x30B2; + public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x30B3; + public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x30B4; + public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x30B5; + public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x30B6; + public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x30B7; + public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x30B8; + public static final int EGL_GL_RENDERBUFFER = 0x30B9; + public static final int EGL_GL_TEXTURE_LEVEL = 0x30BC; + public static final int EGL_GL_TEXTURE_ZOFFSET = 0x30BD; + public static final int EGL_IMAGE_PRESERVED = 0x30D2; + public static final int EGL_SYNC_PRIOR_COMMANDS_COMPLETE = 0x30F0; + public static final int EGL_SYNC_STATUS = 0x30F1; + public static final int EGL_SIGNALED = 0x30F2; + public static final int EGL_UNSIGNALED = 0x30F3; + public static final int EGL_TIMEOUT_EXPIRED = 0x30F5; + public static final int EGL_CONDITION_SATISFIED = 0x30F6; + public static final int EGL_SYNC_TYPE = 0x30F7; + public static final int EGL_SYNC_CONDITION = 0x30F8; + public static final int EGL_SYNC_FENCE = 0x30F9; + public static final int EGL_CONTEXT_MINOR_VERSION = 0x30FB; + public static final int EGL_CONTEXT_OPENGL_PROFILE_MASK = 0x30FD; + public static final int EGL_SYNC_CL_EVENT = 0x30FE; + public static final int EGL_SYNC_CL_EVENT_COMPLETE = 0x30FF; + public static final int EGL_CONTEXT_OPENGL_DEBUG = 0x31B0; + public static final int EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE = 0x31B1; + public static final int EGL_CONTEXT_OPENGL_ROBUST_ACCESS = 0x31B2; + public static final int EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY = 0x31BD; + public static final int EGL_NO_RESET_NOTIFICATION = 0x31BE; + public static final int EGL_LOSE_CONTEXT_ON_RESET = 0x31BF; + public static final int EGL_PLATFORM_ANDROID_KHR = 0x3141; + public static final long EGL_FOREVER = 0xFFFFFFFFFFFFFFFFL; + public static final EGLImage EGL_NO_IMAGE = null; + public static final EGLSync EGL_NO_SYNC = null; + public static final EGLContext EGL_NO_CONTEXT = null; + public static final EGLDisplay EGL_NO_DISPLAY = null; + public static final EGLSurface EGL_NO_SURFACE = null; + + native private static void _nativeClassInit(); + static { + _nativeClassInit(); + } diff --git a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp new file mode 100644 index 0000000000..1c53c9e8e2 --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp @@ -0,0 +1,209 @@ +/* +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +// This source file is automatically generated + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-function" + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> +#include <utils/misc.h> + +#include <assert.h> +#include <EGL/egl.h> + +#include <ui/ANativeObjectBase.h> + +// classes from EGL 1.4 +static jclass egldisplayClass; +static jclass eglsurfaceClass; +static jclass eglconfigClass; +static jclass eglcontextClass; +static jclass bufferClass; +static jclass nioAccessClass; + +static jfieldID positionID; +static jfieldID limitID; +static jfieldID elementSizeShiftID; + +static jmethodID getBasePointerID; +static jmethodID getBaseArrayID; +static jmethodID getBaseArrayOffsetID; + +static jmethodID egldisplayGetHandleID; +static jmethodID eglconfigGetHandleID; +static jmethodID eglcontextGetHandleID; +static jmethodID eglsurfaceGetHandleID; + +static jmethodID egldisplayConstructor; +static jmethodID eglcontextConstructor; +static jmethodID eglsurfaceConstructor; +static jmethodID eglconfigConstructor; + +static jobject eglNoContextObject; +static jobject eglNoDisplayObject; +static jobject eglNoSurfaceObject; + +// classes from EGL 1.5 +static jclass eglimageClass; +static jclass eglsyncClass; + +static jmethodID eglimageGetHandleID; +static jmethodID eglsyncGetHandleID; + +static jmethodID eglimageConstructor; +static jmethodID eglsyncConstructor; + +static jobject eglNoImageObject; +static jobject eglNoSyncObject; + +/* Cache method IDs each time the class is loaded. */ + +static void +nativeClassInit(JNIEnv *_env, jclass glImplClass) +{ + // EGL 1.4 Init + jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig"); + eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal); + jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext"); + eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal); + jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay"); + egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal); + jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface"); + eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal); + + eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J"); + eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J"); + egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J"); + eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J"); + + eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V"); + eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V"); + egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V"); + eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V"); + + jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT)); + eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject); + jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY)); + eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject); + jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE)); + eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject); + + jclass eglClass = _env->FindClass("android/opengl/EGL15"); + jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;"); + _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject); + + jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;"); + _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject); + + jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;"); + _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject); + + // EGL 1.5 init + jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess"); + nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal); + + jclass bufferClassLocal = _env->FindClass("java/nio/Buffer"); + bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal); + + getBasePointerID = _env->GetStaticMethodID(nioAccessClass, + "getBasePointer", "(Ljava/nio/Buffer;)J"); + getBaseArrayID = _env->GetStaticMethodID(nioAccessClass, + "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;"); + getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass, + "getBaseArrayOffset", "(Ljava/nio/Buffer;)I"); + + positionID = _env->GetFieldID(bufferClass, "position", "I"); + limitID = _env->GetFieldID(bufferClass, "limit", "I"); + elementSizeShiftID = + _env->GetFieldID(bufferClass, "_elementSizeShift", "I"); + + jclass eglimageClassLocal = _env->FindClass("android/opengl/EGLImage"); + eglimageClass = (jclass) _env->NewGlobalRef(eglimageClassLocal); + jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync"); + eglsyncClass = (jclass) _env->NewGlobalRef(eglsyncClassLocal); + + eglimageGetHandleID = _env->GetMethodID(eglimageClass, "getNativeHandle", "()J"); + eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J"); + + eglimageConstructor = _env->GetMethodID(eglimageClass, "<init>", "(J)V"); + eglsyncConstructor = _env->GetMethodID(eglsyncClass, "<init>", "(J)V"); + + jfieldID noImageFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_IMAGE", "Landroid/opengl/EGLImage;"); + _env->SetStaticObjectField(eglClass, noImageFieldID, eglNoImageObject); + + jfieldID noSyncFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SYNC", "Landroid/opengl/EGLSync;"); + _env->SetStaticObjectField(eglClass, noSyncFieldID, eglNoSyncObject); +} + +static void * +getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset) +{ + jint position; + jint limit; + jint elementSizeShift; + jlong pointer; + + position = _env->GetIntField(buffer, positionID); + limit = _env->GetIntField(buffer, limitID); + elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID); + *remaining = (limit - position) << elementSizeShift; + pointer = _env->CallStaticLongMethod(nioAccessClass, + getBasePointerID, buffer); + if (pointer != 0L) { + *array = NULL; + return reinterpret_cast<void*>(pointer); + } + + *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass, + getBaseArrayID, buffer); + *offset = _env->CallStaticIntMethod(nioAccessClass, + getBaseArrayOffsetID, buffer); + + return NULL; +} + +static void +releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) +{ + _env->ReleasePrimitiveArrayCritical(array, data, + commit ? 0 : JNI_ABORT); +} + +static void * +fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) { + if (obj == NULL) { + jniThrowException(_env, "java/lang/IllegalArgumentException", + "Object is set to null."); + return nullptr; + } + + jlong handle = _env->CallLongMethod(obj, mid); + return reinterpret_cast<void*>(handle); +} + +static jobject +toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void *handle) { + if (cls == eglimageClass && (EGLImage)handle == EGL_NO_IMAGE) { + return eglNoImageObject; + } + + return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle)); +} + +// -------------------------------------------------------------------------- diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp index 12b96f40d7..b3b069082a 100644 --- a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp +++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp @@ -36,8 +36,6 @@ #include <ui/ANativeObjectBase.h> -static int initialized = 0; - static jclass egldisplayClass; static jclass eglcontextClass; static jclass eglsurfaceClass; @@ -104,6 +102,7 @@ fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) { if (obj == NULL){ jniThrowException(_env, "java/lang/IllegalArgumentException", "Object is set to null."); + return nullptr; } return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid)); diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp index 497d284727..f22986054e 100755 --- a/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp +++ b/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp @@ -54,6 +54,7 @@ exit: } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); + return nullptr; } return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue); } diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp index 3eacf3c3cd..2e146a8044 100644 --- a/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp +++ b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp @@ -4,6 +4,6 @@ android_eglCreatePixmapSurface (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jint pixmap, jintArray attrib_list_ref, jint offset) { jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglCreatePixmapSurface"); - return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0); + return nullptr; } diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp index 355c4b0456..7c255ed106 100644 --- a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp +++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp @@ -67,6 +67,7 @@ exit: } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); + return nullptr; } return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue); } @@ -149,6 +150,7 @@ exit: } if (_exception) { jniThrowException(_env, _exceptionType, _exceptionMessage); + return nullptr; } return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue); } diff --git a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java index 7532abf3a1..85f743d815 100755 --- a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java +++ b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java @@ -7,6 +7,7 @@ /** * {@hide} */ + @UnsupportedAppUsage public static native EGLDisplay eglGetDisplay( long display_id ); diff --git a/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp new file mode 100644 index 0000000000..3a6176f09c --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp @@ -0,0 +1,47 @@ +/* EGLDisplay eglGetPlatformDisplay ( EGLenum platform, EGLAttrib native_display, const EGLAttrib *attrib_list ) */ +static jobject +android_eglGetPlatformDisplay + (JNIEnv *_env, jobject _this, jint platform, jlong native_display, jlongArray attrib_list_ref, jint offset) { + jint _exception = 0; + const char * _exceptionType = NULL; + const char * _exceptionMessage = NULL; + EGLDisplay _returnValue = (EGLDisplay) 0; + EGLAttrib *attrib_list_base = (EGLAttrib *) 0; + jint _remaining; + EGLAttrib *attrib_list = (EGLAttrib *) 0; + + if (!attrib_list_ref) { + _exception = 1; + _exceptionType = "java/lang/IllegalArgumentException"; + _exceptionMessage = "attrib_list == null"; + goto exit; + } + if (offset < 0) { + _exception = 1; + _exceptionType = "java/lang/IllegalArgumentException"; + _exceptionMessage = "offset < 0"; + goto exit; + } + _remaining = _env->GetArrayLength(attrib_list_ref) - offset; + attrib_list_base = (EGLAttrib *) + _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0); + attrib_list = attrib_list_base + offset; + + _returnValue = eglGetPlatformDisplay( + (EGLenum)platform, + (void *)native_display, + (EGLAttrib *)attrib_list + ); + +exit: + if (attrib_list_base) { + _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base, + JNI_ABORT); + } + if (_exception) { + jniThrowException(_env, _exceptionType, _exceptionMessage); + return nullptr; + } + return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue); +} + diff --git a/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.java b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.java new file mode 100644 index 0000000000..28945e8247 --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.java @@ -0,0 +1,9 @@ + // C function EGLDisplay eglGetPlatformDisplay ( EGLenum platform, EGLAttrib native_display, const EGLAttrib *attrib_list ) + + public static native EGLDisplay eglGetPlatformDisplay( + int platform, + long native_display, + long[] attrib_list, + int offset + ); + diff --git a/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.nativeReg b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.nativeReg new file mode 100644 index 0000000000..8a309bf0a2 --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.nativeReg @@ -0,0 +1 @@ +{"eglGetPlatformDisplay", "(IJ[JI)Landroid/opengl/EGLDisplay;", (void *) android_eglGetPlatformDisplay }, diff --git a/opengl/tools/glgen/stubs/gles11/GLES20Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES20Header.java-if index 9ce6728e04..c2711aa4db 100644 --- a/opengl/tools/glgen/stubs/gles11/GLES20Header.java-if +++ b/opengl/tools/glgen/stubs/gles11/GLES20Header.java-if @@ -19,6 +19,8 @@ package android.opengl; +import android.annotation.UnsupportedAppUsage; + /** OpenGL ES 2.0 */ public class GLES20 { diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp index 2163d7600d..51e62ed393 100644 --- a/opengl/tools/glgen/stubs/gles11/common.cpp +++ b/opengl/tools/glgen/stubs/gles11/common.cpp @@ -4,8 +4,6 @@ #include <utils/misc.h> #include <assert.h> -static int initialized = 0; - static jclass nioAccessClass; static jclass bufferClass; static jmethodID getBasePointerID; diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.java b/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.java index d66200f4f0..b297b7a821 100644 --- a/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.java +++ b/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.java @@ -17,6 +17,7 @@ // C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) /** @hide Method is broken, but used to be public (b/6006380) */ + @UnsupportedAppUsage public static native void glGetActiveAttrib( int program, int index, diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.java b/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.java index 8c8d5a2bf9..f211440365 100644 --- a/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.java +++ b/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.java @@ -17,6 +17,7 @@ // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name ) /** @hide Method is broken, but used to be public (b/6006380) */ + @UnsupportedAppUsage public static native void glGetActiveUniform( int program, int index, diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp index 29296ff6a9..c808fe9681 100644 --- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp +++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp @@ -64,8 +64,6 @@ GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, GLsizei count); } -static int initialized = 0; - static jclass nioAccessClass; static jclass bufferClass; static jclass G11ImplClass; diff --git a/opengl/tools/glgen2/glgen.py b/opengl/tools/glgen2/glgen.py index fa981a89a7..86fa28fb1f 100755 --- a/opengl/tools/glgen2/glgen.py +++ b/opengl/tools/glgen2/glgen.py @@ -250,6 +250,27 @@ if __name__ == '__main__': for opts in TRAMPOLINE_OPTIONS: registry.apiGen(opts) + # Generate a GLESv1_CM entries separately to avoid extra driver loading time + apigen = ApiGenerator() + registry.setGenerator(apigen) + API_OPTIONS = [ + # Generate non-extension versions of each API first, then extensions, + # so that if an extension enum was later standardized, we see the non- + # suffixed version first. + reg.GeneratorOptions( + apiname = 'gles1', + profile = 'common'), + reg.GeneratorOptions( + apiname = 'gles1', + profile = 'common', + emitversions = None, + defaultExtensions = 'gles1')] + for opts in API_OPTIONS: + registry.apiGen(opts) + apigen.finish() + with open('../../libs/entries_gles1.in', 'w') as f: + apigen.writeEntries(f) + apigen = ApiGenerator() registry.setGenerator(apigen) API_OPTIONS = [ diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml index e422e96557..8d661aea43 100644 --- a/opengl/tools/glgen2/registry/egl.xml +++ b/opengl/tools/glgen2/registry/egl.xml @@ -801,7 +801,9 @@ <enum value="0x3361" name="EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT"/> <enum value="0x3362" name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/> <enum value="0x3363" name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/> - <unused start="0x3364" end="0x339F"/> + <enum value="0x3364" name="EGL_SYNC_CLIENT_EXT"/> + <enum value="0x3365" name="EGL_SYNC_CLIENT_SIGNAL_EXT"/> + <unused start="0x3366" end="0x339F"/> </enums> <enums namespace="EGL" start="0x33A0" end="0x33AF" vendor="ANGLE" comment="Reserved for Shannon Woods (Bug 13175)"> @@ -887,6 +889,15 @@ <enum value="0x3471" name="EGL_IMPORT_IMPLICIT_SYNC_EXT"/> <enum value="0x3472" name="EGL_IMPORT_EXPLICIT_SYNC_EXT"/> </enums> + <enums namespace="EGL" start="0x3480" end="0x348F" vendor="ANGLE" comment="Reserved for Courtney Goeltzenleuchter - ANGLE (gitlab EGL bug 7)"> + <enum value="0x3480" name="EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE"/> + <unused start="0x3481" end="0x348F"/> + </enums> + + <enums namespace="EGL" start="0x3490" end="0x349F" vendor="EXT" comment="Reserved for Courtney Goeltzenleuchter - Android (gitlab EGL bug 69)"> + <enum value="0x3490" name="EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"/> + <unused start="0x3491" end="0x349F"/> + </enums> <!-- Please remember that new enumerant allocations must be obtained by request to the Khronos API registrar (see comments at the top of this @@ -897,8 +908,8 @@ <!-- Reservable for future use. To generate a new range, allocate multiples of 16 starting at the lowest available point in this block. --> - <enums namespace="EGL" start="0x3480" end="0x3FFF" vendor="KHR" comment="Reserved for future use"> - <unused start="0x3480" end="0x3FFF"/> + <enums namespace="EGL" start="0x34A0" end="0x3FFF" vendor="KHR" comment="Reserved for future use"> + <unused start="0x34A0" end="0x3FFF"/> </enums> <enums namespace="EGL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with GL."> @@ -930,6 +941,12 @@ <param><ptype>EGLint</ptype> *<name>num_config</name></param> </command> <command> + <proto><ptype>EGLBoolean</ptype> <name>eglClientSignalSyncEXT</name></proto> + <param><ptype>EGLDisplay</ptype> <name>dpy</name></param> + <param><ptype>EGLSync</ptype> <name>sync</name></param> + <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param> + </command> + <command> <proto><ptype>EGLint</ptype> <name>eglClientWaitSync</name></proto> <param><ptype>EGLDisplay</ptype> <name>dpy</name></param> <param><ptype>EGLSync</ptype> <name>sync</name></param> @@ -1647,6 +1664,11 @@ <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param> </command> <command> + <proto><ptype>EGLBoolean</ptype> <name>eglStreamFlushNV</name></proto> + <param><ptype>EGLDisplay</ptype> <name>dpy</name></param> + <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param> + </command> + <command> <proto><ptype>EGLBoolean</ptype> <name>eglSurfaceAttrib</name></proto> <param><ptype>EGLDisplay</ptype> <name>dpy</name></param> <param><ptype>EGLSurface</ptype> <name>surface</name></param> @@ -1701,6 +1723,12 @@ <param><ptype>EGLSurface</ptype> <name>surface</name></param> </command> <command> + <proto><ptype>EGLBoolean</ptype> <name>eglUnsignalSyncEXT</name></proto> + <param><ptype>EGLDisplay</ptype> <name>dpy</name></param> + <param><ptype>EGLSync</ptype> <name>sync</name></param> + <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param> + </command> + <command> <proto><ptype>EGLBoolean</ptype> <name>eglWaitClient</name></proto> </command> <command> @@ -2146,6 +2174,13 @@ </require> </extension> <extension name="EGL_EXT_client_extensions" supported="egl"/> + <extension name="EGL_EXT_client_sync" supported="egl"> + <require> + <enum name="EGL_SYNC_CLIENT_EXT"/> + <enum name="EGL_SYNC_CLIENT_SIGNAL_EXT"/> + <command name="eglClientSignalSyncEXT"/> + </require> + </extension> <extension name="EGL_EXT_create_context_robustness" supported="egl"> <require> <enum name="EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT"/> @@ -2220,6 +2255,11 @@ <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/> </require> </extension> + <extension name="EGL_EXT_gl_colorspace_display_p3_passthrough" supported="egl"> + <require> + <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"/> + </require> + </extension> <extension name="EGL_EXT_image_dma_buf_import" supported="egl"> <require> <enum name="EGL_LINUX_DMA_BUF_EXT"/> @@ -2371,6 +2411,11 @@ <command name="eglSwapBuffersWithDamageEXT"/> </require> </extension> + <extension name="EGL_EXT_sync_reuse" supported="egl"> + <require> + <command name="eglUnsignalSyncEXT"/> + </require> + </extension> <extension name="EGL_EXT_yuv_surface" supported="egl"> <require> <enum name="EGL_YUV_ORDER_EXT"/> @@ -2932,6 +2977,11 @@ <enum name="EGL_STREAM_FIFO_SYNCHRONOUS_NV"/> </require> </extension> + <extension name="EGL_NV_stream_flush" supported="egl"> + <require> + <command name="eglStreamFlushNV"/> + </require> + </extension> <extension name="EGL_NV_stream_frame_limits" supported="egl"> <require> <enum name="EGL_PRODUCER_MAX_FRAME_HINT_NV"/> |