summaryrefslogtreecommitdiff
path: root/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'opengl')
-rw-r--r--opengl/include/EGL/Platform.h338
-rw-r--r--opengl/include/EGL/egl.h66
-rw-r--r--opengl/include/EGL/eglext.h51
-rw-r--r--opengl/include/EGL/eglext_angle.h191
-rw-r--r--opengl/include/EGL/eglplatform.h36
-rw-r--r--opengl/libs/Android.bp7
-rw-r--r--opengl/libs/EGL/BlobCache.cpp6
-rw-r--r--opengl/libs/EGL/BlobCache.h4
-rw-r--r--opengl/libs/EGL/BlobCache_test.cpp10
-rw-r--r--opengl/libs/EGL/FileBlobCache.cpp2
-rw-r--r--opengl/libs/EGL/GLES_layers.md258
-rw-r--r--opengl/libs/EGL/Loader.cpp539
-rw-r--r--opengl/libs/EGL/Loader.h11
-rw-r--r--opengl/libs/EGL/egl.cpp62
-rw-r--r--opengl/libs/EGL/eglApi.cpp2338
-rw-r--r--opengl/libs/EGL/egl_angle_platform.cpp146
-rw-r--r--opengl/libs/EGL/egl_angle_platform.h33
-rw-r--r--opengl/libs/EGL/egl_cache.cpp4
-rw-r--r--opengl/libs/EGL/egl_display.cpp214
-rw-r--r--opengl/libs/EGL/egl_display.h6
-rw-r--r--opengl/libs/EGL/egl_entries.in16
-rw-r--r--opengl/libs/EGL/egl_layers.cpp444
-rw-r--r--opengl/libs/EGL/egl_layers.h65
-rw-r--r--opengl/libs/EGL/egl_object.cpp10
-rw-r--r--opengl/libs/EGL/egl_object.h2
-rw-r--r--opengl/libs/EGL/egl_platform_entries.cpp2736
-rw-r--r--opengl/libs/EGL/egl_platform_entries.h32
-rw-r--r--opengl/libs/EGL/egl_tls.cpp40
-rw-r--r--opengl/libs/EGL/egl_tls.h1
-rw-r--r--opengl/libs/EGL/egldefs.h42
-rw-r--r--opengl/libs/GLES2/gl2.cpp64
-rw-r--r--opengl/libs/egl_impl.h3
-rw-r--r--opengl/libs/hooks.h4
-rw-r--r--opengl/libs/libEGL.map.txt10
-rw-r--r--opengl/libs/platform_entries.in86
-rwxr-xr-xopengl/libs/tools/genfiles50
-rwxr-xr-xopengl/libs/tools/glapigen76
-rwxr-xr-xopengl/libs/tools/glentrygen38
-rwxr-xr-xopengl/libs/tools/glenumsgen38
-rw-r--r--opengl/specs/EGL_ANDROID_GLES_layers.txt64
-rw-r--r--opengl/specs/README5
-rw-r--r--opengl/tests/EGLTest/EGL_test.cpp55
-rw-r--r--opengl/tests/lib/WindowSurface.cpp10
-rw-r--r--opengl/tests/lib/glTestLib.cpp2
-rw-r--r--opengl/tests/lib/include/EGLUtils.h10
-rwxr-xr-xopengl/tools/glgen/gen14
-rw-r--r--opengl/tools/glgen/specs/egl/EGL15.spec15
-rw-r--r--opengl/tools/glgen/specs/egl/checks.spec2
-rw-r--r--opengl/tools/glgen/src/CType.java4
-rw-r--r--opengl/tools/glgen/src/GenerateEGL.java2
-rw-r--r--opengl/tools/glgen/src/JType.java6
-rw-r--r--opengl/tools/glgen/src/JniCodeEmitter.java42
-rw-r--r--opengl/tools/glgen/static/egl/EGLImage.java37
-rw-r--r--opengl/tools/glgen/static/egl/EGLSync.java37
-rw-r--r--opengl/tools/glgen/stubs/egl/EGL14Header.java-if1
-rw-r--r--opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp3
-rw-r--r--opengl/tools/glgen/stubs/egl/EGL15Header.java-if78
-rw-r--r--opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp194
-rw-r--r--opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp3
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateImage.cpp50
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateImage.java11
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg1
-rwxr-xr-xopengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp1
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp2
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.cpp68
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java10
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg1
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateSync.cpp101
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateSync.java22
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg2
-rw-r--r--opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp2
-rwxr-xr-xopengl/tools/glgen/stubs/egl/eglGetDisplay.java1
-rw-r--r--opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp47
-rw-r--r--opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.java9
-rw-r--r--opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.nativeReg1
-rw-r--r--opengl/tools/glgen/stubs/gles11/GLES20Header.java-if2
-rw-r--r--opengl/tools/glgen/stubs/gles11/common.cpp64
-rw-r--r--opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.java1
-rw-r--r--opengl/tools/glgen/stubs/gles11/glGetActiveUniform.java1
-rw-r--r--opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp101
-rw-r--r--opengl/tools/glgen2/registry/egl.xml56
81 files changed, 6472 insertions, 2745 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 75dda6dc61..abc7a72716 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/GLES_layers.md b/opengl/libs/EGL/GLES_layers.md
new file mode 100644
index 0000000000..bfc44dbb69
--- /dev/null
+++ b/opengl/libs/EGL/GLES_layers.md
@@ -0,0 +1,258 @@
+# GLES Layers
+
+## EGL Loader Initialization
+After standard entrypoints have all been populated unmodified, a GLES LayerLoader will be instantiated. If debug layers are enabled, the LayerLoader will scan specified directories for layers, just like the Vulkan loader does.
+
+If layering is enabled, the loader will search for and enumerate a specified layer list. The layer list will be specified by colon separated filenames (see [Enabling layers](#Enabling-layers) below).
+
+The layers will be traversed in the order they are specified, so the first layer will be directly below the application. For each layer, it will track two entrypoints from the layer. `AndroidGLESLayer_Initialize` and `AndroidGLESLayer_GetProcAddress`.
+```cpp
+typedef void* (*PFNEGLGETNEXTLAYERPROCADDRESSPROC)(void*, const char*);
+void* AndroidGLESLayer_Initialize(void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address))
+```
+
+`AndroidGLESLayer_Initialize` is a new function that provides an identifier for the layer to use (layer_id) and an entrypoint that can be called to look up functions below the layer. The entrypoint can be used like so:
+```cpp
+const char* func = "eglFoo";
+void* gpa = get_next_layer_proc_address(layer_id, func);
+```
+
+Note that only GLES2+ entrypoints will be provided. If a layer tries to make independent GLES 1.x calls, they will be routed to GLES2+ libraries, which may not behave as expected. Application calls to 1.x will not be affected.
+
+AndroidGLESLayer_GetProcAddress is a new function designed for this layering system. It takes the address of the next call in the chain that the layer should call when finished. If there is only one layer, next will point directly to the driver for most functions.
+```cpp
+void* AndroidGLESLayer_GetProcAddress(const char *funcName, EGLFuncPointer next)
+```
+
+For each layer found, the GLES LayerLoader will call `AndroidGLESLayer_Initialize`, and then walk libEGL’s function lists and call `AndroidGLESLayer_GetProcAddress` for all known functions. The layer can track that next address with any means it wants. If the layer does not intercept the function, `AndroidGLESLayer_GetProcAddress` must return the same function address it was passed. The LayerLoader will then update the function hook list to point to the layer’s entrypoint.
+
+The layers are not required to do anything with the info provided by `AndroidGLESLayer_Initialize` or get_next_layer_proc_address, but providing them makes it easier for existing layers (like GAPID and RenderDoc) to support Android. That way a layer can look up functions independently (i.e. not wait for calls to `AndroidGLESLayer_GetProcAddress`). Layers must be sure to use gen_next_layer_proc_address if they look up function calls instead of eglGetProcAddress or they will not get an accurate answer. eglGetProcAddress must be passed down the chain to the platform.
+
+## Placing layers
+
+Where layers can be found, in order of priority
+ 1. System location for root
+ This requires root access
+ ```bash
+ adb root
+ adb disable-verity
+ adb reboot
+ adb root
+ adb shell setenforce 0
+ adb shell mkdir -p /data/local/debug/gles
+ adb push <layer>.so /data/local/debug/gles/
+ ```
+
+ 2. Application's base directory
+ Target application must be debuggable, or you must have root access:
+ ```bash
+ adb push libGLTrace.so /data/local/tmp
+ adb shell run-as com.android.gl2jni cp /data/local/tmp/libGLTrace.so .
+ adb shell run-as com.android.gl2jni ls | grep libGLTrace
+ libGLTrace.so
+ ```
+
+ 3. External APK
+ Determine the ABI of your target application, then install an APK containing the layers you wish to load:
+ ```bash
+ adb install --abi armeabi-v7a layers.apk
+ ```
+
+ 4. In the target application's APK
+
+## Enabling layers
+
+### Per application
+Note these settings will persist across reboots:
+```bash
+# Enable layers
+adb shell settings put global enable_gpu_debug_layers 1
+
+# Specify target application
+adb shell settings put global gpu_debug_app <package_name>
+
+# Specify layer list (from top to bottom)
+adb shell settings put global gpu_debug_layers_gles <layer1:layer2:layerN>
+
+# Specify a package to search for layers
+adb shell settings put global gpu_debug_layer_app <layer_package>
+```
+To disable the per-app layers:
+```
+adb shell settings delete global enable_gpu_debug_layers
+adb shell settings delete global gpu_debug_app
+adb shell settings delete global gpu_debug_layers_gles
+adb shell settings delete global gpu_debug_layer_app
+```
+
+### Globally
+These will be cleared on reboot:
+```bash
+# This will attempt to load layers for all applications, including native executables
+adb shell setprop debug.gles.layers <layer1:layer2:layerN>
+```
+
+
+## Creating a layer
+
+Layers must expose the following two functions described above:
+```cpp
+AndroidGLESLayer_Initialize
+AndroidGLESLayer_GetProcAddress
+```
+
+For a simple layer that just wants to intercept a handful of functions, a passively initialized layer is the way to go. It can simply wait for the EGL Loader to initialize the function it cares about. See below for an example of creating a passive layer.
+
+For more formalized layers that need to fully initialize up front, or layers that needs to look up extensions not known to the EGL loader, active layer initialization is the way to go. The layer can utilize get_next_layer_proc_address provided by `AndroidGLESLayer_Initialize` to look up a function at any time. The layer must still respond to `AndroidGLESLayer_GetProcAddress` requests from the loader so the platform knows where to route calls. See below for an example of creating an active layer.
+
+### Example Passive Layer Initialization
+```cpp
+namespace {
+
+std::unordered_map<std::string, EGLFuncPointer> funcMap;
+
+EGLAPI EGLBoolean EGLAPIENTRY glesLayer_eglChooseConfig (
+ EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size,
+ EGLint *num_config) {
+
+ EGLFuncPointer entry = funcMap["eglChooseConfig"];
+
+ typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(
+ EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*);
+
+ PFNEGLCHOOSECONFIGPROC next = reinterpret_cast<PFNEGLCHOOSECONFIGPROC>(entry);
+
+ return next(dpy, attrib_list, configs, config_size, num_config);
+}
+
+EGLAPI EGLFuncPointer EGLAPIENTRY eglGPA(const char* funcName) {
+
+ #define GETPROCADDR(func) if(!strcmp(funcName, #func)) { \
+ return (EGLFuncPointer)glesLayer_##func; }
+
+ GETPROCADDR(eglChooseConfig);
+
+ // Don't return anything for unrecognized functions
+ return nullptr;
+}
+
+EGLAPI void EGLAPIENTRY glesLayer_InitializeLayer(
+ void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address) {
+ // This function is purposefully empty, since this layer does not proactively
+ // look up any entrypoints
+ }
+
+EGLAPI EGLFuncPointer EGLAPIENTRY glesLayer_GetLayerProcAddress(
+ const char* funcName, EGLFuncPointer next) {
+ EGLFuncPointer entry = eglGPA(funcName);
+ if (entry != nullptr) {
+ funcMap[std::string(funcName)] = next;
+ return entry;
+ }
+ return next;
+}
+
+} // namespace
+
+extern "C" {
+ __attribute((visibility("default"))) EGLAPI void AndroidGLESLayer_Initialize(
+ void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address) {
+ return (void)glesLayer_InitializeLayer(layer_id, get_next_layer_proc_address);
+ }
+ __attribute((visibility("default"))) EGLAPI void* AndroidGLESLayer_GetProcAddres(
+ const char *funcName, EGLFuncPointer next) {
+ return (void*)glesLayer_GetLayerProcAddress(funcName, next);
+ }
+}
+```
+
+### Example Active Layer Initialization
+```cpp
+namespace {
+
+std::unordered_map<std::string, EGLFuncPointer> funcMap;
+
+EGLAPI EGLBoolean EGLAPIENTRY glesLayer_eglChooseConfig (
+ EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size,
+ EGLint *num_config) {
+
+ EGLFuncPointer entry = funcMap["eglChooseConfig"];
+
+ typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(
+ EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*);
+
+ PFNEGLCHOOSECONFIGPROC next = reinterpret_cast<PFNEGLCHOOSECONFIGPROC>(entry);
+
+ return next(dpy, attrib_list, configs, config_size, num_config);
+}
+
+EGLAPI EGLFuncPointer EGLAPIENTRY eglGPA(const char* funcName) {
+
+ #define GETPROCADDR(func) if(!strcmp(funcName, #func)) { \
+ return (EGLFuncPointer)glesLayer_##func; }
+
+ GETPROCADDR(eglChooseConfig);
+
+ // Don't return anything for unrecognized functions
+ return nullptr;
+}
+
+EGLAPI void EGLAPIENTRY glesLayer_InitializeLayer(
+ void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address) {
+
+ // Note: This is where the layer would populate its function map with all the
+ // functions it cares about
+ const char* func = “eglChooseConfig”;
+ funcMap[func] = get_next_layer_proc_address(layer_id, func);
+}
+
+EGLAPI EGLFuncPointer EGLAPIENTRY glesLayer_GetLayerProcAddress(
+ const char* funcName, EGLFuncPointer next) {
+ EGLFuncPointer entry = eglGPA(funcName);
+ if (entry != nullptr) {
+ return entry;
+ }
+
+ return next;
+}
+
+} // namespace
+
+extern "C" {
+ __attribute((visibility("default"))) EGLAPI void AndroidGLESLayer_Initialize(
+ void* layer_id, PFNEGLGETNEXTLAYERPROCADDRESSPROC get_next_layer_proc_address) {
+ return (void)glesLayer_InitializeLayer(layer_id, get_next_layer_proc_address);
+ }
+ __attribute((visibility("default"))) EGLAPI void* AndroidGLESLayer_GetProcAddres(
+ const char *funcName, EGLFuncPointer next) {
+ return (void*)glesLayer_GetLayerProcAddress(funcName, next);
+ }
+}
+```
+
+## Caveats
+Only supports GLES 2.0+.
+
+When layering is enabled, GLES 1.x exclusive functions will continue to route to GLES 1.x drivers. But functions shared with GLES 2.0+ (like glGetString) will be routed to 2.0+ drivers, which can cause confusion.
+
+## FAQ
+ - Who can use layers?
+ - GLES Layers can be loaded by any debuggable application, or for any application if you have root access
+ - How do we know if layers are working on a device?
+ - This feature is backed by Android CTS, so you can run `atest CtsGpuToolsHostTestCases`
+ - How does a app determine if this feature is supported?
+ - There are two ways. First you can check against the version of Android.
+ ```bash
+ # Q is the first that will support this, so look for `Q` or 10 for release
+ adb shell getprop ro.build.version.sdk
+ # Or look for the SDK version, which should be 29 for Q
+ adb shell getprop ro.build.version.sdk
+ ```
+ - Secondly, if you want to determine from an application that can't call out to ADB for this, you can check for the [EGL_ANDROID_GLES_layers](../../specs/EGL_ANDROID_GLES_layers.txt). It simply indicates support of this layering system:
+ ```cpp
+ std::string display_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (display_extension.find("EGL_ANDROID_GLES_layers") != std::string::npos)
+ {
+ // Layers are supported!
+ }
+ ```
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 6f050bf831..038a432337 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,23 +27,19 @@
#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"
+#include <EGL/eglext_angle.h>
-extern "C" {
- android_namespace_t* android_get_exported_namespace(const char*);
-}
-
-// ----------------------------------------------------------------------------
namespace android {
-// ----------------------------------------------------------------------------
-
/*
* EGL userspace drivers must be provided either:
@@ -73,41 +69,6 @@ Loader& Loader::getInstance() {
return loader;
}
-/* This function is called to check whether we run inside the emulator,
- * and if this is the case whether GLES GPU emulation is supported.
- *
- * Returned values are:
- * -1 -> not running inside the emulator
- * 0 -> running inside the emulator, but GPU emulation not supported
- * 1 -> running inside the emulator, GPU emulation is supported
- * through the "emulation" host-side OpenGL ES implementation.
- * 2 -> running inside the emulator, GPU emulation is supported
- * through a guest-side vendor driver's OpenGL ES implementation.
- */
-static int
-checkGlesEmulationStatus(void)
-{
- /* We're going to check for the following kernel parameters:
- *
- * qemu=1 -> tells us that we run inside the emulator
- * android.qemu.gles=<number> -> tells us the GLES GPU emulation status
- *
- * Note that we will return <number> if we find it. This let us support
- * more additionnal emulation modes in the future.
- */
- char prop[PROPERTY_VALUE_MAX];
- int result = -1;
-
- /* First, check for qemu=1 */
- property_get("ro.kernel.qemu",prop,"0");
- if (atoi(prop) != 1)
- return -1;
-
- /* We are in the emulator, get GPU status value */
- property_get("qemu.gles",prop,"0");
- return atoi(prop);
-}
-
static void* do_dlopen(const char* path, int mode) {
ATRACE_CALL();
return dlopen(path, mode);
@@ -123,13 +84,16 @@ static void* do_android_load_sphal_library(const char* path, int mode) {
return android_load_sphal_library(path, mode);
}
-// ----------------------------------------------------------------------------
+static int do_android_unload_sphal_library(void* dso) {
+ ATRACE_CALL();
+ return android_unload_sphal_library(dso);
+}
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 +101,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;
}
}
}
@@ -160,10 +124,8 @@ int Loader::driver_t::set(void* hnd, int32_t api)
return 0;
}
-// ----------------------------------------------------------------------------
-
Loader::Loader()
- : getProcAddress(NULL)
+ : getProcAddress(nullptr)
{
}
@@ -216,33 +178,161 @@ static void setEmulatorGlesValue(void) {
}
}
+static const char* DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
+
+static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
+ DRIVER_SUFFIX_PROPERTY,
+ "ro.board.platform",
+};
+
+static bool should_unload_system_driver(egl_connection_t* cnx) {
+ // Return false if the system driver has been unloaded once.
+ if (cnx->systemDriverUnloaded) {
+ return false;
+ }
+
+ // Return true if Angle namespace is set.
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+ if (ns) {
+ return true;
+ }
+
+#ifndef __ANDROID_VNDK__
+ // Return true if updated driver namespace is set.
+ ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ if (ns) {
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
+ while (*api) {
+ *curr++ = nullptr;
+ api++;
+ }
+}
+
+void Loader::unload_system_driver(egl_connection_t* cnx) {
+ ATRACE_CALL();
+
+ uninit_api(gl_names,
+ (__eglMustCastToProperFunctionPointerType*)&cnx
+ ->hooks[egl_connection_t::GLESv2_INDEX]
+ ->gl);
+ uninit_api(gl_names,
+ (__eglMustCastToProperFunctionPointerType*)&cnx
+ ->hooks[egl_connection_t::GLESv1_INDEX]
+ ->gl);
+ uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
+
+ if (cnx->dso) {
+ ALOGD("Unload system gl driver.");
+ driver_t* hnd = (driver_t*)cnx->dso;
+ if (hnd->dso[2]) {
+ do_android_unload_sphal_library(hnd->dso[2]);
+ }
+ if (hnd->dso[1]) {
+ do_android_unload_sphal_library(hnd->dso[1]);
+ }
+ if (hnd->dso[0]) {
+ do_android_unload_sphal_library(hnd->dso[0]);
+ }
+ cnx->dso = nullptr;
+ }
+
+ cnx->systemDriverUnloaded = true;
+}
+
void* Loader::open(egl_connection_t* cnx)
{
ATRACE_CALL();
+ const nsecs_t openTime = systemTime();
- void* dso;
- driver_t* hnd = 0;
+ if (should_unload_system_driver(cnx)) {
+ unload_system_driver(cnx);
+ }
+
+ // If a driver has been loaded, return the driver directly.
+ if (cnx->dso) {
+ return cnx->dso;
+ }
setEmulatorGlesValue();
- dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
- if (dso) {
- hnd = new driver_t(dso);
+ // 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 {
- // Always load EGL first
- dso = load_driver("EGL", cnx, EGL);
- if (dso) {
- hnd = new driver_t(dso);
- hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
- hnd->set( load_driver("GLESv2", cnx, GLESv2), GLESv2 );
+ cnx->shouldUseAngle = false;
+ }
+
+ // Firstly, try to load ANGLE driver.
+ driver_t* hnd = attempt_to_load_angle(cnx);
+ if (!hnd) {
+ // Secondly, try to load from driver apk.
+ hnd = attempt_to_load_updated_driver(cnx);
+ }
+
+ bool failToLoadFromDriverSuffixProperty = false;
+ if (!hnd) {
+ // Finally, try to load system driver, start by searching for the library name appended by
+ // the system properties of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES_${prop}.so, or:
+ // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ hnd = attempt_to_load_system_driver(cnx, prop, true);
+ if (hnd) {
+ break;
+ } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+ failToLoadFromDriverSuffixProperty = true;
+ }
}
}
- LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
+ if (!hnd) {
+ // Can't find graphics driver by appending system properties, now search for the exact name
+ // without any suffix of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES.so, or:
+ // libEGL.so, libGLESv1_CM.so, libGLESv2.so
+ hnd = attempt_to_load_system_driver(cnx, nullptr, true);
+ }
+
+ if (!hnd && !failToLoadFromDriverSuffixProperty) {
+ hnd = attempt_to_load_system_driver(cnx, nullptr, false);
+ }
+
+ 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, make sure you set %s or %s",
+ HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
- 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->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
+ }
+ if (!cnx->libGles1) {
+ cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ }
+ if (!cnx->libGles2) {
+ cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.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");
@@ -250,13 +340,26 @@ void* Loader::open(egl_connection_t* cnx)
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,
@@ -282,11 +385,11 @@ void Loader::init_api(void* dso,
__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"))) {
@@ -296,7 +399,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")) {
@@ -305,7 +408,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;
@@ -328,43 +431,11 @@ void Loader::init_api(void* dso,
}
}
-static void* load_system_driver(const char* kind) {
+static void* load_system_driver(const char* kind, const char* suffix, const bool exact) {
ATRACE_CALL();
class MatchFile {
public:
- static std::string find(const char* kind) {
- std::string result;
- int emulationStatus = checkGlesEmulationStatus();
- switch (emulationStatus) {
- case 0:
-#if defined(__LP64__)
- result = "/vendor/lib64/egl/libGLES_android.so";
-#else
- result = "/vendor/lib/egl/libGLES_android.so";
-#endif
- return result;
- case 1:
- // Use host-side OpenGL through the "emulation" library
-#if defined(__LP64__)
- result = std::string("/vendor/lib64/egl/lib") + kind + "_emulation.so";
-#else
- result = std::string("/vendor/lib/egl/lib") + kind + "_emulation.so";
-#endif
- return result;
- case 2:
- // Use guest side swiftshader library
-#if defined(__LP64__)
- result = std::string("/vendor/lib64/egl/lib") + kind + "_swiftshader.so";
-#else
- result = std::string("/vendor/lib/egl/lib") + kind + "_swiftshader.so";
-#endif
- return result;
- default:
- // Not in emulator, or use other guest-side implementation
- break;
- }
-
- std::string pattern = std::string("lib") + kind;
+ static std::string find(const char* libraryName, const bool exact) {
const char* const searchPaths[] = {
#if defined(__LP64__)
"/vendor/lib64/egl",
@@ -375,35 +446,16 @@ static void* load_system_driver(const char* kind) {
#endif
};
- // first, we search for the exact name of the GLES userspace
- // driver in both locations.
- // i.e.:
- // libGLES.so, or:
- // libEGL.so, libGLESv1_CM.so, libGLESv2.so
-
- for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
- if (find(result, pattern, searchPaths[i], true)) {
- return result;
- }
- }
-
- // for compatibility with the old "egl.cfg" naming convention
- // we look for files that match:
- // libGLES_*.so, or:
- // libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
-
- pattern.append("_");
- for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
- if (find(result, pattern, searchPaths[i], false)) {
- return result;
+ for (auto dir : searchPaths) {
+ std::string absolutePath;
+ if (find(absolutePath, libraryName, dir, exact)) {
+ return absolutePath;
}
}
- // we didn't find the driver. gah.
- result.clear();
- return result;
+ // Driver not found. gah.
+ return std::string();
}
-
private:
static bool find(std::string& result,
const std::string& pattern, const char* const search, bool exact) {
@@ -417,9 +469,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;
}
@@ -441,11 +493,19 @@ static void* load_system_driver(const char* kind) {
}
};
-
- std::string absolutePath = MatchFile::find(kind);
+ std::string libraryName = std::string("lib") + kind;
+ if (suffix) {
+ libraryName += std::string("_") + suffix;
+ } else if (!exact) {
+ // Deprecated: we look for files that match
+ // libGLES_*.so, or:
+ // libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
+ libraryName += std::string("_");
+ }
+ std::string absolutePath = MatchFile::find(libraryName.c_str(), exact);
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();
@@ -455,10 +515,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);
@@ -466,10 +526,88 @@ static void* load_system_driver(const char* kind) {
return dso;
}
-static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
- "ro.hardware.egl",
- "ro.board.platform",
-};
+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) {
+ 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.
+ char prop[PROPERTY_VALUE_MAX + 1];
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ void* dso = load_system_driver("EGL", prop, true);
+ if (dso) {
+ cnx->vendorEGL = dso;
+ break;
+ }
+ }
+ if (!cnx->vendorEGL) {
+ cnx->vendorEGL = load_system_driver("EGL", nullptr, true);
+ }
+ }
+ } 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 void* load_updated_driver(const char* kind, android_namespace_t* ns) {
ATRACE_CALL();
@@ -480,35 +618,110 @@ static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
void* so = nullptr;
char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) > 0) {
- std::string name = std::string("lib") + kind + "_" + prop + ".so";
- so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
- if (so) {
- return so;
- }
+ if (property_get(key, prop, nullptr) <= 0) {
+ continue;
+ }
+ std::string name = std::string("lib") + kind + "_" + prop + ".so";
+ so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ if (so) {
+ return so;
}
}
return nullptr;
}
-void *Loader::load_driver(const char* kind,
- egl_connection_t* cnx, uint32_t mask)
-{
+Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
ATRACE_CALL();
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+ if (!ns) {
+ return nullptr;
+ }
+
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE);
+ driver_t* hnd = nullptr;
+
+ // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
+ void* dso = load_angle("EGL", ns, cnx);
+ if (dso) {
+ initialize_api(dso, cnx, EGL);
+ hnd = new driver_t(dso);
+
+ dso = load_angle("GLESv1_CM", ns, cnx);
+ initialize_api(dso, cnx, GLESv1_CM);
+ hnd->set(dso, GLESv1_CM);
- void* dso = nullptr;
+ dso = load_angle("GLESv2", ns, cnx);
+ initialize_api(dso, cnx, GLESv2);
+ hnd->set(dso, GLESv2);
+ }
+ return hnd;
+}
+
+Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
+ ATRACE_CALL();
#ifndef __ANDROID_VNDK__
- android_namespace_t* ns = android_getDriverNamespace();
- if (ns) {
- dso = load_updated_driver(kind, ns);
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ if (!ns) {
+ return nullptr;
+ }
+
+ ALOGD("Load updated gl driver.");
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED);
+ driver_t* hnd = nullptr;
+ void* dso = load_updated_driver("GLES", ns);
+ if (dso) {
+ initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
+ hnd = new driver_t(dso);
+ return hnd;
+ }
+
+ dso = load_updated_driver("EGL", ns);
+ if (dso) {
+ initialize_api(dso, cnx, EGL);
+ hnd = new driver_t(dso);
+
+ dso = load_updated_driver("GLESv1_CM", ns);
+ initialize_api(dso, cnx, GLESv1_CM);
+ hnd->set(dso, GLESv1_CM);
+
+ dso = load_updated_driver("GLESv2", ns);
+ initialize_api(dso, cnx, GLESv2);
+ hnd->set(dso, GLESv2);
}
+ return hnd;
+#else
+ return nullptr;
#endif
- if (!dso) {
- dso = load_system_driver(kind);
- if (!dso)
- return NULL;
+}
+
+Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
+ const bool exact) {
+ ATRACE_CALL();
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
+ driver_t* hnd = nullptr;
+ void* dso = load_system_driver("GLES", suffix, exact);
+ if (dso) {
+ initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
+ hnd = new driver_t(dso);
+ return hnd;
+ }
+ dso = load_system_driver("EGL", suffix, exact);
+ if (dso) {
+ initialize_api(dso, cnx, EGL);
+ hnd = new driver_t(dso);
+
+ dso = load_system_driver("GLESv1_CM", suffix, exact);
+ initialize_api(dso, cnx, GLESv1_CM);
+ hnd->set(dso, GLESv1_CM);
+
+ dso = load_system_driver("GLESv2", suffix, exact);
+ initialize_api(dso, cnx, GLESv2);
+ hnd->set(dso, GLESv2);
}
+ return hnd;
+}
+void Loader::initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask) {
if (mask & EGL) {
getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
@@ -523,11 +736,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;
@@ -548,10 +761,6 @@ void *Loader::load_driver(const char* kind,
&cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
getProcAddress);
}
-
- return dso;
}
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
+} // namespace android
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index e88d1a285e..6f31ab4741 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -33,7 +33,8 @@ class Loader {
enum {
EGL = 0x01,
GLESv1_CM = 0x02,
- GLESv2 = 0x04
+ GLESv2 = 0x04,
+ PLATFORM = 0x08
};
struct driver_t {
explicit driver_t(void* gles);
@@ -50,11 +51,15 @@ public:
~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);
+ driver_t* attempt_to_load_angle(egl_connection_t* cnx);
+ driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
+ driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
+ void unload_system_driver(egl_connection_t* cnx);
+ void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
void init_api(void* dso,
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 213c8023d9..25b1009ba2 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,12 +187,16 @@ static EGLBoolean egl_init_drivers_locked() {
// dynamically load our EGL implementation
egl_connection_t* cnx = &gEGLImpl;
- if (cnx->dso == 0) {
- cnx->hooks[egl_connection_t::GLESv1_INDEX] =
- &gHooks[egl_connection_t::GLESv1_INDEX];
- cnx->hooks[egl_connection_t::GLESv2_INDEX] =
- &gHooks[egl_connection_t::GLESv2_INDEX];
- cnx->dso = loader.open(cnx);
+ cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX];
+ cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX];
+ 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,7 +256,7 @@ void setGlThreadSpecific(gl_hooks_t const *value) {
char const * const gl_names[] = {
#include "../entries.in"
- NULL
+ nullptr
};
char const * const gl_names_1[] = {
@@ -259,7 +266,12 @@ char const * const gl_names_1[] = {
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..67d69b4d06 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;
@@ -65,6 +71,11 @@ bool findExtension(const char* exts, const char* name, size_t nameLen) {
return false;
}
+bool needsAndroidPEglMitigation() {
+ static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
+ return vndk_version <= 28;
+}
+
int egl_get_init_count(EGLDisplay dpy) {
egl_display_t* eglDisplay = egl_display_t::get(dpy);
return eglDisplay ? eglDisplay->getRefsCount() : 0;
@@ -114,15 +125,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);
+}
- return sDisplay[uintptr_t(disp)].getDisplay(disp);
+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 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();
@@ -130,12 +217,38 @@ EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
Loader& loader(Loader::getInstance());
egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
- EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
+ if (cnx->dso) {
+ 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 +261,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) {
@@ -199,9 +319,37 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
}
}
+ if (cnx->minor == 5) {
+ // full list in egl_entries.in
+ if (!cnx->egl.eglCreateImage ||
+ !cnx->egl.eglDestroyImage ||
+ !cnx->egl.eglGetPlatformDisplay ||
+ !cnx->egl.eglCreatePlatformWindowSurface ||
+ !cnx->egl.eglCreatePlatformPixmapSurface ||
+ !cnx->egl.eglCreateSync ||
+ !cnx->egl.eglDestroySync ||
+ !cnx->egl.eglClientWaitSync ||
+ !cnx->egl.eglGetSyncAttrib ||
+ !cnx->egl.eglWaitSync) {
+ ALOGE("Driver indicates EGL 1.5 support, but does not have "
+ "a critical API");
+ cnx->minor = 4;
+ }
+ }
+
// the query strings are per-display
mVendorString = sVendorString;
- mVersionString = sVersionString;
+ mVersionString.clear();
+ cnx->driverVersion = EGL_MAKE_VERSION(1, 4, 0);
+ mVersionString = sVersionString14;
+ if ((cnx->major == 1) && (cnx->minor == 5)) {
+ mVersionString = sVersionString15;
+ cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0);
+ }
+ 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 +366,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,9 +389,10 @@ 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" &&
+ // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on
+ // some Android P vendor partitions this extension under the draft KHR name,
+ // but during Khronos review it was decided to demote it to EXT.
+ if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" &&
findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
mExtensionString.append("EGL_EXT_image_gl_colorspace ");
}
@@ -268,10 +418,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 +463,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 +517,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 +543,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..e117314d71 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -43,12 +43,14 @@ class egl_context_t;
struct egl_connection_t;
bool findExtension(const char* exts, const char* name, size_t nameLen = 0);
+bool needsAndroidPEglMitigation();
// ----------------------------------------------------------------------------
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 +74,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 +162,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..ac01dc8f96
--- /dev/null
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -0,0 +1,444 @@
+/*
+ ** 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 -
+// - AndroidGLESLayer_Initialize (provided by layer, called by loader)
+// - AndroidGLESLayer_GetProcAddress (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 AndroidGLESLayer_Initialize
+ auto next_layer_funcs = reinterpret_cast<FunctionTable*>(layer_id);
+ EGLFuncPointer val;
+
+ ALOGV("getNextLayerProcAddress servicing %s", name);
+
+ 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 - name(%s) no func_indices entry found", name);
+
+ // Look up which GPA we should use
+ int gpaIndex = func_indices["eglGetProcAddress"];
+ ALOGV("getNextLayerProcAddress - name(%s) gpaIndex(%i) <- using GPA from this index", name, gpaIndex);
+ EGLFuncPointer gpaNext = (*next_layer_funcs)[gpaIndex];
+ ALOGV("getNextLayerProcAddress - name(%s) gpaIndex(%i) gpaNext(%llu) <- using GPA at this address", name, gpaIndex, (unsigned long long)gpaNext);
+
+
+ // Call it for the requested function
+ typedef void* (*PFNEGLGETPROCADDRESSPROC)(const char*);
+ PFNEGLGETPROCADDRESSPROC next = reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(gpaNext);
+
+ val = reinterpret_cast<EGLFuncPointer>(next(name));
+ ALOGV("getNextLayerProcAddress - name(%s) gpaIndex(%i) gpaNext(%llu) Got back (%llu) from GPA", name, gpaIndex, (unsigned long long)gpaNext, (unsigned long long)val);
+
+ // 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];
+ ALOGV("getNextLayerProcAddress - name(%s) index(%i) entry(%llu) - Got a hit, returning known entry", name, index, (unsigned long long)val);
+ return reinterpret_cast<void*>(val);
+}
+
+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()) {
+ ALOGV("SetupFuncMaps - name(%s), func_idx(%i), No entry for func_indices, assigning now", name, func_idx);
+ func_names[func_idx] = name;
+ func_indices[name] = func_idx;
+ } else {
+ ALOGV("SetupFuncMaps - name(%s), func_idx(%i), Found entry for 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) {
+ ALOGV("SetupFuncMaps - name(%s), func_idx(%i), No entry for functions, assigning (%llu)", name, func_idx, (unsigned long long) *curr);
+ functions[func_idx] = *curr;
+ } else {
+ ALOGV("SetupFuncMaps - name(%s), func_idx(%i), Found entry for functions (%llu)", name, func_idx, (unsigned long long) functions[func_idx]);
+ }
+
+ 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 = "AndroidGLESLayer_Initialize";
+ 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 = "AndroidGLESLayer_GetProcAddress";
+ 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..e996be6853
--- /dev/null
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -0,0 +1,2736 @@
+/*
+ ** 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 "
+ "EGL_ANDROID_GLES_layers";
+// 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;
+
+ std::vector<AttrType> strippedAttribs;
+ if (needsAndroidPEglMitigation()) {
+ // Mitigation for Android P vendor partitions: 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.
+ for (const AttrType *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;
+ }
+ }
+ strippedAttribs.push_back(attr[0]);
+ strippedAttribs.push_back(attr[1]);
+ }
+ strippedAttribs.push_back(EGL_NONE);
+ }
+
+ 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,
+ needsAndroidPEglMitigation() ? strippedAttribs.data() : 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 acc205aaa1..7bb9b59ea4 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,59 @@ 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),
+ libEgl(nullptr),
+ libGles1(nullptr),
+ libGles2(nullptr),
+ systemDriverUnloaded(false) {
+
+ 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 systemDriverUnloaded;
+ 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
// ----------------------------------------------------------------------------
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/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/EGL_ANDROID_GLES_layers.txt b/opengl/specs/EGL_ANDROID_GLES_layers.txt
new file mode 100644
index 0000000000..eb2a7d95f3
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_GLES_layers.txt
@@ -0,0 +1,64 @@
+Name
+
+ ANDROID_GLES_layers
+
+Name Strings
+
+ EGL_ANDROID_GLES_layers
+
+Contributors
+
+ Cody Northrop
+
+Contact
+
+ Cody Northrop, Google LLC (cnorthrop 'at' google.com)
+
+Status
+
+ Draft
+
+Version
+
+ Version 1, March 3, 2019
+
+Number
+
+ EGL Extension #132
+
+Extension Type
+
+ EGL client extension
+
+Dependencies
+
+ Requires EGL 1.5 or EGL_EXT_client_extensions
+
+Overview
+
+ This extension indicates the EGL loader supports GLES layering on Android.
+ It does not add any requirements to drivers or hardware.
+
+ See frameworks/native/opengl/libs/EGL/GLES_layers.md in Android for
+ more information.
+
+New Types
+
+ None
+
+New Procedures and Functions
+
+ None
+
+New Tokens
+
+ None
+
+Issues
+
+ None
+
+Revision History
+
+#1 (Cody Northrop, March 3, 2019)
+ - Initial draft.
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..5c48a15092
--- /dev/null
+++ b/opengl/tools/glgen/specs/egl/EGL15.spec
@@ -0,0 +1,15 @@
+EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list )
+// eglGetSyncAttrib pulled in with eglCreateSync stubs
+// EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value )
+EGLBoolean eglDestroySync ( EGLDisplay dpy, EGLSync sync )
+EGLint eglClientWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout )
+// 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..34cb3e1a99
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
@@ -0,0 +1,194 @@
+/*
+** 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 <vector>
+#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 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 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;
+
+ pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+ *remaining = (limit - position) << elementSizeShift;
+ if (pointer != 0L) {
+ *array = nullptr;
+ pointer += position << elementSizeShift;
+ return reinterpret_cast<void*>(pointer);
+ }
+
+ *array = jniGetNioBufferBaseArray(_env, buffer);
+ *offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
+ return nullptr;
+}
+
+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));
+}
+
+struct WrappedEGLAttribs {
+private:
+ std::vector<EGLAttrib> backing; // only for 32-bit
+public:
+ EGLAttrib *attribs;
+ WrappedEGLAttribs(): attribs(nullptr) { };
+ void init(jlong *array, jint size) {
+ if (sizeof(EGLAttrib) != sizeof(jlong)) {
+ for (jint i = 0; i < size; ++i) {
+ backing.push_back(array[i]);
+ }
+ attribs = backing.data();
+ } else {
+ attribs = (EGLAttrib*)array;
+ }
+ }
+};
+
+// --------------------------------------------------------------------------
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/eglCreateImage.cpp b/opengl/tools/glgen/stubs/egl/eglCreateImage.cpp
new file mode 100644
index 0000000000..f93815cbba
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateImage.cpp
@@ -0,0 +1,50 @@
+/* EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreateImage
+ (JNIEnv *_env, jobject _this, jobject dpy, jobject context, jint target, jlong buffer, jlongArray attrib_list_ref, jint offset) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
+ EGLImage _returnValue = (EGLImage) 0;
+ EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+ EGLContext context_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, context);
+ jlong *attrib_list_base = (jlong *) 0;
+ jint _remaining;
+ WrappedEGLAttribs attrib_list;
+
+ 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 = (jlong *)
+ _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list.init(attrib_list_base + offset, _remaining);
+
+ _returnValue = eglCreateImage(
+ (EGLDisplay)dpy_native,
+ (EGLContext)context_native,
+ (EGLenum)target,
+ (EGLClientBuffer)buffer,
+ attrib_list.attribs
+ );
+
+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, eglimageClass, eglimageConstructor, _returnValue);
+}
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateImage.java b/opengl/tools/glgen/stubs/egl/eglCreateImage.java
new file mode 100644
index 0000000000..06a04bb30d
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateImage.java
@@ -0,0 +1,11 @@
+ // C function EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list )
+
+ public static native EGLImage eglCreateImage(
+ EGLDisplay dpy,
+ EGLContext context,
+ int target,
+ long buffer,
+ long[] attrib_list,
+ int offset
+ );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg
new file mode 100644
index 0000000000..da5687d507
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg
@@ -0,0 +1 @@
+{"eglCreateImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;IJ[JI)Landroid/opengl/EGLImage;", (void *) android_eglCreateImage },
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/eglCreatePlatformWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.cpp
new file mode 100644
index 0000000000..48dbd35f76
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.cpp
@@ -0,0 +1,68 @@
+/* EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreatePlatformWindowSurface
+ (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_window_buf, jlongArray attrib_list_ref, jint offset) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
+ jarray _array = (jarray) 0;
+ jint _bufferOffset = (jint) 0;
+ EGLSurface _returnValue = (EGLSurface) 0;
+ EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+ EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+ jint _native_windowRemaining;
+ void *native_window = (void *) 0;
+ jlong *attrib_list_base = (jlong *) 0;
+ jint _attrib_listRemaining;
+ WrappedEGLAttribs attrib_list;
+
+ if (!native_window_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "native_window == null";
+ goto exit;
+ }
+ native_window = (void *)getPointer(_env, native_window_buf, (jarray*)&_array, &_native_windowRemaining, &_bufferOffset);
+ 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;
+ }
+ _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - offset;
+ attrib_list_base = (jlong *)
+ _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list.init(attrib_list_base + offset, _attrib_listRemaining);
+
+ if (native_window == NULL) {
+ char * _native_windowBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+ native_window = (void *) (_native_windowBase + _bufferOffset);
+ }
+ _returnValue = eglCreatePlatformWindowSurface(
+ (EGLDisplay)dpy_native,
+ (EGLConfig)config_native,
+ (void *)native_window,
+ attrib_list.attribs
+ );
+
+exit:
+ if (attrib_list_base) {
+ _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+ JNI_ABORT);
+ }
+ if (_array) {
+ releasePointer(_env, _array, native_window, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return nullptr;
+ }
+ return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java
new file mode 100644
index 0000000000..dda37f83a8
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java
@@ -0,0 +1,10 @@
+ // C function EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list )
+
+ public static native EGLSurface eglCreatePlatformWindowSurface(
+ EGLDisplay dpy,
+ EGLConfig config,
+ java.nio.Buffer native_window,
+ long[] attrib_list,
+ int offset
+ );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg
new file mode 100644
index 0000000000..ce464e829a
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg
@@ -0,0 +1 @@
+{"eglCreatePlatformWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/nio/Buffer;[JI)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePlatformWindowSurface },
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateSync.cpp b/opengl/tools/glgen/stubs/egl/eglCreateSync.cpp
new file mode 100644
index 0000000000..c53afeaf12
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateSync.cpp
@@ -0,0 +1,101 @@
+/* EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreateSync
+ (JNIEnv *_env, jobject _this, jobject dpy, jint type, jlongArray attrib_list_ref, jint offset) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
+ EGLSync _returnValue = (EGLSync) 0;
+ EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+ jlong *attrib_list_base = (jlong *) 0;
+ jint _remaining;
+ WrappedEGLAttribs attrib_list;
+
+ 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 = (jlong *)
+ _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list.init(attrib_list_base + offset, _remaining);
+
+ _returnValue = eglCreateSync(
+ (EGLDisplay)dpy_native,
+ (EGLenum)type,
+ attrib_list.attribs
+ );
+
+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, eglsyncClass, eglsyncConstructor, _returnValue);
+}
+
+/* EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value ) */
+static jboolean
+android_eglGetSyncAttrib
+ (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint attribute, jlongArray value_ref, jint offset) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
+ EGLBoolean _returnValue = (EGLBoolean) 0;
+ EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+ EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+ jlong *value_base = (jlong *) 0;
+ jint _remaining;
+ EGLAttrib value;
+
+ if (!value_ref) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "offset < 0";
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(value_ref) - offset;
+ value_base = (jlong *)
+ _env->GetLongArrayElements(value_ref, (jboolean *)0);
+
+ _returnValue = eglGetSyncAttrib(
+ (EGLDisplay)dpy_native,
+ (EGLSync)sync_native,
+ (EGLint)attribute,
+ &value
+ );
+
+ if (value_base && _returnValue == EGL_TRUE) {
+ *(value_base + offset) = (jlong) value;
+ }
+
+exit:
+ if (value_base) {
+ _env->ReleaseLongArrayElements(value_ref, (jlong*)value_base,
+ _exception ? JNI_ABORT: 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ return JNI_FALSE;
+ }
+ return (jboolean)_returnValue;
+}
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateSync.java b/opengl/tools/glgen/stubs/egl/eglCreateSync.java
new file mode 100644
index 0000000000..db8f728ca6
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateSync.java
@@ -0,0 +1,22 @@
+ // C function EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list )
+
+ public static native EGLSync eglCreateSync(
+ EGLDisplay dpy,
+ int type,
+ long[] attrib_list,
+ int offset
+ );
+
+ /**
+ * C function EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute,
+ * EGLAttrib *value )
+ */
+
+ public static native boolean eglGetSyncAttrib(
+ EGLDisplay dpy,
+ EGLSync sync,
+ int attribute,
+ long[] value,
+ int offset
+ );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg
new file mode 100644
index 0000000000..c99e7fe8ec
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg
@@ -0,0 +1,2 @@
+{"eglCreateSync", "(Landroid/opengl/EGLDisplay;I[JI)Landroid/opengl/EGLSync;", (void *) android_eglCreateSync },
+{"eglGetSyncAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;I[JI)Z", (void *) android_eglGetSyncAttrib },
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..6acb32ae6b
--- /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;
+ jlong *attrib_list_base = (jlong *) 0;
+ jint _remaining;
+ WrappedEGLAttribs attrib_list;
+
+ 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 = (jlong *)
+ _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list.init(attrib_list_base + offset, _remaining);
+
+ _returnValue = eglGetPlatformDisplay(
+ (EGLenum)platform,
+ (void *)native_display,
+ attrib_list.attribs
+ );
+
+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..e763b4e983 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -4,17 +4,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
-static jclass nioAccessClass;
-static jclass bufferClass;
-static jmethodID getBasePointerID;
-static jmethodID getBaseArrayID;
-static jmethodID getBaseArrayOffsetID;
-static jfieldID positionID;
-static jfieldID limitID;
-static jfieldID elementSizeShiftID;
-
/* special calls implemented in Android's GLES wrapper used to more
* efficiently bound-check passed arrays */
@@ -49,28 +38,9 @@ static void glVertexAttribIPointerBounds(GLuint indx, GLint size, GLenum type,
#endif
}
-/* Cache method IDs each time the class is loaded. */
-
static void
nativeClassInit(JNIEnv *_env, jclass glImplClass)
{
- 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");
}
static void *
@@ -81,23 +51,17 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *o
jint elementSizeShift;
jlong pointer;
- position = _env->GetIntField(buffer, positionID);
- limit = _env->GetIntField(buffer, limitID);
- elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
*remaining = (limit - position) << elementSizeShift;
- pointer = _env->CallStaticLongMethod(nioAccessClass,
- getBasePointerID, buffer);
if (pointer != 0L) {
- *array = NULL;
+ *array = nullptr;
+ pointer += position << elementSizeShift;
return reinterpret_cast<void*>(pointer);
}
- *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
- getBaseArrayID, buffer);
- *offset = _env->CallStaticIntMethod(nioAccessClass,
- getBaseArrayOffsetID, buffer);
-
- return NULL;
+ *array = jniGetNioBufferBaseArray(_env, buffer);
+ *offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
+ return nullptr;
}
class ByteArrayGetter {
@@ -219,16 +183,18 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
static void *
getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
- char* buf = (char*) _env->GetDirectBufferAddress(buffer);
- if (buf) {
- jint position = _env->GetIntField(buffer, positionID);
- jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
- buf += position << elementSizeShift;
- } else {
+ jint position;
+ jint limit;
+ jint elementSizeShift;
+ jlong pointer;
+ pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+ if (pointer == 0) {
jniThrowException(_env, "java/lang/IllegalArgumentException",
"Must use a native order direct Buffer");
+ return nullptr;
}
- return (void*) buf;
+ pointer += position << elementSizeShift;
+ return reinterpret_cast<void*>(pointer);
}
// --------------------------------------------------------------------------
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..c12efc3795 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -64,18 +64,7 @@ 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;
-static jmethodID getBasePointerID;
-static jmethodID getBaseArrayID;
-static jmethodID getBaseArrayOffsetID;
-static jmethodID allowIndirectBuffersID;
-static jfieldID positionID;
-static jfieldID limitID;
-static jfieldID elementSizeShiftID;
static jfieldID haveCheckedExtensionsID;
static jfieldID have_OES_blend_equation_separateID;
static jfieldID have_OES_blend_subtractID;
@@ -87,12 +76,6 @@ static jfieldID have_OES_texture_cube_mapID;
static void
nativeClassInit(JNIEnv *_env, jclass glImplClass)
{
- jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
- nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
-
- jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
- bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
-
jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
haveCheckedExtensionsID = _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
@@ -100,19 +83,6 @@ nativeClassInit(JNIEnv *_env, jclass glImplClass)
have_OES_blend_subtractID = _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
have_OES_framebuffer_objectID = _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
have_OES_texture_cube_mapID = _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
-
- 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");
- allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
- "allowIndirectBuffers", "(Ljava/lang/String;)Z");
- positionID = _env->GetFieldID(bufferClass, "position", "I");
- limitID = _env->GetFieldID(bufferClass, "limit", "I");
- elementSizeShiftID =
- _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
}
static void *
@@ -123,28 +93,17 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *o
jint elementSizeShift;
jlong pointer;
- position = _env->GetIntField(buffer, positionID);
- limit = _env->GetIntField(buffer, limitID);
- elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
*remaining = (limit - position) << elementSizeShift;
- pointer = _env->CallStaticLongMethod(nioAccessClass,
- getBasePointerID, buffer);
if (pointer != 0L) {
- *offset = 0;
- *array = NULL;
- return reinterpret_cast<void *>(pointer);
+ *array = nullptr;
+ pointer += position << elementSizeShift;
+ return reinterpret_cast<void*>(pointer);
}
- *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
- getBaseArrayID, buffer);
- if (*array == NULL) {
- *offset = 0;
- return (void*) NULL;
- }
- *offset = _env->CallStaticIntMethod(nioAccessClass,
- getBaseArrayOffsetID, buffer);
-
- return NULL;
+ *array = jniGetNioBufferBaseArray(_env, buffer);
+ *offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
+ return nullptr;
}
static void
@@ -158,42 +117,24 @@ extern "C" {
extern char* __progname;
}
-static bool
-allowIndirectBuffers(JNIEnv *_env) {
- static jint sIndirectBufferCompatability;
- if (sIndirectBufferCompatability == 0) {
- jobject appName = _env->NewStringUTF(::__progname);
- sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
- }
- return sIndirectBufferCompatability == 2;
-}
-
static void *
getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
- if (!buffer) {
- return NULL;
+ if (buffer == nullptr) {
+ return nullptr;
}
- void* buf = _env->GetDirectBufferAddress(buffer);
- if (buf) {
- jint position = _env->GetIntField(buffer, positionID);
- jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
- buf = ((char*) buf) + (position << elementSizeShift);
- } else {
- if (allowIndirectBuffers(_env)) {
- jarray array = 0;
- jint remaining;
- jint offset;
- buf = getPointer(_env, buffer, &array, &remaining, &offset);
- if (array) {
- releasePointer(_env, array, buf, 0);
- }
- buf = (char*)buf + offset;
- } else {
- jniThrowException(_env, "java/lang/IllegalArgumentException",
- "Must use a native order direct Buffer");
- }
+
+ jint position;
+ jint limit;
+ jint elementSizeShift;
+ jlong pointer;
+ pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+ if (pointer == 0) {
+ jniThrowException(_env, "java/lang/IllegalArgumentException",
+ "Must use a native order direct Buffer");
+ return nullptr;
}
- return buf;
+ pointer += position << elementSizeShift;
+ return reinterpret_cast<void*>(pointer);
}
static int
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"/>