scoped_app_gl_state_restore_impl_angle.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright 2021 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 "android_webview/browser/gfx/scoped_app_gl_state_restore_impl_angle.h"
  5. #include <EGL/egl.h>
  6. #include <GLES2/gl2.h>
  7. #include "base/android/build_info.h"
  8. #include "base/native_library.h"
  9. #include "base/threading/thread_restrictions.h"
  10. #include "ui/gl/gl_context.h"
  11. namespace android_webview {
  12. namespace {
  13. namespace os {
  14. // TODO(penghuang): remove this typedef when egl headers are updated to 1.5.
  15. typedef __eglMustCastToProperFunctionPointerType(
  16. EGLAPIENTRYP PFNEGLGETPROCADDRESSPROC)(const char* procname);
  17. typedef EGLContext(EGLAPIENTRYP PFNEGLGETCURRENTCONTEXTPROC)(void);
  18. PFNEGLGETPROCADDRESSPROC eglGetProcAddressFn = nullptr;
  19. PFNGLGETBOOLEANVPROC glGetBooleanvFn = nullptr;
  20. PFNGLGETINTEGERVPROC glGetIntegervFn = nullptr;
  21. #if DCHECK_IS_ON()
  22. PFNEGLGETCURRENTCONTEXTPROC eglGetCurrentContextFn = nullptr;
  23. #endif
  24. template <typename T>
  25. void AssignProc(T& fn, const char* name) {
  26. fn = reinterpret_cast<T>(eglGetProcAddressFn(name));
  27. CHECK(fn) << "Failed to get " << name;
  28. }
  29. void InitializeGLBindings() {
  30. if (eglGetProcAddressFn)
  31. return;
  32. base::NativeLibraryLoadError error;
  33. base::FilePath filename("libEGL.so");
  34. base::NativeLibrary egl_library = base::LoadNativeLibrary(filename, &error);
  35. CHECK(egl_library) << "Failed to load " << filename.MaybeAsASCII() << ": "
  36. << error.ToString();
  37. eglGetProcAddressFn = reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(
  38. base::GetFunctionPointerFromNativeLibrary(egl_library,
  39. "eglGetProcAddress"));
  40. CHECK(eglGetProcAddressFn) << "Failed to get eglGetProcAddress.";
  41. AssignProc(glGetBooleanvFn, "glGetBooleanv");
  42. AssignProc(glGetIntegervFn, "glGetIntegerv");
  43. #if DCHECK_IS_ON()
  44. AssignProc(eglGetCurrentContextFn, "eglGetCurrentContext");
  45. #endif
  46. }
  47. } // namespace os
  48. } // namespace
  49. namespace internal {
  50. ScopedAppGLStateRestoreImplAngle::ScopedAppGLStateRestoreImplAngle(
  51. ScopedAppGLStateRestore::CallMode mode,
  52. bool save_restore) {
  53. os::InitializeGLBindings();
  54. #if DCHECK_IS_ON()
  55. egl_context_ = os::eglGetCurrentContextFn();
  56. DCHECK_NE(egl_context_, EGL_NO_CONTEXT) << " no native context is current.";
  57. #endif
  58. if (base::android::BuildInfo::GetInstance()->sdk_int() ==
  59. base::android::SDK_VERSION_S) {
  60. GLint red_bits = 0;
  61. GLint green_bits = 0;
  62. GLint blue_bits = 0;
  63. GLint alpha_bits = 0;
  64. os::glGetIntegervFn(GL_RED_BITS, &red_bits);
  65. os::glGetIntegervFn(GL_GREEN_BITS, &green_bits);
  66. os::glGetIntegervFn(GL_BLUE_BITS, &blue_bits);
  67. os::glGetIntegervFn(GL_ALPHA_BITS, &alpha_bits);
  68. skip_draw_ =
  69. red_bits == 8 && green_bits == 0 && blue_bits == 0 && alpha_bits == 0;
  70. }
  71. // Query |stencil_state_| with native GL API.
  72. // Android should have made a native EGL context current, so we can call GL
  73. // directly.
  74. os::glGetBooleanvFn(GL_STENCIL_TEST, &stencil_state_.stencil_test_enabled);
  75. os::glGetIntegervFn(GL_STENCIL_FUNC, &stencil_state_.stencil_front_func);
  76. os::glGetIntegervFn(GL_STENCIL_VALUE_MASK,
  77. &stencil_state_.stencil_front_mask);
  78. os::glGetIntegervFn(GL_STENCIL_REF, &stencil_state_.stencil_front_ref);
  79. os::glGetIntegervFn(GL_STENCIL_BACK_FUNC, &stencil_state_.stencil_back_func);
  80. os::glGetIntegervFn(GL_STENCIL_BACK_VALUE_MASK,
  81. &stencil_state_.stencil_back_mask);
  82. os::glGetIntegervFn(GL_STENCIL_BACK_REF, &stencil_state_.stencil_back_ref);
  83. os::glGetIntegervFn(GL_STENCIL_CLEAR_VALUE, &stencil_state_.stencil_clear);
  84. os::glGetIntegervFn(GL_STENCIL_WRITEMASK,
  85. &stencil_state_.stencil_front_writemask);
  86. os::glGetIntegervFn(GL_STENCIL_BACK_WRITEMASK,
  87. &stencil_state_.stencil_back_writemask);
  88. os::glGetIntegervFn(GL_STENCIL_FAIL, &stencil_state_.stencil_front_fail_op);
  89. os::glGetIntegervFn(GL_STENCIL_PASS_DEPTH_FAIL,
  90. &stencil_state_.stencil_front_z_fail_op);
  91. os::glGetIntegervFn(GL_STENCIL_PASS_DEPTH_PASS,
  92. &stencil_state_.stencil_front_z_pass_op);
  93. os::glGetIntegervFn(GL_STENCIL_BACK_FAIL,
  94. &stencil_state_.stencil_back_fail_op);
  95. os::glGetIntegervFn(GL_STENCIL_BACK_PASS_DEPTH_FAIL,
  96. &stencil_state_.stencil_back_z_fail_op);
  97. os::glGetIntegervFn(GL_STENCIL_BACK_PASS_DEPTH_PASS,
  98. &stencil_state_.stencil_back_z_pass_op);
  99. // ANGLE can wrap current native FBO to an EGLSurface which will be used
  100. // later, so with that EGLSurface as render target, the framebuffer binding is
  101. // always 0.
  102. framebuffer_binding_ext_ = 0;
  103. // There should be no gl::GLContext current.
  104. DCHECK(!gl::GLContext::GetCurrent());
  105. }
  106. ScopedAppGLStateRestoreImplAngle::~ScopedAppGLStateRestoreImplAngle() {
  107. // There should be no gl::GLContext current.
  108. DCHECK(!gl::GLContext::GetCurrent());
  109. #if DCHECK_IS_ON()
  110. DCHECK_EQ(egl_context_, os::eglGetCurrentContextFn())
  111. << " the native context is changed.";
  112. #endif
  113. }
  114. } // namespace internal
  115. } // namespace android_webview