1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "EglGlobalInfo.h"
17
18 #include "ClientAPIExts.h"
19 #include "EglDisplay.h"
20 #include "EglOsApi.h"
21
22 #include "host-common/GfxstreamFatalError.h"
23 #include "GLcommon/GLutils.h"
24
25 #include <string.h>
26
27 using emugl::ABORT_REASON_OTHER;
28 using emugl::FatalError;
29
30 namespace {
31
32 static EGLBoolean sEgl2Egl = false;
33
sSingleton(bool nullEgl=false)34 static EglGlobalInfo* sSingleton(bool nullEgl = false) {
35 static EglGlobalInfo* i = new EglGlobalInfo(nullEgl);
36 return i;
37 }
38
39 static bool sEgl2EglSyncSafeToUse = false;
40
41 } // namespace
42
setEgl2Egl(EGLBoolean enable,bool nullEgl)43 void EglGlobalInfo::setEgl2Egl(EGLBoolean enable, bool nullEgl) {
44 if (nullEgl && enable == EGL_FALSE) {
45 // No point in nullEgl backend for non egl2egl cases.
46 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER));
47 }
48 sEgl2Egl = enable;
49 setGles2Gles(enable);
50 sSingleton(nullEgl);
51 }
52
isEgl2Egl()53 bool EglGlobalInfo::isEgl2Egl() {
54 return isGles2Gles();
55 }
56
setEgl2EglSyncSafeToUse(EGLBoolean enable)57 void EglGlobalInfo::setEgl2EglSyncSafeToUse(EGLBoolean enable) {
58 sEgl2EglSyncSafeToUse = enable == EGL_TRUE ? true : false;
59 }
60
isEgl2EglSyncSafeToUse()61 bool EglGlobalInfo::isEgl2EglSyncSafeToUse() {
62 return !isGles2Gles() || sEgl2EglSyncSafeToUse;
63 }
64
65 // static
getInstance(bool nullEgl)66 EglGlobalInfo* EglGlobalInfo::getInstance(bool nullEgl) {
67 return sSingleton(nullEgl);
68 }
69
EglGlobalInfo(bool nullEgl)70 EglGlobalInfo::EglGlobalInfo(bool nullEgl) {
71 #if defined(ANDROID) || defined(__QNX__)
72 sEgl2Egl = true;
73 sEgl2EglSyncSafeToUse = true;
74 m_engine = EglOS::
75 getEgl2EglHostInstance(nullEgl);
76 #else
77 if (sEgl2Egl) {
78 m_engine = EglOS::getEgl2EglHostInstance(nullEgl);
79 } else {
80 m_engine = EglOS::Engine::getHostInstance();
81 }
82 #endif
83 m_display = m_engine->getDefaultDisplay();
84 }
85
~EglGlobalInfo()86 EglGlobalInfo::~EglGlobalInfo() {
87 for (size_t n = 0; n < m_displays.size(); ++n) {
88 delete m_displays[n];
89 }
90 }
91
addDisplay(EGLNativeDisplayType dpy,EglOS::Display * idpy)92 EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy,
93 EglOS::Display* idpy) {
94 //search if it already exists.
95 android::base::AutoLock mutex(m_lock);
96 for (size_t n = 0; n < m_displays.size(); ++n) {
97 if (m_displays[n]->getEglOsEngineDisplay() == dpy) {
98 return m_displays[n];
99 }
100 }
101
102 if (!idpy) {
103 return NULL;
104 }
105 EglDisplay* result = new EglDisplay(dpy, idpy);
106 m_displays.push_back(result);
107 return result;
108 }
109
removeDisplay(EGLDisplay dpy)110 bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) {
111 android::base::AutoLock mutex(m_lock);
112 for (size_t n = 0; n < m_displays.size(); ++n) {
113 if (m_displays[n] == static_cast<EglDisplay*>(dpy)) {
114 delete m_displays[n];
115 m_displays.erase(m_displays.begin() + n);
116 return true;
117 }
118 }
119 return false;
120 }
121
getDisplayFromDisplayType(EGLNativeDisplayType dpy) const122 EglDisplay* EglGlobalInfo::getDisplayFromDisplayType(EGLNativeDisplayType dpy) const {
123 android::base::AutoLock mutex(m_lock);
124 for (size_t n = 0; n < m_displays.size(); ++n) {
125 if (m_displays[n]->getEglOsEngineDisplay() == dpy) {
126 return m_displays[n];
127 }
128 }
129 return NULL;
130 }
131
getDisplay(EGLDisplay dpy) const132 EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) const {
133 android::base::AutoLock mutex(m_lock);
134 for (size_t n = 0; n < m_displays.size(); ++n) {
135 if (m_displays[n] == static_cast<EglDisplay*>(dpy)) {
136 return m_displays[n];
137 }
138 }
139 return NULL;
140 }
141
initClientExtFuncTable(GLESVersion ver)142 void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver) {
143 android::base::AutoLock mutex(m_lock);
144 if (!m_gles_extFuncs_inited[ver]) {
145 ClientAPIExts::initClientFuncs(m_gles_ifaces[ver], (int)ver - 1);
146 m_gles_extFuncs_inited[ver] = true;
147 }
148 }
149
markSurfaceForDestroy(EglDisplay * display,EGLSurface toDestroy)150 void EglGlobalInfo::markSurfaceForDestroy(EglDisplay* display,
151 EGLSurface toDestroy) {
152 android::base::AutoLock mutex(m_lock);
153 assert(display);
154 m_surfaceDestroyList.push_back(
155 std::make_pair(display, toDestroy));
156 }
157
sweepDestroySurfaces()158 void EglGlobalInfo::sweepDestroySurfaces() {
159 android::base::AutoLock mutex(m_lock);
160 for (auto elt : m_surfaceDestroyList) {
161 EglDisplay* dpy = elt.first;
162 assert(dpy);
163 EGLSurface surface = elt.second;
164 SurfacePtr surfacePtr = dpy->getSurface(surface);
165 if (surfacePtr) {
166 m_gles_ifaces[GLES_2_0]->deleteRbo(surfacePtr->glRboColor);
167 m_gles_ifaces[GLES_2_0]->deleteRbo(surfacePtr->glRboDepth);
168 }
169 dpy->removeSurface(surface);
170 }
171 m_surfaceDestroyList.clear();
172 }
173