gl_context_egl.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gl/gl_context_egl.h"
  5. #include <memory>
  6. #include "base/command_line.h"
  7. #include "base/logging.h"
  8. #include "base/trace_event/trace_event.h"
  9. #include "build/build_config.h"
  10. #include "third_party/khronos/EGL/egl.h"
  11. #include "third_party/khronos/EGL/eglext.h"
  12. #include "ui/gl/egl_util.h"
  13. #include "ui/gl/gl_bindings.h"
  14. #include "ui/gl/gl_display.h"
  15. #include "ui/gl/gl_fence.h"
  16. #include "ui/gl/gl_gl_api_implementation.h"
  17. #include "ui/gl/gl_surface_egl.h"
  18. #include "ui/gl/yuv_to_rgb_converter.h"
  19. #ifndef EGL_CHROMIUM_create_context_bind_generates_resource
  20. #define EGL_CHROMIUM_create_context_bind_generates_resource 1
  21. #define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x33AD
  22. #endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
  23. #ifndef EGL_ANGLE_create_context_webgl_compatibility
  24. #define EGL_ANGLE_create_context_webgl_compatibility 1
  25. #define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC
  26. #endif /* EGL_ANGLE_create_context_webgl_compatibility */
  27. #ifndef EGL_ANGLE_display_texture_share_group
  28. #define EGL_ANGLE_display_texture_share_group 1
  29. #define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF
  30. #endif /* EGL_ANGLE_display_texture_share_group */
  31. #ifndef EGL_ANGLE_display_semaphore_share_group
  32. #define EGL_ANGLE_display_semaphore_share_group 1
  33. #define EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE 0x348D
  34. #endif /* EGL_ANGLE_display_semaphore_share_group */
  35. #ifndef EGL_ANGLE_external_context_and_surface
  36. #define EGL_ANGLE_external_context_and_surface 1
  37. #define EGL_EXTERNAL_CONTEXT_ANGLE 0x348E
  38. #define EGL_EXTERNAL_SURFACE_ANGLE 0x348F
  39. #define EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE 0x3490
  40. #endif /* EGL_ANGLE_external_context_and_surface */
  41. #ifndef EGL_ANGLE_create_context_client_arrays
  42. #define EGL_ANGLE_create_context_client_arrays 1
  43. #define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
  44. #endif /* EGL_ANGLE_create_context_client_arrays */
  45. #ifndef EGL_ANGLE_robust_resource_initialization
  46. #define EGL_ANGLE_robust_resource_initialization 1
  47. #define EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453
  48. #endif /* EGL_ANGLE_display_robust_resource_initialization */
  49. #ifndef EGL_ANGLE_create_context_backwards_compatible
  50. #define EGL_ANGLE_create_context_backwards_compatible 1
  51. #define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
  52. #endif /* EGL_ANGLE_create_context_backwards_compatible */
  53. #ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG
  54. #define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
  55. #define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
  56. #define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
  57. #define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
  58. #endif /* EGL_CONTEXT_PRIORITY_LEVEL */
  59. #ifndef EGL_ANGLE_power_preference
  60. #define EGL_ANGLE_power_preference 1
  61. #define EGL_POWER_PREFERENCE_ANGLE 0x3482
  62. #define EGL_LOW_POWER_ANGLE 0x0001
  63. #define EGL_HIGH_POWER_ANGLE 0x0002
  64. #endif /* EGL_ANGLE_power_preference */
  65. #ifndef EGL_NV_robustness_video_memory_purge
  66. #define EGL_NV_robustness_video_memory_purge 1
  67. #define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
  68. #endif /*EGL_NV_robustness_video_memory_purge */
  69. #ifndef EGL_ANGLE_context_virtualization
  70. #define EGL_ANGLE_context_virtualization 1
  71. #define EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE 0x3481
  72. #endif /* EGL_ANGLE_context_virtualization */
  73. #ifndef EGL_ANGLE_program_cache_control
  74. #define EGL_ANGLE_program_cache_control 1
  75. #define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459
  76. #endif /* EGL_ANGLE_program_cache_control */
  77. using ui::GetLastEGLErrorString;
  78. namespace gl {
  79. namespace {
  80. // Change the specified attribute in context_attributes. This fails if
  81. // the attribute is not already present. Returns true on success, false
  82. // otherwise.
  83. bool ChangeContextAttributes(std::vector<EGLint>& context_attributes,
  84. EGLint attribute,
  85. EGLint value) {
  86. auto iter = std::find(context_attributes.begin(), context_attributes.end(),
  87. attribute);
  88. if (iter != context_attributes.end()) {
  89. ++iter;
  90. if (iter != context_attributes.end()) {
  91. *iter = value;
  92. return true;
  93. }
  94. }
  95. return false;
  96. }
  97. } // namespace
  98. GLContextEGL::GLContextEGL(GLShareGroup* share_group)
  99. : GLContextReal(share_group) {}
  100. bool GLContextEGL::Initialize(GLSurface* compatible_surface,
  101. const GLContextAttribs& attribs) {
  102. DCHECK(compatible_surface);
  103. DCHECK(!context_);
  104. gl_display_ = static_cast<GLDisplayEGL*>(compatible_surface->GetGLDisplay());
  105. DCHECK(gl_display_);
  106. EGLint context_client_major_version = attribs.client_major_es_version;
  107. EGLint context_client_minor_version = attribs.client_minor_es_version;
  108. // Always prefer to use EGL_KHR_no_config_context so that all surfaces and
  109. // contexts are compatible
  110. if (!gl_display_->ext->b_EGL_KHR_no_config_context) {
  111. config_ = compatible_surface->GetConfig();
  112. EGLint config_renderable_type = 0;
  113. if (!eglGetConfigAttrib(gl_display_->GetDisplay(), config_,
  114. EGL_RENDERABLE_TYPE, &config_renderable_type)) {
  115. LOG(ERROR) << "eglGetConfigAttrib failed with error "
  116. << GetLastEGLErrorString();
  117. return false;
  118. }
  119. // If the requested context is ES3 but the config cannot support ES3,
  120. // request ES2 instead.
  121. if ((config_renderable_type & EGL_OPENGL_ES3_BIT) == 0 &&
  122. context_client_major_version >= 3) {
  123. context_client_major_version = 2;
  124. context_client_minor_version = 0;
  125. }
  126. }
  127. std::vector<EGLint> context_attributes;
  128. if (attribs.can_skip_validation &&
  129. GetGLImplementation() == kGLImplementationEGLANGLE) {
  130. context_attributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
  131. context_attributes.push_back(EGL_TRUE);
  132. }
  133. // EGL_KHR_create_context allows requesting both a major and minor context
  134. // version
  135. if (gl_display_->ext->b_EGL_KHR_create_context) {
  136. context_attributes.push_back(EGL_CONTEXT_MAJOR_VERSION);
  137. context_attributes.push_back(context_client_major_version);
  138. context_attributes.push_back(EGL_CONTEXT_MINOR_VERSION);
  139. context_attributes.push_back(context_client_minor_version);
  140. } else {
  141. context_attributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
  142. context_attributes.push_back(context_client_major_version);
  143. // Can only request 2.0 or 3.0 contexts without the EGL_KHR_create_context
  144. // extension, DCHECK to make sure we update the code to support devices
  145. // without this extension
  146. DCHECK(context_client_minor_version == 0);
  147. }
  148. bool is_swangle = IsSoftwareGLImplementation(GetGLImplementationParts());
  149. if (gl_display_->ext->b_EGL_EXT_create_context_robustness || is_swangle) {
  150. DVLOG(1) << "EGL_EXT_create_context_robustness supported.";
  151. context_attributes.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
  152. context_attributes.push_back(
  153. (attribs.robust_buffer_access || is_swangle) ? EGL_TRUE : EGL_FALSE);
  154. if (attribs.lose_context_on_reset) {
  155. context_attributes.push_back(
  156. EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
  157. context_attributes.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT);
  158. if (gl_display_->ext->b_EGL_NV_robustness_video_memory_purge) {
  159. context_attributes.push_back(
  160. EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV);
  161. context_attributes.push_back(EGL_TRUE);
  162. }
  163. }
  164. } else {
  165. // At some point we should require the presence of the robustness
  166. // extension and remove this code path.
  167. DVLOG(1) << "EGL_EXT_create_context_robustness NOT supported.";
  168. }
  169. if (!eglBindAPI(EGL_OPENGL_ES_API)) {
  170. LOG(ERROR) << "eglBindApi failed with error "
  171. << GetLastEGLErrorString();
  172. return false;
  173. }
  174. if (gl_display_->ext->b_EGL_CHROMIUM_create_context_bind_generates_resource) {
  175. context_attributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
  176. context_attributes.push_back(attribs.bind_generates_resource ? EGL_TRUE
  177. : EGL_FALSE);
  178. } else {
  179. DCHECK(attribs.bind_generates_resource);
  180. }
  181. if (gl_display_->ext->b_EGL_ANGLE_create_context_webgl_compatibility) {
  182. context_attributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
  183. context_attributes.push_back(
  184. attribs.webgl_compatibility_context ? EGL_TRUE : EGL_FALSE);
  185. } else {
  186. DCHECK(!attribs.webgl_compatibility_context);
  187. }
  188. if (gl_display_->IsEGLContextPrioritySupported()) {
  189. // Medium priority is the default, only set the attribute if
  190. // a different priority is requested.
  191. if (attribs.context_priority == ContextPriorityLow) {
  192. DVLOG(1) << __FUNCTION__ << ": setting ContextPriorityLow";
  193. context_attributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
  194. context_attributes.push_back(EGL_CONTEXT_PRIORITY_LOW_IMG);
  195. } else if (attribs.context_priority == ContextPriorityHigh) {
  196. DVLOG(1) << __FUNCTION__ << ": setting ContextPriorityHigh";
  197. context_attributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
  198. context_attributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
  199. }
  200. }
  201. if (gl_display_->ext->b_EGL_ANGLE_display_texture_share_group) {
  202. context_attributes.push_back(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE);
  203. context_attributes.push_back(
  204. attribs.global_texture_share_group ? EGL_TRUE : EGL_FALSE);
  205. } else {
  206. DCHECK(!attribs.global_texture_share_group);
  207. }
  208. if (gl_display_->ext->b_EGL_ANGLE_display_semaphore_share_group) {
  209. context_attributes.push_back(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE);
  210. context_attributes.push_back(
  211. attribs.global_semaphore_share_group ? EGL_TRUE : EGL_FALSE);
  212. } else {
  213. DCHECK(!attribs.global_semaphore_share_group);
  214. }
  215. if (gl_display_->ext->b_EGL_ANGLE_create_context_client_arrays) {
  216. // Disable client arrays if the context supports it
  217. context_attributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
  218. context_attributes.push_back(EGL_FALSE);
  219. }
  220. if (gl_display_->ext->b_EGL_ANGLE_robust_resource_initialization ||
  221. is_swangle) {
  222. context_attributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
  223. context_attributes.push_back(
  224. (attribs.robust_resource_initialization || is_swangle) ? EGL_TRUE
  225. : EGL_FALSE);
  226. } else {
  227. DCHECK(!attribs.robust_resource_initialization);
  228. }
  229. if (gl_display_->ext->b_EGL_ANGLE_create_context_backwards_compatible) {
  230. // Request a specific context version. The Passthrough command decoder
  231. // relies on the returned context being the exact version it requested.
  232. context_attributes.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
  233. context_attributes.push_back(EGL_FALSE);
  234. }
  235. if (gl_display_->ext->b_EGL_ANGLE_power_preference) {
  236. GpuPreference pref = attribs.gpu_preference;
  237. pref = GLSurface::AdjustGpuPreference(pref);
  238. switch (pref) {
  239. case GpuPreference::kDefault:
  240. // Don't request any GPU, let ANGLE and the native driver decide.
  241. break;
  242. case GpuPreference::kLowPower:
  243. context_attributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
  244. context_attributes.push_back(EGL_LOW_POWER_ANGLE);
  245. break;
  246. case GpuPreference::kHighPerformance:
  247. context_attributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
  248. context_attributes.push_back(EGL_HIGH_POWER_ANGLE);
  249. break;
  250. default:
  251. NOTREACHED();
  252. }
  253. }
  254. if (gl_display_->ext->b_EGL_ANGLE_external_context_and_surface) {
  255. if (attribs.angle_create_from_external_context) {
  256. context_attributes.push_back(EGL_EXTERNAL_CONTEXT_ANGLE);
  257. context_attributes.push_back(EGL_TRUE);
  258. }
  259. if (attribs.angle_restore_external_context_state) {
  260. context_attributes.push_back(EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE);
  261. context_attributes.push_back(EGL_TRUE);
  262. }
  263. }
  264. if (gl_display_->ext->b_EGL_ANGLE_context_virtualization) {
  265. context_attributes.push_back(EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE);
  266. context_attributes.push_back(
  267. static_cast<EGLint>(attribs.angle_context_virtualization_group_number));
  268. }
  269. // Skia manages program cache by itself.
  270. // For WebGL program, it should manage program by itself too.
  271. if (gl_display_->ext->b_EGL_ANGLE_program_cache_control) {
  272. context_attributes.push_back(
  273. EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
  274. context_attributes.push_back(EGL_FALSE);
  275. }
  276. // Append final EGL_NONE to signal the context attributes are finished
  277. context_attributes.push_back(EGL_NONE);
  278. context_attributes.push_back(EGL_NONE);
  279. context_ =
  280. eglCreateContext(gl_display_->GetDisplay(), config_,
  281. share_group() ? share_group()->GetHandle() : nullptr,
  282. context_attributes.data());
  283. // If EGL_KHR_no_config_context is in use and context creation failed,
  284. // it might indicate that an unsupported ES version was requested. Try
  285. // falling back to a lower version.
  286. if (!context_ && gl_display_->ext->b_EGL_KHR_no_config_context &&
  287. eglGetError() == EGL_BAD_MATCH) {
  288. // Set up the list of versions to try: 3.1 -> 3.0 -> 2.0
  289. std::vector<std::pair<EGLint, EGLint>> candidate_versions;
  290. if (context_client_major_version == 3 &&
  291. context_client_minor_version == 1) {
  292. candidate_versions.emplace_back(3, 0);
  293. candidate_versions.emplace_back(2, 0);
  294. } else if (context_client_major_version == 3 &&
  295. context_client_minor_version == 0) {
  296. candidate_versions.emplace_back(2, 0);
  297. }
  298. for (const auto& version : candidate_versions) {
  299. if (!ChangeContextAttributes(context_attributes,
  300. EGL_CONTEXT_MAJOR_VERSION, version.first) ||
  301. !ChangeContextAttributes(context_attributes,
  302. EGL_CONTEXT_MINOR_VERSION, version.second)) {
  303. break;
  304. }
  305. context_ =
  306. eglCreateContext(gl_display_->GetDisplay(), config_,
  307. share_group() ? share_group()->GetHandle() : nullptr,
  308. context_attributes.data());
  309. // Stop searching as soon as a context is successfully created.
  310. if (context_) {
  311. break;
  312. }
  313. }
  314. }
  315. if (!context_) {
  316. LOG(ERROR) << "eglCreateContext failed with error "
  317. << GetLastEGLErrorString();
  318. return false;
  319. }
  320. return true;
  321. }
  322. void GLContextEGL::Destroy() {
  323. ReleaseYUVToRGBConvertersAndBackpressureFences();
  324. if (context_) {
  325. if (!eglDestroyContext(gl_display_->GetDisplay(), context_)) {
  326. LOG(ERROR) << "eglDestroyContext failed with error "
  327. << GetLastEGLErrorString();
  328. }
  329. context_ = nullptr;
  330. }
  331. }
  332. YUVToRGBConverter* GLContextEGL::GetYUVToRGBConverter(
  333. const gfx::ColorSpace& color_space) {
  334. // Make sure YUVToRGBConverter objects never get created when surfaceless EGL
  335. // contexts aren't supported since support for surfaceless EGL contexts is
  336. // required in order to properly release YUVToRGBConverter objects (see
  337. // GLContextEGL::ReleaseYUVToRGBConvertersAndBackpressureFences())
  338. if (!gl_display_->IsEGLSurfacelessContextSupported()) {
  339. return nullptr;
  340. }
  341. std::unique_ptr<YUVToRGBConverter>& yuv_to_rgb_converter =
  342. yuv_to_rgb_converters_[color_space];
  343. if (!yuv_to_rgb_converter) {
  344. yuv_to_rgb_converter =
  345. std::make_unique<YUVToRGBConverter>(*GetVersionInfo(), color_space);
  346. }
  347. return yuv_to_rgb_converter.get();
  348. }
  349. void GLContextEGL::SetVisibility(bool visibility) {
  350. if (gl_display_->ext->b_EGL_ANGLE_power_preference) {
  351. // It doesn't matter whether this context was explicitly allocated
  352. // with a power preference - ANGLE will take care of any default behavior.
  353. if (visibility) {
  354. eglReacquireHighPowerGPUANGLE(gl_display_->GetDisplay(), context_);
  355. } else {
  356. eglReleaseHighPowerGPUANGLE(gl_display_->GetDisplay(), context_);
  357. }
  358. }
  359. }
  360. GLDisplayEGL* GLContextEGL::GetGLDisplayEGL() {
  361. return gl_display_;
  362. }
  363. void GLContextEGL::ReleaseYUVToRGBConvertersAndBackpressureFences() {
  364. #if BUILDFLAG(IS_APPLE)
  365. bool has_backpressure_fences = HasBackpressureFences();
  366. #else
  367. bool has_backpressure_fences = false;
  368. #endif
  369. if (!yuv_to_rgb_converters_.empty() || has_backpressure_fences) {
  370. // If this context is not current, bind this context's API so that the YUV
  371. // converter can safely destruct
  372. GLContext* current_context = GetRealCurrent();
  373. if (current_context != this) {
  374. SetCurrentGL(GetCurrentGL());
  375. }
  376. EGLContext current_egl_context = eglGetCurrentContext();
  377. EGLSurface current_draw_surface = EGL_NO_SURFACE;
  378. EGLSurface current_read_surface = EGL_NO_SURFACE;
  379. if (context_ != current_egl_context) {
  380. current_draw_surface = eglGetCurrentSurface(EGL_DRAW);
  381. current_read_surface = eglGetCurrentSurface(EGL_READ);
  382. // This call relies on the fact that yuv_to_rgb_converters_ are only ever
  383. // allocated in GLImageIOSurfaceEGL::CopyTexImage, which is only on
  384. // MacOS, where surfaceless EGL contexts are always supported.
  385. if (!eglMakeCurrent(gl_display_->GetDisplay(), EGL_NO_SURFACE,
  386. EGL_NO_SURFACE, context_)) {
  387. LOG(ERROR) << "eglMakeCurrent failed with error "
  388. << GetLastEGLErrorString();
  389. }
  390. }
  391. yuv_to_rgb_converters_.clear();
  392. #if BUILDFLAG(IS_APPLE)
  393. DestroyBackpressureFences();
  394. #endif
  395. // Rebind the current context's API if needed.
  396. if (current_context && current_context != this) {
  397. SetCurrentGL(current_context->GetCurrentGL());
  398. }
  399. if (context_ != current_egl_context) {
  400. if (!eglMakeCurrent(gl_display_->GetDisplay(), current_draw_surface,
  401. current_read_surface, current_egl_context)) {
  402. LOG(ERROR) << "eglMakeCurrent failed with error "
  403. << GetLastEGLErrorString();
  404. }
  405. }
  406. }
  407. }
  408. bool GLContextEGL::MakeCurrentImpl(GLSurface* surface) {
  409. DCHECK(context_);
  410. if (lost_) {
  411. LOG(ERROR) << "Failed to make context current since it is marked as lost";
  412. return false;
  413. }
  414. if (IsCurrent(surface))
  415. return true;
  416. ScopedReleaseCurrent release_current;
  417. TRACE_EVENT2("gpu", "GLContextEGL::MakeCurrent", "context",
  418. static_cast<void*>(context_), "surface",
  419. static_cast<void*>(surface));
  420. if (unbind_fbo_on_makecurrent_ && GetCurrent()) {
  421. glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
  422. }
  423. if (!eglMakeCurrent(gl_display_->GetDisplay(), surface->GetHandle(),
  424. surface->GetHandle(), context_)) {
  425. LOG(ERROR) << "eglMakeCurrent failed with error "
  426. << GetLastEGLErrorString();
  427. return false;
  428. }
  429. // Set this as soon as the context is current, since we might call into GL.
  430. BindGLApi();
  431. SetCurrent(surface);
  432. InitializeDynamicBindings();
  433. if (!surface->OnMakeCurrent(this)) {
  434. LOG(ERROR) << "Could not make current.";
  435. return false;
  436. }
  437. release_current.Cancel();
  438. return true;
  439. }
  440. void GLContextEGL::SetUnbindFboOnMakeCurrent() {
  441. unbind_fbo_on_makecurrent_ = true;
  442. }
  443. void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
  444. if (!IsCurrent(surface))
  445. return;
  446. if (unbind_fbo_on_makecurrent_)
  447. glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
  448. SetCurrent(nullptr);
  449. if (!eglMakeCurrent(gl_display_->GetDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE,
  450. EGL_NO_CONTEXT)) {
  451. LOG(ERROR) << "eglMakeCurrent failed to release current with error "
  452. << GetLastEGLErrorString();
  453. lost_ = true;
  454. }
  455. DCHECK(!IsCurrent(nullptr));
  456. }
  457. bool GLContextEGL::IsCurrent(GLSurface* surface) {
  458. DCHECK(context_);
  459. if (lost_)
  460. return false;
  461. bool native_context_is_current = context_ == eglGetCurrentContext();
  462. // If our context is current then our notion of which GLContext is
  463. // current must be correct. On the other hand, third-party code
  464. // using OpenGL might change the current context.
  465. DCHECK(!native_context_is_current || (GetRealCurrent() == this));
  466. if (!native_context_is_current)
  467. return false;
  468. if (surface) {
  469. if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW))
  470. return false;
  471. }
  472. return true;
  473. }
  474. void* GLContextEGL::GetHandle() {
  475. return context_;
  476. }
  477. unsigned int GLContextEGL::CheckStickyGraphicsResetStatusImpl() {
  478. DCHECK(IsCurrent(nullptr));
  479. DCHECK(g_current_gl_driver);
  480. const ExtensionsGL& ext = g_current_gl_driver->ext;
  481. if ((graphics_reset_status_ == GL_NO_ERROR) &&
  482. gl_display_->ext->b_EGL_EXT_create_context_robustness &&
  483. (ext.b_GL_KHR_robustness || ext.b_GL_EXT_robustness ||
  484. ext.b_GL_ARB_robustness)) {
  485. graphics_reset_status_ = glGetGraphicsResetStatusARB();
  486. }
  487. return graphics_reset_status_;
  488. }
  489. GLContextEGL::~GLContextEGL() {
  490. Destroy();
  491. }
  492. } // namespace gl