diff options
-rw-r--r-- | app/surface/accelerated_surface_mac.cc | 116 | ||||
-rw-r--r-- | app/surface/accelerated_surface_mac.h | 52 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context.h | 15 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context_linux.cc | 33 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context_mac.cc | 70 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_context_win.cc | 32 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor.cc | 7 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor.h | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor_linux.cc | 10 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor_mac.cc | 61 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor_win.cc | 11 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 2 | ||||
-rw-r--r-- | webkit/tools/test_shell/mac/accelerated_surface_stub.cc | 50 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.gypi | 1 |
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, ¤t_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', |