1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" 6 7#include "third_party/khronos/GLES2/gl2.h" 8#ifndef GL_GLEXT_PROTOTYPES 9#define GL_GLEXT_PROTOTYPES 1 10#endif 11#include "third_party/khronos/GLES2/gl2ext.h" 12 13#include <algorithm> 14#include <set> 15 16#include "base/bind.h" 17#include "base/command_line.h" 18#include "base/debug/trace_event.h" 19#include "base/lazy_instance.h" 20#include "base/logging.h" 21#include "base/message_loop/message_loop.h" 22#include "base/metrics/field_trial.h" 23#include "base/metrics/histogram.h" 24#include "base/synchronization/lock.h" 25#include "content/common/gpu/client/gpu_channel_host.h" 26#include "content/common/gpu/gpu_memory_allocation.h" 27#include "content/common/gpu/gpu_process_launch_causes.h" 28#include "content/public/common/content_constants.h" 29#include "content/public/common/content_switches.h" 30#include "gpu/GLES2/gl2extchromium.h" 31#include "gpu/command_buffer/client/gles2_cmd_helper.h" 32#include "gpu/command_buffer/client/gles2_implementation.h" 33#include "gpu/command_buffer/client/gles2_lib.h" 34#include "gpu/command_buffer/client/gles2_trace_implementation.h" 35#include "gpu/command_buffer/client/transfer_buffer.h" 36#include "gpu/command_buffer/common/constants.h" 37#include "gpu/command_buffer/common/mailbox.h" 38#include "gpu/ipc/command_buffer_proxy.h" 39#include "third_party/skia/include/core/SkTypes.h" 40#include "webkit/common/gpu/gl_bindings_skia_cmd_buffer.h" 41 42namespace content { 43static base::LazyInstance<base::Lock>::Leaky 44 g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER; 45static base::LazyInstance<std::set<WebGraphicsContext3DCommandBufferImpl*> > 46 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER; 47 48namespace { 49 50void ClearSharedContextsIfInShareSet( 51 WebGraphicsContext3DCommandBufferImpl* context) { 52 // If the given context isn't in the share set, that means that it 53 // or another context it was previously sharing with already 54 // provoked a lost context. Other contexts might have since been 55 // successfully created and added to the share set, so do not clear 56 // out the share set unless we know that all the contexts in there 57 // are supposed to be lost simultaneously. 58 base::AutoLock lock(g_all_shared_contexts_lock.Get()); 59 std::set<WebGraphicsContext3DCommandBufferImpl*>* share_set = 60 g_all_shared_contexts.Pointer(); 61 for (std::set<WebGraphicsContext3DCommandBufferImpl*>::iterator iter = 62 share_set->begin(); iter != share_set->end(); ++iter) { 63 if (context == *iter) { 64 share_set->clear(); 65 return; 66 } 67 } 68} 69 70size_t ClampUint64ToSizeT(uint64 value) { 71 value = std::min(value, 72 static_cast<uint64>(std::numeric_limits<size_t>::max())); 73 return static_cast<size_t>(value); 74} 75 76// Singleton used to initialize and terminate the gles2 library. 77class GLES2Initializer { 78 public: 79 GLES2Initializer() { 80 gles2::Initialize(); 81 } 82 83 ~GLES2Initializer() { 84 gles2::Terminate(); 85 } 86 87 private: 88 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); 89}; 90 91//////////////////////////////////////////////////////////////////////////////// 92 93base::LazyInstance<GLES2Initializer> g_gles2_initializer = 94 LAZY_INSTANCE_INITIALIZER; 95 96//////////////////////////////////////////////////////////////////////////////// 97 98} // namespace anonymous 99 100// Helper macros to reduce the amount of code. 101 102#define DELEGATE_TO_GL(name, glname) \ 103void WebGraphicsContext3DCommandBufferImpl::name() { \ 104 gl_->glname(); \ 105} 106 107#define DELEGATE_TO_GL_R(name, glname, rt) \ 108rt WebGraphicsContext3DCommandBufferImpl::name() { \ 109 return gl_->glname(); \ 110} 111 112#define DELEGATE_TO_GL_1(name, glname, t1) \ 113void WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \ 114 gl_->glname(a1); \ 115} 116 117#define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ 118rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \ 119 return gl_->glname(a1); \ 120} 121 122#define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ 123rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1) { \ 124 return gl_->glname(a1) ? true : false; \ 125} 126 127#define DELEGATE_TO_GL_2(name, glname, t1, t2) \ 128void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) { \ 129 gl_->glname(a1, a2); \ 130} 131 132#define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ 133rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2) { \ 134 return gl_->glname(a1, a2); \ 135} 136 137#define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ 138void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \ 139 gl_->glname(a1, a2, a3); \ 140} 141 142#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ 143void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 144 t4 a4) { \ 145 gl_->glname(a1, a2, a3, a4); \ 146} 147 148#define DELEGATE_TO_GL_4R(name, glname, t1, t2, t3, t4, rt) \ 149rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 150 t4 a4) { \ 151 return gl_->glname(a1, a2, a3, a4); \ 152} 153 154#define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ 155void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 156 t4 a4, t5 a5) { \ 157 gl_->glname(a1, a2, a3, a4, a5); \ 158} 159 160#define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ 161void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 162 t4 a4, t5 a5, t6 a6) { \ 163 gl_->glname(a1, a2, a3, a4, a5, a6); \ 164} 165 166#define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ 167void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 168 t4 a4, t5 a5, t6 a6, \ 169 t7 a7) { \ 170 gl_->glname(a1, a2, a3, a4, a5, a6, a7); \ 171} 172 173#define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ 174void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 175 t4 a4, t5 a5, t6 a6, \ 176 t7 a7, t8 a8) { \ 177 gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8); \ 178} 179 180#define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ 181void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \ 182 t4 a4, t5 a5, t6 a6, \ 183 t7 a7, t8 a8, t9 a9) { \ 184 gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ 185} 186 187class WebGraphicsContext3DErrorMessageCallback 188 : public gpu::gles2::GLES2Implementation::ErrorMessageCallback { 189 public: 190 WebGraphicsContext3DErrorMessageCallback( 191 WebGraphicsContext3DCommandBufferImpl* context) 192 : graphics_context_(context) { 193 } 194 195 virtual void OnErrorMessage(const char* msg, int id) OVERRIDE; 196 197 private: 198 WebGraphicsContext3DCommandBufferImpl* graphics_context_; 199 200 DISALLOW_COPY_AND_ASSIGN(WebGraphicsContext3DErrorMessageCallback); 201}; 202 203void WebGraphicsContext3DErrorMessageCallback::OnErrorMessage( 204 const char* msg, int id) { 205 graphics_context_->OnErrorMessage(msg, id); 206} 207 208WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( 209 int surface_id, 210 const GURL& active_url, 211 GpuChannelHostFactory* factory, 212 const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client) 213 : initialize_failed_(false), 214 factory_(factory), 215 visible_(false), 216 free_command_buffer_when_invisible_(false), 217 host_(NULL), 218 surface_id_(surface_id), 219 active_url_(active_url), 220 swap_client_(swap_client), 221 context_lost_callback_(0), 222 context_lost_reason_(GL_NO_ERROR), 223 error_message_callback_(0), 224 swapbuffers_complete_callback_(0), 225 gpu_preference_(gfx::PreferIntegratedGpu), 226 cached_width_(0), 227 cached_height_(0), 228 weak_ptr_factory_(this), 229 initialized_(false), 230 gl_(NULL), 231 frame_number_(0), 232 bind_generates_resources_(false), 233 use_echo_for_swap_ack_(true), 234 command_buffer_size_(0), 235 start_transfer_buffer_size_(0), 236 min_transfer_buffer_size_(0), 237 max_transfer_buffer_size_(0) { 238#if (defined(OS_MACOSX) || defined(OS_WIN)) && !defined(USE_AURA) 239 // Get ViewMsg_SwapBuffers_ACK from browser for single-threaded path. 240 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 241 use_echo_for_swap_ack_ = 242 command_line.HasSwitch(switches::kEnableThreadedCompositing); 243#endif 244} 245 246WebGraphicsContext3DCommandBufferImpl:: 247 ~WebGraphicsContext3DCommandBufferImpl() { 248 if (real_gl_) { 249 real_gl_->SetErrorMessageCallback(NULL); 250 } 251 252 { 253 base::AutoLock lock(g_all_shared_contexts_lock.Get()); 254 g_all_shared_contexts.Pointer()->erase(this); 255 } 256 Destroy(); 257} 258 259bool WebGraphicsContext3DCommandBufferImpl::InitializeWithDefaultBufferSizes( 260 const WebGraphicsContext3D::Attributes& attributes, 261 bool bind_generates_resources, 262 CauseForGpuLaunch cause) { 263 return Initialize(attributes, 264 bind_generates_resources, 265 cause, 266 kDefaultCommandBufferSize, 267 kDefaultStartTransferBufferSize, 268 kDefaultMinTransferBufferSize, 269 kDefaultMaxTransferBufferSize); 270} 271 272bool WebGraphicsContext3DCommandBufferImpl::Initialize( 273 const WebGraphicsContext3D::Attributes& attributes, 274 bool bind_generates_resources, 275 CauseForGpuLaunch cause, 276 size_t command_buffer_size, 277 size_t start_transfer_buffer_size, 278 size_t min_transfer_buffer_size, 279 size_t max_transfer_buffer_size) { 280 TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::initialize"); 281 282 attributes_ = attributes; 283 bind_generates_resources_ = bind_generates_resources; 284 DCHECK(!command_buffer_); 285 286 if (!factory_) 287 return false; 288 289 if (attributes.preferDiscreteGPU) 290 gpu_preference_ = gfx::PreferDiscreteGpu; 291 292 host_ = factory_->EstablishGpuChannelSync(cause); 293 if (!host_.get()) 294 return false; 295 296 command_buffer_size_ = command_buffer_size; 297 start_transfer_buffer_size_ = start_transfer_buffer_size; 298 min_transfer_buffer_size_ = min_transfer_buffer_size; 299 max_transfer_buffer_size_ = max_transfer_buffer_size; 300 301 return true; 302} 303 304bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL( 305 const char* allowed_extensions) { 306 if (initialized_) 307 return true; 308 309 if (initialize_failed_) 310 return false; 311 312 TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::MaybeInitializeGL"); 313 314 const char* preferred_extensions = "*"; 315 316 if (!CreateContext(surface_id_ != 0, 317 allowed_extensions ? 318 allowed_extensions : preferred_extensions)) { 319 Destroy(); 320 initialize_failed_ = true; 321 return false; 322 } 323 324 // TODO(twiz): This code is too fragile in that it assumes that only WebGL 325 // contexts will request noExtensions. 326 if (gl_ && attributes_.noExtensions) 327 gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation"); 328 329 command_buffer_->SetChannelErrorCallback( 330 base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnContextLost, 331 weak_ptr_factory_.GetWeakPtr())); 332 333 command_buffer_->SetOnConsoleMessageCallback( 334 base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnErrorMessage, 335 weak_ptr_factory_.GetWeakPtr())); 336 337 client_error_message_callback_.reset( 338 new WebGraphicsContext3DErrorMessageCallback(this)); 339 real_gl_->SetErrorMessageCallback(client_error_message_callback_.get()); 340 341 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 342 free_command_buffer_when_invisible_ = 343 command_line.HasSwitch(switches::kEnablePruneGpuCommandBuffers); 344 345 // Set attributes_ from created offscreen context. 346 { 347 static const int pcount = 4; 348 static const GLenum pnames[pcount] = { 349 GL_ALPHA_BITS, 350 GL_DEPTH_BITS, 351 GL_STENCIL_BITS, 352 GL_SAMPLE_BUFFERS, 353 }; 354 GLint pvalues[pcount] = { 0, 0, 0, 0 }; 355 356 gl_->GetMultipleIntegervCHROMIUM(pnames, pcount, 357 pvalues, sizeof(pvalues)); 358 359 attributes_.alpha = pvalues[0] > 0; 360 attributes_.depth = pvalues[1] > 0; 361 attributes_.stencil = pvalues[2] > 0; 362 attributes_.antialias = pvalues[3] > 0; 363 } 364 365 visible_ = true; 366 initialized_ = true; 367 return true; 368} 369 370bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( 371 bool onscreen, 372 const char* allowed_extensions) { 373 if (!host_.get()) 374 return false; 375 // We need to lock g_all_shared_contexts to ensure that the context we picked 376 // for our share group isn't deleted. 377 // (There's also a lock in our destructor.) 378 base::AutoLock lock(g_all_shared_contexts_lock.Get()); 379 CommandBufferProxyImpl* share_group = NULL; 380 if (attributes_.shareResources) { 381 WebGraphicsContext3DCommandBufferImpl* share_group_context = 382 g_all_shared_contexts.Pointer()->empty() ? 383 NULL : *g_all_shared_contexts.Pointer()->begin(); 384 share_group = share_group_context ? 385 share_group_context->command_buffer_.get() : NULL; 386 } 387 388 std::vector<int32> attribs; 389 attribs.push_back(ALPHA_SIZE); 390 attribs.push_back(attributes_.alpha ? 8 : 0); 391 attribs.push_back(DEPTH_SIZE); 392 attribs.push_back(attributes_.depth ? 24 : 0); 393 attribs.push_back(STENCIL_SIZE); 394 attribs.push_back(attributes_.stencil ? 8 : 0); 395 attribs.push_back(SAMPLES); 396 attribs.push_back(attributes_.antialias ? 4 : 0); 397 attribs.push_back(SAMPLE_BUFFERS); 398 attribs.push_back(attributes_.antialias ? 1 : 0); 399 attribs.push_back(NONE); 400 401 // Create a proxy to a command buffer in the GPU process. 402 if (onscreen) { 403 command_buffer_.reset(host_->CreateViewCommandBuffer( 404 surface_id_, 405 share_group, 406 allowed_extensions, 407 attribs, 408 active_url_, 409 gpu_preference_)); 410 } else { 411 command_buffer_.reset(host_->CreateOffscreenCommandBuffer( 412 gfx::Size(1, 1), 413 share_group, 414 allowed_extensions, 415 attribs, 416 active_url_, 417 gpu_preference_)); 418 } 419 420 if (!command_buffer_) 421 return false; 422 423 // Initialize the command buffer. 424 return command_buffer_->Initialize(); 425} 426 427bool WebGraphicsContext3DCommandBufferImpl::CreateContext( 428 bool onscreen, 429 const char* allowed_extensions) { 430 431 // Ensure the gles2 library is initialized first in a thread safe way. 432 g_gles2_initializer.Get(); 433 434 if (!command_buffer_ && 435 !InitializeCommandBuffer(onscreen, 436 allowed_extensions)) { 437 return false; 438 } 439 440 // Create the GLES2 helper, which writes the command buffer protocol. 441 gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); 442 if (!gles2_helper_->Initialize(command_buffer_size_)) 443 return false; 444 445 if (attributes_.noAutomaticFlushes) 446 gles2_helper_->SetAutomaticFlushes(false); 447 448 // Create a transfer buffer used to copy resources between the renderer 449 // process and the GPU process. 450 transfer_buffer_ .reset(new gpu::TransferBuffer(gles2_helper_.get())); 451 452 scoped_ptr<base::AutoLock> lock; 453 scoped_refptr<gpu::gles2::ShareGroup> share_group; 454 if (attributes_.shareResources) { 455 // Make sure two clients don't try to create a new ShareGroup 456 // simultaneously. 457 lock.reset(new base::AutoLock(g_all_shared_contexts_lock.Get())); 458 if (!g_all_shared_contexts.Pointer()->empty()) { 459 share_group = (*g_all_shared_contexts.Pointer()->begin()) 460 ->GetImplementation()->share_group(); 461 DCHECK(share_group); 462 } 463 } 464 465 // Create the object exposing the OpenGL API. 466 real_gl_.reset(new gpu::gles2::GLES2Implementation( 467 gles2_helper_.get(), 468 share_group, 469 transfer_buffer_.get(), 470 bind_generates_resources_, 471 NULL)); 472 gl_ = real_gl_.get(); 473 474 if (attributes_.shareResources) { 475 // Don't add ourselves to the list before others can get to our ShareGroup. 476 g_all_shared_contexts.Pointer()->insert(this); 477 lock.reset(); 478 } 479 480 if (!real_gl_->Initialize( 481 start_transfer_buffer_size_, 482 min_transfer_buffer_size_, 483 max_transfer_buffer_size_)) { 484 return false; 485 } 486 487 if (CommandLine::ForCurrentProcess()->HasSwitch( 488 switches::kEnableGpuClientTracing)) { 489 trace_gl_.reset(new gpu::gles2::GLES2TraceImplementation(gl_)); 490 gl_ = trace_gl_.get(); 491 } 492 493 return true; 494} 495 496bool WebGraphicsContext3DCommandBufferImpl::makeContextCurrent() { 497 if (!MaybeInitializeGL(NULL)) 498 return false; 499 gles2::SetGLContext(gl_); 500 if (command_buffer_->GetLastError() != gpu::error::kNoError) 501 return false; 502 503 return true; 504} 505 506int WebGraphicsContext3DCommandBufferImpl::width() { 507 return cached_width_; 508} 509 510int WebGraphicsContext3DCommandBufferImpl::height() { 511 return cached_height_; 512} 513 514DELEGATE_TO_GL_R(insertSyncPoint, InsertSyncPointCHROMIUM, unsigned int) 515 516void WebGraphicsContext3DCommandBufferImpl::Destroy() { 517 if (gl_) { 518 // First flush the context to ensure that any pending frees of resources 519 // are completed. Otherwise, if this context is part of a share group, 520 // those resources might leak. Also, any remaining side effects of commands 521 // issued on this context might not be visible to other contexts in the 522 // share group. 523 gl_->Flush(); 524 gl_ = NULL; 525 } 526 527 trace_gl_.reset(); 528 real_gl_.reset(); 529 transfer_buffer_.reset(); 530 gles2_helper_.reset(); 531 real_gl_.reset(); 532 533 if (command_buffer_) { 534 if (host_.get()) 535 host_->DestroyCommandBuffer(command_buffer_.release()); 536 command_buffer_.reset(); 537 } 538 539 host_ = NULL; 540} 541 542// TODO(apatrick,piman): This should be renamed to something clearer. 543int WebGraphicsContext3DCommandBufferImpl::GetGPUProcessID() { 544 return host_.get() ? host_->gpu_host_id() : 0; 545} 546 547int WebGraphicsContext3DCommandBufferImpl::GetChannelID() { 548 return host_.get() ? host_->client_id() : 0; 549} 550 551int WebGraphicsContext3DCommandBufferImpl::GetContextID() { 552 return command_buffer_->GetRouteID(); 553} 554 555void WebGraphicsContext3DCommandBufferImpl::prepareTexture() { 556 TRACE_EVENT1("gpu", 557 "WebGraphicsContext3DCommandBufferImpl::SwapBuffers", 558 "frame", frame_number_); 559 frame_number_++; 560 // Copies the contents of the off-screen render target into the texture 561 // used by the compositor. 562 if (ShouldUseSwapClient()) 563 swap_client_->OnViewContextSwapBuffersPosted(); 564 565 if (command_buffer_->GetLastState().error == gpu::error::kNoError) 566 gl_->SwapBuffers(); 567 568 if (use_echo_for_swap_ack_) { 569 command_buffer_->Echo(base::Bind( 570 &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete, 571 weak_ptr_factory_.GetWeakPtr())); 572 } 573#if defined(OS_MACOSX) 574 // It appears that making the compositor's on-screen context current on 575 // other platforms implies this flush. TODO(kbr): this means that the 576 // TOUCH build and, in the future, other platforms might need this. 577 gl_->Flush(); 578#endif 579} 580 581void WebGraphicsContext3DCommandBufferImpl::postSubBufferCHROMIUM( 582 int x, int y, int width, int height) { 583 // Same flow control as WebGraphicsContext3DCommandBufferImpl::prepareTexture 584 // (see above). 585 if (ShouldUseSwapClient()) 586 swap_client_->OnViewContextSwapBuffersPosted(); 587 gl_->PostSubBufferCHROMIUM(x, y, width, height); 588 command_buffer_->Echo(base::Bind( 589 &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete, 590 weak_ptr_factory_.GetWeakPtr())); 591} 592 593void WebGraphicsContext3DCommandBufferImpl::reshape(int width, int height) { 594 reshapeWithScaleFactor(width, height, 1.f); 595} 596 597void WebGraphicsContext3DCommandBufferImpl::reshapeWithScaleFactor( 598 int width, int height, float scale_factor) { 599 cached_width_ = width; 600 cached_height_ = height; 601 602 gl_->ResizeCHROMIUM(width, height, scale_factor); 603} 604 605void WebGraphicsContext3DCommandBufferImpl::synthesizeGLError( 606 WGC3Denum error) { 607 if (std::find(synthetic_errors_.begin(), synthetic_errors_.end(), error) == 608 synthetic_errors_.end()) { 609 synthetic_errors_.push_back(error); 610 } 611} 612 613DELEGATE_TO_GL_4R(mapBufferSubDataCHROMIUM, MapBufferSubDataCHROMIUM, WGC3Denum, 614 WGC3Dintptr, WGC3Dsizeiptr, WGC3Denum, void*) 615 616DELEGATE_TO_GL_1(unmapBufferSubDataCHROMIUM, UnmapBufferSubDataCHROMIUM, 617 const void*) 618 619void* WebGraphicsContext3DCommandBufferImpl::mapTexSubImage2DCHROMIUM( 620 WGC3Denum target, 621 WGC3Dint level, 622 WGC3Dint xoffset, 623 WGC3Dint yoffset, 624 WGC3Dsizei width, 625 WGC3Dsizei height, 626 WGC3Denum format, 627 WGC3Denum type, 628 WGC3Denum access) { 629 return gl_->MapTexSubImage2DCHROMIUM( 630 target, level, xoffset, yoffset, width, height, format, type, access); 631} 632 633DELEGATE_TO_GL_1(unmapTexSubImage2DCHROMIUM, UnmapTexSubImage2DCHROMIUM, 634 const void*) 635 636void WebGraphicsContext3DCommandBufferImpl::setVisibilityCHROMIUM( 637 bool visible) { 638 gl_->Flush(); 639 visible_ = visible; 640 command_buffer_->SetSurfaceVisible(visible); 641 if (!visible) 642 real_gl_->FreeEverything(); 643} 644 645DELEGATE_TO_GL_3(discardFramebufferEXT, DiscardFramebufferEXT, WGC3Denum, 646 WGC3Dsizei, const WGC3Denum*) 647 648void WebGraphicsContext3DCommandBufferImpl::discardBackbufferCHROMIUM() { 649 gl_->Flush(); 650 command_buffer_->DiscardBackbuffer(); 651} 652 653void WebGraphicsContext3DCommandBufferImpl::ensureBackbufferCHROMIUM() { 654 gl_->Flush(); 655 command_buffer_->EnsureBackbuffer(); 656} 657 658void WebGraphicsContext3DCommandBufferImpl::sendManagedMemoryStatsCHROMIUM( 659 const WebGraphicsManagedMemoryStats* stats) 660{ 661 CHECK(command_buffer_); 662 command_buffer_->SendManagedMemoryStats(GpuManagedMemoryStats( 663 stats->bytesVisible, 664 stats->bytesVisibleAndNearby, 665 stats->bytesAllocated, 666 stats->backbufferRequested)); 667} 668 669void WebGraphicsContext3DCommandBufferImpl:: 670 setMemoryAllocationChangedCallbackCHROMIUM( 671 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { 672 if (!command_buffer_) 673 return; 674 675 if (callback) 676 command_buffer_->SetMemoryAllocationChangedCallback(base::Bind( 677 &WebGraphicsContext3DCommandBufferImpl::OnMemoryAllocationChanged, 678 weak_ptr_factory_.GetWeakPtr(), 679 callback)); 680 else 681 command_buffer_->SetMemoryAllocationChangedCallback( 682 base::Callback<void(const GpuMemoryAllocationForRenderer&)>()); 683} 684 685 686void WebGraphicsContext3DCommandBufferImpl::copyTextureToParentTextureCHROMIUM( 687 WebGLId texture, WebGLId parentTexture) { 688 NOTIMPLEMENTED(); 689} 690 691DELEGATE_TO_GL(rateLimitOffscreenContextCHROMIUM, 692 RateLimitOffscreenContextCHROMIUM) 693 694WebKit::WebString WebGraphicsContext3DCommandBufferImpl:: 695 getRequestableExtensionsCHROMIUM() { 696 return WebKit::WebString::fromUTF8( 697 gl_->GetRequestableExtensionsCHROMIUM()); 698} 699 700DELEGATE_TO_GL_1(requestExtensionCHROMIUM, RequestExtensionCHROMIUM, 701 const char*) 702 703void WebGraphicsContext3DCommandBufferImpl::blitFramebufferCHROMIUM( 704 WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, 705 WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, 706 WGC3Dbitfield mask, WGC3Denum filter) { 707 gl_->BlitFramebufferEXT( 708 srcX0, srcY0, srcX1, srcY1, 709 dstX0, dstY0, dstX1, dstY1, 710 mask, filter); 711} 712 713DELEGATE_TO_GL_5(renderbufferStorageMultisampleCHROMIUM, 714 RenderbufferStorageMultisampleEXT, WGC3Denum, WGC3Dsizei, 715 WGC3Denum, WGC3Dsizei, WGC3Dsizei) 716 717DELEGATE_TO_GL_1R(createStreamTextureCHROMIUM, CreateStreamTextureCHROMIUM, 718 WebGLId, WebGLId) 719 720DELEGATE_TO_GL_1(destroyStreamTextureCHROMIUM, DestroyStreamTextureCHROMIUM, 721 WebGLId) 722 723DELEGATE_TO_GL_1(activeTexture, ActiveTexture, WGC3Denum) 724 725DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) 726 727DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, WebGLId, 728 WGC3Duint, const WGC3Dchar*) 729 730DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId) 731 732DELEGATE_TO_GL_2(bindFramebuffer, BindFramebuffer, WGC3Denum, WebGLId) 733 734DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbuffer, WGC3Denum, WebGLId) 735 736DELEGATE_TO_GL_2(bindTexture, BindTexture, WGC3Denum, WebGLId) 737 738DELEGATE_TO_GL_4(blendColor, BlendColor, 739 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) 740 741DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) 742 743DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate, 744 WGC3Denum, WGC3Denum) 745 746DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum) 747 748DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate, 749 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) 750 751DELEGATE_TO_GL_4(bufferData, BufferData, 752 WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum) 753 754DELEGATE_TO_GL_4(bufferSubData, BufferSubData, 755 WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) 756 757DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatus, 758 WGC3Denum, WGC3Denum) 759 760DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) 761 762DELEGATE_TO_GL_4(clearColor, ClearColor, 763 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) 764 765DELEGATE_TO_GL_1(clearDepth, ClearDepthf, WGC3Dclampf) 766 767DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) 768 769DELEGATE_TO_GL_4(colorMask, ColorMask, 770 WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) 771 772DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId) 773 774DELEGATE_TO_GL_8(compressedTexImage2D, CompressedTexImage2D, 775 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, 776 WGC3Dsizei, WGC3Dsizei, const void*) 777 778DELEGATE_TO_GL_9(compressedTexSubImage2D, CompressedTexSubImage2D, 779 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, 780 WGC3Denum, WGC3Dsizei, const void*) 781 782DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D, 783 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, 784 WGC3Dsizei, WGC3Dsizei, WGC3Dint) 785 786DELEGATE_TO_GL_8(copyTexSubImage2D, CopyTexSubImage2D, 787 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, 788 WGC3Dsizei, WGC3Dsizei) 789 790DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) 791 792DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) 793 794DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) 795 796DELEGATE_TO_GL_2(depthRange, DepthRangef, WGC3Dclampf, WGC3Dclampf) 797 798DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) 799 800DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) 801 802DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, 803 WGC3Duint) 804 805DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) 806 807void WebGraphicsContext3DCommandBufferImpl::drawElements(WGC3Denum mode, 808 WGC3Dsizei count, 809 WGC3Denum type, 810 WGC3Dintptr offset) { 811 gl_->DrawElements( 812 mode, count, type, 813 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); 814} 815 816DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) 817 818DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, 819 WGC3Duint) 820 821void WebGraphicsContext3DCommandBufferImpl::finish() { 822 gl_->Finish(); 823 if (!visible_ && free_command_buffer_when_invisible_) 824 real_gl_->FreeEverything(); 825} 826 827void WebGraphicsContext3DCommandBufferImpl::flush() { 828 gl_->Flush(); 829 if (!visible_ && free_command_buffer_when_invisible_) 830 real_gl_->FreeEverything(); 831} 832 833DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer, 834 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) 835 836DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D, 837 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) 838 839DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) 840 841DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, WGC3Denum) 842 843bool WebGraphicsContext3DCommandBufferImpl::getActiveAttrib( 844 WebGLId program, WGC3Duint index, ActiveInfo& info) { 845 if (!program) { 846 synthesizeGLError(GL_INVALID_VALUE); 847 return false; 848 } 849 GLint max_name_length = -1; 850 gl_->GetProgramiv( 851 program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); 852 if (max_name_length < 0) 853 return false; 854 scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); 855 if (!name) { 856 synthesizeGLError(GL_OUT_OF_MEMORY); 857 return false; 858 } 859 GLsizei length = 0; 860 GLint size = -1; 861 GLenum type = 0; 862 gl_->GetActiveAttrib( 863 program, index, max_name_length, &length, &size, &type, name.get()); 864 if (size < 0) { 865 return false; 866 } 867 info.name = WebKit::WebString::fromUTF8(name.get(), length); 868 info.type = type; 869 info.size = size; 870 return true; 871} 872 873bool WebGraphicsContext3DCommandBufferImpl::getActiveUniform( 874 WebGLId program, WGC3Duint index, ActiveInfo& info) { 875 GLint max_name_length = -1; 876 gl_->GetProgramiv( 877 program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); 878 if (max_name_length < 0) 879 return false; 880 scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); 881 if (!name) { 882 synthesizeGLError(GL_OUT_OF_MEMORY); 883 return false; 884 } 885 GLsizei length = 0; 886 GLint size = -1; 887 GLenum type = 0; 888 gl_->GetActiveUniform( 889 program, index, max_name_length, &length, &size, &type, name.get()); 890 if (size < 0) { 891 return false; 892 } 893 info.name = WebKit::WebString::fromUTF8(name.get(), length); 894 info.type = type; 895 info.size = size; 896 return true; 897} 898 899DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, 900 WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*) 901 902DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, 903 WebGLId, const WGC3Dchar*, WGC3Dint) 904 905DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, WGC3Denum, WGC3Dboolean*) 906 907DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, 908 WGC3Denum, WGC3Denum, WGC3Dint*) 909 910WebKit::WebGraphicsContext3D::Attributes 911WebGraphicsContext3DCommandBufferImpl::getContextAttributes() { 912 return attributes_; 913} 914 915WGC3Denum WebGraphicsContext3DCommandBufferImpl::getError() { 916 if (!synthetic_errors_.empty()) { 917 std::vector<WGC3Denum>::iterator iter = synthetic_errors_.begin(); 918 WGC3Denum err = *iter; 919 synthetic_errors_.erase(iter); 920 return err; 921 } 922 923 return gl_->GetError(); 924} 925 926bool WebGraphicsContext3DCommandBufferImpl::isContextLost() { 927 return initialize_failed_ || 928 (command_buffer_ && IsCommandBufferContextLost()) || 929 context_lost_reason_ != GL_NO_ERROR; 930} 931 932DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) 933 934DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv, 935 GetFramebufferAttachmentParameteriv, 936 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Dint*) 937 938DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*) 939 940DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) 941 942WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getProgramInfoLog( 943 WebGLId program) { 944 GLint logLength = 0; 945 gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); 946 if (!logLength) 947 return WebKit::WebString(); 948 scoped_ptr<GLchar[]> log(new GLchar[logLength]); 949 if (!log) 950 return WebKit::WebString(); 951 GLsizei returnedLogLength = 0; 952 gl_->GetProgramInfoLog( 953 program, logLength, &returnedLogLength, log.get()); 954 DCHECK_EQ(logLength, returnedLogLength + 1); 955 WebKit::WebString res = 956 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); 957 return res; 958} 959 960DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv, 961 WGC3Denum, WGC3Denum, WGC3Dint*) 962 963DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, WGC3Denum, WGC3Dint*) 964 965WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderInfoLog( 966 WebGLId shader) { 967 GLint logLength = 0; 968 gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); 969 if (!logLength) 970 return WebKit::WebString(); 971 scoped_ptr<GLchar[]> log(new GLchar[logLength]); 972 if (!log) 973 return WebKit::WebString(); 974 GLsizei returnedLogLength = 0; 975 gl_->GetShaderInfoLog( 976 shader, logLength, &returnedLogLength, log.get()); 977 DCHECK_EQ(logLength, returnedLogLength + 1); 978 WebKit::WebString res = 979 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); 980 return res; 981} 982 983DELEGATE_TO_GL_4(getShaderPrecisionFormat, GetShaderPrecisionFormat, 984 WGC3Denum, WGC3Denum, WGC3Dint*, WGC3Dint*) 985 986WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderSource( 987 WebGLId shader) { 988 GLint logLength = 0; 989 gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength); 990 if (!logLength) 991 return WebKit::WebString(); 992 scoped_ptr<GLchar[]> log(new GLchar[logLength]); 993 if (!log) 994 return WebKit::WebString(); 995 GLsizei returnedLogLength = 0; 996 gl_->GetShaderSource( 997 shader, logLength, &returnedLogLength, log.get()); 998 if (!returnedLogLength) 999 return WebKit::WebString(); 1000 DCHECK_EQ(logLength, returnedLogLength + 1); 1001 WebKit::WebString res = 1002 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); 1003 return res; 1004} 1005 1006WebKit::WebString WebGraphicsContext3DCommandBufferImpl:: 1007 getTranslatedShaderSourceANGLE(WebGLId shader) { 1008 GLint logLength = 0; 1009 gl_->GetShaderiv( 1010 shader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &logLength); 1011 if (!logLength) 1012 return WebKit::WebString(); 1013 scoped_ptr<GLchar[]> log(new GLchar[logLength]); 1014 if (!log) 1015 return WebKit::WebString(); 1016 GLsizei returnedLogLength = 0; 1017 gl_->GetTranslatedShaderSourceANGLE( 1018 shader, logLength, &returnedLogLength, log.get()); 1019 if (!returnedLogLength) 1020 return WebKit::WebString(); 1021 DCHECK_EQ(logLength, returnedLogLength + 1); 1022 WebKit::WebString res = 1023 WebKit::WebString::fromUTF8(log.get(), returnedLogLength); 1024 return res; 1025} 1026 1027WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getString( 1028 WGC3Denum name) { 1029 return WebKit::WebString::fromUTF8( 1030 reinterpret_cast<const char*>(gl_->GetString(name))); 1031} 1032 1033DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, 1034 WGC3Denum, WGC3Denum, WGC3Dfloat*) 1035 1036DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv, 1037 WGC3Denum, WGC3Denum, WGC3Dint*) 1038 1039DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*) 1040 1041DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*) 1042 1043DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation, 1044 WebGLId, const WGC3Dchar*, WGC3Dint) 1045 1046DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, 1047 WGC3Duint, WGC3Denum, WGC3Dfloat*) 1048 1049DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, 1050 WGC3Duint, WGC3Denum, WGC3Dint*) 1051 1052WGC3Dsizeiptr WebGraphicsContext3DCommandBufferImpl::getVertexAttribOffset( 1053 WGC3Duint index, WGC3Denum pname) { 1054 GLvoid* value = NULL; 1055 // NOTE: If pname is ever a value that returns more then 1 element 1056 // this will corrupt memory. 1057 gl_->GetVertexAttribPointerv(index, pname, &value); 1058 return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(value)); 1059} 1060 1061DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) 1062 1063DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) 1064 1065DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) 1066 1067DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebuffer, WebGLId, WGC3Dboolean) 1068 1069DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) 1070 1071DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbuffer, WebGLId, WGC3Dboolean) 1072 1073DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) 1074 1075DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean) 1076 1077DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat) 1078 1079DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId) 1080 1081DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) 1082 1083DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) 1084 1085DELEGATE_TO_GL_7(readPixels, ReadPixels, 1086 WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Denum, 1087 WGC3Denum, void*) 1088 1089void WebGraphicsContext3DCommandBufferImpl::releaseShaderCompiler() { 1090} 1091 1092DELEGATE_TO_GL_4(renderbufferStorage, RenderbufferStorage, 1093 WGC3Denum, WGC3Denum, WGC3Dsizei, WGC3Dsizei) 1094 1095DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dfloat, WGC3Dboolean) 1096 1097DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) 1098 1099void WebGraphicsContext3DCommandBufferImpl::shaderSource( 1100 WebGLId shader, const WGC3Dchar* string) { 1101 GLint length = strlen(string); 1102 gl_->ShaderSource(shader, 1, &string, &length); 1103} 1104 1105DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) 1106 1107DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate, 1108 WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint) 1109 1110DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint) 1111 1112DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate, 1113 WGC3Denum, WGC3Duint) 1114 1115DELEGATE_TO_GL_3(stencilOp, StencilOp, 1116 WGC3Denum, WGC3Denum, WGC3Denum) 1117 1118DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, 1119 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) 1120 1121DELEGATE_TO_GL_9(texImage2D, TexImage2D, 1122 WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, 1123 WGC3Dint, WGC3Denum, WGC3Denum, const void*) 1124 1125DELEGATE_TO_GL_3(texParameterf, TexParameterf, 1126 WGC3Denum, WGC3Denum, WGC3Dfloat); 1127 1128static const unsigned int kTextureWrapR = 0x8072; 1129 1130void WebGraphicsContext3DCommandBufferImpl::texParameteri( 1131 WGC3Denum target, WGC3Denum pname, WGC3Dint param) { 1132 // TODO(kbr): figure out whether the setting of TEXTURE_WRAP_R in 1133 // GraphicsContext3D.cpp is strictly necessary to avoid seams at the 1134 // edge of cube maps, and, if it is, push it into the GLES2 service 1135 // side code. 1136 if (pname == kTextureWrapR) { 1137 return; 1138 } 1139 gl_->TexParameteri(target, pname, param); 1140} 1141 1142DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, 1143 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, 1144 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) 1145 1146DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) 1147 1148DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, WGC3Dint, WGC3Dsizei, 1149 const WGC3Dfloat*) 1150 1151DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) 1152 1153DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) 1154 1155DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) 1156 1157DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, WGC3Dint, WGC3Dsizei, 1158 const WGC3Dfloat*) 1159 1160DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) 1161 1162DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) 1163 1164DELEGATE_TO_GL_4(uniform3f, Uniform3f, WGC3Dint, 1165 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) 1166 1167DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, WGC3Dint, WGC3Dsizei, 1168 const WGC3Dfloat*) 1169 1170DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) 1171 1172DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) 1173 1174DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, 1175 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) 1176 1177DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, WGC3Dint, WGC3Dsizei, 1178 const WGC3Dfloat*) 1179 1180DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, 1181 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) 1182 1183DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) 1184 1185DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv, 1186 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) 1187 1188DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv, 1189 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) 1190 1191DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv, 1192 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) 1193 1194DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId) 1195 1196DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) 1197 1198DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) 1199 1200DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, 1201 const WGC3Dfloat*) 1202 1203DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, WGC3Duint, 1204 WGC3Dfloat, WGC3Dfloat) 1205 1206DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, 1207 const WGC3Dfloat*) 1208 1209DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, WGC3Duint, 1210 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) 1211 1212DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, 1213 const WGC3Dfloat*) 1214 1215DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, WGC3Duint, 1216 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) 1217 1218DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, 1219 const WGC3Dfloat*) 1220 1221void WebGraphicsContext3DCommandBufferImpl::vertexAttribPointer( 1222 WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, 1223 WGC3Dsizei stride, WGC3Dintptr offset) { 1224 gl_->VertexAttribPointer( 1225 index, size, type, normalized, stride, 1226 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); 1227} 1228 1229DELEGATE_TO_GL_4(viewport, Viewport, 1230 WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) 1231 1232WebGLId WebGraphicsContext3DCommandBufferImpl::createBuffer() { 1233 GLuint o; 1234 gl_->GenBuffers(1, &o); 1235 return o; 1236} 1237 1238WebGLId WebGraphicsContext3DCommandBufferImpl::createFramebuffer() { 1239 GLuint o = 0; 1240 gl_->GenFramebuffers(1, &o); 1241 return o; 1242} 1243 1244DELEGATE_TO_GL_R(createProgram, CreateProgram, WebGLId) 1245 1246WebGLId WebGraphicsContext3DCommandBufferImpl::createRenderbuffer() { 1247 GLuint o; 1248 gl_->GenRenderbuffers(1, &o); 1249 return o; 1250} 1251 1252DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId) 1253 1254WebGLId WebGraphicsContext3DCommandBufferImpl::createTexture() { 1255 GLuint o; 1256 gl_->GenTextures(1, &o); 1257 return o; 1258} 1259 1260void WebGraphicsContext3DCommandBufferImpl::deleteBuffer(WebGLId buffer) { 1261 gl_->DeleteBuffers(1, &buffer); 1262} 1263 1264void WebGraphicsContext3DCommandBufferImpl::deleteFramebuffer( 1265 WebGLId framebuffer) { 1266 gl_->DeleteFramebuffers(1, &framebuffer); 1267} 1268 1269DELEGATE_TO_GL_1(deleteProgram, DeleteProgram, WebGLId) 1270 1271void WebGraphicsContext3DCommandBufferImpl::deleteRenderbuffer( 1272 WebGLId renderbuffer) { 1273 gl_->DeleteRenderbuffers(1, &renderbuffer); 1274} 1275 1276DELEGATE_TO_GL_1(deleteShader, DeleteShader, WebGLId) 1277 1278void WebGraphicsContext3DCommandBufferImpl::deleteTexture(WebGLId texture) { 1279 gl_->DeleteTextures(1, &texture); 1280} 1281 1282bool WebGraphicsContext3DCommandBufferImpl::ShouldUseSwapClient() { 1283 return factory_ && factory_->IsMainThread() && swap_client_.get(); 1284} 1285 1286void WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete() { 1287 typedef WebGraphicsContext3DSwapBuffersClient WGC3DSwapClient; 1288 // This may be called after tear-down of the RenderView. 1289 if (ShouldUseSwapClient()) { 1290 base::MessageLoop::current()->PostTask( 1291 FROM_HERE, 1292 base::Bind(&WGC3DSwapClient::OnViewContextSwapBuffersComplete, 1293 swap_client_)); 1294 } 1295 1296 if (swapbuffers_complete_callback_) 1297 swapbuffers_complete_callback_->onSwapBuffersComplete(); 1298} 1299 1300WebGraphicsMemoryAllocation::PriorityCutoff 1301 WebGraphicsContext3DCommandBufferImpl::WebkitPriorityCutoff( 1302 GpuMemoryAllocationForRenderer::PriorityCutoff priorityCutoff) { 1303 switch (priorityCutoff) { 1304 case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNothing: 1305 return WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing; 1306 case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowOnlyRequired: 1307 return WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly; 1308 case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNiceToHave: 1309 return WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleAndNearby; 1310 case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything: 1311 return WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything; 1312 } 1313 NOTREACHED(); 1314 return WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything; 1315} 1316 1317void WebGraphicsContext3DCommandBufferImpl::OnMemoryAllocationChanged( 1318 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback, 1319 const GpuMemoryAllocationForRenderer& allocation) { 1320 1321 // Convert the gpu structure to the WebKit structure. 1322 WebGraphicsMemoryAllocation web_allocation; 1323 web_allocation.bytesLimitWhenVisible = 1324 ClampUint64ToSizeT(allocation.bytes_limit_when_visible); 1325 web_allocation.priorityCutoffWhenVisible = 1326 WebkitPriorityCutoff(allocation.priority_cutoff_when_visible); 1327 web_allocation.bytesLimitWhenNotVisible = 1328 ClampUint64ToSizeT(allocation.bytes_limit_when_not_visible); 1329 web_allocation.priorityCutoffWhenNotVisible = 1330 WebkitPriorityCutoff(allocation.priority_cutoff_when_not_visible); 1331 web_allocation.haveBackbufferWhenNotVisible = 1332 allocation.have_backbuffer_when_not_visible; 1333 1334 // Populate deprecated WebKit fields. These may be removed when references to 1335 // them in WebKit are removed. 1336 web_allocation.gpuResourceSizeInBytes = 1337 ClampUint64ToSizeT(allocation.bytes_limit_when_visible); 1338 web_allocation.suggestHaveBackbuffer = 1339 allocation.have_backbuffer_when_not_visible; 1340 1341 if (callback) 1342 callback->onMemoryAllocationChanged(web_allocation); 1343 1344 // We may have allocated transfer buffers in order to free GL resources in a 1345 // backgrounded tab. Re-free the transfer buffers. 1346 if (!visible_) 1347 real_gl_->FreeEverything(); 1348} 1349 1350void WebGraphicsContext3DCommandBufferImpl::setErrorMessageCallback( 1351 WebGraphicsContext3D::WebGraphicsErrorMessageCallback* cb) { 1352 error_message_callback_ = cb; 1353} 1354 1355void WebGraphicsContext3DCommandBufferImpl::setContextLostCallback( 1356 WebGraphicsContext3D::WebGraphicsContextLostCallback* cb) { 1357 context_lost_callback_ = cb; 1358} 1359 1360WGC3Denum WebGraphicsContext3DCommandBufferImpl::getGraphicsResetStatusARB() { 1361 if (IsCommandBufferContextLost() && 1362 context_lost_reason_ == GL_NO_ERROR) { 1363 return GL_UNKNOWN_CONTEXT_RESET_ARB; 1364 } 1365 1366 return context_lost_reason_; 1367} 1368 1369bool WebGraphicsContext3DCommandBufferImpl::IsCommandBufferContextLost() { 1370 // If the channel shut down unexpectedly, let that supersede the 1371 // command buffer's state. 1372 if (host_.get() && host_->IsLost()) 1373 return true; 1374 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); 1375 return state.error == gpu::error::kLostContext; 1376} 1377 1378// static 1379WebGraphicsContext3DCommandBufferImpl* 1380WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 1381 GpuChannelHostFactory* factory, 1382 const WebGraphicsContext3D::Attributes& attributes, 1383 const GURL& active_url) { 1384 if (!factory) 1385 return NULL; 1386 base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> null_client; 1387 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( 1388 new WebGraphicsContext3DCommandBufferImpl( 1389 0, active_url, factory, null_client)); 1390 CauseForGpuLaunch cause = 1391 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; 1392 if (context->InitializeWithDefaultBufferSizes(attributes, false, cause)) 1393 return context.release(); 1394 return NULL; 1395} 1396 1397void WebGraphicsContext3DCommandBufferImpl:: 1398 setSwapBuffersCompleteCallbackCHROMIUM( 1399 WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* cb) { 1400 swapbuffers_complete_callback_ = cb; 1401} 1402 1403DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM, 1404 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Duint, WGC3Duint) 1405 1406DELEGATE_TO_GL_5(texStorage2DEXT, TexStorage2DEXT, 1407 WGC3Denum, WGC3Dint, WGC3Duint, WGC3Dint, WGC3Dint) 1408 1409WebGLId WebGraphicsContext3DCommandBufferImpl::createQueryEXT() { 1410 GLuint o; 1411 gl_->GenQueriesEXT(1, &o); 1412 return o; 1413} 1414 1415void WebGraphicsContext3DCommandBufferImpl::deleteQueryEXT( 1416 WebGLId query) { 1417 gl_->DeleteQueriesEXT(1, &query); 1418} 1419 1420DELEGATE_TO_GL_1R(isQueryEXT, IsQueryEXT, WebGLId, WGC3Dboolean) 1421DELEGATE_TO_GL_2(beginQueryEXT, BeginQueryEXT, WGC3Denum, WebGLId) 1422DELEGATE_TO_GL_1(endQueryEXT, EndQueryEXT, WGC3Denum) 1423DELEGATE_TO_GL_3(getQueryivEXT, GetQueryivEXT, WGC3Denum, WGC3Denum, WGC3Dint*) 1424DELEGATE_TO_GL_3(getQueryObjectuivEXT, GetQueryObjectuivEXT, 1425 WebGLId, WGC3Denum, WGC3Duint*) 1426 1427DELEGATE_TO_GL_6(copyTextureCHROMIUM, CopyTextureCHROMIUM, WGC3Denum, 1428 WebGLId, WebGLId, WGC3Dint, WGC3Denum, WGC3Denum); 1429 1430DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM, 1431 WebGLId, WGC3Dint, const WGC3Dchar*) 1432 1433DELEGATE_TO_GL(shallowFlushCHROMIUM, ShallowFlushCHROMIUM); 1434DELEGATE_TO_GL(shallowFinishCHROMIUM, ShallowFinishCHROMIUM); 1435 1436DELEGATE_TO_GL_1(waitSyncPoint, WaitSyncPointCHROMIUM, GLuint) 1437 1438static void SignalSyncPointCallback( 1439 scoped_ptr< 1440 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> callback) { 1441 callback->onSyncPointReached(); 1442} 1443 1444void WebGraphicsContext3DCommandBufferImpl::signalSyncPoint( 1445 unsigned sync_point, 1446 WebGraphicsSyncPointCallback* callback) { 1447 // Take ownership of the callback. 1448 scoped_ptr<WebGraphicsSyncPointCallback> own_callback(callback); 1449 command_buffer_->SignalSyncPoint( 1450 sync_point, 1451 base::Bind(&SignalSyncPointCallback, base::Passed(&own_callback))); 1452} 1453 1454void WebGraphicsContext3DCommandBufferImpl::signalQuery( 1455 unsigned query, 1456 WebGraphicsSyncPointCallback* callback) { 1457 // Take ownership of the callback. 1458 scoped_ptr<WebGraphicsSyncPointCallback> own_callback(callback); 1459 // Flush any pending commands to make sure that the the query 1460 // has actually been created/started before we try to attach 1461 // a callback to it. 1462 gl_->Flush(); 1463 command_buffer_->SignalQuery( 1464 query, 1465 base::Bind(&SignalSyncPointCallback, base::Passed(&own_callback))); 1466} 1467 1468void WebGraphicsContext3DCommandBufferImpl::loseContextCHROMIUM( 1469 WGC3Denum current, WGC3Denum other) { 1470 gl_->LoseContextCHROMIUM(current, other); 1471 gl_->Flush(); 1472} 1473 1474void WebGraphicsContext3DCommandBufferImpl::genMailboxCHROMIUM( 1475 WGC3Dbyte* name) { 1476 std::vector<gpu::Mailbox> names; 1477 if (command_buffer_->GenerateMailboxNames(1, &names)) 1478 memcpy(name, names[0].name, GL_MAILBOX_SIZE_CHROMIUM); 1479 else 1480 synthesizeGLError(GL_OUT_OF_MEMORY); 1481} 1482 1483DELEGATE_TO_GL_2(produceTextureCHROMIUM, ProduceTextureCHROMIUM, 1484 WGC3Denum, const WGC3Dbyte*) 1485DELEGATE_TO_GL_2(consumeTextureCHROMIUM, ConsumeTextureCHROMIUM, 1486 WGC3Denum, const WGC3Dbyte*) 1487 1488void WebGraphicsContext3DCommandBufferImpl::insertEventMarkerEXT( 1489 const WGC3Dchar* marker) { 1490 gl_->InsertEventMarkerEXT(0, marker); 1491} 1492 1493void WebGraphicsContext3DCommandBufferImpl::pushGroupMarkerEXT( 1494 const WGC3Dchar* marker) { 1495 gl_->PushGroupMarkerEXT(0, marker); 1496} 1497 1498DELEGATE_TO_GL(popGroupMarkerEXT, PopGroupMarkerEXT); 1499 1500WebGLId WebGraphicsContext3DCommandBufferImpl::createVertexArrayOES() { 1501 GLuint array; 1502 gl_->GenVertexArraysOES(1, &array); 1503 return array; 1504} 1505 1506void WebGraphicsContext3DCommandBufferImpl::deleteVertexArrayOES( 1507 WebGLId array) { 1508 gl_->DeleteVertexArraysOES(1, &array); 1509} 1510 1511DELEGATE_TO_GL_1R(isVertexArrayOES, IsVertexArrayOES, WebGLId, WGC3Dboolean) 1512DELEGATE_TO_GL_1(bindVertexArrayOES, BindVertexArrayOES, WebGLId) 1513 1514DELEGATE_TO_GL_2(bindTexImage2DCHROMIUM, BindTexImage2DCHROMIUM, 1515 WGC3Denum, WGC3Dint) 1516DELEGATE_TO_GL_2(releaseTexImage2DCHROMIUM, ReleaseTexImage2DCHROMIUM, 1517 WGC3Denum, WGC3Dint) 1518 1519DELEGATE_TO_GL_2R(mapBufferCHROMIUM, MapBufferCHROMIUM, WGC3Denum, WGC3Denum, 1520 void*) 1521DELEGATE_TO_GL_1R(unmapBufferCHROMIUM, UnmapBufferCHROMIUM, WGC3Denum, 1522 WGC3Dboolean) 1523 1524DELEGATE_TO_GL_9(asyncTexImage2DCHROMIUM, AsyncTexImage2DCHROMIUM, WGC3Denum, 1525 WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, WGC3Dint, 1526 WGC3Denum, WGC3Denum, const void*) 1527DELEGATE_TO_GL_9(asyncTexSubImage2DCHROMIUM, AsyncTexSubImage2DCHROMIUM, 1528 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, 1529 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) 1530 1531DELEGATE_TO_GL_1(waitAsyncTexImage2DCHROMIUM, WaitAsyncTexImage2DCHROMIUM, 1532 WGC3Denum) 1533 1534DELEGATE_TO_GL_2(drawBuffersEXT, DrawBuffersEXT, WGC3Dsizei, const WGC3Denum*) 1535 1536DELEGATE_TO_GL_4(drawArraysInstancedANGLE, DrawArraysInstancedANGLE, WGC3Denum, 1537 WGC3Dint, WGC3Dsizei, WGC3Dsizei) 1538 1539void WebGraphicsContext3DCommandBufferImpl::drawElementsInstancedANGLE( 1540 WGC3Denum mode, 1541 WGC3Dsizei count, 1542 WGC3Denum type, 1543 WGC3Dintptr offset, 1544 WGC3Dsizei primcount) { 1545 gl_->DrawElementsInstancedANGLE( 1546 mode, count, type, 1547 reinterpret_cast<void*>(static_cast<intptr_t>(offset)), primcount); 1548} 1549 1550DELEGATE_TO_GL_2(vertexAttribDivisorANGLE, VertexAttribDivisorANGLE, WGC3Duint, 1551 WGC3Duint) 1552 1553GrGLInterface* WebGraphicsContext3DCommandBufferImpl::onCreateGrGLInterface() { 1554 return webkit::gpu::CreateCommandBufferSkiaGLBinding(); 1555} 1556 1557namespace { 1558 1559WGC3Denum convertReason(gpu::error::ContextLostReason reason) { 1560 switch (reason) { 1561 case gpu::error::kGuilty: 1562 return GL_GUILTY_CONTEXT_RESET_ARB; 1563 case gpu::error::kInnocent: 1564 return GL_INNOCENT_CONTEXT_RESET_ARB; 1565 case gpu::error::kUnknown: 1566 return GL_UNKNOWN_CONTEXT_RESET_ARB; 1567 } 1568 1569 NOTREACHED(); 1570 return GL_UNKNOWN_CONTEXT_RESET_ARB; 1571} 1572 1573} // anonymous namespace 1574 1575void WebGraphicsContext3DCommandBufferImpl::OnContextLost() { 1576 context_lost_reason_ = convertReason( 1577 command_buffer_->GetLastState().context_lost_reason); 1578 if (context_lost_callback_) { 1579 context_lost_callback_->onContextLost(); 1580 } 1581 if (attributes_.shareResources) 1582 ClearSharedContextsIfInShareSet(this); 1583 if (ShouldUseSwapClient()) 1584 swap_client_->OnViewContextSwapBuffersAborted(); 1585} 1586 1587void WebGraphicsContext3DCommandBufferImpl::OnErrorMessage( 1588 const std::string& message, int id) { 1589 if (error_message_callback_) { 1590 WebKit::WebString str = WebKit::WebString::fromUTF8(message.c_str()); 1591 error_message_callback_->onErrorMessage(str, id); 1592 } 1593} 1594 1595} // namespace content 1596