egl_display.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /*
  2. ** Copyright 2007, 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. #define __STDC_LIMIT_MACROS 1
  17. #define ATRACE_TAG ATRACE_TAG_GRAPHICS
  18. #include "egl_display.h"
  19. #include "../egl_impl.h"
  20. #include <EGL/eglext_angle.h>
  21. #include <private/EGL/display.h>
  22. #include <cutils/properties.h>
  23. #include "Loader.h"
  24. #include "egl_angle_platform.h"
  25. #include "egl_cache.h"
  26. #include "egl_object.h"
  27. #include "egl_tls.h"
  28. #include <android/dlext.h>
  29. #include <dlfcn.h>
  30. #include <graphicsenv/GraphicsEnv.h>
  31. #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
  32. #include <configstore/Utils.h>
  33. using namespace android::hardware::configstore;
  34. using namespace android::hardware::configstore::V1_0;
  35. // ----------------------------------------------------------------------------
  36. namespace android {
  37. // ----------------------------------------------------------------------------
  38. static char const * const sVendorString = "Android";
  39. static char const* const sVersionString14 = "1.4 Android META-EGL";
  40. static char const* const sVersionString15 = "1.5 Android META-EGL";
  41. static char const * const sClientApiString = "OpenGL_ES";
  42. extern char const * const gBuiltinExtensionString;
  43. extern char const * const gExtensionString;
  44. extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
  45. // ----------------------------------------------------------------------------
  46. bool findExtension(const char* exts, const char* name, size_t nameLen) {
  47. if (exts) {
  48. if (!nameLen) {
  49. nameLen = strlen(name);
  50. }
  51. for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
  52. if (match[nameLen] == '\0' || match[nameLen] == ' ') {
  53. return true;
  54. }
  55. }
  56. }
  57. return false;
  58. }
  59. bool needsAndroidPEglMitigation() {
  60. static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
  61. return vndk_version <= 28;
  62. }
  63. int egl_get_init_count(EGLDisplay dpy) {
  64. egl_display_t* eglDisplay = egl_display_t::get(dpy);
  65. return eglDisplay ? eglDisplay->getRefsCount() : 0;
  66. }
  67. egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
  68. egl_display_t::egl_display_t() :
  69. magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), eglIsInitialized(false) {
  70. }
  71. egl_display_t::~egl_display_t() {
  72. magic = 0;
  73. egl_cache_t::get()->terminate();
  74. }
  75. egl_display_t* egl_display_t::get(EGLDisplay dpy) {
  76. if (uintptr_t(dpy) == 0) {
  77. return nullptr;
  78. }
  79. uintptr_t index = uintptr_t(dpy)-1U;
  80. if (index >= NUM_DISPLAYS || !sDisplay[index].isValid()) {
  81. return nullptr;
  82. }
  83. return &sDisplay[index];
  84. }
  85. void egl_display_t::addObject(egl_object_t* object) {
  86. std::lock_guard<std::mutex> _l(lock);
  87. objects.insert(object);
  88. }
  89. void egl_display_t::removeObject(egl_object_t* object) {
  90. std::lock_guard<std::mutex> _l(lock);
  91. objects.erase(object);
  92. }
  93. bool egl_display_t::getObject(egl_object_t* object) const {
  94. std::lock_guard<std::mutex> _l(lock);
  95. if (objects.find(object) != objects.end()) {
  96. if (object->getDisplay() == this) {
  97. object->incRef();
  98. return true;
  99. }
  100. }
  101. return false;
  102. }
  103. EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp,
  104. const EGLAttrib* attrib_list) {
  105. if (uintptr_t(disp) >= NUM_DISPLAYS)
  106. return nullptr;
  107. return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list);
  108. }
  109. static bool addAnglePlatformAttributes(egl_connection_t* const cnx,
  110. std::vector<EGLAttrib>& attrs) {
  111. intptr_t vendorEGL = (intptr_t)cnx->vendorEGL;
  112. attrs.reserve(4 * 2);
  113. attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
  114. attrs.push_back(cnx->angleBackend);
  115. switch (cnx->angleBackend) {
  116. case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
  117. ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__);
  118. char prop[PROPERTY_VALUE_MAX];
  119. property_get("debug.angle.validation", prop, "0");
  120. attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
  121. attrs.push_back(atoi(prop));
  122. break;
  123. case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
  124. ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__);
  125. break;
  126. case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
  127. ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__);
  128. // NOTE: This is only valid if the backend is OpenGL
  129. attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
  130. attrs.push_back(vendorEGL);
  131. break;
  132. default:
  133. ALOGV("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
  134. break;
  135. }
  136. attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
  137. attrs.push_back(EGL_FALSE);
  138. return true;
  139. }
  140. static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
  141. const EGLAttrib* attrib_list, EGLint* error) {
  142. EGLDisplay dpy = EGL_NO_DISPLAY;
  143. *error = EGL_NONE;
  144. if (cnx->egl.eglGetPlatformDisplay) {
  145. std::vector<EGLAttrib> attrs;
  146. if (attrib_list) {
  147. for (const EGLAttrib* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
  148. attrs.push_back(attr[0]);
  149. attrs.push_back(attr[1]);
  150. }
  151. }
  152. if (!addAnglePlatformAttributes(cnx, attrs)) {
  153. ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display);
  154. *error = EGL_BAD_PARAMETER;
  155. return EGL_NO_DISPLAY;
  156. }
  157. attrs.push_back(EGL_NONE);
  158. dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
  159. reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY),
  160. attrs.data());
  161. if (dpy == EGL_NO_DISPLAY) {
  162. ALOGE("eglGetPlatformDisplay failed!");
  163. } else {
  164. if (!angle::initializeAnglePlatform(dpy)) {
  165. ALOGE("initializeAnglePlatform failed!");
  166. }
  167. }
  168. } else {
  169. ALOGE("eglGetDisplay(%p) failed: Unable to look up eglGetPlatformDisplay from ANGLE",
  170. display);
  171. }
  172. return dpy;
  173. }
  174. EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display,
  175. const EGLAttrib* attrib_list) {
  176. std::lock_guard<std::mutex> _l(lock);
  177. ATRACE_CALL();
  178. // get our driver loader
  179. Loader& loader(Loader::getInstance());
  180. egl_connection_t* const cnx = &gEGLImpl;
  181. if (cnx->dso) {
  182. EGLDisplay dpy = EGL_NO_DISPLAY;
  183. if (cnx->useAngle) {
  184. EGLint error;
  185. dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error);
  186. if (error != EGL_NONE) {
  187. return setError(error, dpy);
  188. }
  189. }
  190. if (dpy == EGL_NO_DISPLAY) {
  191. // NOTE: eglGetPlatformDisplay with a empty attribute list
  192. // behaves the same as eglGetDisplay
  193. if (cnx->egl.eglGetPlatformDisplay) {
  194. dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANDROID_KHR, display,
  195. attrib_list);
  196. }
  197. // It is possible that eglGetPlatformDisplay does not have a
  198. // working implementation for Android platform; in that case,
  199. // one last fallback to eglGetDisplay
  200. if(dpy == EGL_NO_DISPLAY) {
  201. if (attrib_list) {
  202. ALOGW("getPlatformDisplay: unexpected attribute list, attributes ignored");
  203. }
  204. dpy = cnx->egl.eglGetDisplay(display);
  205. }
  206. }
  207. disp.dpy = dpy;
  208. if (dpy == EGL_NO_DISPLAY) {
  209. loader.close(cnx);
  210. }
  211. }
  212. return EGLDisplay(uintptr_t(display) + 1U);
  213. }
  214. EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
  215. { // scope for refLock
  216. std::unique_lock<std::mutex> _l(refLock);
  217. refs++;
  218. if (refs > 1) {
  219. // We don't know what to report until we know what the
  220. // driver supports. Make sure we are initialized before
  221. // returning the version info.
  222. while(!eglIsInitialized) {
  223. refCond.wait(_l);
  224. }
  225. egl_connection_t* const cnx = &gEGLImpl;
  226. // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
  227. // changing the behavior from the past where we always advertise
  228. // version 1.4. May need to check that revision is valid
  229. // before using cnx->major & cnx->minor
  230. if (major != nullptr) *major = cnx->major;
  231. if (minor != nullptr) *minor = cnx->minor;
  232. return EGL_TRUE;
  233. }
  234. while(eglIsInitialized) {
  235. refCond.wait(_l);
  236. }
  237. }
  238. { // scope for lock
  239. std::lock_guard<std::mutex> _l(lock);
  240. setGLHooksThreadSpecific(&gHooksNoContext);
  241. // initialize each EGL and
  242. // build our own extension string first, based on the extension we know
  243. // and the extension supported by our client implementation
  244. egl_connection_t* const cnx = &gEGLImpl;
  245. cnx->major = -1;
  246. cnx->minor = -1;
  247. if (cnx->dso) {
  248. EGLDisplay idpy = disp.dpy;
  249. if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
  250. //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
  251. // idpy, cnx->major, cnx->minor, cnx);
  252. // display is now initialized
  253. disp.state = egl_display_t::INITIALIZED;
  254. // get the query-strings for this display for each implementation
  255. disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
  256. EGL_VENDOR);
  257. disp.queryString.version = cnx->egl.eglQueryString(idpy,
  258. EGL_VERSION);
  259. disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
  260. EGL_EXTENSIONS);
  261. disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
  262. EGL_CLIENT_APIS);
  263. } else {
  264. ALOGW("eglInitialize(%p) failed (%s)", idpy,
  265. egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
  266. }
  267. }
  268. if (cnx->minor == 5) {
  269. // full list in egl_entries.in
  270. if (!cnx->egl.eglCreateImage ||
  271. !cnx->egl.eglDestroyImage ||
  272. !cnx->egl.eglGetPlatformDisplay ||
  273. !cnx->egl.eglCreatePlatformWindowSurface ||
  274. !cnx->egl.eglCreatePlatformPixmapSurface ||
  275. !cnx->egl.eglCreateSync ||
  276. !cnx->egl.eglDestroySync ||
  277. !cnx->egl.eglClientWaitSync ||
  278. !cnx->egl.eglGetSyncAttrib ||
  279. !cnx->egl.eglWaitSync) {
  280. ALOGE("Driver indicates EGL 1.5 support, but does not have "
  281. "a critical API");
  282. cnx->minor = 4;
  283. }
  284. }
  285. // the query strings are per-display
  286. mVendorString = sVendorString;
  287. mVersionString.clear();
  288. cnx->driverVersion = EGL_MAKE_VERSION(1, 4, 0);
  289. mVersionString = sVersionString14;
  290. if ((cnx->major == 1) && (cnx->minor == 5)) {
  291. mVersionString = sVersionString15;
  292. cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0);
  293. }
  294. if (mVersionString.empty()) {
  295. ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor);
  296. mVersionString = sVersionString14;
  297. }
  298. mClientApiString = sClientApiString;
  299. mExtensionString = gBuiltinExtensionString;
  300. hasColorSpaceSupport = findExtension(disp.queryString.extensions, "EGL_KHR_gl_colorspace");
  301. // Note: CDD requires that devices supporting wide color and/or HDR color also support
  302. // the EGL_KHR_gl_colorspace extension.
  303. bool wideColorBoardConfig =
  304. getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(
  305. false);
  306. // Add wide-color extensions if device can support wide-color
  307. if (wideColorBoardConfig && hasColorSpaceSupport) {
  308. mExtensionString.append(
  309. "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear "
  310. "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 "
  311. "EGL_EXT_gl_colorspace_display_p3_passthrough ");
  312. }
  313. bool hasHdrBoardConfig =
  314. getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
  315. if (hasHdrBoardConfig && hasColorSpaceSupport) {
  316. // hasHDRBoardConfig indicates the system is capable of supporting HDR content.
  317. // Typically that means there is an HDR capable display attached, but could be
  318. // support for attaching an HDR display. In either case, advertise support for
  319. // HDR color spaces.
  320. mExtensionString.append(
  321. "EGL_EXT_gl_colorspace_bt2020_linear EGL_EXT_gl_colorspace_bt2020_pq ");
  322. }
  323. char const* start = gExtensionString;
  324. do {
  325. // length of the extension name
  326. size_t len = strcspn(start, " ");
  327. if (len) {
  328. // NOTE: we could avoid the copy if we had strnstr.
  329. const std::string ext(start, len);
  330. // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on
  331. // some Android P vendor partitions this extension under the draft KHR name,
  332. // but during Khronos review it was decided to demote it to EXT.
  333. if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" &&
  334. findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
  335. mExtensionString.append("EGL_EXT_image_gl_colorspace ");
  336. }
  337. if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
  338. mExtensionString.append(ext + " ");
  339. }
  340. // advance to the next extension name, skipping the space.
  341. start += len;
  342. start += (*start == ' ') ? 1 : 0;
  343. }
  344. } while (*start != '\0');
  345. egl_cache_t::get()->initialize(this);
  346. char value[PROPERTY_VALUE_MAX];
  347. property_get("debug.egl.finish", value, "0");
  348. if (atoi(value)) {
  349. finishOnSwap = true;
  350. }
  351. property_get("debug.egl.traceGpuCompletion", value, "0");
  352. if (atoi(value)) {
  353. traceGpuCompletion = true;
  354. }
  355. // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
  356. // changing the behavior from the past where we always advertise
  357. // version 1.4. May need to check that revision is valid
  358. // before using cnx->major & cnx->minor
  359. if (major != nullptr) *major = cnx->major;
  360. if (minor != nullptr) *minor = cnx->minor;
  361. }
  362. { // scope for refLock
  363. std::unique_lock<std::mutex> _l(refLock);
  364. eglIsInitialized = true;
  365. refCond.notify_all();
  366. }
  367. return EGL_TRUE;
  368. }
  369. EGLBoolean egl_display_t::terminate() {
  370. { // scope for refLock
  371. std::unique_lock<std::mutex> _rl(refLock);
  372. if (refs == 0) {
  373. /*
  374. * From the EGL spec (3.2):
  375. * "Termination of a display that has already been terminated,
  376. * (...), is allowed, but the only effect of such a call is
  377. * to return EGL_TRUE (...)
  378. */
  379. return EGL_TRUE;
  380. }
  381. // this is specific to Android, display termination is ref-counted.
  382. refs--;
  383. if (refs > 0) {
  384. return EGL_TRUE;
  385. }
  386. }
  387. EGLBoolean res = EGL_FALSE;
  388. { // scope for lock
  389. std::lock_guard<std::mutex> _l(lock);
  390. egl_connection_t* const cnx = &gEGLImpl;
  391. if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
  392. // If we're using ANGLE reset any custom DisplayPlatform
  393. if (cnx->useAngle) {
  394. angle::resetAnglePlatform(disp.dpy);
  395. }
  396. if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
  397. ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
  398. egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
  399. }
  400. // REVISIT: it's unclear what to do if eglTerminate() fails
  401. disp.state = egl_display_t::TERMINATED;
  402. res = EGL_TRUE;
  403. }
  404. // Reset the extension string since it will be regenerated if we get
  405. // reinitialized.
  406. mExtensionString.clear();
  407. // Mark all objects remaining in the list as terminated, unless
  408. // there are no reference to them, it which case, we're free to
  409. // delete them.
  410. size_t count = objects.size();
  411. ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count);
  412. for (auto o : objects) {
  413. o->destroy();
  414. }
  415. // this marks all object handles are "terminated"
  416. objects.clear();
  417. }
  418. { // scope for refLock
  419. std::unique_lock<std::mutex> _rl(refLock);
  420. eglIsInitialized = false;
  421. refCond.notify_all();
  422. }
  423. return res;
  424. }
  425. void egl_display_t::loseCurrent(egl_context_t * cur_c)
  426. {
  427. if (cur_c) {
  428. egl_display_t* display = cur_c->getDisplay();
  429. if (display) {
  430. display->loseCurrentImpl(cur_c);
  431. }
  432. }
  433. }
  434. void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
  435. {
  436. // by construction, these are either 0 or valid (possibly terminated)
  437. // it should be impossible for these to be invalid
  438. ContextRef _cur_c(cur_c);
  439. SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr);
  440. SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr);
  441. { // scope for the lock
  442. std::lock_guard<std::mutex> _l(lock);
  443. cur_c->onLooseCurrent();
  444. }
  445. // This cannot be called with the lock held because it might end-up
  446. // calling back into EGL (in particular when a surface is destroyed
  447. // it calls ANativeWindow::disconnect
  448. _cur_c.release();
  449. _cur_r.release();
  450. _cur_d.release();
  451. }
  452. EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
  453. EGLSurface draw, EGLSurface read, EGLContext /*ctx*/,
  454. EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
  455. {
  456. EGLBoolean result;
  457. // by construction, these are either 0 or valid (possibly terminated)
  458. // it should be impossible for these to be invalid
  459. ContextRef _cur_c(cur_c);
  460. SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr);
  461. SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr);
  462. { // scope for the lock
  463. std::lock_guard<std::mutex> _l(lock);
  464. if (c) {
  465. result = c->cnx->egl.eglMakeCurrent(
  466. disp.dpy, impl_draw, impl_read, impl_ctx);
  467. if (result == EGL_TRUE) {
  468. c->onMakeCurrent(draw, read);
  469. }
  470. } else {
  471. result = cur_c->cnx->egl.eglMakeCurrent(
  472. disp.dpy, impl_draw, impl_read, impl_ctx);
  473. if (result == EGL_TRUE) {
  474. cur_c->onLooseCurrent();
  475. }
  476. }
  477. }
  478. if (result == EGL_TRUE) {
  479. // This cannot be called with the lock held because it might end-up
  480. // calling back into EGL (in particular when a surface is destroyed
  481. // it calls ANativeWindow::disconnect
  482. _cur_c.release();
  483. _cur_r.release();
  484. _cur_d.release();
  485. }
  486. return result;
  487. }
  488. bool egl_display_t::haveExtension(const char* name, size_t nameLen) const {
  489. if (!nameLen) {
  490. nameLen = strlen(name);
  491. }
  492. return findExtension(mExtensionString.c_str(), name, nameLen);
  493. }
  494. // ----------------------------------------------------------------------------
  495. }; // namespace android
  496. // ----------------------------------------------------------------------------