gl_gl_api_implementation.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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_gl_api_implementation.h"
  5. #include <vector>
  6. #include "base/command_line.h"
  7. #include "base/containers/contains.h"
  8. #include "base/strings/string_split.h"
  9. #include "base/strings/string_util.h"
  10. #include "ui/gl/gl_context.h"
  11. #include "ui/gl/gl_implementation.h"
  12. #include "ui/gl/gl_state_restorer.h"
  13. #include "ui/gl/gl_surface.h"
  14. #include "ui/gl/gl_switches.h"
  15. #include "ui/gl/gl_version_info.h"
  16. #include "ui/gl/shader_tracking.h"
  17. namespace gl {
  18. // The GL state for when no context is bound
  19. static CurrentGL* g_no_context_current_gl = nullptr;
  20. // If the null draw bindings are currently enabled.
  21. // TODO: Consider adding a new GLApi that no-ops these functions
  22. static bool g_null_draw_bindings_enabled = false;
  23. namespace {
  24. // TODO(epenner): Could the above function be merged into GetInternalFormat and
  25. // removed?
  26. static inline GLenum GetTexInternalFormat(const GLVersionInfo* version,
  27. GLenum internal_format,
  28. GLenum format,
  29. GLenum type) {
  30. GLenum gl_internal_format = GetInternalFormat(version, internal_format);
  31. // g_version_info must be initialized when this function is bound.
  32. if (version->is_es3) {
  33. if (internal_format == GL_RED_EXT) {
  34. // GL_EXT_texture_rg case in ES2.
  35. switch (type) {
  36. case GL_UNSIGNED_BYTE:
  37. gl_internal_format = GL_R8_EXT;
  38. break;
  39. case GL_UNSIGNED_SHORT:
  40. gl_internal_format = GL_R16_EXT;
  41. break;
  42. case GL_HALF_FLOAT_OES:
  43. gl_internal_format = GL_R16F_EXT;
  44. break;
  45. case GL_FLOAT:
  46. gl_internal_format = GL_R32F_EXT;
  47. break;
  48. default:
  49. NOTREACHED();
  50. break;
  51. }
  52. return gl_internal_format;
  53. } else if (internal_format == GL_RG_EXT) {
  54. // GL_EXT_texture_rg case in ES2.
  55. switch (type) {
  56. case GL_UNSIGNED_BYTE:
  57. gl_internal_format = GL_RG8_EXT;
  58. break;
  59. case GL_HALF_FLOAT_OES:
  60. gl_internal_format = GL_RG16F_EXT;
  61. break;
  62. case GL_FLOAT:
  63. gl_internal_format = GL_RG32F_EXT;
  64. break;
  65. default:
  66. NOTREACHED();
  67. break;
  68. }
  69. return gl_internal_format;
  70. }
  71. }
  72. if (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) {
  73. switch (internal_format) {
  74. case GL_SRGB_EXT:
  75. gl_internal_format = GL_SRGB8;
  76. break;
  77. case GL_SRGB_ALPHA_EXT:
  78. gl_internal_format = GL_SRGB8_ALPHA8;
  79. break;
  80. default:
  81. break;
  82. }
  83. }
  84. if (version->is_es2)
  85. return gl_internal_format;
  86. // For ES3, use sized float/half_float internal formats whenever posssible.
  87. if (type == GL_FLOAT) {
  88. switch (internal_format) {
  89. // We need to map all the unsized internal formats from ES2 clients.
  90. case GL_RGBA:
  91. gl_internal_format = GL_RGBA32F;
  92. break;
  93. case GL_RGB:
  94. gl_internal_format = GL_RGB32F;
  95. break;
  96. case GL_LUMINANCE_ALPHA:
  97. if (!version->is_es)
  98. gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
  99. break;
  100. case GL_LUMINANCE:
  101. if (!version->is_es)
  102. gl_internal_format = GL_LUMINANCE32F_ARB;
  103. break;
  104. case GL_ALPHA:
  105. if (!version->is_es)
  106. gl_internal_format = GL_ALPHA32F_ARB;
  107. break;
  108. default:
  109. // We can't assert here because if the client context is ES3,
  110. // all sized internal_format will reach here.
  111. break;
  112. }
  113. } else if (type == GL_HALF_FLOAT_OES) {
  114. switch (internal_format) {
  115. case GL_RGBA:
  116. gl_internal_format = GL_RGBA16F;
  117. break;
  118. case GL_RGB:
  119. gl_internal_format = GL_RGB16F;
  120. break;
  121. case GL_LUMINANCE_ALPHA:
  122. if (!version->is_es)
  123. gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
  124. break;
  125. case GL_LUMINANCE:
  126. if (!version->is_es)
  127. gl_internal_format = GL_LUMINANCE16F_ARB;
  128. break;
  129. case GL_ALPHA:
  130. if (!version->is_es)
  131. gl_internal_format = GL_ALPHA16F_ARB;
  132. break;
  133. default:
  134. break;
  135. }
  136. }
  137. return gl_internal_format;
  138. }
  139. static inline GLenum GetTexFormat(const GLVersionInfo* version, GLenum format) {
  140. GLenum gl_format = format;
  141. if (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) {
  142. switch (format) {
  143. case GL_SRGB_EXT:
  144. gl_format = GL_RGB;
  145. break;
  146. case GL_SRGB_ALPHA_EXT:
  147. gl_format = GL_RGBA;
  148. break;
  149. default:
  150. break;
  151. }
  152. }
  153. return gl_format;
  154. }
  155. static inline GLenum GetPixelType(const GLVersionInfo* version,
  156. GLenum type,
  157. GLenum format) {
  158. if (!version->is_es2) {
  159. if (type == GL_HALF_FLOAT_OES) {
  160. if (version->is_es) {
  161. // For ES3+, use HALF_FLOAT instead of HALF_FLOAT_OES whenever possible.
  162. switch (format) {
  163. case GL_LUMINANCE:
  164. case GL_LUMINANCE_ALPHA:
  165. case GL_ALPHA:
  166. return type;
  167. default:
  168. break;
  169. }
  170. }
  171. return GL_HALF_FLOAT;
  172. }
  173. }
  174. return type;
  175. }
  176. } // anonymous namespace
  177. GLenum GetInternalFormat(const GLVersionInfo* version, GLenum internal_format) {
  178. if (!version->is_es) {
  179. if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
  180. return GL_RGBA8;
  181. }
  182. if (version->is_es3 && version->is_mesa) {
  183. // Mesa bug workaround: Mipmapping does not work when using GL_BGRA_EXT
  184. if (internal_format == GL_BGRA_EXT)
  185. return GL_RGBA;
  186. }
  187. return internal_format;
  188. }
  189. void InitializeStaticGLBindingsGL() {
  190. g_current_gl_context_tls = new base::ThreadLocalPointer<CurrentGL>;
  191. g_no_context_current_gl = new CurrentGL;
  192. g_no_context_current_gl->Api = new NoContextGLApi;
  193. }
  194. void ClearBindingsGL() {
  195. if (g_no_context_current_gl) {
  196. delete g_no_context_current_gl->Api;
  197. delete g_no_context_current_gl->Driver;
  198. delete g_no_context_current_gl->Version;
  199. delete g_no_context_current_gl;
  200. g_no_context_current_gl = nullptr;
  201. }
  202. if (g_current_gl_context_tls) {
  203. delete g_current_gl_context_tls;
  204. g_current_gl_context_tls = nullptr;
  205. }
  206. }
  207. bool SetNullDrawGLBindingsEnabled(bool enabled) {
  208. bool old_value = g_null_draw_bindings_enabled;
  209. g_null_draw_bindings_enabled = enabled;
  210. return old_value;
  211. }
  212. bool GetNullDrawBindingsEnabled() {
  213. return g_null_draw_bindings_enabled;
  214. }
  215. void SetCurrentGL(CurrentGL* current) {
  216. CurrentGL* new_current = current ? current : g_no_context_current_gl;
  217. g_current_gl_context_tls->Set(new_current);
  218. }
  219. GLApi::GLApi() = default;
  220. GLApi::~GLApi() = default;
  221. GLApiBase::GLApiBase() : driver_(nullptr) {}
  222. GLApiBase::~GLApiBase() = default;
  223. void GLApiBase::InitializeBase(DriverGL* driver) {
  224. driver_ = driver;
  225. }
  226. RealGLApi::RealGLApi()
  227. : logging_enabled_(base::CommandLine::ForCurrentProcess()->HasSwitch(
  228. switches::kEnableGPUServiceLogging)) {}
  229. RealGLApi::~RealGLApi() = default;
  230. void RealGLApi::Initialize(DriverGL* driver) {
  231. InitializeBase(driver);
  232. }
  233. void RealGLApi::glGetIntegervFn(GLenum pname, GLint* params) {
  234. if (pname == GL_NUM_EXTENSIONS && disabled_exts_.size()) {
  235. InitializeFilteredExtensionsIfNeeded();
  236. *params = static_cast<GLint>(filtered_exts_.size());
  237. } else {
  238. GLApiBase::glGetIntegervFn(pname, params);
  239. }
  240. }
  241. const GLubyte* RealGLApi::glGetStringFn(GLenum name) {
  242. if (name == GL_EXTENSIONS && disabled_exts_.size()) {
  243. InitializeFilteredExtensionsIfNeeded();
  244. return reinterpret_cast<const GLubyte*>(filtered_exts_str_.c_str());
  245. }
  246. return GLApiBase::glGetStringFn(name);
  247. }
  248. const GLubyte* RealGLApi::glGetStringiFn(GLenum name, GLuint index) {
  249. if (name == GL_EXTENSIONS && disabled_exts_.size()) {
  250. InitializeFilteredExtensionsIfNeeded();
  251. if (index >= filtered_exts_.size()) {
  252. return nullptr;
  253. }
  254. return reinterpret_cast<const GLubyte*>(filtered_exts_[index].c_str());
  255. }
  256. return GLApiBase::glGetStringiFn(name, index);
  257. }
  258. void RealGLApi::glTexImage2DFn(GLenum target,
  259. GLint level,
  260. GLint internalformat,
  261. GLsizei width,
  262. GLsizei height,
  263. GLint border,
  264. GLenum format,
  265. GLenum type,
  266. const void* pixels) {
  267. GLenum gl_internal_format =
  268. GetTexInternalFormat(version_.get(), internalformat, format, type);
  269. GLenum gl_format = GetTexFormat(version_.get(), format);
  270. GLenum gl_type = GetPixelType(version_.get(), type, format);
  271. // TODO(yizhou): Check if cubemap, 3d texture or texture2d array has the same
  272. // bug on intel mac.
  273. if (!version_->is_angle && gl_workarounds_.reset_teximage2d_base_level &&
  274. target == GL_TEXTURE_2D) {
  275. GLint base_level = 0;
  276. GLApiBase::glGetTexParameterivFn(target, GL_TEXTURE_BASE_LEVEL,
  277. &base_level);
  278. if (base_level) {
  279. GLApiBase::glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, 0);
  280. GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width,
  281. height, border, gl_format, gl_type, pixels);
  282. GLApiBase::glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, base_level);
  283. return;
  284. }
  285. }
  286. GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width, height,
  287. border, gl_format, gl_type, pixels);
  288. }
  289. void RealGLApi::glTexSubImage2DFn(GLenum target,
  290. GLint level,
  291. GLint xoffset,
  292. GLint yoffset,
  293. GLsizei width,
  294. GLsizei height,
  295. GLenum format,
  296. GLenum type,
  297. const void* pixels) {
  298. GLenum gl_format = GetTexFormat(version_.get(), format);
  299. GLenum gl_type = GetPixelType(version_.get(), type, format);
  300. GLApiBase::glTexSubImage2DFn(target, level, xoffset, yoffset, width, height,
  301. gl_format, gl_type, pixels);
  302. }
  303. void RealGLApi::glTexStorage2DEXTFn(GLenum target,
  304. GLsizei levels,
  305. GLenum internalformat,
  306. GLsizei width,
  307. GLsizei height) {
  308. GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  309. GLApiBase::glTexStorage2DEXTFn(target, levels, gl_internal_format, width,
  310. height);
  311. }
  312. void RealGLApi::glTexStorageMem2DEXTFn(GLenum target,
  313. GLsizei levels,
  314. GLenum internalformat,
  315. GLsizei width,
  316. GLsizei height,
  317. GLuint memory,
  318. GLuint64 offset) {
  319. internalformat = GetInternalFormat(version_.get(), internalformat);
  320. GLApiBase::glTexStorageMem2DEXTFn(target, levels, internalformat, width,
  321. height, memory, offset);
  322. }
  323. void RealGLApi::glTexStorageMemFlags2DANGLEFn(
  324. GLenum target,
  325. GLsizei levels,
  326. GLenum internalformat,
  327. GLsizei width,
  328. GLsizei height,
  329. GLuint memory,
  330. GLuint64 offset,
  331. GLbitfield createFlags,
  332. GLbitfield usageFlags,
  333. const void* imageCreateInfoPNext) {
  334. internalformat = GetInternalFormat(version_.get(), internalformat);
  335. GLApiBase::glTexStorageMemFlags2DANGLEFn(
  336. target, levels, internalformat, width, height, memory, offset,
  337. createFlags, usageFlags, imageCreateInfoPNext);
  338. }
  339. void RealGLApi::glRenderbufferStorageEXTFn(GLenum target,
  340. GLenum internalformat,
  341. GLsizei width,
  342. GLsizei height) {
  343. GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  344. GLApiBase::glRenderbufferStorageEXTFn(target, gl_internal_format, width,
  345. height);
  346. }
  347. // The ANGLE and IMG variants of glRenderbufferStorageMultisample currently do
  348. // not support BGRA render buffers so only the EXT one is customized. If
  349. // GL_CHROMIUM_renderbuffer_format_BGRA8888 support is added to ANGLE then the
  350. // ANGLE version should also be customized.
  351. void RealGLApi::glRenderbufferStorageMultisampleEXTFn(GLenum target,
  352. GLsizei samples,
  353. GLenum internalformat,
  354. GLsizei width,
  355. GLsizei height) {
  356. GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  357. GLApiBase::glRenderbufferStorageMultisampleEXTFn(
  358. target, samples, gl_internal_format, width, height);
  359. }
  360. void RealGLApi::glRenderbufferStorageMultisampleFn(GLenum target,
  361. GLsizei samples,
  362. GLenum internalformat,
  363. GLsizei width,
  364. GLsizei height) {
  365. GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat);
  366. GLApiBase::glRenderbufferStorageMultisampleFn(
  367. target, samples, gl_internal_format, width, height);
  368. }
  369. void RealGLApi::glReadPixelsFn(GLint x,
  370. GLint y,
  371. GLsizei width,
  372. GLsizei height,
  373. GLenum format,
  374. GLenum type,
  375. void* pixels) {
  376. GLenum gl_type = GetPixelType(version_.get(), type, format);
  377. GLApiBase::glReadPixelsFn(x, y, width, height, format, gl_type, pixels);
  378. }
  379. void RealGLApi::glClearFn(GLbitfield mask) {
  380. if (!g_null_draw_bindings_enabled) {
  381. GLApiBase::glClearFn(mask);
  382. } else if (logging_enabled_) {
  383. LOG(WARNING) << "Skipped glClear()";
  384. }
  385. }
  386. void RealGLApi::glClearColorFn(GLclampf red,
  387. GLclampf green,
  388. GLclampf blue,
  389. GLclampf alpha) {
  390. if (!version_->is_angle && gl_workarounds_.clear_to_zero_or_one_broken &&
  391. (1 == red || 0 == red) && (1 == green || 0 == green) &&
  392. (1 == blue || 0 == blue) && (1 == alpha || 0 == alpha)) {
  393. if (1 == alpha)
  394. alpha = 2;
  395. else
  396. alpha = -1;
  397. }
  398. GLApiBase::glClearColorFn(red, green, blue, alpha);
  399. }
  400. void RealGLApi::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) {
  401. if (!g_null_draw_bindings_enabled) {
  402. GLApiBase::glDrawArraysFn(mode, first, count);
  403. } else if (logging_enabled_) {
  404. LOG(WARNING) << "Skipped glDrawArrays()";
  405. }
  406. }
  407. void RealGLApi::glDrawElementsFn(GLenum mode,
  408. GLsizei count,
  409. GLenum type,
  410. const void* indices) {
  411. if (!g_null_draw_bindings_enabled) {
  412. GLApiBase::glDrawElementsFn(mode, count, type, indices);
  413. } else if (logging_enabled_) {
  414. LOG(WARNING) << "Skipped glDrawElements()";
  415. }
  416. }
  417. void RealGLApi::glClearDepthFn(GLclampd depth) {
  418. // OpenGL ES only has glClearDepthf, forward the parameters from glClearDepth.
  419. // Many mock tests expect only glClearDepth is called so don't make the
  420. // interception when testing with mocks.
  421. if (version_->is_es && GetGLImplementation() != kGLImplementationMockGL) {
  422. DCHECK(driver_->fn.glClearDepthfFn);
  423. GLApiBase::glClearDepthfFn(static_cast<GLclampf>(depth));
  424. } else {
  425. DCHECK(driver_->fn.glClearDepthFn);
  426. GLApiBase::glClearDepthFn(depth);
  427. }
  428. }
  429. void RealGLApi::glDepthRangeFn(GLclampd z_near, GLclampd z_far) {
  430. // OpenGL ES only has glDepthRangef, forward the parameters from glDepthRange.
  431. // Many mock tests expect only glDepthRange is called so don't make the
  432. // interception when testing with mocks.
  433. if (version_->is_es && GetGLImplementation() != kGLImplementationMockGL) {
  434. DCHECK(driver_->fn.glDepthRangefFn);
  435. GLApiBase::glDepthRangefFn(static_cast<GLclampf>(z_near),
  436. static_cast<GLclampf>(z_far));
  437. } else {
  438. DCHECK(driver_->fn.glDepthRangeFn);
  439. GLApiBase::glDepthRangeFn(z_near, z_far);
  440. }
  441. }
  442. void RealGLApi::glUseProgramFn(GLuint program) {
  443. ShaderTracking* shader_tracking = ShaderTracking::GetInstance();
  444. if (shader_tracking) {
  445. std::vector<char> buffers[2];
  446. char* strings[2] = {nullptr, nullptr};
  447. if (program) {
  448. // The following only works with ANGLE backend because ANGLE makes sure
  449. // a program's shaders are not actually deleted and source can still be
  450. // queried even if glDeleteShaders() has been called on them.
  451. // Also, in theory, different shaders can be attached to the program
  452. // after the last link, but for now, ignore such corner case patterns.
  453. GLsizei count = 0;
  454. GLuint shaders[2] = {0};
  455. glGetAttachedShadersFn(program, 2, &count, shaders);
  456. for (GLsizei ii = 0; ii < std::min(2, count); ++ii) {
  457. buffers[ii].resize(ShaderTracking::kMaxShaderSize);
  458. glGetShaderSourceFn(shaders[ii], ShaderTracking::kMaxShaderSize,
  459. nullptr, buffers[ii].data());
  460. strings[ii] = buffers[ii].data();
  461. }
  462. }
  463. shader_tracking->SetShaders(strings[0], strings[1]);
  464. }
  465. GLApiBase::glUseProgramFn(program);
  466. }
  467. void RealGLApi::InitializeFilteredExtensionsIfNeeded() {
  468. DCHECK(disabled_exts_.size());
  469. if (filtered_exts_.size())
  470. return;
  471. DCHECK(filtered_exts_str_.empty());
  472. if (WillUseGLGetStringForExtensions(this)) {
  473. filtered_exts_str_ = FilterGLExtensionList(
  474. reinterpret_cast<const char*>(GLApiBase::glGetStringFn(GL_EXTENSIONS)),
  475. disabled_exts_);
  476. filtered_exts_ = base::SplitString(
  477. filtered_exts_str_, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  478. } else {
  479. GLint num_extensions = 0;
  480. GLApiBase::glGetIntegervFn(GL_NUM_EXTENSIONS, &num_extensions);
  481. for (GLint i = 0; i < num_extensions; ++i) {
  482. const char* gl_extension = reinterpret_cast<const char*>(
  483. GLApiBase::glGetStringiFn(GL_EXTENSIONS, i));
  484. DCHECK(gl_extension);
  485. if (!base::Contains(disabled_exts_, gl_extension))
  486. filtered_exts_.push_back(gl_extension);
  487. }
  488. filtered_exts_str_ = base::JoinString(filtered_exts_, " ");
  489. }
  490. }
  491. void RealGLApi::SetDisabledExtensions(const std::string& disabled_extensions) {
  492. ClearCachedGLExtensions();
  493. disabled_exts_.clear();
  494. if (disabled_extensions.empty())
  495. return;
  496. disabled_exts_ =
  497. base::SplitString(disabled_extensions, ", ;", base::KEEP_WHITESPACE,
  498. base::SPLIT_WANT_NONEMPTY);
  499. DCHECK(disabled_exts_.size());
  500. }
  501. void RealGLApi::ClearCachedGLExtensions() {
  502. filtered_exts_.clear();
  503. filtered_exts_str_.clear();
  504. }
  505. void RealGLApi::set_gl_workarounds(const GLWorkarounds& workarounds) {
  506. gl_workarounds_ = workarounds;
  507. }
  508. void RealGLApi::set_version(std::unique_ptr<GLVersionInfo> version) {
  509. version_ = std::move(version);
  510. }
  511. TraceGLApi::~TraceGLApi() = default;
  512. LogGLApi::LogGLApi(GLApi* gl_api) : gl_api_(gl_api) {}
  513. LogGLApi::~LogGLApi() = default;
  514. NoContextGLApi::NoContextGLApi() = default;
  515. NoContextGLApi::~NoContextGLApi() = default;
  516. } // namespace gl