eglApi.cpp revision 73d2b3c7e5537a6645f20f022b2e60cb9f342cbe
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/* 2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** Copyright 2007, The Android Open Source Project 3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** 4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** Licensed under the Apache License, Version 2.0 (the "License"); 5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** you may not use this file except in compliance with the License. 6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** You may obtain a copy of the License at 7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** 8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** http://www.apache.org/licenses/LICENSE-2.0 9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** 10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** Unless required by applicable law or agreed to in writing, software 11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** distributed under the License is distributed on an "AS IS" BASIS, 12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** See the License for the specific language governing permissions and 14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy ** limitations under the License. 15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */ 16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 17a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy#include <ctype.h> 18a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy#include <stdlib.h> 19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <string.h> 20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 21e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <hardware/gralloc.h> 22deba785f122a47915756ffd991f5540d952cf937Romain Guy#include <system/window.h> 23e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 24ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <EGL/egl.h> 25c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy#include <EGL/eglext.h> 26f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy#include <GLES/gl.h> 27c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy#include <GLES/glext.h> 28079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy 29a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy#include <cutils/log.h> 3085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <cutils/atomic.h> 31e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <cutils/properties.h> 3285bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <cutils/memory.h> 3306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 34db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy#include <utils/KeyedVector.h> 359d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <utils/SortedVector.h> 369d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <utils/String8.h> 3785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy 38e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy#include "egl_impl.h" 39e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy#include "egl_tls.h" 40e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include "glestrace.h" 41e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include "hooks.h" 429d5316e3f56d138504565ff311145ac01621dff4Romain Guy 439d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "egl_display.h" 44163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#include "egl_impl.h" 45163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#include "egl_object.h" 46163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#include "egl_tls.h" 47163935113919a184122b8b3bd672ef08c8df65dcRomain Guy 48163935113919a184122b8b3bd672ef08c8df65dcRomain Guyusing namespace android; 49163935113919a184122b8b3bd672ef08c8df65dcRomain Guy 50163935113919a184122b8b3bd672ef08c8df65dcRomain Guy// ---------------------------------------------------------------------------- 519d5316e3f56d138504565ff311145ac01621dff4Romain Guy 529d5316e3f56d138504565ff311145ac01621dff4Romain Guy#define EGL_VERSION_HW_ANDROID 0x3143 539d5316e3f56d138504565ff311145ac01621dff4Romain Guy 549d5316e3f56d138504565ff311145ac01621dff4Romain Guystruct extention_map_t { 559d5316e3f56d138504565ff311145ac01621dff4Romain Guy const char* name; 567ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy __eglMustCastToProperFunctionPointerType address; 577ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy}; 589d5316e3f56d138504565ff311145ac01621dff4Romain Guy 599d5316e3f56d138504565ff311145ac01621dff4Romain Guystatic const extention_map_t sExtentionMap[] = { 60e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy { "eglLockSurfaceKHR", 61e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 62e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy { "eglUnlockSurfaceKHR", 63e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 64ce0537b80087a6225273040a987414b1dd081aa0Romain Guy { "eglCreateImageKHR", 6585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 66e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy { "eglDestroyImageKHR", 67e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 68ce0537b80087a6225273040a987414b1dd081aa0Romain Guy { "eglGetSystemTimeFrequencyNV", 69f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 70f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy { "eglGetSystemTimeNV", 71e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 72e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}; 73e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 74e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy// accesses protected by sExtensionMapMutex 75e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guystatic DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 76e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guystatic int sGLExtentionSlot = 0; 77ce0537b80087a6225273040a987414b1dd081aa0Romain Guystatic pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 78f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 79f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guystatic void(*findProcAddress(const char* name, 80e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy const extention_map_t* map, size_t n))() { 81e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy for (uint32_t i=0 ; i<n ; i++) { 82ce0537b80087a6225273040a987414b1dd081aa0Romain Guy if (!strcmp(name, map[i].name)) { 83f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy return map[i].address; 84f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 85e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 86e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy return NULL; 87e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy} 88bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 89bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy// ---------------------------------------------------------------------------- 90bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 91ce0537b80087a6225273040a987414b1dd081aa0Romain Guytemplate<typename T> 92bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guystatic __attribute__((noinline)) 93f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyint binarySearch(T const sortedArray[], int first, int last, T key) { 94f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy while (first <= last) { 95bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy int mid = (first + last) / 2; 96ce0537b80087a6225273040a987414b1dd081aa0Romain Guy if (sortedArray[mid] < key) { 97f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy first = mid + 1; 98f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } else if (key < sortedArray[mid]) { 99bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy last = mid - 1; 100bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy } else { 101ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return mid; 102f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 103f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 104bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy return -1; 105bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 106ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 107f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// ---------------------------------------------------------------------------- 108f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 109bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guynamespace android { 110bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyextern void setGLHooksThreadSpecific(gl_hooks_t const *value); 111f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyextern EGLBoolean egl_init_drivers(); 112bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyextern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 113bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyextern int gEGLDebugLevel; 114bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyextern gl_hooks_t gHooksTrace; 115ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} // namespace android; 116bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 117bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// ---------------------------------------------------------------------------- 118bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 119bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guystatic inline void clearError() { egl_tls_t::clearError(); } 120bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guystatic inline EGLContext getContext() { return egl_tls_t::getContext(); } 121ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 122bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy// ---------------------------------------------------------------------------- 123bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 124bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain GuyEGLDisplay eglGetDisplay(EGLNativeDisplayType display) 125bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy{ 126bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy clearError(); 127bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 128f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy uint32_t index = uint32_t(display); 129f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy if (index >= NUM_DISPLAYS) { 130f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 131ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 132c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy 133c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy if (egl_init_drivers() == EGL_FALSE) { 134c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 135c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy } 136c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy 137ce0537b80087a6225273040a987414b1dd081aa0Romain Guy EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 138079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy return dpy; 139079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy} 140079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy 141f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// ---------------------------------------------------------------------------- 142bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy// Initialization 143ce0537b80087a6225273040a987414b1dd081aa0Romain Guy// ---------------------------------------------------------------------------- 144079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy 145079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain GuyEGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 146079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy{ 147bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy clearError(); 148bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 149ce0537b80087a6225273040a987414b1dd081aa0Romain Guy egl_display_t * const dp = get_display(dpy); 1509d5316e3f56d138504565ff311145ac01621dff4Romain Guy if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1517ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy 1529d5316e3f56d138504565ff311145ac01621dff4Romain Guy EGLBoolean res = dp->initialize(major, minor); 1537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy 1547ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy return res; 1559d5316e3f56d138504565ff311145ac01621dff4Romain Guy} 1567ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy 1579d5316e3f56d138504565ff311145ac01621dff4Romain GuyEGLBoolean eglTerminate(EGLDisplay dpy) 1589d5316e3f56d138504565ff311145ac01621dff4Romain Guy{ 159bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy // NOTE: don't unload the drivers b/c some APIs can be called 160f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy // after eglTerminate() has been called. eglTerminate() only 161bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy // terminates an EGLDisplay, not a EGL itself. 162bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 163ce0537b80087a6225273040a987414b1dd081aa0Romain Guy clearError(); 164f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1657ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy egl_display_t* const dp = get_display(dpy); 166f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 167bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 168ce0537b80087a6225273040a987414b1dd081aa0Romain Guy EGLBoolean res = dp->terminate(); 169f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1707ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy return res; 171bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy} 172bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 173ce0537b80087a6225273040a987414b1dd081aa0Romain Guy// ---------------------------------------------------------------------------- 174f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy// configuration 1757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy// ---------------------------------------------------------------------------- 176f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 177bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain GuyEGLBoolean eglGetConfigs( EGLDisplay dpy, 178ce0537b80087a6225273040a987414b1dd081aa0Romain Guy EGLConfig *configs, 179f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy EGLint config_size, EGLint *num_config) 1807ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy{ 181f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy clearError(); 182f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 183ce0537b80087a6225273040a987414b1dd081aa0Romain Guy egl_display_t const * const dp = validate_display(dpy); 184f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy if (!dp) return EGL_FALSE; 1857ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy 186f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy GLint numConfigs = dp->numTotalConfigs; 187f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy if (!configs) { 188ce0537b80087a6225273040a987414b1dd081aa0Romain Guy *num_config = numConfigs; 189f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy return EGL_TRUE; 1907ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 191bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy 192bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy GLint n = 0; 193bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) { 194bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy *configs++ = EGLConfig(i); 19585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy config_size--; 19685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy n++; 197ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 198dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 199dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy *num_config = n; 200ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return EGL_TRUE; 201ce0537b80087a6225273040a987414b1dd081aa0Romain Guy} 202ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 203ce0537b80087a6225273040a987414b1dd081aa0Romain GuyEGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 204ce0537b80087a6225273040a987414b1dd081aa0Romain Guy EGLConfig *configs, EGLint config_size, 205dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy EGLint *num_config) 206dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy{ 207dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy clearError(); 208f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 2098ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy egl_display_t const * const dp = validate_display(dpy); 210f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy if (!dp) return EGL_FALSE; 211dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 212dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy if (num_config==0) { 213ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return setError(EGL_BAD_PARAMETER, EGL_FALSE); 214ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 215deba785f122a47915756ffd991f5540d952cf937Romain Guy 216deba785f122a47915756ffd991f5540d952cf937Romain Guy EGLint n; 217dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy EGLBoolean res = EGL_FALSE; 218deba785f122a47915756ffd991f5540d952cf937Romain Guy *num_config = 0; 219deba785f122a47915756ffd991f5540d952cf937Romain Guy 220deba785f122a47915756ffd991f5540d952cf937Romain Guy 221deba785f122a47915756ffd991f5540d952cf937Romain Guy // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 222dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy // to do this, we have to go through the attrib_list array once 223deba785f122a47915756ffd991f5540d952cf937Romain Guy // to figure out both its size and if it contains an EGL_CONFIG_ID 224deba785f122a47915756ffd991f5540d952cf937Romain Guy // key. If so, the full array is copied and patched. 225deba785f122a47915756ffd991f5540d952cf937Romain Guy // NOTE: we assume that there can be only one occurrence 226deba785f122a47915756ffd991f5540d952cf937Romain Guy // of EGL_CONFIG_ID. 227ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 228ce0537b80087a6225273040a987414b1dd081aa0Romain Guy EGLint patch_index = -1; 229ce0537b80087a6225273040a987414b1dd081aa0Romain Guy GLint attr; 23085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy size_t size = 0; 23185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy if (attrib_list) { 232ce0537b80087a6225273040a987414b1dd081aa0Romain Guy while ((attr=attrib_list[size]) != EGL_NONE) { 233c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy if (attr == EGL_CONFIG_ID) 234c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy patch_index = size; 235c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy size += 2; 236c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy } 237c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy } 2387fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy if (patch_index >= 0) { 2397fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy size += 2; // we need copy the sentinel as well 2407fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint)); 2417fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy if (new_list == 0) 2427fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy return setError(EGL_BAD_ALLOC, EGL_FALSE); 24385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy memcpy(new_list, attrib_list, size*sizeof(EGLint)); 244db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 245d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy // patch the requested EGL_CONFIG_ID 246d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy bool found = false; 247db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy EGLConfig ourConfig(0); 248d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy EGLint& configId(new_list[patch_index+1]); 249d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) { 250db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy if (dp->configs[i].configId == configId) { 251d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy ourConfig = EGLConfig(i); 252d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy configId = dp->configs[i].implConfigId; 25306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy found = true; 25406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy break; 25506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy } 2567fac2e18339f765320d759e8d4c090f92431959eRomain Guy } 2577fac2e18339f765320d759e8d4c090f92431959eRomain Guy 258db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl]; 259db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy if (found && cnx->dso) { 260db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy // and switch to the new list 261db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy attrib_list = const_cast<const EGLint *>(new_list); 262db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 263d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy // At this point, the only configuration that can match is 264a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy // dp->configs[i][index], however, we don't know if it would be 265a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy // rejected because of the other attributes, so we do have to call 266a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy // cnx->egl.eglChooseConfig() -- but we don't have to loop 267e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy // through all the EGLimpl[]. 268e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy // We also know we can only get a single config back, and we know 269e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy // which one. 2709226298891119acff6b5e8b65fb7074fb99dc0c0Romain Guy 271e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy res = cnx->egl.eglChooseConfig( 2729226298891119acff6b5e8b65fb7074fb99dc0c0Romain Guy dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy, 273e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy attrib_list, configs, config_size, &n); 2749226298891119acff6b5e8b65fb7074fb99dc0c0Romain Guy if (res && n>0) { 275e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy // n has to be 0 or 1, by construction, and we already know 276e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy // which config it will return (since there can be only one). 277e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy if (configs) { 278a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy configs[0] = ourConfig; 279a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy } 280a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy *num_config = 1; 281a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy } 282e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy } 283a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy 284a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy free(const_cast<EGLint *>(attrib_list)); 285a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy return res; 286a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy } 287a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy 288a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy 289a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 290e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy egl_connection_t* const cnx = &gEGLImpl[i]; 291a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy if (cnx->dso) { 292a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy if (cnx->egl.eglChooseConfig( 293a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy dp->disp[i].dpy, attrib_list, configs, config_size, &n)) { 294163935113919a184122b8b3bd672ef08c8df65dcRomain Guy if (configs) { 295163935113919a184122b8b3bd672ef08c8df65dcRomain Guy // now we need to convert these client EGLConfig to our 296163935113919a184122b8b3bd672ef08c8df65dcRomain Guy // internal EGLConfig format. 297163935113919a184122b8b3bd672ef08c8df65dcRomain Guy // This is done in O(n Log(n)) time. 298163935113919a184122b8b3bd672ef08c8df65dcRomain Guy for (int j=0 ; j<n ; j++) { 299163935113919a184122b8b3bd672ef08c8df65dcRomain Guy egl_config_t key(i, configs[j]); 300163935113919a184122b8b3bd672ef08c8df65dcRomain Guy intptr_t index = binarySearch<egl_config_t>( 301163935113919a184122b8b3bd672ef08c8df65dcRomain Guy dp->configs, 0, dp->numTotalConfigs, key); 302163935113919a184122b8b3bd672ef08c8df65dcRomain Guy if (index >= 0) { 303163935113919a184122b8b3bd672ef08c8df65dcRomain Guy configs[j] = EGLConfig(index); 304163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } else { 305163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return setError(EGL_BAD_CONFIG, EGL_FALSE); 306163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } 307163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } 308a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy configs += n; 309e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy config_size -= n; 310e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 311e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *num_config += n; 312e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy res = EGL_TRUE; 313e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 314e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 315163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } 316163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return res; 317163935113919a184122b8b3bd672ef08c8df65dcRomain Guy} 318dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 319dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain GuyEGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 320dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy EGLint attribute, EGLint *value) 321dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy{ 322dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy clearError(); 323dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 324dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy egl_display_t const* dp = 0; 325dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy egl_connection_t* cnx = validate_display_config(dpy, config, dp); 326dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy if (!cnx) return EGL_FALSE; 327dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 328dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy if (attribute == EGL_CONFIG_ID) { 329dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy *value = dp->configs[intptr_t(config)].configId; 330dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy return EGL_TRUE; 331dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy } 332079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy return cnx->egl.eglGetConfigAttrib( 333079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 334dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy dp->configs[intptr_t(config)].config, attribute, value); 335dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy} 336dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 337dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy// ---------------------------------------------------------------------------- 338dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy// surfaces 339dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy// ---------------------------------------------------------------------------- 340dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 341dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain GuyEGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 342dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy NativeWindowType window, 343dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy const EGLint *attrib_list) 344dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy{ 345dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy clearError(); 346dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy 347dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy egl_display_t const* dp = 0; 348dbd77cd444f89d94ec5333223c1bc17dbe0c90cdRomain Guy egl_connection_t* cnx = validate_display_config(dpy, config, dp); 3497fbcc0492fca03857e3c45064f4aa040af817d55Romain Guy if (cnx) { 350f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy; 351db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy EGLConfig iConfig = dp->configs[intptr_t(config)].config; 35206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy EGLint format; 353db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy 354d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { 355a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy LOGE("EGLNativeWindowType %p already connected to another API", 356a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy window); 357a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 358a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy } 359c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy 360ce0537b80087a6225273040a987414b1dd081aa0Romain Guy // set the native window's buffers format to match this config 361163935113919a184122b8b3bd672ef08c8df65dcRomain Guy if (cnx->egl.eglGetConfigAttrib(iDpy, 362e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy iConfig, EGL_NATIVE_VISUAL_ID, &format)) { 363e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy if (format != 0) { 364163935113919a184122b8b3bd672ef08c8df65dcRomain Guy int err = native_window_set_buffers_format(window, format); 365163935113919a184122b8b3bd672ef08c8df65dcRomain Guy if (err != 0) { 366163935113919a184122b8b3bd672ef08c8df65dcRomain Guy LOGE("error setting native window pixel format: %s (%d)", 367163935113919a184122b8b3bd672ef08c8df65dcRomain Guy strerror(-err), err); 368163935113919a184122b8b3bd672ef08c8df65dcRomain Guy native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 369163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 370163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } 371163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } 372163935113919a184122b8b3bd672ef08c8df65dcRomain Guy } 373163935113919a184122b8b3bd672ef08c8df65dcRomain Guy 374163935113919a184122b8b3bd672ef08c8df65dcRomain Guy // the EGL spec requires that a new EGLSurface default to swap interval 375163935113919a184122b8b3bd672ef08c8df65dcRomain Guy // 1, so explicitly set that on the window here. 376163935113919a184122b8b3bd672ef08c8df65dcRomain Guy ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 3779d5316e3f56d138504565ff311145ac01621dff4Romain Guy anw->setSwapInterval(anw, 1); 378e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 3797ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy EGLSurface surface = cnx->egl.eglCreateWindowSurface( 3807ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy iDpy, iConfig, window, attrib_list); 3819d5316e3f56d138504565ff311145ac01621dff4Romain Guy if (surface != EGL_NO_SURFACE) { 382e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, 383e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy dp->configs[intptr_t(config)].impl, cnx); 384e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy return s; 385e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 386 387 // EGLSurface creation failed 388 native_window_set_buffers_format(window, 0); 389 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 390 } 391 return EGL_NO_SURFACE; 392} 393 394EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 395 NativePixmapType pixmap, 396 const EGLint *attrib_list) 397{ 398 clearError(); 399 400 egl_display_t const* dp = 0; 401 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 402 if (cnx) { 403 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 404 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 405 dp->configs[intptr_t(config)].config, pixmap, attrib_list); 406 if (surface != EGL_NO_SURFACE) { 407 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 408 dp->configs[intptr_t(config)].impl, cnx); 409 return s; 410 } 411 } 412 return EGL_NO_SURFACE; 413} 414 415EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 416 const EGLint *attrib_list) 417{ 418 clearError(); 419 420 egl_display_t const* dp = 0; 421 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 422 if (cnx) { 423 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 424 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 425 dp->configs[intptr_t(config)].config, attrib_list); 426 if (surface != EGL_NO_SURFACE) { 427 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 428 dp->configs[intptr_t(config)].impl, cnx); 429 return s; 430 } 431 } 432 return EGL_NO_SURFACE; 433} 434 435EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 436{ 437 clearError(); 438 439 egl_display_t const * const dp = validate_display(dpy); 440 if (!dp) return EGL_FALSE; 441 442 SurfaceRef _s(dp, surface); 443 if (!_s.get()) 444 return setError(EGL_BAD_SURFACE, EGL_FALSE); 445 446 egl_surface_t * const s = get_surface(surface); 447 EGLBoolean result = s->cnx->egl.eglDestroySurface( 448 dp->disp[s->impl].dpy, s->surface); 449 if (result == EGL_TRUE) { 450 _s.terminate(); 451 } 452 return result; 453} 454 455EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 456 EGLint attribute, EGLint *value) 457{ 458 clearError(); 459 460 egl_display_t const * const dp = validate_display(dpy); 461 if (!dp) return EGL_FALSE; 462 463 SurfaceRef _s(dp, surface); 464 if (!_s.get()) 465 return setError(EGL_BAD_SURFACE, EGL_FALSE); 466 467 egl_surface_t const * const s = get_surface(surface); 468 EGLBoolean result(EGL_TRUE); 469 if (attribute == EGL_CONFIG_ID) { 470 // We need to remap EGL_CONFIG_IDs 471 *value = dp->configs[intptr_t(s->config)].configId; 472 } else { 473 result = s->cnx->egl.eglQuerySurface( 474 dp->disp[s->impl].dpy, s->surface, attribute, value); 475 } 476 477 return result; 478} 479 480// ---------------------------------------------------------------------------- 481// Contexts 482// ---------------------------------------------------------------------------- 483 484EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 485 EGLContext share_list, const EGLint *attrib_list) 486{ 487 clearError(); 488 489 egl_display_t const* dp = 0; 490 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 491 if (cnx) { 492 if (share_list != EGL_NO_CONTEXT) { 493 egl_context_t* const c = get_context(share_list); 494 share_list = c->context; 495 } 496 EGLContext context = cnx->egl.eglCreateContext( 497 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 498 dp->configs[intptr_t(config)].config, 499 share_list, attrib_list); 500 if (context != EGL_NO_CONTEXT) { 501 // figure out if it's a GLESv1 or GLESv2 502 int version = 0; 503 if (attrib_list) { 504 while (*attrib_list != EGL_NONE) { 505 GLint attr = *attrib_list++; 506 GLint value = *attrib_list++; 507 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 508 if (value == 1) { 509 version = GLESv1_INDEX; 510 } else if (value == 2) { 511 version = GLESv2_INDEX; 512 } 513 } 514 }; 515 } 516 egl_context_t* c = new egl_context_t(dpy, context, config, 517 dp->configs[intptr_t(config)].impl, cnx, version); 518#if EGL_TRACE 519 if (gEGLDebugLevel > 0) 520 GLTrace_eglCreateContext(version, c); 521#endif 522 return c; 523 } 524 } 525 return EGL_NO_CONTEXT; 526} 527 528EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 529{ 530 clearError(); 531 532 egl_display_t const * const dp = validate_display(dpy); 533 if (!dp) 534 return EGL_FALSE; 535 536 ContextRef _c(dp, ctx); 537 if (!_c.get()) 538 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 539 540 egl_context_t * const c = get_context(ctx); 541 EGLBoolean result = c->cnx->egl.eglDestroyContext( 542 dp->disp[c->impl].dpy, c->context); 543 if (result == EGL_TRUE) { 544 _c.terminate(); 545 } 546 return result; 547} 548 549static void loseCurrent(egl_context_t * cur_c) 550{ 551 if (cur_c) { 552 egl_surface_t * cur_r = get_surface(cur_c->read); 553 egl_surface_t * cur_d = get_surface(cur_c->draw); 554 555 // by construction, these are either 0 or valid (possibly terminated) 556 // it should be impossible for these to be invalid 557 ContextRef _cur_c(cur_c); 558 SurfaceRef _cur_r(cur_r); 559 SurfaceRef _cur_d(cur_d); 560 561 cur_c->read = NULL; 562 cur_c->draw = NULL; 563 564 _cur_c.release(); 565 _cur_r.release(); 566 _cur_d.release(); 567 } 568} 569 570EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 571 EGLSurface read, EGLContext ctx) 572{ 573 clearError(); 574 575 egl_display_t const * const dp = get_display(dpy); 576 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 577 578 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 579 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 580 // a valid but uninitialized display. 581 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 582 (draw != EGL_NO_SURFACE) ) { 583 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 584 } 585 586 // get a reference to the object passed in 587 ContextRef _c(dp, ctx); 588 SurfaceRef _d(dp, draw); 589 SurfaceRef _r(dp, read); 590 591 // validate the context (if not EGL_NO_CONTEXT) 592 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 593 // EGL_NO_CONTEXT is valid 594 return EGL_FALSE; 595 } 596 597 // these are the underlying implementation's object 598 EGLContext impl_ctx = EGL_NO_CONTEXT; 599 EGLSurface impl_draw = EGL_NO_SURFACE; 600 EGLSurface impl_read = EGL_NO_SURFACE; 601 602 // these are our objects structs passed in 603 egl_context_t * c = NULL; 604 egl_surface_t const * d = NULL; 605 egl_surface_t const * r = NULL; 606 607 // these are the current objects structs 608 egl_context_t * cur_c = get_context(getContext()); 609 610 if (ctx != EGL_NO_CONTEXT) { 611 c = get_context(ctx); 612 impl_ctx = c->context; 613 } else { 614 // no context given, use the implementation of the current context 615 if (cur_c == NULL) { 616 // no current context 617 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 618 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 619 return setError(EGL_BAD_MATCH, EGL_FALSE); 620 } 621 // not an error, there is just no current context. 622 return EGL_TRUE; 623 } 624 } 625 626 // retrieve the underlying implementation's draw EGLSurface 627 if (draw != EGL_NO_SURFACE) { 628 d = get_surface(draw); 629 // make sure the EGLContext and EGLSurface passed in are for 630 // the same driver 631 if (c && d->impl != c->impl) 632 return setError(EGL_BAD_MATCH, EGL_FALSE); 633 impl_draw = d->surface; 634 } 635 636 // retrieve the underlying implementation's read EGLSurface 637 if (read != EGL_NO_SURFACE) { 638 r = get_surface(read); 639 // make sure the EGLContext and EGLSurface passed in are for 640 // the same driver 641 if (c && r->impl != c->impl) 642 return setError(EGL_BAD_MATCH, EGL_FALSE); 643 impl_read = r->surface; 644 } 645 646 EGLBoolean result; 647 648 if (c) { 649 result = c->cnx->egl.eglMakeCurrent( 650 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 651 } else { 652 result = cur_c->cnx->egl.eglMakeCurrent( 653 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 654 } 655 656 if (result == EGL_TRUE) { 657 658 loseCurrent(cur_c); 659 660 if (ctx != EGL_NO_CONTEXT) { 661 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 662 egl_tls_t::setContext(ctx); 663#if EGL_TRACE 664 if (gEGLDebugLevel > 0) 665 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version]); 666#endif 667 _c.acquire(); 668 _r.acquire(); 669 _d.acquire(); 670 c->read = read; 671 c->draw = draw; 672 } else { 673 setGLHooksThreadSpecific(&gHooksNoContext); 674 egl_tls_t::setContext(EGL_NO_CONTEXT); 675 } 676 } else { 677 // this will LOGE the error 678 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 679 } 680 return result; 681} 682 683 684EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 685 EGLint attribute, EGLint *value) 686{ 687 clearError(); 688 689 egl_display_t const * const dp = validate_display(dpy); 690 if (!dp) return EGL_FALSE; 691 692 ContextRef _c(dp, ctx); 693 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 694 695 egl_context_t * const c = get_context(ctx); 696 697 EGLBoolean result(EGL_TRUE); 698 if (attribute == EGL_CONFIG_ID) { 699 *value = dp->configs[intptr_t(c->config)].configId; 700 } else { 701 // We need to remap EGL_CONFIG_IDs 702 result = c->cnx->egl.eglQueryContext( 703 dp->disp[c->impl].dpy, c->context, attribute, value); 704 } 705 706 return result; 707} 708 709EGLContext eglGetCurrentContext(void) 710{ 711 // could be called before eglInitialize(), but we wouldn't have a context 712 // then, and this function would correctly return EGL_NO_CONTEXT. 713 714 clearError(); 715 716 EGLContext ctx = getContext(); 717 return ctx; 718} 719 720EGLSurface eglGetCurrentSurface(EGLint readdraw) 721{ 722 // could be called before eglInitialize(), but we wouldn't have a context 723 // then, and this function would correctly return EGL_NO_SURFACE. 724 725 clearError(); 726 727 EGLContext ctx = getContext(); 728 if (ctx) { 729 egl_context_t const * const c = get_context(ctx); 730 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 731 switch (readdraw) { 732 case EGL_READ: return c->read; 733 case EGL_DRAW: return c->draw; 734 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 735 } 736 } 737 return EGL_NO_SURFACE; 738} 739 740EGLDisplay eglGetCurrentDisplay(void) 741{ 742 // could be called before eglInitialize(), but we wouldn't have a context 743 // then, and this function would correctly return EGL_NO_DISPLAY. 744 745 clearError(); 746 747 EGLContext ctx = getContext(); 748 if (ctx) { 749 egl_context_t const * const c = get_context(ctx); 750 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 751 return c->dpy; 752 } 753 return EGL_NO_DISPLAY; 754} 755 756EGLBoolean eglWaitGL(void) 757{ 758 // could be called before eglInitialize(), but we wouldn't have a context 759 // then, and this function would return GL_TRUE, which isn't wrong. 760 761 clearError(); 762 763 EGLBoolean res = EGL_TRUE; 764 EGLContext ctx = getContext(); 765 if (ctx) { 766 egl_context_t const * const c = get_context(ctx); 767 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 768 if (uint32_t(c->impl)>=2) 769 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 770 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 771 if (!cnx->dso) 772 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 773 res = cnx->egl.eglWaitGL(); 774 } 775 return res; 776} 777 778EGLBoolean eglWaitNative(EGLint engine) 779{ 780 // could be called before eglInitialize(), but we wouldn't have a context 781 // then, and this function would return GL_TRUE, which isn't wrong. 782 783 clearError(); 784 785 EGLBoolean res = EGL_TRUE; 786 EGLContext ctx = getContext(); 787 if (ctx) { 788 egl_context_t const * const c = get_context(ctx); 789 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 790 if (uint32_t(c->impl)>=2) 791 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 792 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 793 if (!cnx->dso) 794 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 795 res = cnx->egl.eglWaitNative(engine); 796 } 797 return res; 798} 799 800EGLint eglGetError(void) 801{ 802 EGLint result = EGL_SUCCESS; 803 EGLint err; 804 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 805 err = EGL_SUCCESS; 806 egl_connection_t* const cnx = &gEGLImpl[i]; 807 if (cnx->dso) 808 err = cnx->egl.eglGetError(); 809 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 810 result = err; 811 } 812 err = egl_tls_t::getError(); 813 if (result == EGL_SUCCESS) 814 result = err; 815 return result; 816} 817 818// Note: Similar implementations of these functions also exist in 819// gl2.cpp and gl.cpp, and are used by applications that call the 820// exported entry points directly. 821typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); 822typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); 823 824static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL; 825static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL; 826 827static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image) 828{ 829 GLeglImageOES implImage = 830 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 831 glEGLImageTargetTexture2DOES_impl(target, implImage); 832} 833 834static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image) 835{ 836 GLeglImageOES implImage = 837 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 838 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage); 839} 840 841__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 842{ 843 // eglGetProcAddress() could be the very first function called 844 // in which case we must make sure we've initialized ourselves, this 845 // happens the first time egl_get_display() is called. 846 847 clearError(); 848 849 if (egl_init_drivers() == EGL_FALSE) { 850 setError(EGL_BAD_PARAMETER, NULL); 851 return NULL; 852 } 853 854 // The EGL_ANDROID_blob_cache extension should not be exposed to 855 // applications. It is used internally by the Android EGL layer. 856 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) { 857 return NULL; 858 } 859 860 __eglMustCastToProperFunctionPointerType addr; 861 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 862 if (addr) return addr; 863 864 865 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 866 pthread_mutex_lock(&sExtensionMapMutex); 867 868 /* 869 * Since eglGetProcAddress() is not associated to anything, it needs 870 * to return a function pointer that "works" regardless of what 871 * the current context is. 872 * 873 * For this reason, we return a "forwarder", a small stub that takes 874 * care of calling the function associated with the context 875 * currently bound. 876 * 877 * We first look for extensions we've already resolved, if we're seeing 878 * this extension for the first time, we go through all our 879 * implementations and call eglGetProcAddress() and record the 880 * result in the appropriate implementation hooks and return the 881 * address of the forwarder corresponding to that hook set. 882 * 883 */ 884 885 const String8 name(procname); 886 addr = sGLExtentionMap.valueFor(name); 887 const int slot = sGLExtentionSlot; 888 889 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 890 "no more slots for eglGetProcAddress(\"%s\")", 891 procname); 892 893#if EGL_TRACE 894 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 895#endif 896 897 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 898 bool found = false; 899 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 900 egl_connection_t* const cnx = &gEGLImpl[i]; 901 if (cnx->dso && cnx->egl.eglGetProcAddress) { 902 found = true; 903 // Extensions are independent of the bound context 904 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 905 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 906#if EGL_TRACE 907 debugHooks->ext.extensions[slot] = gHooksTrace.ext.extensions[slot] = 908#endif 909 cnx->egl.eglGetProcAddress(procname); 910 } 911 } 912 if (found) { 913 addr = gExtensionForwarders[slot]; 914 915 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) { 916 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr; 917 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper; 918 } 919 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) { 920 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr; 921 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper; 922 } 923 924 sGLExtentionMap.add(name, addr); 925 sGLExtentionSlot++; 926 } 927 } 928 929 pthread_mutex_unlock(&sExtensionMapMutex); 930 return addr; 931} 932 933EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 934{ 935 clearError(); 936 937 egl_display_t const * const dp = validate_display(dpy); 938 if (!dp) return EGL_FALSE; 939 940 SurfaceRef _s(dp, draw); 941 if (!_s.get()) 942 return setError(EGL_BAD_SURFACE, EGL_FALSE); 943 944#if EGL_TRACE 945 if (gEGLDebugLevel > 0) 946 GLTrace_eglSwapBuffers(dpy, draw); 947#endif 948 949 egl_surface_t const * const s = get_surface(draw); 950 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 951} 952 953EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 954 NativePixmapType target) 955{ 956 clearError(); 957 958 egl_display_t const * const dp = validate_display(dpy); 959 if (!dp) return EGL_FALSE; 960 961 SurfaceRef _s(dp, surface); 962 if (!_s.get()) 963 return setError(EGL_BAD_SURFACE, EGL_FALSE); 964 965 egl_surface_t const * const s = get_surface(surface); 966 return s->cnx->egl.eglCopyBuffers( 967 dp->disp[s->impl].dpy, s->surface, target); 968} 969 970const char* eglQueryString(EGLDisplay dpy, EGLint name) 971{ 972 clearError(); 973 974 egl_display_t const * const dp = validate_display(dpy); 975 if (!dp) return (const char *) NULL; 976 977 switch (name) { 978 case EGL_VENDOR: 979 return dp->getVendorString(); 980 case EGL_VERSION: 981 return dp->getVersionString(); 982 case EGL_EXTENSIONS: 983 return dp->getExtensionString(); 984 case EGL_CLIENT_APIS: 985 return dp->getClientApiString(); 986 case EGL_VERSION_HW_ANDROID: { 987 if (gEGLImpl[IMPL_HARDWARE].dso) { 988 return dp->disp[IMPL_HARDWARE].queryString.version; 989 } 990 return dp->disp[IMPL_SOFTWARE].queryString.version; 991 } 992 } 993 return setError(EGL_BAD_PARAMETER, (const char *)0); 994} 995 996 997// ---------------------------------------------------------------------------- 998// EGL 1.1 999// ---------------------------------------------------------------------------- 1000 1001EGLBoolean eglSurfaceAttrib( 1002 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1003{ 1004 clearError(); 1005 1006 egl_display_t const * const dp = validate_display(dpy); 1007 if (!dp) return EGL_FALSE; 1008 1009 SurfaceRef _s(dp, surface); 1010 if (!_s.get()) 1011 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1012 1013 egl_surface_t const * const s = get_surface(surface); 1014 if (s->cnx->egl.eglSurfaceAttrib) { 1015 return s->cnx->egl.eglSurfaceAttrib( 1016 dp->disp[s->impl].dpy, s->surface, attribute, value); 1017 } 1018 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1019} 1020 1021EGLBoolean eglBindTexImage( 1022 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1023{ 1024 clearError(); 1025 1026 egl_display_t const * const dp = validate_display(dpy); 1027 if (!dp) return EGL_FALSE; 1028 1029 SurfaceRef _s(dp, surface); 1030 if (!_s.get()) 1031 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1032 1033 egl_surface_t const * const s = get_surface(surface); 1034 if (s->cnx->egl.eglBindTexImage) { 1035 return s->cnx->egl.eglBindTexImage( 1036 dp->disp[s->impl].dpy, s->surface, buffer); 1037 } 1038 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1039} 1040 1041EGLBoolean eglReleaseTexImage( 1042 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1043{ 1044 clearError(); 1045 1046 egl_display_t const * const dp = validate_display(dpy); 1047 if (!dp) return EGL_FALSE; 1048 1049 SurfaceRef _s(dp, surface); 1050 if (!_s.get()) 1051 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1052 1053 egl_surface_t const * const s = get_surface(surface); 1054 if (s->cnx->egl.eglReleaseTexImage) { 1055 return s->cnx->egl.eglReleaseTexImage( 1056 dp->disp[s->impl].dpy, s->surface, buffer); 1057 } 1058 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1059} 1060 1061EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1062{ 1063 clearError(); 1064 1065 egl_display_t const * const dp = validate_display(dpy); 1066 if (!dp) return EGL_FALSE; 1067 1068 EGLBoolean res = EGL_TRUE; 1069 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1070 egl_connection_t* const cnx = &gEGLImpl[i]; 1071 if (cnx->dso) { 1072 if (cnx->egl.eglSwapInterval) { 1073 if (cnx->egl.eglSwapInterval( 1074 dp->disp[i].dpy, interval) == EGL_FALSE) { 1075 res = EGL_FALSE; 1076 } 1077 } 1078 } 1079 } 1080 return res; 1081} 1082 1083 1084// ---------------------------------------------------------------------------- 1085// EGL 1.2 1086// ---------------------------------------------------------------------------- 1087 1088EGLBoolean eglWaitClient(void) 1089{ 1090 clearError(); 1091 1092 // could be called before eglInitialize(), but we wouldn't have a context 1093 // then, and this function would return GL_TRUE, which isn't wrong. 1094 EGLBoolean res = EGL_TRUE; 1095 EGLContext ctx = getContext(); 1096 if (ctx) { 1097 egl_context_t const * const c = get_context(ctx); 1098 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1099 if (uint32_t(c->impl)>=2) 1100 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1101 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1102 if (!cnx->dso) 1103 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1104 if (cnx->egl.eglWaitClient) { 1105 res = cnx->egl.eglWaitClient(); 1106 } else { 1107 res = cnx->egl.eglWaitGL(); 1108 } 1109 } 1110 return res; 1111} 1112 1113EGLBoolean eglBindAPI(EGLenum api) 1114{ 1115 clearError(); 1116 1117 if (egl_init_drivers() == EGL_FALSE) { 1118 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1119 } 1120 1121 // bind this API on all EGLs 1122 EGLBoolean res = EGL_TRUE; 1123 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1124 egl_connection_t* const cnx = &gEGLImpl[i]; 1125 if (cnx->dso) { 1126 if (cnx->egl.eglBindAPI) { 1127 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1128 res = EGL_FALSE; 1129 } 1130 } 1131 } 1132 } 1133 return res; 1134} 1135 1136EGLenum eglQueryAPI(void) 1137{ 1138 clearError(); 1139 1140 if (egl_init_drivers() == EGL_FALSE) { 1141 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1142 } 1143 1144 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1145 egl_connection_t* const cnx = &gEGLImpl[i]; 1146 if (cnx->dso) { 1147 if (cnx->egl.eglQueryAPI) { 1148 // the first one we find is okay, because they all 1149 // should be the same 1150 return cnx->egl.eglQueryAPI(); 1151 } 1152 } 1153 } 1154 // or, it can only be OpenGL ES 1155 return EGL_OPENGL_ES_API; 1156} 1157 1158EGLBoolean eglReleaseThread(void) 1159{ 1160 clearError(); 1161 1162 // If there is context bound to the thread, release it 1163 loseCurrent(get_context(getContext())); 1164 1165 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1166 egl_connection_t* const cnx = &gEGLImpl[i]; 1167 if (cnx->dso) { 1168 if (cnx->egl.eglReleaseThread) { 1169 cnx->egl.eglReleaseThread(); 1170 } 1171 } 1172 } 1173 egl_tls_t::clearTLS(); 1174#if EGL_TRACE 1175 if (gEGLDebugLevel > 0) 1176 GLTrace_eglReleaseThread(); 1177#endif 1178 return EGL_TRUE; 1179} 1180 1181EGLSurface eglCreatePbufferFromClientBuffer( 1182 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1183 EGLConfig config, const EGLint *attrib_list) 1184{ 1185 clearError(); 1186 1187 egl_display_t const* dp = 0; 1188 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1189 if (!cnx) return EGL_FALSE; 1190 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1191 return cnx->egl.eglCreatePbufferFromClientBuffer( 1192 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1193 buftype, buffer, 1194 dp->configs[intptr_t(config)].config, attrib_list); 1195 } 1196 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1197} 1198 1199// ---------------------------------------------------------------------------- 1200// EGL_EGLEXT_VERSION 3 1201// ---------------------------------------------------------------------------- 1202 1203EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1204 const EGLint *attrib_list) 1205{ 1206 clearError(); 1207 1208 egl_display_t const * const dp = validate_display(dpy); 1209 if (!dp) return EGL_FALSE; 1210 1211 SurfaceRef _s(dp, surface); 1212 if (!_s.get()) 1213 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1214 1215 egl_surface_t const * const s = get_surface(surface); 1216 if (s->cnx->egl.eglLockSurfaceKHR) { 1217 return s->cnx->egl.eglLockSurfaceKHR( 1218 dp->disp[s->impl].dpy, s->surface, attrib_list); 1219 } 1220 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1221} 1222 1223EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1224{ 1225 clearError(); 1226 1227 egl_display_t const * const dp = validate_display(dpy); 1228 if (!dp) return EGL_FALSE; 1229 1230 SurfaceRef _s(dp, surface); 1231 if (!_s.get()) 1232 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1233 1234 egl_surface_t const * const s = get_surface(surface); 1235 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1236 return s->cnx->egl.eglUnlockSurfaceKHR( 1237 dp->disp[s->impl].dpy, s->surface); 1238 } 1239 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1240} 1241 1242EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1243 EGLClientBuffer buffer, const EGLint *attrib_list) 1244{ 1245 clearError(); 1246 1247 egl_display_t const * const dp = validate_display(dpy); 1248 if (!dp) return EGL_NO_IMAGE_KHR; 1249 1250 if (ctx != EGL_NO_CONTEXT) { 1251 ContextRef _c(dp, ctx); 1252 if (!_c.get()) 1253 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1254 egl_context_t * const c = get_context(ctx); 1255 // since we have an EGLContext, we know which implementation to use 1256 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1257 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1258 if (image == EGL_NO_IMAGE_KHR) 1259 return image; 1260 1261 egl_image_t* result = new egl_image_t(dpy, ctx); 1262 result->images[c->impl] = image; 1263 return (EGLImageKHR)result; 1264 } else { 1265 // EGL_NO_CONTEXT is a valid parameter 1266 1267 /* Since we don't have a way to know which implementation to call, 1268 * we're calling all of them. If at least one of the implementation 1269 * succeeded, this is a success. 1270 */ 1271 1272 EGLint currentError = eglGetError(); 1273 1274 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1275 bool success = false; 1276 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1277 egl_connection_t* const cnx = &gEGLImpl[i]; 1278 implImages[i] = EGL_NO_IMAGE_KHR; 1279 if (cnx->dso) { 1280 if (cnx->egl.eglCreateImageKHR) { 1281 implImages[i] = cnx->egl.eglCreateImageKHR( 1282 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1283 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1284 success = true; 1285 } 1286 } 1287 } 1288 } 1289 1290 if (!success) { 1291 // failure, if there was an error when we entered this function, 1292 // the error flag must not be updated. 1293 // Otherwise, the error is whatever happened in the implementation 1294 // that faulted. 1295 if (currentError != EGL_SUCCESS) { 1296 setError(currentError, EGL_NO_IMAGE_KHR); 1297 } 1298 return EGL_NO_IMAGE_KHR; 1299 } else { 1300 // In case of success, we need to clear all error flags 1301 // (especially those caused by the implementation that didn't 1302 // succeed). TODO: we could avoid this if we knew this was 1303 // a "full" success (all implementation succeeded). 1304 eglGetError(); 1305 } 1306 1307 egl_image_t* result = new egl_image_t(dpy, ctx); 1308 memcpy(result->images, implImages, sizeof(implImages)); 1309 return (EGLImageKHR)result; 1310 } 1311} 1312 1313EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1314{ 1315 clearError(); 1316 1317 egl_display_t const * const dp = validate_display(dpy); 1318 if (!dp) return EGL_FALSE; 1319 1320 ImageRef _i(dp, img); 1321 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1322 1323 egl_image_t* image = get_image(img); 1324 bool success = false; 1325 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1326 egl_connection_t* const cnx = &gEGLImpl[i]; 1327 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1328 if (cnx->dso) { 1329 if (cnx->egl.eglDestroyImageKHR) { 1330 if (cnx->egl.eglDestroyImageKHR( 1331 dp->disp[i].dpy, image->images[i])) { 1332 success = true; 1333 } 1334 } 1335 } 1336 } 1337 } 1338 if (!success) 1339 return EGL_FALSE; 1340 1341 _i.terminate(); 1342 1343 return EGL_TRUE; 1344} 1345 1346// ---------------------------------------------------------------------------- 1347// EGL_EGLEXT_VERSION 5 1348// ---------------------------------------------------------------------------- 1349 1350 1351EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1352{ 1353 clearError(); 1354 1355 egl_display_t const * const dp = validate_display(dpy); 1356 if (!dp) return EGL_NO_SYNC_KHR; 1357 1358 EGLContext ctx = eglGetCurrentContext(); 1359 ContextRef _c(dp, ctx); 1360 if (!_c.get()) 1361 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 1362 1363 egl_context_t * const c = get_context(ctx); 1364 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1365 if (c->cnx->egl.eglCreateSyncKHR) { 1366 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 1367 dp->disp[c->impl].dpy, type, attrib_list); 1368 if (sync == EGL_NO_SYNC_KHR) 1369 return sync; 1370 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 1371 } 1372 return (EGLSyncKHR)result; 1373} 1374 1375EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1376{ 1377 clearError(); 1378 1379 egl_display_t const * const dp = validate_display(dpy); 1380 if (!dp) return EGL_FALSE; 1381 1382 SyncRef _s(dp, sync); 1383 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1384 egl_sync_t* syncObject = get_sync(sync); 1385 1386 EGLContext ctx = syncObject->context; 1387 ContextRef _c(dp, ctx); 1388 if (!_c.get()) 1389 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1390 1391 EGLBoolean result = EGL_FALSE; 1392 egl_context_t * const c = get_context(ctx); 1393 if (c->cnx->egl.eglDestroySyncKHR) { 1394 result = c->cnx->egl.eglDestroySyncKHR( 1395 dp->disp[c->impl].dpy, syncObject->sync); 1396 if (result) 1397 _s.terminate(); 1398 } 1399 return result; 1400} 1401 1402EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1403{ 1404 clearError(); 1405 1406 egl_display_t const * const dp = validate_display(dpy); 1407 if (!dp) return EGL_FALSE; 1408 1409 SyncRef _s(dp, sync); 1410 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1411 egl_sync_t* syncObject = get_sync(sync); 1412 1413 EGLContext ctx = syncObject->context; 1414 ContextRef _c(dp, ctx); 1415 if (!_c.get()) 1416 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1417 1418 egl_context_t * const c = get_context(ctx); 1419 if (c->cnx->egl.eglClientWaitSyncKHR) { 1420 return c->cnx->egl.eglClientWaitSyncKHR( 1421 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 1422 } 1423 1424 return EGL_FALSE; 1425} 1426 1427EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1428{ 1429 clearError(); 1430 1431 egl_display_t const * const dp = validate_display(dpy); 1432 if (!dp) return EGL_FALSE; 1433 1434 SyncRef _s(dp, sync); 1435 if (!_s.get()) 1436 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1437 1438 egl_sync_t* syncObject = get_sync(sync); 1439 EGLContext ctx = syncObject->context; 1440 ContextRef _c(dp, ctx); 1441 if (!_c.get()) 1442 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1443 1444 egl_context_t * const c = get_context(ctx); 1445 if (c->cnx->egl.eglGetSyncAttribKHR) { 1446 return c->cnx->egl.eglGetSyncAttribKHR( 1447 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 1448 } 1449 1450 return EGL_FALSE; 1451} 1452 1453// ---------------------------------------------------------------------------- 1454// ANDROID extensions 1455// ---------------------------------------------------------------------------- 1456 1457/* ANDROID extensions entry-point go here */ 1458 1459// ---------------------------------------------------------------------------- 1460// NVIDIA extensions 1461// ---------------------------------------------------------------------------- 1462EGLuint64NV eglGetSystemTimeFrequencyNV() 1463{ 1464 clearError(); 1465 1466 if (egl_init_drivers() == EGL_FALSE) { 1467 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1468 } 1469 1470 EGLuint64NV ret = 0; 1471 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1472 1473 if (cnx->dso) { 1474 if (cnx->egl.eglGetSystemTimeFrequencyNV) { 1475 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1476 } 1477 } 1478 1479 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1480} 1481 1482EGLuint64NV eglGetSystemTimeNV() 1483{ 1484 clearError(); 1485 1486 if (egl_init_drivers() == EGL_FALSE) { 1487 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1488 } 1489 1490 EGLuint64NV ret = 0; 1491 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1492 1493 if (cnx->dso) { 1494 if (cnx->egl.eglGetSystemTimeNV) { 1495 return cnx->egl.eglGetSystemTimeNV(); 1496 } 1497 } 1498 1499 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1500} 1501