diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-14 21:45:58 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-14 21:45:58 +0000 |
commit | 2f2d704a4fbee7cf83f30be7f668c7c793a08b54 (patch) | |
tree | 5cf551615bde20fe3dd7481a52447b316d5f8b15 /gpu/command_buffer | |
parent | 37c841918d0604e5589e2c35eb6a48f5c33feec4 (diff) | |
download | chromium_src-2f2d704a4fbee7cf83f30be7f668c7c793a08b54.zip chromium_src-2f2d704a4fbee7cf83f30be7f668c7c793a08b54.tar.gz chromium_src-2f2d704a4fbee7cf83f30be7f668c7c793a08b54.tar.bz2 |
Clear GL contexts and frame buffers after creation and resizing.
Also added a new "default" context so command decoders have a GL context they can rely on the state of.
TEST=trybots, verified that buffers were clear.
BUG=none
Review URL: http://codereview.chromium.org/1593018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44544 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r-- | gpu/command_buffer/service/gl_context.cc | 10 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context.h | 15 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context_linux.cc | 63 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context_mac.cc | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context_win.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 141 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor_linux.cc | 10 |
7 files changed, 171 insertions, 88 deletions
diff --git a/gpu/command_buffer/service/gl_context.cc b/gpu/command_buffer/service/gl_context.cc index 3602a07..e123936 100644 --- a/gpu/command_buffer/service/gl_context.cc +++ b/gpu/command_buffer/service/gl_context.cc @@ -78,4 +78,14 @@ bool InitializeGLEW() { #endif } +bool GLContext::InitializeCommon() { + if (!MakeCurrent()) + return false; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (glGetError() != GL_NO_ERROR) + return false; + + return true; +} } // namespace gpu diff --git a/gpu/command_buffer/service/gl_context.h b/gpu/command_buffer/service/gl_context.h index e4d033e..988b7d6 100644 --- a/gpu/command_buffer/service/gl_context.h +++ b/gpu/command_buffer/service/gl_context.h @@ -62,6 +62,9 @@ class GLContext { // Get the underlying platform specific GL context "handle". virtual GLContextHandle GetHandle() = 0; + protected: + bool InitializeCommon(); + private: DISALLOW_COPY_AND_ASSIGN(GLContext); }; @@ -78,11 +81,9 @@ class ViewGLContext : public GLContext { DCHECK(window); } #elif defined(OS_LINUX) - ViewGLContext(Display* display, gfx::PluginWindowHandle window) - : display_(display), - window_(window), + explicit ViewGLContext(gfx::PluginWindowHandle window) + : window_(window), context_(NULL) { - DCHECK(display); DCHECK(window); } #elif defined(OS_MACOSX) @@ -108,7 +109,6 @@ class ViewGLContext : public GLContext { HDC device_context_; GLContextHandle context_; #elif defined(OS_LINUX) - Display* display_; gfx::PluginWindowHandle window_; GLContextHandle context_; #elif defined(OS_MACOSX) @@ -130,11 +130,9 @@ class PbufferGLContext : public GLContext { pbuffer_(NULL) { } #elif defined(OS_LINUX) - explicit PbufferGLContext(Display* display) + explicit PbufferGLContext() : context_(NULL), - display_(display), pbuffer_(NULL) { - DCHECK(display_); } #elif defined(OS_MACOSX) PbufferGLContext() @@ -161,7 +159,6 @@ class PbufferGLContext : public GLContext { HDC device_context_; PbufferHandle pbuffer_; #elif defined(OS_LINUX) - Display* display_; PbufferHandle pbuffer_; #elif defined(OS_MACOSX) PbufferHandle pbuffer_; diff --git a/gpu/command_buffer/service/gl_context_linux.cc b/gpu/command_buffer/service/gl_context_linux.cc index 9b56bb3..acafd3b2 100644 --- a/gpu/command_buffer/service/gl_context_linux.cc +++ b/gpu/command_buffer/service/gl_context_linux.cc @@ -10,6 +10,7 @@ #include <X11/Xutil.h> #endif +#include "app/x11_util.h" #include "gpu/command_buffer/service/gl_context.h" #include "base/scoped_ptr.h" #include "gpu/command_buffer/service/gl_utils.h" @@ -70,23 +71,24 @@ bool ViewGLContext::Initialize(bool multisampled) { DLOG(WARNING) << "Multisampling not implemented."; } - if (!InitializeGLXEW(display_)) + Display* display = x11_util::GetXDisplay(); + if (!InitializeGLXEW(display)) return false; XWindowAttributes attributes; - XGetWindowAttributes(display_, window_, &attributes); + XGetWindowAttributes(display, window_, &attributes); XVisualInfo visual_info_template; visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); int visual_info_count = 0; scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( - XGetVisualInfo(display_, VisualIDMask, + XGetVisualInfo(display, VisualIDMask, &visual_info_template, &visual_info_count)); DCHECK(visual_info_list.get()); DCHECK_GT(visual_info_count, 0); context_ = NULL; for (int i = 0; i < visual_info_count; ++i) { - context_ = glXCreateContext(display_, visual_info_list.get() + i, 0, True); + context_ = glXCreateContext(display, visual_info_list.get() + i, 0, True); if (context_) break; } @@ -105,20 +107,28 @@ bool ViewGLContext::Initialize(bool multisampled) { Destroy(); return false; } + + if (!InitializeCommon()) { + Destroy(); + return false; + } + #endif // UNIT_TEST return true; } void ViewGLContext::Destroy() { - #if !defined(UNIT_TEST) -Bool result = glXMakeCurrent(display_, 0, 0); +#if !defined(UNIT_TEST) + Display* display = x11_util::GetXDisplay(); + Bool result = glXMakeCurrent(display, 0, 0); + // glXMakeCurrent isn't supposed to fail when unsetting the context, unless // we have pending draws on an invalid window - which shouldn't be the case // here. DCHECK(result); if (context_) { - glXDestroyContext(display_, context_); + glXDestroyContext(display, context_); context_ = NULL; } #endif // UNIT_TEST @@ -129,8 +139,10 @@ bool ViewGLContext::MakeCurrent() { if (IsCurrent()) { return true; } - if (glXMakeCurrent(display_, window_, context_) != True) { - glXDestroyContext(display_, context_); + + Display* display = x11_util::GetXDisplay(); + if (glXMakeCurrent(display, window_, context_) != True) { + glXDestroyContext(display, context_); context_ = 0; DLOG(ERROR) << "Couldn't make context current."; return false; @@ -155,14 +167,16 @@ bool ViewGLContext::IsOffscreen() { void ViewGLContext::SwapBuffers() { #if !defined(UNIT_TEST) - glXSwapBuffers(display_, window_); + Display* display = x11_util::GetXDisplay(); + glXSwapBuffers(display, window_); #endif // UNIT_TEST } gfx::Size ViewGLContext::GetSize() { #if !defined(UNIT_TEST) XWindowAttributes attributes; - XGetWindowAttributes(display_, window_, &attributes); + Display* display = x11_util::GetXDisplay(); + XGetWindowAttributes(display, window_, &attributes); return gfx::Size(attributes.width, attributes.height); #else return gfx::Size(); @@ -183,7 +197,8 @@ bool PbufferGLContext::Initialize(GLContext* shared_context) { bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { #if !defined(UNIT_TEST) - if (!InitializeGLXEW(display_)) + Display* display = x11_util::GetXDisplay(); + if (!InitializeGLXEW(display)) return false; if (!glXChooseFBConfig || @@ -207,7 +222,7 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { int nelements = 0; // TODO(kbr): figure out whether hardcoding screen to 0 is sufficient. scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config( - glXChooseFBConfig(display_, 0, config_attributes, &nelements)); + glXChooseFBConfig(display, 0, config_attributes, &nelements)); if (!config.get()) { DLOG(ERROR) << "glXChooseFBConfig failed."; return false; @@ -216,7 +231,7 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { DLOG(ERROR) << "glXChooseFBConfig returned 0 elements."; return false; } - context_ = glXCreateNewContext(display_, + context_ = glXCreateNewContext(display, config.get()[0], GLX_RGBA_TYPE, shared_handle, @@ -232,7 +247,7 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { 1, 0 }; - pbuffer_ = glXCreatePbuffer(display_, + pbuffer_ = glXCreatePbuffer(display, config.get()[0], pbuffer_attributes); if (!pbuffer_) { Destroy(); @@ -250,6 +265,12 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { Destroy(); return false; } + + if (!InitializeCommon()) { + Destroy(); + return false; + } + #endif // UNIT_TEST return true; @@ -257,18 +278,19 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { void PbufferGLContext::Destroy() { #if !defined(UNIT_TEST) - Bool result = glXMakeCurrent(display_, 0, 0); + Display* display = x11_util::GetXDisplay(); + Bool result = glXMakeCurrent(display, 0, 0); // glXMakeCurrent isn't supposed to fail when unsetting the context, unless // we have pending draws on an invalid window - which shouldn't be the case // here. DCHECK(result); if (context_) { - glXDestroyContext(display_, context_); + glXDestroyContext(display, context_); context_ = NULL; } if (pbuffer_) { - glXDestroyPbuffer(display_, pbuffer_); + glXDestroyPbuffer(display, pbuffer_); pbuffer_ = NULL; } #endif // UNIT_TEST @@ -279,8 +301,9 @@ bool PbufferGLContext::MakeCurrent() { if (IsCurrent()) { return true; } - if (glXMakeCurrent(display_, pbuffer_, context_) != True) { - glXDestroyContext(display_, context_); + Display* display = x11_util::GetXDisplay(); + if (glXMakeCurrent(display, pbuffer_, context_) != True) { + glXDestroyContext(display, context_); context_ = NULL; DLOG(ERROR) << "Couldn't make context current."; return false; diff --git a/gpu/command_buffer/service/gl_context_mac.cc b/gpu/command_buffer/service/gl_context_mac.cc index 6d2f726..3a5a03d 100644 --- a/gpu/command_buffer/service/gl_context_mac.cc +++ b/gpu/command_buffer/service/gl_context_mac.cc @@ -129,6 +129,12 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { Destroy(); return false; } + + if (!InitializeCommon()) { + Destroy(); + return false; + } + #endif // UNIT_TEST return true; @@ -190,4 +196,4 @@ GLContextHandle PbufferGLContext::GetHandle() { #endif // UNIT_TEST } -} // namespace gpu +} // namespace gpu
\ No newline at end of file diff --git a/gpu/command_buffer/service/gl_context_win.cc b/gpu/command_buffer/service/gl_context_win.cc index 6b5896c..0425e17 100644 --- a/gpu/command_buffer/service/gl_context_win.cc +++ b/gpu/command_buffer/service/gl_context_win.cc @@ -206,6 +206,12 @@ bool ViewGLContext::Initialize(bool multisampled) { Destroy(); return false; } + + if (!InitializeCommon()) { + Destroy(); + return false; + } + #endif // UNIT_TEST return true; @@ -325,6 +331,12 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) { return false; } } + + if (!InitializeCommon()) { + Destroy(); + return false; + } + #endif // UNIT_TEST return true; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index ce4f44d..0c25c2f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -167,6 +167,18 @@ class ScopedFrameBufferBinder { DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder); }; +// Temporarily switch to a decoder's default GL context, having known default +// state. +class ScopedDefaultGLContext { + public: + explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder); + ~ScopedDefaultGLContext(); + + private: + GLES2DecoderImpl* decoder_; + DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext); +}; + // Encapsulates an OpenGL texture. class Texture { public: @@ -374,6 +386,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, friend class ScopedTexture2DBinder; friend class ScopedFrameBufferBinder; friend class ScopedRenderBufferBinder; + friend class ScopedDefaultGLContext; friend class RenderBuffer; friend class FrameBuffer; @@ -809,9 +822,16 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, #undef GLES2_CMD_OP - // The GL context this decoder renders to. + // The GL context this decoder renders to on behalf of the client. GLContext* context_; + // A GLContext that is kept in its default state. It is used to perform + // operations that should not be dependent on client set GLContext state, like + // clearing a render buffer when it is created. + // TODO(apatrick): Decoders in the same ContextGroup could potentially share + // the same default GL context. + scoped_ptr<PbufferGLContext> default_context_; + // A parent decoder can access this decoders saved offscreen frame buffer. // The parent pointer is reset if the parent is destroyed. base::WeakPtr<GLES2DecoderImpl> parent_; @@ -877,11 +897,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // The copy that is saved when SwapBuffers is called. scoped_ptr<Texture> offscreen_saved_color_texture_; - // A frame buffer used for rendering to render textures and render buffers - // without concern about any state the client might have changed on the frame - // buffers it has access to. - scoped_ptr<FrameBuffer> temporary_frame_buffer_; - scoped_ptr<Callback0::Type> swap_buffers_callback_; DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); @@ -956,6 +971,15 @@ ScopedFrameBufferBinder::~ScopedFrameBufferBinder() { } } +ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder) + : decoder_(decoder) { + decoder_->default_context_->MakeCurrent(); +} + +ScopedDefaultGLContext::~ScopedDefaultGLContext() { + decoder_->context_->MakeCurrent(); +} + Texture::Texture(GLES2DecoderImpl* decoder) : decoder_(decoder), id_(0) { @@ -1147,6 +1171,14 @@ bool GLES2DecoderImpl::Initialize(GLContext* context, DCHECK(!context_); context_ = context; + // Create a GL context that is kept in a default state and shares a namespace + // with the main GL context. + default_context_.reset(new PbufferGLContext); + if (!default_context_->Initialize(context_)) { + Destroy(); + return false; + } + // Keep only a weak pointer to the parent so we don't unmap its client // frame buffer after it has been destroyed. if (parent) @@ -1211,12 +1243,6 @@ bool GLES2DecoderImpl::Initialize(GLContext* context, offscreen_saved_color_texture_.reset(new Texture(this)); offscreen_saved_color_texture_->Create(); - // Create the temporary frame buffer, used to operate on render textures - // without concern for state the client might have changed on the frame - // buffers it has access to, like the clear color and the color mask. - temporary_frame_buffer_.reset(new FrameBuffer(this)); - temporary_frame_buffer_->Create(); - // Map the ID of the saved offscreen texture into the parent so that // it can reference it. if (parent_) { @@ -1466,6 +1492,35 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { if (offscreen_target_color_texture_->size() == pending_offscreen_size_) return true; + if (parent_) { + // Create the saved offscreen color texture (only accessible to parent). + offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_); + + // Attach the saved offscreen color texture to a frame buffer so we can + // clear it with glClear. + offscreen_target_frame_buffer_->AttachRenderTexture( + offscreen_saved_color_texture_.get()); + if (offscreen_target_frame_buffer_->CheckStatus() != + GL_FRAMEBUFFER_COMPLETE) { + return false; + } + +#if !defined(UNIT_TEST) + // Clear the saved offscreen color texture. Use default GL context + // to ensure clear is not affected by client set state. + { + ScopedDefaultGLContext scoped_context(this); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, + offscreen_target_frame_buffer_->id()); + glClear(GL_COLOR_BUFFER_BIT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + if (glGetError() != GL_NO_ERROR) + return false; + } +#endif + } + // Reallocate the offscreen target buffers. if (!offscreen_target_color_texture_->AllocateStorage( pending_offscreen_size_)) { @@ -1477,28 +1532,7 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { return false; } - // Attach the offscreen target buffers to the temporary frame buffer - // so they can be cleared using that frame buffer's clear parameters (all - // zero, no color mask, etc). - temporary_frame_buffer_->AttachRenderTexture( - offscreen_target_color_texture_.get()); - temporary_frame_buffer_->AttachDepthStencilRenderBuffer( - offscreen_target_depth_stencil_render_buffer_.get()); - if (temporary_frame_buffer_->CheckStatus() != - GL_FRAMEBUFFER_COMPLETE) { - return false; - } - - // Clear the offscreen target buffers to all zero (using the saved frame - // buffer they are temporarily attached to). - temporary_frame_buffer_->Clear( - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - // Detach the offscreen target buffer. - temporary_frame_buffer_->AttachRenderTexture(NULL); - temporary_frame_buffer_->AttachDepthStencilRenderBuffer(NULL); - - // Attach the offscreen target buffers to the proper frame buffer. + // Attach the offscreen target buffers to the target frame buffer. offscreen_target_frame_buffer_->AttachRenderTexture( offscreen_target_color_texture_.get()); offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer( @@ -1508,21 +1542,28 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { return false; } - // Update the info about the offscreen saved color texture in the parent. - // The reference to the parent is a weak pointer and will become null if the - // parent is later destroyed. +#if !defined(UNIT_TEST) + // Clear offscreen frame buffer to its initial state. Use default GL context + // to ensure clear is not affected by client set state. + { + ScopedDefaultGLContext scoped_context(this); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, + offscreen_target_frame_buffer_->id()); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + if (glGetError() != GL_NO_ERROR) + return false; + } +#endif + if (parent_) { // Create the saved offscreen color texture (only accessible to parent). offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_); - // Clear the offscreen saved color texture by copying the cleared target - // frame buffer into it. - { - ScopedFrameBufferBinder binder(this, - offscreen_target_frame_buffer_->id()); - offscreen_saved_color_texture_->Copy(pending_offscreen_size_); - } - + // Update the info about the offscreen saved color texture in the parent. + // The reference to the parent is a weak pointer and will become null if the + // parent is later destroyed. GLuint service_id = offscreen_saved_color_texture_->id(); TextureManager::TextureInfo* info = @@ -1579,15 +1620,15 @@ void GLES2DecoderImpl::Destroy() { offscreen_target_depth_stencil_render_buffer_.reset(); } - if (temporary_frame_buffer_.get()) { - temporary_frame_buffer_->Destroy(); - temporary_frame_buffer_.reset(); - } - if (offscreen_saved_color_texture_.get()) { offscreen_saved_color_texture_->Destroy(); offscreen_saved_color_texture_.reset(); } + + if (default_context_.get()) { + default_context_->Destroy(); + default_context_.reset(); + } } void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { diff --git a/gpu/command_buffer/service/gpu_processor_linux.cc b/gpu/command_buffer/service/gpu_processor_linux.cc index 4217b72..aae4d7b 100644 --- a/gpu/command_buffer/service/gpu_processor_linux.cc +++ b/gpu/command_buffer/service/gpu_processor_linux.cc @@ -2,12 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if !defined(UNIT_TEST) -#include <gdk/gdkx.h> -#else -#define GDK_DISPLAY() NULL -#endif - #include "gpu/command_buffer/service/gl_context.h" #include "gpu/command_buffer/service/gpu_processor.h" @@ -36,7 +30,7 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window, // Create either a view or pbuffer based GLContext. if (window) { - scoped_ptr<ViewGLContext> context(new ViewGLContext(GDK_DISPLAY(), window)); + scoped_ptr<ViewGLContext> context(new ViewGLContext(window)); // TODO(apatrick): support multisampling. if (!context->Initialize(false)) { Destroy(); @@ -44,7 +38,7 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window, } context_.reset(context.release()); } else { - scoped_ptr<PbufferGLContext> context(new PbufferGLContext(GDK_DISPLAY())); + scoped_ptr<PbufferGLContext> context(new PbufferGLContext()); if (!context->Initialize(parent_context)) { Destroy(); return false; |