blob: b69692002397ba3dc60b724551f3b616cc76a3b8 [file] [log] [blame]
Jesse Hall21558da2013-08-06 15:31:22 -07001/*
Mathias Agopian518ec112011-05-13 16:21:08 -07002 ** Copyright 2007, The Android Open Source Project
3 **
Jesse Hall21558da2013-08-06 15:31:22 -07004 ** 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
Mathias Agopian518ec112011-05-13 16:21:08 -07007 **
Jesse Hall21558da2013-08-06 15:31:22 -07008 ** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopian518ec112011-05-13 16:21:08 -07009 **
Jesse Hall21558da2013-08-06 15:31:22 -070010 ** 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
Mathias Agopian518ec112011-05-13 16:21:08 -070014 ** limitations under the License.
15 */
16
Jesse Hallb29e5e82012-04-04 16:53:42 -070017#define __STDC_LIMIT_MACROS 1
Jesse Hall1508ae62017-01-19 17:43:26 -080018#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Jesse Hallb29e5e82012-04-04 16:53:42 -070019
Mathias Agopian311b4792017-02-28 15:00:49 -080020#include "egl_display.h"
Mathias Agopian4b9511c2011-11-13 23:52:47 -080021
Mathias Agopian39c24a22013-04-04 23:17:56 -070022#include "../egl_impl.h"
23
Mathias Agopianb7f9a242017-03-08 22:29:31 -080024#include <private/EGL/display.h>
25
Jamie Gennisaca51c02011-11-03 17:42:43 -070026#include "egl_cache.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070027#include "egl_object.h"
28#include "egl_tls.h"
Mathias Agopian65421432017-03-08 11:49:05 -080029#include "egl_trace.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070030#include "Loader.h"
Mathias Agopian7db993a2012-03-25 00:49:46 -070031#include <cutils/properties.h>
Mathias Agopian311b4792017-02-28 15:00:49 -080032
Mathias Agopian518ec112011-05-13 16:21:08 -070033// ----------------------------------------------------------------------------
34namespace android {
35// ----------------------------------------------------------------------------
36
Mathias Agopian4b9511c2011-11-13 23:52:47 -080037static char const * const sVendorString = "Android";
38static char const * const sVersionString = "1.4 Android META-EGL";
Mathias Agopiancc2b1562012-05-21 14:01:37 -070039static char const * const sClientApiString = "OpenGL_ES";
Mathias Agopian4b9511c2011-11-13 23:52:47 -080040
Jesse Hall21558da2013-08-06 15:31:22 -070041extern char const * const gBuiltinExtensionString;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070042extern char const * const gExtensionString;
Mathias Agopian4b9511c2011-11-13 23:52:47 -080043
Mathias Agopian518ec112011-05-13 16:21:08 -070044extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
45
Mathias Agopian518ec112011-05-13 16:21:08 -070046// ----------------------------------------------------------------------------
47
Jesse Hallc2e41222013-08-08 13:40:22 -070048static bool findExtension(const char* exts, const char* name, size_t nameLen) {
49 if (exts) {
Kalle Raita7804aa22016-04-18 16:03:37 -070050 for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
51 if (match[nameLen] == '\0' || match[nameLen] == ' ') {
52 return true;
53 }
Jesse Hallc2e41222013-08-08 13:40:22 -070054 }
55 }
56 return false;
57}
58
Mathias Agopianb7f9a242017-03-08 22:29:31 -080059int egl_get_init_count(EGLDisplay dpy) {
60 egl_display_t* eglDisplay = egl_display_t::get(dpy);
61 return eglDisplay ? eglDisplay->getRefsCount() : 0;
62}
63
Mathias Agopian518ec112011-05-13 16:21:08 -070064egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
65
66egl_display_t::egl_display_t() :
Michael Lentine54466bc2015-01-27 09:01:03 -080067 magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), eglIsInitialized(false) {
Mathias Agopian518ec112011-05-13 16:21:08 -070068}
69
70egl_display_t::~egl_display_t() {
71 magic = 0;
Jamie Gennis76601082011-11-06 14:14:33 -080072 egl_cache_t::get()->terminate();
Mathias Agopian518ec112011-05-13 16:21:08 -070073}
74
75egl_display_t* egl_display_t::get(EGLDisplay dpy) {
76 uintptr_t index = uintptr_t(dpy)-1U;
Jesse Halld6e99462016-09-28 11:26:57 -070077 if (index >= NUM_DISPLAYS || !sDisplay[index].isValid()) {
78 return nullptr;
79 }
80 return &sDisplay[index];
Mathias Agopian518ec112011-05-13 16:21:08 -070081}
82
83void egl_display_t::addObject(egl_object_t* object) {
Mathias Agopian65421432017-03-08 11:49:05 -080084 std::lock_guard<std::mutex> _l(lock);
85 objects.insert(object);
Mathias Agopian518ec112011-05-13 16:21:08 -070086}
87
Mathias Agopian5b287a62011-05-16 18:58:55 -070088void egl_display_t::removeObject(egl_object_t* object) {
Mathias Agopian65421432017-03-08 11:49:05 -080089 std::lock_guard<std::mutex> _l(lock);
90 objects.erase(object);
Mathias Agopian5b287a62011-05-16 18:58:55 -070091}
92
Mathias Agopianf0480de2011-11-13 20:50:07 -080093bool egl_display_t::getObject(egl_object_t* object) const {
Mathias Agopian65421432017-03-08 11:49:05 -080094 std::lock_guard<std::mutex> _l(lock);
95 if (objects.find(object) != objects.end()) {
Mathias Agopianf0480de2011-11-13 20:50:07 -080096 if (object->getDisplay() == this) {
97 object->incRef();
98 return true;
99 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700100 }
101 return false;
102}
103
Mathias Agopian518ec112011-05-13 16:21:08 -0700104EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
105 if (uintptr_t(disp) >= NUM_DISPLAYS)
106 return NULL;
107
108 return sDisplay[uintptr_t(disp)].getDisplay(disp);
109}
110
111EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
112
Mathias Agopian65421432017-03-08 11:49:05 -0800113 std::lock_guard<std::mutex> _l(lock);
Jesse Hall1508ae62017-01-19 17:43:26 -0800114 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700115
116 // get our driver loader
117 Loader& loader(Loader::getInstance());
118
Mathias Agopianada798b2012-02-13 17:09:30 -0800119 egl_connection_t* const cnx = &gEGLImpl;
120 if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
121 EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
122 disp.dpy = dpy;
123 if (dpy == EGL_NO_DISPLAY) {
124 loader.close(cnx->dso);
125 cnx->dso = NULL;
Mathias Agopian518ec112011-05-13 16:21:08 -0700126 }
127 }
128
129 return EGLDisplay(uintptr_t(display) + 1U);
130}
131
132EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
133
Mathias Agopian65421432017-03-08 11:49:05 -0800134 { // scope for refLock
135 std::unique_lock<std::mutex> _l(refLock);
Michael Lentine54466bc2015-01-27 09:01:03 -0800136 refs++;
137 if (refs > 1) {
138 if (major != NULL)
139 *major = VERSION_MAJOR;
140 if (minor != NULL)
141 *minor = VERSION_MINOR;
Mathias Agopian65421432017-03-08 11:49:05 -0800142 while(!eglIsInitialized) {
143 refCond.wait(_l);
144 }
Michael Lentine54466bc2015-01-27 09:01:03 -0800145 return EGL_TRUE;
146 }
Mathias Agopian65421432017-03-08 11:49:05 -0800147 while(eglIsInitialized) {
148 refCond.wait(_l);
149 }
Michael Lentine54466bc2015-01-27 09:01:03 -0800150 }
151
Mathias Agopian65421432017-03-08 11:49:05 -0800152 { // scope for lock
153 std::lock_guard<std::mutex> _l(lock);
Michael Lentine54466bc2015-01-27 09:01:03 -0800154
Michael Lentine54466bc2015-01-27 09:01:03 -0800155 setGLHooksThreadSpecific(&gHooksNoContext);
156
157 // initialize each EGL and
158 // build our own extension string first, based on the extension we know
159 // and the extension supported by our client implementation
160
161 egl_connection_t* const cnx = &gEGLImpl;
162 cnx->major = -1;
163 cnx->minor = -1;
164 if (cnx->dso) {
165 EGLDisplay idpy = disp.dpy;
166 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
167 //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
168 // idpy, cnx->major, cnx->minor, cnx);
169
170 // display is now initialized
171 disp.state = egl_display_t::INITIALIZED;
172
173 // get the query-strings for this display for each implementation
174 disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
175 EGL_VENDOR);
176 disp.queryString.version = cnx->egl.eglQueryString(idpy,
177 EGL_VERSION);
178 disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
179 EGL_EXTENSIONS);
180 disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
181 EGL_CLIENT_APIS);
182
183 } else {
184 ALOGW("eglInitialize(%p) failed (%s)", idpy,
185 egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
186 }
187 }
188
189 // the query strings are per-display
Mathias Agopian65421432017-03-08 11:49:05 -0800190 mVendorString = sVendorString;
191 mVersionString = sVersionString;
192 mClientApiString = sClientApiString;
Michael Lentine54466bc2015-01-27 09:01:03 -0800193
Mathias Agopian65421432017-03-08 11:49:05 -0800194 mExtensionString = gBuiltinExtensionString;
Michael Lentine54466bc2015-01-27 09:01:03 -0800195 char const* start = gExtensionString;
Michael Lentine54466bc2015-01-27 09:01:03 -0800196 do {
Nicolas Capensecc0c9a2015-10-30 12:55:21 -0400197 // length of the extension name
198 size_t len = strcspn(start, " ");
199 if (len) {
200 // NOTE: we could avoid the copy if we had strnstr.
Mathias Agopian65421432017-03-08 11:49:05 -0800201 const std::string ext(start, len);
202 if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
Nicolas Capensecc0c9a2015-10-30 12:55:21 -0400203 mExtensionString.append(ext + " ");
Michael Lentine54466bc2015-01-27 09:01:03 -0800204 }
Nicolas Capensecc0c9a2015-10-30 12:55:21 -0400205 // advance to the next extension name, skipping the space.
206 start += len;
207 start += (*start == ' ') ? 1 : 0;
Michael Lentine54466bc2015-01-27 09:01:03 -0800208 }
Nicolas Capensecc0c9a2015-10-30 12:55:21 -0400209 } while (*start != '\0');
Michael Lentine54466bc2015-01-27 09:01:03 -0800210
211 egl_cache_t::get()->initialize(this);
212
213 char value[PROPERTY_VALUE_MAX];
214 property_get("debug.egl.finish", value, "0");
215 if (atoi(value)) {
216 finishOnSwap = true;
217 }
218
219 property_get("debug.egl.traceGpuCompletion", value, "0");
220 if (atoi(value)) {
221 traceGpuCompletion = true;
222 }
223
Mathias Agopian518ec112011-05-13 16:21:08 -0700224 if (major != NULL)
225 *major = VERSION_MAJOR;
226 if (minor != NULL)
227 *minor = VERSION_MINOR;
Mathias Agopian518ec112011-05-13 16:21:08 -0700228 }
229
Mathias Agopian65421432017-03-08 11:49:05 -0800230 { // scope for refLock
231 std::unique_lock<std::mutex> _l(refLock);
Michael Lentine54466bc2015-01-27 09:01:03 -0800232 eglIsInitialized = true;
Mathias Agopian65421432017-03-08 11:49:05 -0800233 refCond.notify_all();
Mathias Agopian518ec112011-05-13 16:21:08 -0700234 }
235
Mathias Agopian7773c432012-02-13 20:06:08 -0800236 return EGL_TRUE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700237}
238
239EGLBoolean egl_display_t::terminate() {
240
Mathias Agopian65421432017-03-08 11:49:05 -0800241 { // scope for refLock
242 std::unique_lock<std::mutex> _rl(refLock);
Michael Lentine54466bc2015-01-27 09:01:03 -0800243 if (refs == 0) {
244 /*
245 * From the EGL spec (3.2):
246 * "Termination of a display that has already been terminated,
247 * (...), is allowed, but the only effect of such a call is
248 * to return EGL_TRUE (...)
249 */
250 return EGL_TRUE;
251 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700252
Michael Lentine54466bc2015-01-27 09:01:03 -0800253 // this is specific to Android, display termination is ref-counted.
Mathias Agopian518ec112011-05-13 16:21:08 -0700254 refs--;
Michael Lentine54466bc2015-01-27 09:01:03 -0800255 if (refs > 0) {
256 return EGL_TRUE;
257 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700258 }
259
260 EGLBoolean res = EGL_FALSE;
Michael Lentine54466bc2015-01-27 09:01:03 -0800261
Mathias Agopian65421432017-03-08 11:49:05 -0800262 { // scope for lock
263 std::lock_guard<std::mutex> _l(lock);
Michael Lentine54466bc2015-01-27 09:01:03 -0800264
265 egl_connection_t* const cnx = &gEGLImpl;
266 if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
267 if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
268 ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
269 egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
270 }
271 // REVISIT: it's unclear what to do if eglTerminate() fails
272 disp.state = egl_display_t::TERMINATED;
273 res = EGL_TRUE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700274 }
Michael Lentine54466bc2015-01-27 09:01:03 -0800275
Michael Lentine54466bc2015-01-27 09:01:03 -0800276 // Reset the extension string since it will be regenerated if we get
277 // reinitialized.
Mathias Agopian65421432017-03-08 11:49:05 -0800278 mExtensionString.clear();
Michael Lentine54466bc2015-01-27 09:01:03 -0800279
280 // Mark all objects remaining in the list as terminated, unless
281 // there are no reference to them, it which case, we're free to
282 // delete them.
283 size_t count = objects.size();
Dan Alberteacd31f2016-02-02 15:08:34 -0800284 ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count);
Mathias Agopian65421432017-03-08 11:49:05 -0800285 for (auto o : objects) {
Michael Lentine54466bc2015-01-27 09:01:03 -0800286 o->destroy();
287 }
288
289 // this marks all object handles are "terminated"
290 objects.clear();
Mathias Agopian518ec112011-05-13 16:21:08 -0700291 }
292
Mathias Agopian65421432017-03-08 11:49:05 -0800293 { // scope for refLock
294 std::unique_lock<std::mutex> _rl(refLock);
Michael Lentine54466bc2015-01-27 09:01:03 -0800295 eglIsInitialized = false;
Mathias Agopian65421432017-03-08 11:49:05 -0800296 refCond.notify_all();
Mathias Agopian5b287a62011-05-16 18:58:55 -0700297 }
298
Mathias Agopian518ec112011-05-13 16:21:08 -0700299 return res;
300}
301
Mathias Agopianfb87e542012-01-30 18:20:52 -0800302void egl_display_t::loseCurrent(egl_context_t * cur_c)
303{
304 if (cur_c) {
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800305 egl_display_t* display = cur_c->getDisplay();
306 if (display) {
307 display->loseCurrentImpl(cur_c);
308 }
309 }
310}
Mathias Agopianfb87e542012-01-30 18:20:52 -0800311
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800312void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
313{
314 // by construction, these are either 0 or valid (possibly terminated)
315 // it should be impossible for these to be invalid
316 ContextRef _cur_c(cur_c);
317 SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
318 SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
Mathias Agopianfb87e542012-01-30 18:20:52 -0800319
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800320 { // scope for the lock
Mathias Agopian65421432017-03-08 11:49:05 -0800321 std::lock_guard<std::mutex> _l(lock);
Mathias Agopianfb87e542012-01-30 18:20:52 -0800322 cur_c->onLooseCurrent();
323
Mathias Agopianfb87e542012-01-30 18:20:52 -0800324 }
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800325
326 // This cannot be called with the lock held because it might end-up
327 // calling back into EGL (in particular when a surface is destroyed
328 // it calls ANativeWindow::disconnect
329 _cur_c.release();
330 _cur_r.release();
331 _cur_d.release();
Mathias Agopianfb87e542012-01-30 18:20:52 -0800332}
333
334EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700335 EGLSurface draw, EGLSurface read, EGLContext /*ctx*/,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800336 EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
337{
Mathias Agopianfb87e542012-01-30 18:20:52 -0800338 EGLBoolean result;
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800339
340 // by construction, these are either 0 or valid (possibly terminated)
341 // it should be impossible for these to be invalid
342 ContextRef _cur_c(cur_c);
343 SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
344 SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
345
346 { // scope for the lock
Mathias Agopian65421432017-03-08 11:49:05 -0800347 std::lock_guard<std::mutex> _l(lock);
Mathias Agopianfb87e542012-01-30 18:20:52 -0800348 if (c) {
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800349 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopianada798b2012-02-13 17:09:30 -0800350 disp.dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800351 if (result == EGL_TRUE) {
352 c->onMakeCurrent(draw, read);
353 }
354 } else {
355 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopianada798b2012-02-13 17:09:30 -0800356 disp.dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800357 if (result == EGL_TRUE) {
358 cur_c->onLooseCurrent();
359 }
Mathias Agopianfb87e542012-01-30 18:20:52 -0800360 }
361 }
Mathias Agopiana4b2c042012-02-03 15:24:51 -0800362
363 if (result == EGL_TRUE) {
364 // This cannot be called with the lock held because it might end-up
365 // calling back into EGL (in particular when a surface is destroyed
366 // it calls ANativeWindow::disconnect
367 _cur_c.release();
368 _cur_r.release();
369 _cur_d.release();
370 }
371
Mathias Agopianfb87e542012-01-30 18:20:52 -0800372 return result;
373}
Mathias Agopian518ec112011-05-13 16:21:08 -0700374
Jesse Hallc2e41222013-08-08 13:40:22 -0700375bool egl_display_t::haveExtension(const char* name, size_t nameLen) const {
376 if (!nameLen) {
377 nameLen = strlen(name);
378 }
Mathias Agopian65421432017-03-08 11:49:05 -0800379 return findExtension(mExtensionString.c_str(), name, nameLen);
Jesse Hallc2e41222013-08-08 13:40:22 -0700380}
381
Jesse Halla0fef1c2012-04-17 12:02:26 -0700382// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -0700383}; // namespace android
384// ----------------------------------------------------------------------------