| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" | 5 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" |
| 6 | 6 |
| 7 #include "third_party/khronos/GLES2/gl2.h" | 7 #include "third_party/khronos/GLES2/gl2.h" |
| 8 #ifndef GL_GLEXT_PROTOTYPES | 8 #ifndef GL_GLEXT_PROTOTYPES |
| 9 #define GL_GLEXT_PROTOTYPES 1 | 9 #define GL_GLEXT_PROTOTYPES 1 |
| 10 #endif | 10 #endif |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 | 39 |
| 40 namespace content { | 40 namespace content { |
| 41 | 41 |
| 42 WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( | 42 WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( |
| 43 gpu::SurfaceHandle surface_handle, | 43 gpu::SurfaceHandle surface_handle, |
| 44 const GURL& active_url, | 44 const GURL& active_url, |
| 45 scoped_refptr<gpu::GpuChannelHost> host, | 45 scoped_refptr<gpu::GpuChannelHost> host, |
| 46 gfx::GpuPreference gpu_preference, | 46 gfx::GpuPreference gpu_preference, |
| 47 bool automatic_flushes) | 47 bool automatic_flushes) |
| 48 : automatic_flushes_(automatic_flushes), | 48 : automatic_flushes_(automatic_flushes), |
| 49 host_(std::move(host)), | |
| 50 surface_handle_(surface_handle), | 49 surface_handle_(surface_handle), |
| 51 active_url_(active_url), | 50 active_url_(active_url), |
| 52 gpu_preference_(gpu_preference), | 51 gpu_preference_(gpu_preference), |
| 53 weak_ptr_factory_(this) { | 52 host_(std::move(host)) { |
| 54 DCHECK(host_); | 53 DCHECK(host_); |
| 55 } | 54 } |
| 56 | 55 |
| 57 WebGraphicsContext3DCommandBufferImpl:: | 56 WebGraphicsContext3DCommandBufferImpl:: |
| 58 ~WebGraphicsContext3DCommandBufferImpl() { | 57 ~WebGraphicsContext3DCommandBufferImpl() { |
| 59 if (real_gl_) | 58 if (real_gl_) |
| 60 real_gl_->SetLostContextCallback(base::Closure()); | 59 real_gl_->SetLostContextCallback(base::Closure()); |
| 61 | |
| 62 Destroy(); | |
| 63 } | 60 } |
| 64 | 61 |
| 65 bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL( | 62 bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL( |
| 66 const gpu::SharedMemoryLimits& memory_limits, | 63 const gpu::SharedMemoryLimits& memory_limits, |
| 67 gpu::CommandBufferProxyImpl* shared_command_buffer, | 64 gpu::CommandBufferProxyImpl* shared_command_buffer, |
| 68 scoped_refptr<gpu::gles2::ShareGroup> share_group, | 65 scoped_refptr<gpu::gles2::ShareGroup> share_group, |
| 69 const gpu::gles2::ContextCreationAttribHelper& attributes, | 66 const gpu::gles2::ContextCreationAttribHelper& attributes, |
| 70 command_buffer_metrics::ContextType context_type) { | 67 command_buffer_metrics::ContextType context_type) { |
| 71 if (initialized_) | 68 DCHECK_EQ(!!shared_command_buffer, !!share_group); |
| 72 return true; | |
| 73 | |
| 74 if (initialize_failed_) | |
| 75 return false; | |
| 76 | |
| 77 TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::MaybeInitializeGL"); | 69 TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::MaybeInitializeGL"); |
| 78 | 70 |
| 79 // TODO(vadimt): Remove ScopedTracker below once crbug.com/125248 is fixed. | |
| 80 tracked_objects::ScopedTracker tracking_profile( | |
| 81 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 82 "125248 WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL")); | |
| 83 | |
| 84 if (!CreateContext(memory_limits, shared_command_buffer, | |
| 85 std::move(share_group), attributes, context_type)) { | |
| 86 Destroy(); | |
| 87 | |
| 88 initialize_failed_ = true; | |
| 89 return false; | |
| 90 } | |
| 91 | |
| 92 real_gl_->SetLostContextCallback( | |
| 93 base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnContextLost, | |
| 94 // The callback is unset in the destructor. | |
| 95 base::Unretained(this))); | |
| 96 | |
| 97 real_gl_->TraceBeginCHROMIUM("WebGraphicsContext3D", | |
| 98 "CommandBufferContext"); | |
| 99 | |
| 100 initialized_ = true; | |
| 101 return true; | |
| 102 } | |
| 103 | |
| 104 bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( | |
| 105 gpu::CommandBufferProxyImpl* shared_command_buffer, | |
| 106 const gpu::gles2::ContextCreationAttribHelper& attributes, | |
| 107 command_buffer_metrics::ContextType context_type) { | |
| 108 if (!host_.get()) | |
| 109 return false; | |
| 110 | |
| 111 DCHECK(attributes.buffer_preserved); | 71 DCHECK(attributes.buffer_preserved); |
| 112 std::vector<int32_t> serialized_attributes; | 72 std::vector<int32_t> serialized_attributes; |
| 113 attributes.Serialize(&serialized_attributes); | 73 attributes.Serialize(&serialized_attributes); |
| 114 | 74 |
| 115 // Create a proxy to a command buffer in the GPU process. | 75 // Create a proxy to a command buffer in the GPU process. |
| 116 command_buffer_ = host_->CreateCommandBuffer( | 76 command_buffer_ = host_->CreateCommandBuffer( |
| 117 surface_handle_, gfx::Size(), shared_command_buffer, | 77 surface_handle_, gfx::Size(), shared_command_buffer, |
| 118 gpu::GpuChannelHost::kDefaultStreamId, | 78 gpu::GpuChannelHost::kDefaultStreamId, |
| 119 gpu::GpuChannelHost::kDefaultStreamPriority, serialized_attributes, | 79 gpu::GpuChannelHost::kDefaultStreamPriority, serialized_attributes, |
| 120 active_url_, gpu_preference_); | 80 active_url_, gpu_preference_); |
| 121 | 81 |
| 122 if (!command_buffer_) { | 82 if (!command_buffer_) { |
| 123 DLOG(ERROR) << "GpuChannelHost failed to create command buffer."; | 83 DLOG(ERROR) << "GpuChannelHost failed to create command buffer."; |
| 124 command_buffer_metrics::UmaRecordContextInitFailed(context_type); | 84 command_buffer_metrics::UmaRecordContextInitFailed(context_type); |
| 125 return false; | 85 return false; |
| 126 } | 86 } |
| 127 | 87 |
| 128 DVLOG_IF(1, gpu::error::IsError(command_buffer_->GetLastError())) | 88 // The GLES2 helper writes the command buffer protocol. |
| 129 << "Context dead on arrival. Last error: " | 89 gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); |
| 130 << command_buffer_->GetLastError(); | 90 gles2_helper_->SetAutomaticFlushes(automatic_flushes_); |
| 131 return true; | 91 if (!gles2_helper_->Initialize(memory_limits.command_buffer_size)) { |
| 132 } | 92 DLOG(ERROR) << "Failed to initialize GLES2CmdHelper."; |
| 133 | |
| 134 bool WebGraphicsContext3DCommandBufferImpl::CreateContext( | |
| 135 const gpu::SharedMemoryLimits& memory_limits, | |
| 136 gpu::CommandBufferProxyImpl* shared_command_buffer, | |
| 137 scoped_refptr<gpu::gles2::ShareGroup> share_group, | |
| 138 const gpu::gles2::ContextCreationAttribHelper& attributes, | |
| 139 command_buffer_metrics::ContextType context_type) { | |
| 140 TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::CreateContext"); | |
| 141 DCHECK_EQ(!!shared_command_buffer, !!share_group); | |
| 142 | |
| 143 if (!InitializeCommandBuffer(shared_command_buffer, attributes, | |
| 144 context_type)) { | |
| 145 LOG(ERROR) << "Failed to initialize command buffer."; | |
| 146 return false; | 93 return false; |
| 147 } | 94 } |
| 148 | 95 |
| 149 // Create the GLES2 helper, which writes the command buffer protocol. | 96 // The transfer buffer is used to copy resources between the client |
| 150 gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); | |
| 151 if (!gles2_helper_->Initialize(memory_limits.command_buffer_size)) { | |
| 152 LOG(ERROR) << "Failed to initialize GLES2CmdHelper."; | |
| 153 return false; | |
| 154 } | |
| 155 | |
| 156 if (!automatic_flushes_) | |
| 157 gles2_helper_->SetAutomaticFlushes(false); | |
| 158 // Create a transfer buffer used to copy resources between the renderer | |
| 159 // process and the GPU process. | 97 // process and the GPU process. |
| 160 transfer_buffer_ .reset(new gpu::TransferBuffer(gles2_helper_.get())); | 98 transfer_buffer_ .reset(new gpu::TransferBuffer(gles2_helper_.get())); |
| 161 | 99 |
| 162 DCHECK(host_.get()); | |
| 163 | |
| 164 const bool bind_generates_resource = attributes.bind_generates_resource; | 100 const bool bind_generates_resource = attributes.bind_generates_resource; |
| 165 const bool lose_context_when_out_of_memory = | 101 const bool lose_context_when_out_of_memory = |
| 166 attributes.lose_context_when_out_of_memory; | 102 attributes.lose_context_when_out_of_memory; |
| 167 const bool support_client_side_arrays = false; | 103 const bool support_client_side_arrays = false; |
| 168 | 104 |
| 169 // Create the object exposing the OpenGL API. | 105 // The GLES2Implementation exposes the OpenGLES2 API, as well as the |
| 106 // gpu::ContextSupport interface. |
| 170 real_gl_.reset(new gpu::gles2::GLES2Implementation( | 107 real_gl_.reset(new gpu::gles2::GLES2Implementation( |
| 171 gles2_helper_.get(), std::move(share_group), transfer_buffer_.get(), | 108 gles2_helper_.get(), std::move(share_group), transfer_buffer_.get(), |
| 172 bind_generates_resource, lose_context_when_out_of_memory, | 109 bind_generates_resource, lose_context_when_out_of_memory, |
| 173 support_client_side_arrays, command_buffer_.get())); | 110 support_client_side_arrays, command_buffer_.get())); |
| 174 if (!real_gl_->Initialize(memory_limits.start_transfer_buffer_size, | 111 if (!real_gl_->Initialize(memory_limits.start_transfer_buffer_size, |
| 175 memory_limits.min_transfer_buffer_size, | 112 memory_limits.min_transfer_buffer_size, |
| 176 memory_limits.max_transfer_buffer_size, | 113 memory_limits.max_transfer_buffer_size, |
| 177 memory_limits.mapped_memory_reclaim_limit)) { | 114 memory_limits.mapped_memory_reclaim_limit)) { |
| 178 LOG(ERROR) << "Failed to initialize GLES2Implementation."; | 115 DLOG(ERROR) << "Failed to initialize GLES2Implementation."; |
| 179 return false; | 116 return false; |
| 180 } | 117 } |
| 181 | 118 |
| 119 real_gl_->SetLostContextCallback( |
| 120 base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnContextLost, |
| 121 // The callback is unset in the destructor. |
| 122 base::Unretained(this))); |
| 123 real_gl_->TraceBeginCHROMIUM("WebGraphicsContext3D", "CommandBufferContext"); |
| 182 return true; | 124 return true; |
| 183 } | 125 } |
| 184 | 126 |
| 185 bool WebGraphicsContext3DCommandBufferImpl::InitializeOnCurrentThread( | 127 bool WebGraphicsContext3DCommandBufferImpl::InitializeOnCurrentThread( |
| 186 const gpu::SharedMemoryLimits& memory_limits, | 128 const gpu::SharedMemoryLimits& memory_limits, |
| 187 gpu::CommandBufferProxyImpl* shared_command_buffer, | 129 gpu::CommandBufferProxyImpl* shared_command_buffer, |
| 188 scoped_refptr<gpu::gles2::ShareGroup> share_group, | 130 scoped_refptr<gpu::gles2::ShareGroup> share_group, |
| 189 const gpu::gles2::ContextCreationAttribHelper& attributes, | 131 const gpu::gles2::ContextCreationAttribHelper& attributes, |
| 190 command_buffer_metrics::ContextType context_type) { | 132 command_buffer_metrics::ContextType context_type) { |
| 191 if (!MaybeInitializeGL(memory_limits, shared_command_buffer, | 133 if (!MaybeInitializeGL(memory_limits, shared_command_buffer, |
| 192 std::move(share_group), attributes, context_type)) { | 134 std::move(share_group), attributes, context_type)) |
| 193 DLOG(ERROR) << "Failed to initialize context."; | |
| 194 return false; | 135 return false; |
| 195 } | |
| 196 if (gpu::error::IsError(command_buffer_->GetLastError())) { | 136 if (gpu::error::IsError(command_buffer_->GetLastError())) { |
| 197 LOG(ERROR) << "Context dead on arrival. Last error: " | 137 DLOG(ERROR) << "Context dead on arrival. Last error: " |
| 198 << command_buffer_->GetLastError(); | 138 << command_buffer_->GetLastError(); |
| 199 return false; | 139 return false; |
| 200 } | 140 } |
| 201 | 141 |
| 202 return true; | 142 return true; |
| 203 } | 143 } |
| 204 | 144 |
| 205 void WebGraphicsContext3DCommandBufferImpl::Destroy() { | |
| 206 trace_gl_.reset(); | |
| 207 real_gl_.reset(); | |
| 208 transfer_buffer_.reset(); | |
| 209 gles2_helper_.reset(); | |
| 210 real_gl_.reset(); | |
| 211 command_buffer_.reset(); | |
| 212 | |
| 213 host_ = nullptr; | |
| 214 } | |
| 215 | |
| 216 gpu::ContextSupport* | |
| 217 WebGraphicsContext3DCommandBufferImpl::GetContextSupport() { | |
| 218 return real_gl_.get(); | |
| 219 } | |
| 220 | |
| 221 void WebGraphicsContext3DCommandBufferImpl::OnContextLost() { | 145 void WebGraphicsContext3DCommandBufferImpl::OnContextLost() { |
| 222 if (context_lost_callback_) | 146 if (context_lost_callback_) |
| 223 context_lost_callback_->onContextLost(); | 147 context_lost_callback_->onContextLost(); |
| 224 } | 148 } |
| 225 | 149 |
| 226 } // namespace content | 150 } // namespace content |
| OLD | NEW |