diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 04:16:29 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 04:16:29 +0000 |
commit | 39aa139b52a9baf917f7b3f9f1ee647853aa4602 (patch) | |
tree | 8eca0f46bd878bd8e33a65e83b6c3e727688fee2 | |
parent | 6f41ac2a6d15c24e8d97eeb9be8c44330b5d5dfb (diff) | |
download | chromium_src-39aa139b52a9baf917f7b3f9f1ee647853aa4602.zip chromium_src-39aa139b52a9baf917f7b3f9f1ee647853aa4602.tar.gz chromium_src-39aa139b52a9baf917f7b3f9f1ee647853aa4602.tar.bz2 |
gpu: Lose context when BeginQueryEXT fails to allocate.
Instead of crashes, raise a GL_OUT_OF_MEMORY error. Since compositor
does not want to deal with these errors and it would leave it in a
bad state, add the ability to lose the context when GL_OUT_OF_MEMORY
occurs.
R=piman
BUG=351587
Review URL: https://codereview.chromium.org/199443004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261064 0039d316-1c4b-4281-b951-d872f2087c98
41 files changed, 853 insertions, 1028 deletions
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc index 86d1619..b17aa6c 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc @@ -44,12 +44,10 @@ scoped_ptr<gpu::GLInProcessContext> CreateContext( gpu::GLInProcessContextAttribs in_process_attribs; WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes( GetDefaultAttribs(), &in_process_attribs); + in_process_attribs.lose_context_when_out_of_memory = 1; scoped_ptr<gpu::GLInProcessContext> context( - gpu::GLInProcessContext::CreateWithSurface(surface, - service, - share_context, - in_process_attribs, - gpu_preference)); + gpu::GLInProcessContext::CreateWithSurface( + surface, service, share_context, in_process_attribs, gpu_preference)); return context.Pass(); } diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index bc9f7ec..79c1749 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -428,6 +428,8 @@ GpuProcessTransportFactory::CreateContextCommon(int surface_id) { attrs.stencil = false; attrs.antialias = false; attrs.noAutomaticFlushes = true; + bool bind_generates_resources = false; + bool lose_context_when_out_of_memory = true; CauseForGpuLaunch cause = CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; scoped_refptr<GpuChannelHost> gpu_channel_host( @@ -443,7 +445,8 @@ GpuProcessTransportFactory::CreateContextCommon(int surface_id) { url, gpu_channel_host.get(), attrs, - false, + bind_generates_resources, + lose_context_when_out_of_memory, WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)); return context.Pass(); diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index ebeceff..cbe4539 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc @@ -35,12 +35,14 @@ class ContextTestBase : public content::ContentBrowserTest { content::BrowserGpuChannelHostFactory* factory = content::BrowserGpuChannelHostFactory::instance(); CHECK(factory); + bool lose_context_when_out_of_memory = false; scoped_refptr<content::GpuChannelHost> gpu_channel_host( factory->EstablishGpuChannelSync(kInitCause)); context_.reset( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( gpu_channel_host.get(), blink::WebGraphicsContext3D::Attributes(), + lose_context_when_out_of_memory, GURL(), WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)); @@ -115,10 +117,12 @@ class BrowserGpuChannelHostFactoryTest : public ContentBrowserTest { } scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext() { + bool lose_context_when_out_of_memory = false; return make_scoped_ptr( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( GetGpuChannel(), blink::WebGraphicsContext3D::Attributes(), + lose_context_when_out_of_memory, GURL(), WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)); diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 6fd6a2a..b3ccbcc 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -518,12 +518,15 @@ CreateGpuProcessViewContext( limits.max_transfer_buffer_size = std::min( 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024; + bool bind_generates_resource = false; + bool lose_context_when_out_of_memory = true; return make_scoped_ptr( new WebGraphicsContext3DCommandBufferImpl(surface_id, url, gpu_channel_host.get(), attributes, - false, + bind_generates_resource, + lose_context_when_out_of_memory, limits, NULL)); } diff --git a/content/browser/renderer_host/image_transport_factory_android.cc b/content/browser/renderer_host/image_transport_factory_android.cc index 7080ddc..f622f0a 100644 --- a/content/browser/renderer_host/image_transport_factory_android.cc +++ b/content/browser/renderer_host/image_transport_factory_android.cc @@ -82,12 +82,15 @@ CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() { 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); limits.mapped_memory_reclaim_limit = WebGraphicsContext3DCommandBufferImpl::kNoLimit; + bool bind_generates_resource = false; + bool lose_context_when_out_of_memory = false; context_.reset( new WebGraphicsContext3DCommandBufferImpl(0, // offscreen url, gpu_channel_host.get(), attrs, - false, + bind_generates_resource, + lose_context_when_out_of_memory, limits, NULL)); context_->setContextLostCallback(context_lost_listener_.get()); diff --git a/content/common/gpu/client/context_provider_command_buffer_browsertest.cc b/content/common/gpu/client/context_provider_command_buffer_browsertest.cc index d6378ad..7588571 100644 --- a/content/common/gpu/client/context_provider_command_buffer_browsertest.cc +++ b/content/common/gpu/client/context_provider_command_buffer_browsertest.cc @@ -30,6 +30,7 @@ class ContextProviderCommandBufferBrowserTest : public ContentBrowserTest { } scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3d() { + bool lose_context_when_out_of_memory = false; scoped_refptr<GpuChannelHost> gpu_channel_host( GetFactory()->EstablishGpuChannelSync( CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); @@ -37,6 +38,7 @@ class ContextProviderCommandBufferBrowserTest : public ContentBrowserTest { WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( gpu_channel_host.get(), blink::WebGraphicsContext3D::Attributes(), + lose_context_when_out_of_memory, GURL("chrome://gpu/ContextProviderCommandBufferTest"), WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)); diff --git a/content/common/gpu/client/gl_helper_unittest.cc b/content/common/gpu/client/gl_helper_unittest.cc index 028777b..38b45ce 100644 --- a/content/common/gpu/client/gl_helper_unittest.cc +++ b/content/common/gpu/client/gl_helper_unittest.cc @@ -60,9 +60,10 @@ class GLHelperTest : public testing::Test { protected: virtual void SetUp() { WebGraphicsContext3D::Attributes attributes; + bool lose_context_when_out_of_memory = false; context_ = WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( - attributes); + attributes, lose_context_when_out_of_memory); context_->makeContextCurrent(); context_support_ = context_->GetContextSupport(); helper_.reset( diff --git a/content/common/gpu/client/gpu_in_process_context_tests.cc b/content/common/gpu/client/gpu_in_process_context_tests.cc index 7be7890..8288237 100644 --- a/content/common/gpu/client/gpu_in_process_context_tests.cc +++ b/content/common/gpu/client/gpu_in_process_context_tests.cc @@ -20,8 +20,10 @@ class ContextTestBase : public testing::Test { public: virtual void SetUp() { blink::WebGraphicsContext3D::Attributes attributes; - context_ = WebGraphicsContext3DInProcessCommandBufferImpl:: - CreateOffscreenContext(attributes); + bool lose_context_when_out_of_memory = false; + typedef WebGraphicsContext3DInProcessCommandBufferImpl WGC3DIPCBI; + context_ = WGC3DIPCBI::CreateOffscreenContext( + attributes, lose_context_when_out_of_memory); context_->makeContextCurrent(); context_support_ = context_->GetContextSupport(); } diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index 4b91c42..425990c 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc @@ -230,6 +230,7 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( GpuChannelHost* host, const Attributes& attributes, bool bind_generates_resources, + bool lose_context_when_out_of_memory, const SharedMemoryLimits& limits, WebGraphicsContext3DCommandBufferImpl* share_context) : initialize_failed_(false), @@ -247,6 +248,7 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( initialized_(false), gl_(NULL), bind_generates_resources_(bind_generates_resources), + lose_context_when_out_of_memory_(lose_context_when_out_of_memory), mem_limits_(limits), flush_id_(0) { if (share_context) { @@ -350,6 +352,8 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( attribs.push_back(attributes_.antialias ? 1 : 0); attribs.push_back(FAIL_IF_MAJOR_PERF_CAVEAT); attribs.push_back(attributes_.failIfMajorPerformanceCaveat ? 1 : 0); + attribs.push_back(LOSE_CONTEXT_WHEN_OUT_OF_MEMORY); + attribs.push_back(lose_context_when_out_of_memory_ ? 1 : 0); attribs.push_back(NONE); // Create a proxy to a command buffer in the GPU process. @@ -424,12 +428,13 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) { DCHECK(host_.get()); // Create the object exposing the OpenGL API. - real_gl_.reset(new gpu::gles2::GLES2Implementation( - gles2_helper_.get(), - gles2_share_group, - transfer_buffer_.get(), - bind_generates_resources_, - command_buffer_.get())); + real_gl_.reset( + new gpu::gles2::GLES2Implementation(gles2_helper_.get(), + gles2_share_group, + transfer_buffer_.get(), + bind_generates_resources_, + lose_context_when_out_of_memory_, + command_buffer_.get())); gl_ = real_gl_.get(); if (!real_gl_->Initialize( @@ -1191,6 +1196,7 @@ WebGraphicsContext3DCommandBufferImpl* WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( GpuChannelHost* host, const WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory, const GURL& active_url, const SharedMemoryLimits& limits, WebGraphicsContext3DCommandBufferImpl* share_context) { @@ -1200,13 +1206,16 @@ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( if (share_context && share_context->IsCommandBufferContextLost()) return NULL; - return new WebGraphicsContext3DCommandBufferImpl(0, - active_url, - host, - attributes, - false, - limits, - share_context); + bool bind_generates_resources = false; + return new WebGraphicsContext3DCommandBufferImpl( + 0, + active_url, + host, + attributes, + bind_generates_resources, + lose_context_when_out_of_memory, + limits, + share_context); } DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM, diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h index 2ff411b..dd65b76 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h @@ -124,6 +124,7 @@ class WebGraphicsContext3DCommandBufferImpl GpuChannelHost* host, const Attributes& attributes, bool bind_generates_resources, + bool lose_context_when_out_of_memory, const SharedMemoryLimits& limits, WebGraphicsContext3DCommandBufferImpl* share_context); @@ -149,6 +150,7 @@ class WebGraphicsContext3DCommandBufferImpl CreateOffscreenContext( GpuChannelHost* host, const WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory, const GURL& active_url, const SharedMemoryLimits& limits, WebGraphicsContext3DCommandBufferImpl* share_context); @@ -687,20 +689,21 @@ class WebGraphicsContext3DCommandBufferImpl // gpu/command_buffer/common/gles2_cmd_utils.cc and to // gpu/command_buffer/client/gl_in_process_context.cc enum Attribute { - ALPHA_SIZE = 0x3021, - BLUE_SIZE = 0x3022, - GREEN_SIZE = 0x3023, - RED_SIZE = 0x3024, - DEPTH_SIZE = 0x3025, - STENCIL_SIZE = 0x3026, - SAMPLES = 0x3031, - SAMPLE_BUFFERS = 0x3032, - HEIGHT = 0x3056, - WIDTH = 0x3057, - NONE = 0x3038, // Attrib list = terminator - SHARE_RESOURCES = 0x10000, - BIND_GENERATES_RESOURCES = 0x10001, - FAIL_IF_MAJOR_PERF_CAVEAT = 0x10002 + ALPHA_SIZE = 0x3021, + BLUE_SIZE = 0x3022, + GREEN_SIZE = 0x3023, + RED_SIZE = 0x3024, + DEPTH_SIZE = 0x3025, + STENCIL_SIZE = 0x3026, + SAMPLES = 0x3031, + SAMPLE_BUFFERS = 0x3032, + HEIGHT = 0x3056, + WIDTH = 0x3057, + NONE = 0x3038, // Attrib list = terminator + SHARE_RESOURCES = 0x10000, + BIND_GENERATES_RESOURCES = 0x10001, + FAIL_IF_MAJOR_PERF_CAVEAT = 0x10002, + LOSE_CONTEXT_WHEN_OUT_OF_MEMORY = 0x10003, }; friend class WebGraphicsContext3DErrorMessageCallback; @@ -767,6 +770,7 @@ class WebGraphicsContext3DCommandBufferImpl scoped_ptr<gpu::gles2::GLES2Interface> trace_gl_; Error last_error_; bool bind_generates_resources_; + bool lose_context_when_out_of_memory_; SharedMemoryLimits mem_limits_; uint32_t flush_id_; diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 8ddb89b..3a94dcb 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -984,11 +984,14 @@ RenderThreadImpl::GetGpuFactories() { gpu_channel_host = EstablishGpuChannelSync( CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); } + blink::WebGraphicsContext3D::Attributes attributes; + bool lose_context_when_out_of_memory = false; gpu_va_context_provider_ = ContextProviderCommandBuffer::Create( make_scoped_ptr( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( gpu_channel_host.get(), - blink::WebGraphicsContext3D::Attributes(), + attributes, + lose_context_when_out_of_memory, GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"), WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)), @@ -1010,6 +1013,7 @@ RenderThreadImpl::CreateOffscreenContext3d() { attributes.stencil = false; attributes.antialias = false; attributes.noAutomaticFlushes = true; + bool lose_context_when_out_of_memory = true; scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync( CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); @@ -1017,6 +1021,7 @@ RenderThreadImpl::CreateOffscreenContext3d() { WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( gpu_channel_host.get(), attributes, + lose_context_when_out_of_memory, GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"), WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)); diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 21f19c2..4cdae04 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -919,25 +919,8 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) { scoped_refptr<ContextProviderCommandBuffer> context_provider; if (!use_software) { - // Explicitly disable antialiasing for the compositor. As of the time of - // this writing, the only platform that supported antialiasing for the - // compositor was Mac OS X, because the on-screen OpenGL context creation - // code paths on Windows and Linux didn't yet have multisampling support. - // Mac OS X essentially always behaves as though it's rendering offscreen. - // Multisampling has a heavy cost especially on devices with relatively low - // fill rate like most notebooks, and the Mac implementation would need to - // be optimized to resolve directly into the IOSurface shared between the - // GPU and browser processes. For these reasons and to avoid platform - // disparities we explicitly disable antialiasing. - blink::WebGraphicsContext3D::Attributes attributes; - attributes.antialias = false; - attributes.shareResources = true; - attributes.noAutomaticFlushes = true; - attributes.depth = false; - attributes.stencil = false; context_provider = ContextProviderCommandBuffer::Create( - CreateGraphicsContext3D(attributes), - "RenderCompositor"); + CreateGraphicsContext3D(), "RenderCompositor"); if (!context_provider.get()) { // Cause the compositor to wait and try again. return scoped_ptr<cc::OutputSurface>(); @@ -2842,8 +2825,7 @@ bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const { } scoped_ptr<WebGraphicsContext3DCommandBufferImpl> -RenderWidget::CreateGraphicsContext3D( - const blink::WebGraphicsContext3D::Attributes& attributes) { +RenderWidget::CreateGraphicsContext3D() { if (!webwidget_) return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); if (CommandLine::ForCurrentProcess()->HasSwitch( @@ -2858,6 +2840,24 @@ RenderWidget::CreateGraphicsContext3D( if (!gpu_channel_host) return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + // Explicitly disable antialiasing for the compositor. As of the time of + // this writing, the only platform that supported antialiasing for the + // compositor was Mac OS X, because the on-screen OpenGL context creation + // code paths on Windows and Linux didn't yet have multisampling support. + // Mac OS X essentially always behaves as though it's rendering offscreen. + // Multisampling has a heavy cost especially on devices with relatively low + // fill rate like most notebooks, and the Mac implementation would need to + // be optimized to resolve directly into the IOSurface shared between the + // GPU and browser processes. For these reasons and to avoid platform + // disparities we explicitly disable antialiasing. + blink::WebGraphicsContext3D::Attributes attributes; + attributes.antialias = false; + attributes.shareResources = true; + attributes.noAutomaticFlushes = true; + attributes.depth = false; + attributes.stencil = false; + bool bind_generates_resources = false; + bool lose_context_when_out_of_memory = true; WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; #if defined(OS_ANDROID) // If we raster too fast we become upload bound, and pending @@ -2883,14 +2883,14 @@ RenderWidget::CreateGraphicsContext3D( #endif scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( - new WebGraphicsContext3DCommandBufferImpl( - surface_id(), - GetURLForGraphicsContext3D(), - gpu_channel_host.get(), - attributes, - false /* bind generates resources */, - limits, - NULL)); + new WebGraphicsContext3DCommandBufferImpl(surface_id(), + GetURLForGraphicsContext3D(), + gpu_channel_host.get(), + attributes, + bind_generates_resources, + lose_context_when_out_of_memory, + limits, + NULL)); return context.Pass(); } diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index b43cfe5..25d929f 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h @@ -530,8 +530,7 @@ class CONTENT_EXPORT RenderWidget #endif // Creates a 3D context associated with this view. - scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateGraphicsContext3D( - const blink::WebGraphicsContext3D::Attributes& attributes); + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateGraphicsContext3D(); bool OnSnapshotHelper(const gfx::Rect& src_subrect, SkBitmap* bitmap); diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc index 1a067f6..2bd6fca 100644 --- a/content/renderer/renderer_webkitplatformsupport_impl.cc +++ b/content/renderer/renderer_webkitplatformsupport_impl.cc @@ -1005,10 +1005,11 @@ RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D( limits.command_buffer_size = buffer_size_kb * 1024; } } - + bool lose_context_when_out_of_memory = false; return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( gpu_channel_host.get(), attributes, + lose_context_when_out_of_memory, GURL(attributes.topDocumentURL), limits, static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context)); diff --git a/content/test/test_context_provider_factory.cc b/content/test/test_context_provider_factory.cc index 96ce738e..33ba614 100644 --- a/content/test/test_context_provider_factory.cc +++ b/content/test/test_context_provider_factory.cc @@ -26,7 +26,9 @@ TestContextProviderFactory::~TestContextProviderFactory() {} scoped_refptr<cc::ContextProvider> TestContextProviderFactory:: OffscreenContextProviderForMainThread() { if (!main_thread_.get() || main_thread_->DestroyedOnMainThread()) { - main_thread_ = webkit::gpu::ContextProviderInProcess::CreateOffscreen(); + bool lose_context_when_out_of_memory = false; + main_thread_ = webkit::gpu::ContextProviderInProcess::CreateOffscreen( + lose_context_when_out_of_memory); if (main_thread_.get() && !main_thread_->BindToCurrentThread()) main_thread_ = NULL; } diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc index 1db894f..2b5e559 100644 --- a/gpu/command_buffer/client/gl_in_process_context.cc +++ b/gpu/command_buffer/client/gl_in_process_context.cc @@ -147,6 +147,7 @@ bool GLInProcessContextImpl::Initialize( // Chromium-specific attributes const int32 FAIL_IF_MAJOR_PERF_CAVEAT = 0x10002; + const int32 LOSE_CONTEXT_WHEN_OUT_OF_MEMORY = 0x10003; std::vector<int32> attrib_vector; if (attribs.alpha_size >= 0) { @@ -185,6 +186,10 @@ bool GLInProcessContextImpl::Initialize( attrib_vector.push_back(FAIL_IF_MAJOR_PERF_CAVEAT); attrib_vector.push_back(attribs.fail_if_major_perf_caveat); } + if (attribs.lose_context_when_out_of_memory > 0) { + attrib_vector.push_back(LOSE_CONTEXT_WHEN_OUT_OF_MEMORY); + attrib_vector.push_back(attribs.lose_context_when_out_of_memory); + } attrib_vector.push_back(NONE); base::Closure wrapped_callback = @@ -250,6 +255,7 @@ bool GLInProcessContextImpl::Initialize( share_group, transfer_buffer_.get(), bind_generates_resources, + attribs.lose_context_when_out_of_memory > 0, command_buffer_.get())); if (use_global_share_group) { @@ -302,7 +308,9 @@ GLInProcessContextAttribs::GLInProcessContextAttribs() depth_size(-1), stencil_size(-1), samples(-1), - sample_buffers(-1) {} + sample_buffers(-1), + fail_if_major_perf_caveat(-1), + lose_context_when_out_of_memory(-1) {} // static GLInProcessContext* GLInProcessContext::CreateContext( diff --git a/gpu/command_buffer/client/gl_in_process_context.h b/gpu/command_buffer/client/gl_in_process_context.h index 188ed34..be91cfd 100644 --- a/gpu/command_buffer/client/gl_in_process_context.h +++ b/gpu/command_buffer/client/gl_in_process_context.h @@ -42,6 +42,7 @@ struct GLES2_IMPL_EXPORT GLInProcessContextAttribs { int32 samples; int32 sample_buffers; int32 fail_if_major_perf_caveat; + int32 lose_context_when_out_of_memory; }; class GLES2_IMPL_EXPORT GLInProcessContext { diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index c155af5..194ccfe 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -83,11 +83,12 @@ GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() { } GLES2Implementation::GLES2Implementation( - GLES2CmdHelper* helper, - ShareGroup* share_group, - TransferBufferInterface* transfer_buffer, - bool bind_generates_resource, - GpuControl* gpu_control) + GLES2CmdHelper* helper, + ShareGroup* share_group, + TransferBufferInterface* transfer_buffer, + bool bind_generates_resource, + bool lose_context_when_out_of_memory, + GpuControl* gpu_control) : helper_(helper), transfer_buffer_(transfer_buffer), angle_pack_reverse_row_order_status_(kUnknownExtensionStatus), @@ -113,6 +114,7 @@ GLES2Implementation::GLES2Implementation( async_upload_sync_shm_offset_(0), error_bits_(0), debug_(false), + lose_context_when_out_of_memory_(lose_context_when_out_of_memory), use_count_(0), error_message_callback_(NULL), gpu_control_(gpu_control), @@ -504,6 +506,11 @@ void GLES2Implementation::SetGLError( error_message_callback_->OnErrorMessage(temp.c_str(), 0); } error_bits_ |= GLES2Util::GLErrorToErrorBit(error); + + if (error == GL_OUT_OF_MEMORY && lose_context_when_out_of_memory_) { + helper_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_UNKNOWN_CONTEXT_RESET_ARB); + } } void GLES2Implementation::SetGLErrorInvalidEnum( @@ -891,16 +898,6 @@ void GLES2Implementation::ShallowFinishCHROMIUM() { helper_->CommandBufferHelper::Finish(); } -bool GLES2Implementation::MustBeContextLost() { - bool context_lost = helper_->IsContextLost(); - if (!context_lost) { - WaitForCmd(); - context_lost = helper_->IsContextLost(); - } - CHECK(context_lost); - return context_lost; -} - void GLES2Implementation::FinishHelper() { GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()"); TRACE_EVENT0("gpu", "GLES2::Finish"); @@ -3330,7 +3327,9 @@ void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { if (!query) { query = query_tracker_->CreateQuery(id, target); if (!query) { - MustBeContextLost(); + SetGLError(GL_OUT_OF_MEMORY, + "glBeginQueryEXT", + "transfer buffer allocation failed"); return; } } else if (query->target() != target) { diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index b120a62..c843802 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -180,12 +180,12 @@ class GLES2_IMPL_EXPORT GLES2Implementation // Number of swap buffers allowed before waiting. static const size_t kMaxSwapBuffers = 2; - GLES2Implementation( - GLES2CmdHelper* helper, - ShareGroup* share_group, - TransferBufferInterface* transfer_buffer, - bool bind_generates_resource, - GpuControl* gpu_control); + GLES2Implementation(GLES2CmdHelper* helper, + ShareGroup* share_group, + TransferBufferInterface* transfer_buffer, + bool bind_generates_resource, + bool lose_context_when_out_of_memory, + GpuControl* gpu_control); virtual ~GLES2Implementation(); @@ -592,11 +592,6 @@ class GLES2_IMPL_EXPORT GLES2Implementation void FinishHelper(); - // Asserts that the context is lost. - // NOTE: This is an expensive call and should only be called - // for error checking. - bool MustBeContextLost(); - void RunIfContextNotLost(const base::Closure& callback); void OnSwapBuffersComplete(); @@ -729,6 +724,9 @@ class GLES2_IMPL_EXPORT GLES2Implementation // Whether or not to print debugging info. bool debug_; + // When true, the context is lost when a GL_OUT_OF_MEMORY error occurs. + bool lose_context_when_out_of_memory_; + // Used to check for single threaded access. int use_count_; diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index aa90733..f57d07a 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -6,6 +6,8 @@ #include "gpu/command_buffer/client/gles2_implementation.h" +#include <limits> + #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include "base/compiler_specific.h" @@ -390,7 +392,9 @@ class GLES2ImplementationTest : public testing::Test { public: TestContext() : commands_(NULL), token_(0) {} - void Initialize(ShareGroup* share_group, bool bind_generates_resource) { + void Initialize(ShareGroup* share_group, + bool bind_generates_resource, + bool lose_context_when_out_of_memory) { command_buffer_.reset(new StrictMock<MockClientCommandBuffer>()); ASSERT_TRUE(command_buffer_->Initialize()); @@ -439,12 +443,12 @@ class GLES2ImplementationTest : public testing::Test { .RetiresOnSaturation(); GetNextToken(); // eat the token that starting up will use. - gl_.reset( - new GLES2Implementation(helper_.get(), - share_group, - transfer_buffer_.get(), - bind_generates_resource, - gpu_control_.get())); + gl_.reset(new GLES2Implementation(helper_.get(), + share_group, + transfer_buffer_.get(), + bind_generates_resource, + lose_context_when_out_of_memory, + gpu_control_.get())); ASSERT_TRUE(gl_->Initialize(kTransferBufferSize, kTransferBufferSize, kTransferBufferSize, @@ -514,11 +518,14 @@ class GLES2ImplementationTest : public testing::Test { return gl_->query_tracker_->GetQuery(id); } - void Initialize(bool bind_generates_resource) { + void Initialize(bool bind_generates_resource, + bool lose_context_when_out_of_memory) { share_group_ = new ShareGroup(bind_generates_resource); for (int i = 0; i < kNumTestContexts; i++) - test_contexts_[i].Initialize(share_group_.get(), bind_generates_resource); + test_contexts_[i].Initialize(share_group_.get(), + bind_generates_resource, + lose_context_when_out_of_memory); // Default to test context 0. gpu_control_ = test_contexts_[0].gpu_control_.get(); @@ -585,7 +592,9 @@ class GLES2ImplementationTest : public testing::Test { }; void GLES2ImplementationTest::SetUp() { - Initialize(true); + bool bind_generates_resource = true; + bool lose_context_when_out_of_memory = false; + Initialize(bind_generates_resource, lose_context_when_out_of_memory); } void GLES2ImplementationTest::TearDown() { @@ -593,6 +602,11 @@ void GLES2ImplementationTest::TearDown() { test_contexts_[i].TearDown(); } +class GLES2ImplementationManualInitTest : public GLES2ImplementationTest { + protected: + virtual void SetUp() OVERRIDE {} +}; + class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest { protected: virtual void SetUp() OVERRIDE; @@ -683,7 +697,9 @@ class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest { }; void GLES2ImplementationStrictSharedTest::SetUp() { - Initialize(false); + bool bind_generates_resource = false; + bool lose_context_when_out_of_memory = false; + Initialize(bind_generates_resource, lose_context_when_out_of_memory); } // GCC requires these declarations, but MSVC requires they not be present @@ -3100,6 +3116,42 @@ TEST_F(GLES2ImplementationTest, ProduceTextureCHROMIUM) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) { + bool bind_generates_resource = false; + bool lose_context_when_out_of_memory = true; + Initialize(bind_generates_resource, lose_context_when_out_of_memory); + + struct Cmds { + cmds::LoseContextCHROMIUM cmd; + }; + + GLsizei max = std::numeric_limits<GLsizei>::max(); + EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _)) + .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL))); + gl_->CreateImageCHROMIUM(max, max, 0); + // The context should be lost. + Cmds expected; + expected.cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_UNKNOWN_CONTEXT_RESET_ARB); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationManualInitTest, NoLoseContextOnOOM) { + bool bind_generates_resource = false; + bool lose_context_when_out_of_memory = false; + Initialize(bind_generates_resource, lose_context_when_out_of_memory); + + struct Cmds { + cmds::LoseContextCHROMIUM cmd; + }; + + GLsizei max = std::numeric_limits<GLsizei>::max(); + EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _)) + .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL))); + gl_->CreateImageCHROMIUM(max, max, 0); + // The context should not be lost. + EXPECT_TRUE(NoCommandsWritten()); +} + #include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h" } // namespace gles2 diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index f310d47..97bc081 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -774,23 +774,24 @@ const int32 kBufferDestroyed = 0x3095; // EGL_BUFFER_DESTROYED const int32 kShareResources = 0x10000; const int32 kBindGeneratesResource = 0x10001; const int32 kFailIfMajorPerfCaveat = 0x10002; +const int32 kLoseContextWhenOutOfMemory = 0x10003; } // namespace ContextCreationAttribHelper::ContextCreationAttribHelper() - : alpha_size_(-1), - blue_size_(-1), - green_size_(-1), - red_size_(-1), - depth_size_(-1), - stencil_size_(-1), - samples_(-1), - sample_buffers_(-1), - buffer_preserved_(true), - share_resources_(false), - bind_generates_resource_(true), - fail_if_major_perf_caveat_(false) { -} + : alpha_size_(-1), + blue_size_(-1), + green_size_(-1), + red_size_(-1), + depth_size_(-1), + stencil_size_(-1), + samples_(-1), + sample_buffers_(-1), + buffer_preserved_(true), + share_resources_(false), + bind_generates_resource_(true), + fail_if_major_perf_caveat_(false), + lose_context_when_out_of_memory_(false) {} void ContextCreationAttribHelper::Serialize(std::vector<int32>* attribs) { if (alpha_size_ != -1) { @@ -833,6 +834,8 @@ void ContextCreationAttribHelper::Serialize(std::vector<int32>* attribs) { attribs->push_back(bind_generates_resource_ ? 1 : 0); attribs->push_back(kFailIfMajorPerfCaveat); attribs->push_back(fail_if_major_perf_caveat_ ? 1 : 0); + attribs->push_back(kLoseContextWhenOutOfMemory); + attribs->push_back(lose_context_when_out_of_memory_ ? 1 : 0); attribs->push_back(kNone); } @@ -887,6 +890,9 @@ bool ContextCreationAttribHelper::Parse(const std::vector<int32>& attribs) { case kFailIfMajorPerfCaveat: fail_if_major_perf_caveat_ = value != 0; break; + case kLoseContextWhenOutOfMemory: + lose_context_when_out_of_memory_ = value != 0; + break; case kNone: // Terminate list, even if more attributes. return true; diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h index 59b5d96..0df1f31 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/gpu/command_buffer/common/gles2_cmd_utils.h @@ -199,6 +199,7 @@ class GLES2_UTILS_EXPORT ContextCreationAttribHelper { bool share_resources_; bool bind_generates_resource_; bool fail_if_major_perf_caveat_; + bool lose_context_when_out_of_memory_; }; } // namespace gles2 diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc index f046872..6c929de 100644 --- a/gpu/command_buffer/service/context_state.cc +++ b/gpu/command_buffer/service/context_state.cc @@ -87,12 +87,14 @@ TextureUnit::TextureUnit() TextureUnit::~TextureUnit() { } -ContextState::ContextState(FeatureInfo* feature_info, Logger* logger) +ContextState::ContextState(FeatureInfo* feature_info, + ErrorStateClient* error_state_client, + Logger* logger) : active_texture_unit(0), pack_reverse_row_order(false), fbo_binding_for_scissor_workaround_dirty_(false), feature_info_(feature_info), - error_state_(ErrorState::Create(logger)) { + error_state_(ErrorState::Create(error_state_client, logger)) { Initialize(); } diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h index 2697e15..2c1f0e1 100644 --- a/gpu/command_buffer/service/context_state.h +++ b/gpu/command_buffer/service/context_state.h @@ -22,6 +22,7 @@ namespace gles2 { class Buffer; class ErrorState; +class ErrorStateClient; class FeatureInfo; class Framebuffer; class Program; @@ -93,7 +94,9 @@ struct Vec4 { }; struct GPU_EXPORT ContextState { - ContextState(FeatureInfo* feature_info, Logger* logger); + ContextState(FeatureInfo* feature_info, + ErrorStateClient* error_state_client, + Logger* logger); ~ContextState(); void Initialize(); diff --git a/gpu/command_buffer/service/error_state.cc b/gpu/command_buffer/service/error_state.cc index 3468c7e..ce65aa1 100644 --- a/gpu/command_buffer/service/error_state.cc +++ b/gpu/command_buffer/service/error_state.cc @@ -16,7 +16,7 @@ namespace gles2 { class ErrorStateImpl : public ErrorState { public: - explicit ErrorStateImpl(Logger* logger); + explicit ErrorStateImpl(ErrorStateClient* client, Logger* logger); virtual ~ErrorStateImpl(); virtual uint32 GetGLError() OVERRIDE; @@ -63,6 +63,7 @@ class ErrorStateImpl : public ErrorState { // Current GL error bits. uint32 error_bits_; + ErrorStateClient* client_; Logger* logger_; DISALLOW_COPY_AND_ASSIGN(ErrorStateImpl); @@ -72,13 +73,12 @@ ErrorState::ErrorState() {} ErrorState::~ErrorState() {} -ErrorState* ErrorState::Create(Logger* logger) { - return new ErrorStateImpl(logger); +ErrorState* ErrorState::Create(ErrorStateClient* client, Logger* logger) { + return new ErrorStateImpl(client, logger); } -ErrorStateImpl::ErrorStateImpl(Logger* logger) - : error_bits_(0), - logger_(logger) {} +ErrorStateImpl::ErrorStateImpl(ErrorStateClient* client, Logger* logger) + : error_bits_(0), client_(client), logger_(logger) {} ErrorStateImpl::~ErrorStateImpl() {} @@ -125,6 +125,8 @@ void ErrorStateImpl::SetGLError( function_name + ": " + msg); } error_bits_ |= GLES2Util::GLErrorToErrorBit(error); + if (error == GL_OUT_OF_MEMORY) + client_->OnOutOfMemoryError(); } void ErrorStateImpl::SetGLErrorInvalidEnum( diff --git a/gpu/command_buffer/service/error_state.h b/gpu/command_buffer/service/error_state.h index c4ef691..0e6a4b0 100644 --- a/gpu/command_buffer/service/error_state.h +++ b/gpu/command_buffer/service/error_state.h @@ -55,12 +55,17 @@ class Logger; #define ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state, function_name) \ error_state->ClearRealGLErrors(__FILE__, __LINE__, function_name) +class GPU_EXPORT ErrorStateClient { + public: + // GL_OUT_OF_MEMORY can cause side effects such as losing the context. + virtual void OnOutOfMemoryError() = 0; +}; class GPU_EXPORT ErrorState { public: virtual ~ErrorState(); - static ErrorState* Create(Logger* logger); + static ErrorState* Create(ErrorStateClient* client, Logger* logger); virtual uint32 GetGLError() = 0; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index c3bdae5..c0e0e3d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -566,7 +566,8 @@ void GLES2Decoder::EndDecoding() {} // This class implements GLES2Decoder so we don't have to expose all the GLES2 // cmd stuff to outside this class. class GLES2DecoderImpl : public GLES2Decoder, - public FramebufferManager::TextureDetachObserver { + public FramebufferManager::TextureDetachObserver, + public ErrorStateClient { public: explicit GLES2DecoderImpl(ContextGroup* group); virtual ~GLES2DecoderImpl(); @@ -694,6 +695,9 @@ class GLES2DecoderImpl : public GLES2Decoder, virtual void OnTextureRefDetachedFromFramebuffer( TextureRef* texture) OVERRIDE; + // Overriden from ErrorStateClient. + virtual void OnOutOfMemoryError() OVERRIDE; + // Helpers to facilitate calling into compatible extensions. static void RenderbufferStorageMultisampleHelper( const FeatureInfo* feature_info, @@ -1752,6 +1756,9 @@ class GLES2DecoderImpl : public GLES2Decoder, bool compile_shader_always_succeeds_; + // An optional behaviour to lose the context and group when OOM. + bool lose_context_when_out_of_memory_; + // Log extra info. bool service_logging_; @@ -2217,7 +2224,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) : GLES2Decoder(), group_(group), logger_(&debug_marker_manager_), - state_(group_->feature_info(), &logger_), + state_(group_->feature_info(), this, &logger_), unpack_flip_y_(false), unpack_premultiply_alpha_(false), unpack_unpremultiply_alpha_(false), @@ -2250,6 +2257,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) frag_depth_explicitly_enabled_(false), draw_buffers_explicitly_enabled_(false), compile_shader_always_succeeds_(false), + lose_context_when_out_of_memory_(false), service_logging_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUServiceLoggingGPU)), viewport_max_width_(0), @@ -2323,6 +2331,10 @@ bool GLES2DecoderImpl::Initialize( if (!attrib_parser.Parse(attribs)) return false; + // Save the loseContextWhenOutOfMemory context creation attribute. + lose_context_when_out_of_memory_ = + attrib_parser.lose_context_when_out_of_memory_; + // If the failIfMajorPerformanceCaveat context creation attribute was true // and we are using a software renderer, fail. if (attrib_parser.fail_if_major_perf_caveat_ && @@ -10659,6 +10671,13 @@ void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer( DoDidUseTexImageIfNeeded(texture, texture->target()); } +void GLES2DecoderImpl::OnOutOfMemoryError() { + if (lose_context_when_out_of_memory_) { + group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB); + LoseContext(GL_GUILTY_CONTEXT_RESET_ARB); + } +} + // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file // instead of having to edit some template or the code generator. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 6437648..16783b8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -71,15 +71,14 @@ class GLES2DecoderTestWithExtensionsOnGLES2 GLES2DecoderTestWithExtensionsOnGLES2() {} virtual void SetUp() { - InitDecoder(GetParam(), // extensions - "opengl es 2.0", // gl version - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = GetParam(); + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + InitDecoder(init); } }; @@ -100,16 +99,15 @@ class GLES2DecoderGeometryInstancingTest : public GLES2DecoderWithShaderTest { } virtual void SetUp() { - InitDecoder( - "GL_ANGLE_instanced_arrays", // extensions - "opengl es 2.0", // gl version - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ANGLE_instanced_arrays"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); SetupDefaultProgram(); } }; @@ -125,17 +123,10 @@ class GLES2DecoderRGBBackbufferTest : public GLES2DecoderWithShaderTest { command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::CLEAR_ALPHA_IN_READPIXELS)); - InitDecoderWithCommandLine( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true, // bind generates resource - &command_line); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); SetupDefaultProgram(); } }; @@ -215,6 +206,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OverflowFails) { cmd.Init(GL_TRIANGLES, 0, kLargeCount); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(GetDecoder()->WasContextLost()); } // Tests when the math overflows (0x7FFFFFFF + 1 = 0x8000000 verts) @@ -228,6 +220,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0PosToNegFails) { cmd.Init(GL_TRIANGLES, 0, kLargeCount); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(GetDecoder()->WasContextLost()); } // Tests when the driver returns an error @@ -243,6 +236,37 @@ TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OOMFails) { cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_FALSE(GetDecoder()->WasContextLost()); +} + +// Test that we lose context. +TEST_F(GLES2DecoderManualInitTest, LoseContextWhenOOM) { + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + init.lose_context_when_out_of_memory = true; + InitDecoder(init); + SetupDefaultProgram(); + + const GLsizei kFakeLargeCount = 0x1234; + SetupTexture(); + AddExpectationsForSimulatedAttrib0WithError( + kFakeLargeCount, 0, GL_OUT_OF_MEMORY); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + // Other contexts in the group should be lost also. + EXPECT_CALL(*mock_decoder_, LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); + // This context should be lost. + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); } TEST_F(GLES2DecoderWithShaderTest, DrawArraysBadTextureUsesBlack) { @@ -328,17 +352,14 @@ TEST_F(GLES2DecoderManualInitTest, InitVertexAttributes) { command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::INIT_VERTEX_ATTRIBUTES)); - InitDecoderWithCommandLine( - "", // extensions - "3.0", // gl version - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true, // bind generates resource - &command_line); + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); SetupDefaultProgram(); SetupTexture(); SetupVertexBuffer(); @@ -1928,17 +1949,10 @@ TEST_F(GLES2DecoderManualInitTest, SetTextureFiltersBeforeGenerateMipmap) { command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::SET_TEXTURE_FILTER_BEFORE_GENERATING_MIPMAP)); - InitDecoderWithCommandLine( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true, // bind generates resource - &command_line); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); EXPECT_CALL(*gl_, GenerateMipmapEXT(_)) .Times(0); @@ -2604,16 +2618,13 @@ TEST_F(GLES2DecoderTest, ReadPixelsInvalidArgs) { } TEST_F(GLES2DecoderManualInitTest, ReadPixelsAsyncError) { - InitDecoder( - "GL_ARB_sync", // extensions - "opengl es 3.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_sync"; + init.gl_version = "opengl es 3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); typedef ReadPixels::Result Result; Result* result = GetSharedMemoryAs<Result*>(); @@ -3892,16 +3903,12 @@ TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMaskFBO) { } TEST_F(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { - InitDecoder( - "", // extensions - "3.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3924,16 +3931,11 @@ TEST_F(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { } TEST_F(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { - InitDecoder( - "", // extensions - "3.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3956,16 +3958,12 @@ TEST_F(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { } TEST_F(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -3988,16 +3986,11 @@ TEST_F(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) { } TEST_F(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4020,16 +4013,12 @@ TEST_F(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) { } TEST_F(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - true, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4052,16 +4041,11 @@ TEST_F(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) { } TEST_F(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4084,16 +4068,12 @@ TEST_F(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) { } TEST_F(GLES2DecoderManualInitTest, DepthEnableWithDepth) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); Enable cmd; cmd.Init(GL_DEPTH_TEST); @@ -4147,16 +4127,11 @@ TEST_F(GLES2DecoderManualInitTest, DepthEnableWithDepth) { } TEST_F(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - true, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); Enable cmd; cmd.Init(GL_DEPTH_TEST); @@ -4209,16 +4184,12 @@ TEST_F(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) { } TEST_F(GLES2DecoderManualInitTest, StencilEnableWithStencil) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - true, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); Enable cmd; cmd.Init(GL_STENCIL_TEST); @@ -4271,16 +4242,11 @@ TEST_F(GLES2DecoderManualInitTest, StencilEnableWithStencil) { } TEST_F(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - true, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); Enable cmd; cmd.Init(GL_STENCIL_TEST); @@ -4333,16 +4299,15 @@ TEST_F(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) { } TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - "opengl es 2.0", // gl version - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - true, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4378,16 +4343,14 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) { } TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - "opengl es 2.0", // gl version - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -4423,16 +4386,11 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) { } TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, @@ -4495,16 +4453,11 @@ TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) { } TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferStencil) { - InitDecoder( - "GL_OES_packed_depth_stencil", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_packed_depth_stencil"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, @@ -4899,16 +4852,11 @@ TEST_F(GLES2DecoderTest, RenderbufferStorageBadArgs) { TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUMGLError) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_CALL(*gl_, GetError()) @@ -4927,16 +4875,11 @@ TEST_F(GLES2DecoderManualInitTest, TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUMBadArgs) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_CALL(*gl_, RenderbufferStorageMultisampleEXT(_, _, _, _, _)) @@ -4958,16 +4901,10 @@ TEST_F(GLES2DecoderManualInitTest, } TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUM) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); InSequence sequence; @@ -4995,16 +4932,11 @@ TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUM) { TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleEXTNotSupported) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); InSequence sequence; @@ -5114,16 +5046,11 @@ static bool ValueInArray(GLint value, GLint* array, GLint count) { } TEST_F(GLES2DecoderManualInitTest, GetCompressedTextureFormats) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -5172,16 +5099,10 @@ TEST_F(GLES2DecoderManualInitTest, GetCompressedTextureFormats) { } TEST_F(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -5217,16 +5138,11 @@ TEST_F(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) { } TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DBucketBadBucket) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); const uint32 kBadBucketId = 123; DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -5252,16 +5168,11 @@ struct S3TCTestData { } // anonymous namespace. TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DS3TC) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); const uint32 kBucketId = 123; CommonDecoder::Bucket* bucket = decoder_->CreateBucket(kBucketId); ASSERT_TRUE(bucket != NULL); @@ -5407,16 +5318,11 @@ TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DS3TC) { } TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DETC1) { - InitDecoder( - "GL_OES_compressed_ETC1_RGB8_texture", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_compressed_ETC1_RGB8_texture"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); const uint32 kBucketId = 123; CommonDecoder::Bucket* bucket = decoder_->CreateBucket(kBucketId); ASSERT_TRUE(bucket != NULL); @@ -5480,16 +5386,11 @@ TEST_F(GLES2DecoderManualInitTest, CompressedTexImage2DETC1) { } TEST_F(GLES2DecoderManualInitTest, GetCompressedTextureFormatsETC1) { - InitDecoder( - "GL_OES_compressed_ETC1_RGB8_texture", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_compressed_ETC1_RGB8_texture"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -5556,16 +5457,11 @@ TEST_F(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMInvalidArgs) { } TEST_F(GLES2DecoderManualInitTest, EGLImageExternalBindTexture) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_EXTERNAL_OES, kNewServiceId)); EXPECT_CALL(*gl_, GenTextures(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); @@ -5579,16 +5475,11 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalBindTexture) { } TEST_F(GLES2DecoderManualInitTest, EGLImageExternalGetBinding) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); EXPECT_CALL(*gl_, GetError()) @@ -5613,16 +5504,11 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalGetBinding) { } TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureDefaults) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); TextureRef* texture_ref = GetTexture(client_texture_id_); @@ -5635,17 +5521,11 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureDefaults) { } TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParam) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_EXTERNAL_OES, @@ -5695,17 +5575,11 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParam) { } TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParamInvalid) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_EXTERNAL_OES, client_texture_id_, kServiceTextureId); TexParameteri cmd; @@ -5737,16 +5611,11 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTextureParamInvalid) { } TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTexImage2DError) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); GLenum target = GL_TEXTURE_EXTERNAL_OES; GLint level = 0; @@ -5768,16 +5637,9 @@ TEST_F(GLES2DecoderManualInitTest, EGLImageExternalTexImage2DError) { } TEST_F(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); BindTexture cmd1; cmd1.Init(GL_TEXTURE_2D, kInvalidClientId); @@ -5801,16 +5663,11 @@ TEST_F(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) { } TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_RECTANGLE_ARB, kNewServiceId)); EXPECT_CALL(*gl_, GenTextures(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); @@ -5824,16 +5681,11 @@ TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) { } TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleGetBinding) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture( GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); @@ -5859,16 +5711,11 @@ TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleGetBinding) { } TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureDefaults) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture( GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); @@ -5881,16 +5728,11 @@ TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureDefaults) { } TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParam) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture( GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); @@ -5941,16 +5783,11 @@ TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParam) { } TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParamInvalid) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture( GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); @@ -5983,16 +5820,11 @@ TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParamInvalid) { } TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTexImage2DError) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); GLenum target = GL_TEXTURE_RECTANGLE_ARB; GLint level = 0; @@ -6087,17 +5919,10 @@ TEST_F( command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::TEXSUBIMAGE2D_FASTER_THAN_TEXIMAGE2D)); - InitDecoderWithCommandLine( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true, // bind generates resource - &command_line); + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); @@ -6379,16 +6204,11 @@ TEST_F(GLES2DecoderTest, CopyTexSubImage2DClearsUnclearedTexture) { } TEST_F(GLES2DecoderManualInitTest, CompressedImage2DMarksTextureAsCleared) { - InitDecoder( - "GL_EXT_texture_compression_s3tc", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_texture_compression_s3tc"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); EXPECT_CALL(*gl_, GetError()) @@ -6519,16 +6339,11 @@ TEST_F(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnReadPixels) { TEST_F(GLES2DecoderManualInitTest, UnClearedAttachmentsGetClearedOnReadPixelsAndDrawBufferGetsRestored) { - InitDecoder( - "GL_EXT_framebuffer_multisample", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_framebuffer_multisample"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); const GLuint kFBOClientTextureId = 4100; const GLuint kFBOServiceTextureId = 4101; @@ -6974,16 +6789,13 @@ TEST_F(GLES2DecoderTest, BeginQueryEXTDisabled) { } TEST_F(GLES2DecoderManualInitTest, BeginEndQueryEXT) { - InitDecoder( - "GL_EXT_occlusion_query_boolean", // extensions - "opengl es 2.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_EXT_occlusion_query_boolean"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); // Test end fails if no begin. EndQueryEXT end_cmd; @@ -7066,16 +6878,13 @@ static void CheckBeginEndQueryBadMemoryFails( uint32 shm_offset) { // We need to reset the decoder on each iteration, because we lose the // context every time. - test->InitDecoder( - "GL_EXT_occlusion_query_boolean", // extensions - "opengl es 2.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + GLES2DecoderTestBase::InitState init; + init.extensions = "GL_EXT_occlusion_query_boolean"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + test->InitDecoder(init); ::testing::StrictMock< ::gfx::MockGLInterface>* gl = test->GetGLMock(); BeginQueryEXT begin_cmd; @@ -7341,16 +7150,15 @@ TEST_F(GLES2DecoderTest, IsEnabledReturnsCachedValue) { } TEST_F(GLES2DecoderManualInitTest, DepthTextureBadArgs) { - InitDecoder( - "GL_ANGLE_depth_texture", // extensions - "opengl es 2.0", // gl version - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - true, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ANGLE_depth_texture"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); // Check trying to upload data fails. @@ -7394,16 +7202,15 @@ TEST_F(GLES2DecoderManualInitTest, DepthTextureBadArgs) { } TEST_F(GLES2DecoderManualInitTest, GenerateMipmapDepthTexture) { - InitDecoder( - "GL_ANGLE_depth_texture", // extensions - "opengl es 2.0", // gl version - false, // has alpha - true, // has depth - true, // has stencil - false, // request alpha - true, // request depth - true, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ANGLE_depth_texture"; + init.gl_version = "opengl es 2.0"; + init.has_depth = true; + init.has_stencil = true; + init.request_depth = true; + init.request_stencil = true; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 2, 2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, @@ -7415,16 +7222,15 @@ TEST_F(GLES2DecoderManualInitTest, GenerateMipmapDepthTexture) { } TEST_F(GLES2DecoderManualInitTest, DrawClearsDepthTexture) { - InitDecoder( - "GL_ANGLE_depth_texture", // extensions - "opengl es 2.0", // gl version - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ANGLE_depth_texture"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); SetupDefaultProgram(); SetupAllNeededVertexBuffers(); @@ -7547,16 +7353,11 @@ class GLES2DecoderVertexArraysOESTest : public GLES2DecoderWithShaderTest { bool vertex_array_deleted_manually_; virtual void SetUp() { - InitDecoder( - "GL_OES_vertex_array_object", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_vertex_array_object"; + init.gl_version = "opengl es 2.0"; + init.bind_generates_resource = true; + InitDecoder(init); SetupDefaultProgram(); AddExpectationsForGenVertexArraysOES(); @@ -7698,16 +7499,10 @@ class GLES2DecoderEmulatedVertexArraysOESTest GLES2DecoderEmulatedVertexArraysOESTest() { } virtual void SetUp() { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); SetupDefaultProgram(); AddExpectationsForGenVertexArraysOES(); @@ -8085,16 +7880,15 @@ TEST_F(GLES2DecoderWithShaderTest, UseTexImage) { } TEST_F(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { - InitDecoder( - "GL_OES_EGL_image_external", // extensions - "opengl es 2.0", // gl version - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_EGL_image_external"; + init.gl_version = "opengl es 2.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); TextureRef* texture_ref = GetTexture(client_texture_id_); scoped_refptr<MockGLImage> image(new MockGLImage); @@ -8160,16 +7954,11 @@ TEST_F(GLES2DecoderManualInitTest, DrawWithGLImageExternal) { } TEST_F(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) { - InitDecoder( - "GL_ARB_texture_rectangle", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_rectangle"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); Texture* texture = GetTexture(client_texture_id_)->texture(); EXPECT_TRUE(texture != NULL); @@ -8201,12 +7990,11 @@ TEST_F(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) { } TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) { - InitDecoder( - "GL_CHROMIUM_async_pixel_transfers", // extensions - "3.0", // gl version - false, false, false, // has alpha/depth/stencil - false, false, false, // request alpha/depth/stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_CHROMIUM_async_pixel_transfers"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); // Set up the texture. DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -8439,12 +8227,11 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) { } TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransferManager) { - InitDecoder( - "GL_CHROMIUM_async_pixel_transfers", // extensions - "3.0", // gl version - false, false, false, // has alpha/depth/stencil - false, false, false, // request alpha/depth/stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_CHROMIUM_async_pixel_transfers"; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); // Set up the texture. DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -8544,16 +8331,10 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerInitialSize) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); // Expect that initial size - size is 0. EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kManaged)); @@ -8563,16 +8344,10 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexImage2D) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) .WillOnce(Return(true)).RetiresOnSaturation(); @@ -8600,16 +8375,10 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexStorage2DEXT) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); // Check we get out of memory and no call to glTexStorage2DEXT // if Ensure fails. @@ -8632,16 +8401,12 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerCopyTexImage2D) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - "3.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(128)) .WillOnce(Return(true)).RetiresOnSaturation(); @@ -8670,16 +8435,10 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerRenderbufferStorage) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId); EXPECT_CALL(*gl_, GetError()) @@ -8710,16 +8469,10 @@ TEST_F(GLES2DecoderManualInitTest, MemoryTrackerBufferData) { scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = new SizeOnlyMemoryTracker(); set_memory_tracker(memory_tracker.get()); - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.bind_generates_resource = true; + InitDecoder(init); DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); EXPECT_CALL(*gl_, GetError()) @@ -8801,15 +8554,9 @@ TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateBackbuffer) { } TEST_F(GLES2DecoderManualInitTest, InvalidateFramebufferBinding) { - InitDecoder("", // extensions - "opengl es 3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); // EXPECT_EQ can't be used to compare function pointers EXPECT_TRUE( @@ -8821,15 +8568,10 @@ TEST_F(GLES2DecoderManualInitTest, InvalidateFramebufferBinding) { } TEST_F(GLES2DecoderManualInitTest, DiscardFramebufferEXT) { - InitDecoder("GL_EXT_discard_framebuffer", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_EXT_discard_framebuffer"; + init.gl_version = "opengl es 2.0"; + InitDecoder(init); // EXPECT_EQ can't be used to compare function pointers EXPECT_TRUE( @@ -8883,16 +8625,9 @@ TEST_F(GLES2DecoderTest, DiscardFramebufferEXTUnsupported) { } TEST_F(GLES2DecoderRestoreStateTest, NullPreviousState) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); SetupTexture(); InSequence sequence; @@ -8918,21 +8653,14 @@ TEST_F(GLES2DecoderRestoreStateTest, NullPreviousState) { } TEST_F(GLES2DecoderRestoreStateTest, WithPreviousState) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); SetupTexture(); // Construct a previous ContextState with all texture bindings // set to default textures. - ContextState prev_state(NULL, NULL); + ContextState prev_state(NULL, NULL, NULL); InitializeContextState(&prev_state, std::numeric_limits<uint32>::max(), 0); InSequence sequence; @@ -8949,16 +8677,9 @@ TEST_F(GLES2DecoderRestoreStateTest, WithPreviousState) { } TEST_F(GLES2DecoderRestoreStateTest, ActiveUnit1) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); // Bind a non-default texture to GL_TEXTURE1 unit. EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); @@ -8970,7 +8691,7 @@ TEST_F(GLES2DecoderRestoreStateTest, ActiveUnit1) { // Construct a previous ContextState with all texture bindings // set to default textures. - ContextState prev_state(NULL, NULL); + ContextState prev_state(NULL, NULL, NULL); InitializeContextState(&prev_state, std::numeric_limits<uint32>::max(), 0); InSequence sequence; @@ -8987,16 +8708,9 @@ TEST_F(GLES2DecoderRestoreStateTest, ActiveUnit1) { } TEST_F(GLES2DecoderRestoreStateTest, NonDefaultUnit0) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); // Bind a non-default texture to GL_TEXTURE1 unit. EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE1)); @@ -9010,7 +8724,7 @@ TEST_F(GLES2DecoderRestoreStateTest, NonDefaultUnit0) { // Construct a previous ContextState with GL_TEXTURE_2D target in // GL_TEXTURE0 unit bound to a non-default texture and the rest // set to default textures. - ContextState prev_state(NULL, NULL); + ContextState prev_state(NULL, NULL, NULL); InitializeContextState(&prev_state, 0, kServiceTextureId); InSequence sequence; @@ -9032,16 +8746,9 @@ TEST_F(GLES2DecoderRestoreStateTest, NonDefaultUnit0) { } TEST_F(GLES2DecoderRestoreStateTest, NonDefaultUnit1) { - InitDecoder( - "", // extensions - "3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.gl_version = "3.0"; + InitDecoder(init); // Bind a non-default texture to GL_TEXTURE0 unit. SetupTexture(); @@ -9049,7 +8756,7 @@ TEST_F(GLES2DecoderRestoreStateTest, NonDefaultUnit1) { // Construct a previous ContextState with GL_TEXTURE_2D target in // GL_TEXTURE1 unit bound to a non-default texture and the rest // set to default textures. - ContextState prev_state(NULL, NULL); + ContextState prev_state(NULL, NULL, NULL); InitializeContextState(&prev_state, 1, kServiceTextureId); InSequence sequence; @@ -9075,17 +8782,12 @@ TEST_F(GLES2DecoderManualInitTest, ClearUniformsBeforeFirstProgramUse) { command_line.AppendSwitchASCII( switches::kGpuDriverBugWorkarounds, base::IntToString(gpu::CLEAR_UNIFORMS_BEFORE_FIRST_PROGRAM_USE)); - InitDecoderWithCommandLine( - "", // extensions - "3.0", // gl version - true, // has alpha - false, // has depth - false, // has stencil - true, // request alpha - false, // request depth - false, // request stencil - true, // bind generates resource - &command_line); + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.request_alpha = true; + init.bind_generates_resource = true; + InitDecoderWithCommandLine(init, &command_line); { static AttribInfo attribs[] = { { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, @@ -9122,15 +8824,10 @@ TEST_F(GLES2DecoderManualInitTest, ClearUniformsBeforeFirstProgramUse) { } TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES2) { - InitDecoder("GL_OES_texture_float", // extensions - "opengl es 2.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_OES_texture_float"; + init.gl_version = "opengl es 2.0"; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0); @@ -9143,15 +8840,10 @@ TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES2) { } TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES3) { - InitDecoder("GL_OES_texture_float GL_EXT_color_buffer_float", // extensions - "opengl es 3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_OES_texture_float GL_EXT_color_buffer_float"; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 17, 0, GL_RGB, GL_FLOAT, 0, 0); @@ -9166,15 +8858,10 @@ TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatOnGLES3) { } TEST_F(GLES2DecoderManualInitTest, TexSubImage2DFloatOnGLES3) { - InitDecoder("GL_OES_texture_float GL_EXT_color_buffer_float", // extensions - "opengl es 3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_OES_texture_float GL_EXT_color_buffer_float"; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); const int kWidth = 8; const int kHeight = 4; DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -9194,15 +8881,10 @@ TEST_F(GLES2DecoderManualInitTest, TexSubImage2DFloatOnGLES3) { } TEST_F(GLES2DecoderManualInitTest, TexSubImage2DFloatDoesClearOnGLES3) { - InitDecoder("GL_OES_texture_float GL_EXT_color_buffer_float", // extensions - "opengl es 3.0", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_OES_texture_float GL_EXT_color_buffer_float"; + init.gl_version = "opengl es 3.0"; + InitDecoder(init); const int kWidth = 8; const int kHeight = 4; DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); @@ -9225,15 +8907,10 @@ TEST_F(GLES2DecoderManualInitTest, TexSubImage2DFloatDoesClearOnGLES3) { } TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatConvertsFormatDesktop) { - InitDecoder("GL_ARB_texture_float", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - false); // bind generates resource + InitState init; + init.extensions = "GL_ARB_texture_float"; + init.gl_version = "2.1"; + InitDecoder(init); DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 17, 0, GL_RGBA, GL_FLOAT, 0, 0); @@ -9253,16 +8930,11 @@ TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatConvertsFormatDesktop) { } TEST_F(GLES2DecoderManualInitTest, ReadFormatExtension) { - InitDecoder( - "GL_OES_read_format", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.extensions = "GL_OES_read_format"; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -9320,16 +8992,10 @@ TEST_F(GLES2DecoderManualInitTest, ReadFormatExtension) { } TEST_F(GLES2DecoderManualInitTest, NoReadFormatExtension) { - InitDecoder( - "", // extensions - "2.1", // gl version - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "2.1"; + init.bind_generates_resource = true; + InitDecoder(init); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 1acdf35..c582019 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -14,7 +14,6 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/test_helper.h" @@ -61,16 +60,14 @@ GLES2DecoderTestBase::GLES2DecoderTestBase() GLES2DecoderTestBase::~GLES2DecoderTestBase() {} void GLES2DecoderTestBase::SetUp() { - InitDecoder( - "", // extensions - "3.0", // gl version - true, // has alpha - true, // has depth - false, // has stencil - true, // request alpha - true, // request depth - false, // request stencil - true); // bind generates resource + InitState init; + init.gl_version = "3.0"; + init.has_alpha = true; + init.has_depth = true; + init.request_alpha = true; + init.request_depth = true; + init.bind_generates_resource = true; + InitDecoder(init); } void GLES2DecoderTestBase::AddExpectationsForVertexAttribManager() { @@ -81,38 +78,22 @@ void GLES2DecoderTestBase::AddExpectationsForVertexAttribManager() { } } -void GLES2DecoderTestBase::InitDecoder( - const char* extensions, - const char* gl_version, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource) { - InitDecoderWithCommandLine(extensions, - gl_version, - has_alpha, - has_depth, - has_stencil, - request_alpha, - request_depth, - request_stencil, - bind_generates_resource, - NULL); +GLES2DecoderTestBase::InitState::InitState() + : has_alpha(false), + has_depth(false), + has_stencil(false), + request_alpha(false), + request_depth(false), + request_stencil(false), + bind_generates_resource(false), + lose_context_when_out_of_memory(false) {} + +void GLES2DecoderTestBase::InitDecoder(const InitState& init) { + InitDecoderWithCommandLine(init, NULL); } void GLES2DecoderTestBase::InitDecoderWithCommandLine( - const char* extensions, - const char* gl_version, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource, + const InitState& init, const base::CommandLine* command_line) { Framebuffer::ClearFramebufferCompleteComboMap(); @@ -124,16 +105,16 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( // Only create stream texture manager if extension is requested. std::vector<std::string> list; - base::SplitString(std::string(extensions), ' ', &list); + base::SplitString(init.extensions, ' ', &list); scoped_refptr<FeatureInfo> feature_info; if (command_line) feature_info = new FeatureInfo(*command_line); - group_ = scoped_refptr<ContextGroup>(new ContextGroup( - NULL, - NULL, - memory_tracker_, - feature_info.get(), - bind_generates_resource)); + group_ = scoped_refptr<ContextGroup>( + new ContextGroup(NULL, + NULL, + memory_tracker_, + feature_info.get(), + init.bind_generates_resource)); InSequence sequence; @@ -144,14 +125,16 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( // in turn initialize FeatureInfo, which needs a context to determine // extension support. context_ = new gfx::GLContextStubWithExtensions; - context_->AddExtensionsString(extensions); - context_->SetGLVersionString(gl_version); + context_->AddExtensionsString(init.extensions.c_str()); + context_->SetGLVersionString(init.gl_version.c_str()); context_->MakeCurrent(surface_.get()); gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_); TestHelper::SetupContextGroupInitExpectations(gl_.get(), - DisallowedFeatures(), extensions, gl_version); + DisallowedFeatures(), + init.extensions.c_str(), + init.gl_version.c_str()); // We initialize the ContextGroup with a MockGLES2Decoder so that // we can use the ContextGroup to figure out how the real GLES2Decoder @@ -228,14 +211,14 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_alpha ? 8 : 0)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(init.has_alpha ? 8 : 0)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_depth ? 24 : 0)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(init.has_depth ? 24 : 0)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_stencil ? 8 : 0)) - .RetiresOnSaturation(); + .WillOnce(SetArgumentPointee<1>(init.has_stencil ? 8 : 0)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, Enable(GL_VERTEX_PROGRAM_POINT_SIZE)) .Times(1) @@ -292,11 +275,16 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( shared_memory_id_ = kSharedMemoryId; shared_memory_base_ = buffer->memory(); - int32 attributes[] = { - EGL_ALPHA_SIZE, request_alpha ? 8 : 0, - EGL_DEPTH_SIZE, request_depth ? 24 : 0, - EGL_STENCIL_SIZE, request_stencil ? 8 : 0, - }; + static const int32 kLoseContextWhenOutOfMemory = 0x10003; + + int32 attributes[] = {EGL_ALPHA_SIZE, + init.request_alpha ? 8 : 0, + EGL_DEPTH_SIZE, + init.request_depth ? 24 : 0, + EGL_STENCIL_SIZE, + init.request_stencil ? 8 : 0, + kLoseContextWhenOutOfMemory, + init.lose_context_when_out_of_memory ? 1 : 0, }; std::vector<int32> attribs(attributes, attributes + arraysize(attributes)); decoder_.reset(GLES2Decoder::Create(group_.get())); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 5ceb445..24a960e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -12,6 +12,7 @@ #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/query_manager.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" @@ -150,28 +151,24 @@ class GLES2DecoderTestBase : public testing::Test { memory_tracker_ = memory_tracker; } - void InitDecoder( - const char* extensions, - const char* gl_version, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource); - - void InitDecoderWithCommandLine( - const char* extensions, - const char* gl_version, - bool has_alpha, - bool has_depth, - bool has_stencil, - bool request_alpha, - bool request_depth, - bool request_stencil, - bool bind_generates_resource, - const base::CommandLine* command_line); + struct InitState { + InitState(); + + std::string extensions; + std::string gl_version; + bool has_alpha; + bool has_depth; + bool has_stencil; + bool request_alpha; + bool request_depth; + bool request_stencil; + bool bind_generates_resource; + bool lose_context_when_out_of_memory; + }; + + void InitDecoder(const InitState& init); + void InitDecoderWithCommandLine(const InitState& init, + const base::CommandLine* command_line); void ResetDecoder(); @@ -489,7 +486,7 @@ class GLES2DecoderTestBase : public testing::Test { scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<gfx::GLSurfaceStub> surface_; scoped_refptr<gfx::GLContextStubWithExtensions> context_; - scoped_ptr<GLES2Decoder> mock_decoder_; + scoped_ptr<MockGLES2Decoder> mock_decoder_; scoped_ptr<GLES2Decoder> decoder_; MemoryTracker* memory_tracker_; diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index e8d6452..dc30f45 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -39,9 +39,9 @@ GLManager::Options::Options() share_mailbox_manager(NULL), virtual_manager(NULL), bind_generates_resource(false), + lose_context_when_out_of_memory(false), context_lost_allowed(false), - image_manager(NULL) { -} + image_manager(NULL) {} GLManager::GLManager() : context_lost_allowed_(false) { @@ -189,12 +189,13 @@ void GLManager::Initialize(const GLManager::Options& options) { transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); // Create the object exposing the OpenGL API. - gles2_implementation_.reset(new gles2::GLES2Implementation( - gles2_helper_.get(), - client_share_group, - transfer_buffer_.get(), - options.bind_generates_resource, - gpu_control_.get())); + gles2_implementation_.reset( + new gles2::GLES2Implementation(gles2_helper_.get(), + client_share_group, + transfer_buffer_.get(), + options.bind_generates_resource, + options.lose_context_when_out_of_memory, + gpu_control_.get())); ASSERT_TRUE(gles2_implementation_->Initialize( kStartTransferBufferSize, diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index 8a811fd..6eb5909 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h @@ -53,6 +53,8 @@ class GLManager { GLManager* virtual_manager; // Whether or not glBindXXX generates a resource. bool bind_generates_resource; + // Whether or not the context is auto-lost when GL_OUT_OF_MEMORY occurs. + bool lose_context_when_out_of_memory; // Whether or not it's ok to lose the context. bool context_lost_allowed; // Image manager to be used. diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 9885cd6..8b43dff 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -229,13 +229,15 @@ EGLContext Display::CreateContext(EGLConfig config, DCHECK(transfer_buffer_.get()); bool bind_generates_resources = true; - - context_.reset(new gpu::gles2::GLES2Implementation( - gles2_cmd_helper_.get(), - NULL, - transfer_buffer_.get(), - bind_generates_resources, - gpu_control_.get())); + bool lose_context_when_out_of_memory = false; + + context_.reset( + new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), + NULL, + transfer_buffer_.get(), + bind_generates_resources, + lose_context_when_out_of_memory, + gpu_control_.get())); if (!context_->Initialize( kTransferBufferSize, diff --git a/mojo/examples/aura_demo/demo_context_factory.cc b/mojo/examples/aura_demo/demo_context_factory.cc index e9312ad..4040208 100644 --- a/mojo/examples/aura_demo/demo_context_factory.cc +++ b/mojo/examples/aura_demo/demo_context_factory.cc @@ -56,8 +56,10 @@ DemoContextFactory::OffscreenCompositorContextProvider() { // to leak the context provider when we shutdown to avoid destroying the // contexts on the wrong thread. DCHECK(!ui::Compositor::WasInitializedWithThread()); + bool lose_context_when_out_of_memory = true; offscreen_compositor_contexts_ = - webkit::gpu::ContextProviderInProcess::CreateOffscreen(); + webkit::gpu::ContextProviderInProcess::CreateOffscreen( + lose_context_when_out_of_memory); } return offscreen_compositor_contexts_; } @@ -66,8 +68,10 @@ scoped_refptr<cc::ContextProvider> DemoContextFactory::SharedMainThreadContextProvider() { if (!shared_main_thread_contexts_ || shared_main_thread_contexts_->DestroyedOnMainThread()) { + bool lose_context_when_out_of_memory = false; shared_main_thread_contexts_ = - webkit::gpu::ContextProviderInProcess::CreateOffscreen(); + webkit::gpu::ContextProviderInProcess::CreateOffscreen( + lose_context_when_out_of_memory); if (shared_main_thread_contexts_ && !shared_main_thread_contexts_->BindToCurrentThread()) shared_main_thread_contexts_ = NULL; diff --git a/mojo/gles2/gles2_context.cc b/mojo/gles2/gles2_context.cc index 6d4106d..306ffeb 100644 --- a/mojo/gles2/gles2_context.cc +++ b/mojo/gles2/gles2_context.cc @@ -40,11 +40,16 @@ bool GLES2Context::Initialize() { return false; gles2_helper_->SetAutomaticFlushes(false); transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get())); + bool bind_generates_resource = true; + // TODO(piman): Some contexts (such as compositor) want this to be true, so + // this needs to be a public parameter. + bool lose_context_when_out_of_memory = false; implementation_.reset( new gpu::gles2::GLES2Implementation(gles2_helper_.get(), NULL, transfer_buffer_.get(), - true, + bind_generates_resource, + lose_context_when_out_of_memory, &command_buffer_)); return implementation_->Initialize(kDefaultStartTransferBufferSize, kDefaultMinTransferBufferSize, diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.cc b/ppapi/shared_impl/ppb_graphics_3d_shared.cc index b4e258b..1b3677b1 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.cc +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.cc @@ -118,6 +118,7 @@ bool PPB_Graphics3D_Shared::CreateGLES2Impl( transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get())); const bool bind_creates_resources = true; + const bool lose_context_when_out_of_memory = false; // Create the object exposing the OpenGL API. gles2_impl_.reset(new gpu::gles2::GLES2Implementation( @@ -125,6 +126,7 @@ bool PPB_Graphics3D_Shared::CreateGLES2Impl( share_gles2 ? share_gles2->share_group() : NULL, transfer_buffer_.get(), bind_creates_resources, + lose_context_when_out_of_memory, GetGpuControl())); if (!gles2_impl_->Initialize( diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index ce83286..e49ea51 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc @@ -29,11 +29,12 @@ scoped_ptr<cc::OutputSurface> InProcessContextFactory::CreateOutputSurface( attrs.stencil = false; attrs.antialias = false; attrs.shareResources = true; + bool lose_context_when_out_of_memory = true; using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d( WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( - attrs, compositor->widget())); + attrs, lose_context_when_out_of_memory, compositor->widget())); CHECK(context3d); using webkit::gpu::ContextProviderInProcess; @@ -56,8 +57,10 @@ scoped_refptr<cc::ContextProvider> InProcessContextFactory::OffscreenCompositorContextProvider() { if (!offscreen_compositor_contexts_.get() || !offscreen_compositor_contexts_->DestroyedOnMainThread()) { + bool lose_context_when_out_of_memory = true; offscreen_compositor_contexts_ = - webkit::gpu::ContextProviderInProcess::CreateOffscreen(); + webkit::gpu::ContextProviderInProcess::CreateOffscreen( + lose_context_when_out_of_memory); } return offscreen_compositor_contexts_; } @@ -69,8 +72,10 @@ InProcessContextFactory::SharedMainThreadContextProvider() { return shared_main_thread_contexts_; if (ui::Compositor::WasInitializedWithThread()) { + bool lose_context_when_out_of_memory = false; shared_main_thread_contexts_ = - webkit::gpu::ContextProviderInProcess::CreateOffscreen(); + webkit::gpu::ContextProviderInProcess::CreateOffscreen( + lose_context_when_out_of_memory); } else { shared_main_thread_contexts_ = static_cast<webkit::gpu::ContextProviderInProcess*>( diff --git a/webkit/common/gpu/context_provider_in_process.cc b/webkit/common/gpu/context_provider_in_process.cc index 6f1be9c..e9d2558 100644 --- a/webkit/common/gpu/context_provider_in_process.cc +++ b/webkit/common/gpu/context_provider_in_process.cc @@ -48,7 +48,8 @@ scoped_refptr<ContextProviderInProcess> ContextProviderInProcess::Create( // static scoped_refptr<ContextProviderInProcess> -ContextProviderInProcess::CreateOffscreen() { +ContextProviderInProcess::CreateOffscreen( + bool lose_context_when_out_of_memory) { blink::WebGraphicsContext3D::Attributes attributes; attributes.depth = false; attributes.stencil = true; @@ -58,7 +59,8 @@ ContextProviderInProcess::CreateOffscreen() { return Create( WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( - attributes), "Offscreen"); + attributes, lose_context_when_out_of_memory), + "Offscreen"); } ContextProviderInProcess::ContextProviderInProcess( diff --git a/webkit/common/gpu/context_provider_in_process.h b/webkit/common/gpu/context_provider_in_process.h index fc1d15c..c42585f 100644 --- a/webkit/common/gpu/context_provider_in_process.h +++ b/webkit/common/gpu/context_provider_in_process.h @@ -26,9 +26,9 @@ class WEBKIT_GPU_EXPORT ContextProviderInProcess scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d, const std::string& debug_name); - // Calls Create() with a default factory method for creating an offscreen - // context. - static scoped_refptr<ContextProviderInProcess> CreateOffscreen(); + // Uses default attributes for creating an offscreen context. + static scoped_refptr<ContextProviderInProcess> CreateOffscreen( + bool lose_context_when_out_of_memory); virtual blink::WebGraphicsContext3D* WebContext3D() OVERRIDE; diff --git a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc index 3c6d608..992bcb4 100644 --- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -73,20 +73,29 @@ static base::LazyInstance<GLES2Initializer> g_gles2_initializer = scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( const blink::WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory, gfx::AcceleratedWidget window) { DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone); + bool is_offscreen = false; return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl( - scoped_ptr< ::gpu::GLInProcessContext>(), attributes, false, window)); + scoped_ptr< ::gpu::GLInProcessContext>(), + attributes, + lose_context_when_out_of_memory, + is_offscreen, + window)); } // static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( - const blink::WebGraphicsContext3D::Attributes& attributes) { + const blink::WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory) { + bool is_offscreen = true; return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl( scoped_ptr< ::gpu::GLInProcessContext>(), attributes, - true, + lose_context_when_out_of_memory, + is_offscreen, gfx::kNullAcceleratedWidget)); } @@ -94,10 +103,13 @@ scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( scoped_ptr< ::gpu::GLInProcessContext> context, const blink::WebGraphicsContext3D::Attributes& attributes) { + bool lose_context_when_out_of_memory = false; // Not used. + bool is_offscreen = true; // Not used. return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl( context.Pass(), attributes, - true /* is_offscreen. Not used. */, + lose_context_when_out_of_memory, + is_offscreen, gfx::kNullAcceleratedWidget /* window. Not used. */)); } @@ -105,6 +117,7 @@ WebGraphicsContext3DInProcessCommandBufferImpl:: WebGraphicsContext3DInProcessCommandBufferImpl( scoped_ptr< ::gpu::GLInProcessContext> context, const blink::WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory, bool is_offscreen, gfx::AcceleratedWidget window) : is_offscreen_(is_offscreen), @@ -116,8 +129,8 @@ WebGraphicsContext3DInProcessCommandBufferImpl:: context_lost_callback_(NULL), context_lost_reason_(GL_NO_ERROR), attributes_(attributes), - flush_id_(0) { -} + lose_context_when_out_of_memory_(lose_context_when_out_of_memory), + flush_id_(0) {} WebGraphicsContext3DInProcessCommandBufferImpl:: ~WebGraphicsContext3DInProcessCommandBufferImpl() { @@ -155,7 +168,9 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() { gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; ::gpu::GLInProcessContextAttribs attrib_struct; - ConvertAttributes(attributes_, &attrib_struct), + ConvertAttributes(attributes_, &attrib_struct); + attrib_struct.lose_context_when_out_of_memory = + lose_context_when_out_of_memory_; context_.reset(GLInProcessContext::CreateContext( is_offscreen_, 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 f278bb0..0e4348d 100644 --- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h @@ -52,11 +52,13 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> CreateViewContext( const blink::WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory, gfx::AcceleratedWidget window); static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> CreateOffscreenContext( - const blink::WebGraphicsContext3D::Attributes& attributes); + const blink::WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory); static scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WrapContext( @@ -571,6 +573,7 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl WebGraphicsContext3DInProcessCommandBufferImpl( scoped_ptr< ::gpu::GLInProcessContext> context, const blink::WebGraphicsContext3D::Attributes& attributes, + bool lose_context_when_out_of_memory, bool is_offscreen, gfx::AcceleratedWidget window); @@ -598,6 +601,7 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl WGC3Denum context_lost_reason_; blink::WebGraphicsContext3D::Attributes attributes_; + bool lose_context_when_out_of_memory_; // Errors raised by synthesizeGLError(). std::vector<WGC3Denum> synthetic_errors_; |