summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/surface/accelerated_surface_mac.cc116
-rw-r--r--app/surface/accelerated_surface_mac.h52
-rw-r--r--gpu/command_buffer/service/gl_context.h15
-rw-r--r--gpu/command_buffer/service/gl_context_linux.cc33
-rw-r--r--gpu/command_buffer/service/gl_context_mac.cc70
-rw-r--r--gpu/command_buffer/service/gl_context_win.cc32
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc8
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc7
-rw-r--r--gpu/command_buffer/service/gpu_processor.h8
-rw-r--r--gpu/command_buffer/service/gpu_processor_linux.cc10
-rw-r--r--gpu/command_buffer/service/gpu_processor_mac.cc61
-rw-r--r--gpu/command_buffer/service/gpu_processor_win.cc11
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm2
-rw-r--r--webkit/tools/test_shell/mac/accelerated_surface_stub.cc50
-rw-r--r--webkit/tools/test_shell/test_shell.gypi1
15 files changed, 296 insertions, 180 deletions
diff --git a/app/surface/accelerated_surface_mac.cc b/app/surface/accelerated_surface_mac.cc
index f348cd8..a8f5a0e 100644
--- a/app/surface/accelerated_surface_mac.cc
+++ b/app/surface/accelerated_surface_mac.cc
@@ -11,14 +11,20 @@
AcceleratedSurface::AcceleratedSurface()
: gl_context_(NULL),
pbuffer_(NULL),
+ allocate_fbo_(false),
texture_(0),
fbo_(0),
- depth_stencil_renderbuffer_(0),
- bound_fbo_(0),
- bound_renderbuffer_(0) {
+ depth_stencil_renderbuffer_(0) {
}
-bool AcceleratedSurface::Initialize() {
+bool AcceleratedSurface::Initialize(CGLContextObj share_context,
+ bool allocate_fbo) {
+ allocate_fbo_ = allocate_fbo;
+
+ // TODO(kbr): we should reuse the code for PbufferGLContext here instead
+ // of duplicating it. However, in order to do so, we need to move the
+ // GLContext classes out of gpu/ and into gfx/.
+
// Create a 1x1 pbuffer and associated context to bootstrap things
static const CGLPixelFormatAttribute attribs[] = {
(CGLPixelFormatAttribute) kCGLPFAPBuffer,
@@ -36,7 +42,7 @@ bool AcceleratedSurface::Initialize() {
return false;
}
CGLContextObj context;
- CGLError res = CGLCreateContext(pixel_format, 0, &context);
+ CGLError res = CGLCreateContext(pixel_format, share_context, &context);
CGLDestroyPixelFormat(pixel_format);
if (res != kCGLNoError) {
DLOG(ERROR) << "Error creating context.";
@@ -65,6 +71,11 @@ bool AcceleratedSurface::Initialize() {
}
void AcceleratedSurface::Destroy() {
+ // The FBO and texture objects will be destroyed when the OpenGL context,
+ // and any other contexts sharing resources with it, is. We don't want to
+ // make the context current one last time here just in order to delete
+ // these objects.
+
// Release the old TransportDIB in the browser.
if (dib_free_callback_.get() && transport_dib_.get()) {
dib_free_callback_->Run(transport_dib_->id());
@@ -79,25 +90,39 @@ void AcceleratedSurface::Destroy() {
// Call after making changes to the surface which require a visual update.
// Makes the rendering show up in other processes.
void AcceleratedSurface::SwapBuffers() {
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- }
if (io_surface_.get() != NULL) {
- // Bind and unbind the framebuffer to make changes to the
- // IOSurface show up in the other process.
- glFlush();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ if (allocate_fbo_) {
+ // Bind and unbind the framebuffer to make changes to the
+ // IOSurface show up in the other process.
+ glFlush();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ } else {
+ // Copy the current framebuffer's contents into our "live" texture.
+ // Note that the current GL context might not be ours at this point!
+ // This is deliberate, so that surrounding code using GL can produce
+ // rendering results consumed by the AcceleratedSurface.
+ // Need to save and restore OpenGL state around this call.
+ GLint current_texture = 0;
+ GLenum target_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+ glGetIntegerv(target_binding, &current_texture);
+ glBindTexture(target, texture_);
+ glCopyTexSubImage2D(target, 0,
+ 0, 0,
+ 0, 0,
+ surface_size_.width(), surface_size_.height());
+ glBindTexture(target, current_texture);
+ }
} else if (transport_dib_.get() != NULL) {
- // Pre-Mac OS X 10.6, fetch the rendered image from the FBO and copy it
- // into the TransportDIB.
+ // Pre-Mac OS X 10.6, fetch the rendered image from the current frame
+ // buffer and copy it into the TransportDIB.
// TODO(dspringer): There are a couple of options that can speed this up.
// First is to use async reads into a PBO, second is to use SPI that
// allows many tasks to access the same CGSSurface.
void* pixel_memory = transport_dib_->memory();
if (pixel_memory) {
// Note that glReadPixels does an implicit glFlush().
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(0,
0,
surface_size_.width(),
@@ -107,9 +132,6 @@ void AcceleratedSurface::SwapBuffers() {
pixel_memory);
}
}
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
- }
}
static void AddBooleanValue(CFMutableDictionaryRef dictionary,
@@ -137,7 +159,6 @@ void AcceleratedSurface::AllocateRenderBuffers(GLenum target,
// Generate and bind the framebuffer object.
glGenFramebuffersEXT(1, &fbo_);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- bound_fbo_ = fbo_;
// Generate (but don't bind) the depth buffer -- we don't need
// this bound in order to do offscreen rendering.
glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_);
@@ -151,16 +172,14 @@ void AcceleratedSurface::AllocateRenderBuffers(GLenum target,
size.height());
// Unbind the renderbuffers.
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, bound_renderbuffer_);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// Make sure that subsequent set-up code affects the render texture.
glBindTexture(target, texture_);
}
bool AcceleratedSurface::SetupFrameBufferObject(GLenum target) {
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- }
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
GLenum fbo_status;
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
@@ -183,9 +202,6 @@ bool AcceleratedSurface::SetupFrameBufferObject(GLenum target) {
depth_stencil_renderbuffer_);
fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
}
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
- }
return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT;
}
@@ -225,7 +241,15 @@ uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) {
// GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
// Mac OS X and is required for IOSurface interoperability.
GLenum target = GL_TEXTURE_RECTANGLE_ARB;
- AllocateRenderBuffers(target, size);
+ if (allocate_fbo_) {
+ AllocateRenderBuffers(target, size);
+ } else if (!texture_) {
+ // Generate the texture object.
+ glGenTextures(1, &texture_);
+ glBindTexture(target, texture_);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ }
// Allocate a new IOSurface, which is the GPU resource that can be
// shared across processes.
@@ -258,8 +282,10 @@ uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) {
GL_UNSIGNED_INT_8_8_8_8_REV,
io_surface_.get(),
plane);
- // Set up the frame buffer object.
- SetupFrameBufferObject(target);
+ if (allocate_fbo_) {
+ // Set up the frame buffer object.
+ SetupFrameBufferObject(target);
+ }
surface_size_ = size;
// Now send back an identifier for the IOSurface. We originally
@@ -305,20 +331,22 @@ TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize(
return TransportDIB::DefaultHandleValue();
}
- // Set up the render buffers and reserve enough space on the card for the
- // framebuffer texture.
- GLenum target = GL_TEXTURE_RECTANGLE_ARB;
- AllocateRenderBuffers(target, size);
- glTexImage2D(target,
- 0, // mipmap level 0
- GL_RGBA8, // internal pixel format
- size.width(),
- size.height(),
- 0, // 0 border
- GL_BGRA, // Used for consistency
- GL_UNSIGNED_INT_8_8_8_8_REV,
- NULL); // No data, just reserve room on the card.
- SetupFrameBufferObject(target);
+ if (allocate_fbo_) {
+ // Set up the render buffers and reserve enough space on the card for the
+ // framebuffer texture.
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+ AllocateRenderBuffers(target, size);
+ glTexImage2D(target,
+ 0, // mipmap level 0
+ GL_RGBA8, // internal pixel format
+ size.width(),
+ size.height(),
+ 0, // 0 border
+ GL_BGRA, // Used for consistency
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ NULL); // No data, just reserve room on the card.
+ SetupFrameBufferObject(target);
+ }
return transport_dib_->handle();
}
diff --git a/app/surface/accelerated_surface_mac.h b/app/surface/accelerated_surface_mac.h
index 3808dcd..336d0bf 100644
--- a/app/surface/accelerated_surface_mac.h
+++ b/app/surface/accelerated_surface_mac.h
@@ -29,8 +29,17 @@ class AcceleratedSurface {
AcceleratedSurface();
virtual ~AcceleratedSurface() { }
- // Set up internal buffers. Returns false upon failure.
- bool Initialize();
+ // Set up internal buffers. |share_context|, if non-NULL, is a context
+ // with which the internally created OpenGL context shares textures and
+ // other resources. |allocate_fbo| indicates whether or not this surface
+ // should allocate an offscreen frame buffer object (FBO) internally. If
+ // not, then the user is expected to allocate one. NOTE that allocating
+ // an FBO internally does NOT work properly with client code which uses
+ // OpenGL (i.e., via GLES2 command buffers), because the GLES2
+ // implementation does not know to bind the accelerated surface's
+ // internal FBO when the default FBO is bound. Returns false upon
+ // failure.
+ bool Initialize(CGLContextObj share_context, bool allocate_fbo);
// Tear down. Must be called before destructor to prevent leaks.
void Destroy();
@@ -50,7 +59,25 @@ class AcceleratedSurface {
void Clear(const gfx::Rect& rect);
// Call after making changes to the surface which require a visual update.
// Makes the rendering show up in other processes.
+ //
+ // If this AcceleratedSurface is configured with its own FBO, then
+ // this call causes the color buffer to be transmitted. Otherwise,
+ // it causes the frame buffer of the current GL context to be copied
+ // either into an internal texture via glCopyTexSubImage2D or into a
+ // TransportDIB via glReadPixels.
+ //
+ // The size of the rectangle copied is the size last specified via
+ // SetSurfaceSize. If another GL context than the one this
+ // AcceleratedSurface contains is responsible for the production of
+ // the pixels, then when this entry point is called, the color
+ // buffer must be in a state where a glCopyTexSubImage2D or
+ // glReadPixels is legal. (For example, if using multisampled FBOs,
+ // the FBO must have been resolved into a non-multisampled color
+ // texture.) Additionally, in this situation, the contexts must
+ // share server-side GL objects, so that this AcceleratedSurface's
+ // texture is a legal name in the namespace of the current context.
void SwapBuffers();
+
CGLContextObj context() { return gl_context_; }
// These methods are only used when there is a transport DIB.
@@ -81,6 +108,11 @@ class AcceleratedSurface {
// object is valid.
bool SetupFrameBufferObject(GLenum target);
+ // The OpenGL context, and pbuffer drawable, used to transfer data
+ // to the shared region (IOSurface or TransportDIB). Strictly
+ // speaking, we do not need to allocate a GL context all of the
+ // time. We only need one if (a) we are using the IOSurface code
+ // path, or (b) if we are allocating an FBO internally.
CGLContextObj gl_context_;
CGLPBufferObj pbuffer_;
// Either |io_surface_| or |transport_dib_| is a valid pointer, but not both.
@@ -95,15 +127,19 @@ class AcceleratedSurface {
// make this work (or even compile).
scoped_ptr<TransportDIB> transport_dib_;
gfx::Size surface_size_;
+ // TODO(kbr): the FBO management should not be in this class at all.
+ // However, if it is factored out, care needs to be taken to not
+ // introduce another copy of the color data on the GPU; the direct
+ // binding of the internal texture to the IOSurface saves a copy.
+ bool allocate_fbo_;
+ // If the IOSurface code path is being used, then this texture
+ // object is always allocated. Otherwise, it is only allocated if
+ // the user requests an FBO be allocated.
GLuint texture_;
+ // The FBO and renderbuffer are only allocated if allocate_fbo_ is
+ // true.
GLuint fbo_;
GLuint depth_stencil_renderbuffer_;
- // For tracking whether the default framebuffer / renderbuffer or
- // ones created by the end user are currently bound
- // TODO(kbr): Need to property hook up and track the OpenGL state and hook
- // up the notion of the currently bound FBO.
- GLuint bound_fbo_;
- GLuint bound_renderbuffer_;
// Allocate a TransportDIB in the renderer.
scoped_ptr<Callback2<size_t, TransportDIB::Handle*>::Type>
dib_alloc_callback_;
diff --git a/gpu/command_buffer/service/gl_context.h b/gpu/command_buffer/service/gl_context.h
index 832624db9..e4d033e 100644
--- a/gpu/command_buffer/service/gl_context.h
+++ b/gpu/command_buffer/service/gl_context.h
@@ -8,13 +8,12 @@
#include <build/build_config.h>
#include "base/basictypes.h"
+#include "base/logging.h"
#include "gfx/native_widget_types.h"
#include "gfx/size.h"
#include "gpu/command_buffer/common/logging.h"
#include "gpu/command_buffer/service/gl_utils.h"
-class AcceleratedSurface;
-
namespace gpu {
#if defined(UNIT_TEST)
@@ -47,6 +46,9 @@ class GLContext {
// Makes the GL context current on the current thread.
virtual bool MakeCurrent() = 0;
+ // Returns true if this context is current.
+ virtual bool IsCurrent() = 0;
+
// Returns true if this context is offscreen.
virtual bool IsOffscreen() = 0;
@@ -84,8 +86,8 @@ class ViewGLContext : public GLContext {
DCHECK(window);
}
#elif defined(OS_MACOSX)
- explicit ViewGLContext(AcceleratedSurface* surface) : surface_(surface) {
- DCHECK(surface);
+ ViewGLContext() {
+ NOTIMPLEMENTED() << "ViewGLContext not supported on Mac platform.";
}
#endif
@@ -94,6 +96,7 @@ class ViewGLContext : public GLContext {
virtual void Destroy();
virtual bool MakeCurrent();
+ virtual bool IsCurrent();
virtual bool IsOffscreen();
virtual void SwapBuffers();
virtual gfx::Size GetSize();
@@ -109,7 +112,7 @@ class ViewGLContext : public GLContext {
gfx::PluginWindowHandle window_;
GLContextHandle context_;
#elif defined(OS_MACOSX)
- AcceleratedSurface* surface_;
+ // This context isn't implemented on Mac OS X.
#endif
DISALLOW_COPY_AND_ASSIGN(ViewGLContext);
@@ -142,9 +145,11 @@ class PbufferGLContext : public GLContext {
// Initializes the GL context.
bool Initialize(GLContext* shared_context);
+ bool Initialize(GLContextHandle shared_handle);
virtual void Destroy();
virtual bool MakeCurrent();
+ virtual bool IsCurrent();
virtual bool IsOffscreen();
virtual void SwapBuffers();
virtual gfx::Size GetSize();
diff --git a/gpu/command_buffer/service/gl_context_linux.cc b/gpu/command_buffer/service/gl_context_linux.cc
index 0acbb02..9b56bb3 100644
--- a/gpu/command_buffer/service/gl_context_linux.cc
+++ b/gpu/command_buffer/service/gl_context_linux.cc
@@ -126,8 +126,7 @@ Bool result = glXMakeCurrent(display_, 0, 0);
bool ViewGLContext::MakeCurrent() {
#if !defined(UNIT_TEST)
- if (glXGetCurrentDrawable() == window_ &&
- glXGetCurrentContext() == context_) {
+ if (IsCurrent()) {
return true;
}
if (glXMakeCurrent(display_, window_, context_) != True) {
@@ -141,6 +140,15 @@ bool ViewGLContext::MakeCurrent() {
return true;
}
+bool ViewGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ return glXGetCurrentDrawable() == window_ &&
+ glXGetCurrentContext() == context_;
+#else
+ return true;
+#endif
+}
+
bool ViewGLContext::IsOffscreen() {
return false;
}
@@ -170,6 +178,10 @@ GLContextHandle ViewGLContext::GetHandle() {
}
bool PbufferGLContext::Initialize(GLContext* shared_context) {
+ return Initialize(shared_context ? shared_context->GetHandle() : NULL);
+}
+
+bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
#if !defined(UNIT_TEST)
if (!InitializeGLXEW(display_))
return false;
@@ -182,11 +194,6 @@ bool PbufferGLContext::Initialize(GLContext* shared_context) {
return false;
}
- // Get the shared context handle.
- GLContextHandle shared_handle = NULL;
- if (shared_context)
- shared_handle = shared_context->GetHandle();
-
static const int config_attributes[] = {
GLX_DRAWABLE_TYPE,
GLX_PBUFFER_BIT,
@@ -269,8 +276,7 @@ void PbufferGLContext::Destroy() {
bool PbufferGLContext::MakeCurrent() {
#if !defined(UNIT_TEST)
- if (glXGetCurrentDrawable() == pbuffer_ &&
- glXGetCurrentContext() == context_) {
+ if (IsCurrent()) {
return true;
}
if (glXMakeCurrent(display_, pbuffer_, context_) != True) {
@@ -284,6 +290,15 @@ bool PbufferGLContext::MakeCurrent() {
return true;
}
+bool PbufferGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ return glXGetCurrentDrawable() == pbuffer_ &&
+ glXGetCurrentContext() == context_;
+#else
+ return true;
+#endif
+}
+
bool PbufferGLContext::IsOffscreen() {
return true;
}
diff --git a/gpu/command_buffer/service/gl_context_mac.cc b/gpu/command_buffer/service/gl_context_mac.cc
index 9e79a69..6d2f726 100644
--- a/gpu/command_buffer/service/gl_context_mac.cc
+++ b/gpu/command_buffer/service/gl_context_mac.cc
@@ -13,29 +13,13 @@
namespace gpu {
+static const char* error_message =
+ "ViewGLContext not supported on Mac platform.";
+
bool ViewGLContext::Initialize(bool multisampled) {
#if !defined(UNIT_TEST)
- if (multisampled) {
- DLOG(WARNING) << "Multisampling not implemented.";
- }
-
- if (!surface_->Initialize()) {
- DLOG(ERROR) << "Error initializing accelerated surface.";
- return false;
- }
-
- if (!MakeCurrent()) {
- Destroy();
- DLOG(ERROR) << "Couldn't make context current for initialization.";
- return false;
- }
-
- if (!InitializeGLEW()) {
- Destroy();
- return false;
- }
-
- return true;
+ NOTIMPLEMENTED() << error_message;
+ return false;
#else
return true;
#endif // UNIT_TEST
@@ -43,31 +27,43 @@ bool ViewGLContext::Initialize(bool multisampled) {
void ViewGLContext::Destroy() {
#if !defined(UNIT_TEST)
- surface_->Destroy();
+ NOTIMPLEMENTED() << error_message;
#endif // UNIT_TEST
}
bool ViewGLContext::MakeCurrent() {
#if !defined(UNIT_TEST)
- return surface_->MakeCurrent();
+ NOTIMPLEMENTED() << error_message;
+ return false;
+#else
+ return true;
+#endif
+}
+
+bool ViewGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ NOTIMPLEMENTED() << error_message;
+ return false;
#else
return true;
#endif
}
bool ViewGLContext::IsOffscreen() {
+ NOTIMPLEMENTED() << error_message;
return false;
}
void ViewGLContext::SwapBuffers() {
#if !defined(UNIT_TEST)
- surface_->SwapBuffers();
+ NOTIMPLEMENTED() << error_message;
#endif // UNIT_TEST
}
gfx::Size ViewGLContext::GetSize() {
#if !defined(UNIT_TEST)
- return surface_->GetSize();
+ NOTIMPLEMENTED() << error_message;
+ return gfx::Size();
#else
return gfx::Size();
#endif // UNIT_TEST
@@ -75,19 +71,17 @@ gfx::Size ViewGLContext::GetSize() {
GLContextHandle ViewGLContext::GetHandle() {
#if !defined(UNIT_TEST)
- return surface_->context();
-#else
- return NULL;
+ NOTIMPLEMENTED() << error_message;
#endif // UNIT_TEST
+ return NULL;
}
bool PbufferGLContext::Initialize(GLContext* shared_context) {
-#if !defined(UNIT_TEST)
- // Get the shared context handle.
- GLContextHandle shared_handle = NULL;
- if (shared_context)
- shared_handle = shared_context->GetHandle();
+ return Initialize(shared_context ? shared_context->GetHandle() : NULL);
+}
+bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
+#if !defined(UNIT_TEST)
// Create a 1x1 pbuffer and associated context to bootstrap things.
static const CGLPixelFormatAttribute attribs[] = {
(CGLPixelFormatAttribute) kCGLPFAPBuffer,
@@ -156,7 +150,7 @@ void PbufferGLContext::Destroy() {
bool PbufferGLContext::MakeCurrent() {
#if !defined(UNIT_TEST)
- if (CGLGetCurrentContext() != context_) {
+ if (!IsCurrent()) {
if (CGLSetCurrentContext(context_) != kCGLNoError) {
DLOG(ERROR) << "Unable to make gl context current.";
return false;
@@ -167,6 +161,14 @@ bool PbufferGLContext::MakeCurrent() {
return true;
}
+bool PbufferGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ return CGLGetCurrentContext() == context_;
+#else
+ return true;
+#endif
+}
+
bool PbufferGLContext::IsOffscreen() {
return true;
}
diff --git a/gpu/command_buffer/service/gl_context_win.cc b/gpu/command_buffer/service/gl_context_win.cc
index 3be106a..6b5896c 100644
--- a/gpu/command_buffer/service/gl_context_win.cc
+++ b/gpu/command_buffer/service/gl_context_win.cc
@@ -228,8 +228,7 @@ void ViewGLContext::Destroy() {
bool ViewGLContext::MakeCurrent() {
#if !defined(UNIT_TEST)
- if (wglGetCurrentDC() == device_context_ &&
- wglGetCurrentContext() == context_) {
+ if (IsCurrent()) {
return true;
}
if (!wglMakeCurrent(device_context_, context_)) {
@@ -241,6 +240,15 @@ bool ViewGLContext::MakeCurrent() {
return true;
}
+bool ViewGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ return wglGetCurrentDC() == device_context_ &&
+ wglGetCurrentContext() == context_;
+#else
+ return true;
+#endif
+}
+
bool ViewGLContext::IsOffscreen() {
return false;
}
@@ -271,6 +279,10 @@ GLContextHandle ViewGLContext::GetHandle() {
}
bool PbufferGLContext::Initialize(GLContext* shared_context) {
+ return Initialize(shared_context ? shared_context->GetHandle() : NULL);
+}
+
+bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
#if !defined(UNIT_TEST)
InitializeOneOff();
@@ -306,8 +318,8 @@ bool PbufferGLContext::Initialize(GLContext* shared_context) {
return false;
}
- if (shared_context) {
- if (!wglShareLists(shared_context->GetHandle(), context_)) {
+ if (shared_handle) {
+ if (!wglShareLists(shared_handle, context_)) {
DLOG(ERROR) << "Could not share GL contexts.";
Destroy();
return false;
@@ -339,8 +351,7 @@ void PbufferGLContext::Destroy() {
bool PbufferGLContext::MakeCurrent() {
#if !defined(UNIT_TEST)
- if (wglGetCurrentDC() == device_context_ &&
- wglGetCurrentContext() == context_) {
+ if (IsCurrent()) {
return true;
}
if (!wglMakeCurrent(device_context_, context_)) {
@@ -352,6 +363,15 @@ bool PbufferGLContext::MakeCurrent() {
return true;
}
+bool PbufferGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ return wglGetCurrentDC() == device_context_ &&
+ wglGetCurrentContext() == context_;
+#else
+ return true;
+#endif
+}
+
bool PbufferGLContext::IsOffscreen() {
return true;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 911c19a..ce4f44d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -3405,6 +3405,14 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers(
#endif
}
+ // TODO(kbr): when the back buffer is multisampled, then at least on Mac
+ // OS X (and probably on all platforms, for best semantics), we will need
+ // to perform the resolve step and bind the offscreen_saved_color_texture_
+ // as the color attachment before calling the swap buffers callback, which
+ // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
+ // glReadPixels. After the callback runs, the multisampled frame buffer
+ // needs to be bound again.
+
if (swap_buffers_callback_.get()) {
swap_buffers_callback_->Run();
}
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index 4514211..ab3230b 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -69,7 +69,7 @@ bool GPUProcessor::InitializeCommon(const gfx::Size& size,
return true;
}
-void GPUProcessor::Destroy() {
+void GPUProcessor::DestroyCommon() {
if (decoder_.get()) {
decoder_->Destroy();
decoder_.reset();
@@ -141,7 +141,10 @@ void GPUProcessor::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
void GPUProcessor::SetSwapBuffersCallback(
Callback0::Type* callback) {
- decoder_->SetSwapBuffersCallback(callback);
+ wrapped_swap_buffers_callback_.reset(callback);
+ decoder_->SetSwapBuffersCallback(
+ NewCallback(this,
+ &GPUProcessor::WillSwapBuffers));
}
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
index c4c0ea5..eb2d52b 100644
--- a/gpu/command_buffer/service/gpu_processor.h
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -51,6 +51,7 @@ class GPUProcessor : public CommandBufferEngine {
uint32 parent_texture_id);
void Destroy();
+ void DestroyCommon();
virtual void ProcessCommands();
@@ -84,6 +85,10 @@ class GPUProcessor : public CommandBufferEngine {
virtual void SetSwapBuffersCallback(Callback0::Type* callback);
private:
+ // Called via a callback just before we are supposed to call the
+ // user's swap buffers callback.
+ virtual void WillSwapBuffers();
+
// The GPUProcessor holds a weak reference to the CommandBuffer. The
// CommandBuffer owns the GPUProcessor and holds a strong reference to it
// through the ProcessCommands callback.
@@ -97,10 +102,11 @@ class GPUProcessor : public CommandBufferEngine {
scoped_ptr<GLContext> context_;
#if defined(OS_MACOSX) && !defined(UNIT_TEST)
- AcceleratedSurface surface_;
+ scoped_ptr<AcceleratedSurface> surface_;
#endif
ScopedRunnableMethodFactory<GPUProcessor> method_factory_;
+ scoped_ptr<Callback0::Type> wrapped_swap_buffers_callback_;
};
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor_linux.cc b/gpu/command_buffer/service/gpu_processor_linux.cc
index 10f1a87..4217b72 100644
--- a/gpu/command_buffer/service/gpu_processor_linux.cc
+++ b/gpu/command_buffer/service/gpu_processor_linux.cc
@@ -57,4 +57,14 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
return true;
}
+void GPUProcessor::Destroy() {
+ DestroyCommon();
+}
+
+void GPUProcessor::WillSwapBuffers() {
+ if (wrapped_swap_buffers_callback_.get()) {
+ wrapped_swap_buffers_callback_->Run();
+ }
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor_mac.cc b/gpu/command_buffer/service/gpu_processor_mac.cc
index 55b6816..4893c89 100644
--- a/gpu/command_buffer/service/gpu_processor_mac.cc
+++ b/gpu/command_buffer/service/gpu_processor_mac.cc
@@ -28,27 +28,25 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
DCHECK(parent_context);
}
- // Create either a view or pbuffer based GLContext.
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
+ if (!context->Initialize(parent_context)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
+ // On Mac OS X since we can not render on-screen we don't even
+ // attempt to create a view based GLContext. The only difference
+ // between "on-screen" and "off-screen" rendering on this platform
+ // is whether we allocate an AcceleratedSurface, which transmits the
+ // rendering results back to the browser.
if (window) {
#if !defined(UNIT_TEST)
- AcceleratedSurface* surface_ptr = &surface_;
-#else
- AcceleratedSurface* surface_ptr = NULL;
-#endif
- scoped_ptr<ViewGLContext> context(new ViewGLContext(surface_ptr));
- // TODO(apatrick): support multisampling.
- if (!context->Initialize(false)) {
- Destroy();
- return false;
- }
- context_.reset(context.release());
- } else {
- scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
- if (!context->Initialize(parent_context)) {
+ surface_.reset(new AcceleratedSurface());
+ if (!surface_->Initialize(context_->GetHandle(), false)) {
Destroy();
return false;
}
- context_.reset(context.release());
+#endif
}
return InitializeCommon(size, parent_decoder, parent_texture_id);
@@ -56,9 +54,20 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
return true;
}
+void GPUProcessor::Destroy() {
+#if !defined(UNIT_TEST)
+ if (surface_.get()) {
+ surface_->Destroy();
+ }
+ surface_.reset();
+#endif
+ DestroyCommon();
+}
+
uint64 GPUProcessor::SetWindowSizeForIOSurface(const gfx::Size& size) {
#if !defined(UNIT_TEST)
- return surface_.SetSurfaceSize(size);
+ ResizeOffscreenFrameBuffer(size);
+ return surface_->SetSurfaceSize(size);
#else
return 0;
#endif
@@ -67,7 +76,8 @@ uint64 GPUProcessor::SetWindowSizeForIOSurface(const gfx::Size& size) {
TransportDIB::Handle GPUProcessor::SetWindowSizeForTransportDIB(
const gfx::Size& size) {
#if !defined(UNIT_TEST)
- return surface_.SetTransportDIBSize(size);
+ ResizeOffscreenFrameBuffer(size);
+ return surface_->SetTransportDIBSize(size);
#else
return TransportDIB::DefaultHandleValue();
#endif
@@ -77,8 +87,21 @@ void GPUProcessor::SetTransportDIBAllocAndFree(
Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
Callback1<TransportDIB::Id>::Type* deallocator) {
#if !defined(UNIT_TEST)
- surface_.SetTransportDIBAllocAndFree(allocator, deallocator);
+ surface_->SetTransportDIBAllocAndFree(allocator, deallocator);
+#endif
+}
+
+void GPUProcessor::WillSwapBuffers() {
+ DCHECK(context_->IsCurrent());
+#if !defined(UNIT_TEST)
+ if (surface_.get()) {
+ surface_->SwapBuffers();
+ }
#endif
+
+ if (wrapped_swap_buffers_callback_.get()) {
+ wrapped_swap_buffers_callback_->Run();
+ }
}
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc
index 143d5a6..77523be 100644
--- a/gpu/command_buffer/service/gpu_processor_win.cc
+++ b/gpu/command_buffer/service/gpu_processor_win.cc
@@ -52,4 +52,15 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
return true;
}
+
+void GPUProcessor::Destroy() {
+ DestroyCommon();
+}
+
+void GPUProcessor::WillSwapBuffers() {
+ if (wrapped_swap_buffers_callback_.get()) {
+ wrapped_swap_buffers_callback_->Run();
+ }
+}
+
} // namespace gpu
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index 77aae29..7f33a52 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -296,7 +296,7 @@ bool WebPluginDelegateImpl::PlatformInitialize() {
layer_ = layer;
plugin_->BindFakePluginWindowHandle();
surface_ = new AcceleratedSurface;
- surface_->Initialize();
+ surface_->Initialize(NULL, true);
renderer_ = [[CARenderer rendererWithCGLContext:surface_->context()
options:NULL] retain];
[renderer_ setLayer:layer_];
diff --git a/webkit/tools/test_shell/mac/accelerated_surface_stub.cc b/webkit/tools/test_shell/mac/accelerated_surface_stub.cc
deleted file mode 100644
index a4ca5de..0000000
--- a/webkit/tools/test_shell/mac/accelerated_surface_stub.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is a complete and total hack intended to stub out some classes
-// used by WebPluginDelegateImpl on Mac. Unfortunately, they live in
-// chrome/common, so we can't compile them into TestShell. Instead, provide
-// some stubs. It will need to be updated if new methods are added to
-// AcceleratedSurface that get called from WebPluginDelegateImpl. It's not
-// like plug-ins work in TestShell anyway.
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <OpenGL/OpenGL.h>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "gfx/rect.h"
-#include "gfx/size.h"
-
-class TransportDIB {
- public:
- TransportDIB() { }
- ~TransportDIB() { }
-};
-
-class AcceleratedSurface {
- public:
- AcceleratedSurface();
- virtual ~AcceleratedSurface();
-
- bool Initialize();
- void Destroy();
- uint64 SetSurfaceSize(const gfx::Size& size);
- bool MakeCurrent();
- void Clear(const gfx::Rect& rect);
- void SwapBuffers();
- CGLContextObj context() { return NULL; }
- private:
- scoped_ptr<TransportDIB> ignore_;
-};
-
-AcceleratedSurface::AcceleratedSurface() { }
-AcceleratedSurface::~AcceleratedSurface() { }
-bool AcceleratedSurface::Initialize() { return false; }
-void AcceleratedSurface::Destroy() { }
-uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size)
- { return 0; }
-bool AcceleratedSurface::MakeCurrent() { return false; }
-void AcceleratedSurface::Clear(const gfx::Rect& rect) { }
-void AcceleratedSurface::SwapBuffers() { }
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index 84c085f..79a8242 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -47,7 +47,6 @@
],
'msvs_guid': '77C32787-1B96-CB84-B905-7F170629F0AC',
'sources': [
- 'mac/accelerated_surface_stub.cc',
'mac/DumpRenderTreePasteboard.h',
'mac/DumpRenderTreePasteboard.m',
'mac/test_shell_webview.h',