diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-22 23:04:37 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-22 23:04:37 +0000 |
commit | ad7bbbd6badf073dfd61bcc8d3ea9124d8b14ce7 (patch) | |
tree | 16d59f3a765faf69f39bf3dcff8d2fa4b6e15030 /ui/gfx | |
parent | 9cb2b3b8c8b21fb46d20ad4d6f14cdc7d6b3aeaf (diff) | |
download | chromium_src-ad7bbbd6badf073dfd61bcc8d3ea9124d8b14ce7.zip chromium_src-ad7bbbd6badf073dfd61bcc8d3ea9124d8b14ce7.tar.gz chromium_src-ad7bbbd6badf073dfd61bcc8d3ea9124d8b14ce7.tar.bz2 |
Reland 81998.The bug in webkit\gpu\webgraphicscontext3d_in_process_impl.cc that assumed creating a new GLContext made it current is now fixed and this patch should now work.
Original message:
Split OSMesa implementations of *GLContext into GLContextOSMesa and *GLSurfaceOSMesa.
Surfaces are independent of contexts in GL. To facilitate sharing of surfaces between processes, I have separated them from the notion of contexts because contexts cannot be shared between processes.
I started with EGL in r81512 and WGL in r81807. This is the same thing for OSMesa.
GLContextOSMesa still has a pointer to a surface and still has some surface specific operations that just forward through to it. Once I have refactored all the GLContext implementations in this way, I will remove these pointers and the surface specific opertations.
There will not be "view" and "offscreen" GL contexts. Rather there will be a single context type for each backend which can be made current with a surface that directs output either to a view or offscreen surface.
Original review:
http://codereview.chromium.org/6864031/
TEST=ran linux_layout and mac_layout try jobs (they were failing before)
BUG=none
Review URL: http://codereview.chromium.org/6881071
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82748 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r-- | ui/gfx/gl/gl.gyp | 2 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_linux.cc | 107 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_mac.cc | 6 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_osmesa.cc | 102 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_osmesa.h | 22 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_win.cc | 101 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_egl.h | 6 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_osmesa.cc | 61 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_osmesa.h | 43 |
9 files changed, 240 insertions, 210 deletions
diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp index 507d9b4..83299b3a 100644 --- a/ui/gfx/gl/gl.gyp +++ b/ui/gfx/gl/gl.gyp @@ -76,6 +76,8 @@ 'gl_interface.h', 'gl_surface.cc', 'gl_surface.h', + 'gl_surface_osmesa.cc', + 'gl_surface_osmesa.h', 'gl_switches.cc', 'gl_switches.h', '<(gl_binding_output_dir)/gl_bindings_autogen_gl.cc', diff --git a/ui/gfx/gl/gl_context_linux.cc b/ui/gfx/gl/gl_context_linux.cc index 6cd77dd..36f0e8a 100644 --- a/ui/gfx/gl/gl_context_linux.cc +++ b/ui/gfx/gl/gl_context_linux.cc @@ -22,6 +22,7 @@ extern "C" { #include "ui/gfx/gl/gl_context_stub.h" #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface_egl.h" +#include "ui/gfx/gl/gl_surface_osmesa.h" namespace { @@ -77,29 +78,20 @@ class ViewGLContext : public BaseLinuxGLContext { DISALLOW_COPY_AND_ASSIGN(ViewGLContext); }; -// This class is a wrapper around a GL context that uses OSMesa to render -// to an offscreen buffer and then blits it to a window. -class OSMesaViewGLContext : public GLContext { +// This OSMesa GL surface can use XLib to swap the contents of the buffer to a +// view. +class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa { public: - explicit OSMesaViewGLContext(gfx::PluginWindowHandle window) - : window_graphics_context_(0), - window_(window), - pixmap_graphics_context_(0), - pixmap_(0) { - DCHECK(window); - } + explicit NativeViewGLSurfaceOSMesa(gfx::PluginWindowHandle window); + virtual ~NativeViewGLSurfaceOSMesa(); // Initializes the GL context. bool Initialize(); + // Implement a subset of GLSurface. virtual void Destroy(); - virtual bool MakeCurrent(); - virtual bool IsCurrent(); virtual bool IsOffscreen(); virtual bool SwapBuffers(); - virtual gfx::Size GetSize(); - virtual void* GetHandle(); - virtual void SetSwapInterval(int interval); private: bool UpdateSize(); @@ -108,9 +100,8 @@ class OSMesaViewGLContext : public GLContext { gfx::PluginWindowHandle window_; GC pixmap_graphics_context_; Pixmap pixmap_; - OSMesaGLContext osmesa_context_; - DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext); + DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa); }; // This class is a wrapper around a GL context used for offscreen rendering. @@ -348,13 +339,20 @@ void ViewGLContext::SetSwapInterval(int interval) { } } -bool OSMesaViewGLContext::Initialize() { - if (!osmesa_context_.Initialize(OSMESA_BGRA, NULL)) { - LOG(ERROR) << "OSMesaGLContext::Initialize failed."; - Destroy(); - return false; - } +NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa( + gfx::PluginWindowHandle window) + : window_graphics_context_(0), + window_(window), + pixmap_graphics_context_(0), + pixmap_(0) { + DCHECK(window); +} +NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() { + Destroy(); +} + +bool NativeViewGLSurfaceOSMesa::Initialize() { window_graphics_context_ = XCreateGC(GetXDisplayHelper(), window_, 0, @@ -370,9 +368,7 @@ bool OSMesaViewGLContext::Initialize() { return true; } -void OSMesaViewGLContext::Destroy() { - osmesa_context_.Destroy(); - +void NativeViewGLSurfaceOSMesa::Destroy() { Display* display = GetXDisplayHelper(); if (pixmap_graphics_context_) { @@ -391,31 +387,19 @@ void OSMesaViewGLContext::Destroy() { } } -bool OSMesaViewGLContext::MakeCurrent() { - // TODO(apatrick): This is a bit of a hack. The window might have had zero - // size when the context was initialized. Assume it has a valid size when - // MakeCurrent is called and resize the back buffer if necessary. - UpdateSize(); - return osmesa_context_.MakeCurrent(); -} - -bool OSMesaViewGLContext::IsCurrent() { - return osmesa_context_.IsCurrent(); -} - -bool OSMesaViewGLContext::IsOffscreen() { +bool NativeViewGLSurfaceOSMesa::IsOffscreen() { return false; } -bool OSMesaViewGLContext::SwapBuffers() { +bool NativeViewGLSurfaceOSMesa::SwapBuffers() { // Update the size before blitting so that the blit size is exactly the same // as the window. if (!UpdateSize()) { - LOG(ERROR) << "Failed to update size of OSMesaGLContext."; + LOG(ERROR) << "Failed to update size of GLContextOSMesa."; return false; } - gfx::Size size = osmesa_context_.GetSize(); + gfx::Size size = GetSize(); Display* display = GetXDisplayHelper(); @@ -427,7 +411,7 @@ bool OSMesaViewGLContext::SwapBuffers() { attributes.depth, pixmap_, pixmap_graphics_context_, - static_cast<const uint8*>(osmesa_context_.buffer()), + static_cast<const uint8*>(GetHandle()), size.width(), size.height()); @@ -443,21 +427,7 @@ bool OSMesaViewGLContext::SwapBuffers() { return true; } -gfx::Size OSMesaViewGLContext::GetSize() { - return osmesa_context_.GetSize(); -} - -void* OSMesaViewGLContext::GetHandle() { - return osmesa_context_.GetHandle(); -} - -void OSMesaViewGLContext::SetSwapInterval(int interval) { - DCHECK(IsCurrent()); - // Fail silently. It is legitimate to set the swap interval on a view context - // but XLib does not have those semantics. -} - -bool OSMesaViewGLContext::UpdateSize() { +bool NativeViewGLSurfaceOSMesa::UpdateSize() { // Get the window size. XWindowAttributes attributes; Display* display = GetXDisplayHelper(); @@ -466,12 +436,12 @@ bool OSMesaViewGLContext::UpdateSize() { std::max(1, attributes.height)); // Early out if the size has not changed. - gfx::Size osmesa_size = osmesa_context_.GetSize(); + gfx::Size osmesa_size = GetSize(); if (pixmap_graphics_context_ && pixmap_ && window_size == osmesa_size) return true; // Change osmesa surface size to that of window. - osmesa_context_.Resize(window_size); + Resize(window_size); // Destroy the previous pixmap and graphics context. if (pixmap_graphics_context_) { @@ -529,9 +499,14 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, return context.release(); } case kGLImplementationOSMesaGL: { - scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); + scoped_ptr<NativeViewGLSurfaceOSMesa> surface( + new NativeViewGLSurfaceOSMesa(window)); + if (!surface->Initialize()) + return NULL; - if (!context->Initialize()) + scoped_ptr<GLContextOSMesa> context( + new GLContextOSMesa(surface.release())); + if (!context->Initialize(OSMESA_BGRA, NULL)) return NULL; return context.release(); @@ -823,8 +798,12 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { return context.release(); } case kGLImplementationOSMesaGL: { - scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); - if (!context->Initialize(OSMESA_RGBA, shared_context)) + scoped_ptr<GLSurfaceOSMesa> surface(new GLSurfaceOSMesa()); + surface->Resize(gfx::Size(1, 1)); + + scoped_ptr<GLContextOSMesa> context( + new GLContextOSMesa(surface.release())); + if (!context->Initialize(OSMESA_BGRA, shared_context)) return NULL; return context.release(); diff --git a/ui/gfx/gl/gl_context_mac.cc b/ui/gfx/gl/gl_context_mac.cc index 10e8bf3..21b0403 100644 --- a/ui/gfx/gl/gl_context_mac.cc +++ b/ui/gfx/gl/gl_context_mac.cc @@ -192,7 +192,11 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { return context.release(); } case kGLImplementationOSMesaGL: { - scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + scoped_ptr<GLSurfaceOSMesa> surface(new GLSurfaceOSMesa()); + surface->Resize(gfx::Size(1, 1)); + + scoped_ptr<GLContextOSMesa> context( + new GLContextOSMesa(surface.release())); if (!context->Initialize(OSMESA_RGBA, shared_context)) return NULL; diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc index 9d1e802..6da01d1 100644 --- a/ui/gfx/gl/gl_context_osmesa.cc +++ b/ui/gfx/gl/gl_context_osmesa.cc @@ -12,19 +12,18 @@ namespace gfx { -OSMesaGLContext::OSMesaGLContext() : context_(NULL) +GLContextOSMesa::GLContextOSMesa(GLSurfaceOSMesa* surface) + : surface_(surface), + context_(NULL) { } -OSMesaGLContext::~OSMesaGLContext() { +GLContextOSMesa::~GLContextOSMesa() { } -bool OSMesaGLContext::Initialize(GLuint format, GLContext* shared_context) { +bool GLContextOSMesa::Initialize(GLuint format, GLContext* shared_context) { DCHECK(!context_); - size_ = gfx::Size(1, 1); - buffer_.reset(new int32[1]); - OSMesaContext shared_handle = NULL; if (shared_context) shared_handle = static_cast<OSMesaContext>(shared_context->GetHandle()); @@ -39,93 +38,64 @@ bool OSMesaGLContext::Initialize(GLuint format, GLContext* shared_context) { return false; } - if (!MakeCurrent()) { - LOG(ERROR) << "MakeCurrent failed."; - Destroy(); - return false; - } - - // Row 0 is at the top. - OSMesaPixelStore(OSMESA_Y_UP, 0); - - if (!InitializeCommon()) { - LOG(ERROR) << "GLContext::InitializeCommon failed."; - Destroy(); - return false; - } - return true; } -void OSMesaGLContext::Resize(const gfx::Size& new_size) { - if (new_size == size_) - return; - - // Allocate a new back buffer. - scoped_array<int32> new_buffer(new int32[new_size.GetArea()]); - memset(new_buffer.get(), 0, new_size.GetArea() * sizeof(new_buffer[0])); - - // Copy the current back buffer into the new buffer. - int copy_width = std::min(size_.width(), new_size.width()); - int copy_height = std::min(size_.height(), new_size.height()); - for (int y = 0; y < copy_height; ++y) { - for (int x = 0; x < copy_width; ++x) { - new_buffer[y * new_size.width() + x] = buffer_[y * size_.width() + x]; - } - } - - buffer_.reset(new_buffer.release()); - size_ = new_size; - - // If this context is current, need to call MakeCurrent again so OSMesa uses - // the new buffer. - if (IsCurrent()) - MakeCurrent(); -} - -void OSMesaGLContext::Destroy() { +void GLContextOSMesa::Destroy() { if (context_) { OSMesaDestroyContext(static_cast<OSMesaContext>(context_)); context_ = NULL; } - buffer_.reset(); - size_ = gfx::Size(); + + surface_->Destroy(); + surface_.reset(); } -bool OSMesaGLContext::MakeCurrent() { +bool GLContextOSMesa::MakeCurrent() { DCHECK(context_); - return OSMesaMakeCurrent(static_cast<OSMesaContext>(context_), - buffer_.get(), - GL_UNSIGNED_BYTE, - size_.width(), size_.height()) == GL_TRUE; + + gfx::Size size = surface_->GetSize(); + + if (!OSMesaMakeCurrent(static_cast<OSMesaContext>(context_), + surface_->GetHandle(), + GL_UNSIGNED_BYTE, + size.width(), size.height())) { + return false; + } + + // Row 0 is at the top. + OSMesaPixelStore(OSMESA_Y_UP, 0); + return true; } -bool OSMesaGLContext::IsCurrent() { +bool GLContextOSMesa::IsCurrent() { DCHECK(context_); return context_ == OSMesaGetCurrentContext(); } -bool OSMesaGLContext::IsOffscreen() { - return true; +bool GLContextOSMesa::IsOffscreen() { + // TODO(apatrick): remove this from GLContext interface. + return surface_->IsOffscreen(); } -bool OSMesaGLContext::SwapBuffers() { - NOTREACHED() << "Should not call SwapBuffers on an OSMesaGLContext."; - return false; +bool GLContextOSMesa::SwapBuffers() { + // TODO(apatrick): remove this from GLContext interface. + return surface_->SwapBuffers(); } -gfx::Size OSMesaGLContext::GetSize() { - return size_; +gfx::Size GLContextOSMesa::GetSize() { + // TODO(apatrick): remove this from GLContext interface. + return surface_->GetSize(); } -void* OSMesaGLContext::GetHandle() { +void* GLContextOSMesa::GetHandle() { return context_; } -void OSMesaGLContext::SetSwapInterval(int interval) { +void GLContextOSMesa::SetSwapInterval(int interval) { DCHECK(IsCurrent()); - NOTREACHED() << "Attempt to call SetSwapInterval on an OSMesaGLContext."; + NOTREACHED() << "Attempt to call SetSwapInterval on an GLContextOSMesa."; } } // namespace gfx diff --git a/ui/gfx/gl/gl_context_osmesa.h b/ui/gfx/gl/gl_context_osmesa.h index 77ca820..33aa21c 100644 --- a/ui/gfx/gl/gl_context_osmesa.h +++ b/ui/gfx/gl/gl_context_osmesa.h @@ -8,6 +8,7 @@ #include "base/memory/scoped_ptr.h" #include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_surface_osmesa.h" #include "ui/gfx/size.h" typedef struct osmesa_context *OSMesaContext; @@ -15,22 +16,14 @@ typedef struct osmesa_context *OSMesaContext; namespace gfx { // Encapsulates an OSMesa OpenGL context that uses software rendering. -class OSMesaGLContext : public GLContext { +class GLContextOSMesa : public GLContext { public: - OSMesaGLContext(); - virtual ~OSMesaGLContext(); + explicit GLContextOSMesa(GLSurfaceOSMesa* surface); + virtual ~GLContextOSMesa(); - // Initialize an OSMesa GL context with the default 1 x 1 initial size. + // Initialize an OSMesa GL context. bool Initialize(GLuint format, GLContext* shared_context); - // Resize the back buffer, preserving the old content. Does nothing if the - // size is unchanged. - void Resize(const gfx::Size& new_size); - - const void* buffer() const { - return buffer_.get(); - } - // Implement GLContext. virtual void Destroy(); virtual bool MakeCurrent(); @@ -42,11 +35,10 @@ class OSMesaGLContext : public GLContext { virtual void SetSwapInterval(int interval); private: - gfx::Size size_; - scoped_array<int32> buffer_; + scoped_ptr<GLSurfaceOSMesa> surface_; OSMesaContext context_; - DISALLOW_COPY_AND_ASSIGN(OSMesaGLContext); + DISALLOW_COPY_AND_ASSIGN(GLContextOSMesa); }; } // namespace gfx diff --git a/ui/gfx/gl/gl_context_win.cc b/ui/gfx/gl/gl_context_win.cc index 87f3d98..3222b84 100644 --- a/ui/gfx/gl/gl_context_win.cc +++ b/ui/gfx/gl/gl_context_win.cc @@ -19,40 +19,33 @@ #include "ui/gfx/gl/gl_context_wgl.h" #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface_egl.h" +#include "ui/gfx/gl/gl_surface_osmesa.h" #include "ui/gfx/gl/gl_surface_wgl.h" namespace gfx { -// This class is a wrapper around a GL context that uses OSMesa to render -// to an offscreen buffer and then blits it to a window. -class OSMesaViewGLContext : public GLContext { +// This OSMesa GL surface can use GDI to swap the contents of the buffer to a +// view. +class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa { public: - explicit OSMesaViewGLContext(gfx::PluginWindowHandle window) - : window_(window), - device_context_(NULL) { - DCHECK(window); - } + explicit NativeViewGLSurfaceOSMesa(gfx::PluginWindowHandle window); + virtual ~NativeViewGLSurfaceOSMesa(); // Initializes the GL context. bool Initialize(); + // Implement subset of GLSurface. virtual void Destroy(); - virtual bool MakeCurrent(); - virtual bool IsCurrent(); virtual bool IsOffscreen(); virtual bool SwapBuffers(); - virtual gfx::Size GetSize(); - virtual void* GetHandle(); - virtual void SetSwapInterval(int interval); private: void UpdateSize(); gfx::PluginWindowHandle window_; HDC device_context_; - OSMesaGLContext osmesa_context_; - DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext); + DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa); }; // Helper routine that does one-off initialization like determining the @@ -93,55 +86,45 @@ bool GLContext::InitializeOneOff() { return true; } -bool OSMesaViewGLContext::Initialize() { - // The GL context will render to this window. - device_context_ = GetDC(window_); +NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa( + gfx::PluginWindowHandle window) + : window_(window), + device_context_(NULL) { + DCHECK(window); +} - if (!osmesa_context_.Initialize(OSMESA_RGBA, NULL)) { - LOG(ERROR) << "OSMesaGLContext::Initialize failed."; - Destroy(); - return false; - } +NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() { + Destroy(); +} +bool NativeViewGLSurfaceOSMesa::Initialize() { + device_context_ = GetDC(window_); UpdateSize(); - return true; } -void OSMesaViewGLContext::Destroy() { - osmesa_context_.Destroy(); - +void NativeViewGLSurfaceOSMesa::Destroy() { if (window_ && device_context_) ReleaseDC(window_, device_context_); window_ = NULL; device_context_ = NULL; -} -bool OSMesaViewGLContext::MakeCurrent() { - // TODO(apatrick): This is a bit of a hack. The window might have had zero - // size when the context was initialized. Assume it has a valid size when - // MakeCurrent is called and resize the back buffer if necessary. - UpdateSize(); - return osmesa_context_.MakeCurrent(); + GLSurfaceOSMesa::Destroy(); } -bool OSMesaViewGLContext::IsCurrent() { - return osmesa_context_.IsCurrent(); -} - -bool OSMesaViewGLContext::IsOffscreen() { +bool NativeViewGLSurfaceOSMesa::IsOffscreen() { return false; } -bool OSMesaViewGLContext::SwapBuffers() { +bool NativeViewGLSurfaceOSMesa::SwapBuffers() { DCHECK(device_context_); // Update the size before blitting so that the blit size is exactly the same // as the window. UpdateSize(); - gfx::Size size = osmesa_context_.GetSize(); + gfx::Size size = GetSize(); // Note: negating the height below causes GDI to treat the bitmap data as row // 0 being at the top. @@ -166,7 +149,7 @@ bool OSMesaViewGLContext::SwapBuffers() { StretchDIBits(device_context_, 0, 0, size.width(), size.height(), 0, 0, size.width(), size.height(), - osmesa_context_.buffer(), + GetHandle(), reinterpret_cast<BITMAPINFO*>(&info), DIB_RGB_COLORS, SRCCOPY); @@ -174,21 +157,7 @@ bool OSMesaViewGLContext::SwapBuffers() { return true; } -gfx::Size OSMesaViewGLContext::GetSize() { - return osmesa_context_.GetSize(); -} - -void* OSMesaViewGLContext::GetHandle() { - return osmesa_context_.GetHandle(); -} - -void OSMesaViewGLContext::SetSwapInterval(int interval) { - DCHECK(IsCurrent()); - // Fail silently. It is legitimate to set the swap interval on a view context - // but GDI does not have those semantics. -} - -void OSMesaViewGLContext::UpdateSize() { +void NativeViewGLSurfaceOSMesa::UpdateSize() { // Change back buffer size to that of window. If window handle is invalid, do // not change the back buffer size. RECT rect; @@ -198,15 +167,21 @@ void OSMesaViewGLContext::UpdateSize() { gfx::Size window_size = gfx::Size( std::max(1, static_cast<int>(rect.right - rect.left)), std::max(1, static_cast<int>(rect.bottom - rect.top))); - osmesa_context_.Resize(window_size); + Resize(window_size); } GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, bool multisampled) { switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { - scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); - if (!context->Initialize()) + scoped_ptr<NativeViewGLSurfaceOSMesa> surface( + new NativeViewGLSurfaceOSMesa(window)); + if (!surface->Initialize()) + return NULL; + + scoped_ptr<GLContextOSMesa> context( + new GLContextOSMesa(surface.release())); + if (!context->Initialize(OSMESA_RGBA, NULL)) return NULL; return context.release(); @@ -248,7 +223,11 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { - scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + scoped_ptr<GLSurfaceOSMesa> surface(new GLSurfaceOSMesa()); + surface->Resize(gfx::Size(1, 1)); + + scoped_ptr<GLContextOSMesa> context( + new GLContextOSMesa(surface.release())); if (!context->Initialize(OSMESA_RGBA, shared_context)) return NULL; diff --git a/ui/gfx/gl/gl_surface_egl.h b/ui/gfx/gl/gl_surface_egl.h index 9ff1c2b..fe31494 100644 --- a/ui/gfx/gl/gl_surface_egl.h +++ b/ui/gfx/gl/gl_surface_egl.h @@ -15,7 +15,7 @@ typedef void* EGLSurface; namespace gfx { -// Interface for EGL contexts. +// Interface for EGL surface. class GLSurfaceEGL : public GLSurface { public: GLSurfaceEGL(); @@ -35,7 +35,7 @@ class NativeViewGLSurfaceEGL : public GLSurfaceEGL { explicit NativeViewGLSurfaceEGL(void* window); virtual ~NativeViewGLSurfaceEGL(); - // Initialize an EGL context. + // Initialize an EGL surface. bool Initialize(); // Implement GLSurface. @@ -58,7 +58,7 @@ class PbufferGLSurfaceEGL : public GLSurfaceEGL { explicit PbufferGLSurfaceEGL(const gfx::Size& size); virtual ~PbufferGLSurfaceEGL(); - // Initialize an EGL context that shares a namespace with another. + // Initialize an EGL surface. bool Initialize(); // Implement GLSurface. diff --git a/ui/gfx/gl/gl_surface_osmesa.cc b/ui/gfx/gl/gl_surface_osmesa.cc new file mode 100644 index 0000000..8c4d11d --- /dev/null +++ b/ui/gfx/gl/gl_surface_osmesa.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2011 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. + +#include "ui/gfx/gl/gl_surface_osmesa.h" +#include "base/logging.h" +#include "ui/gfx/gl/gl_bindings.h" + +namespace gfx { + +GLSurfaceOSMesa::GLSurfaceOSMesa() +{ +} + +GLSurfaceOSMesa::~GLSurfaceOSMesa() { +} + +void GLSurfaceOSMesa::Resize(const gfx::Size& new_size) { + if (new_size == size_) + return; + + // Allocate a new back buffer. + scoped_array<int32> new_buffer(new int32[new_size.GetArea()]); + memset(new_buffer.get(), 0, new_size.GetArea() * sizeof(new_buffer[0])); + + // Copy the current back buffer into the new buffer. + int copy_width = std::min(size_.width(), new_size.width()); + int copy_height = std::min(size_.height(), new_size.height()); + for (int y = 0; y < copy_height; ++y) { + for (int x = 0; x < copy_width; ++x) { + new_buffer[y * new_size.width() + x] = buffer_[y * size_.width() + x]; + } + } + + buffer_.reset(new_buffer.release()); + size_ = new_size; +} + +void GLSurfaceOSMesa::Destroy() { + buffer_.reset(); + size_ = gfx::Size(); +} + +bool GLSurfaceOSMesa::IsOffscreen() { + return true; +} + +bool GLSurfaceOSMesa::SwapBuffers() { + NOTREACHED() << "Should not call SwapBuffers on an GLSurfaceOSMesa."; + return false; +} + +gfx::Size GLSurfaceOSMesa::GetSize() { + return size_; +} + +void* GLSurfaceOSMesa::GetHandle() { + return buffer_.get(); +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_surface_osmesa.h b/ui/gfx/gl/gl_surface_osmesa.h new file mode 100644 index 0000000..742d28a --- /dev/null +++ b/ui/gfx/gl/gl_surface_osmesa.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 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. + +#ifndef UI_GFX_GL_GL_SURFACE_OSMESA_H_ +#define UI_GFX_GL_GL_SURFACE_OSMESA_H_ +#pragma once + +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/gl/gl_surface.h" +#include "ui/gfx/size.h" + +namespace gfx { + +// A surface that the Mesa software renderer draws to. This is actually just a +// buffer in system memory. GetHandle returns a pointer to the buffer. These +// surfaces can be resized and resizing preserves the contents. +class GLSurfaceOSMesa : public GLSurface { + public: + GLSurfaceOSMesa(); + virtual ~GLSurfaceOSMesa(); + + // Resize the back buffer, preserving the old content. Does nothing if the + // size is unchanged. + void Resize(const gfx::Size& new_size); + + // Implement GLSurface. + virtual void Destroy(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + + private: + gfx::Size size_; + scoped_array<int32> buffer_; + + DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesa); +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_SURFACE_OSMESA_H_ |