OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #if defined(ENABLE_GPU) | |
6 | |
5 #include "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" | 7 #include "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" |
6 | 8 |
7 #include <string.h> | 9 #include <GLES2/gl2.h> |
10 #ifndef GL_GLEXT_PROTOTYPES | |
11 #define GL_GLEXT_PROTOTYPES 1 | |
12 #endif | |
13 #include <GLES2/gl2ext.h> | |
8 | 14 |
9 #include <algorithm> | 15 #include <algorithm> |
10 #include <string> | 16 |
11 | 17 #include "base/string_tokenizer.h" |
18 #include "base/command_line.h" | |
19 #include "base/lazy_instance.h" | |
12 #include "base/logging.h" | 20 #include "base/logging.h" |
21 #include "base/memory/singleton.h" | |
22 #include "base/metrics/histogram.h" | |
23 #include "content/common/content_switches.h" | |
24 #include "gpu/command_buffer/client/gles2_lib.h" | |
25 #include "gpu/command_buffer/client/gles2_implementation.h" | |
26 #include "gpu/command_buffer/common/constants.h" | |
27 #include "gpu/command_buffer/service/gpu_scheduler.h" | |
28 #include "gpu/command_buffer/service/command_buffer_service.h" | |
29 #include "gpu/GLES2/gles2_command_buffer.h" | |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" | |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
16 #include "ui/gfx/gl/gl_bindings.h" | 32 #include "webkit/glue/gl_bindings_skia_cmd_buffer.h" |
17 #include "ui/gfx/gl/gl_bindings_skia_in_process.h" | 33 |
18 #include "ui/gfx/gl/gl_context.h" | 34 using gpu::Buffer; |
19 #include "ui/gfx/gl/gl_implementation.h" | 35 using gpu::CommandBuffer; |
20 #include "ui/gfx/gl/gl_surface.h" | 36 using gpu::CommandBufferService; |
37 using gpu::gles2::GLES2CmdHelper; | |
38 using gpu::gles2::GLES2Implementation; | |
39 using gpu::GpuScheduler; | |
21 | 40 |
22 namespace webkit { | 41 namespace webkit { |
23 namespace gpu { | 42 namespace gpu { |
24 | 43 |
25 enum { | 44 class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> { |
26 MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB, | 45 public: |
27 MAX_VARYING_VECTORS = 0x8DFC, | 46 // These are the same error codes as used by EGL. |
28 MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD | 47 enum Error { |
48 SUCCESS = 0x3000, | |
49 NOT_INITIALIZED = 0x3001, | |
50 BAD_ATTRIBUTE = 0x3004, | |
51 BAD_GLContext = 0x3006, | |
52 CONTEXT_LOST = 0x300E | |
53 }; | |
54 | |
55 // GLInProcessContext configuration attributes. These are the same as used by | |
56 // EGL. Attributes are matched using a closest fit algorithm. | |
57 enum Attribute { | |
58 ALPHA_SIZE = 0x3021, | |
59 BLUE_SIZE = 0x3022, | |
60 GREEN_SIZE = 0x3023, | |
61 RED_SIZE = 0x3024, | |
62 DEPTH_SIZE = 0x3025, | |
63 STENCIL_SIZE = 0x3026, | |
64 SAMPLES = 0x3031, | |
65 SAMPLE_BUFFERS = 0x3032, | |
66 NONE = 0x3038 // Attrib list = terminator | |
67 }; | |
68 | |
69 // Initialize the library. This must have completed before any other | |
70 // functions are invoked. | |
71 static bool Initialize(); | |
72 | |
73 // Terminate the library. This must be called after any other functions | |
74 // have completed. | |
75 static bool Terminate(); | |
76 | |
77 ~GLInProcessContext(); | |
78 | |
79 // Create a GLInProcessContext that renders directly to a view. The view and | |
80 // the associated window must not be destroyed until the returned | |
81 // GLInProcessContext has been destroyed, otherwise the GPU process might | |
82 // attempt to render to an invalid window handle. | |
83 // | |
84 // NOTE: on Mac OS X, this entry point is only used to set up the | |
85 // accelerated compositor's output. On this platform, we actually pass | |
86 // a gfx::PluginWindowHandle in place of the gfx::NativeViewId, | |
87 // because the facility to allocate a fake PluginWindowHandle is | |
88 // already in place. We could add more entry points and messages to | |
89 // allocate both fake PluginWindowHandles and NativeViewIds and map | |
90 // from fake NativeViewIds to PluginWindowHandles, but this seems like | |
91 // unnecessary complexity at the moment. | |
92 // | |
93 static GLInProcessContext* CreateViewContext( | |
94 gfx::PluginWindowHandle render_surface, | |
95 const char* allowed_extensions, | |
96 const int32* attrib_list, | |
97 const GURL& active_arl); | |
98 | |
99 #if defined(OS_MACOSX) | |
100 // On Mac OS X only, view GLInProcessContexts actually behave like offscreen | |
101 // GLInProcessContexts, and require an explicit resize operation which is | |
102 // slightly different from that of offscreen GLInProcessContexts. | |
103 void ResizeOnscreen(const gfx::Size& size); | |
104 #endif | |
105 | |
106 // Create a GLInProcessContext that renders to an offscreen frame buffer. If | |
107 // parent is not NULL, that GLInProcessContext can access a copy of the | |
108 // created GLInProcessContext's frame buffer that is updated every time | |
109 // SwapBuffers is called. It is not as general as shared GLInProcessContexts | |
110 // in other implementations of OpenGL. If parent is not NULL, it must be used | |
111 // on the same thread as the parent. A child GLInProcessContext may not | |
112 // outlive its parent. attrib_list must be NULL or a NONE-terminated list of | |
113 // attribute/value pairs. | |
114 static GLInProcessContext* CreateOffscreenContext( | |
115 GLInProcessContext* parent, | |
116 const gfx::Size& size, | |
117 const char* allowed_extensions, | |
118 const int32* attrib_list, | |
119 const GURL& active_url); | |
120 | |
121 // Resize an offscreen frame buffer. The resize occurs on the next call to | |
122 // SwapBuffers. This is to avoid waiting until all pending GL calls have been | |
123 // executed by the GPU process. Everything rendered up to the call to | |
124 // SwapBuffers will be lost. A lost GLInProcessContext will be reported if the | |
125 // resize fails. | |
126 void ResizeOffscreen(const gfx::Size& size); | |
127 | |
128 // For an offscreen frame buffer GLInProcessContext, return the texture ID | |
129 // with respect to the parent GLInProcessContext. Returns zero if | |
130 // GLInProcessContext does not have a parent. | |
131 uint32 GetParentTextureId(); | |
132 | |
133 // Create a new texture in the parent's GLInProcessContext. Returns zero if | |
134 // GLInProcessContext does not have a parent. | |
135 uint32 CreateParentTexture(const gfx::Size& size); | |
136 | |
137 // Deletes a texture in the parent's GLInProcessContext. | |
138 void DeleteParentTexture(uint32 texture); | |
139 | |
140 // Provides a callback that will be invoked when SwapBuffers has completed | |
141 // service side. | |
142 void SetSwapBuffersCallback(Callback0::Type* callback); | |
143 | |
144 void SetContextLostCallback(Callback0::Type* callback); | |
145 | |
146 // Set the current GLInProcessContext for the calling thread. | |
147 static bool MakeCurrent(GLInProcessContext* context); | |
148 | |
149 // For a view GLInProcessContext, display everything that has been rendered | |
150 // since the last call. For an offscreen GLInProcessContext, resolve | |
151 // everything that has been rendered since the last call to a copy that can be | |
152 // accessed by the parent GLInProcessContext. | |
153 bool SwapBuffers(); | |
154 | |
155 // TODO(gman): Remove this | |
156 void DisableShaderTranslation(); | |
157 | |
158 // Allows direct access to the GLES2 implementation so a GLInProcessContext | |
159 // can be used without making it current. | |
160 GLES2Implementation* GetImplementation(); | |
161 | |
162 // Return the current error. | |
163 Error GetError(); | |
164 | |
165 // Return true if GPU process reported GLInProcessContext lost or there was a | |
166 // problem communicating with the GPU process. | |
167 bool IsCommandBufferContextLost(); | |
168 | |
169 CommandBufferService* GetCommandBufferService(); | |
170 | |
171 // Create a latch for synchronization between contexts using glSetLatch and | |
172 // glWaitLatch. | |
173 // CreateLatch will only fail if there is a generally unrecoverable | |
174 // error, in which case 0 is returned. Returns latch_id on success. | |
175 bool CreateLatch(uint32* ret_latch); | |
176 | |
177 // Destroy a latch. | |
178 bool DestroyLatch(uint32 latch); | |
179 | |
180 // All child contexts get a latch pair automatically. These latches are used | |
181 // for synchronization with parent context. If *this* context does not have a | |
182 // parent context, these methods will return false. | |
183 bool GetParentToChildLatch(uint32* parent_to_child_latch); | |
184 bool GetChildToParentLatch(uint32* child_to_parent_latch); | |
185 | |
186 private: | |
187 GLInProcessContext(GLInProcessContext* parent); | |
188 | |
189 bool Initialize(bool onscreen, | |
190 gfx::PluginWindowHandle render_surface, | |
191 const gfx::Size& size, | |
192 const char* allowed_extensions, | |
193 const int32* attrib_list, | |
194 const GURL& active_url); | |
195 void Destroy(); | |
196 | |
197 void OnSwapBuffers(); | |
198 void OnContextLost(); | |
199 | |
200 base::WeakPtr<GLInProcessContext> parent_; | |
201 scoped_ptr<Callback0::Type> swap_buffers_callback_; | |
202 scoped_ptr<Callback0::Type> context_lost_callback_; | |
203 uint32 parent_texture_id_; | |
204 uint32 child_to_parent_latch_; | |
205 uint32 parent_to_child_latch_; | |
206 int32 latch_transfer_buffer_id_; | |
207 scoped_ptr<CommandBufferService> command_buffer_; | |
208 GpuScheduler* gpu_scheduler_; | |
209 GLES2CmdHelper* gles2_helper_; | |
210 int32 transfer_buffer_id_; | |
211 GLES2Implementation* gles2_implementation_; | |
212 gfx::Size size_; | |
213 Error last_error_; | |
214 | |
215 DISALLOW_COPY_AND_ASSIGN(GLInProcessContext); | |
29 }; | 216 }; |
30 | 217 |
31 struct WebGraphicsContext3DInProcessCommandBufferImpl::ShaderSourceEntry { | 218 namespace { |
32 explicit ShaderSourceEntry(WGC3Denum shader_type) | 219 |
33 : type(shader_type), | 220 const int32 kCommandBufferSize = 1024 * 1024; |
34 is_valid(false) { | 221 // TODO(kbr): make the transfer buffer size configurable via context |
35 } | 222 // creation attributes. |
36 | 223 const int32 kTransferBufferSize = 1024 * 1024; |
37 WGC3Denum type; | 224 |
38 scoped_array<char> source; | 225 const uint32 kMaxLatchesPerRenderer = 2048; |
39 scoped_array<char> log; | 226 const uint32 kInvalidLatchId = 0xffffffffu; |
40 scoped_array<char> translated_source; | 227 |
41 bool is_valid; | 228 // Singleton used to initialize and terminate the gles2 library. |
229 class GLES2Initializer { | |
230 public: | |
231 GLES2Initializer() { | |
232 gles2::Initialize(); | |
233 } | |
234 | |
235 ~GLES2Initializer() { | |
236 gles2::Terminate(); | |
237 } | |
238 | |
239 private: | |
240 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); | |
42 }; | 241 }; |
43 | 242 |
243 // Shared memory allocator for latches. Creates a block of shared memory for | |
jamesr
2011/06/01 02:07:02
this isn't really shared memory in this implementa
greggman
2011/06/01 21:55:39
Done.
| |
244 // each renderer process. | |
245 class LatchAllocator { | |
246 public: | |
247 static LatchAllocator* GetInstance(); | |
248 static uint32 size() { return kMaxLatchesPerRenderer*sizeof(uint32); } | |
249 static const uint32_t kFreeLatch = 0xffffffffu; | |
250 | |
251 LatchAllocator(); | |
252 ~LatchAllocator(); | |
253 | |
254 bool AllocateLatch(uint32* latch_id); | |
255 bool FreeLatch(uint32 latch_id); | |
256 | |
257 private: | |
258 friend struct DefaultSingletonTraits<LatchAllocator>; | |
259 | |
260 // Because this is in process this can just be normal memory. | |
261 scoped_array<uint32> memory_; | |
262 | |
263 // Pointer to mapped shared memory. | |
jamesr
2011/06/01 02:07:02
this is confusing - can't we just use memory_ (and
greggman
2011/06/01 21:55:39
Done.
| |
264 volatile uint32* latches_; | |
265 | |
266 DISALLOW_COPY_AND_ASSIGN(LatchAllocator); | |
267 }; | |
268 | |
269 //////////////////////////////////////////////////////////////////////////////// | |
270 /// LatchAllocator implementation | |
271 | |
272 LatchAllocator* LatchAllocator::GetInstance() { | |
273 return Singleton<LatchAllocator>::get(); | |
274 } | |
275 | |
276 LatchAllocator::LatchAllocator() { | |
277 memory_.reset(new uint32[size()]); | |
278 latches_ = memory_.get(); | |
279 // Mark all latches as unallocated. | |
280 for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) | |
281 latches_[i] = kFreeLatch; | |
282 } | |
283 | |
284 LatchAllocator::~LatchAllocator() { | |
285 } | |
286 | |
287 bool LatchAllocator::AllocateLatch(uint32* latch_id) { | |
288 for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) { | |
289 if (latches_[i] == kFreeLatch) { | |
290 // mark latch as taken and blocked. | |
291 // 0 means waiter will block, 1 means waiter will pass. | |
292 latches_[i] = 0; | |
293 *latch_id = i; | |
294 return true; | |
295 } | |
296 } | |
297 return false; | |
298 } | |
299 | |
300 bool LatchAllocator::FreeLatch(uint32 latch_id) { | |
301 if (latch_id < kMaxLatchesPerRenderer && latches_[latch_id] != kFreeLatch) { | |
302 latches_[latch_id] = kFreeLatch; | |
303 return true; | |
304 } | |
305 return false; | |
306 } | |
307 | |
308 //////////////////////////////////////////////////////////////////////////////// | |
309 | |
310 static base::LazyInstance<GLES2Initializer> g_gles2_initializer( | |
311 base::LINKER_INITIALIZED); | |
312 | |
313 } // namespace anonymous | |
314 | |
315 GLInProcessContext::~GLInProcessContext() { | |
316 Destroy(); | |
317 } | |
318 | |
319 GLInProcessContext* GLInProcessContext::CreateViewContext( | |
320 gfx::PluginWindowHandle render_surface, | |
321 const char* allowed_extensions, | |
322 const int32* attrib_list, | |
323 const GURL& active_url) { | |
324 #if defined(ENABLE_GPU) | |
325 scoped_ptr<GLInProcessContext> context(new GLInProcessContext(NULL)); | |
326 if (!context->Initialize( | |
327 true, | |
328 render_surface, | |
329 gfx::Size(), | |
330 allowed_extensions, | |
331 attrib_list, | |
332 active_url)) | |
333 return NULL; | |
334 | |
335 return context.release(); | |
336 #else | |
337 return NULL; | |
338 #endif | |
339 } | |
340 | |
341 #if defined(OS_MACOSX) | |
342 void GLInProcessContext::ResizeOnscreen(const gfx::Size& size) { | |
343 DCHECK(size.width() > 0 && size.height() > 0); | |
344 size_ = size; | |
345 } | |
346 #endif | |
347 | |
348 GLInProcessContext* GLInProcessContext::CreateOffscreenContext( | |
349 GLInProcessContext* parent, | |
350 const gfx::Size& size, | |
351 const char* allowed_extensions, | |
352 const int32* attrib_list, | |
353 const GURL& active_url) { | |
354 #if defined(ENABLE_GPU) | |
355 scoped_ptr<GLInProcessContext> context(new GLInProcessContext(parent)); | |
356 if (!context->Initialize( | |
357 false, | |
358 gfx::kNullPluginWindow, | |
359 size, | |
360 allowed_extensions, | |
361 attrib_list, | |
362 active_url)) | |
363 return NULL; | |
364 | |
365 return context.release(); | |
366 #else | |
367 return NULL; | |
368 #endif | |
369 } | |
370 | |
371 void GLInProcessContext::ResizeOffscreen(const gfx::Size& size) { | |
372 DCHECK(size.width() > 0 && size.height() > 0); | |
373 if (size_ != size) { | |
374 gpu_scheduler_->ResizeOffscreenFrameBuffer(size); | |
375 // TODO(gman): See if the next line is needed. | |
376 gles2_implementation_->ResizeCHROMIUM(size.width(), size.height()); | |
377 size_ = size; | |
378 } | |
379 } | |
380 | |
381 uint32 GLInProcessContext::GetParentTextureId() { | |
382 return parent_texture_id_; | |
383 } | |
384 | |
385 uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) { | |
386 // Allocate a texture ID with respect to the parent. | |
387 if (parent_.get()) { | |
388 if (!MakeCurrent(parent_.get())) | |
389 return 0; | |
390 uint32 texture_id = parent_->gles2_implementation_->MakeTextureId(); | |
391 parent_->gles2_implementation_->BindTexture(GL_TEXTURE_2D, texture_id); | |
392 parent_->gles2_implementation_->TexParameteri( | |
393 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
394 parent_->gles2_implementation_->TexParameteri( | |
395 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
396 parent_->gles2_implementation_->TexParameteri( | |
397 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
398 parent_->gles2_implementation_->TexParameteri( | |
399 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
400 | |
401 parent_->gles2_implementation_->TexImage2D(GL_TEXTURE_2D, | |
402 0, // mip level | |
403 GL_RGBA, | |
404 size.width(), | |
405 size.height(), | |
406 0, // border | |
407 GL_RGBA, | |
408 GL_UNSIGNED_BYTE, | |
409 NULL); | |
410 // Make sure that the parent texture's storage is allocated before we let | |
411 // the caller attempt to use it. | |
412 int32 token = parent_->gles2_helper_->InsertToken(); | |
413 parent_->gles2_helper_->WaitForToken(token); | |
414 return texture_id; | |
415 } | |
416 return 0; | |
417 } | |
418 | |
419 void GLInProcessContext::DeleteParentTexture(uint32 texture) { | |
420 if (parent_.get()) { | |
421 if (!MakeCurrent(parent_.get())) | |
422 return; | |
423 parent_->gles2_implementation_->DeleteTextures(1, &texture); | |
424 } | |
425 } | |
426 | |
427 void GLInProcessContext::SetSwapBuffersCallback(Callback0::Type* callback) { | |
428 swap_buffers_callback_.reset(callback); | |
429 } | |
430 | |
431 void GLInProcessContext::SetContextLostCallback(Callback0::Type* callback) { | |
432 context_lost_callback_.reset(callback); | |
433 } | |
434 | |
435 bool GLInProcessContext::MakeCurrent(GLInProcessContext* context) { | |
436 if (context) { | |
437 gles2::SetGLContext(context->gles2_implementation_); | |
438 | |
439 // Don't request latest error status from service. Just use the locally | |
440 // cached information from the last flush. | |
441 // TODO(apatrick): I'm not sure if this should actually change the | |
442 // current context if it fails. For now it gets changed even if it fails | |
443 // because making GL calls with a NULL context crashes. | |
444 if (context->command_buffer_->GetState().error != ::gpu::error::kNoError) | |
445 return false; | |
446 } else { | |
447 gles2::SetGLContext(NULL); | |
448 } | |
449 | |
450 return true; | |
451 } | |
452 | |
453 bool GLInProcessContext::SwapBuffers() { | |
454 // Don't request latest error status from service. Just use the locally cached | |
455 // information from the last flush. | |
456 if (command_buffer_->GetState().error != ::gpu::error::kNoError) | |
457 return false; | |
458 | |
459 gles2_implementation_->SwapBuffers(); | |
460 gles2_implementation_->Finish(); | |
461 return true; | |
462 } | |
463 | |
464 GLInProcessContext::Error GLInProcessContext::GetError() { | |
465 CommandBuffer::State state = command_buffer_->GetState(); | |
466 if (state.error == ::gpu::error::kNoError) { | |
467 Error old_error = last_error_; | |
468 last_error_ = SUCCESS; | |
469 return old_error; | |
470 } else { | |
471 // All command buffer errors are unrecoverable. The error is treated as a | |
472 // lost context: destroy the context and create another one. | |
473 return CONTEXT_LOST; | |
474 } | |
475 } | |
476 | |
477 bool GLInProcessContext::IsCommandBufferContextLost() { | |
478 CommandBuffer::State state = command_buffer_->GetState(); | |
479 return state.error == ::gpu::error::kLostContext; | |
480 } | |
481 | |
482 CommandBufferService* GLInProcessContext::GetCommandBufferService() { | |
483 return command_buffer_.get(); | |
484 } | |
485 | |
486 // TODO(gman): Remove This | |
487 void GLInProcessContext::DisableShaderTranslation() { | |
488 gles2_implementation_->CommandBufferEnableCHROMIUM( | |
489 PEPPER3D_SKIP_GLSL_TRANSLATION); | |
490 } | |
491 | |
492 GLES2Implementation* GLInProcessContext::GetImplementation() { | |
493 return gles2_implementation_; | |
494 } | |
495 | |
496 GLInProcessContext::GLInProcessContext(GLInProcessContext* parent) | |
497 : parent_(parent ? | |
498 parent->AsWeakPtr() : base::WeakPtr<GLInProcessContext>()), | |
499 parent_texture_id_(0), | |
500 child_to_parent_latch_(kInvalidLatchId), | |
501 parent_to_child_latch_(kInvalidLatchId), | |
502 latch_transfer_buffer_id_(-1), | |
503 gpu_scheduler_(NULL), | |
504 gles2_helper_(NULL), | |
505 transfer_buffer_id_(-1), | |
506 gles2_implementation_(NULL), | |
507 last_error_(SUCCESS) { | |
508 } | |
509 | |
510 bool GLInProcessContext::Initialize(bool onscreen, | |
511 gfx::PluginWindowHandle render_surface, | |
512 const gfx::Size& size, | |
513 const char* allowed_extensions, | |
514 const int32* attrib_list, | |
515 const GURL& active_url) { | |
516 DCHECK(size.width() >= 0 && size.height() >= 0); | |
517 | |
518 // Ensure the gles2 library is initialized first in a thread safe way. | |
519 g_gles2_initializer.Get(); | |
520 | |
521 // Allocate a frame buffer ID with respect to the parent. | |
522 if (parent_.get()) { | |
523 // Flush any remaining commands in the parent context to make sure the | |
524 // texture id accounting stays consistent. | |
525 int32 token = parent_->gles2_helper_->InsertToken(); | |
526 parent_->gles2_helper_->WaitForToken(token); | |
527 parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId(); | |
528 } | |
529 | |
530 std::vector<int32> attribs; | |
531 while (attrib_list) { | |
532 int32 attrib = *attrib_list++; | |
533 switch (attrib) { | |
534 // Known attributes | |
535 case ALPHA_SIZE: | |
536 case BLUE_SIZE: | |
537 case GREEN_SIZE: | |
538 case RED_SIZE: | |
539 case DEPTH_SIZE: | |
540 case STENCIL_SIZE: | |
541 case SAMPLES: | |
542 case SAMPLE_BUFFERS: | |
543 attribs.push_back(attrib); | |
544 attribs.push_back(*attrib_list++); | |
545 break; | |
546 case NONE: | |
547 attribs.push_back(attrib); | |
548 attrib_list = NULL; | |
549 break; | |
550 default: | |
551 last_error_ = BAD_ATTRIBUTE; | |
552 attribs.push_back(NONE); | |
553 attrib_list = NULL; | |
554 break; | |
555 } | |
556 } | |
557 | |
558 command_buffer_.reset(new CommandBufferService); | |
559 if (!command_buffer_->Initialize(kCommandBufferSize)) | |
560 return false; | |
561 | |
562 gpu_scheduler_ = new GpuScheduler(command_buffer_.get(), NULL); | |
563 | |
564 if (onscreen) { | |
565 if (render_surface == gfx::kNullPluginWindow) { | |
566 LOG(ERROR) << "Invalid surface handle for onscreen context."; | |
567 command_buffer_.reset(); | |
568 } else { | |
569 if (!gpu_scheduler_->Initialize(render_surface, | |
570 gfx::Size(), | |
571 ::gpu::gles2::DisallowedExtensions(), | |
572 allowed_extensions, | |
573 attribs, | |
574 NULL, | |
575 0)) { | |
576 LOG(ERROR) << "Could not initialize GpuScheduler."; | |
577 command_buffer_.reset(); | |
578 } | |
579 } | |
580 } else { | |
581 GpuScheduler* parent_scheduler = | |
582 parent_.get() ? parent_->gpu_scheduler_ : NULL; | |
583 | |
584 if (!gpu_scheduler_->Initialize(render_surface, | |
585 size, | |
586 ::gpu::gles2::DisallowedExtensions(), | |
587 allowed_extensions, | |
588 attribs, | |
589 parent_scheduler, | |
590 parent_texture_id_)) { | |
591 LOG(ERROR) << "Could not initialize offscreen GpuScheduler."; | |
592 command_buffer_.reset(); | |
593 } | |
594 } | |
595 if (!command_buffer_.get()) { | |
596 Destroy(); | |
597 return false; | |
598 } | |
599 | |
600 command_buffer_->SetPutOffsetChangeCallback( | |
601 NewCallback(gpu_scheduler_, &GpuScheduler::PutChanged)); | |
602 | |
603 // Create the GLES2 helper, which writes the command buffer protocol. | |
604 gles2_helper_ = new GLES2CmdHelper(command_buffer_.get()); | |
605 if (!gles2_helper_->Initialize(kCommandBufferSize)) { | |
606 Destroy(); | |
607 return false; | |
608 } | |
609 | |
610 // Create a transfer buffer used to copy resources between the renderer | |
611 // process and the GPU process. | |
jamesr
2011/06/01 02:07:02
comment isn't quite correct for this case. what i
greggman
2011/06/01 21:55:39
Done.
| |
612 transfer_buffer_id_ = | |
613 command_buffer_->CreateTransferBuffer( | |
614 kTransferBufferSize, ::gpu::kCommandBufferSharedMemoryId); | |
615 if (transfer_buffer_id_ < 0) { | |
616 Destroy(); | |
617 return false; | |
618 } | |
619 | |
620 // Map the buffer into the renderer process's address space. | |
621 Buffer transfer_buffer = | |
622 command_buffer_->GetTransferBuffer(transfer_buffer_id_); | |
jamesr
2011/06/01 02:07:02
this is a no-op for this case right?
greggman
2011/06/01 21:55:39
I don't actually know and I shouldn't have to. I w
| |
623 if (!transfer_buffer.ptr) { | |
624 Destroy(); | |
625 return false; | |
626 } | |
627 | |
628 // Register transfer buffer so that the context can access latches. | |
jamesr
2011/06/01 02:07:02
comment is misleading
greggman
2011/06/01 21:55:39
Done.
| |
629 // LatchAllocator* latch_shm = LatchAllocator::GetInstance(); | |
630 // latch_transfer_buffer_id_ = command_buffer_->RegisterTransferBuffer( | |
jamesr
2011/06/01 02:07:02
what does this really do?
greggman
2011/06/01 21:55:39
This code has been deleted.
| |
631 // latch_shm->shared_memory(), LatchAllocator::size(), | |
632 // ::gpu::kLatchSharedMemoryId); | |
633 // if (latch_transfer_buffer_id_ != ::gpu::kLatchSharedMemoryId) { | |
634 // Destroy(); | |
635 // return false; | |
636 // } | |
637 | |
638 // If this is a child context, setup latches for synchronization between child | |
639 // and parent. | |
640 if (parent_.get()) { | |
641 if (!CreateLatch(&child_to_parent_latch_) || | |
642 !CreateLatch(&parent_to_child_latch_)) { | |
643 Destroy(); | |
644 return false; | |
645 } | |
646 } | |
647 | |
648 // Create the object exposing the OpenGL API. | |
649 gles2_implementation_ = new GLES2Implementation( | |
650 gles2_helper_, | |
651 transfer_buffer.size, | |
652 transfer_buffer.ptr, | |
653 transfer_buffer_id_, | |
654 false); | |
655 | |
656 size_ = size; | |
657 | |
658 return true; | |
659 } | |
660 | |
661 void GLInProcessContext::Destroy() { | |
662 if (parent_.get() && parent_texture_id_ != 0) { | |
663 parent_->gles2_implementation_->FreeTextureId(parent_texture_id_); | |
664 parent_texture_id_ = 0; | |
665 } | |
666 | |
667 delete gles2_implementation_; | |
668 gles2_implementation_ = NULL; | |
669 | |
670 if (child_to_parent_latch_ != kInvalidLatchId) { | |
671 DestroyLatch(child_to_parent_latch_); | |
672 child_to_parent_latch_ = kInvalidLatchId; | |
673 } | |
674 if (parent_to_child_latch_ != kInvalidLatchId) { | |
675 DestroyLatch(parent_to_child_latch_); | |
676 parent_to_child_latch_ = kInvalidLatchId; | |
677 } | |
678 if (command_buffer_.get() && latch_transfer_buffer_id_ != -1) { | |
679 command_buffer_->DestroyTransferBuffer(latch_transfer_buffer_id_); | |
680 latch_transfer_buffer_id_ = -1; | |
681 } | |
682 | |
683 if (command_buffer_.get() && transfer_buffer_id_ != -1) { | |
684 command_buffer_->DestroyTransferBuffer(transfer_buffer_id_); | |
685 transfer_buffer_id_ = -1; | |
686 } | |
687 | |
688 delete gles2_helper_; | |
689 gles2_helper_ = NULL; | |
690 | |
691 command_buffer_.reset(); | |
692 } | |
693 | |
694 void GLInProcessContext::OnSwapBuffers() { | |
695 if (swap_buffers_callback_.get()) | |
696 swap_buffers_callback_->Run(); | |
697 } | |
698 | |
699 void GLInProcessContext::OnContextLost() { | |
700 if (context_lost_callback_.get()) | |
701 context_lost_callback_->Run(); | |
702 } | |
703 | |
704 bool GLInProcessContext::CreateLatch(uint32* ret_latch) { | |
705 return LatchAllocator::GetInstance()->AllocateLatch(ret_latch); | |
706 } | |
707 | |
708 bool GLInProcessContext::DestroyLatch(uint32 latch) { | |
709 return LatchAllocator::GetInstance()->FreeLatch(latch); | |
710 } | |
711 | |
712 bool GLInProcessContext::GetParentToChildLatch(uint32* parent_to_child_latch) { | |
713 if (parent_.get()) { | |
714 *parent_to_child_latch = parent_to_child_latch_; | |
715 return true; | |
716 } | |
717 return false; | |
718 } | |
719 | |
720 bool GLInProcessContext::GetChildToParentLatch(uint32* child_to_parent_latch) { | |
721 if (parent_.get()) { | |
722 *child_to_parent_latch = child_to_parent_latch_; | |
723 return true; | |
724 } | |
725 return false; | |
726 } | |
727 | |
44 WebGraphicsContext3DInProcessCommandBufferImpl::WebGraphicsContext3DInProcessCom mandBufferImpl() | 728 WebGraphicsContext3DInProcessCommandBufferImpl::WebGraphicsContext3DInProcessCom mandBufferImpl() |
45 : initialized_(false), | 729 : context_(NULL), |
46 render_directly_to_web_view_(false), | 730 gl_(NULL), |
47 is_gles2_(false), | 731 web_view_(NULL), |
48 have_ext_framebuffer_object_(false), | 732 #if defined(OS_MACOSX) |
49 have_ext_framebuffer_multisample_(false), | 733 plugin_handle_(NULL), |
50 have_angle_framebuffer_multisample_(false), | 734 #endif // defined(OS_MACOSX) |
51 texture_(0), | 735 context_lost_callback_(0), |
52 fbo_(0), | |
53 depth_stencil_buffer_(0), | |
54 cached_width_(0), | 736 cached_width_(0), |
55 cached_height_(0), | 737 cached_height_(0), |
56 multisample_fbo_(0), | 738 bound_fbo_(0) { |
57 multisample_depth_stencil_buffer_(0), | 739 } |
58 multisample_color_buffer_(0), | 740 |
59 bound_fbo_(0), | 741 WebGraphicsContext3DInProcessCommandBufferImpl:: |
60 bound_texture_(0), | 742 ~WebGraphicsContext3DInProcessCommandBufferImpl() { |
61 copy_texture_to_parent_texture_fbo_(0), | 743 } |
62 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 744 |
63 scanline_(0), | 745 // This string should only be passed for WebGL contexts. Nothing ELSE!!! |
64 #endif | 746 // Compositor contexts, Canvas2D contexts, Pepper Contexts, nor any other use of |
65 fragment_compiler_(0), | 747 // a context should not pass this string. |
66 vertex_compiler_(0) { | 748 static const char* kWebGLPreferredGLExtensions = |
67 } | 749 "GL_OES_packed_depth_stencil " |
68 | 750 "GL_OES_depth24 " |
69 WebGraphicsContext3DInProcessCommandBufferImpl::~WebGraphicsContext3DInProcessCo mmandBufferImpl() { | 751 "GL_CHROMIUM_webglsl"; |
70 if (!initialized_) | |
71 return; | |
72 | |
73 makeContextCurrent(); | |
74 | |
75 if (attributes_.antialias) { | |
76 glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); | |
77 if (attributes_.depth || attributes_.stencil) | |
78 glDeleteRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); | |
79 glDeleteFramebuffersEXT(1, &multisample_fbo_); | |
80 } else { | |
81 if (attributes_.depth || attributes_.stencil) | |
82 glDeleteRenderbuffersEXT(1, &depth_stencil_buffer_); | |
83 } | |
84 glDeleteTextures(1, &texture_); | |
85 glDeleteFramebuffersEXT(1, ©_texture_to_parent_texture_fbo_); | |
86 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | |
87 if (scanline_) | |
88 delete[] scanline_; | |
89 #endif | |
90 glDeleteFramebuffersEXT(1, &fbo_); | |
91 | |
92 gl_context_->Destroy(); | |
93 | |
94 for (ShaderSourceMap::iterator ii = shader_source_map_.begin(); | |
95 ii != shader_source_map_.end(); ++ii) { | |
96 if (ii->second) | |
97 delete ii->second; | |
98 } | |
99 AngleDestroyCompilers(); | |
100 } | |
101 | 752 |
102 bool WebGraphicsContext3DInProcessCommandBufferImpl::initialize( | 753 bool WebGraphicsContext3DInProcessCommandBufferImpl::initialize( |
103 WebGraphicsContext3D::Attributes attributes, | 754 WebGraphicsContext3D::Attributes attributes, |
104 WebView* webView, | 755 WebKit::WebView* web_view, |
105 bool render_directly_to_web_view) { | 756 bool render_directly_to_web_view) { |
106 if (!gfx::GLSurface::InitializeOneOff()) | 757 webkit_glue::BindSkiaToCommandBufferGL(); |
758 | |
759 // Convert WebGL context creation attributes into GLInProcessContext / EGL | |
760 // size requests. | |
761 const int alpha_size = attributes.alpha ? 8 : 0; | |
762 const int depth_size = attributes.depth ? 24 : 0; | |
763 const int stencil_size = attributes.stencil ? 8 : 0; | |
764 const int samples = attributes.antialias ? 4 : 0; | |
765 const int sample_buffers = attributes.antialias ? 1 : 0; | |
766 const int32 attribs[] = { | |
767 GLInProcessContext::ALPHA_SIZE, alpha_size, | |
768 GLInProcessContext::DEPTH_SIZE, depth_size, | |
769 GLInProcessContext::STENCIL_SIZE, stencil_size, | |
770 GLInProcessContext::SAMPLES, samples, | |
771 GLInProcessContext::SAMPLE_BUFFERS, sample_buffers, | |
772 GLInProcessContext::NONE, | |
773 }; | |
774 | |
775 const char* preferred_extensions = attributes.noExtensions ? | |
776 kWebGLPreferredGLExtensions : "*"; | |
777 | |
778 GURL active_url; | |
779 if (web_view && web_view->mainFrame()) | |
780 active_url = GURL(web_view->mainFrame()->url()); | |
781 | |
782 GLInProcessContext* parent_context = NULL; | |
783 if (!render_directly_to_web_view) { | |
784 WebKit::WebGraphicsContext3D* view_context = | |
785 web_view->graphicsContext3D(); | |
786 if (view_context) { | |
787 WebGraphicsContext3DInProcessCommandBufferImpl* context_impl = | |
788 static_cast<WebGraphicsContext3DInProcessCommandBufferImpl*>( | |
789 view_context); | |
790 parent_context = context_impl->context_; | |
791 } else { | |
792 NOTREACHED() << "no parent context."; | |
793 } | |
794 } | |
795 | |
796 context_ = GLInProcessContext::CreateOffscreenContext( | |
797 parent_context, | |
798 gfx::Size(1, 1), | |
799 preferred_extensions, | |
800 attribs, | |
801 active_url); | |
802 web_view_ = NULL; | |
803 | |
804 if (!context_) | |
107 return false; | 805 return false; |
108 gfx::BindSkiaToInProcessGL(); | 806 |
109 | 807 gl_ = context_->GetImplementation(); |
110 render_directly_to_web_view_ = render_directly_to_web_view; | 808 context_->SetContextLostCallback( |
111 gfx::GLContext* share_context = 0; | 809 NewCallback( |
112 | 810 this, |
113 if (!render_directly_to_web_view) { | 811 &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost)); |
114 // Pick up the compositor's context to share resources with. | 812 |
115 WebGraphicsContext3D* view_context = webView->graphicsContext3D(); | 813 // Set attributes_ from created offscreen context. |
116 if (view_context) { | 814 { |
117 WebGraphicsContext3DInProcessCommandBufferImpl* contextImpl = | 815 attributes_ = attributes; |
118 static_cast<WebGraphicsContext3DInProcessCommandBufferImpl*>(view_cont ext); | 816 GLint alpha_bits = 0; |
119 share_context = contextImpl->gl_context_.get(); | 817 getIntegerv(GL_ALPHA_BITS, &alpha_bits); |
120 } else { | 818 attributes_.alpha = alpha_bits > 0; |
121 // The compositor's context didn't get created | 819 GLint depth_bits = 0; |
122 // successfully, so conceptually there is no way we can | 820 getIntegerv(GL_DEPTH_BITS, &depth_bits); |
123 // render successfully to the WebView. | 821 attributes_.depth = depth_bits > 0; |
124 render_directly_to_web_view_ = false; | 822 GLint stencil_bits = 0; |
125 } | 823 getIntegerv(GL_STENCIL_BITS, &stencil_bits); |
126 } | 824 attributes_.stencil = stencil_bits > 0; |
127 | 825 GLint samples = 0; |
128 is_gles2_ = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | 826 getIntegerv(GL_SAMPLES, &samples); |
129 | 827 attributes_.antialias = samples > 0; |
130 // This implementation always renders offscreen regardless of | 828 } |
131 // whether render_directly_to_web_view is true. Both DumpRenderTree | 829 makeContextCurrent(); |
132 // and test_shell paint first to an intermediate offscreen buffer | 830 |
133 // and from there to the window, and WebViewImpl::paint already | |
134 // correctly handles the case where the compositor is active but | |
135 // the output needs to go to a WebCanvas. | |
136 gl_surface_.reset(gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1))); | |
137 | |
138 if (!gl_surface_.get()) { | |
139 if (!is_gles2_) | |
140 return false; | |
141 | |
142 // Embedded systems have smaller limit on number of GL contexts. Sometimes | |
143 // failure of GL context creation is because of existing GL contexts | |
144 // referenced by JavaScript garbages. Collect garbage and try again. | |
145 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving | |
146 // a page unload event, iterate down any live WebGraphicsContext3D instances | |
147 // and force them to drop their contexts, sending a context lost event if | |
148 // necessary. | |
149 webView->mainFrame()->collectGarbage(); | |
150 | |
151 gl_surface_.reset(gfx::GLSurface::CreateOffscreenGLSurface( | |
152 gfx::Size(1, 1))); | |
153 if (!gl_surface_.get()) | |
154 return false; | |
155 } | |
156 | |
157 gl_context_.reset(gfx::GLContext::CreateGLContext(share_context, | |
158 gl_surface_.get())); | |
159 if (!gl_context_.get()) { | |
160 if (!is_gles2_) | |
161 return false; | |
162 | |
163 // Embedded systems have smaller limit on number of GL contexts. Sometimes | |
164 // failure of GL context creation is because of existing GL contexts | |
165 // referenced by JavaScript garbages. Collect garbage and try again. | |
166 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving | |
167 // a page unload event, iterate down any live WebGraphicsContext3D instances | |
168 // and force them to drop their contexts, sending a context lost event if | |
169 // necessary. | |
170 webView->mainFrame()->collectGarbage(); | |
171 | |
172 gl_context_.reset(gfx::GLContext::CreateGLContext(share_context, | |
173 gl_surface_.get())); | |
174 if (!gl_context_.get()) | |
175 return false; | |
176 } | |
177 | |
178 attributes_ = attributes; | |
179 | |
180 // FIXME: for the moment we disable multisampling for the compositor. | |
181 // It actually works in this implementation, but there are a few | |
182 // considerations. First, we likely want to reduce the fuzziness in | |
183 // these tests as much as possible because we want to run pixel tests. | |
184 // Second, Mesa's multisampling doesn't seem to antialias straight | |
185 // edges in some CSS 3D samples. Third, we don't have multisampling | |
186 // support for the compositor in the normal case at the time of this | |
187 // writing. | |
188 if (render_directly_to_web_view) | |
189 attributes_.antialias = false; | |
190 | |
191 if (!gl_context_->MakeCurrent(gl_surface_.get())) { | |
192 gl_context_.reset(); | |
193 return false; | |
194 } | |
195 | |
196 const char* extensions = | |
197 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); | |
198 DCHECK(extensions); | |
199 have_ext_framebuffer_object_ = | |
200 strstr(extensions, "GL_EXT_framebuffer_object") != NULL; | |
201 have_ext_framebuffer_multisample_ = | |
202 strstr(extensions, "GL_EXT_framebuffer_multisample") != NULL; | |
203 have_angle_framebuffer_multisample_ = | |
204 strstr(extensions, "GL_ANGLE_framebuffer_multisample") != NULL; | |
205 | |
206 ValidateAttributes(); | |
207 | |
208 if (!is_gles2_) { | |
209 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); | |
210 glEnable(GL_POINT_SPRITE); | |
211 } | |
212 | |
213 if (!AngleCreateCompilers()) { | |
214 AngleDestroyCompilers(); | |
215 return false; | |
216 } | |
217 | |
218 glGenFramebuffersEXT(1, ©_texture_to_parent_texture_fbo_); | |
219 | |
220 initialized_ = true; | |
221 return true; | 831 return true; |
222 } | 832 } |
223 | 833 |
224 void WebGraphicsContext3DInProcessCommandBufferImpl::ValidateAttributes() { | |
225 const char* extensions = | |
226 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); | |
227 | |
228 if (attributes_.stencil) { | |
229 if (strstr(extensions, "GL_OES_packed_depth_stencil") || | |
230 strstr(extensions, "GL_EXT_packed_depth_stencil")) { | |
231 if (!attributes_.depth) { | |
232 attributes_.depth = true; | |
233 } | |
234 } else { | |
235 attributes_.stencil = false; | |
236 } | |
237 } | |
238 if (attributes_.antialias) { | |
239 bool isValidVendor = true; | |
240 #if defined(OS_MACOSX) | |
241 // Currently in Mac we only turn on antialias if vendor is NVIDIA. | |
242 const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | |
243 if (!strstr(vendor, "NVIDIA")) | |
244 isValidVendor = false; | |
245 #endif | |
246 if (!(isValidVendor && | |
247 (have_ext_framebuffer_multisample_ || | |
248 (have_angle_framebuffer_multisample_ && | |
249 strstr(extensions, "GL_OES_rgb8_rgba8"))))) | |
250 attributes_.antialias = false; | |
251 | |
252 // Don't antialias when using Mesa to ensure more reliable testing and | |
253 // because it doesn't appear to multisample straight lines correctly. | |
254 const char* renderer = | |
255 reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | |
256 if (!strncmp(renderer, "Mesa", 4)) { | |
257 attributes_.antialias = false; | |
258 } | |
259 } | |
260 } | |
261 | |
262 void WebGraphicsContext3DInProcessCommandBufferImpl::ResolveMultisampledFramebuf fer( | |
263 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { | |
264 if (attributes_.antialias) { | |
265 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fbo_); | |
266 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_); | |
267 if (have_ext_framebuffer_multisample_) { | |
268 glBlitFramebufferEXT(x, y, | |
269 x + width, y + height, | |
270 x, y, | |
271 x + width, y + height, | |
272 GL_COLOR_BUFFER_BIT, GL_NEAREST); | |
273 } else { | |
274 DCHECK(have_angle_framebuffer_multisample_); | |
275 glBlitFramebufferANGLE(x, y, | |
276 x + width, y + height, | |
277 x, y, | |
278 x + width, y + height, | |
279 GL_COLOR_BUFFER_BIT, GL_NEAREST); | |
280 } | |
281 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
282 } | |
283 } | |
284 | |
285 bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { | 834 bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { |
286 return gl_context_->MakeCurrent(gl_surface_.get()); | 835 return GLInProcessContext::MakeCurrent(context_); |
836 } | |
837 | |
838 void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() { | |
839 // Comment the next line in to help find missing MakeCurrent calls | |
840 // in code not going through WebGraphicsContext3D. | |
841 // GLInProcessContext::MakeCurrent(NULL); | |
jamesr
2011/06/01 02:07:02
comment and code are out of sync
greggman
2011/06/01 21:55:39
I updated the comment though it still says basical
| |
287 } | 842 } |
288 | 843 |
289 int WebGraphicsContext3DInProcessCommandBufferImpl::width() { | 844 int WebGraphicsContext3DInProcessCommandBufferImpl::width() { |
290 return cached_width_; | 845 return cached_width_; |
291 } | 846 } |
292 | 847 |
293 int WebGraphicsContext3DInProcessCommandBufferImpl::height() { | 848 int WebGraphicsContext3DInProcessCommandBufferImpl::height() { |
294 return cached_height_; | 849 return cached_height_; |
295 } | 850 } |
296 | 851 |
297 bool WebGraphicsContext3DInProcessCommandBufferImpl::isGLES2Compliant() { | 852 bool WebGraphicsContext3DInProcessCommandBufferImpl::isGLES2Compliant() { |
298 return is_gles2_; | 853 return true; |
299 } | 854 } |
300 | 855 |
301 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::getPlatformTextureId() { | 856 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::getPlatformTextureId() { |
302 return texture_; | 857 DCHECK(context_); |
858 return context_->GetParentTextureId(); | |
303 } | 859 } |
304 | 860 |
305 void WebGraphicsContext3DInProcessCommandBufferImpl::prepareTexture() { | 861 void WebGraphicsContext3DInProcessCommandBufferImpl::prepareTexture() { |
306 if (!render_directly_to_web_view_) { | 862 // Copies the contents of the off-screen render target into the texture |
307 // We need to prepare our rendering results for the compositor. | 863 // used by the compositor. |
308 makeContextCurrent(); | 864 context_->SwapBuffers(); |
309 ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); | 865 } |
310 } | 866 |
311 } | 867 void WebGraphicsContext3DInProcessCommandBufferImpl::reshape( |
312 | 868 int width, int height) { |
313 namespace { | |
314 | |
315 int CreateTextureObject(GLenum target) { | |
316 GLuint texture = 0; | |
317 glGenTextures(1, &texture); | |
318 glBindTexture(target, texture); | |
319 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
320 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
321 return texture; | |
322 } | |
323 | |
324 } // anonymous namespace | |
325 | |
326 void WebGraphicsContext3DInProcessCommandBufferImpl::reshape(int width, int heig ht) { | |
327 cached_width_ = width; | 869 cached_width_ = width; |
328 cached_height_ = height; | 870 cached_height_ = height; |
329 makeContextCurrent(); | 871 |
330 | 872 ClearContext(); |
331 GLenum target = GL_TEXTURE_2D; | 873 |
332 | 874 if (web_view_) { |
333 if (!texture_) { | 875 #if defined(OS_MACOSX) |
334 // Generate the texture object | 876 context_->ResizeOnscreen(gfx::Size(width, height)); |
335 texture_ = CreateTextureObject(target); | 877 #else |
336 // Generate the framebuffer object | 878 gl_->ResizeCHROMIUM(width, height); |
337 glGenFramebuffersEXT(1, &fbo_); | 879 #endif |
338 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
339 bound_fbo_ = fbo_; | |
340 if (attributes_.depth || attributes_.stencil) | |
341 glGenRenderbuffersEXT(1, &depth_stencil_buffer_); | |
342 // Generate the multisample framebuffer object | |
343 if (attributes_.antialias) { | |
344 glGenFramebuffersEXT(1, &multisample_fbo_); | |
345 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); | |
346 bound_fbo_ = multisample_fbo_; | |
347 glGenRenderbuffersEXT(1, &multisample_color_buffer_); | |
348 if (attributes_.depth || attributes_.stencil) | |
349 glGenRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); | |
350 } | |
351 } | |
352 | |
353 GLint internal_multisampled_color_format = 0; | |
354 GLint internal_color_format = 0; | |
355 GLint color_format = 0; | |
356 GLint internal_depth_stencil_format = 0; | |
357 if (attributes_.alpha) { | |
358 // GL_RGBA8_OES == GL_RGBA8 | |
359 internal_multisampled_color_format = GL_RGBA8; | |
360 internal_color_format = is_gles2_ ? GL_RGBA : GL_RGBA8; | |
361 color_format = GL_RGBA; | |
362 } else { | 880 } else { |
363 // GL_RGB8_OES == GL_RGB8 | 881 context_->ResizeOffscreen(gfx::Size(width, height)); |
364 internal_multisampled_color_format = GL_RGB8; | 882 // Force a SwapBuffers to get the framebuffer to resize. |
365 internal_color_format = is_gles2_ ? GL_RGB : GL_RGB8; | 883 context_->SwapBuffers(); |
366 color_format = GL_RGB; | 884 } |
367 } | |
368 if (attributes_.stencil || attributes_.depth) { | |
369 // We don't allow the logic where stencil is required and depth is not. | |
370 // See GraphicsContext3DInternal constructor. | |
371 if (attributes_.stencil && attributes_.depth) { | |
372 internal_depth_stencil_format = GL_DEPTH24_STENCIL8_EXT; | |
373 } else { | |
374 if (is_gles2_) | |
375 internal_depth_stencil_format = GL_DEPTH_COMPONENT16; | |
376 else | |
377 internal_depth_stencil_format = GL_DEPTH_COMPONENT; | |
378 } | |
379 } | |
380 | |
381 bool must_restore_fbo = false; | |
382 | |
383 // Resize multisampling FBO | |
384 if (attributes_.antialias) { | |
385 GLint max_sample_count; | |
386 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); | |
387 GLint sample_count = std::min(8, max_sample_count); | |
388 if (bound_fbo_ != multisample_fbo_) { | |
389 must_restore_fbo = true; | |
390 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); | |
391 } | |
392 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, multisample_color_buffer_); | |
393 if (have_ext_framebuffer_multisample_) { | |
394 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, | |
395 sample_count, | |
396 internal_multisampled_color_format, | |
397 width, | |
398 height); | |
399 } else { | |
400 DCHECK(have_angle_framebuffer_multisample_); | |
401 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT, | |
402 sample_count, | |
403 internal_multisampled_color_format, | |
404 width, | |
405 height); | |
406 } | |
407 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
408 GL_COLOR_ATTACHMENT0_EXT, | |
409 GL_RENDERBUFFER_EXT, | |
410 multisample_color_buffer_); | |
411 if (attributes_.stencil || attributes_.depth) { | |
412 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, | |
413 multisample_depth_stencil_buffer_); | |
414 if (have_ext_framebuffer_multisample_) { | |
415 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, | |
416 sample_count, | |
417 internal_depth_stencil_format, | |
418 width, | |
419 height); | |
420 } else { | |
421 DCHECK(have_angle_framebuffer_multisample_); | |
422 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT, | |
423 sample_count, | |
424 internal_depth_stencil_format, | |
425 width, | |
426 height); | |
427 } | |
428 if (attributes_.stencil) | |
429 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
430 GL_STENCIL_ATTACHMENT_EXT, | |
431 GL_RENDERBUFFER_EXT, | |
432 multisample_depth_stencil_buffer_); | |
433 if (attributes_.depth) | |
434 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
435 GL_DEPTH_ATTACHMENT_EXT, | |
436 GL_RENDERBUFFER_EXT, | |
437 multisample_depth_stencil_buffer_); | |
438 } | |
439 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); | |
440 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | |
441 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { | |
442 LOG(ERROR) << "Multisampling framebuffer was incomplete"; | |
443 | |
444 // FIXME: cleanup. | |
445 NOTIMPLEMENTED(); | |
446 } | |
447 } | |
448 | |
449 // Resize regular FBO | |
450 if (bound_fbo_ != fbo_) { | |
451 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
452 must_restore_fbo = true; | |
453 } | |
454 glBindTexture(target, texture_); | |
455 glTexImage2D(target, 0, internal_color_format, | |
456 width, height, | |
457 0, color_format, GL_UNSIGNED_BYTE, 0); | |
458 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, | |
459 GL_COLOR_ATTACHMENT0_EXT, | |
460 target, | |
461 texture_, | |
462 0); | |
463 glBindTexture(target, 0); | |
464 if (!attributes_.antialias && (attributes_.stencil || attributes_.depth)) { | |
465 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer_); | |
466 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, | |
467 internal_depth_stencil_format, | |
468 width, height); | |
469 if (attributes_.stencil) | |
470 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
471 GL_STENCIL_ATTACHMENT_EXT, | |
472 GL_RENDERBUFFER_EXT, | |
473 depth_stencil_buffer_); | |
474 if (attributes_.depth) | |
475 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
476 GL_DEPTH_ATTACHMENT_EXT, | |
477 GL_RENDERBUFFER_EXT, | |
478 depth_stencil_buffer_); | |
479 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); | |
480 } | |
481 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | |
482 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { | |
483 LOG(ERROR) << "Framebuffer was incomplete"; | |
484 | |
485 // FIXME: cleanup. | |
486 NOTIMPLEMENTED(); | |
487 } | |
488 | |
489 if (attributes_.antialias) { | |
490 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); | |
491 if (bound_fbo_ == multisample_fbo_) | |
492 must_restore_fbo = false; | |
493 } | |
494 | |
495 // Initialize renderbuffers to 0. | |
496 GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0; | |
497 GLint clearStencil = 0; | |
498 GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; | |
499 GLboolean depthMask = GL_TRUE; | |
500 GLuint stencilMask = 0xffffffff; | |
501 GLboolean isScissorEnabled = GL_FALSE; | |
502 GLboolean isDitherEnabled = GL_FALSE; | |
503 GLbitfield clearMask = GL_COLOR_BUFFER_BIT; | |
504 glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); | |
505 glClearColor(0, 0, 0, 0); | |
506 glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); | |
507 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
508 if (attributes_.depth) { | |
509 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); | |
510 glClearDepth(1); | |
511 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); | |
512 glDepthMask(GL_TRUE); | |
513 clearMask |= GL_DEPTH_BUFFER_BIT; | |
514 } | |
515 if (attributes_.stencil) { | |
516 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil); | |
517 glClearStencil(0); | |
518 glGetIntegerv(GL_STENCIL_WRITEMASK, | |
519 reinterpret_cast<GLint*>(&stencilMask)); | |
520 glStencilMaskSeparate(GL_FRONT, 0xffffffff); | |
521 clearMask |= GL_STENCIL_BUFFER_BIT; | |
522 } | |
523 isScissorEnabled = glIsEnabled(GL_SCISSOR_TEST); | |
524 glDisable(GL_SCISSOR_TEST); | |
525 isDitherEnabled = glIsEnabled(GL_DITHER); | |
526 glDisable(GL_DITHER); | |
527 | |
528 glClear(clearMask); | |
529 | |
530 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); | |
531 glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); | |
532 if (attributes_.depth) { | |
533 glClearDepth(clearDepth); | |
534 glDepthMask(depthMask); | |
535 } | |
536 if (attributes_.stencil) { | |
537 glClearStencil(clearStencil); | |
538 glStencilMaskSeparate(GL_FRONT, stencilMask); | |
539 } | |
540 if (isScissorEnabled) | |
541 glEnable(GL_SCISSOR_TEST); | |
542 else | |
543 glDisable(GL_SCISSOR_TEST); | |
544 if (isDitherEnabled) | |
545 glEnable(GL_DITHER); | |
546 else | |
547 glDisable(GL_DITHER); | |
548 | |
549 if (must_restore_fbo) | |
550 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
551 | 885 |
552 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 886 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
553 if (scanline_) { | 887 scanline_.reset(new uint8[width * 4]); |
554 delete[] scanline_; | |
555 scanline_ = 0; | |
556 } | |
557 scanline_ = new unsigned char[width * 4]; | |
558 #endif // FLIP_FRAMEBUFFER_VERTICALLY | 888 #endif // FLIP_FRAMEBUFFER_VERTICALLY |
559 } | 889 } |
560 | 890 |
891 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createCompositorTexture( | |
892 WGC3Dsizei width, WGC3Dsizei height) { | |
893 ClearContext(); | |
894 return context_->CreateParentTexture(gfx::Size(width, height)); | |
895 } | |
896 | |
897 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteCompositorTexture( | |
898 WebGLId parent_texture) { | |
899 ClearContext(); | |
900 context_->DeleteParentTexture(parent_texture); | |
901 } | |
902 | |
561 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 903 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
562 void WebGraphicsContext3DInProcessCommandBufferImpl::FlipVertically( | 904 void WebGraphicsContext3DInProcessCommandBufferImpl::FlipVertically( |
563 unsigned char* framebuffer, unsigned int width, unsigned int height) { | 905 uint8* framebuffer, |
564 unsigned char* scanline = scanline_; | 906 unsigned int width, |
907 unsigned int height) { | |
908 uint8* scanline = scanline_.get(); | |
565 if (!scanline) | 909 if (!scanline) |
566 return; | 910 return; |
567 unsigned int row_bytes = width * 4; | 911 unsigned int row_bytes = width * 4; |
568 unsigned int count = height / 2; | 912 unsigned int count = height / 2; |
569 for (unsigned int i = 0; i < count; i++) { | 913 for (unsigned int i = 0; i < count; i++) { |
570 unsigned char* row_a = framebuffer + i * row_bytes; | 914 uint8* row_a = framebuffer + i * row_bytes; |
571 unsigned char* row_b = framebuffer + (height - i - 1) * row_bytes; | 915 uint8* row_b = framebuffer + (height - i - 1) * row_bytes; |
572 // FIXME: this is where the multiplication of the alpha | 916 // TODO(kbr): this is where the multiplication of the alpha |
573 // channel into the color buffer will need to occur if the | 917 // channel into the color buffer will need to occur if the |
574 // user specifies the "premultiplyAlpha" flag in the context | 918 // user specifies the "premultiplyAlpha" flag in the context |
575 // creation attributes. | 919 // creation attributes. |
576 memcpy(scanline, row_b, row_bytes); | 920 memcpy(scanline, row_b, row_bytes); |
577 memcpy(row_b, row_a, row_bytes); | 921 memcpy(row_b, row_a, row_bytes); |
578 memcpy(row_a, scanline, row_bytes); | 922 memcpy(row_a, scanline, row_bytes); |
579 } | 923 } |
580 } | 924 } |
581 #endif | 925 #endif |
582 | 926 |
583 bool WebGraphicsContext3DInProcessCommandBufferImpl::readBackFramebuffer( | 927 bool WebGraphicsContext3DInProcessCommandBufferImpl::readBackFramebuffer( |
584 unsigned char* pixels, size_t bufferSize) { | 928 unsigned char* pixels, |
585 if (bufferSize != static_cast<size_t>(4 * width() * height())) | 929 size_t buffer_size) { |
930 ClearContext(); | |
931 if (buffer_size != static_cast<size_t>(4 * width() * height())) { | |
586 return false; | 932 return false; |
587 | 933 } |
588 makeContextCurrent(); | |
589 | 934 |
590 // Earlier versions of this code used the GPU to flip the | 935 // Earlier versions of this code used the GPU to flip the |
591 // framebuffer vertically before reading it back for compositing | 936 // framebuffer vertically before reading it back for compositing |
592 // via software. This code was quite complicated, used a lot of | 937 // via software. This code was quite complicated, used a lot of |
593 // GPU memory, and didn't provide an obvious speedup. Since this | 938 // GPU memory, and didn't provide an obvious speedup. Since this |
594 // vertical flip is only a temporary solution anyway until Chrome | 939 // vertical flip is only a temporary solution anyway until Chrome |
595 // is fully GPU composited, it wasn't worth the complexity. | 940 // is fully GPU composited, it wasn't worth the complexity. |
596 | 941 |
597 ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); | 942 bool mustRestoreFBO = (bound_fbo_ != 0); |
598 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | 943 if (mustRestoreFBO) { |
599 | 944 gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); |
600 GLint pack_alignment = 4; | 945 } |
601 bool must_restore_pack_alignment = false; | 946 gl_->ReadPixels(0, 0, cached_width_, cached_height_, |
602 glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); | 947 GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
603 if (pack_alignment > 4) { | 948 |
604 glPixelStorei(GL_PACK_ALIGNMENT, 4); | 949 // Swizzle red and blue channels |
605 must_restore_pack_alignment = true; | 950 // TODO(kbr): expose GL_BGRA as extension |
606 } | 951 for (size_t i = 0; i < buffer_size; i += 4) { |
607 | 952 std::swap(pixels[i], pixels[i + 2]); |
608 if (is_gles2_) { | 953 } |
609 // FIXME: consider testing for presence of GL_OES_read_format | 954 |
610 // and GL_EXT_read_format_bgra, and using GL_BGRA_EXT here | 955 if (mustRestoreFBO) { |
611 // directly. | 956 gl_->BindFramebuffer(GL_FRAMEBUFFER, bound_fbo_); |
612 glReadPixels(0, 0, cached_width_, cached_height_, | 957 } |
613 GL_RGBA, GL_UNSIGNED_BYTE, pixels); | |
614 for (size_t i = 0; i < bufferSize; i += 4) { | |
615 std::swap(pixels[i], pixels[i + 2]); | |
616 } | |
617 } else { | |
618 glReadPixels(0, 0, cached_width_, cached_height_, | |
619 GL_BGRA, GL_UNSIGNED_BYTE, pixels); | |
620 } | |
621 | |
622 if (must_restore_pack_alignment) | |
623 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); | |
624 | |
625 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
626 | 958 |
627 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 959 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
628 if (pixels) | 960 if (pixels) { |
629 FlipVertically(pixels, cached_width_, cached_height_); | 961 FlipVertically(pixels, cached_width_, cached_height_); |
962 } | |
630 #endif | 963 #endif |
631 | 964 |
632 return true; | 965 return true; |
633 } | 966 } |
634 | 967 |
635 void WebGraphicsContext3DInProcessCommandBufferImpl::synthesizeGLError(WGC3Denum error) { | 968 void WebGraphicsContext3DInProcessCommandBufferImpl::synthesizeGLError( |
636 if (synthetic_errors_set_.find(error) == synthetic_errors_set_.end()) { | 969 WGC3Denum error) { |
637 synthetic_errors_set_.insert(error); | 970 if (find(synthetic_errors_.begin(), synthetic_errors_.end(), error) == |
638 synthetic_errors_list_.push_back(error); | 971 synthetic_errors_.end()) { |
972 synthetic_errors_.push_back(error); | |
639 } | 973 } |
640 } | 974 } |
641 | 975 |
642 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapBufferSubDataCHROMIUM( | 976 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapBufferSubDataCHROMIUM( |
643 WGC3Denum target, WGC3Dintptr offset, | 977 WGC3Denum target, |
644 WGC3Dsizeiptr size, WGC3Denum access) { | 978 WGC3Dintptr offset, |
645 return 0; | 979 WGC3Dsizeiptr size, |
980 WGC3Denum access) { | |
981 ClearContext(); | |
982 return gl_->MapBufferSubDataCHROMIUM(target, offset, size, access); | |
646 } | 983 } |
647 | 984 |
648 void WebGraphicsContext3DInProcessCommandBufferImpl::unmapBufferSubDataCHROMIUM( | 985 void WebGraphicsContext3DInProcessCommandBufferImpl::unmapBufferSubDataCHROMIUM( |
649 const void* mem) { | 986 const void* mem) { |
987 ClearContext(); | |
988 return gl_->UnmapBufferSubDataCHROMIUM(mem); | |
650 } | 989 } |
651 | 990 |
652 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapTexSubImage2DCHROMIUM( | 991 void* WebGraphicsContext3DInProcessCommandBufferImpl::mapTexSubImage2DCHROMIUM( |
653 WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, | 992 WGC3Denum target, |
654 WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3Denum type, | 993 WGC3Dint level, |
994 WGC3Dint xoffset, | |
995 WGC3Dint yoffset, | |
996 WGC3Dsizei width, | |
997 WGC3Dsizei height, | |
998 WGC3Denum format, | |
999 WGC3Denum type, | |
655 WGC3Denum access) { | 1000 WGC3Denum access) { |
656 return 0; | 1001 ClearContext(); |
1002 return gl_->MapTexSubImage2DCHROMIUM( | |
1003 target, level, xoffset, yoffset, width, height, format, type, access); | |
657 } | 1004 } |
658 | 1005 |
659 void WebGraphicsContext3DInProcessCommandBufferImpl::unmapTexSubImage2DCHROMIUM( | 1006 void WebGraphicsContext3DInProcessCommandBufferImpl::unmapTexSubImage2DCHROMIUM( |
660 const void* mem) { | 1007 const void* mem) { |
1008 ClearContext(); | |
1009 gl_->UnmapTexSubImage2DCHROMIUM(mem); | |
661 } | 1010 } |
662 | 1011 |
663 void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToParentTextureC HROMIUM( | 1012 void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToParentTextureC HROMIUM( |
664 WebGLId id, WebGLId id2) { | 1013 WebGLId texture, WebGLId parentTexture) { |
665 if (!glGetTexLevelParameteriv) | 1014 ClearContext(); |
666 return; | 1015 copyTextureToCompositor(texture, parentTexture); |
667 | |
668 makeContextCurrent(); | |
669 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, copy_texture_to_parent_texture_fbo_); | |
670 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | |
671 GL_COLOR_ATTACHMENT0, | |
672 GL_TEXTURE_2D, | |
673 id, | |
674 0); // level | |
675 glBindTexture(GL_TEXTURE_2D, id2); | |
676 GLsizei width, height; | |
677 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); | |
678 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); | |
679 glCopyTexImage2D(GL_TEXTURE_2D, | |
680 0, // level | |
681 GL_RGBA, | |
682 0, 0, // x, y | |
683 width, | |
684 height, | |
685 0); // border | |
686 glBindTexture(GL_TEXTURE_2D, bound_texture_); | |
687 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
688 } | 1016 } |
689 | 1017 |
690 void WebGraphicsContext3DInProcessCommandBufferImpl::getParentToChildLatchCHROMI UM( | 1018 void WebGraphicsContext3DInProcessCommandBufferImpl::getParentToChildLatchCHROMI UM( |
691 WGC3Duint* latch_id) | 1019 WGC3Duint* latch_id) |
692 { | 1020 { |
1021 ClearContext(); | |
1022 if (!context_->GetParentToChildLatch(latch_id)) { | |
1023 LOG(ERROR) << "getLatch must only be called on child context"; | |
1024 synthesizeGLError(GL_INVALID_OPERATION); | |
1025 *latch_id = ::gpu::kInvalidLatchId; | |
1026 } | |
693 } | 1027 } |
694 | 1028 |
695 void WebGraphicsContext3DInProcessCommandBufferImpl::getChildToParentLatchCHROMI UM( | 1029 void WebGraphicsContext3DInProcessCommandBufferImpl::getChildToParentLatchCHROMI UM( |
696 WGC3Duint* latch_id) | 1030 WGC3Duint* latch_id) |
697 { | 1031 { |
1032 ClearContext(); | |
1033 if (!context_->GetChildToParentLatch(latch_id)) { | |
1034 LOG(ERROR) << "getLatch must only be called on child context"; | |
1035 synthesizeGLError(GL_INVALID_OPERATION); | |
1036 *latch_id = ::gpu::kInvalidLatchId; | |
1037 } | |
698 } | 1038 } |
699 | 1039 |
700 void WebGraphicsContext3DInProcessCommandBufferImpl::waitLatchCHROMIUM( | 1040 void WebGraphicsContext3DInProcessCommandBufferImpl::waitLatchCHROMIUM( |
701 WGC3Duint latch_id) | 1041 WGC3Duint latch_id) |
702 { | 1042 { |
1043 ClearContext(); | |
1044 gl_->WaitLatchCHROMIUM(latch_id); | |
703 } | 1045 } |
704 | 1046 |
705 void WebGraphicsContext3DInProcessCommandBufferImpl::setLatchCHROMIUM( | 1047 void WebGraphicsContext3DInProcessCommandBufferImpl::setLatchCHROMIUM( |
706 WGC3Duint latch_id) | 1048 WGC3Duint latch_id) |
707 { | 1049 { |
708 } | 1050 ClearContext(); |
709 | 1051 gl_->SetLatchCHROMIUM(latch_id); |
710 WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | 1052 // required to ensure set command is sent to GPU process |
1053 gl_->Flush(); | |
1054 } | |
1055 | |
1056 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1057 rateLimitOffscreenContextCHROMIUM() { | |
1058 ClearContext(); | |
1059 gl_->RateLimitOffscreenContextCHROMIUM(); | |
1060 } | |
1061 | |
1062 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: | |
711 getRequestableExtensionsCHROMIUM() { | 1063 getRequestableExtensionsCHROMIUM() { |
712 return WebString(); | 1064 ClearContext(); |
713 } | 1065 return WebKit::WebString::fromUTF8( |
714 | 1066 gl_->GetRequestableExtensionsCHROMIUM()); |
715 void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM(co nst char*) { | 1067 } |
1068 | |
1069 void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM( | |
1070 const char* extension) { | |
1071 ClearContext(); | |
1072 gl_->RequestExtensionCHROMIUM(extension); | |
716 } | 1073 } |
717 | 1074 |
718 void WebGraphicsContext3DInProcessCommandBufferImpl::blitFramebufferCHROMIUM( | 1075 void WebGraphicsContext3DInProcessCommandBufferImpl::blitFramebufferCHROMIUM( |
719 WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, | 1076 WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, |
720 WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, | 1077 WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, |
721 WGC3Dbitfield mask, WGC3Denum filter) { | 1078 WGC3Dbitfield mask, WGC3Denum filter) { |
722 } | 1079 ClearContext(); |
723 | 1080 gl_->BlitFramebufferEXT( |
724 void WebGraphicsContext3DInProcessCommandBufferImpl::renderbufferStorageMultisam pleCHROMIUM( | 1081 srcX0, srcY0, srcX1, srcY1, |
725 WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, | 1082 dstX0, dstY0, dstX1, dstY1, |
726 WGC3Dsizei width, WGC3Dsizei height) { | 1083 mask, filter); |
1084 } | |
1085 | |
1086 void WebGraphicsContext3DInProcessCommandBufferImpl:: | |
1087 renderbufferStorageMultisampleCHROMIUM( | |
1088 WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, | |
1089 WGC3Dsizei width, WGC3Dsizei height) { | |
1090 ClearContext(); | |
1091 gl_->RenderbufferStorageMultisampleEXT( | |
1092 target, samples, internalformat, width, height); | |
727 } | 1093 } |
728 | 1094 |
729 // Helper macros to reduce the amount of code. | 1095 // Helper macros to reduce the amount of code. |
730 | 1096 |
731 #define DELEGATE_TO_GL(name, glname) \ | 1097 #define DELEGATE_TO_GL(name, glname) \ |
732 void WebGraphicsContext3DInProcessCommandBufferImpl::name() { \ | 1098 void WebGraphicsContext3DInProcessCommandBufferImpl::name() { \ |
733 makeContextCurrent(); \ | 1099 ClearContext(); \ |
734 gl##glname(); \ | 1100 gl_->glname(); \ |
735 } | 1101 } |
736 | 1102 |
737 #define DELEGATE_TO_GL_1(name, glname, t1) \ | 1103 #define DELEGATE_TO_GL_1(name, glname, t1) \ |
738 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ | 1104 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
739 makeContextCurrent(); \ | 1105 ClearContext(); \ |
740 gl##glname(a1); \ | 1106 gl_->glname(a1); \ |
741 } | 1107 } |
742 | 1108 |
743 #define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ | 1109 #define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ |
744 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ | 1110 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
745 makeContextCurrent(); \ | 1111 ClearContext(); \ |
746 return gl##glname(a1); \ | 1112 return gl_->glname(a1); \ |
747 } | 1113 } |
748 | 1114 |
749 #define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ | 1115 #define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ |
750 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ | 1116 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
751 makeContextCurrent(); \ | 1117 ClearContext(); \ |
752 return gl##glname(a1) ? true : false; \ | 1118 return gl_->glname(a1) ? true : false; \ |
753 } | 1119 } |
754 | 1120 |
755 #define DELEGATE_TO_GL_2(name, glname, t1, t2) \ | 1121 #define DELEGATE_TO_GL_2(name, glname, t1, t2) \ |
756 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ | 1122 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
757 makeContextCurrent(); \ | 1123 t1 a1, t2 a2) { \ |
758 gl##glname(a1, a2); \ | 1124 ClearContext(); \ |
759 } | 1125 gl_->glname(a1, a2); \ |
760 | 1126 } |
761 #define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ | 1127 |
762 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ | 1128 #define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ |
763 makeContextCurrent(); \ | 1129 rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ |
764 return gl##glname(a1, a2); \ | 1130 ClearContext(); \ |
765 } | 1131 return gl_->glname(a1, a2); \ |
766 | 1132 } |
767 #define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ | 1133 |
768 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \ | 1134 #define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ |
769 makeContextCurrent(); \ | 1135 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
770 gl##glname(a1, a2, a3); \ | 1136 t1 a1, t2 a2, t3 a3) { \ |
771 } | 1137 ClearContext(); \ |
772 | 1138 gl_->glname(a1, a2, a3); \ |
773 #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ | 1139 } |
774 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t 4 a4) { \ | 1140 |
775 makeContextCurrent(); \ | 1141 #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ |
776 gl##glname(a1, a2, a3, a4); \ | 1142 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
777 } | 1143 t1 a1, t2 a2, t3 a3, t4 a4) { \ |
778 | 1144 ClearContext(); \ |
779 #define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ | 1145 gl_->glname(a1, a2, a3, a4); \ |
780 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t 4 a4, \ | 1146 } |
781 t5 a5) { \ | 1147 |
782 makeContextCurrent(); \ | 1148 #define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ |
783 gl##glname(a1, a2, a3, a4, a5); \ | 1149 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
784 } | 1150 t1 a1, t2 a2, t3 a3, \ |
785 | 1151 t4 a4, t5 a5) { \ |
786 #define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ | 1152 ClearContext(); \ |
787 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t 4 a4, \ | 1153 gl_->glname(a1, a2, a3, a4, a5); \ |
788 t5 a5, t6 a6) { \ | 1154 } |
789 makeContextCurrent(); \ | 1155 |
790 gl##glname(a1, a2, a3, a4, a5, a6); \ | 1156 #define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ |
791 } | 1157 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
792 | 1158 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \ |
793 #define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ | 1159 ClearContext(); \ |
794 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t 4 a4, \ | 1160 gl_->glname(a1, a2, a3, a4, a5, a6); \ |
795 t5 a5, t6 a6, t7 a7) { \ | 1161 } |
796 makeContextCurrent(); \ | 1162 |
797 gl##glname(a1, a2, a3, a4, a5, a6, a7); \ | 1163 #define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ |
798 } | 1164 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
799 | 1165 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) { \ |
800 #define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ | 1166 ClearContext(); \ |
801 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t 4 a4, \ | 1167 gl_->glname(a1, a2, a3, a4, a5, a6, a7); \ |
802 t5 a5, t6 a6, t7 a7, t8 a8) { \ | 1168 } |
803 makeContextCurrent(); \ | 1169 |
804 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8); \ | 1170 #define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ |
805 } | 1171 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
806 | 1172 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) { \ |
807 #define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ | 1173 ClearContext(); \ |
808 void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t 4 a4, \ | 1174 gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8); \ |
809 t5 a5, t6 a6, t7 a7, t8 a8, \ | 1175 } |
810 t9 a9) { \ | 1176 |
811 makeContextCurrent(); \ | 1177 #define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ |
812 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ | 1178 void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
813 } | 1179 t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) { \ |
814 | 1180 ClearContext(); \ |
815 void WebGraphicsContext3DInProcessCommandBufferImpl::activeTexture(WGC3Denum tex ture) { | 1181 gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ |
816 // FIXME: query number of textures available. | 1182 } |
817 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) | 1183 |
818 // FIXME: raise exception. | 1184 DELEGATE_TO_GL_1(activeTexture, ActiveTexture, WGC3Denum) |
819 return; | |
820 | |
821 makeContextCurrent(); | |
822 glActiveTexture(texture); | |
823 } | |
824 | 1185 |
825 DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) | 1186 DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) |
826 | 1187 |
827 DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, | 1188 DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, WebGLId, |
828 WebGLId, WGC3Duint, const WGC3Dchar*) | 1189 WGC3Duint, const WGC3Dchar*) |
829 | 1190 |
830 DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId); | 1191 DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId) |
831 | 1192 |
832 void WebGraphicsContext3DInProcessCommandBufferImpl::bindFramebuffer( | 1193 void WebGraphicsContext3DInProcessCommandBufferImpl::bindFramebuffer( |
833 WGC3Denum target, WebGLId framebuffer) { | 1194 WGC3Denum target, |
834 makeContextCurrent(); | 1195 WebGLId framebuffer) { |
835 if (!framebuffer) | 1196 ClearContext(); |
836 framebuffer = (attributes_.antialias ? multisample_fbo_ : fbo_); | 1197 gl_->BindFramebuffer(target, framebuffer); |
837 if (framebuffer != bound_fbo_) { | 1198 bound_fbo_ = framebuffer; |
838 glBindFramebufferEXT(target, framebuffer); | 1199 } |
839 bound_fbo_ = framebuffer; | 1200 |
840 } | 1201 DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbuffer, WGC3Denum, WebGLId) |
841 } | 1202 |
842 | 1203 DELEGATE_TO_GL_2(bindTexture, BindTexture, WGC3Denum, WebGLId) |
843 DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbufferEXT, WGC3Denum, WebGLId) | |
844 | |
845 void WebGraphicsContext3DInProcessCommandBufferImpl::bindTexture( | |
846 WGC3Denum target, WebGLId texture) { | |
847 makeContextCurrent(); | |
848 glBindTexture(target, texture); | |
849 bound_texture_ = texture; | |
850 } | |
851 | 1204 |
852 DELEGATE_TO_GL_4(blendColor, BlendColor, | 1205 DELEGATE_TO_GL_4(blendColor, BlendColor, |
853 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | 1206 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) |
854 | 1207 |
855 DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) | 1208 DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) |
856 | 1209 |
857 DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate, | 1210 DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate, |
858 WGC3Denum, WGC3Denum) | 1211 WGC3Denum, WGC3Denum) |
859 | 1212 |
860 DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum) | 1213 DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum) |
861 | 1214 |
862 DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate, | 1215 DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate, |
863 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | 1216 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) |
864 | 1217 |
865 DELEGATE_TO_GL_4(bufferData, BufferData, | 1218 DELEGATE_TO_GL_4(bufferData, BufferData, |
866 WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum) | 1219 WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum) |
867 | 1220 |
868 DELEGATE_TO_GL_4(bufferSubData, BufferSubData, | 1221 DELEGATE_TO_GL_4(bufferSubData, BufferSubData, |
869 WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) | 1222 WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) |
870 | 1223 |
871 DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatusEXT, | 1224 DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatus, |
872 WGC3Denum, WGC3Denum) | 1225 WGC3Denum, WGC3Denum) |
873 | 1226 |
874 DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) | 1227 DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) |
875 | 1228 |
876 DELEGATE_TO_GL_4(clearColor, ClearColor, | 1229 DELEGATE_TO_GL_4(clearColor, ClearColor, |
877 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) | 1230 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) |
878 | 1231 |
879 DELEGATE_TO_GL_1(clearDepth, ClearDepth, WGC3Dclampf) | 1232 DELEGATE_TO_GL_1(clearDepth, ClearDepthf, WGC3Dclampf) |
880 | 1233 |
881 DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) | 1234 DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) |
882 | 1235 |
883 DELEGATE_TO_GL_4(colorMask, ColorMask, | 1236 DELEGATE_TO_GL_4(colorMask, ColorMask, |
884 WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) | 1237 WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) |
885 | 1238 |
886 void WebGraphicsContext3DInProcessCommandBufferImpl::compileShader(WebGLId shade r) { | 1239 DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId) |
887 makeContextCurrent(); | |
888 | 1240 |
889 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | 1241 DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D, |
890 if (result == shader_source_map_.end()) { | 1242 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, |
891 // Passing down to gl driver to generate the correct error; or the case | 1243 WGC3Dsizei, WGC3Dsizei, WGC3Dint) |
892 // where the shader deletion is delayed when it's attached to a program. | |
893 glCompileShader(shader); | |
894 return; | |
895 } | |
896 ShaderSourceEntry* entry = result->second; | |
897 DCHECK(entry); | |
898 | 1244 |
899 if (!AngleValidateShaderSource(entry)) { | 1245 DELEGATE_TO_GL_8(copyTexSubImage2D, CopyTexSubImage2D, |
900 // Shader didn't validate; don't move forward with compiling | 1246 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, |
901 // translated source. | 1247 WGC3Dsizei, WGC3Dsizei) |
902 return; | |
903 } | |
904 | |
905 const char* translated_source = entry->translated_source.get(); | |
906 int shader_length = translated_source ? strlen(translated_source) : 0; | |
907 glShaderSource( | |
908 shader, 1, const_cast<const char**>(&translated_source), &shader_length); | |
909 glCompileShader(shader); | |
910 | |
911 #ifndef NDEBUG | |
912 int compileStatus; | |
913 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); | |
914 // DCHECK that ANGLE generated GLSL will be accepted by OpenGL | |
915 DCHECK(compileStatus == GL_TRUE); | |
916 #endif | |
917 } | |
918 | |
919 void WebGraphicsContext3DInProcessCommandBufferImpl::copyTexImage2D( | |
920 WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dint x, | |
921 WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border) { | |
922 makeContextCurrent(); | |
923 | |
924 bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
925 if (needsResolve) { | |
926 ResolveMultisampledFramebuffer(x, y, width, height); | |
927 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
928 } | |
929 | |
930 glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); | |
931 | |
932 if (needsResolve) | |
933 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
934 } | |
935 | |
936 void WebGraphicsContext3DInProcessCommandBufferImpl::copyTexSubImage2D( | |
937 WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, | |
938 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { | |
939 makeContextCurrent(); | |
940 | |
941 bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
942 if (needsResolve) { | |
943 ResolveMultisampledFramebuffer(x, y, width, height); | |
944 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
945 } | |
946 | |
947 glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); | |
948 | |
949 if (needsResolve) | |
950 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
951 } | |
952 | 1248 |
953 DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) | 1249 DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) |
954 | 1250 |
955 DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) | 1251 DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) |
956 | 1252 |
957 DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) | 1253 DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) |
958 | 1254 |
959 DELEGATE_TO_GL_2(depthRange, DepthRange, WGC3Dclampf, WGC3Dclampf) | 1255 DELEGATE_TO_GL_2(depthRange, DepthRangef, WGC3Dclampf, WGC3Dclampf) |
960 | 1256 |
961 DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) | 1257 DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) |
962 | 1258 |
963 DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) | 1259 DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) |
964 | 1260 |
965 DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, WGC3Duint) | 1261 DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, |
1262 WGC3Duint) | |
966 | 1263 |
967 DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) | 1264 DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) |
968 | 1265 |
969 void WebGraphicsContext3DInProcessCommandBufferImpl::drawElements( | 1266 void WebGraphicsContext3DInProcessCommandBufferImpl::drawElements( |
970 WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset) { | 1267 WGC3Denum mode, |
971 makeContextCurrent(); | 1268 WGC3Dsizei count, |
972 glDrawElements(mode, count, type, | 1269 WGC3Denum type, |
973 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | 1270 WGC3Dintptr offset) { |
1271 ClearContext(); | |
1272 gl_->DrawElements( | |
1273 mode, count, type, | |
1274 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
974 } | 1275 } |
975 | 1276 |
976 DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) | 1277 DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) |
977 | 1278 |
978 DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, WGC3Duint) | 1279 DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, |
1280 WGC3Duint) | |
979 | 1281 |
980 DELEGATE_TO_GL(finish, Finish) | 1282 DELEGATE_TO_GL(finish, Finish) |
981 | 1283 |
982 DELEGATE_TO_GL(flush, Flush) | 1284 DELEGATE_TO_GL(flush, Flush) |
983 | 1285 |
984 DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbufferEXT, | 1286 DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer, |
985 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) | 1287 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) |
986 | 1288 |
987 DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2DEXT, | 1289 DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D, |
988 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) | 1290 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) |
989 | 1291 |
990 DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) | 1292 DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) |
991 | 1293 |
992 void WebGraphicsContext3DInProcessCommandBufferImpl::generateMipmap(WGC3Denum ta rget) { | 1294 DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, WGC3Denum) |
993 makeContextCurrent(); | |
994 if (is_gles2_ || have_ext_framebuffer_object_) | |
995 glGenerateMipmapEXT(target); | |
996 // FIXME: provide alternative code path? This will be unpleasant | |
997 // to implement if glGenerateMipmapEXT is not available -- it will | |
998 // require a texture readback and re-upload. | |
999 } | |
1000 | 1295 |
1001 bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveAttrib( | 1296 bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveAttrib( |
1002 WebGLId program, WGC3Duint index, ActiveInfo& info) { | 1297 WebGLId program, WGC3Duint index, ActiveInfo& info) { |
1003 makeContextCurrent(); | 1298 ClearContext(); |
1004 if (!program) { | 1299 if (!program) { |
1005 synthesizeGLError(GL_INVALID_VALUE); | 1300 synthesizeGLError(GL_INVALID_VALUE); |
1006 return false; | 1301 return false; |
1007 } | 1302 } |
1008 GLint max_name_length = -1; | 1303 GLint max_name_length = -1; |
1009 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); | 1304 gl_->GetProgramiv( |
1305 program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); | |
1010 if (max_name_length < 0) | 1306 if (max_name_length < 0) |
1011 return false; | 1307 return false; |
1012 scoped_array<GLchar> name(new GLchar[max_name_length]); | 1308 scoped_array<GLchar> name(new GLchar[max_name_length]); |
1309 if (!name.get()) { | |
1310 synthesizeGLError(GL_OUT_OF_MEMORY); | |
1311 return false; | |
1312 } | |
1013 GLsizei length = 0; | 1313 GLsizei length = 0; |
1014 GLint size = -1; | 1314 GLint size = -1; |
1015 GLenum type = 0; | 1315 GLenum type = 0; |
1016 glGetActiveAttrib(program, index, max_name_length, | 1316 gl_->GetActiveAttrib( |
1017 &length, &size, &type, name.get()); | 1317 program, index, max_name_length, &length, &size, &type, name.get()); |
1018 if (size < 0) { | 1318 if (size < 0) { |
1019 return false; | 1319 return false; |
1020 } | 1320 } |
1021 info.name = WebString::fromUTF8(name.get(), length); | 1321 info.name = WebKit::WebString::fromUTF8(name.get(), length); |
1022 info.type = type; | 1322 info.type = type; |
1023 info.size = size; | 1323 info.size = size; |
1024 return true; | 1324 return true; |
1025 } | 1325 } |
1026 | 1326 |
1027 bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveUniform( | 1327 bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveUniform( |
1028 WebGLId program, WGC3Duint index, ActiveInfo& info) { | 1328 WebGLId program, WGC3Duint index, ActiveInfo& info) { |
1029 makeContextCurrent(); | 1329 ClearContext(); |
1030 GLint max_name_length = -1; | 1330 GLint max_name_length = -1; |
1031 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); | 1331 gl_->GetProgramiv( |
1332 program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); | |
1032 if (max_name_length < 0) | 1333 if (max_name_length < 0) |
1033 return false; | 1334 return false; |
1034 scoped_array<GLchar> name(new GLchar[max_name_length]); | 1335 scoped_array<GLchar> name(new GLchar[max_name_length]); |
1336 if (!name.get()) { | |
1337 synthesizeGLError(GL_OUT_OF_MEMORY); | |
1338 return false; | |
1339 } | |
1035 GLsizei length = 0; | 1340 GLsizei length = 0; |
1036 GLint size = -1; | 1341 GLint size = -1; |
1037 GLenum type = 0; | 1342 GLenum type = 0; |
1038 glGetActiveUniform(program, index, max_name_length, | 1343 gl_->GetActiveUniform( |
1039 &length, &size, &type, name.get()); | 1344 program, index, max_name_length, &length, &size, &type, name.get()); |
1040 if (size < 0) { | 1345 if (size < 0) { |
1041 return false; | 1346 return false; |
1042 } | 1347 } |
1043 info.name = WebString::fromUTF8(name.get(), length); | 1348 info.name = WebKit::WebString::fromUTF8(name.get(), length); |
1044 info.type = type; | 1349 info.type = type; |
1045 info.size = size; | 1350 info.size = size; |
1046 return true; | 1351 return true; |
1047 } | 1352 } |
1048 | 1353 |
1049 DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, | 1354 DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, |
1050 WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*) | 1355 WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*) |
1051 | 1356 |
1052 DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, | 1357 DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, |
1053 WebGLId, const WGC3Dchar*, WGC3Dint) | 1358 WebGLId, const WGC3Dchar*, WGC3Dint) |
1054 | 1359 |
1055 DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, | 1360 DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, WGC3Denum, WGC3Dboolean*) |
1056 WGC3Denum, WGC3Dboolean*) | |
1057 | 1361 |
1058 DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, | 1362 DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, |
1059 WGC3Denum, WGC3Denum, WGC3Dint*) | 1363 WGC3Denum, WGC3Denum, WGC3Dint*) |
1060 | 1364 |
1061 WebGraphicsContext3D::Attributes WebGraphicsContext3DInProcessCommandBufferImpl: : | 1365 WebKit::WebGraphicsContext3D::Attributes |
1062 getContextAttributes() { | 1366 WebGraphicsContext3DInProcessCommandBufferImpl::getContextAttributes() { |
1063 return attributes_; | 1367 return attributes_; |
1064 } | 1368 } |
1065 | 1369 |
1066 WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::getError() { | 1370 WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::getError() { |
1067 DCHECK(synthetic_errors_list_.size() == synthetic_errors_set_.size()); | 1371 ClearContext(); |
1068 if (!synthetic_errors_set_.empty()) { | 1372 if (!synthetic_errors_.empty()) { |
1069 WGC3Denum error = synthetic_errors_list_.front(); | 1373 std::vector<WGC3Denum>::iterator iter = synthetic_errors_.begin(); |
1070 synthetic_errors_list_.pop_front(); | 1374 WGC3Denum err = *iter; |
1071 synthetic_errors_set_.erase(error); | 1375 synthetic_errors_.erase(iter); |
1072 return error; | 1376 return err; |
1073 } | 1377 } |
1074 | 1378 |
1075 makeContextCurrent(); | 1379 return gl_->GetError(); |
1076 return glGetError(); | |
1077 } | 1380 } |
1078 | 1381 |
1079 bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() { | 1382 bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() { |
1080 return false; | 1383 return context_->IsCommandBufferContextLost(); |
1081 } | 1384 } |
1082 | 1385 |
1083 DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) | 1386 DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) |
1084 | 1387 |
1085 void WebGraphicsContext3DInProcessCommandBufferImpl::getFramebufferAttachmentPar ameteriv( | 1388 DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv, |
1086 WGC3Denum target, WGC3Denum attachment, | 1389 GetFramebufferAttachmentParameteriv, |
1087 WGC3Denum pname, WGC3Dint* value) { | 1390 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Dint*) |
1088 makeContextCurrent(); | |
1089 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) | |
1090 attachment = GL_DEPTH_ATTACHMENT; // Or GL_STENCIL_ATTACHMENT; | |
1091 // either works. | |
1092 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); | |
1093 } | |
1094 | 1391 |
1095 void WebGraphicsContext3DInProcessCommandBufferImpl::getIntegerv( | 1392 DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*) |
1096 WGC3Denum pname, WGC3Dint* value) { | |
1097 makeContextCurrent(); | |
1098 if (is_gles2_) { | |
1099 glGetIntegerv(pname, value); | |
1100 return; | |
1101 } | |
1102 // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and | |
1103 // MAX_VARYING_VECTORS because desktop GL's corresponding queries | |
1104 // return the number of components whereas GLES2 return the number | |
1105 // of vectors (each vector has 4 components). Therefore, the value | |
1106 // returned by desktop GL needs to be divided by 4. | |
1107 switch (pname) { | |
1108 case MAX_FRAGMENT_UNIFORM_VECTORS: | |
1109 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); | |
1110 *value /= 4; | |
1111 break; | |
1112 case MAX_VERTEX_UNIFORM_VECTORS: | |
1113 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); | |
1114 *value /= 4; | |
1115 break; | |
1116 case MAX_VARYING_VECTORS: | |
1117 glGetIntegerv(GL_MAX_VARYING_FLOATS, value); | |
1118 *value /= 4; | |
1119 break; | |
1120 default: | |
1121 glGetIntegerv(pname, value); | |
1122 } | |
1123 } | |
1124 | 1393 |
1125 DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) | 1394 DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) |
1126 | 1395 |
1127 WebString WebGraphicsContext3DInProcessCommandBufferImpl::getProgramInfoLog( | 1396 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getProgramInfo Log( |
1128 WebGLId program) { | 1397 WebGLId program) { |
1129 makeContextCurrent(); | 1398 ClearContext(); |
1130 GLint log_length; | 1399 GLint logLength = 0; |
1131 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); | 1400 gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); |
1132 if (!log_length) | 1401 if (!logLength) |
1133 return WebString(); | 1402 return WebKit::WebString(); |
1134 scoped_array<GLchar> log(new GLchar[log_length]); | 1403 scoped_array<GLchar> log(new GLchar[logLength]); |
1135 GLsizei returned_log_length; | 1404 if (!log.get()) |
1136 glGetProgramInfoLog(program, log_length, &returned_log_length, log.get()); | 1405 return WebKit::WebString(); |
1137 DCHECK(log_length == returned_log_length + 1); | 1406 GLsizei returnedLogLength = 0; |
1138 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | 1407 gl_->GetProgramInfoLog( |
1408 program, logLength, &returnedLogLength, log.get()); | |
1409 DCHECK_EQ(logLength, returnedLogLength + 1); | |
1410 WebKit::WebString res = | |
1411 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); | |
1139 return res; | 1412 return res; |
1140 } | 1413 } |
1141 | 1414 |
1142 DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameterivEXT, | 1415 DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv, |
1143 WGC3Denum, WGC3Denum, WGC3Dint*) | 1416 WGC3Denum, WGC3Denum, WGC3Dint*) |
1144 | 1417 |
1145 void WebGraphicsContext3DInProcessCommandBufferImpl::getShaderiv( | 1418 DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, WGC3Denum, WGC3Dint*) |
1146 WebGLId shader, WGC3Denum pname, WGC3Dint* value) { | |
1147 makeContextCurrent(); | |
1148 | 1419 |
1149 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | 1420 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderInfoL og( |
1150 if (result != shader_source_map_.end()) { | 1421 WebGLId shader) { |
1151 ShaderSourceEntry* entry = result->second; | 1422 ClearContext(); |
1152 DCHECK(entry); | 1423 GLint logLength = 0; |
1153 switch (pname) { | 1424 gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); |
1154 case GL_COMPILE_STATUS: | 1425 if (!logLength) |
1155 if (!entry->is_valid) { | 1426 return WebKit::WebString(); |
1156 *value = 0; | 1427 scoped_array<GLchar> log(new GLchar[logLength]); |
1157 return; | 1428 if (!log.get()) |
1158 } | 1429 return WebKit::WebString(); |
1159 break; | 1430 GLsizei returnedLogLength = 0; |
1160 case GL_INFO_LOG_LENGTH: | 1431 gl_->GetShaderInfoLog( |
1161 if (!entry->is_valid) { | 1432 shader, logLength, &returnedLogLength, log.get()); |
1162 *value = entry->log.get() ? strlen(entry->log.get()) : 0; | 1433 DCHECK_EQ(logLength, returnedLogLength + 1); |
1163 if (*value) | 1434 WebKit::WebString res = |
1164 (*value)++; | 1435 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); |
1165 return; | |
1166 } | |
1167 break; | |
1168 case GL_SHADER_SOURCE_LENGTH: | |
1169 *value = entry->source.get() ? strlen(entry->source.get()) : 0; | |
1170 if (*value) | |
1171 (*value)++; | |
1172 return; | |
1173 } | |
1174 } | |
1175 | |
1176 glGetShaderiv(shader, pname, value); | |
1177 } | |
1178 | |
1179 WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderInfoLog(WebGL Id shader) { | |
1180 makeContextCurrent(); | |
1181 | |
1182 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1183 if (result != shader_source_map_.end()) { | |
1184 ShaderSourceEntry* entry = result->second; | |
1185 DCHECK(entry); | |
1186 if (!entry->is_valid) { | |
1187 if (!entry->log.get()) | |
1188 return WebString(); | |
1189 WebString res = WebString::fromUTF8( | |
1190 entry->log.get(), strlen(entry->log.get())); | |
1191 return res; | |
1192 } | |
1193 } | |
1194 | |
1195 GLint log_length = 0; | |
1196 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); | |
1197 if (log_length <= 1) | |
1198 return WebString(); | |
1199 scoped_array<GLchar> log(new GLchar[log_length]); | |
1200 GLsizei returned_log_length; | |
1201 glGetShaderInfoLog(shader, log_length, &returned_log_length, log.get()); | |
1202 DCHECK(log_length == returned_log_length + 1); | |
1203 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1204 return res; | 1436 return res; |
1205 } | 1437 } |
1206 | 1438 |
1207 WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderSource(WebGLI d shader) { | 1439 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderSourc e( |
1208 makeContextCurrent(); | 1440 WebGLId shader) { |
1209 | 1441 ClearContext(); |
1210 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | 1442 GLint logLength = 0; |
1211 if (result != shader_source_map_.end()) { | 1443 gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength); |
1212 ShaderSourceEntry* entry = result->second; | 1444 if (!logLength) |
1213 DCHECK(entry); | 1445 return WebKit::WebString(); |
1214 if (!entry->source.get()) | 1446 scoped_array<GLchar> log(new GLchar[logLength]); |
1215 return WebString(); | 1447 if (!log.get()) |
1216 WebString res = WebString::fromUTF8( | 1448 return WebKit::WebString(); |
1217 entry->source.get(), strlen(entry->source.get())); | 1449 GLsizei returnedLogLength = 0; |
1218 return res; | 1450 gl_->GetShaderSource( |
1219 } | 1451 shader, logLength, &returnedLogLength, log.get()); |
1220 | 1452 DCHECK_EQ(logLength, returnedLogLength + 1); |
1221 GLint log_length = 0; | 1453 WebKit::WebString res = |
1222 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &log_length); | 1454 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); |
1223 if (log_length <= 1) | |
1224 return WebString(); | |
1225 scoped_array<GLchar> log(new GLchar[log_length]); | |
1226 GLsizei returned_log_length; | |
1227 glGetShaderSource(shader, log_length, &returned_log_length, log.get()); | |
1228 DCHECK(log_length == returned_log_length + 1); | |
1229 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1230 return res; | 1455 return res; |
1231 } | 1456 } |
1232 | 1457 |
1233 WebString WebGraphicsContext3DInProcessCommandBufferImpl::getString(WGC3Denum na me) { | 1458 WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getString( |
1234 makeContextCurrent(); | 1459 WGC3Denum name) { |
1235 std::string result(reinterpret_cast<const char*>(glGetString(name))); | 1460 ClearContext(); |
1236 if (name == GL_EXTENSIONS) { | 1461 return WebKit::WebString::fromUTF8( |
1237 // GL_CHROMIUM_copy_texture_to_parent_texture requires the | 1462 reinterpret_cast<const char*>(gl_->GetString(name))); |
1238 // desktopGL-only function glGetTexLevelParameteriv (GLES2 | |
1239 // doesn't support it). | |
1240 if (!is_gles2_) | |
1241 result += " GL_CHROMIUM_copy_texture_to_parent_texture"; | |
1242 } | |
1243 return WebString::fromUTF8(result.c_str()); | |
1244 } | 1463 } |
1245 | 1464 |
1246 DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, | 1465 DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, |
1247 WGC3Denum, WGC3Denum, WGC3Dfloat*) | 1466 WGC3Denum, WGC3Denum, WGC3Dfloat*) |
1248 | 1467 |
1249 DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv, | 1468 DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv, |
1250 WGC3Denum, WGC3Denum, WGC3Dint*) | 1469 WGC3Denum, WGC3Denum, WGC3Dint*) |
1251 | 1470 |
1252 DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*) | 1471 DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*) |
1253 | 1472 |
1254 DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*) | 1473 DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*) |
1255 | 1474 |
1256 DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation, | 1475 DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation, |
1257 WebGLId, const WGC3Dchar*, WGC3Dint) | 1476 WebGLId, const WGC3Dchar*, WGC3Dint) |
1258 | 1477 |
1259 DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, | 1478 DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, |
1260 WGC3Duint, WGC3Denum, WGC3Dfloat*) | 1479 WGC3Duint, WGC3Denum, WGC3Dfloat*) |
1261 | 1480 |
1262 DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, | 1481 DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, |
1263 WGC3Duint, WGC3Denum, WGC3Dint*) | 1482 WGC3Duint, WGC3Denum, WGC3Dint*) |
1264 | 1483 |
1265 WGC3Dsizeiptr WebGraphicsContext3DInProcessCommandBufferImpl::getVertexAttribOff set( | 1484 WGC3Dsizeiptr WebGraphicsContext3DInProcessCommandBufferImpl::getVertexAttribOff set( |
1266 WGC3Duint index, WGC3Denum pname) { | 1485 WGC3Duint index, WGC3Denum pname) { |
1267 makeContextCurrent(); | 1486 ClearContext(); |
1268 void* pointer; | 1487 GLvoid* value = NULL; |
1269 glGetVertexAttribPointerv(index, pname, &pointer); | 1488 // NOTE: If pname is ever a value that returns more then 1 element |
1270 return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer)); | 1489 // this will corrupt memory. |
1490 gl_->GetVertexAttribPointerv(index, pname, &value); | |
1491 return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(value)); | |
1271 } | 1492 } |
1272 | 1493 |
1273 DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) | 1494 DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) |
1274 | 1495 |
1275 DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) | 1496 DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) |
1276 | 1497 |
1277 DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) | 1498 DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) |
1278 | 1499 |
1279 DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebufferEXT, WebGLId, WGC3Dboolean) | 1500 DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebuffer, WebGLId, WGC3Dboolean) |
1280 | 1501 |
1281 DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) | 1502 DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) |
1282 | 1503 |
1283 DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbufferEXT, WebGLId, WGC3Dboolean) | 1504 DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbuffer, WebGLId, WGC3Dboolean) |
1284 | 1505 |
1285 DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) | 1506 DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) |
1286 | 1507 |
1287 DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean) | 1508 DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean) |
1288 | 1509 |
1289 DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat) | 1510 DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat) |
1290 | 1511 |
1291 DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId) | 1512 DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId) |
1292 | 1513 |
1293 DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) | 1514 DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) |
1294 | 1515 |
1295 DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) | 1516 DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) |
1296 | 1517 |
1297 void WebGraphicsContext3DInProcessCommandBufferImpl::readPixels( | 1518 DELEGATE_TO_GL_7(readPixels, ReadPixels, |
1298 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, | 1519 WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Denum, |
1299 WGC3Denum format, WGC3Denum type, void* pixels) { | 1520 WGC3Denum, void*) |
1300 makeContextCurrent(); | |
1301 // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., | |
1302 // all previous rendering calls should be done before reading pixels. | |
1303 glFlush(); | |
1304 bool needs_resolve = | |
1305 (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
1306 if (needs_resolve) { | |
1307 ResolveMultisampledFramebuffer(x, y, width, height); | |
1308 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
1309 glFlush(); | |
1310 } | |
1311 | 1521 |
1312 glReadPixels(x, y, width, height, format, type, pixels); | 1522 void WebGraphicsContext3DInProcessCommandBufferImpl::releaseShaderCompiler() { |
1313 | 1523 ClearContext(); |
1314 if (needs_resolve) | |
1315 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
1316 } | 1524 } |
1317 | 1525 |
1318 void WebGraphicsContext3DInProcessCommandBufferImpl::releaseShaderCompiler() { | 1526 DELEGATE_TO_GL_4(renderbufferStorage, RenderbufferStorage, |
1319 } | 1527 WGC3Denum, WGC3Denum, WGC3Dsizei, WGC3Dsizei) |
1320 | 1528 |
1321 void WebGraphicsContext3DInProcessCommandBufferImpl::renderbufferStorage( | 1529 DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dfloat, WGC3Dboolean) |
1322 WGC3Denum target, | |
1323 WGC3Denum internalformat, | |
1324 WGC3Dsizei width, | |
1325 WGC3Dsizei height) { | |
1326 makeContextCurrent(); | |
1327 if (!is_gles2_) { | |
1328 switch (internalformat) { | |
1329 case GL_DEPTH_STENCIL: | |
1330 internalformat = GL_DEPTH24_STENCIL8_EXT; | |
1331 break; | |
1332 case GL_DEPTH_COMPONENT16: | |
1333 internalformat = GL_DEPTH_COMPONENT; | |
1334 break; | |
1335 case GL_RGBA4: | |
1336 case GL_RGB5_A1: | |
1337 internalformat = GL_RGBA; | |
1338 break; | |
1339 case 0x8D62: // GL_RGB565 | |
1340 internalformat = GL_RGB; | |
1341 break; | |
1342 } | |
1343 } | |
1344 glRenderbufferStorageEXT(target, internalformat, width, height); | |
1345 } | |
1346 | |
1347 DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dclampf, WGC3Dboolean) | |
1348 | 1530 |
1349 DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | 1531 DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) |
1350 | 1532 |
1351 void WebGraphicsContext3DInProcessCommandBufferImpl::texImage2D( | |
1352 WGC3Denum target, WGC3Dint level, WGC3Denum internalFormat, | |
1353 WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, | |
1354 WGC3Denum format, WGC3Denum type, const void* pixels) { | |
1355 if (width && height && !pixels) { | |
1356 synthesizeGLError(GL_INVALID_VALUE); | |
1357 return; | |
1358 } | |
1359 makeContextCurrent(); | |
1360 glTexImage2D(target, level, internalFormat, | |
1361 width, height, border, format, type, pixels); | |
1362 } | |
1363 | |
1364 void WebGraphicsContext3DInProcessCommandBufferImpl::shaderSource( | 1533 void WebGraphicsContext3DInProcessCommandBufferImpl::shaderSource( |
1365 WebGLId shader, const WGC3Dchar* source) { | 1534 WebGLId shader, const WGC3Dchar* string) { |
1366 makeContextCurrent(); | 1535 ClearContext(); |
1367 GLint length = source ? strlen(source) : 0; | 1536 GLint length = strlen(string); |
1368 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | 1537 gl_->ShaderSource(shader, 1, &string, &length); |
1369 if (result != shader_source_map_.end()) { | |
1370 ShaderSourceEntry* entry = result->second; | |
1371 DCHECK(entry); | |
1372 entry->source.reset(new char[length + 1]); | |
1373 memcpy(entry->source.get(), source, (length + 1) * sizeof(char)); | |
1374 } else { | |
1375 glShaderSource(shader, 1, &source, &length); | |
1376 } | |
1377 } | 1538 } |
1378 | 1539 |
1379 DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) | 1540 DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) |
1380 | 1541 |
1381 DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate, | 1542 DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate, |
1382 WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint) | 1543 WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint) |
1383 | 1544 |
1384 DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint) | 1545 DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint) |
1385 | 1546 |
1386 DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate, | 1547 DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate, |
1387 WGC3Denum, WGC3Duint) | 1548 WGC3Denum, WGC3Duint) |
1388 | 1549 |
1389 DELEGATE_TO_GL_3(stencilOp, StencilOp, | 1550 DELEGATE_TO_GL_3(stencilOp, StencilOp, |
1390 WGC3Denum, WGC3Denum, WGC3Denum) | 1551 WGC3Denum, WGC3Denum, WGC3Denum) |
1391 | 1552 |
1392 DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, | 1553 DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, |
1393 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | 1554 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) |
1394 | 1555 |
1395 DELEGATE_TO_GL_3(texParameterf, TexParameterf, WGC3Denum, WGC3Denum, WGC3Dfloat) | 1556 DELEGATE_TO_GL_9(texImage2D, TexImage2D, |
1557 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, | |
1558 WGC3Dint, WGC3Denum, WGC3Denum, const void*) | |
1396 | 1559 |
1397 DELEGATE_TO_GL_3(texParameteri, TexParameteri, WGC3Denum, WGC3Denum, WGC3Dint) | 1560 DELEGATE_TO_GL_3(texParameterf, TexParameterf, |
1561 WGC3Denum, WGC3Denum, WGC3Dfloat); | |
1562 | |
1563 static const unsigned int kTextureWrapR = 0x8072; | |
1564 | |
1565 void WebGraphicsContext3DInProcessCommandBufferImpl::texParameteri( | |
1566 WGC3Denum target, WGC3Denum pname, WGC3Dint param) { | |
1567 ClearContext(); | |
1568 // TODO(kbr): figure out whether the setting of TEXTURE_WRAP_R in | |
1569 // GraphicsContext3D.cpp is strictly necessary to avoid seams at the | |
1570 // edge of cube maps, and, if it is, push it into the GLES2 service | |
1571 // side code. | |
1572 if (pname == kTextureWrapR) { | |
1573 return; | |
1574 } | |
1575 gl_->TexParameteri(target, pname, param); | |
1576 } | |
1398 | 1577 |
1399 DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, | 1578 DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, |
1400 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, | 1579 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, |
1401 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) | 1580 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) |
1402 | 1581 |
1403 DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) | 1582 DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) |
1404 | 1583 |
1405 DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, | 1584 DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, WGC3Dint, WGC3Dsizei, |
1406 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | 1585 const WGC3Dfloat*) |
1407 | 1586 |
1408 DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) | 1587 DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) |
1409 | 1588 |
1410 DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | 1589 DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
1411 | 1590 |
1412 DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) | 1591 DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) |
1413 | 1592 |
1414 DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, | 1593 DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, WGC3Dint, WGC3Dsizei, |
1415 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | 1594 const WGC3Dfloat*) |
1416 | 1595 |
1417 DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) | 1596 DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) |
1418 | 1597 |
1419 DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | 1598 DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
1420 | 1599 |
1421 DELEGATE_TO_GL_4(uniform3f, Uniform3f, | 1600 DELEGATE_TO_GL_4(uniform3f, Uniform3f, WGC3Dint, |
1422 WGC3Dint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | 1601 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
1423 | 1602 |
1424 DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, | 1603 DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, WGC3Dint, WGC3Dsizei, |
1425 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | 1604 const WGC3Dfloat*) |
1426 | 1605 |
1427 DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | 1606 DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) |
1428 | 1607 |
1429 DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | 1608 DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
1430 | 1609 |
1431 DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, | 1610 DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, |
1432 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | 1611 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
1433 | 1612 |
1434 DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, | 1613 DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, WGC3Dint, WGC3Dsizei, |
1435 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | 1614 const WGC3Dfloat*) |
1436 | 1615 |
1437 DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, | 1616 DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, |
1438 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | 1617 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) |
1439 | 1618 |
1440 DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | 1619 DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
1441 | 1620 |
1442 DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv, | 1621 DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv, |
1443 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | 1622 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) |
1444 | 1623 |
1445 DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv, | 1624 DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv, |
1446 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | 1625 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) |
1447 | 1626 |
1448 DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv, | 1627 DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv, |
1449 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | 1628 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) |
1450 | 1629 |
1451 DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId) | 1630 DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId) |
1452 | 1631 |
1453 DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) | 1632 DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) |
1454 | 1633 |
1455 DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) | 1634 DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) |
1456 | 1635 |
1457 DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, const WGC3Dfloat*) | 1636 DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, |
1637 const WGC3Dfloat*) | |
1458 | 1638 |
1459 DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, | 1639 DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, WGC3Duint, |
1460 WGC3Duint, WGC3Dfloat, WGC3Dfloat) | 1640 WGC3Dfloat, WGC3Dfloat) |
1461 | 1641 |
1462 DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, const WGC3Dfloat*) | 1642 DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, |
1643 const WGC3Dfloat*) | |
1463 | 1644 |
1464 DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, | 1645 DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, WGC3Duint, |
1465 WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | 1646 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
1466 | 1647 |
1467 DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, const WGC3Dfloat*) | 1648 DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, |
1649 const WGC3Dfloat*) | |
1468 | 1650 |
1469 DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, | 1651 DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, WGC3Duint, |
1470 WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | 1652 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
1471 | 1653 |
1472 DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, const WGC3Dfloat*) | 1654 DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, |
1655 const WGC3Dfloat*) | |
1473 | 1656 |
1474 void WebGraphicsContext3DInProcessCommandBufferImpl::vertexAttribPointer( | 1657 void WebGraphicsContext3DInProcessCommandBufferImpl::vertexAttribPointer( |
1475 WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, | 1658 WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, |
1476 WGC3Dsizei stride, WGC3Dintptr offset) { | 1659 WGC3Dsizei stride, WGC3Dintptr offset) { |
1477 makeContextCurrent(); | 1660 ClearContext(); |
1478 glVertexAttribPointer(index, size, type, normalized, stride, | 1661 gl_->VertexAttribPointer( |
1479 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | 1662 index, size, type, normalized, stride, |
1663 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
1480 } | 1664 } |
1481 | 1665 |
1482 DELEGATE_TO_GL_4(viewport, Viewport, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | 1666 DELEGATE_TO_GL_4(viewport, Viewport, |
1667 WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1483 | 1668 |
1484 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createBuffer() { | 1669 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createBuffer() { |
1485 makeContextCurrent(); | 1670 ClearContext(); |
1486 GLuint o; | 1671 GLuint o; |
1487 glGenBuffersARB(1, &o); | 1672 gl_->GenBuffers(1, &o); |
1488 return o; | 1673 return o; |
1489 } | 1674 } |
1490 | 1675 |
1491 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createFramebuffer() { | 1676 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createFramebuffer() { |
1492 makeContextCurrent(); | 1677 ClearContext(); |
1493 GLuint o = 0; | 1678 GLuint o = 0; |
1494 glGenFramebuffersEXT(1, &o); | 1679 gl_->GenFramebuffers(1, &o); |
1495 return o; | 1680 return o; |
1496 } | 1681 } |
1497 | 1682 |
1498 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createProgram() { | 1683 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createProgram() { |
1499 makeContextCurrent(); | 1684 ClearContext(); |
1500 return glCreateProgram(); | 1685 return gl_->CreateProgram(); |
1501 } | 1686 } |
1502 | 1687 |
1503 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createRenderbuffer() { | 1688 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createRenderbuffer() { |
1504 makeContextCurrent(); | 1689 ClearContext(); |
1505 GLuint o; | 1690 GLuint o; |
1506 glGenRenderbuffersEXT(1, &o); | 1691 gl_->GenRenderbuffers(1, &o); |
1507 return o; | 1692 return o; |
1508 } | 1693 } |
1509 | 1694 |
1510 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createShader( | 1695 DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId); |
1511 WGC3Denum shaderType) { | |
1512 makeContextCurrent(); | |
1513 DCHECK(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); | |
1514 GLuint shader = glCreateShader(shaderType); | |
1515 if (shader) { | |
1516 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1517 if (result != shader_source_map_.end()) { | |
1518 delete result->second; | |
1519 shader_source_map_.erase(result); | |
1520 } | |
1521 shader_source_map_.insert( | |
1522 ShaderSourceMap::value_type(shader, new ShaderSourceEntry(shaderType))); | |
1523 } | |
1524 | |
1525 return shader; | |
1526 } | |
1527 | 1696 |
1528 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createTexture() { | 1697 WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createTexture() { |
1529 makeContextCurrent(); | 1698 ClearContext(); |
1530 GLuint o; | 1699 GLuint o; |
1531 glGenTextures(1, &o); | 1700 gl_->GenTextures(1, &o); |
1532 return o; | 1701 return o; |
1533 } | 1702 } |
1534 | 1703 |
1535 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteBuffer(WebGLId buffer ) { | 1704 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteBuffer( |
1536 makeContextCurrent(); | 1705 WebGLId buffer) { |
1537 glDeleteBuffersARB(1, &buffer); | 1706 ClearContext(); |
1707 gl_->DeleteBuffers(1, &buffer); | |
1538 } | 1708 } |
1539 | 1709 |
1540 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteFramebuffer( | 1710 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteFramebuffer( |
1541 WebGLId framebuffer) { | 1711 WebGLId framebuffer) { |
1542 makeContextCurrent(); | 1712 ClearContext(); |
1543 glDeleteFramebuffersEXT(1, &framebuffer); | 1713 gl_->DeleteFramebuffers(1, &framebuffer); |
1544 } | 1714 } |
1545 | 1715 |
1546 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteProgram(WebGLId progr am) { | 1716 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteProgram( |
1547 makeContextCurrent(); | 1717 WebGLId program) { |
1548 glDeleteProgram(program); | 1718 ClearContext(); |
1719 gl_->DeleteProgram(program); | |
1549 } | 1720 } |
1550 | 1721 |
1551 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteRenderbuffer( | 1722 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteRenderbuffer( |
1552 WebGLId renderbuffer) { | 1723 WebGLId renderbuffer) { |
1553 makeContextCurrent(); | 1724 ClearContext(); |
1554 glDeleteRenderbuffersEXT(1, &renderbuffer); | 1725 gl_->DeleteRenderbuffers(1, &renderbuffer); |
1555 } | 1726 } |
1556 | 1727 |
1557 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteShader(WebGLId shader ) { | 1728 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteShader( |
1558 makeContextCurrent(); | 1729 WebGLId shader) { |
1559 | 1730 ClearContext(); |
1560 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | 1731 gl_->DeleteShader(shader); |
1561 if (result != shader_source_map_.end()) { | |
1562 delete result->second; | |
1563 shader_source_map_.erase(result); | |
1564 } | |
1565 glDeleteShader(shader); | |
1566 } | 1732 } |
1567 | 1733 |
1568 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteTexture(WebGLId textu re) { | 1734 void WebGraphicsContext3DInProcessCommandBufferImpl::deleteTexture( |
1569 makeContextCurrent(); | 1735 WebGLId texture) { |
1570 glDeleteTextures(1, &texture); | 1736 ClearContext(); |
1737 gl_->DeleteTextures(1, &texture); | |
1571 } | 1738 } |
1572 | 1739 |
1573 bool WebGraphicsContext3DInProcessCommandBufferImpl::AngleCreateCompilers() { | 1740 void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToCompositor( |
1574 if (!ShInitialize()) | 1741 WebGLId texture, WebGLId parentTexture) { |
1575 return false; | 1742 ClearContext(); |
1576 | 1743 gl_->CopyTextureToParentTextureCHROMIUM(texture, parentTexture); |
1577 ShBuiltInResources resources; | 1744 gl_->Flush(); |
1578 ShInitBuiltInResources(&resources); | |
1579 getIntegerv(GL_MAX_VERTEX_ATTRIBS, &resources.MaxVertexAttribs); | |
1580 getIntegerv(MAX_VERTEX_UNIFORM_VECTORS, &resources.MaxVertexUniformVectors); | |
1581 getIntegerv(MAX_VARYING_VECTORS, &resources.MaxVaryingVectors); | |
1582 getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, | |
1583 &resources.MaxVertexTextureImageUnits); | |
1584 getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, | |
1585 &resources.MaxCombinedTextureImageUnits); | |
1586 getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &resources.MaxTextureImageUnits); | |
1587 getIntegerv(MAX_FRAGMENT_UNIFORM_VECTORS, | |
1588 &resources.MaxFragmentUniformVectors); | |
1589 // Always set to 1 for OpenGL ES. | |
1590 resources.MaxDrawBuffers = 1; | |
1591 | |
1592 fragment_compiler_ = ShConstructCompiler( | |
1593 SH_FRAGMENT_SHADER, SH_WEBGL_SPEC, &resources); | |
1594 vertex_compiler_ = ShConstructCompiler( | |
1595 SH_VERTEX_SHADER, SH_WEBGL_SPEC, &resources); | |
1596 return (fragment_compiler_ && vertex_compiler_); | |
1597 } | 1745 } |
1598 | 1746 |
1599 void WebGraphicsContext3DInProcessCommandBufferImpl::AngleDestroyCompilers() { | 1747 void WebGraphicsContext3DInProcessCommandBufferImpl::OnSwapBuffersComplete() { |
1600 if (fragment_compiler_) { | |
1601 ShDestruct(fragment_compiler_); | |
1602 fragment_compiler_ = 0; | |
1603 } | |
1604 if (vertex_compiler_) { | |
1605 ShDestruct(vertex_compiler_); | |
1606 vertex_compiler_ = 0; | |
1607 } | |
1608 } | 1748 } |
1609 | 1749 |
1610 bool WebGraphicsContext3DInProcessCommandBufferImpl::AngleValidateShaderSource( | 1750 void WebGraphicsContext3DInProcessCommandBufferImpl::setContextLostCallback( |
1611 ShaderSourceEntry* entry) { | 1751 WebGraphicsContext3D::WebGraphicsContextLostCallback* cb) |
1612 entry->is_valid = false; | 1752 { |
1613 entry->translated_source.reset(); | 1753 context_lost_callback_ = cb; |
1614 entry->log.reset(); | 1754 } |
1615 | 1755 |
1616 ShHandle compiler = 0; | 1756 void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() { |
1617 switch (entry->type) { | 1757 if (context_lost_callback_) { |
1618 case GL_FRAGMENT_SHADER: | 1758 context_lost_callback_->onContextLost(); |
1619 compiler = fragment_compiler_; | |
1620 break; | |
1621 case GL_VERTEX_SHADER: | |
1622 compiler = vertex_compiler_; | |
1623 break; | |
1624 } | 1759 } |
1625 if (!compiler) | |
1626 return false; | |
1627 | |
1628 char* source = entry->source.get(); | |
1629 if (!ShCompile(compiler, &source, 1, SH_OBJECT_CODE)) { | |
1630 int logSize = 0; | |
1631 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize); | |
1632 if (logSize > 1) { | |
1633 entry->log.reset(new char[logSize]); | |
1634 ShGetInfoLog(compiler, entry->log.get()); | |
1635 } | |
1636 return false; | |
1637 } | |
1638 | |
1639 int length = 0; | |
1640 if (is_gles2_) { | |
1641 // ANGLE does not yet have a GLSL ES backend. Therefore if the | |
1642 // compile succeeds we send the original source down. | |
1643 length = strlen(entry->source.get()); | |
1644 if (length > 0) | |
1645 ++length; // Add null terminator | |
1646 } else { | |
1647 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &length); | |
1648 } | |
1649 if (length > 1) { | |
1650 entry->translated_source.reset(new char[length]); | |
1651 if (is_gles2_) | |
1652 strncpy(entry->translated_source.get(), entry->source.get(), length); | |
1653 else | |
1654 ShGetObjectCode(compiler, entry->translated_source.get()); | |
1655 } | |
1656 entry->is_valid = true; | |
1657 return true; | |
1658 } | 1760 } |
1659 | 1761 |
1660 } // namespace gpu | 1762 } // namespace gpu |
1661 } // namespace webkit | 1763 } // namespace webkit |
1662 | 1764 |
1765 #endif // defined(ENABLE_GPU) | |
1766 | |
OLD | NEW |