1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897 |
- /*
- ** 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 <dlfcn.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <hardware/gralloc.h>
- #include <system/window.h>
- #include <EGL/egl.h>
- #include <EGL/eglext.h>
- #include <cutils/log.h>
- #include <cutils/atomic.h>
- #include <cutils/compiler.h>
- #include <cutils/properties.h>
- #include <cutils/memory.h>
- #include <utils/KeyedVector.h>
- #include <utils/SortedVector.h>
- #include <utils/String8.h>
- #include <utils/Trace.h>
- #include "../egl_impl.h"
- #include "../glestrace.h"
- #include "../hooks.h"
- #include "egl_display.h"
- #include "egl_object.h"
- #include "egl_tls.h"
- #include "egldefs.h"
- using namespace android;
- // This extension has not been ratified yet, so can't be shipped.
- // Implementation is incomplete and untested.
- #define ENABLE_EGL_KHR_GL_COLORSPACE 0
- // ----------------------------------------------------------------------------
- namespace android {
- 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
- * listd 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 =
- "EGL_KHR_get_all_proc_addresses "
- "EGL_ANDROID_presentation_time "
- "EGL_KHR_swap_buffers_with_damage "
- ;
- extern char const * const gExtensionString =
- "EGL_KHR_image " // mandatory
- "EGL_KHR_image_base " // mandatory
- "EGL_KHR_image_pixmap "
- "EGL_KHR_lock_surface "
- #if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
- "EGL_KHR_gl_colorspace "
- #endif
- "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_buffer_age " // strongly recommended with partial_update
- "EGL_KHR_create_context_no_error "
- ;
- // 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_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 },
- };
- /*
- * 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") || \
- !strcmp((procname), "eglDupNativeFenceFDANDROID"))
- // accesses protected by sExtensionMapMutex
- static DefaultKeyedVector<String8, __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 int getEGLDebugLevel();
- extern void setEGLDebugLevel(int level);
- extern gl_hooks_t gHooksTrace;
- } // namespace android;
- // ----------------------------------------------------------------------------
- static inline void clearError() { egl_tls_t::clearError(); }
- static inline EGLContext getContext() { return egl_tls_t::getContext(); }
- // ----------------------------------------------------------------------------
- EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
- {
- 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;
- }
- // ----------------------------------------------------------------------------
- // Initialization
- // ----------------------------------------------------------------------------
- EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
- {
- clearError();
- egl_display_ptr dp = get_display(dpy);
- if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- EGLBoolean res = dp->initialize(major, minor);
- return res;
- }
- 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.
- clearError();
- egl_display_ptr dp = get_display(dpy);
- if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- EGLBoolean res = dp->terminate();
- return res;
- }
- // ----------------------------------------------------------------------------
- // configuration
- // ----------------------------------------------------------------------------
- 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, 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 eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
- 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, 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;
- }
- 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 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
- EGLint attribute, EGLint *value)
- {
- 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);
- }
- // ----------------------------------------------------------------------------
- // surfaces
- // ----------------------------------------------------------------------------
- // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
- // been added to the Khronos egl.h.
- #define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
- #define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
- #define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
- // Turn linear formats into corresponding sRGB formats when colorspace is
- // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
- // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
- // the modification isn't possible, the original dataSpace is returned.
- static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
- EGLint colorspace) {
- if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
- return HAL_DATASPACE_SRGB_LINEAR;
- } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
- return HAL_DATASPACE_SRGB;
- }
- return dataSpace;
- }
- EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
- NativeWindowType window,
- 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;
- int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- if (result != OK) {
- 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);
- }
- // 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 format;
- android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
- #if WORKAROUND_BUG_10194508
- if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
- &format)) {
- ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x",
- eglGetError());
- format = 0;
- }
- #else
- EGLint a = 0;
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
- if (a > 0) {
- // alpha-channel requested, there's really only one suitable format
- if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
- &format)) {
- ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x",
- eglGetError());
- format = HAL_PIXEL_FORMAT_RGBA_8888;
- }
- } else {
- EGLint r, g, b;
- r = g = b = 0;
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
- EGLint colorDepth = r + g + b;
- if (colorDepth <= 16) {
- format = HAL_PIXEL_FORMAT_RGB_565;
- } else {
- format = HAL_PIXEL_FORMAT_RGBX_8888;
- }
- }
- #endif
- // now select a corresponding sRGB format if needed
- if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
- for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
- if (*attr == EGL_GL_COLORSPACE_KHR) {
- if (ENABLE_EGL_KHR_GL_COLORSPACE) {
- dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
- } else {
- // Normally we'd pass through unhandled attributes to
- // the driver. But in case the driver implements this
- // extension but we're disabling it, we want to prevent
- // it getting through -- support will be broken without
- // our help.
- ALOGE("sRGB window surfaces not supported");
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
- }
- }
- }
- }
- if (format != 0) {
- 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);
- }
- }
- if (dataSpace != 0) {
- 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, 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) {
- 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, 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) {
- 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, cnx);
- return s;
- }
- }
- return EGL_NO_SURFACE;
- }
- EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
- {
- 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, 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 eglQuerySurface( 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, EGL_FALSE);
- egl_surface_t const * const s = get_surface(surface);
- return s->cnx->egl.eglQuerySurface(
- dp->disp.dpy, s->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);
- return;
- }
- }
- // ----------------------------------------------------------------------------
- // Contexts
- // ----------------------------------------------------------------------------
- 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);
- #if EGL_TRACE
- if (getEGLDebugLevel() > 0)
- GLTrace_eglCreateContext(version, c);
- #endif
- return c;
- }
- }
- return EGL_NO_CONTEXT;
- }
- 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, 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 eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
- EGLSurface read, EGLContext ctx)
- {
- clearError();
- egl_display_ptr dp = validate_display(dpy);
- if (!dp) return setError(EGL_BAD_DISPLAY, 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, 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, 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, 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, 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, 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);
- #if EGL_TRACE
- if (getEGLDebugLevel() > 0)
- GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
- #endif
- _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(), EGL_FALSE);
- }
- return result;
- }
- 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, EGL_FALSE);
- egl_context_t * const c = get_context(ctx);
- return c->cnx->egl.eglQueryContext(
- dp->disp.dpy, c->context, 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.
- clearError();
- EGLContext ctx = getContext();
- return ctx;
- }
- 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.
- 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;
- }
- 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.
- 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;
- }
- EGLBoolean eglWaitGL(void)
- {
- clearError();
- egl_connection_t* const cnx = &gEGLImpl;
- if (!cnx->dso)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- return cnx->egl.eglWaitGL();
- }
- EGLBoolean eglWaitNative(EGLint engine)
- {
- clearError();
- egl_connection_t* const cnx = &gEGLImpl;
- if (!cnx->dso)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- return cnx->egl.eglWaitNative(engine);
- }
- EGLint eglGetError(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 = 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;
- }
- __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.
- clearError();
- 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 String8 name(procname);
- addr = sGLExtentionMap.valueFor(name);
- const int slot = sGLExtentionSlot;
- ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
- "no more slots for eglGetProcAddress(\"%s\")",
- procname);
- #if EGL_TRACE
- gl_hooks_t *debugHooks = GLTrace_getGLHooks();
- #endif
- 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] =
- #if EGL_TRACE
- debugHooks->ext.extensions[slot] =
- gHooksTrace.ext.extensions[slot] =
- #endif
- cnx->egl.eglGetProcAddress(procname);
- if (addr) found = true;
- }
- if (found) {
- addr = gExtensionForwarders[slot];
- sGLExtentionMap.add(name, addr);
- sGLExtentionSlot++;
- }
- }
- pthread_mutex_unlock(&sExtensionMapMutex);
- return addr;
- }
- class FrameCompletionThread : public Thread {
- public:
- static void queueSync(EGLSyncKHR sync) {
- static sp<FrameCompletionThread> thread(new FrameCompletionThread);
- static bool running = false;
- if (!running) {
- thread->run("GPUFrameCompletion");
- running = true;
- }
- {
- Mutex::Autolock lock(thread->mMutex);
- ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
- thread->mFramesQueued).string());
- thread->mQueue.push_back(sync);
- thread->mCondition.signal();
- thread->mFramesQueued++;
- ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
- }
- }
- private:
- FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
- virtual bool threadLoop() {
- EGLSyncKHR sync;
- uint32_t frameNum;
- {
- Mutex::Autolock lock(mMutex);
- while (mQueue.isEmpty()) {
- mCondition.wait(mMutex);
- }
- sync = mQueue[0];
- frameNum = mFramesCompleted;
- }
- EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- {
- ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
- frameNum).string());
- 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);
- }
- {
- Mutex::Autolock lock(mMutex);
- mQueue.removeAt(0);
- mFramesCompleted++;
- ATRACE_INT("GPU Frames Outstanding", mQueue.size());
- }
- return true;
- }
- uint32_t mFramesQueued;
- uint32_t mFramesCompleted;
- Vector<EGLSyncKHR> mQueue;
- Condition mCondition;
- Mutex mMutex;
- };
- 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, EGL_FALSE);
- #if EGL_TRACE
- gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
- if (getEGLDebugLevel() > 0) {
- if (trace_hooks == NULL) {
- if (GLTrace_start() < 0) {
- ALOGE("Disabling Tracer for OpenGL ES");
- setEGLDebugLevel(0);
- } else {
- // switch over to the trace version of hooks
- EGLContext ctx = egl_tls_t::getContext();
- egl_context_t * const c = get_context(ctx);
- if (c) {
- setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
- GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
- }
- }
- }
- GLTrace_eglSwapBuffers(dpy, draw);
- } else if (trace_hooks != NULL) {
- // tracing is now disabled, so switch back to the non trace version
- EGLContext ctx = egl_tls_t::getContext();
- egl_context_t * const c = get_context(ctx);
- if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
- GLTrace_stop();
- }
- #endif
- egl_surface_t const * 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 (n_rects == 0) {
- return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
- }
- Vector<android_native_rect_t> androidRects;
- 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->win.get(), androidRects.array(),
- 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);
- }
- EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
- NativePixmapType target)
- {
- 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, EGL_FALSE);
- egl_surface_t const * const s = get_surface(surface);
- return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
- }
- 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->getVendorString();
- case EGL_VERSION:
- return dp->getVersionString();
- case EGL_EXTENSIONS:
- return dp->getExtensionString();
- case EGL_CLIENT_APIS:
- return dp->getClientApiString();
- }
- return setError(EGL_BAD_PARAMETER, (const char *)0);
- }
- EGLAPI const char* eglQueryStringImplementationANDROID(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;
- }
- return setError(EGL_BAD_PARAMETER, (const char *)0);
- }
- // ----------------------------------------------------------------------------
- // EGL 1.1
- // ----------------------------------------------------------------------------
- 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, EGL_FALSE);
- egl_surface_t const * const s = get_surface(surface);
- if (s->cnx->egl.eglSurfaceAttrib) {
- return s->cnx->egl.eglSurfaceAttrib(
- dp->disp.dpy, s->surface, attribute, value);
- }
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- }
- 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, 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, EGL_FALSE);
- }
- EGLBoolean eglReleaseTexImage(
- 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, 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, EGL_FALSE);
- }
- EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
- {
- 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;
- }
- // ----------------------------------------------------------------------------
- // EGL 1.2
- // ----------------------------------------------------------------------------
- EGLBoolean eglWaitClient(void)
- {
- clearError();
- egl_connection_t* const cnx = &gEGLImpl;
- if (!cnx->dso)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- EGLBoolean res;
- if (cnx->egl.eglWaitClient) {
- res = cnx->egl.eglWaitClient();
- } else {
- res = cnx->egl.eglWaitGL();
- }
- return res;
- }
- EGLBoolean eglBindAPI(EGLenum api)
- {
- clearError();
- if (egl_init_drivers() == EGL_FALSE) {
- return setError(EGL_BAD_PARAMETER, 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;
- }
- EGLenum eglQueryAPI(void)
- {
- clearError();
- if (egl_init_drivers() == EGL_FALSE) {
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- }
- 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 eglReleaseThread(void)
- {
- clearError();
- #if EGL_TRACE
- if (getEGLDebugLevel() > 0)
- GLTrace_eglReleaseThread();
- #endif
- // If there is context bound to the thread, release it
- egl_display_t::loseCurrent(get_context(getContext()));
- egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso && cnx->egl.eglReleaseThread) {
- cnx->egl.eglReleaseThread();
- }
- egl_tls_t::clearTLS();
- return EGL_TRUE;
- }
- 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_EGLEXT_VERSION 3
- // ----------------------------------------------------------------------------
- EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
- const EGLint *attrib_list)
- {
- 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, 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, EGL_FALSE);
- }
- EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
- {
- 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, 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, EGL_FALSE);
- }
- 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();
- 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, attrib_list);
- }
- return result;
- }
- EGLBoolean eglDestroyImageKHR(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;
- }
- // ----------------------------------------------------------------------------
- // EGL_EGLEXT_VERSION 5
- // ----------------------------------------------------------------------------
- EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
- {
- clearError();
- const egl_display_ptr dp = validate_display(dpy);
- if (!dp) return EGL_NO_SYNC_KHR;
- 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;
- }
- EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
- {
- 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.eglDestroySyncKHR) {
- result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
- }
- return result;
- }
- 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;
- }
- 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.eglClientWaitSyncKHR) {
- result = cnx->egl.eglClientWaitSyncKHR(
- dp->disp.dpy, sync, flags, timeout);
- }
- return result;
- }
- 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.eglGetSyncAttribKHR) {
- result = cnx->egl.eglGetSyncAttribKHR(
- dp->disp.dpy, sync, attribute, value);
- }
- return result;
- }
- EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
- {
- 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;
- }
- 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.eglDestroyStreamKHR) {
- result = cnx->egl.eglDestroyStreamKHR(
- dp->disp.dpy, stream);
- }
- return result;
- }
- 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.eglStreamAttribKHR) {
- result = cnx->egl.eglStreamAttribKHR(
- dp->disp.dpy, stream, attribute, value);
- }
- return result;
- }
- 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.eglQueryStreamKHR) {
- result = cnx->egl.eglQueryStreamKHR(
- dp->disp.dpy, stream, attribute, value);
- }
- return result;
- }
- EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
- EGLenum attribute, EGLuint64KHR *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;
- }
- 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.eglQueryStreamTimeKHR) {
- result = cnx->egl.eglQueryStreamTimeKHR(
- dp->disp.dpy, stream, attribute, value);
- }
- return result;
- }
- EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
- EGLStreamKHR stream, const EGLint *attrib_list)
- {
- 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, cnx);
- return s;
- }
- }
- return EGL_NO_SURFACE;
- }
- 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.eglStreamConsumerGLTextureExternalKHR) {
- result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
- dp->disp.dpy, stream);
- }
- return result;
- }
- EGLBoolean eglStreamConsumerAcquireKHR(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.eglStreamConsumerAcquireKHR) {
- result = cnx->egl.eglStreamConsumerAcquireKHR(
- dp->disp.dpy, stream);
- }
- return result;
- }
- EGLBoolean eglStreamConsumerReleaseKHR(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;
- }
- EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
- 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;
- }
- EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
- EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
- {
- 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;
- }
- // ----------------------------------------------------------------------------
- // EGL_EGLEXT_VERSION 15
- // ----------------------------------------------------------------------------
- EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
- 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;
- }
- // ----------------------------------------------------------------------------
- // ANDROID extensions
- // ----------------------------------------------------------------------------
- EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
- {
- clearError();
- 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 eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
- EGLnsecsANDROID time)
- {
- clearError();
- 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->win.get(), time);
- return EGL_TRUE;
- }
- // ----------------------------------------------------------------------------
- // NVIDIA extensions
- // ----------------------------------------------------------------------------
- EGLuint64NV eglGetSystemTimeFrequencyNV()
- {
- clearError();
- if (egl_init_drivers() == EGL_FALSE) {
- return setError(EGL_BAD_PARAMETER, 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, 0);
- }
- EGLuint64NV eglGetSystemTimeNV()
- {
- clearError();
- if (egl_init_drivers() == EGL_FALSE) {
- return setError(EGL_BAD_PARAMETER, 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, 0);
- }
- // ----------------------------------------------------------------------------
- // Partial update extension
- // ----------------------------------------------------------------------------
- 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;
- }
|