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

Side by Side Diff: chrome/renderer/ggl/ggl.cc

Issue 6673090: Move core renderer subdirectories to content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 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
« no previous file with comments | « chrome/renderer/ggl/ggl.h ('k') | chrome/renderer/media/audio_renderer_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "build/build_config.h"
6
7 #include "base/lazy_instance.h"
8 #include "base/ref_counted.h"
9 #include "base/weak_ptr.h"
10 #include "chrome/renderer/command_buffer_proxy.h"
11 #include "chrome/renderer/ggl/ggl.h"
12 #include "chrome/renderer/gpu_channel_host.h"
13 #include "chrome/renderer/gpu_video_service_host.h"
14 #include "chrome/renderer/media/gles2_video_decode_context.h"
15 #include "chrome/renderer/render_widget.h"
16 #include "ipc/ipc_channel_handle.h"
17
18
19 #if defined(ENABLE_GPU)
20 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
21 #include "gpu/command_buffer/client/gles2_implementation.h"
22 #include "gpu/command_buffer/client/gles2_lib.h"
23 #include "gpu/command_buffer/common/constants.h"
24 #include "gpu/common/gpu_trace_event.h"
25 #include "gpu/GLES2/gles2_command_buffer.h"
26 #endif // ENABLE_GPU
27
28 namespace ggl {
29
30 #if defined(ENABLE_GPU)
31
32 namespace {
33
34 const int32 kCommandBufferSize = 1024 * 1024;
35 // TODO(kbr): make the transfer buffer size configurable via context
36 // creation attributes.
37 const int32 kTransferBufferSize = 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 static base::LazyInstance<GLES2Initializer> g_gles2_initializer(
55 base::LINKER_INITIALIZED);
56
57 } // namespace anonymous
58
59 // Manages a GL context.
60 class Context : public base::SupportsWeakPtr<Context> {
61 public:
62 Context(GpuChannelHost* channel, Context* parent);
63 ~Context();
64
65 // Initialize a GGL context that can be used in association with a a GPU
66 // channel acquired from a RenderWidget or RenderView.
67 bool Initialize(bool onscreen,
68 int render_view_id,
69 const gfx::Size& size,
70 const char* allowed_extensions,
71 const int32* attrib_list);
72
73 #if defined(OS_MACOSX)
74 // Asynchronously resizes an onscreen frame buffer.
75 void ResizeOnscreen(const gfx::Size& size);
76 #endif
77
78 // Asynchronously resizes an offscreen frame buffer.
79 void ResizeOffscreen(const gfx::Size& size);
80
81 // Provides a callback that will be invoked when SwapBuffers has completed
82 // service side.
83 void SetSwapBuffersCallback(Callback0::Type* callback) {
84 swap_buffers_callback_.reset(callback);
85 }
86
87 void SetContextLostCallback(Callback0::Type* callback) {
88 context_lost_callback_.reset(callback);
89 }
90
91 // For an offscreen frame buffer context, return the frame buffer ID with
92 // respect to the parent.
93 uint32 parent_texture_id() const {
94 return parent_texture_id_;
95 }
96
97 uint32 CreateParentTexture(const gfx::Size& size) const;
98 void DeleteParentTexture(uint32 texture) const;
99
100 // Destroy all resources associated with the GGL context.
101 void Destroy();
102
103 // Make a GGL context current for the calling thread.
104 static bool MakeCurrent(Context* context);
105
106 // Display all content rendered since last call to SwapBuffers.
107 // TODO(apatrick): support rendering to browser window. This function is
108 // not useful at this point.
109 bool SwapBuffers();
110
111 // Create a hardware accelerated video decoder associated with this context.
112 media::VideoDecodeEngine* CreateVideoDecodeEngine();
113
114 // Create a hardware video decode context associated with this context.
115 media::VideoDecodeContext* CreateVideoDecodeContext(MessageLoop* message_loop,
116 bool hardware_decoder);
117
118 // Get the current error code. Clears context's error code afterwards.
119 Error GetError();
120
121 // Replace the current error code with this.
122 void SetError(Error error);
123
124 bool IsCommandBufferContextLost();
125
126 // TODO(gman): Remove this.
127 void DisableShaderTranslation();
128
129 gpu::gles2::GLES2Implementation* gles2_implementation() const {
130 return gles2_implementation_;
131 }
132
133 CommandBufferProxy* command_buffer() const {
134 return command_buffer_;
135 }
136
137 private:
138 void OnSwapBuffers();
139 void OnContextLost();
140
141 scoped_refptr<GpuChannelHost> channel_;
142 base::WeakPtr<Context> parent_;
143 scoped_ptr<Callback0::Type> swap_buffers_callback_;
144 scoped_ptr<Callback0::Type> context_lost_callback_;
145 uint32 parent_texture_id_;
146 CommandBufferProxy* command_buffer_;
147 gpu::gles2::GLES2CmdHelper* gles2_helper_;
148 int32 transfer_buffer_id_;
149 gpu::gles2::GLES2Implementation* gles2_implementation_;
150 gfx::Size size_;
151 Error last_error_;
152
153 DISALLOW_COPY_AND_ASSIGN(Context);
154 };
155
156 Context::Context(GpuChannelHost* channel, Context* parent)
157 : channel_(channel),
158 parent_(parent ? parent->AsWeakPtr() : base::WeakPtr<Context>()),
159 parent_texture_id_(0),
160 command_buffer_(NULL),
161 gles2_helper_(NULL),
162 transfer_buffer_id_(0),
163 gles2_implementation_(NULL),
164 last_error_(SUCCESS) {
165 DCHECK(channel);
166 }
167
168 Context::~Context() {
169 Destroy();
170 }
171
172 bool Context::Initialize(bool onscreen,
173 int render_view_id,
174 const gfx::Size& size,
175 const char* allowed_extensions,
176 const int32* attrib_list) {
177 DCHECK(size.width() >= 0 && size.height() >= 0);
178
179 if (channel_->state() != GpuChannelHost::kConnected)
180 return false;
181
182 // Ensure the gles2 library is initialized first in a thread safe way.
183 g_gles2_initializer.Get();
184
185 // Allocate a frame buffer ID with respect to the parent.
186 if (parent_.get()) {
187 // Flush any remaining commands in the parent context to make sure the
188 // texture id accounting stays consistent.
189 int32 token = parent_->gles2_helper_->InsertToken();
190 parent_->gles2_helper_->WaitForToken(token);
191 parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId();
192 }
193
194 std::vector<int32> attribs;
195 while (attrib_list) {
196 int32 attrib = *attrib_list++;
197 switch (attrib) {
198 // Known attributes
199 case ggl::GGL_ALPHA_SIZE:
200 case ggl::GGL_BLUE_SIZE:
201 case ggl::GGL_GREEN_SIZE:
202 case ggl::GGL_RED_SIZE:
203 case ggl::GGL_DEPTH_SIZE:
204 case ggl::GGL_STENCIL_SIZE:
205 case ggl::GGL_SAMPLES:
206 case ggl::GGL_SAMPLE_BUFFERS:
207 attribs.push_back(attrib);
208 attribs.push_back(*attrib_list++);
209 break;
210 case ggl::GGL_NONE:
211 attribs.push_back(attrib);
212 attrib_list = NULL;
213 break;
214 default:
215 SetError(ggl::BAD_ATTRIBUTE);
216 attribs.push_back(ggl::GGL_NONE);
217 attrib_list = NULL;
218 break;
219 }
220 }
221
222 // Create a proxy to a command buffer in the GPU process.
223 if (onscreen) {
224 command_buffer_ = channel_->CreateViewCommandBuffer(
225 render_view_id,
226 allowed_extensions,
227 attribs);
228 } else {
229 CommandBufferProxy* parent_command_buffer =
230 parent_.get() ? parent_->command_buffer_ : NULL;
231 command_buffer_ = channel_->CreateOffscreenCommandBuffer(
232 parent_command_buffer,
233 size,
234 allowed_extensions,
235 attribs,
236 parent_texture_id_);
237 }
238 if (!command_buffer_) {
239 Destroy();
240 return false;
241 }
242
243 // Initiaize the command buffer.
244 if (!command_buffer_->Initialize(kCommandBufferSize)) {
245 Destroy();
246 return false;
247 }
248
249 command_buffer_->SetSwapBuffersCallback(
250 NewCallback(this, &Context::OnSwapBuffers));
251
252 command_buffer_->SetChannelErrorCallback(
253 NewCallback(this, &Context::OnContextLost));
254
255 // Create the GLES2 helper, which writes the command buffer protocol.
256 gles2_helper_ = new gpu::gles2::GLES2CmdHelper(command_buffer_);
257 if (!gles2_helper_->Initialize(kCommandBufferSize)) {
258 Destroy();
259 return false;
260 }
261
262 // Create a transfer buffer used to copy resources between the renderer
263 // process and the GPU process.
264 transfer_buffer_id_ =
265 command_buffer_->CreateTransferBuffer(kTransferBufferSize);
266 if (transfer_buffer_id_ < 0) {
267 Destroy();
268 return false;
269 }
270
271 // Map the buffer into the renderer process's address space.
272 gpu::Buffer transfer_buffer =
273 command_buffer_->GetTransferBuffer(transfer_buffer_id_);
274 if (!transfer_buffer.ptr) {
275 Destroy();
276 return false;
277 }
278
279 // Create the object exposing the OpenGL API.
280 gles2_implementation_ = new gpu::gles2::GLES2Implementation(
281 gles2_helper_,
282 transfer_buffer.size,
283 transfer_buffer.ptr,
284 transfer_buffer_id_,
285 false);
286
287 size_ = size;
288
289 return true;
290 }
291
292 #if defined(OS_MACOSX)
293 void Context::ResizeOnscreen(const gfx::Size& size) {
294 DCHECK(size.width() > 0 && size.height() > 0);
295 size_ = size;
296 command_buffer_->SetWindowSize(size);
297 }
298 #endif
299
300 void Context::ResizeOffscreen(const gfx::Size& size) {
301 DCHECK(size.width() > 0 && size.height() > 0);
302 if (size_ != size) {
303 command_buffer_->ResizeOffscreenFrameBuffer(size);
304 size_ = size;
305 }
306 }
307
308 uint32 Context::CreateParentTexture(const gfx::Size& size) const {
309 // Allocate a texture ID with respect to the parent.
310 if (parent_.get()) {
311 if (!MakeCurrent(parent_.get()))
312 return 0;
313 uint32 texture_id = parent_->gles2_implementation_->MakeTextureId();
314 parent_->gles2_implementation_->BindTexture(GL_TEXTURE_2D, texture_id);
315 parent_->gles2_implementation_->TexParameteri(
316 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
317 parent_->gles2_implementation_->TexParameteri(
318 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
319 parent_->gles2_implementation_->TexParameteri(
320 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
321 parent_->gles2_implementation_->TexParameteri(
322 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
323
324 parent_->gles2_implementation_->TexImage2D(GL_TEXTURE_2D,
325 0, // mip level
326 GL_RGBA,
327 size.width(),
328 size.height(),
329 0, // border
330 GL_RGBA,
331 GL_UNSIGNED_BYTE,
332 NULL);
333 // Make sure that the parent texture's storage is allocated before we let
334 // the caller attempt to use it.
335 int32 token = parent_->gles2_helper_->InsertToken();
336 parent_->gles2_helper_->WaitForToken(token);
337 return texture_id;
338 }
339 return 0;
340 }
341
342 void Context::DeleteParentTexture(uint32 texture) const {
343 if (parent_.get()) {
344 if (!MakeCurrent(parent_.get()))
345 return;
346 parent_->gles2_implementation_->DeleteTextures(1, &texture);
347 }
348 }
349
350 void Context::Destroy() {
351 if (parent_.get() && parent_texture_id_ != 0)
352 parent_->gles2_implementation_->FreeTextureId(parent_texture_id_);
353
354 delete gles2_implementation_;
355 gles2_implementation_ = NULL;
356
357 if (command_buffer_ && transfer_buffer_id_ != 0) {
358 command_buffer_->DestroyTransferBuffer(transfer_buffer_id_);
359 transfer_buffer_id_ = 0;
360 }
361
362 delete gles2_helper_;
363 gles2_helper_ = NULL;
364
365 if (channel_ && command_buffer_) {
366 channel_->DestroyCommandBuffer(command_buffer_);
367 command_buffer_ = NULL;
368 }
369
370 channel_ = NULL;
371 }
372
373 bool Context::MakeCurrent(Context* context) {
374 if (context) {
375 gles2::SetGLContext(context->gles2_implementation_);
376
377 // Don't request latest error status from service. Just use the locally
378 // cached information from the last flush.
379 // TODO(apatrick): I'm not sure if this should actually change the
380 // current context if it fails. For now it gets changed even if it fails
381 // because making GL calls with a NULL context crashes.
382 if (context->command_buffer_->GetLastState().error != gpu::error::kNoError)
383 return false;
384 } else {
385 gles2::SetGLContext(NULL);
386 }
387
388 return true;
389 }
390
391 bool Context::SwapBuffers() {
392 GPU_TRACE_EVENT0("gpu", "Context::SwapBuffers");
393 // Don't request latest error status from service. Just use the locally cached
394 // information from the last flush.
395 if (command_buffer_->GetLastState().error != gpu::error::kNoError)
396 return false;
397
398 gles2_implementation_->SwapBuffers();
399 return true;
400 }
401
402 media::VideoDecodeEngine* Context::CreateVideoDecodeEngine() {
403 return channel_->gpu_video_service_host()->CreateVideoDecoder(
404 command_buffer_->route_id());
405 }
406
407 media::VideoDecodeContext* Context::CreateVideoDecodeContext(
408 MessageLoop* message_loop, bool hardware_decoder) {
409 return new Gles2VideoDecodeContext(message_loop, hardware_decoder, this);
410 }
411
412 Error Context::GetError() {
413 gpu::CommandBuffer::State state = command_buffer_->GetState();
414 if (state.error == gpu::error::kNoError) {
415 Error old_error = last_error_;
416 last_error_ = SUCCESS;
417 return old_error;
418 } else {
419 // All command buffer errors are unrecoverable. The error is treated as a
420 // lost context: destroy the context and create another one.
421 return CONTEXT_LOST;
422 }
423 }
424
425 void Context::SetError(Error error) {
426 last_error_ = error;
427 }
428
429 bool Context::IsCommandBufferContextLost() {
430 gpu::CommandBuffer::State state = command_buffer_->GetLastState();
431 return state.error == gpu::error::kLostContext;
432 }
433
434 // TODO(gman): Remove This
435 void Context::DisableShaderTranslation() {
436 gles2_implementation_->CommandBufferEnableCHROMIUM(
437 PEPPER3D_SKIP_GLSL_TRANSLATION);
438 }
439
440 void Context::OnSwapBuffers() {
441 if (swap_buffers_callback_.get())
442 swap_buffers_callback_->Run();
443 }
444
445 void Context::OnContextLost() {
446 if (context_lost_callback_.get())
447 context_lost_callback_->Run();
448 }
449
450 #endif // ENABLE_GPU
451
452 Context* CreateViewContext(GpuChannelHost* channel,
453 int render_view_id,
454 const char* allowed_extensions,
455 const int32* attrib_list) {
456 #if defined(ENABLE_GPU)
457 scoped_ptr<Context> context(new Context(channel, NULL));
458 if (!context->Initialize(
459 true, render_view_id, gfx::Size(), allowed_extensions, attrib_list))
460 return NULL;
461
462 return context.release();
463 #else
464 return NULL;
465 #endif
466 }
467
468 #if defined(OS_MACOSX)
469 void ResizeOnscreenContext(Context* context, const gfx::Size& size) {
470 #if defined(ENABLE_GPU)
471 context->ResizeOnscreen(size);
472 #endif
473 }
474 #endif
475
476 Context* CreateOffscreenContext(GpuChannelHost* channel,
477 Context* parent,
478 const gfx::Size& size,
479 const char* allowed_extensions,
480 const int32* attrib_list) {
481 #if defined(ENABLE_GPU)
482 scoped_ptr<Context> context(new Context(channel, parent));
483 if (!context->Initialize(false, 0, size, allowed_extensions, attrib_list))
484 return NULL;
485
486 return context.release();
487 #else
488 return NULL;
489 #endif
490 }
491
492 void ResizeOffscreenContext(Context* context, const gfx::Size& size) {
493 #if defined(ENABLE_GPU)
494 context->ResizeOffscreen(size);
495 #endif
496 }
497
498 uint32 GetParentTextureId(Context* context) {
499 #if defined(ENABLE_GPU)
500 return context->parent_texture_id();
501 #else
502 return 0;
503 #endif
504 }
505
506 uint32 CreateParentTexture(Context* context, const gfx::Size& size) {
507 #if defined(ENABLE_GPU)
508 return context->CreateParentTexture(size);
509 #else
510 return 0;
511 #endif
512 }
513
514 void DeleteParentTexture(Context* context, uint32 texture) {
515 #if defined(ENABLE_GPU)
516 context->DeleteParentTexture(texture);
517 #endif
518 }
519
520 void SetSwapBuffersCallback(Context* context,
521 Callback0::Type* callback) {
522 #if defined(ENABLE_GPU)
523 context->SetSwapBuffersCallback(callback);
524 #endif
525 }
526
527 void SetContextLostCallback(Context* context,
528 Callback0::Type* callback) {
529 #if defined(ENABLE_GPU)
530 context->SetContextLostCallback(callback);
531 #endif
532 }
533
534 bool MakeCurrent(Context* context) {
535 #if defined(ENABLE_GPU)
536 return Context::MakeCurrent(context);
537 #else
538 return false;
539 #endif
540 }
541
542 bool SwapBuffers(Context* context) {
543 #if defined(ENABLE_GPU)
544 if (!context)
545 return false;
546
547 return context->SwapBuffers();
548 #else
549 return false;
550 #endif
551 }
552
553 bool DestroyContext(Context* context) {
554 #if defined(ENABLE_GPU)
555 if (!context)
556 return false;
557
558 delete context;
559 return true;
560 #else
561 return false;
562 #endif
563 }
564
565 media::VideoDecodeEngine* CreateVideoDecodeEngine(Context* context) {
566 return context->CreateVideoDecodeEngine();
567 }
568
569 media::VideoDecodeContext* CreateVideoDecodeContext(
570 Context* context, MessageLoop* message_loop, bool hardware_decoder) {
571 return context->CreateVideoDecodeContext(message_loop, hardware_decoder);
572 }
573
574 Error GetError(Context* context) {
575 #if defined(ENABLE_GPU)
576 return context->GetError();
577 #else
578 return NOT_INITIALIZED;
579 #endif
580 }
581
582 bool IsCommandBufferContextLost(Context* context) {
583 return context->IsCommandBufferContextLost();
584 }
585
586 // TODO(gman): Remove This
587 void DisableShaderTranslation(Context* context) {
588 #if defined(ENABLE_GPU)
589 if (context) {
590 context->DisableShaderTranslation();
591 }
592 #endif
593 }
594
595 gpu::gles2::GLES2Implementation* GetImplementation(Context* context) {
596 if (!context)
597 return NULL;
598
599 return context->gles2_implementation();
600 }
601
602 CommandBufferProxy* GetCommandBufferProxy(Context* context) {
603 DCHECK(context);
604 return context->command_buffer();
605 }
606
607 } // namespace ggl
OLDNEW
« no previous file with comments | « chrome/renderer/ggl/ggl.h ('k') | chrome/renderer/media/audio_renderer_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698