Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: content/renderer/gpu/renderer_gl_context.cc

Issue 9340012: Move gpu client files to content_common, in content/common/gpu/client (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove unneeded enums Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "content/renderer/gpu/renderer_gl_context.h"
6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/lazy_instance.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/singleton.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/shared_memory.h"
15 #include "content/common/view_messages.h"
16 #include "content/renderer/gpu/command_buffer_proxy.h"
17 #include "content/renderer/gpu/gpu_channel_host.h"
18 #include "content/renderer/render_widget.h"
19 #include "googleurl/src/gurl.h"
20 #include "ipc/ipc_channel_handle.h"
21
22 #if defined(ENABLE_GPU)
23 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
24 #include "gpu/command_buffer/client/gles2_implementation.h"
25 #include "gpu/command_buffer/client/gles2_lib.h"
26 #include "gpu/command_buffer/client/transfer_buffer.h"
27 #include "gpu/command_buffer/common/constants.h"
28 #endif // ENABLE_GPU
29
30 namespace {
31
32 const int32 kCommandBufferSize = 1024 * 1024;
33 // TODO(kbr): make the transfer buffer size configurable via context
34 // creation attributes.
35 const size_t kStartTransferBufferSize = 1 * 1024 * 1024;
36 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
37 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
38
39 // Singleton used to initialize and terminate the gles2 library.
40 class GLES2Initializer {
41 public:
42 GLES2Initializer() {
43 gles2::Initialize();
44 }
45
46 ~GLES2Initializer() {
47 gles2::Terminate();
48 }
49
50 private:
51 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
52 };
53
54 ////////////////////////////////////////////////////////////////////////////////
55
56 base::LazyInstance<GLES2Initializer> g_gles2_initializer =
57 LAZY_INSTANCE_INITIALIZER;
58
59 ////////////////////////////////////////////////////////////////////////////////
60
61 #if defined(ENABLE_GPU)
62 RendererGLContext::ContextLostReason ConvertReason(
63 gpu::error::ContextLostReason reason) {
64 switch (reason) {
65 case gpu::error::kGuilty:
66 return RendererGLContext::kGuilty;
67 case gpu::error::kInnocent:
68 return RendererGLContext::kInnocent;
69 case gpu::error::kUnknown:
70 return RendererGLContext::kUnknown;
71 }
72 NOTREACHED();
73 return RendererGLContext::kUnknown;
74 }
75 #endif
76
77 } // namespace
78
79 RendererGLContext::~RendererGLContext() {
80 Destroy();
81 }
82
83 RendererGLContext* RendererGLContext::CreateViewContext(
84 GpuChannelHost* channel,
85 int32 surface_id,
86 RendererGLContext* share_group,
87 const char* allowed_extensions,
88 const int32* attrib_list,
89 const GURL& active_url,
90 gfx::GpuPreference gpu_preference) {
91 #if defined(ENABLE_GPU)
92 scoped_ptr<RendererGLContext> context(new RendererGLContext(channel));
93 if (!context->Initialize(
94 true,
95 surface_id,
96 gfx::Size(),
97 share_group,
98 allowed_extensions,
99 attrib_list,
100 active_url,
101 gpu_preference))
102 return NULL;
103
104 return context.release();
105 #else
106 return NULL;
107 #endif
108 }
109
110 RendererGLContext* RendererGLContext::CreateOffscreenContext(
111 GpuChannelHost* channel,
112 const gfx::Size& size,
113 RendererGLContext* share_group,
114 const char* allowed_extensions,
115 const int32* attrib_list,
116 const GURL& active_url,
117 gfx::GpuPreference gpu_preference) {
118 #if defined(ENABLE_GPU)
119 scoped_ptr<RendererGLContext> context(new RendererGLContext(channel));
120 if (!context->Initialize(
121 false,
122 0,
123 size,
124 share_group,
125 allowed_extensions,
126 attrib_list,
127 active_url,
128 gpu_preference))
129 return NULL;
130
131 return context.release();
132 #else
133 return NULL;
134 #endif
135 }
136
137 bool RendererGLContext::SetParent(RendererGLContext* new_parent) {
138 if (parent_.get() == new_parent)
139 return true;
140
141 // Allocate a texture ID with respect to the parent and change the parent.
142 uint32 new_parent_texture_id = 0;
143 if (command_buffer_) {
144 if (new_parent) {
145 TRACE_EVENT0("gpu", "RendererGLContext::SetParent::flushParent");
146 // Flush any remaining commands in the parent context to make sure the
147 // texture id accounting stays consistent.
148 int32 token = new_parent->gles2_helper_->InsertToken();
149 new_parent->gles2_helper_->WaitForToken(token);
150 new_parent_texture_id =
151 new_parent->gles2_implementation_->MakeTextureId();
152
153 if (!command_buffer_->SetParent(new_parent->command_buffer_,
154 new_parent_texture_id)) {
155 new_parent->gles2_implementation_->FreeTextureId(parent_texture_id_);
156 return false;
157 }
158 } else {
159 if (!command_buffer_->SetParent(NULL, 0))
160 return false;
161 }
162 }
163
164 // Free the previous parent's texture ID.
165 if (parent_.get() && parent_texture_id_ != 0) {
166 // Flush any remaining commands in the parent context to make sure the
167 // texture id accounting stays consistent.
168 gpu::gles2::GLES2Implementation* parent_gles2 =
169 parent_->GetImplementation();
170 parent_gles2->helper()->CommandBufferHelper::Finish();
171 parent_gles2->FreeTextureId(parent_texture_id_);
172 }
173
174 if (new_parent) {
175 parent_ = new_parent->AsWeakPtr();
176 parent_texture_id_ = new_parent_texture_id;
177 } else {
178 parent_.reset();
179 parent_texture_id_ = 0;
180 }
181
182 return true;
183 }
184
185 uint32 RendererGLContext::GetParentTextureId() {
186 return parent_texture_id_;
187 }
188
189 uint32 RendererGLContext::CreateParentTexture(const gfx::Size& size) {
190 uint32 texture_id = 0;
191 gles2_implementation_->GenTextures(1, &texture_id);
192 gles2_implementation_->Flush();
193 return texture_id;
194 }
195
196 void RendererGLContext::DeleteParentTexture(uint32 texture) {
197 gles2_implementation_->DeleteTextures(1, &texture);
198 }
199
200 void RendererGLContext::SetContextLostCallback(
201 const base::Callback<void (ContextLostReason)>& callback) {
202 context_lost_callback_ = callback;
203 }
204
205 bool RendererGLContext::MakeCurrent(RendererGLContext* context) {
206 if (context) {
207 DCHECK(context->CalledOnValidThread());
208 gles2::SetGLContext(context->gles2_implementation_);
209
210 // Don't request latest error status from service. Just use the locally
211 // cached information from the last flush.
212 // TODO(apatrick): I'm not sure if this should actually change the
213 // current context if it fails. For now it gets changed even if it fails
214 // because making GL calls with a NULL context crashes.
215 if (context->command_buffer_->GetLastState().error != gpu::error::kNoError)
216 return false;
217 } else {
218 gles2::SetGLContext(NULL);
219 }
220
221 return true;
222 }
223
224 bool RendererGLContext::SwapBuffers() {
225 TRACE_EVENT1("gpu", "RendererGLContext::SwapBuffers", "frame", frame_number_);
226 frame_number_++;
227
228 // Don't request latest error status from service. Just use the locally cached
229 // information from the last flush.
230 if (command_buffer_->GetLastState().error != gpu::error::kNoError)
231 return false;
232
233 gles2_implementation_->SwapBuffers();
234
235 return true;
236 }
237
238 bool RendererGLContext::Echo(const base::Closure& task) {
239 return command_buffer_->Echo(task);
240 }
241
242 RendererGLContext::Error RendererGLContext::GetError() {
243 gpu::CommandBuffer::State state = command_buffer_->GetState();
244 if (state.error == gpu::error::kNoError) {
245 Error old_error = last_error_;
246 last_error_ = SUCCESS;
247 return old_error;
248 } else {
249 // All command buffer errors are unrecoverable. The error is treated as a
250 // lost context: destroy the context and create another one.
251 return CONTEXT_LOST;
252 }
253 }
254
255 bool RendererGLContext::IsCommandBufferContextLost() {
256 // If the channel shut down unexpectedly, let that supersede the
257 // command buffer's state.
258 if (channel_->state() == GpuChannelHost::kLost)
259 return true;
260 gpu::CommandBuffer::State state = command_buffer_->GetLastState();
261 return state.error == gpu::error::kLostContext;
262 }
263
264 CommandBufferProxy* RendererGLContext::GetCommandBufferProxy() {
265 return command_buffer_;
266 }
267
268 bool RendererGLContext::SetSurfaceVisible(bool visible) {
269 return GetCommandBufferProxy()->SetSurfaceVisible(visible);
270 }
271
272 // TODO(gman): Remove This
273 void RendererGLContext::DisableShaderTranslation() {
274 NOTREACHED();
275 }
276
277 gpu::gles2::GLES2Implementation* RendererGLContext::GetImplementation() {
278 return gles2_implementation_;
279 }
280
281 RendererGLContext::RendererGLContext(GpuChannelHost* channel)
282 : channel_(channel),
283 parent_(base::WeakPtr<RendererGLContext>()),
284 parent_texture_id_(0),
285 command_buffer_(NULL),
286 gles2_helper_(NULL),
287 transfer_buffer_(NULL),
288 gles2_implementation_(NULL),
289 last_error_(SUCCESS),
290 frame_number_(0) {
291 DCHECK(channel);
292 }
293
294 bool RendererGLContext::Initialize(bool onscreen,
295 int32 surface_id,
296 const gfx::Size& size,
297 RendererGLContext* share_group,
298 const char* allowed_extensions,
299 const int32* attrib_list,
300 const GURL& active_url,
301 gfx::GpuPreference gpu_preference) {
302 DCHECK(CalledOnValidThread());
303 DCHECK(size.width() >= 0 && size.height() >= 0);
304 TRACE_EVENT2("gpu", "RendererGLContext::Initialize",
305 "on_screen", onscreen, "num_pixels", size.GetArea());
306
307 if (channel_->state() != GpuChannelHost::kConnected)
308 return false;
309
310 // Ensure the gles2 library is initialized first in a thread safe way.
311 g_gles2_initializer.Get();
312
313 bool share_resources = true;
314 bool bind_generates_resources = true;
315 std::vector<int32> attribs;
316 while (attrib_list) {
317 int32 attrib = *attrib_list++;
318 switch (attrib) {
319 // Known attributes
320 case ALPHA_SIZE:
321 case BLUE_SIZE:
322 case GREEN_SIZE:
323 case RED_SIZE:
324 case DEPTH_SIZE:
325 case STENCIL_SIZE:
326 case SAMPLES:
327 case SAMPLE_BUFFERS:
328 attribs.push_back(attrib);
329 attribs.push_back(*attrib_list++);
330 break;
331 case SHARE_RESOURCES:
332 share_resources = !!(*attrib_list++);
333 break;
334 case BIND_GENERATES_RESOURCES:
335 bind_generates_resources = !!(*attrib_list++);
336 break;
337 case NONE:
338 attribs.push_back(attrib);
339 attrib_list = NULL;
340 break;
341 default:
342 last_error_ = BAD_ATTRIBUTE;
343 attribs.push_back(NONE);
344 attrib_list = NULL;
345 break;
346 }
347 }
348
349 // Create a proxy to a command buffer in the GPU process.
350 if (onscreen) {
351 TRACE_EVENT0("gpu",
352 "RendererGLContext::Initialize::CreateViewCommandBuffer");
353 command_buffer_ = channel_->CreateViewCommandBuffer(
354 surface_id,
355 share_group ? share_group->command_buffer_ : NULL,
356 allowed_extensions,
357 attribs,
358 active_url,
359 gpu_preference);
360 } else {
361 command_buffer_ = channel_->CreateOffscreenCommandBuffer(
362 size,
363 share_group ? share_group->command_buffer_ : NULL,
364 allowed_extensions,
365 attribs,
366 active_url,
367 gpu_preference);
368 }
369 if (!command_buffer_) {
370 Destroy();
371 return false;
372 }
373
374 {
375 TRACE_EVENT0("gpu",
376 "RendererGLContext::Initialize::InitializeCommandBuffer");
377 // Initiaize the command buffer.
378 if (!command_buffer_->Initialize()) {
379 Destroy();
380 return false;
381 }
382 }
383
384 command_buffer_->SetChannelErrorCallback(
385 base::Bind(&RendererGLContext::OnContextLost, base::Unretained(this)));
386
387 // Create the GLES2 helper, which writes the command buffer protocol.
388 gles2_helper_ = new gpu::gles2::GLES2CmdHelper(command_buffer_);
389 if (!gles2_helper_->Initialize(kCommandBufferSize)) {
390 Destroy();
391 return false;
392 }
393
394 {
395 TRACE_EVENT0("gpu", "RendererGLContext::Initialize::CreateTransferBuffer");
396 // Create a transfer buffer used to copy resources between the renderer
397 // process and the GPU process.
398 transfer_buffer_ = new gpu::TransferBuffer(gles2_helper_);
399 }
400
401 // Create the object exposing the OpenGL API.
402 gles2_implementation_ = new gpu::gles2::GLES2Implementation(
403 gles2_helper_,
404 transfer_buffer_,
405 share_resources,
406 bind_generates_resources);
407
408 if (!gles2_implementation_->Initialize(
409 kStartTransferBufferSize,
410 kMinTransferBufferSize,
411 kMaxTransferBufferSize)) {
412 Destroy();
413 return false;
414 }
415
416 return true;
417 }
418
419 void RendererGLContext::Destroy() {
420 TRACE_EVENT0("gpu", "RendererGLContext::Destroy");
421 DCHECK(CalledOnValidThread());
422 SetParent(NULL);
423
424 if (gles2_implementation_) {
425 // First flush the context to ensure that any pending frees of resources
426 // are completed. Otherwise, if this context is part of a share group,
427 // those resources might leak. Also, any remaining side effects of commands
428 // issued on this context might not be visible to other contexts in the
429 // share group.
430 gles2_implementation_->Flush();
431
432 delete gles2_implementation_;
433 gles2_implementation_ = NULL;
434 }
435
436 if (transfer_buffer_) {
437 delete transfer_buffer_;
438 transfer_buffer_ = NULL;
439 }
440
441 delete gles2_helper_;
442 gles2_helper_ = NULL;
443
444 if (channel_ && command_buffer_) {
445 channel_->DestroyCommandBuffer(command_buffer_);
446 command_buffer_ = NULL;
447 }
448
449 channel_ = NULL;
450 }
451
452 void RendererGLContext::OnContextLost() {
453 if (!context_lost_callback_.is_null()) {
454 RendererGLContext::ContextLostReason reason = kUnknown;
455 if (command_buffer_) {
456 reason = ConvertReason(
457 command_buffer_->GetLastState().context_lost_reason);
458 }
459 context_lost_callback_.Run(reason);
460 }
461 }
OLDNEW
« no previous file with comments | « content/renderer/gpu/renderer_gl_context.h ('k') | content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698