Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 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 | |
| 5 | #include "gpu/command_buffer/client/gl_in_process_context.h" |
| 6 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 7 | #include <set> |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 8 | #include <utility> |
| 9 | #include <vector> |
| 10 | |
| 11 | #include <GLES2/gl2.h> |
| 12 | #ifndef GL_GLEXT_PROTOTYPES |
| 13 | #define GL_GLEXT_PROTOTYPES 1 |
| 14 | #endif |
| 15 | #include <GLES2/gl2ext.h> |
| 16 | #include <GLES2/gl2extchromium.h> |
| 17 | |
| 18 | #include "base/bind.h" |
| 19 | #include "base/bind_helpers.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 20 | #include "base/lazy_instance.h" |
| 21 | #include "base/logging.h" |
| 22 | #include "base/memory/scoped_ptr.h" |
| 23 | #include "base/memory/weak_ptr.h" |
Ben Murdoch | 9ab5563 | 2013-07-18 11:57:30 +0100 | [diff] [blame] | 24 | #include "base/message_loop/message_loop.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 25 | #include "gpu/command_buffer/client/gles2_implementation.h" |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 26 | #include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 27 | #include "gpu/command_buffer/client/image_factory.h" |
| 28 | #include "gpu/command_buffer/client/transfer_buffer.h" |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 29 | #include "gpu/command_buffer/common/command_buffer.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 30 | #include "gpu/command_buffer/common/constants.h" |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 31 | #include "gpu/command_buffer/service/in_process_command_buffer.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 32 | #include "ui/gfx/size.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 33 | #include "ui/gl/gl_image.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 34 | |
| 35 | namespace gpu { |
| 36 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 37 | namespace { |
| 38 | |
| 39 | const int32 kCommandBufferSize = 1024 * 1024; |
| 40 | // TODO(kbr): make the transfer buffer size configurable via context |
| 41 | // creation attributes. |
| 42 | const size_t kStartTransferBufferSize = 4 * 1024 * 1024; |
| 43 | const size_t kMinTransferBufferSize = 1 * 256 * 1024; |
| 44 | const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; |
| 45 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 46 | static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 47 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 48 | class GLInProcessContextImpl |
| 49 | : public GLInProcessContext, |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 50 | public gles2::ImageFactory, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 51 | public base::SupportsWeakPtr<GLInProcessContextImpl> { |
| 52 | public: |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 53 | explicit GLInProcessContextImpl(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 54 | virtual ~GLInProcessContextImpl(); |
| 55 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 56 | bool Initialize(scoped_refptr<gfx::GLSurface> surface, |
| 57 | bool is_offscreen, |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 58 | bool share_resources, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 59 | gfx::AcceleratedWidget window, |
| 60 | const gfx::Size& size, |
| 61 | const char* allowed_extensions, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 62 | const GLInProcessContextAttribs& attribs, |
| 63 | gfx::GpuPreference gpu_preference); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 64 | |
| 65 | // GLInProcessContext implementation: |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 66 | virtual void SetContextLostCallback(const base::Closure& callback) OVERRIDE; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 67 | virtual void SignalSyncPoint(unsigned sync_point, |
| 68 | const base::Closure& callback) OVERRIDE; |
| 69 | virtual void SignalQuery(unsigned query, const base::Closure& callback) |
| 70 | OVERRIDE; |
| 71 | virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE; |
| 72 | |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 73 | // ImageFactory implementation: |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 74 | virtual scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 75 | int width, int height, GLenum internalformat, |
| 76 | unsigned* image_id) OVERRIDE; |
| 77 | virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE; |
| 78 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 79 | private: |
| 80 | void Destroy(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 81 | void PollQueryCallbacks(); |
| 82 | void CallQueryCallback(size_t index); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 83 | void OnContextLost(); |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 84 | void OnSignalSyncPoint(const base::Closure& callback); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 85 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 86 | scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; |
| 87 | scoped_ptr<TransferBuffer> transfer_buffer_; |
| 88 | scoped_ptr<gles2::GLES2Implementation> gles2_implementation_; |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 89 | scoped_ptr<InProcessCommandBuffer> command_buffer_; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 90 | |
| 91 | typedef std::pair<unsigned, base::Closure> QueryCallback; |
| 92 | std::vector<QueryCallback> query_callbacks_; |
| 93 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 94 | unsigned int share_group_id_; |
| 95 | bool context_lost_; |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 96 | base::Closure context_lost_callback_; |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 97 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 98 | DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl); |
| 99 | }; |
| 100 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 101 | base::LazyInstance<base::Lock> g_all_shared_contexts_lock = |
| 102 | LAZY_INSTANCE_INITIALIZER; |
| 103 | base::LazyInstance<std::set<GLInProcessContextImpl*> > g_all_shared_contexts = |
| 104 | LAZY_INSTANCE_INITIALIZER; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 105 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 106 | size_t SharedContextCount() { |
| 107 | base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| 108 | return g_all_shared_contexts.Get().size(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 109 | } |
| 110 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 111 | scoped_ptr<gfx::GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer( |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 112 | int width, int height, GLenum internalformat, unsigned int* image_id) { |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 113 | scoped_ptr<gfx::GpuMemoryBuffer> buffer( |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 114 | g_gpu_memory_buffer_factory->CreateGpuMemoryBuffer(width, |
| 115 | height, |
| 116 | internalformat)); |
| 117 | if (!buffer) |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 118 | return scoped_ptr<gfx::GpuMemoryBuffer>(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 119 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 120 | *image_id = command_buffer_->CreateImageForGpuMemoryBuffer( |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 121 | buffer->GetHandle(), gfx::Size(width, height)); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 122 | return buffer.Pass(); |
| 123 | } |
| 124 | |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 125 | void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) { |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 126 | command_buffer_->RemoveImage(image_id); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 127 | } |
| 128 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 129 | GLInProcessContextImpl::GLInProcessContextImpl() |
| 130 | : share_group_id_(0), context_lost_(false) {} |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 131 | |
| 132 | GLInProcessContextImpl::~GLInProcessContextImpl() { |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 133 | { |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 134 | base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| 135 | g_all_shared_contexts.Get().erase(this); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 136 | } |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 137 | Destroy(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point, |
| 141 | const base::Closure& callback) { |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 142 | DCHECK(!callback.is_null()); |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 143 | base::Closure wrapped_callback = base::Bind( |
| 144 | &GLInProcessContextImpl::OnSignalSyncPoint, AsWeakPtr(), callback); |
| 145 | command_buffer_->SignalSyncPoint(sync_point, wrapped_callback); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 146 | } |
| 147 | |
| 148 | gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { |
| 149 | return gles2_implementation_.get(); |
| 150 | } |
| 151 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 152 | void GLInProcessContextImpl::SetContextLostCallback( |
| 153 | const base::Closure& callback) { |
| 154 | context_lost_callback_ = callback; |
| 155 | } |
| 156 | |
| 157 | void GLInProcessContextImpl::OnContextLost() { |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 158 | context_lost_ = true; |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 159 | if (!context_lost_callback_.is_null()) { |
| 160 | context_lost_callback_.Run(); |
| 161 | } |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | void GLInProcessContextImpl::OnSignalSyncPoint(const base::Closure& callback) { |
| 165 | // TODO: Should it always trigger callbacks? |
| 166 | if (!context_lost_) |
| 167 | callback.Run(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | bool GLInProcessContextImpl::Initialize( |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 171 | scoped_refptr<gfx::GLSurface> surface, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 172 | bool is_offscreen, |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 173 | bool share_resources, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 174 | gfx::AcceleratedWidget window, |
| 175 | const gfx::Size& size, |
| 176 | const char* allowed_extensions, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 177 | const GLInProcessContextAttribs& attribs, |
| 178 | gfx::GpuPreference gpu_preference) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 179 | DCHECK(size.width() >= 0 && size.height() >= 0); |
| 180 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 181 | const int32 ALPHA_SIZE = 0x3021; |
| 182 | const int32 BLUE_SIZE = 0x3022; |
| 183 | const int32 GREEN_SIZE = 0x3023; |
| 184 | const int32 RED_SIZE = 0x3024; |
| 185 | const int32 DEPTH_SIZE = 0x3025; |
| 186 | const int32 STENCIL_SIZE = 0x3026; |
| 187 | const int32 SAMPLES = 0x3031; |
| 188 | const int32 SAMPLE_BUFFERS = 0x3032; |
| 189 | const int32 NONE = 0x3038; |
| 190 | |
| 191 | std::vector<int32> attrib_vector; |
| 192 | if (attribs.alpha_size >= 0) { |
| 193 | attrib_vector.push_back(ALPHA_SIZE); |
| 194 | attrib_vector.push_back(attribs.alpha_size); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 195 | } |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 196 | if (attribs.blue_size >= 0) { |
| 197 | attrib_vector.push_back(BLUE_SIZE); |
| 198 | attrib_vector.push_back(attribs.blue_size); |
| 199 | } |
| 200 | if (attribs.green_size >= 0) { |
| 201 | attrib_vector.push_back(GREEN_SIZE); |
| 202 | attrib_vector.push_back(attribs.green_size); |
| 203 | } |
| 204 | if (attribs.red_size >= 0) { |
| 205 | attrib_vector.push_back(RED_SIZE); |
| 206 | attrib_vector.push_back(attribs.red_size); |
| 207 | } |
| 208 | if (attribs.depth_size >= 0) { |
| 209 | attrib_vector.push_back(DEPTH_SIZE); |
| 210 | attrib_vector.push_back(attribs.depth_size); |
| 211 | } |
| 212 | if (attribs.stencil_size >= 0) { |
| 213 | attrib_vector.push_back(STENCIL_SIZE); |
| 214 | attrib_vector.push_back(attribs.stencil_size); |
| 215 | } |
| 216 | if (attribs.samples >= 0) { |
| 217 | attrib_vector.push_back(SAMPLES); |
| 218 | attrib_vector.push_back(attribs.samples); |
| 219 | } |
| 220 | if (attribs.sample_buffers >= 0) { |
| 221 | attrib_vector.push_back(SAMPLE_BUFFERS); |
| 222 | attrib_vector.push_back(attribs.sample_buffers); |
| 223 | } |
| 224 | attrib_vector.push_back(NONE); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 225 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 226 | base::Closure wrapped_callback = |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 227 | base::Bind(&GLInProcessContextImpl::OnContextLost, AsWeakPtr()); |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 228 | command_buffer_.reset(new InProcessCommandBuffer()); |
| 229 | |
| 230 | scoped_ptr<base::AutoLock> scoped_shared_context_lock; |
| 231 | scoped_refptr<gles2::ShareGroup> share_group; |
| 232 | if (share_resources) { |
| 233 | scoped_shared_context_lock.reset( |
| 234 | new base::AutoLock(g_all_shared_contexts_lock.Get())); |
| 235 | for (std::set<GLInProcessContextImpl*>::const_iterator it = |
| 236 | g_all_shared_contexts.Get().begin(); |
| 237 | it != g_all_shared_contexts.Get().end(); |
| 238 | it++) { |
| 239 | const GLInProcessContextImpl* context = *it; |
| 240 | if (!context->context_lost_) { |
| 241 | share_group = context->gles2_implementation_->share_group(); |
| 242 | DCHECK(share_group); |
| 243 | share_group_id_ = context->share_group_id_; |
| 244 | break; |
| 245 | } |
| 246 | share_group_id_ = std::max(share_group_id_, context->share_group_id_); |
| 247 | } |
| 248 | if (!share_group && !++share_group_id_) |
| 249 | ++share_group_id_; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 250 | } |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 251 | if (!command_buffer_->Initialize(surface, |
| 252 | is_offscreen, |
| 253 | share_resources, |
| 254 | window, |
| 255 | size, |
| 256 | allowed_extensions, |
| 257 | attrib_vector, |
| 258 | gpu_preference, |
| 259 | wrapped_callback, |
| 260 | share_group_id_)) { |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 261 | LOG(INFO) << "Failed to initialize InProcessCommmandBuffer"; |
| 262 | return false; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 263 | } |
| 264 | |
| 265 | // Create the GLES2 helper, which writes the command buffer protocol. |
| 266 | gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); |
| 267 | if (!gles2_helper_->Initialize(kCommandBufferSize)) { |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 268 | LOG(INFO) << "Failed to initialize GLES2CmdHelper"; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 269 | Destroy(); |
| 270 | return false; |
| 271 | } |
| 272 | |
| 273 | // Create a transfer buffer. |
| 274 | transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); |
| 275 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 276 | // Create the object exposing the OpenGL API. |
| 277 | gles2_implementation_.reset(new gles2::GLES2Implementation( |
| 278 | gles2_helper_.get(), |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 279 | share_group, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 280 | transfer_buffer_.get(), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 281 | false, |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 282 | this)); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 283 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 284 | if (share_resources) { |
| 285 | g_all_shared_contexts.Get().insert(this); |
| 286 | scoped_shared_context_lock.reset(); |
| 287 | } |
| 288 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 289 | if (!gles2_implementation_->Initialize( |
| 290 | kStartTransferBufferSize, |
| 291 | kMinTransferBufferSize, |
| 292 | kMaxTransferBufferSize)) { |
| 293 | return false; |
| 294 | } |
| 295 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 296 | return true; |
| 297 | } |
| 298 | |
| 299 | void GLInProcessContextImpl::Destroy() { |
| 300 | while (!query_callbacks_.empty()) { |
| 301 | CallQueryCallback(0); |
| 302 | } |
| 303 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 304 | if (gles2_implementation_) { |
| 305 | // First flush the context to ensure that any pending frees of resources |
| 306 | // are completed. Otherwise, if this context is part of a share group, |
| 307 | // those resources might leak. Also, any remaining side effects of commands |
| 308 | // issued on this context might not be visible to other contexts in the |
| 309 | // share group. |
| 310 | gles2_implementation_->Flush(); |
| 311 | |
| 312 | gles2_implementation_.reset(); |
| 313 | } |
| 314 | |
| 315 | transfer_buffer_.reset(); |
| 316 | gles2_helper_.reset(); |
| 317 | command_buffer_.reset(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 318 | } |
| 319 | |
| 320 | void GLInProcessContextImpl::CallQueryCallback(size_t index) { |
| 321 | DCHECK_LT(index, query_callbacks_.size()); |
| 322 | QueryCallback query_callback = query_callbacks_[index]; |
| 323 | query_callbacks_[index] = query_callbacks_.back(); |
| 324 | query_callbacks_.pop_back(); |
| 325 | query_callback.second.Run(); |
| 326 | } |
| 327 | |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 328 | // TODO(sievers): Move this to the service side |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 329 | void GLInProcessContextImpl::PollQueryCallbacks() { |
| 330 | for (size_t i = 0; i < query_callbacks_.size();) { |
| 331 | unsigned query = query_callbacks_[i].first; |
| 332 | GLuint param = 0; |
| 333 | gles2::GLES2Implementation* gl = GetImplementation(); |
| 334 | if (gl->IsQueryEXT(query)) { |
| 335 | gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, ¶m); |
| 336 | } else { |
| 337 | param = 1; |
| 338 | } |
| 339 | if (param) { |
| 340 | CallQueryCallback(i); |
| 341 | } else { |
| 342 | i++; |
| 343 | } |
| 344 | } |
| 345 | if (!query_callbacks_.empty()) { |
| 346 | base::MessageLoop::current()->PostDelayedTask( |
| 347 | FROM_HERE, |
| 348 | base::Bind(&GLInProcessContextImpl::PollQueryCallbacks, |
| 349 | this->AsWeakPtr()), |
| 350 | base::TimeDelta::FromMilliseconds(5)); |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | void GLInProcessContextImpl::SignalQuery( |
| 355 | unsigned query, |
| 356 | const base::Closure& callback) { |
| 357 | query_callbacks_.push_back(std::make_pair(query, callback)); |
| 358 | // If size > 1, there is already a poll callback pending. |
| 359 | if (query_callbacks_.size() == 1) { |
| 360 | PollQueryCallbacks(); |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | } // anonymous namespace |
| 365 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 366 | GLInProcessContextAttribs::GLInProcessContextAttribs() |
| 367 | : alpha_size(-1), |
| 368 | blue_size(-1), |
| 369 | green_size(-1), |
| 370 | red_size(-1), |
| 371 | depth_size(-1), |
| 372 | stencil_size(-1), |
| 373 | samples(-1), |
| 374 | sample_buffers(-1) {} |
| 375 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 376 | // static |
| 377 | GLInProcessContext* GLInProcessContext::CreateContext( |
| 378 | bool is_offscreen, |
| 379 | gfx::AcceleratedWidget window, |
| 380 | const gfx::Size& size, |
| 381 | bool share_resources, |
| 382 | const char* allowed_extensions, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 383 | const GLInProcessContextAttribs& attribs, |
| 384 | gfx::GpuPreference gpu_preference) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 385 | scoped_ptr<GLInProcessContextImpl> context( |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 386 | new GLInProcessContextImpl()); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 387 | if (!context->Initialize( |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 388 | NULL /* surface */, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 389 | is_offscreen, |
Ben Murdoch | 28390f6 | 2013-08-01 12:44:22 +0100 | [diff] [blame] | 390 | share_resources, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 391 | window, |
| 392 | size, |
| 393 | allowed_extensions, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 394 | attribs, |
| 395 | gpu_preference)) |
| 396 | return NULL; |
| 397 | |
| 398 | return context.release(); |
| 399 | } |
| 400 | |
| 401 | // static |
| 402 | GLInProcessContext* GLInProcessContext::CreateWithSurface( |
| 403 | scoped_refptr<gfx::GLSurface> surface, |
| 404 | bool share_resources, |
| 405 | const char* allowed_extensions, |
| 406 | const GLInProcessContextAttribs& attribs, |
| 407 | gfx::GpuPreference gpu_preference) { |
| 408 | scoped_ptr<GLInProcessContextImpl> context( |
| 409 | new GLInProcessContextImpl()); |
| 410 | if (!context->Initialize( |
| 411 | surface, |
| 412 | surface->IsOffscreen(), |
| 413 | share_resources, |
| 414 | gfx::kNullAcceleratedWidget, |
| 415 | surface->GetSize(), |
| 416 | allowed_extensions, |
| 417 | attribs, |
| 418 | gpu_preference)) |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 419 | return NULL; |
| 420 | |
| 421 | return context.release(); |
| 422 | } |
| 423 | |
| 424 | // static |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 425 | void GLInProcessContext::SetGpuMemoryBufferFactory( |
| 426 | GpuMemoryBufferFactory* factory) { |
| 427 | DCHECK_EQ(0u, SharedContextCount()); |
| 428 | g_gpu_memory_buffer_factory = factory; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 429 | } |
| 430 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 431 | } // namespace gpu |