diff options
33 files changed, 288 insertions, 135 deletions
@@ -2,6 +2,7 @@ include_rules = [ "+gpu/GLES2", "+gpu/command_buffer/client/context_support.h", "+gpu/command_buffer/common/gpu_memory_allocation.h", + "+gpu/command_buffer/common/capabilities.h", "+gpu/command_buffer/common/mailbox.h", "+media", "+skia/ext", diff --git a/cc/output/context_provider.cc b/cc/output/context_provider.cc index 853a519..e8e5c9d 100644 --- a/cc/output/context_provider.cc +++ b/cc/output/context_provider.cc @@ -27,4 +27,24 @@ ContextProvider::Capabilities::Capabilities() discard_framebuffer(false), max_transfer_buffer_usage_bytes(std::numeric_limits<size_t>::max()) {} +ContextProvider::Capabilities::Capabilities( + const gpu::Capabilities& gpu_capabilities) + : discard_backbuffer(false), + egl_image_external(gpu_capabilities.egl_image_external), + fast_npot_mo8_textures(gpu_capabilities.fast_npot_mo8_textures), + iosurface(gpu_capabilities.iosurface), + map_image(gpu_capabilities.map_image), + map_sub(false), + post_sub_buffer(gpu_capabilities.post_sub_buffer), + set_visibility(false), + shallow_flush(false), + swapbuffers_complete_callback(false), + texture_format_bgra8888(gpu_capabilities.texture_format_bgra8888), + texture_format_etc1(gpu_capabilities.texture_format_etc1), + texture_rectangle(gpu_capabilities.texture_rectangle), + texture_storage(gpu_capabilities.texture_storage), + texture_usage(gpu_capabilities.texture_usage), + discard_framebuffer(gpu_capabilities.discard_framebuffer), + max_transfer_buffer_usage_bytes(std::numeric_limits<size_t>::max()) {} + } // namespace cc diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h index a79fbfc..72a627cb 100644 --- a/cc/output/context_provider.h +++ b/cc/output/context_provider.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "cc/base/cc_export.h" +#include "gpu/command_buffer/common/capabilities.h" class GrContext; namespace blink { class WebGraphicsContext3D; } @@ -48,6 +49,10 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { size_t max_transfer_buffer_usage_bytes; CC_EXPORT Capabilities(); + + // TODO(boliu): Compose a gpu::Capabilities instead and remove this + // constructor. + explicit CC_EXPORT Capabilities(const gpu::Capabilities& gpu_capabilities); }; // Returns the capabilities of the currently bound 3d context. virtual Capabilities ContextCapabilities() = 0; diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc index 8013932..23a0848c 100644 --- a/content/common/gpu/client/command_buffer_proxy_impl.cc +++ b/content/common/gpu/client/command_buffer_proxy_impl.cc @@ -155,7 +155,8 @@ bool CommandBufferProxyImpl::Initialize() { return false; bool result; - if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, handle, &result))) { + if (!Send(new GpuCommandBufferMsg_Initialize( + route_id_, handle, &result, &capabilities_))) { LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize."; return false; } @@ -165,6 +166,8 @@ bool CommandBufferProxyImpl::Initialize() { return false; } + capabilities_.map_image = true; + return true; } @@ -365,8 +368,8 @@ void CommandBufferProxyImpl::SetContextLostReason( NOTREACHED(); } -bool CommandBufferProxyImpl::SupportsGpuMemoryBuffer() { - return true; +gpu::Capabilities CommandBufferProxyImpl::GetCapabilities() { + return capabilities_; } gfx::GpuMemoryBuffer* CommandBufferProxyImpl::CreateGpuMemoryBuffer( diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h index b018367..ee85fd7 100644 --- a/content/common/gpu/client/command_buffer_proxy_impl.h +++ b/content/common/gpu/client/command_buffer_proxy_impl.h @@ -96,7 +96,7 @@ class CommandBufferProxyImpl gpu::error::ContextLostReason reason) OVERRIDE; // gpu::GpuControl implementation: - virtual bool SupportsGpuMemoryBuffer() OVERRIDE; + virtual gpu::Capabilities GetCapabilities() OVERRIDE; virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( size_t width, size_t height, @@ -207,6 +207,8 @@ class CommandBufferProxyImpl // Local cache of id to gpu memory buffer mapping. GpuMemoryBufferMap gpu_memory_buffers_; + gpu::Capabilities capabilities_; + DISALLOW_COPY_AND_ASSIGN(CommandBufferProxyImpl); }; diff --git a/content/common/gpu/client/context_provider_command_buffer.cc b/content/common/gpu/client/context_provider_command_buffer.cc index 990a151..b769cb4 100644 --- a/content/common/gpu/client/context_provider_command_buffer.cc +++ b/content/common/gpu/client/context_provider_command_buffer.cc @@ -8,7 +8,6 @@ #include <vector> #include "base/callback_helpers.h" -#include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "cc/output/managed_memory_policy.h" #include "gpu/command_buffer/client/gles2_implementation.h" @@ -112,8 +111,7 @@ bool ContextProviderCommandBuffer::BindToCurrentThread() { if (!context3d_->makeContextCurrent()) return false; - if (!InitializeCapabilities()) - return false; + InitializeCapabilities(); std::string unique_context_name = base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get()); @@ -208,11 +206,11 @@ void ContextProviderCommandBuffer::OnMemoryAllocationChanged( memory_policy_changed_callback_.Run(cc::ManagedMemoryPolicy(allocation)); } -bool ContextProviderCommandBuffer::InitializeCapabilities() { +void ContextProviderCommandBuffer::InitializeCapabilities() { // The command buffer provides the following capabilities always. // TODO(jamesr): This information is duplicated with // gpu::gles2::FeatureInfo::AddFeatures(). - Capabilities caps; + Capabilities caps(context3d_->GetImplementation()->capabilities()); caps.discard_backbuffer = true; caps.set_visibility = true; @@ -225,56 +223,12 @@ bool ContextProviderCommandBuffer::InitializeCapabilities() { // command buffer implementations. caps.swapbuffers_complete_callback = true; - const GLubyte* extensions_cstr = - context3d_->GetImplementation()->GetString(0x1F03 /* GL_EXTENSIONS */); - if (!extensions_cstr) - return false; - std::string extensions = reinterpret_cast<const char*>(extensions_cstr); - std::vector<std::string> extension_list; - base::SplitString(extensions, ' ', &extension_list); - std::set<std::string> extension_set(extension_list.begin(), - extension_list.end()); - - - // caps.map_image depends on GL_CHROMIUM_map_image, which is set client-side - // based on the presence of GpuControl. - caps.map_image = extension_set.count("GL_CHROMIUM_map_image") > 0; - - // caps.fast_npot_mo8_textures depends on - // workarounds_.enable_chromium_fast_npot_mo8_textures which controls - // GL_CHROMIUM_fast_NPOT_MO8_textures - caps.fast_npot_mo8_textures = - extension_set.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0; - - caps.egl_image_external = - extension_set.count("GL_OES_EGL_image_external") > 0; - - caps.texture_format_bgra8888 = - extension_set.count("GL_EXT_texture_format_BGRA8888") > 0; - - caps.texture_format_etc1 = - extension_set.count("GL_OES_compressed_ETC1_RGB8_texture") > 0; - - caps.texture_rectangle = extension_set.count("GL_ARB_texture_rectangle") > 0; - - caps.post_sub_buffer = extension_set.count("GL_CHROMIUM_post_sub_buffer") > 0; - - // TODO(jamesr): This is unconditionally true on mac, no need to test for it - // at runtime. - caps.iosurface = extension_set.count("GL_CHROMIUM_iosurface") > 0; - - caps.texture_usage = extension_set.count("GL_ANGLE_texture_usage") > 0; - caps.texture_storage = extension_set.count("GL_EXT_texture_storage") > 0; - - caps.discard_framebuffer = - extension_set.count("GL_EXT_discard_framebuffer") > 0; size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit(); caps.max_transfer_buffer_usage_bytes = mapped_memory_limit == WebGraphicsContext3DCommandBufferImpl::kNoLimit ? std::numeric_limits<size_t>::max() : mapped_memory_limit; capabilities_ = caps; - return true; } diff --git a/content/common/gpu/client/context_provider_command_buffer.h b/content/common/gpu/client/context_provider_command_buffer.h index 5ee668c..e0c6816 100644 --- a/content/common/gpu/client/context_provider_command_buffer.h +++ b/content/common/gpu/client/context_provider_command_buffer.h @@ -63,7 +63,7 @@ class CONTENT_EXPORT ContextProviderCommandBuffer void OnMemoryAllocationChanged(const gpu::MemoryAllocation& allocation); private: - bool InitializeCapabilities(); + void InitializeCapabilities(); base::ThreadChecker main_thread_checker_; base::ThreadChecker context_thread_checker_; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 1bcfbe8..7dc3ada 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -390,7 +390,8 @@ void GpuCommandBufferStub::Destroy() { void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) { Destroy(); - GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, false); + GpuCommandBufferMsg_Initialize::WriteReplyParams( + reply_message, false, gpu::Capabilities()); Send(reply_message); } @@ -412,12 +413,6 @@ void GpuCommandBufferStub::OnInitialize( return; } - gpu_control_.reset( - new gpu::GpuControlService(context_group_->image_manager(), - NULL, - context_group_->mailbox_manager(), - NULL)); - decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group_.get())); scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(), @@ -519,6 +514,13 @@ void GpuCommandBufferStub::OnInitialize( return; } + gpu_control_.reset( + new gpu::GpuControlService(context_group_->image_manager(), + NULL, + context_group_->mailbox_manager(), + NULL, + decoder_->GetCapabilities())); + if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUServiceLogging)) { decoder_->set_log_commands(true); @@ -557,7 +559,8 @@ void GpuCommandBufferStub::OnInitialize( return; } - GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, true); + GpuCommandBufferMsg_Initialize::WriteReplyParams( + reply_message, true, gpu_control_->GetCapabilities()); Send(reply_message); if (handle_.is_null() && !active_url_.is_empty()) { diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 08821bc..f399a89 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -15,6 +15,7 @@ #include "content/common/gpu/gpu_rendering_stats.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/gpu_memory_stats.h" +#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/gpu_memory_allocation.h" @@ -166,6 +167,20 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo) #endif IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities) + IPC_STRUCT_TRAITS_MEMBER(post_sub_buffer) + IPC_STRUCT_TRAITS_MEMBER(fast_npot_mo8_textures) + IPC_STRUCT_TRAITS_MEMBER(egl_image_external) + IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888) + IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1) + IPC_STRUCT_TRAITS_MEMBER(texture_rectangle) + IPC_STRUCT_TRAITS_MEMBER(iosurface) + IPC_STRUCT_TRAITS_MEMBER(texture_usage) + IPC_STRUCT_TRAITS_MEMBER(texture_storage) + IPC_STRUCT_TRAITS_MEMBER(discard_framebuffer) + IPC_STRUCT_TRAITS_MEMBER(map_image) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(content::GPUVideoMemoryUsageStats::ProcessStats) IPC_STRUCT_TRAITS_MEMBER(video_memory) IPC_STRUCT_TRAITS_MEMBER(has_duplicates) @@ -520,9 +535,10 @@ IPC_MESSAGE_ROUTED1(GpuStreamTextureMsg_MatrixChanged, // Initialize a command buffer with the given number of command entries. // Returns the shared memory handle for the command buffer mapped to the // calling process. -IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_Initialize, +IPC_SYNC_MESSAGE_ROUTED1_2(GpuCommandBufferMsg_Initialize, base::SharedMemoryHandle /* shared_state */, - bool /* result */) + bool /* result */, + gpu::Capabilities /* capabilities */) // Sets the shared memory buffer used for commands. IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_SetGetBuffer, diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h index ac0a271..4842cc0 100644 --- a/gpu/command_buffer/client/client_test_helper.h +++ b/gpu/command_buffer/client/client_test_helper.h @@ -87,7 +87,7 @@ class MockClientGpuControl : public GpuControl { MockClientGpuControl(); virtual ~MockClientGpuControl(); - MOCK_METHOD0(SupportsGpuMemoryBuffer, bool()); + MOCK_METHOD0(GetCapabilities, Capabilities()); MOCK_METHOD4(CreateGpuMemoryBuffer, gfx::GpuMemoryBuffer*(size_t width, size_t height, diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index df70976..1e97f19 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -112,6 +112,7 @@ GLES2Implementation::GLES2Implementation( current_query_(NULL), error_message_callback_(NULL), gpu_control_(gpu_control), + capabilities_(gpu_control->GetCapabilities()), weak_ptr_factory_(this) { DCHECK(helper); DCHECK(transfer_buffer); @@ -2131,7 +2132,7 @@ const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { "GL_CHROMIUM_map_sub " "GL_CHROMIUM_shallow_flush " "GL_EXT_unpack_subimage"; - if (gpu_control_->SupportsGpuMemoryBuffer()) { + if (capabilities_.map_image) { // The first space character is intentional. str += " GL_CHROMIUM_map_image"; } diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 2268195..0f47a78 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -28,6 +28,7 @@ #include "gpu/command_buffer/client/ref_counted.h" #include "gpu/command_buffer/client/ring_buffer.h" #include "gpu/command_buffer/client/share_group.h" +#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/debug_marker_manager.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -242,6 +243,10 @@ class GLES2_IMPL_EXPORT GLES2Implementation return share_group_.get(); } + const Capabilities& capabilities() const { + return capabilities_; + } + private: friend class GLES2ImplementationTest; friend class VertexArrayObjectManager; @@ -690,6 +695,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation GpuControl* gpu_control_; + Capabilities capabilities_; + base::WeakPtrFactory<GLES2Implementation> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(GLES2Implementation); diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 0aa7da2..f2d4dbc 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -367,6 +367,8 @@ class GLES2ImplementationTest : public testing::Test { helper_->Initialize(kCommandBufferSizeBytes); gpu_control_.reset(new StrictMock<MockClientGpuControl>()); + EXPECT_CALL(*gpu_control_, GetCapabilities()) + .WillOnce(testing::Return(Capabilities())); GLES2Implementation::GLStaticState state; GLES2Implementation::GLStaticState::IntState& int_state = state.int_state; @@ -2479,8 +2481,7 @@ TEST_F(GLES2ImplementationTest, GetString) { "GL_CHROMIUM_flipy " "GL_CHROMIUM_map_sub " "GL_CHROMIUM_shallow_flush " - "GL_EXT_unpack_subimage " - "GL_CHROMIUM_map_image"; + "GL_EXT_unpack_subimage"; const char kBad = 0x12; struct Cmds { cmd::SetBucketSize set_bucket_size1; @@ -2503,8 +2504,6 @@ TEST_F(GLES2ImplementationTest, GetString) { char buf[sizeof(kString) + 1]; memset(buf, kBad, sizeof(buf)); - EXPECT_CALL(*gpu_control_.get(), SupportsGpuMemoryBuffer()) - .WillOnce(Return(true)); EXPECT_CALL(*command_buffer(), OnFlush()) .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), SetMemory(mem1.ptr, kString))) @@ -2541,8 +2540,6 @@ TEST_F(GLES2ImplementationTest, PixelStoreiGLPackReverseRowOrderANGLE) { expected.set_bucket_size2.Init(kBucketId, 0); expected.pixel_store.Init(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1); - EXPECT_CALL(*gpu_control_.get(), SupportsGpuMemoryBuffer()) - .WillOnce(Return(false)); EXPECT_CALL(*command_buffer(), OnFlush()) .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), SetMemory(mem1.ptr, kString))) diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc new file mode 100644 index 0000000..9f35c82 --- /dev/null +++ b/gpu/command_buffer/common/capabilities.cc @@ -0,0 +1,22 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/common/capabilities.h" + +namespace gpu { + +Capabilities::Capabilities() + : post_sub_buffer(false), + fast_npot_mo8_textures(false), + egl_image_external(false), + texture_format_bgra8888(false), + texture_format_etc1(false), + texture_rectangle(false), + iosurface(false), + texture_usage(false), + texture_storage(false), + discard_framebuffer(false), + map_image(false) {} + +} // namespace gpu diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h new file mode 100644 index 0000000..b6c34da --- /dev/null +++ b/gpu/command_buffer/common/capabilities.h @@ -0,0 +1,32 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_COMMON_CAPABILITIES_H_ +#define GPU_COMMAND_BUFFER_COMMON_CAPABILITIES_H_ + +#include "gpu/gpu_export.h" + +namespace gpu { + +struct GPU_EXPORT Capabilities { + bool post_sub_buffer; + bool fast_npot_mo8_textures; + bool egl_image_external; + bool texture_format_bgra8888; + bool texture_format_etc1; + bool texture_rectangle; + bool iosurface; + bool texture_usage; + bool texture_storage; + bool discard_framebuffer; + + // Capabilities below are not populated by GLES2Decoder. + bool map_image; + + Capabilities(); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_COMMON_CAPABILITIES_H_ diff --git a/gpu/command_buffer/common/gpu_control.h b/gpu/command_buffer/common/gpu_control.h index 4fdab4b..eb17153 100644 --- a/gpu/command_buffer/common/gpu_control.h +++ b/gpu/command_buffer/common/gpu_control.h @@ -8,6 +8,7 @@ #include <vector> #include "base/callback.h" +#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/types.h" #include "gpu/gpu_export.h" @@ -25,7 +26,7 @@ class GPU_EXPORT GpuControl { GpuControl() {} virtual ~GpuControl() {} - virtual bool SupportsGpuMemoryBuffer() = 0; + virtual Capabilities GetCapabilities() = 0; // Create a gpu memory buffer of the given dimensions and format. Returns // its ID or -1 on error. diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 40c3701..57db99b 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -106,6 +106,7 @@ FeatureInfo::FeatureFlags::FeatureFlags() oes_standard_derivatives(false), oes_egl_image_external(false), oes_depth24(false), + oes_compressed_etc1_rgb8_texture(false), packed_depth24_stencil8(false), npot_ok(false), enable_texture_float_linear(false), @@ -119,6 +120,7 @@ FeatureInfo::FeatureFlags::FeatureFlags() use_arb_occlusion_query2_for_occlusion_query_boolean(false), use_arb_occlusion_query_for_occlusion_query_boolean(false), native_vertex_array_object(false), + ext_texture_format_bgra8888(false), enable_shader_name_hashing(false), enable_samplers(false), ext_draw_buffers(false), @@ -128,7 +130,9 @@ FeatureInfo::FeatureFlags::FeatureFlags() ext_discard_framebuffer(false), angle_depth_texture(false), is_angle(false), - is_swiftshader(false) { + is_swiftshader(false), + angle_texture_usage(false), + ext_texture_storage(false) { } FeatureInfo::Workarounds::Workarounds() : @@ -405,6 +409,7 @@ void FeatureInfo::InitializeFeatures() { } if (enable_texture_format_bgra8888) { + feature_flags_.ext_texture_format_bgra8888 = true; AddExtensionString("GL_EXT_texture_format_BGRA8888"); texture_format_validators_[GL_BGRA_EXT].AddValue(GL_UNSIGNED_BYTE); validators_.texture_internal_format.AddValue(GL_BGRA_EXT); @@ -557,6 +562,7 @@ void FeatureInfo::InitializeFeatures() { if (extensions.Contains("GL_OES_compressed_ETC1_RGB8_texture")) { AddExtensionString("GL_OES_compressed_ETC1_RGB8_texture"); + feature_flags_.oes_compressed_etc1_rgb8_texture = true; validators_.compressed_texture_format.AddValue(GL_ETC1_RGB8_OES); } @@ -600,11 +606,13 @@ void FeatureInfo::InitializeFeatures() { } if (extensions.Contains("GL_ANGLE_texture_usage")) { + feature_flags_.angle_texture_usage = true; AddExtensionString("GL_ANGLE_texture_usage"); validators_.texture_parameter.AddValue(GL_TEXTURE_USAGE_ANGLE); } if (extensions.Contains("GL_EXT_texture_storage")) { + feature_flags_.ext_texture_storage = true; AddExtensionString("GL_EXT_texture_storage"); validators_.texture_parameter.AddValue(GL_TEXTURE_IMMUTABLE_FORMAT_EXT); if (enable_texture_format_bgra8888) diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index 46eda99..ca8c03c 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h @@ -37,6 +37,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool oes_standard_derivatives; bool oes_egl_image_external; bool oes_depth24; + bool oes_compressed_etc1_rgb8_texture; bool packed_depth24_stencil8; bool npot_ok; bool enable_texture_float_linear; @@ -50,6 +51,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool use_arb_occlusion_query2_for_occlusion_query_boolean; bool use_arb_occlusion_query_for_occlusion_query_boolean; bool native_vertex_array_object; + bool ext_texture_format_bgra8888; bool enable_shader_name_hashing; bool enable_samplers; bool ext_draw_buffers; @@ -60,6 +62,8 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool angle_depth_texture; bool is_angle; bool is_swiftshader; + bool angle_texture_usage; + bool ext_texture_storage; }; struct Workarounds { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 3364f0c..71f168c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -19,6 +19,7 @@ #include "base/debug/trace_event.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "build/build_config.h" #define GLES2_GPU_SERVICE 1 #include "gpu/command_buffer/common/debug_marker_manager.h" @@ -543,6 +544,7 @@ class GLES2DecoderImpl : public GLES2Decoder, virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; } virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); } virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); } + virtual Capabilities GetCapabilities() OVERRIDE; virtual void RestoreState() const OVERRIDE; virtual void RestoreActiveTexture() const OVERRIDE { @@ -2527,6 +2529,41 @@ bool GLES2DecoderImpl::Initialize( return true; } +Capabilities GLES2DecoderImpl::GetCapabilities() { + DCHECK(initialized()); + + Capabilities caps; + + caps.fast_npot_mo8_textures = + feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures; + caps.egl_image_external = + feature_info_->feature_flags().oes_egl_image_external; + caps.texture_format_bgra8888 = + feature_info_->feature_flags().ext_texture_format_bgra8888; + caps.texture_format_etc1 = + feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture; + caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle; + caps.texture_usage = feature_info_->feature_flags().angle_texture_usage; + caps.texture_storage = feature_info_->feature_flags().ext_texture_storage; + caps.discard_framebuffer = + feature_info_->feature_flags().ext_discard_framebuffer; + +#if defined(OS_MACOSX) + // This is unconditionally true on mac, no need to test for it at runtime. + caps.iosurface = true; +#endif + + // TODO(boliu): Expose this directly from GLSurface. + std::vector<std::string> extension_list; + base::SplitString(surface_->GetExtensions(), ' ', &extension_list); + std::set<std::string> extension_set(extension_list.begin(), + extension_list.end()); + caps.post_sub_buffer = + extension_set.count("GL_CHROMIUM_post_sub_buffer") > 0; + + return caps; +} + void GLES2DecoderImpl::UpdateCapabilities() { util_.set_num_compressed_texture_formats( validators_->compressed_texture_format.GetValues().size()); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 4187e87..ce65f7e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "build/build_config.h" +#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/service/common_decoder.h" #include "gpu/command_buffer/service/logger.h" #include "ui/gfx/size.h" @@ -138,6 +139,8 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // Gets the associated ContextGroup virtual ContextGroup* GetContextGroup() = 0; + virtual Capabilities GetCapabilities() = 0; + // Restores all of the decoder GL state. virtual void RestoreState() const = 0; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index e993a5e..f52c221 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -52,6 +52,7 @@ class MockGLES2Decoder : public GLES2Decoder { MOCK_METHOD0(GetGLSurface, gfx::GLSurface*()); MOCK_METHOD0(GetGLContext, gfx::GLContext*()); MOCK_METHOD0(GetContextGroup, ContextGroup*()); + MOCK_METHOD0(GetCapabilities, Capabilities()); MOCK_METHOD0(ProcessPendingQueries, bool()); MOCK_METHOD0(HasMoreIdleWork, bool()); MOCK_METHOD0(PerformIdleWork, void()); diff --git a/gpu/command_buffer/service/gpu_control_service.cc b/gpu/command_buffer/service/gpu_control_service.cc index 8306ab0..1cb15bf 100644 --- a/gpu/command_buffer/service/gpu_control_service.cc +++ b/gpu/command_buffer/service/gpu_control_service.cc @@ -15,18 +15,22 @@ GpuControlService::GpuControlService( GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager, GpuMemoryBufferFactory* gpu_memory_buffer_factory, gles2::MailboxManager* mailbox_manager, - gles2::QueryManager* query_manager) + gles2::QueryManager* query_manager, + const gpu::Capabilities& decoder_capabilities) : gpu_memory_buffer_manager_(gpu_memory_buffer_manager), gpu_memory_buffer_factory_(gpu_memory_buffer_factory), mailbox_manager_(mailbox_manager), - query_manager_(query_manager) { + query_manager_(query_manager), + capabilities_(decoder_capabilities) { + capabilities_.map_image = + gpu_memory_buffer_manager_ && gpu_memory_buffer_factory_; } GpuControlService::~GpuControlService() { } -bool GpuControlService::SupportsGpuMemoryBuffer() { - return gpu_memory_buffer_manager_ && gpu_memory_buffer_factory_; +gpu::Capabilities GpuControlService::GetCapabilities() { + return capabilities_; } gfx::GpuMemoryBuffer* GpuControlService::CreateGpuMemoryBuffer( diff --git a/gpu/command_buffer/service/gpu_control_service.h b/gpu/command_buffer/service/gpu_control_service.h index b9e7474..df77850 100644 --- a/gpu/command_buffer/service/gpu_control_service.h +++ b/gpu/command_buffer/service/gpu_control_service.h @@ -25,11 +25,13 @@ class GPU_EXPORT GpuControlService : public GpuControl { GpuControlService(GpuMemoryBufferManagerInterface* gpu_memory_buffer_manager, GpuMemoryBufferFactory* gpu_memory_buffer_factory, gles2::MailboxManager* mailbox_manager, - gles2::QueryManager* query_manager); + gles2::QueryManager* query_manager, + const gpu::Capabilities& decoder_capabilities); virtual ~GpuControlService(); // Overridden from GpuControl: - virtual bool SupportsGpuMemoryBuffer() OVERRIDE; + + virtual gpu::Capabilities GetCapabilities() OVERRIDE; virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( size_t width, @@ -62,6 +64,7 @@ class GPU_EXPORT GpuControlService : public GpuControl { gles2::QueryManager* query_manager_; typedef std::map<int32, linked_ptr<gfx::GpuMemoryBuffer> > GpuMemoryBufferMap; GpuMemoryBufferMap gpu_memory_buffers_; + gpu::Capabilities capabilities_; DISALLOW_COPY_AND_ASSIGN(GpuControlService); }; diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index ab6e354..ba4e3fa 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc @@ -253,7 +253,6 @@ InProcessCommandBuffer::InProcessCommandBuffer() : context_lost_(false), share_group_id_(0), last_put_offset_(-1), - supports_gpu_memory_buffer_(false), flush_event_(false, false), queue_(CreateSchedulerClient()), gpu_thread_weak_ptr_factory_(this) {} @@ -328,36 +327,35 @@ bool InProcessCommandBuffer::Initialize( surface_ = surface; } + gpu::Capabilities capabilities; + InitializeOnGpuThreadParams params( + is_offscreen, window, size, attribs, gpu_preference, &capabilities); + base::Callback<bool(void)> init_task = base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread, base::Unretained(this), - is_offscreen, - window, - size, - attribs, - gpu_preference); + params); base::WaitableEvent completion(true, false); bool result = false; QueueTask( base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion)); completion.Wait(); + + if (result) + capabilities_ = capabilities; return result; } bool InProcessCommandBuffer::InitializeOnGpuThread( - bool is_offscreen, - gfx::AcceleratedWidget window, - const gfx::Size& size, - const std::vector<int32>& attribs, - gfx::GpuPreference gpu_preference) { + const InitializeOnGpuThreadParams& params) { CheckSequencedThread(); gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr(); // Use one share group for all contexts. CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, (new gfx::GLShareGroup)); - DCHECK(size.width() >= 0 && size.height() >= 0); + DCHECK(params.size.width() >= 0 && params.size.height() >= 0); TransferBufferManager* manager = new TransferBufferManager(); transfer_buffer_manager_.reset(manager); @@ -421,10 +419,10 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( decoder_->set_engine(gpu_scheduler_.get()); if (!surface_) { - if (is_offscreen) - surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); + if (params.is_offscreen) + surface_ = gfx::GLSurface::CreateOffscreenGLSurface(params.size); else - surface_ = gfx::GLSurface::CreateViewGLSurface(window); + surface_ = gfx::GLSurface::CreateViewGLSurface(params.window); } if (!surface_.get()) { @@ -437,20 +435,20 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( context_ = share_group->GetSharedContext(); if (!context_.get()) { context_ = gfx::GLContext::CreateGLContext( - share_group.get(), surface_.get(), gpu_preference); + share_group.get(), surface_.get(), params.gpu_preference); share_group->SetSharedContext(context_.get()); } context_ = new GLContextVirtual( share_group.get(), context_.get(), decoder_->AsWeakPtr()); - if (context_->Initialize(surface_.get(), gpu_preference)) { + if (context_->Initialize(surface_.get(), params.gpu_preference)) { VLOG(1) << "Created virtual GL context."; } else { context_ = NULL; } } else { context_ = gfx::GLContext::CreateGLContext( - share_group.get(), surface_.get(), gpu_preference); + share_group.get(), surface_.get(), params.gpu_preference); } if (!context_.get()) { @@ -470,10 +468,10 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( disallowed_features.gpu_memory_manager = true; if (!decoder_->Initialize(surface_, context_, - is_offscreen, - size, + params.is_offscreen, + params.size, disallowed_features, - attribs)) { + params.attribs)) { LOG(ERROR) << "Could not initialize decoder."; DestroyOnGpuThread(); return false; @@ -483,11 +481,12 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( new GpuControlService(decoder_->GetContextGroup()->image_manager(), g_gpu_memory_buffer_factory, decoder_->GetContextGroup()->mailbox_manager(), - decoder_->GetQueryManager())); - supports_gpu_memory_buffer_ = gpu_control_->SupportsGpuMemoryBuffer(); + decoder_->GetQueryManager(), + decoder_->GetCapabilities())); + *params.capabilities = gpu_control_->GetCapabilities(); - if (!is_offscreen) { + if (!params.is_offscreen) { decoder_->SetResizeCallback(base::Bind( &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_)); } @@ -678,8 +677,8 @@ gpu::Buffer InProcessCommandBuffer::GetTransferBuffer(int32 id) { return gpu::Buffer(); } -bool InProcessCommandBuffer::SupportsGpuMemoryBuffer() { - return supports_gpu_memory_buffer_; +gpu::Capabilities InProcessCommandBuffer::GetCapabilities() { + return capabilities_; } gfx::GpuMemoryBuffer* InProcessCommandBuffer::CreateGpuMemoryBuffer( diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h index ee39df6..404ac9d 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.h +++ b/gpu/command_buffer/service/in_process_command_buffer.h @@ -108,7 +108,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, virtual gpu::error::Error GetLastError() OVERRIDE; // GpuControl implementation: - virtual bool SupportsGpuMemoryBuffer() OVERRIDE; + virtual gpu::Capabilities GetCapabilities() OVERRIDE; virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( size_t width, size_t height, @@ -144,11 +144,29 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, #endif private: - bool InitializeOnGpuThread(bool is_offscreen, - gfx::AcceleratedWidget window, - const gfx::Size& size, - const std::vector<int32>& attribs, - gfx::GpuPreference gpu_preference); + struct InitializeOnGpuThreadParams { + bool is_offscreen; + gfx::AcceleratedWidget window; + const gfx::Size& size; + const std::vector<int32>& attribs; + gfx::GpuPreference gpu_preference; + gpu::Capabilities* capabilities; // Ouptut. + + InitializeOnGpuThreadParams(bool is_offscreen, + gfx::AcceleratedWidget window, + const gfx::Size& size, + const std::vector<int32>& attribs, + gfx::GpuPreference gpu_preference, + gpu::Capabilities* capabilities) + : is_offscreen(is_offscreen), + window(window), + size(size), + attribs(attribs), + gpu_preference(gpu_preference), + capabilities(capabilities) {} + }; + + bool InitializeOnGpuThread(const InitializeOnGpuThreadParams& params); bool DestroyOnGpuThread(); void FlushOnGpuThread(int32 put_offset); bool MakeCurrent(); @@ -180,7 +198,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, // Members accessed on the client thread: State last_state_; int32 last_put_offset_; - bool supports_gpu_memory_buffer_; + gpu::Capabilities capabilities_; // Accessed on both threads: scoped_ptr<CommandBuffer> command_buffer_; diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 1e00a02..1da8d67 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -174,7 +174,8 @@ void GLManager::Initialize(const GLManager::Options& options) { new GpuControlService(decoder_->GetContextGroup()->image_manager(), options.gpu_memory_buffer_factory, decoder_->GetContextGroup()->mailbox_manager(), - decoder_->GetQueryManager())); + decoder_->GetQueryManager(), + decoder_->GetCapabilities())); command_buffer_->SetPutOffsetChangeCallback( base::Bind(&GLManager::PumpCommands, base::Unretained(this))); diff --git a/gpu/command_buffer_common.gypi b/gpu/command_buffer_common.gypi index 587e7d6..87eeb5b 100644 --- a/gpu/command_buffer_common.gypi +++ b/gpu/command_buffer_common.gypi @@ -9,6 +9,8 @@ 'sources': [ 'command_buffer/common/bitfield_helpers.h', 'command_buffer/common/buffer.h', + 'command_buffer/common/capabilities.cc', + 'command_buffer/common/capabilities.h', 'command_buffer/common/cmd_buffer_common.h', 'command_buffer/common/cmd_buffer_common.cc', 'command_buffer/common/command_buffer.h', diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 6cbd047..118ef72 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -123,8 +123,6 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), decoder_.get(), NULL)); - gpu_control_.reset( - new gpu::GpuControlService(NULL, NULL, group->mailbox_manager(), NULL)); decoder_->set_engine(gpu_scheduler_.get()); gfx::Size size(create_offscreen_width_, create_offscreen_height_); @@ -172,6 +170,9 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, return EGL_NO_SURFACE; } + gpu_control_.reset(new gpu::GpuControlService( + NULL, NULL, group->mailbox_manager(), NULL, decoder_->GetCapabilities())); + command_buffer->SetPutOffsetChangeCallback( base::Bind(&gpu::GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.cc b/ppapi/proxy/ppapi_command_buffer_proxy.cc index 063cafb..5c2642d 100644 --- a/ppapi/proxy/ppapi_command_buffer_proxy.cc +++ b/ppapi/proxy/ppapi_command_buffer_proxy.cc @@ -218,8 +218,10 @@ void PpapiCommandBufferProxy::SendManagedMemoryStats( NOTREACHED(); } -bool PpapiCommandBufferProxy::SupportsGpuMemoryBuffer() { - return false; +gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() { + // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in + // crbug.com/325391. + return gpu::Capabilities(); } gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer( diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.h b/ppapi/proxy/ppapi_command_buffer_proxy.h index bca5190..94e2582 100644 --- a/ppapi/proxy/ppapi_command_buffer_proxy.h +++ b/ppapi/proxy/ppapi_command_buffer_proxy.h @@ -47,7 +47,7 @@ class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy OVERRIDE; // gpu::GpuControl implementation: - virtual bool SupportsGpuMemoryBuffer() OVERRIDE; + virtual gpu::Capabilities GetCapabilities() OVERRIDE; virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer( size_t width, size_t height, diff --git a/webkit/common/gpu/context_provider_in_process.cc b/webkit/common/gpu/context_provider_in_process.cc index f37bf90..d38b3a0 100644 --- a/webkit/common/gpu/context_provider_in_process.cc +++ b/webkit/common/gpu/context_provider_in_process.cc @@ -110,6 +110,8 @@ bool ContextProviderInProcess::BindToCurrentThread() { if (!context3d_->makeContextCurrent()) return false; + InitializeCapabilities(); + std::string unique_context_name = base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get()); context3d_->pushGroupMarkerEXT(unique_context_name.c_str()); @@ -120,28 +122,24 @@ bool ContextProviderInProcess::BindToCurrentThread() { return true; } -cc::ContextProvider::Capabilities -ContextProviderInProcess::ContextCapabilities() { +void ContextProviderInProcess::InitializeCapabilities() { + Capabilities caps(context3d_->GetImplementation()->capabilities()); + // We always use a WebGraphicsContext3DInProcessCommandBufferImpl which // provides the following capabilities: - Capabilities caps; caps.discard_backbuffer = true; - caps.map_image = true; caps.map_sub = true; caps.set_visibility = true; caps.shallow_flush = true; - caps.texture_format_bgra8888 = true; - caps.texture_rectangle = true; - - blink::WebString extensions = - context3d_->getString(0x1F03 /* GL_EXTENSIONS */); - std::vector<std::string> extension_list; - base::SplitString(extensions.utf8(), ' ', &extension_list); - std::set<std::string> extension_set(extension_list.begin(), - extension_list.end()); - - caps.post_sub_buffer = extension_set.count("GL_CHROMIUM_post_sub_buffer") > 0; - return caps; + + capabilities_ = caps; +} + +cc::ContextProvider::Capabilities +ContextProviderInProcess::ContextCapabilities() { + DCHECK(lost_context_callback_proxy_); // Is bound to thread. + DCHECK(context_thread_checker_.CalledOnValidThread()); + return capabilities_; } blink::WebGraphicsContext3D* ContextProviderInProcess::Context3d() { diff --git a/webkit/common/gpu/context_provider_in_process.h b/webkit/common/gpu/context_provider_in_process.h index c700614..2dbb7a6 100644 --- a/webkit/common/gpu/context_provider_in_process.h +++ b/webkit/common/gpu/context_provider_in_process.h @@ -57,6 +57,8 @@ class WEBKIT_GPU_EXPORT ContextProviderInProcess void OnSwapBuffersComplete(); private: + void InitializeCapabilities(); + base::ThreadChecker main_thread_checker_; base::ThreadChecker context_thread_checker_; @@ -78,6 +80,8 @@ class WEBKIT_GPU_EXPORT ContextProviderInProcess scoped_ptr<SwapBuffersCompleteCallbackProxy> swap_buffers_complete_callback_proxy_; + cc::ContextProvider::Capabilities capabilities_; + DISALLOW_COPY_AND_ASSIGN(ContextProviderInProcess); }; diff --git a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h index 7ebc5e8..76d1715 100644 --- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h @@ -555,6 +555,10 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl ::gpu::ContextSupport* GetContextSupport(); + ::gpu::gles2::GLES2Implementation* GetImplementation() { + return gl_; + } + private: WebGraphicsContext3DInProcessCommandBufferImpl( scoped_ptr< ::gpu::GLInProcessContext> context, |