| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "EglGlobalInfo.h" |
| |
| #include "ClientAPIExts.h" |
| #include "EglDisplay.h" |
| #include "EglOsApi.h" |
| |
| #include "host-common/GfxstreamFatalError.h" |
| #include "GLcommon/GLutils.h" |
| |
| #include <string.h> |
| |
| using emugl::ABORT_REASON_OTHER; |
| using emugl::FatalError; |
| |
| namespace { |
| |
| static EGLBoolean sEgl2Egl = false; |
| |
| static EglGlobalInfo* sSingleton(bool nullEgl = false) { |
| static EglGlobalInfo* i = new EglGlobalInfo(nullEgl); |
| return i; |
| } |
| |
| static bool sEgl2EglSyncSafeToUse = false; |
| |
| } // namespace |
| |
| void EglGlobalInfo::setEgl2Egl(EGLBoolean enable, bool nullEgl) { |
| if (nullEgl && enable == EGL_FALSE) { |
| // No point in nullEgl backend for non egl2egl cases. |
| GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)); |
| } |
| sEgl2Egl = enable; |
| setGles2Gles(enable); |
| sSingleton(nullEgl); |
| } |
| |
| bool EglGlobalInfo::isEgl2Egl() { |
| return isGles2Gles(); |
| } |
| |
| void EglGlobalInfo::setEgl2EglSyncSafeToUse(EGLBoolean enable) { |
| sEgl2EglSyncSafeToUse = enable == EGL_TRUE ? true : false; |
| } |
| |
| bool EglGlobalInfo::isEgl2EglSyncSafeToUse() { |
| return !isGles2Gles() || sEgl2EglSyncSafeToUse; |
| } |
| |
| // static |
| EglGlobalInfo* EglGlobalInfo::getInstance(bool nullEgl) { |
| return sSingleton(nullEgl); |
| } |
| |
| EglGlobalInfo::EglGlobalInfo(bool nullEgl) { |
| #if defined(ANDROID) || defined(__QNX__) |
| sEgl2Egl = true; |
| sEgl2EglSyncSafeToUse = true; |
| m_engine = EglOS:: |
| getEgl2EglHostInstance(nullEgl); |
| #else |
| if (sEgl2Egl) { |
| m_engine = EglOS::getEgl2EglHostInstance(nullEgl); |
| } else { |
| m_engine = EglOS::Engine::getHostInstance(); |
| } |
| #endif |
| m_display = m_engine->getDefaultDisplay(); |
| } |
| |
| EglGlobalInfo::~EglGlobalInfo() { |
| for (size_t n = 0; n < m_displays.size(); ++n) { |
| delete m_displays[n]; |
| } |
| } |
| |
| EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy, |
| EglOS::Display* idpy) { |
| //search if it already exists. |
| android::base::AutoLock mutex(m_lock); |
| for (size_t n = 0; n < m_displays.size(); ++n) { |
| if (m_displays[n]->getEglOsEngineDisplay() == dpy) { |
| return m_displays[n]; |
| } |
| } |
| |
| if (!idpy) { |
| return NULL; |
| } |
| EglDisplay* result = new EglDisplay(dpy, idpy); |
| m_displays.push_back(result); |
| return result; |
| } |
| |
| bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) { |
| android::base::AutoLock mutex(m_lock); |
| for (size_t n = 0; n < m_displays.size(); ++n) { |
| if (m_displays[n] == static_cast<EglDisplay*>(dpy)) { |
| delete m_displays[n]; |
| m_displays.erase(m_displays.begin() + n); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| EglDisplay* EglGlobalInfo::getDisplayFromDisplayType(EGLNativeDisplayType dpy) const { |
| android::base::AutoLock mutex(m_lock); |
| for (size_t n = 0; n < m_displays.size(); ++n) { |
| if (m_displays[n]->getEglOsEngineDisplay() == dpy) { |
| return m_displays[n]; |
| } |
| } |
| return NULL; |
| } |
| |
| EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) const { |
| android::base::AutoLock mutex(m_lock); |
| for (size_t n = 0; n < m_displays.size(); ++n) { |
| if (m_displays[n] == static_cast<EglDisplay*>(dpy)) { |
| return m_displays[n]; |
| } |
| } |
| return NULL; |
| } |
| |
| void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver) { |
| android::base::AutoLock mutex(m_lock); |
| if (!m_gles_extFuncs_inited[ver]) { |
| ClientAPIExts::initClientFuncs(m_gles_ifaces[ver], (int)ver - 1); |
| m_gles_extFuncs_inited[ver] = true; |
| } |
| } |
| |
| void EglGlobalInfo::markSurfaceForDestroy(EglDisplay* display, |
| EGLSurface toDestroy) { |
| android::base::AutoLock mutex(m_lock); |
| assert(display); |
| m_surfaceDestroyList.push_back( |
| std::make_pair(display, toDestroy)); |
| } |
| |
| void EglGlobalInfo::sweepDestroySurfaces() { |
| android::base::AutoLock mutex(m_lock); |
| for (auto elt : m_surfaceDestroyList) { |
| EglDisplay* dpy = elt.first; |
| assert(dpy); |
| EGLSurface surface = elt.second; |
| SurfacePtr surfacePtr = dpy->getSurface(surface); |
| if (surfacePtr) { |
| m_gles_ifaces[GLES_2_0]->deleteRbo(surfacePtr->glRboColor); |
| m_gles_ifaces[GLES_2_0]->deleteRbo(surfacePtr->glRboDepth); |
| } |
| dpy->removeSurface(surface); |
| } |
| m_surfaceDestroyList.clear(); |
| } |