summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-14 21:45:58 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-14 21:45:58 +0000
commit2f2d704a4fbee7cf83f30be7f668c7c793a08b54 (patch)
tree5cf551615bde20fe3dd7481a52447b316d5f8b15 /gpu/command_buffer
parent37c841918d0604e5589e2c35eb6a48f5c33feec4 (diff)
downloadchromium_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.cc10
-rw-r--r--gpu/command_buffer/service/gl_context.h15
-rw-r--r--gpu/command_buffer/service/gl_context_linux.cc63
-rw-r--r--gpu/command_buffer/service/gl_context_mac.cc8
-rw-r--r--gpu/command_buffer/service/gl_context_win.cc12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc141
-rw-r--r--gpu/command_buffer/service/gpu_processor_linux.cc10
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;