context.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // Copyright (c) 2016 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 "gpu/gles2_conform_support/egl/context.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/command_line.h"
  8. #include "gpu/command_buffer/client/gles2_implementation.h"
  9. #include "gpu/command_buffer/client/gles2_lib.h"
  10. #include "gpu/command_buffer/client/shared_memory_limits.h"
  11. #include "gpu/command_buffer/client/transfer_buffer.h"
  12. #include "gpu/command_buffer/service/context_group.h"
  13. #include "gpu/command_buffer/service/memory_tracking.h"
  14. #include "gpu/command_buffer/service/service_discardable_manager.h"
  15. #include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
  16. #include "gpu/gles2_conform_support/egl/config.h"
  17. #include "gpu/gles2_conform_support/egl/display.h"
  18. #include "gpu/gles2_conform_support/egl/surface.h"
  19. #include "gpu/gles2_conform_support/egl/thread_state.h"
  20. #include "ui/gl/init/gl_factory.h"
  21. // The slight complexification in this file comes from following properties:
  22. // 1) Command buffer connection (context) can not be established without a
  23. // GLSurface. EGL Context can be created independent of a surface. This is why
  24. // the connection is created only during first MakeCurrent.
  25. // 2) Command buffer MakeCurrent calls need the real gl context and surface be
  26. // current.
  27. // 3) Client can change real EGL context behind the scenes and then still expect
  28. // command buffer MakeCurrent re-set the command buffer context. This is why all
  29. // MakeCurrent calls must actually reset the real context, even though command
  30. // buffer current context does not change.
  31. // 4) EGL context can be destroyed without surface, but command buffer would
  32. // need the surface to run various cleanups. If context is destroyed
  33. // surfaceless, the context is marked lost before destruction. This is avoided
  34. // if possible, since command buffer at the time of writing prints out debug
  35. // text in this case.
  36. namespace {
  37. const bool kBindGeneratesResources = true;
  38. const bool kLoseContextWhenOutOfMemory = false;
  39. const bool kSupportClientSideArrays = true;
  40. }
  41. namespace gles2_conform_support {
  42. namespace egl {
  43. // static
  44. gpu::GpuFeatureInfo Context::platform_gpu_feature_info_;
  45. // static
  46. void Context::SetPlatformGpuFeatureInfo(
  47. const gpu::GpuFeatureInfo& gpu_feature_info) {
  48. platform_gpu_feature_info_ = gpu_feature_info;
  49. }
  50. Context::Context(Display* display, const Config* config)
  51. : display_(display),
  52. config_(config),
  53. is_current_in_some_thread_(false),
  54. is_destroyed_(false),
  55. gpu_driver_bug_workarounds_(
  56. platform_gpu_feature_info_.enabled_gpu_driver_bug_workarounds),
  57. discardable_manager_(gpu::GpuPreferences()),
  58. passthrough_discardable_manager_(gpu::GpuPreferences()),
  59. translator_cache_(gpu::GpuPreferences()) {}
  60. Context::~Context() {
  61. // We might not have a surface, so we must lose the context. Cleanup will
  62. // execute GL commands otherwise. TODO: if shared contexts are ever
  63. // implemented, this will leak the GL resources. For pbuffer contexts, one
  64. // could track the last current surface or create a surface for destroying
  65. // purposes only. Other option would be to make the service usable without
  66. // surface.
  67. if (HasService()) {
  68. if (!WasServiceContextLost())
  69. MarkServiceContextLost();
  70. DestroyService();
  71. }
  72. }
  73. void Context::MarkDestroyed() {
  74. is_destroyed_ = true;
  75. }
  76. bool Context::SwapBuffers(Surface* current_surface) {
  77. DCHECK(HasService() && is_current_in_some_thread_);
  78. if (WasServiceContextLost())
  79. return false;
  80. client_gl_context_->SwapBuffers(1);
  81. return true;
  82. }
  83. bool Context::MakeCurrent(Context* current_context,
  84. Surface* current_surface,
  85. Context* new_context,
  86. Surface* new_surface) {
  87. if (!new_context && !current_context) {
  88. return true;
  89. }
  90. bool cleanup_old_current_context = false;
  91. if (current_context) {
  92. if (current_context->Flush(current_surface->gl_surface()))
  93. cleanup_old_current_context = new_context != current_context;
  94. }
  95. if (new_context) {
  96. if (!new_context->IsCompatibleSurface(new_surface))
  97. return false;
  98. if (new_context->HasService()) {
  99. if (new_context->WasServiceContextLost())
  100. return false;
  101. if (new_context != current_context) {
  102. // If Flush did not set the current context, set it now. Otherwise
  103. // calling into the decoder is not ok.
  104. if (!new_context->gl_context_->MakeCurrent(new_surface->gl_surface())) {
  105. new_context->MarkServiceContextLost();
  106. return false;
  107. }
  108. }
  109. if (new_context != current_context || new_surface != current_surface)
  110. new_context->decoder_->SetSurface(new_surface->gl_surface());
  111. if (!new_context->decoder_->MakeCurrent()) {
  112. new_context->MarkServiceContextLost();
  113. return false;
  114. }
  115. } else {
  116. if (!new_context->CreateService(new_surface->gl_surface())) {
  117. return false;
  118. }
  119. }
  120. }
  121. // The current_surface will be released when MakeCurrent succeeds.
  122. // Cleanup in this case only.
  123. if (cleanup_old_current_context) {
  124. if (current_context->is_destroyed_ && current_surface != new_surface) {
  125. current_context->gl_context_->MakeCurrent(current_surface->gl_surface());
  126. // If we are releasing the context and we have one ref, it means that the
  127. // ref will be lost and the object will be destroyed. Destroy the service
  128. // explicitly here, so that cleanup can happen and client GL
  129. // implementation does not print errors.
  130. current_context->DestroyService();
  131. } else {
  132. current_context->decoder_->ReleaseSurface();
  133. }
  134. }
  135. return true;
  136. }
  137. bool Context::ValidateAttributeList(const EGLint* attrib_list) {
  138. if (attrib_list) {
  139. for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) {
  140. switch (attrib_list[i]) {
  141. case EGL_CONTEXT_CLIENT_VERSION:
  142. break;
  143. default:
  144. return false;
  145. }
  146. }
  147. }
  148. return true;
  149. }
  150. void Context::SetGpuControlClient(gpu::GpuControlClient*) {
  151. // The client is not currently called, so don't store it.
  152. }
  153. const gpu::Capabilities& Context::GetCapabilities() const {
  154. return capabilities_;
  155. }
  156. void Context::SignalQuery(uint32_t query, base::OnceClosure callback) {
  157. NOTREACHED();
  158. }
  159. void Context::CreateGpuFence(uint32_t gpu_fence_id, ClientGpuFence source) {
  160. NOTREACHED();
  161. }
  162. void Context::GetGpuFence(
  163. uint32_t gpu_fence_id,
  164. base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) {
  165. NOTREACHED();
  166. }
  167. void Context::SetLock(base::Lock*) {
  168. NOTREACHED();
  169. }
  170. void Context::EnsureWorkVisible() {
  171. NOTREACHED();
  172. }
  173. gpu::CommandBufferNamespace Context::GetNamespaceID() const {
  174. return gpu::CommandBufferNamespace::INVALID;
  175. }
  176. gpu::CommandBufferId Context::GetCommandBufferID() const {
  177. return gpu::CommandBufferId();
  178. }
  179. void Context::FlushPendingWork() {
  180. NOTREACHED();
  181. }
  182. uint64_t Context::GenerateFenceSyncRelease() {
  183. NOTREACHED();
  184. return 0;
  185. }
  186. bool Context::IsFenceSyncReleased(uint64_t release) {
  187. NOTREACHED();
  188. return false;
  189. }
  190. void Context::SignalSyncToken(const gpu::SyncToken& sync_token,
  191. base::OnceClosure callback) {
  192. NOTREACHED();
  193. }
  194. void Context::WaitSyncToken(const gpu::SyncToken& sync_token) {
  195. NOTREACHED();
  196. }
  197. bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken& sync_token) {
  198. return false;
  199. }
  200. void Context::ApplyCurrentContext(gl::GLSurface* current_surface) {
  201. DCHECK(HasService());
  202. // The current_surface will be the same as
  203. // the surface of the decoder. We can not DCHECK as there is
  204. // no accessor.
  205. if (!WasServiceContextLost()) {
  206. if (!gl_context_->MakeCurrent(current_surface))
  207. MarkServiceContextLost();
  208. }
  209. gles2::SetGLContext(client_gl_context_.get());
  210. }
  211. void Context::ApplyContextReleased() {
  212. gles2::SetGLContext(nullptr);
  213. }
  214. bool Context::CreateService(gl::GLSurface* gl_surface) {
  215. gpu::SharedMemoryLimits limits;
  216. gpu::GpuPreferences gpu_preferences;
  217. gpu::GpuFeatureInfo gpu_feature_info;
  218. scoped_refptr<gpu::gles2::FeatureInfo> feature_info(
  219. new gpu::gles2::FeatureInfo(gpu_driver_bug_workarounds_,
  220. gpu_feature_info));
  221. scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
  222. gpu_preferences, true, &mailbox_manager_, nullptr /* memory_tracker */,
  223. &translator_cache_, &completeness_cache_, feature_info, true,
  224. nullptr /* image_factory */, nullptr /* progress_reporter */,
  225. gpu_feature_info, &discardable_manager_,
  226. &passthrough_discardable_manager_, &shared_image_manager_));
  227. auto command_buffer = std::make_unique<gpu::CommandBufferDirect>();
  228. std::unique_ptr<gpu::gles2::GLES2Decoder> decoder(
  229. gpu::gles2::GLES2Decoder::Create(command_buffer.get(),
  230. command_buffer->service(), &outputter_,
  231. group.get()));
  232. command_buffer->set_handler(decoder.get());
  233. gl::GLContextAttribs context_attribs;
  234. context_attribs.gpu_preference = gl::GpuPreference::kHighPerformance;
  235. scoped_refptr<gl::GLContext> gl_context(
  236. gl::init::CreateGLContext(nullptr, gl_surface, context_attribs));
  237. if (!gl_context)
  238. return false;
  239. platform_gpu_feature_info_.ApplyToGLContext(gl_context.get());
  240. gl_context->MakeCurrent(gl_surface);
  241. gpu::ContextCreationAttribs helper;
  242. config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size);
  243. config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size);
  244. config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size);
  245. helper.buffer_preserved = false;
  246. helper.bind_generates_resource = kBindGeneratesResources;
  247. helper.fail_if_major_perf_caveat = false;
  248. helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory;
  249. helper.context_type = gpu::CONTEXT_TYPE_OPENGLES2;
  250. helper.offscreen_framebuffer_size = gl_surface->GetSize();
  251. auto result = decoder->Initialize(gl_surface, gl_context.get(),
  252. gl_surface->IsOffscreen(),
  253. gpu::gles2::DisallowedFeatures(), helper);
  254. if (result != gpu::ContextResult::kSuccess)
  255. return false;
  256. auto gles2_cmd_helper =
  257. std::make_unique<gpu::gles2::GLES2CmdHelper>(command_buffer.get());
  258. result = gles2_cmd_helper->Initialize(limits.command_buffer_size);
  259. if (result != gpu::ContextResult::kSuccess) {
  260. decoder->Destroy(true);
  261. return false;
  262. }
  263. // Client side Capabilities queries return reference, service side return
  264. // value. Here two sides are joined together.
  265. capabilities_ = decoder->GetCapabilities();
  266. auto transfer_buffer =
  267. std::make_unique<gpu::TransferBuffer>(gles2_cmd_helper.get());
  268. gles2_cmd_helper_ = std::move(gles2_cmd_helper);
  269. transfer_buffer_ = std::move(transfer_buffer);
  270. command_buffer_ = std::move(command_buffer);
  271. decoder_ = std::move(decoder);
  272. gl_context_ = gl_context.get();
  273. auto context = std::make_unique<gpu::gles2::GLES2Implementation>(
  274. gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(),
  275. kBindGeneratesResources, kLoseContextWhenOutOfMemory,
  276. kSupportClientSideArrays, this);
  277. result = context->Initialize(limits);
  278. if (result != gpu::ContextResult::kSuccess) {
  279. DestroyService();
  280. return false;
  281. }
  282. context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
  283. context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
  284. client_gl_context_ = std::move(context);
  285. return true;
  286. }
  287. void Context::DestroyService() {
  288. DCHECK(HasService());
  289. bool have_context = !WasServiceContextLost();
  290. // The client gl interface might still be set to current global
  291. // interface. This will be cleaned up in ApplyContextReleased
  292. // with AutoCurrentContextRestore.
  293. client_gl_context_.reset();
  294. gl_context_ = nullptr;
  295. transfer_buffer_.reset();
  296. gles2_cmd_helper_.reset();
  297. if (decoder_)
  298. decoder_->Destroy(have_context);
  299. decoder_.reset();
  300. command_buffer_.reset();
  301. }
  302. bool Context::HasService() const {
  303. return decoder_ != nullptr;
  304. }
  305. void Context::MarkServiceContextLost() {
  306. decoder_->GetContextGroup()->LoseContexts(gpu::error::kMakeCurrentFailed);
  307. }
  308. bool Context::WasServiceContextLost() const {
  309. return decoder_->WasContextLost();
  310. }
  311. bool Context::IsCompatibleSurface(Surface* surface) const {
  312. // Inspect current_surface->config() instead of gl_surface()->IsOffscreen()
  313. // because GTF windowless window surfaces might be emulated with offscreen
  314. // surfaces.
  315. EGLint value = EGL_NONE;
  316. config_->GetAttrib(EGL_SURFACE_TYPE, &value);
  317. bool context_config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0;
  318. surface->config()->GetAttrib(EGL_SURFACE_TYPE, &value);
  319. bool surface_config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0;
  320. return surface_config_is_offscreen == context_config_is_offscreen;
  321. }
  322. bool Context::Flush(gl::GLSurface* gl_surface) {
  323. if (WasServiceContextLost())
  324. return false;
  325. if (!gl_context_->MakeCurrent(gl_surface)) {
  326. MarkServiceContextLost();
  327. return false;
  328. }
  329. client_gl_context_->Flush();
  330. return true;
  331. }
  332. } // namespace egl
  333. } // namespace gles2_conform_support