Chromium Code Reviews| 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 |