diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 18:41:29 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 18:41:29 +0000 |
commit | 2e7bbf2913e4327aab57e5c1b440c13711241609 (patch) | |
tree | ea7833ea4c0d051a0d3ef626c33fd043c4fea2f9 | |
parent | c620fd59c67f5421b75e865075fb4e9aa2c24f7f (diff) | |
download | chromium_src-2e7bbf2913e4327aab57e5c1b440c13711241609.zip chromium_src-2e7bbf2913e4327aab57e5c1b440c13711241609.tar.gz chromium_src-2e7bbf2913e4327aab57e5c1b440c13711241609.tar.bz2 |
Create new GLSurface for cross process image transport.
Currently cross process image transport (on OSX and TOUCH_UI) uses the WebGL code path to render to a texture via FBO. This makes a clean break with path and centralizes the GL context specific IPC communication in one location.
By separating from the WebGL code, I was able to avoid wasting a texture attached to the FBO in the decoder (the old code ignored this attachment --- the new code makes no such attachment at the decoder level).
As a test of the new architecture, I have also implemented XComposite/GLX_texture_from_pixmap image transport (i.e. it's now possible to use the --use-gl=desktop backend on touch_ui builds).
BUG=none
TEST=3D CSS and WebGL on TOUCH_UI.
Review URL: http://codereview.chromium.org/7395020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93681 0039d316-1c4b-4281-b951-d872f2087c98
30 files changed, 896 insertions, 344 deletions
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_touch.cc b/chrome/browser/renderer_host/accelerated_surface_container_touch.cc index 47d23b8..f09f8ff 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_touch.cc +++ b/chrome/browser/renderer_host/accelerated_surface_container_touch.cc @@ -4,17 +4,65 @@ #include "chrome/browser/renderer_host/accelerated_surface_container_touch.h" +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> + +#include "base/memory/scoped_ptr.h" #include "third_party/angle/include/EGL/egl.h" #include "third_party/angle/include/EGL/eglext.h" #include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface_egl.h" +#include "ui/gfx/gl/gl_surface_glx.h" #include "ui/gfx/transform.h" -AcceleratedSurfaceContainerTouch::AcceleratedSurfaceContainerTouch( +namespace { + +class AcceleratedSurfaceContainerTouchEGL + : public AcceleratedSurfaceContainerTouch { + public: + AcceleratedSurfaceContainerTouchEGL(ui::CompositorGL* compositor, + const gfx::Size& size, + uint64 surface_handle); + // TextureGL implementation + virtual void Draw(const ui::TextureDrawParams& params) OVERRIDE; + + private: + ~AcceleratedSurfaceContainerTouchEGL(); + + void* image_; + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerTouchEGL); +}; + +class AcceleratedSurfaceContainerTouchGLX + : public AcceleratedSurfaceContainerTouch { + public: + AcceleratedSurfaceContainerTouchGLX(ui::CompositorGL* compositor, + const gfx::Size& size, + uint64 surface_handle); + // TextureGL implementation + virtual void Draw(const ui::TextureDrawParams& params) OVERRIDE; + + private: + ~AcceleratedSurfaceContainerTouchGLX(); + + XID pixmap_; + XID glx_pixmap_; + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerTouchGLX); +}; + +class ScopedPtrXFree { + public: + void operator()(void* x) const { + ::XFree(x); + } +}; + +AcceleratedSurfaceContainerTouchEGL::AcceleratedSurfaceContainerTouchEGL( ui::CompositorGL* compositor, const gfx::Size& size, uint64 surface_handle) - : TextureGL(compositor, size), + : AcceleratedSurfaceContainerTouch(compositor, size), image_(NULL) { compositor_->MakeCurrent(); @@ -32,25 +80,18 @@ AcceleratedSurfaceContainerTouch::AcceleratedSurfaceContainerTouch( glFlush(); } -AcceleratedSurfaceContainerTouch::~AcceleratedSurfaceContainerTouch() { +AcceleratedSurfaceContainerTouchEGL::~AcceleratedSurfaceContainerTouchEGL() { eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_); glFlush(); } -void AcceleratedSurfaceContainerTouch::SetBitmap( - const SkBitmap& bitmap, - const gfx::Point& origin, - const gfx::Size& overall_size) { - NOTIMPLEMENTED(); -} - -void AcceleratedSurfaceContainerTouch::Draw( +void AcceleratedSurfaceContainerTouchEGL::Draw( const ui::TextureDrawParams& params) { DCHECK(compositor_->program_no_swizzle()); ui::TextureDrawParams modified_params = params; - // Texture from GPU is flipped horizontally. + // Texture from GPU is flipped vertically. ui::Transform flipped; flipped.SetScaleY(-1.0); flipped.SetTranslateY(size_.height()); @@ -60,3 +101,145 @@ void AcceleratedSurfaceContainerTouch::Draw( DrawInternal(*compositor_->program_no_swizzle(), modified_params); } + +AcceleratedSurfaceContainerTouchGLX::AcceleratedSurfaceContainerTouchGLX( + ui::CompositorGL* compositor, + const gfx::Size& size, + uint64 surface_handle) + : AcceleratedSurfaceContainerTouch(compositor, size), + pixmap_(0), + glx_pixmap_(0) { + // Create pixmap from window. + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + int event_base, error_base; + if (XCompositeQueryExtension(dpy, &event_base, &error_base)) { + int major = 0, minor = 2; + XCompositeQueryVersion(dpy, &major, &minor); + if (major == 0 && minor < 2) { + LOG(ERROR) << "Pixmap from window not supported."; + return; + } + } + pixmap_ = XCompositeNameWindowPixmap(dpy, surface_handle); + + // Wrap the pixmap in a GLXPixmap + int screen = DefaultScreen(dpy); + XWindowAttributes gwa; + XGetWindowAttributes(dpy, RootWindow(dpy, screen), &gwa); + unsigned int visualid = XVisualIDFromVisual(gwa.visual); + + int nfbconfigs, config; + scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> fbconfigs( + glXGetFBConfigs(dpy, screen, &nfbconfigs)); + + for (config = 0; config < nfbconfigs; config++) { + XVisualInfo* visinfo = glXGetVisualFromFBConfig( + dpy, fbconfigs.get()[config]); + if (!visinfo || visinfo->visualid != visualid) + continue; + + int value; + glXGetFBConfigAttrib(dpy, + fbconfigs.get()[config], + GLX_DRAWABLE_TYPE, + &value); + if (!(value & GLX_PIXMAP_BIT)) + continue; + + glXGetFBConfigAttrib(dpy, + fbconfigs.get()[config], + GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value); + if (!(value & GLX_TEXTURE_2D_BIT_EXT)) + continue; + + glXGetFBConfigAttrib(dpy, + fbconfigs.get()[config], + GLX_BIND_TO_TEXTURE_RGB_EXT, + &value); + if (value == GL_FALSE) + continue; + + break; + } + + if (config == nfbconfigs) { + LOG(ERROR) + << "Could not find configuration suitable for binding a pixmap " + << "as a texture."; + return; + } + + const int pixmapAttribs[] = { + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, + 0 + }; + + glx_pixmap_ = glXCreatePixmap( + dpy, fbconfigs.get()[config], pixmap_, pixmapAttribs); + + // Create texture. + compositor_->MakeCurrent(); + glGenTextures(1, &texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_id_); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} + +AcceleratedSurfaceContainerTouchGLX::~AcceleratedSurfaceContainerTouchGLX() { + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + if (glx_pixmap_) + glXDestroyGLXPixmap(dpy, glx_pixmap_); + if (pixmap_) + XFreePixmap(dpy, pixmap_); +} + +void AcceleratedSurfaceContainerTouchGLX::Draw( + const ui::TextureDrawParams& params) { + DCHECK(compositor_->program_no_swizzle()); + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + + glBindTexture(GL_TEXTURE_2D, texture_id_); + glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); + DrawInternal(*compositor_->program_no_swizzle(), params); + glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT); +} + +} // namespace + +AcceleratedSurfaceContainerTouch::AcceleratedSurfaceContainerTouch( + ui::CompositorGL* compositor, + const gfx::Size& size) : + TextureGL(compositor, size) { +} + +// static +AcceleratedSurfaceContainerTouch* +AcceleratedSurfaceContainerTouch::CreateAcceleratedSurfaceContainer( + ui::CompositorGL* compositor, + const gfx::Size& size, + uint64 surface_handle) { + switch (gfx::GetGLImplementation()) { + case gfx::kGLImplementationDesktopGL: + return new AcceleratedSurfaceContainerTouchGLX(compositor, + size, + surface_handle); + case gfx::kGLImplementationEGLGLES2: + return new AcceleratedSurfaceContainerTouchEGL(compositor, + size, + surface_handle); + default: + NOTREACHED(); + return NULL; + } +} + +void AcceleratedSurfaceContainerTouch::SetBitmap( + const SkBitmap& bitmap, + const gfx::Point& origin, + const gfx::Size& overall_size) { + NOTREACHED(); +} diff --git a/chrome/browser/renderer_host/accelerated_surface_container_touch.h b/chrome/browser/renderer_host/accelerated_surface_container_touch.h index c30fdc7..8c770fa 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_touch.h +++ b/chrome/browser/renderer_host/accelerated_surface_container_touch.h @@ -7,7 +7,6 @@ #pragma once #include "base/basictypes.h" -#include "base/memory/ref_counted.h" #include "ui/gfx/compositor/compositor_gl.h" // Helper class for storing image data from the GPU process renderered @@ -16,20 +15,22 @@ // or destroyed. class AcceleratedSurfaceContainerTouch : public ui::TextureGL { public: - AcceleratedSurfaceContainerTouch(ui::CompositorGL* compositor, - const gfx::Size& size, - uint64 surface_handle); + static AcceleratedSurfaceContainerTouch* CreateAcceleratedSurfaceContainer( + ui::CompositorGL* compositor, + const gfx::Size& size, + uint64 surface_handle); + // TextureGL implementation virtual void SetBitmap(const SkBitmap& bitmap, const gfx::Point& origin, const gfx::Size& overall_size) OVERRIDE; - virtual void Draw(const ui::TextureDrawParams& params) OVERRIDE; - protected: - ~AcceleratedSurfaceContainerTouch(); + AcceleratedSurfaceContainerTouch( + ui::CompositorGL* compositor, + const gfx::Size& size); - void* image_; + private: DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerTouch); }; diff --git a/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc b/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc index 94f382f..6b3a5153 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc @@ -200,7 +200,7 @@ gfx::PluginWindowHandle RenderWidgetHostViewViews::GetCompositingSurface() { void RenderWidgetHostViewViews::AcceleratedSurfaceSetIOSurface( int32 width, int32 height, uint64 surface_id) { accelerated_surface_containers_[surface_id] = - new AcceleratedSurfaceContainerTouch( + AcceleratedSurfaceContainerTouch::CreateAcceleratedSurfaceContainer( static_cast<ui::CompositorGL*>(GetWidget()->GetCompositor()), gfx::Size(width, height), surface_id); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 42d7c1b..bd8f82d 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3844,6 +3844,11 @@ 'include_dirs': [ '../third_party/angle/include', ], + 'link_settings': { + 'libraries': [ + '-lXcomposite', + ], + }, }], ['webui_certificate_viewer==0', { 'sources/': [ diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 3b3fc5c..e689b07 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -270,15 +270,6 @@ bool GpuProcessHost::Init() { if (!CreateChannel()) return false; -#if defined(TOUCH_UI) - if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kUseGL) != gfx::kGLImplementationEGLName) { - LOG(ERROR) << "GPU process needs EGL_KHR_image_pixmap extension. " - << "Try --use-gl=egl on the command line."; - return false; - } -#endif - if (in_process_) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisableGpuWatchdog); diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc index 2bd04f1..365aa24 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.cc +++ b/content/browser/gpu/gpu_process_host_ui_shim.cc @@ -243,8 +243,8 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceSetIOSurface( #elif defined(TOUCH_UI) view->AcceleratedSurfaceSetIOSurface( params.width, params.height, params.identifier); - Send(new GpuMsg_AcceleratedSurfaceSetIOSurfaceACK( - params.renderer_id, params.route_id, params.identifier)); + Send(new AcceleratedSurfaceMsg_SetSurfaceACK( + params.route_id, params.identifier)); #endif } @@ -271,8 +271,7 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped( params.swap_buffers_count); #elif defined(TOUCH_UI) view->AcceleratedSurfaceBuffersSwapped(params.surface_id); - Send(new GpuMsg_AcceleratedSurfaceBuffersSwappedACK( - params.renderer_id, params.route_id, params.swap_buffers_count)); + Send(new AcceleratedSurfaceMsg_BuffersSwappedACK(params.route_id)); #endif } @@ -290,9 +289,6 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease( if (!view) return; view->AcceleratedSurfaceRelease(params.identifier); - - Send(new GpuMsg_AcceleratedSurfaceReleaseACK( - params.renderer_id, params.route_id, params.identifier)); } #endif diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index 5c430c4..4270bb0 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -234,25 +234,7 @@ GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { return stubs_.Lookup(route_id); } -#if defined(TOUCH_UI) -void GpuChannel::AcceleratedSurfaceIOSurfaceSet( - int32 route_id, uint64 surface_id) { - GpuCommandBufferStub* stub = stubs_.Lookup(route_id); - if (stub == NULL) - return; - stub->AcceleratedSurfaceIOSurfaceSet(surface_id); -} - -void GpuChannel::AcceleratedSurfaceReleased( - int32 route_id, uint64 surface_id) { - GpuCommandBufferStub* stub = stubs_.Lookup(route_id); - if (stub == NULL) - return; - stub->AcceleratedSurfaceReleased(surface_id); -} -#endif - -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) void GpuChannel::AcceleratedSurfaceBuffersSwapped( int32 route_id, uint64 swap_buffers_count) { GpuCommandBufferStub* stub = stubs_.Lookup(route_id); @@ -260,9 +242,7 @@ void GpuChannel::AcceleratedSurfaceBuffersSwapped( return; stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); } -#endif -#if defined(OS_MACOSX) void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { // This responds to a message from the browser process to destroy the command // buffer when the window with a GpuScheduler is closed (see diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index 7defd5b..6f7614b 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -101,19 +101,9 @@ class GpuChannel : public IPC::Channel::Listener, GpuCommandBufferStub* LookupCommandBuffer(int32 route_id); -#if defined(TOUCH_UI) - virtual void AcceleratedSurfaceIOSurfaceSet( - int32 route_id, uint64 surface_id); - virtual void AcceleratedSurfaceReleased( - int32 route_id, uint64 surface_id); -#endif - -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) virtual void AcceleratedSurfaceBuffersSwapped( int32 route_id, uint64 swap_buffers_count); -#endif - -#if defined(OS_MACOSX) void DestroyCommandBufferByViewId(int32 render_view_id); #endif diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index c2ef865..d9732fc 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc @@ -4,19 +4,20 @@ #include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/child_thread.h" #include "content/common/gpu/gpu_channel.h" #include "content/common/gpu/gpu_messages.h" -GpuChannelManager::GpuChannelManager(IPC::Message::Sender* browser_channel, +GpuChannelManager::GpuChannelManager(ChildThread* gpu_child_thread, GpuWatchdog* watchdog, base::MessageLoopProxy* io_message_loop, base::WaitableEvent* shutdown_event) : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), io_message_loop_(io_message_loop), shutdown_event_(shutdown_event), - browser_channel_(browser_channel), + gpu_child_thread_(gpu_child_thread), watchdog_(watchdog) { - DCHECK(browser_channel); + DCHECK(gpu_child_thread); DCHECK(io_message_loop); DCHECK(shutdown_event); } @@ -29,6 +30,20 @@ void GpuChannelManager::RemoveChannel(int renderer_id) { gpu_channels_.erase(renderer_id); } +int GpuChannelManager::GenerateRouteID() { + static int last_id = 0; + return ++last_id; +} + +void GpuChannelManager::AddRoute(int32 routing_id, + IPC::Channel::Listener* listener) { + gpu_child_thread_->AddRoute(routing_id, listener); +} + +void GpuChannelManager::RemoveRoute(int32 routing_id) { + gpu_child_thread_->RemoveRoute(routing_id); +} + bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { bool msg_is_ok = true; bool handled = true; @@ -41,17 +56,9 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { #if defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN) IPC_MESSAGE_HANDLER(GpuMsg_ResizeViewACK, OnResizeViewACK); #endif -#if defined(TOUCH_UI) - IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceSetIOSurfaceACK, - OnAcceleratedSurfaceSetIOSurfaceACK) - IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceReleaseACK, - OnAcceleratedSurfaceReleaseACK) -#endif -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, OnAcceleratedSurfaceBuffersSwappedACK) -#endif -#if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(GpuMsg_DestroyCommandBuffer, OnDestroyCommandBuffer) #endif @@ -61,7 +68,7 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { } bool GpuChannelManager::Send(IPC::Message* msg) { - return browser_channel_->Send(msg); + return gpu_child_thread_->Send(msg); } void GpuChannelManager::OnEstablishChannel(int renderer_id) { @@ -138,27 +145,7 @@ void GpuChannelManager::OnResizeViewACK(int32 renderer_id, channel->ViewResized(command_buffer_route_id); } -#if defined(TOUCH_UI) -void GpuChannelManager::OnAcceleratedSurfaceSetIOSurfaceACK( - int renderer_id, int32 route_id, uint64 surface_id) { - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter == gpu_channels_.end()) - return; - scoped_refptr<GpuChannel> channel = iter->second; - channel->AcceleratedSurfaceIOSurfaceSet(route_id, surface_id); -} - -void GpuChannelManager::OnAcceleratedSurfaceReleaseACK( - int renderer_id, int32 route_id, uint64 surface_id) { - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter == gpu_channels_.end()) - return; - scoped_refptr<GpuChannel> channel = iter->second; - channel->AcceleratedSurfaceReleased(route_id, surface_id); -} -#endif - -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) void GpuChannelManager::OnAcceleratedSurfaceBuffersSwappedACK( int renderer_id, int32 route_id, uint64 swap_buffers_count) { GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); @@ -167,9 +154,7 @@ void GpuChannelManager::OnAcceleratedSurfaceBuffersSwappedACK( scoped_refptr<GpuChannel> channel = iter->second; channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count); } -#endif -#if defined(OS_MACOSX) void GpuChannelManager::OnDestroyCommandBuffer( int renderer_id, int32 renderer_view_id) { GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index 683c9cd..dd176aa 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h @@ -22,6 +22,7 @@ namespace IPC { struct ChannelHandle; } +class ChildThread; class GpuChannel; class GpuWatchdog; struct GPUCreateCommandBufferConfig; @@ -39,7 +40,7 @@ struct GPUCreateCommandBufferConfig; class GpuChannelManager : public IPC::Channel::Listener, public IPC::Message::Sender { public: - GpuChannelManager(IPC::Message::Sender* browser_channel, + GpuChannelManager(ChildThread* gpu_child_thread, GpuWatchdog* watchdog, base::MessageLoopProxy* io_message_loop, base::WaitableEvent* shutdown_event); @@ -58,6 +59,10 @@ class GpuChannelManager : public IPC::Channel::Listener, ScopedRunnableMethodFactory<GpuChannelManager> method_factory_; + int GenerateRouteID(); + void AddRoute(int32 routing_id, IPC::Channel::Listener* listener); + void RemoveRoute(int32 routing_id); + private: // Message handlers. void OnEstablishChannel(int renderer_id); @@ -71,19 +76,9 @@ class GpuChannelManager : public IPC::Channel::Listener, const GPUCreateCommandBufferConfig& init_params); void OnResizeViewACK(int32 renderer_id, int32 command_buffer_route_id); -#if defined(TOUCH_UI) - void OnAcceleratedSurfaceSetIOSurfaceACK( - int renderer_id, int32 route_id, uint64 surface_id); - void OnAcceleratedSurfaceReleaseACK( - int renderer_id, int32 route_id, uint64 surface_id); -#endif - -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) void OnAcceleratedSurfaceBuffersSwappedACK( int renderer_id, int32 route_id, uint64 swap_buffers_count); -#endif - -#if defined(OS_MACOSX) void OnDestroyCommandBuffer(int renderer_id, int32 renderer_view_id); #endif @@ -92,10 +87,8 @@ class GpuChannelManager : public IPC::Channel::Listener, scoped_refptr<base::MessageLoopProxy> io_message_loop_; base::WaitableEvent* shutdown_event_; - // Either an IPC channel to the browser or, if the GpuChannelManager is - // running in the browser process, a Sender implementation that will post - // IPC messages to the UI thread. - IPC::Message::Sender* browser_channel_; + // Used to send and receive IPC messages from the browser process. + ChildThread* gpu_child_thread_; // These objects manage channels to individual renderer processes there is // one channel for each renderer process that has connected to this GPU diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 3890e81..b86750a 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -22,6 +22,8 @@ #if defined(OS_WIN) #include "base/win/wrapped_window_proc.h" +#elif defined(TOUCH_UI) +#include "content/common/gpu/image_transport_surface_linux.h" #endif using gpu::Buffer; @@ -115,14 +117,19 @@ bool GpuCommandBufferStub::IsScheduled() { return !scheduler_.get() || scheduler_->IsScheduled(); } +void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) { + scheduler_.reset(); + command_buffer_.reset(); + GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, false); + Send(reply_message); +} + void GpuCommandBufferStub::OnInitialize( base::SharedMemoryHandle ring_buffer, int32 size, IPC::Message* reply_message) { DCHECK(!command_buffer_.get()); - bool result = false; - command_buffer_.reset(new gpu::CommandBufferService); #if defined(OS_WIN) @@ -142,6 +149,41 @@ void GpuCommandBufferStub::OnInitialize( scheduler_.reset(gpu::GpuScheduler::Create(command_buffer_.get(), channel_, NULL)); +#if defined(TOUCH_UI) + if (software_) { + OnInitializeFailed(reply_message); + return; + } + + scoped_refptr<gfx::GLSurface> surface; + if (handle_) + surface = ImageTransportSurface::CreateSurface(this); + else + surface = gfx::GLSurface::CreateOffscreenGLSurface(software_, + gfx::Size(1, 1)); + if (!surface.get()) { + LOG(ERROR) << "GpuCommandBufferStub: failed to create surface."; + OnInitializeFailed(reply_message); + return; + } + + scoped_refptr<gfx::GLContext> context( + gfx::GLContext::CreateGLContext(channel_->share_group(), + surface.get())); + if (!context.get()) { + LOG(ERROR) << "GpuCommandBufferStub: failed to create context."; + OnInitializeFailed(reply_message); + return; + } + + if (scheduler_->InitializeCommon( + surface, + context, + initial_size_, + disallowed_extensions_, + allowed_extensions_.c_str(), + requested_attribs_)) { +#else if (scheduler_->Initialize( handle_, initial_size_, @@ -150,6 +192,7 @@ void GpuCommandBufferStub::OnInitialize( allowed_extensions_.c_str(), requested_attribs_, channel_->share_group())) { +#endif command_buffer_->SetPutOffsetChangeCallback( NewCallback(scheduler_.get(), &gpu::GpuScheduler::PutChanged)); @@ -165,7 +208,7 @@ void GpuCommandBufferStub::OnInitialize( scheduler_->SetCommandProcessedCallback( NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed)); -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) if (handle_) { // This context conceptually puts its output directly on the // screen, rendered by the accelerated plugin layer in @@ -175,12 +218,19 @@ void GpuCommandBufferStub::OnInitialize( NewCallback(this, &GpuCommandBufferStub::SwapBuffersCallback)); } -#endif // defined(OS_MACOSX) || defined(TOUCH_UI) +#endif // defined(OS_MACOSX) // Set up a pathway for resizing the output window or framebuffer at the // right time relative to other GL commands. +#if defined(TOUCH_UI) + if (handle_ == gfx::kNullPluginWindow) { + scheduler_->SetResizeCallback( + NewCallback(this, &GpuCommandBufferStub::ResizeCallback)); + } +#else scheduler_->SetResizeCallback( NewCallback(this, &GpuCommandBufferStub::ResizeCallback)); +#endif if (parent_stub_for_initialization_) { scheduler_->SetParent(parent_stub_for_initialization_->scheduler_.get(), @@ -189,14 +239,13 @@ void GpuCommandBufferStub::OnInitialize( parent_texture_for_initialization_ = 0; } - result = true; } else { - scheduler_.reset(); - command_buffer_.reset(); + OnInitializeFailed(reply_message); + return; } } - GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, result); + GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, true); Send(reply_message); } @@ -438,34 +487,7 @@ void GpuCommandBufferStub::SwapBuffersCallback() { scheduler_->SetScheduled(false); } -#endif // defined(OS_MACOSX) -#if defined(TOUCH_UI) -void GpuCommandBufferStub::SwapBuffersCallback() { - TRACE_EVENT0("gpu", "GpuCommandBufferStub::SwapBuffersCallback"); - GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.surface_id = scheduler_->GetFrontSurfaceId(); - params.route_id = route_id(); - params.swap_buffers_count = scheduler_->swap_buffers_count(); - gpu_channel_manager->Send( - new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); - - scheduler_->SetScheduled(false); -} - -void GpuCommandBufferStub::AcceleratedSurfaceIOSurfaceSet(uint64 surface_id) { - scheduler_->SetScheduled(true); -} - -void GpuCommandBufferStub::AcceleratedSurfaceReleased(uint64 surface_id) { - scheduler_->ReleaseSurface(surface_id); -} -#endif // defined(TOUCH_UI) - -#if defined(OS_MACOSX) || defined(TOUCH_UI) void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped( uint64 swap_buffers_count) { TRACE_EVENT1("gpu", @@ -485,7 +507,7 @@ void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped( scheduler_->SetScheduled(true); } } -#endif // defined(OS_MACOSX) || defined(TOUCH_UI) +#endif // defined(OS_MACOSX) void GpuCommandBufferStub::AddSetTokenCallback( const base::Callback<void(int32)>& callback) { @@ -511,31 +533,6 @@ void GpuCommandBufferStub::ResizeCallback(gfx::Size size) { size)); scheduler_->SetScheduled(false); -#elif defined(TOUCH_UI) - if (scheduler_->GetBackSurfaceId()) { - GpuHostMsg_AcceleratedSurfaceRelease_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.identifier = scheduler_->GetBackSurfaceId(); - params.route_id = route_id(); - - GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); - gpu_channel_manager->Send( - new GpuHostMsg_AcceleratedSurfaceRelease(params)); - } - scheduler_->CreateBackSurface(size); - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.width = size.width(); - params.height = size.height(); - params.identifier = scheduler_->GetBackSurfaceId(); - params.route_id = route_id(); - - GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); - gpu_channel_manager->Send( - new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); - scheduler_->SetScheduled(false); #endif } } diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h index b97234d4..26dd64b 100644 --- a/content/common/gpu/gpu_command_buffer_stub.h +++ b/content/common/gpu/gpu_command_buffer_stub.h @@ -58,6 +58,9 @@ class GpuCommandBufferStub // Get the GLContext associated with this object. gpu::GpuScheduler* scheduler() const { return scheduler_.get(); } + // Get the GpuChannel associated with this object. + GpuChannel* channel() const { return channel_; } + // Identifies the renderer process. int32 renderer_id() const { return renderer_id_; } @@ -81,15 +84,10 @@ class GpuCommandBufferStub void ViewResized(); -#if defined(TOUCH_UI) - void AcceleratedSurfaceIOSurfaceSet(uint64 surface_id); - void AcceleratedSurfaceReleased(uint64 surface_id); -#endif // defined(TOUCH_UI) - -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) // Called only by the GpuChannel. void AcceleratedSurfaceBuffersSwapped(uint64 swap_buffers_count); -#endif // defined(OS_MACOSX) || defined(TOUCH_UI) +#endif // defined(OS_MACOSX) // Register a callback to be Run() whenever the underlying scheduler receives // a set_token() call. The callback will be Run() with the just-set token as @@ -97,6 +95,9 @@ class GpuCommandBufferStub void AddSetTokenCallback(const base::Callback<void(int32)>& callback); private: + // Cleans up and sends reply if OnInitialize failed. + void OnInitializeFailed(IPC::Message* reply_message); + // Message handlers: void OnInitialize(base::SharedMemoryHandle ring_buffer, int32 size, @@ -131,11 +132,8 @@ class GpuCommandBufferStub #if defined(OS_MACOSX) void OnSetWindowSize(const gfx::Size& size); -#endif // defined(OS_MACOSX) - -#if defined(OS_MACOSX) || defined(TOUCH_UI) void SwapBuffersCallback(); -#endif // defined(TOUCH_UI) +#endif // defined(OS_MACOSX) void ResizeCallback(gfx::Size size); void ReportState(); diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index b4fc5ff..a852b45 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -159,19 +159,15 @@ IPC_MESSAGE_CONTROL2(GpuMsg_ResizeViewACK, #if defined(TOUCH_UI) // Tells the GPU process that it's safe to start rendering to the surface. -IPC_MESSAGE_CONTROL3(GpuMsg_AcceleratedSurfaceSetIOSurfaceACK, - int /* renderer_id */, - int32 /* route_id */, - uint64 /* surface_id */) +IPC_MESSAGE_ROUTED1(AcceleratedSurfaceMsg_SetSurfaceACK, + uint64 /* surface_id */) -// Tells the GPU process the surface has been released. -IPC_MESSAGE_CONTROL3(GpuMsg_AcceleratedSurfaceReleaseACK, - int /* renderer_id */, - int32 /* route_id */, - uint64 /* surface_id */) +// Tells the GPU process that the browser process handled the swap +// buffers request with the given number. +IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_BuffersSwappedACK) #endif -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) // Tells the GPU process that the browser process handled the swap // buffers request with the given number. Note that it is possible // for the browser process to coalesce frames; it is not guaranteed @@ -181,9 +177,7 @@ IPC_MESSAGE_CONTROL3(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, int /* renderer_id */, int32 /* route_id */, uint64 /* swap_buffers_count */) -#endif -#if defined(OS_MACOSX) // Requests the GPU process to destroy the command buffer and remove the // associated route. Further messages to this command buffer will result in a // channel error. diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc new file mode 100644 index 0000000..93a067a --- /dev/null +++ b/content/common/gpu/image_transport_surface_linux.cc @@ -0,0 +1,448 @@ +// 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. + +#if defined(ENABLE_GPU) + +#include "content/common/gpu/image_transport_surface_linux.h" + +// This conflicts with the defines in Xlib.h and must come first. +#include "content/common/gpu/gpu_messages.h" + +#include <map> +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> + +#include "base/callback.h" +#include "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/gpu_command_buffer_stub.h" +#include "gpu/command_buffer/service/gpu_scheduler.h" +#include "third_party/angle/include/EGL/egl.h" +#include "third_party/angle/include/EGL/eglext.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" +#include "ui/gfx/gl/gl_surface_egl.h" +#include "ui/gfx/gl/gl_surface_glx.h" +#include "ui/gfx/surface/accelerated_surface_linux.h" + +namespace { + +// We are backed by an Pbuffer offscreen surface for the purposes of creating a +// context, but use FBOs to render to X Pixmap backed EGLImages. +class EGLImageTransportSurface : public ImageTransportSurface, + public gfx::PbufferGLSurfaceEGL { + public: + explicit EGLImageTransportSurface(GpuCommandBufferStub* stub); + + // GLSurface implementation + virtual bool Initialize() OVERRIDE; + virtual void Destroy() OVERRIDE; + virtual bool IsOffscreen() OVERRIDE; + virtual bool SwapBuffers() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual void OnMakeCurrent() OVERRIDE; + virtual unsigned int GetBackingFrameBufferObject() OVERRIDE; + + protected: + // ImageTransportSurface implementation + virtual void OnSetSurfaceACK(uint64 surface_id) OVERRIDE; + virtual void OnBuffersSwappedACK() OVERRIDE; + virtual void Resize(gfx::Size size) OVERRIDE; + + private: + virtual ~EGLImageTransportSurface() OVERRIDE; + void ReleaseSurface(scoped_refptr<AcceleratedSurface>& surface); + + uint32 fbo_id_; + uint32 depth_id_; + gfx::Size depth_buffer_size_; + + scoped_refptr<AcceleratedSurface> back_surface_; + scoped_refptr<AcceleratedSurface> front_surface_; + + DISALLOW_COPY_AND_ASSIGN(EGLImageTransportSurface); +}; + +// We are backed by an Pbuffer offscreen surface for the purposes of creating a +// context, but use FBOs to render to X Pixmap backed EGLImages. +class GLXImageTransportSurface : public ImageTransportSurface, + public gfx::NativeViewGLSurfaceGLX { + public: + explicit GLXImageTransportSurface(GpuCommandBufferStub* stub); + + // gfx::GLSurface implementation: + virtual bool Initialize() OVERRIDE; + virtual void Destroy() OVERRIDE; + virtual bool SwapBuffers() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + + protected: + // ImageTransportSurface implementation: + void OnSetSurfaceACK(uint64 surface_id) OVERRIDE; + void OnBuffersSwappedACK() OVERRIDE; + void Resize(gfx::Size size) OVERRIDE; + + private: + virtual ~GLXImageTransportSurface(); + + // Tell the browser to release the surface. + void ReleaseSurface(); + + XID dummy_parent_; + gfx::Size size_; + + // Whether or not the image has been bound on the browser side. + bool bound_; + + DISALLOW_COPY_AND_ASSIGN(GLXImageTransportSurface); +}; + +EGLImageTransportSurface::EGLImageTransportSurface(GpuCommandBufferStub* stub) : + ImageTransportSurface(stub), + gfx::PbufferGLSurfaceEGL(false, gfx::Size(1,1)), + fbo_id_(0) { +} + +EGLImageTransportSurface::~EGLImageTransportSurface() { +} + +bool EGLImageTransportSurface::Initialize() { + if (!ImageTransportSurface::Initialize()) + return false; + return PbufferGLSurfaceEGL::Initialize(); +} + +void EGLImageTransportSurface::Destroy() { + if (depth_id_) { + glDeleteRenderbuffersEXT(1, &depth_id_); + depth_id_ = 0; + } + + if (back_surface_.get()) + ReleaseSurface(back_surface_); + if (front_surface_.get()) + ReleaseSurface(front_surface_); + + ImageTransportSurface::Destroy(); + PbufferGLSurfaceEGL::Destroy(); +} + +bool EGLImageTransportSurface::IsOffscreen() { + return false; +} + +void EGLImageTransportSurface::OnMakeCurrent() { + if (fbo_id_) + return; + + glGenFramebuffersEXT(1, &fbo_id_); + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); + Resize(gfx::Size(1,1)); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR) << "Framebuffer incomplete."; + } +} + +unsigned int EGLImageTransportSurface::GetBackingFrameBufferObject() { + return fbo_id_; +} + +void EGLImageTransportSurface::ReleaseSurface( + scoped_refptr<AcceleratedSurface>& surface) { + if (surface.get()) { + GpuHostMsg_AcceleratedSurfaceRelease_Params params; + params.renderer_id = stub()->renderer_id(); + params.render_view_id = stub()->render_view_id(); + params.identifier = back_surface_->pixmap(); + params.route_id = route_id(); + Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); + surface = NULL; + } +} + +void EGLImageTransportSurface::Resize(gfx::Size size) { + if (back_surface_.get()) + ReleaseSurface(back_surface_); + + if (depth_id_ && depth_buffer_size_ != size) { + glDeleteRenderbuffersEXT(1, &depth_id_); + depth_id_ = 0; + } + + if (!depth_id_) { + glGenRenderbuffersEXT(1, &depth_id_); + glBindRenderbufferEXT(GL_RENDERBUFFER, depth_id_); + glRenderbufferStorageEXT(GL_RENDERBUFFER, + GL_DEPTH24_STENCIL8, + size.width(), + size.height()); + glBindRenderbufferEXT(GL_RENDERBUFFER, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + depth_id_); + depth_buffer_size_ = size; + } + + back_surface_ = new AcceleratedSurface(size); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + back_surface_->texture(), + 0); + glFlush(); + + GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; + params.renderer_id = stub()->renderer_id(); + params.render_view_id = stub()->render_view_id(); + params.width = size.width(); + params.height = size.height(); + params.identifier = back_surface_->pixmap(); + params.route_id = route_id(); + Send(new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); + + scheduler()->SetScheduled(false); +} + +bool EGLImageTransportSurface::SwapBuffers() { + front_surface_.swap(back_surface_); + DCHECK_NE(front_surface_.get(), static_cast<AcceleratedSurface*>(NULL)); + glFlush(); + + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.renderer_id = stub()->renderer_id(); + params.render_view_id = stub()->render_view_id(); + params.surface_id = front_surface_->pixmap(); + params.route_id = route_id(); + Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); + + gfx::Size expected_size = front_surface_->size(); + if (!back_surface_.get() || back_surface_->size() != expected_size) { + Resize(expected_size); + } else { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + back_surface_->texture(), + 0); + } + scheduler()->SetScheduled(false); + return true; +} + +gfx::Size EGLImageTransportSurface::GetSize() { + return back_surface_->size(); +} + +void EGLImageTransportSurface::OnSetSurfaceACK( + uint64 surface_id) { + DCHECK_EQ(back_surface_->pixmap(), surface_id); + scheduler()->SetScheduled(true); +} + +void EGLImageTransportSurface::OnBuffersSwappedACK() { + scheduler()->SetScheduled(true); +} + +GLXImageTransportSurface::GLXImageTransportSurface(GpuCommandBufferStub* stub) : + ImageTransportSurface(stub), + gfx::NativeViewGLSurfaceGLX(), + dummy_parent_(0), + size_(1, 1), + bound_(false) { +} + +GLXImageTransportSurface::~GLXImageTransportSurface() { +} + +bool GLXImageTransportSurface::Initialize() { + // Create a dummy window to host the real window. + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + XSetWindowAttributes swa; + swa.event_mask = StructureNotifyMask; + swa.override_redirect = True; + dummy_parent_ = XCreateWindow( + dpy, + RootWindow(dpy, DefaultScreen(dpy)), // parent + -100, -100, 1, 1, + 0, // border width + CopyFromParent, // depth + InputOutput, + CopyFromParent, // visual + CWEventMask | CWOverrideRedirect, &swa); + XMapWindow(dpy, dummy_parent_); + + swa.event_mask = StructureNotifyMask; + swa.override_redirect = false; + window_ = XCreateWindow(dpy, + dummy_parent_, + 0, 0, size_.width(), size_.height(), + 0, // border width + CopyFromParent, // depth + InputOutput, + CopyFromParent, // visual + CWEventMask, &swa); + XMapWindow(dpy, window_); + while(1) { + XEvent event; + XNextEvent(dpy, &event); + if (event.type == MapNotify && event.xmap.window == window_) + break; + } + // Manual setting must be used to avoid unnecessary rendering by server. + XCompositeRedirectWindow(dpy, window_, CompositeRedirectManual); + Resize(size_); + + if (!ImageTransportSurface::Initialize()) + return false; + return gfx::NativeViewGLSurfaceGLX::Initialize(); +} + +void GLXImageTransportSurface::Destroy() { + if (bound_) + ReleaseSurface(); + + if (window_) { + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + XDestroyWindow(dpy, window_); + XDestroyWindow(dpy, dummy_parent_); + } + + ImageTransportSurface::Destroy(); + gfx::NativeViewGLSurfaceGLX::Destroy(); +} + +void GLXImageTransportSurface::ReleaseSurface() { + DCHECK(bound_); + GpuHostMsg_AcceleratedSurfaceRelease_Params params; + params.renderer_id = stub()->renderer_id(); + params.render_view_id = stub()->render_view_id(); + params.identifier = window_; + params.route_id = route_id(); + Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); +} + +void GLXImageTransportSurface::Resize(gfx::Size size) { + size_ = size; + if (bound_) { + ReleaseSurface(); + bound_ = false; + } + + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + XResizeWindow(dpy, window_, size_.width(), size_.height()); + XFlush(dpy); + + GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; + params.renderer_id = stub()->renderer_id(); + params.render_view_id = stub()->render_view_id(); + params.width = size_.width(); + params.height = size_.height(); + params.identifier = window_; + params.route_id = route_id(); + Send(new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); + + scheduler()->SetScheduled(false); +} + +bool GLXImageTransportSurface::SwapBuffers() { + gfx::NativeViewGLSurfaceGLX::SwapBuffers(); + glFlush(); + + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.renderer_id = stub()->renderer_id(); + params.render_view_id = stub()->render_view_id(); + params.surface_id = window_; + params.route_id = route_id(); + Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); + + return true; +} + +gfx::Size GLXImageTransportSurface::GetSize() { + return size_; +} + +void GLXImageTransportSurface::OnSetSurfaceACK( + uint64 surface_id) { + DCHECK(!bound_); + bound_ = true; + scheduler()->SetScheduled(true); +} + +void GLXImageTransportSurface::OnBuffersSwappedACK() { +} + +} // namespace + +ImageTransportSurface::ImageTransportSurface(GpuCommandBufferStub* stub) : + stub_(stub) { + GpuChannelManager* gpu_channel_manager + = stub_->channel()->gpu_channel_manager(); + route_id_ = gpu_channel_manager->GenerateRouteID(); + gpu_channel_manager->AddRoute(route_id_, this); +} + +ImageTransportSurface::~ImageTransportSurface() { + GpuChannelManager* gpu_channel_manager + = stub_->channel()->gpu_channel_manager(); + gpu_channel_manager->RemoveRoute(route_id_); +} + +bool ImageTransportSurface::Initialize() { + scheduler()->SetResizeCallback( + NewCallback(this, &ImageTransportSurface::Resize)); + return true; +} + +void ImageTransportSurface::Destroy() { + scheduler()->SetResizeCallback(NULL); +} + +bool ImageTransportSurface::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ImageTransportSurface, message) + IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_SetSurfaceACK, + OnSetSurfaceACK) + IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BuffersSwappedACK, + OnBuffersSwappedACK) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +bool ImageTransportSurface::Send(IPC::Message* message) { + GpuChannelManager* gpu_channel_manager = + stub_->channel()->gpu_channel_manager(); + return gpu_channel_manager->Send(message); +} + +gpu::GpuScheduler* ImageTransportSurface::scheduler() { + return stub_->scheduler(); +} + +// static +scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( + GpuCommandBufferStub* stub) { + scoped_refptr<gfx::GLSurface> surface; + switch (gfx::GetGLImplementation()) { + case gfx::kGLImplementationDesktopGL: + surface = new GLXImageTransportSurface(stub); + break; + case gfx::kGLImplementationEGLGLES2: + surface = new EGLImageTransportSurface(stub); + break; + default: + NOTREACHED(); + return NULL; + } + if (surface->Initialize()) + return surface; + else + return NULL; +} + +#endif // defined(USE_GPU) diff --git a/content/common/gpu/image_transport_surface_linux.h b/content/common/gpu/image_transport_surface_linux.h new file mode 100644 index 0000000..6ad1d0b --- /dev/null +++ b/content/common/gpu/image_transport_surface_linux.h @@ -0,0 +1,67 @@ +// 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 CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_LINUX_H_ +#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_LINUX_H_ +#pragma once + +#if defined(ENABLE_GPU) + +#include "base/memory/ref_counted.h" +#include "ipc/ipc_channel.h" +#include "ipc/ipc_message.h" +#include "ui/gfx/size.h" + +class GpuCommandBufferStub; + +namespace gfx { +class GLSurface; +} + +namespace gpu { +class GpuScheduler; +} + +class ImageTransportSurface : public IPC::Channel::Listener, + public IPC::Message::Sender { + public: + // Creates the appropriate surface depending on the GL implementation + static scoped_refptr<gfx::GLSurface> + CreateSurface(GpuCommandBufferStub* stub); + + bool Initialize(); + void Destroy(); + + // IPC::Channel::Listener implementation: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // IPC::Message::Sender implementation: + virtual bool Send(IPC::Message* msg) OVERRIDE; + + protected: + explicit ImageTransportSurface(GpuCommandBufferStub* stub); + ~ImageTransportSurface(); + + // IPC::Message handlers + virtual void OnSetSurfaceACK(uint64 surface_id) = 0; + virtual void OnBuffersSwappedACK() = 0; + + // Resize the backbuffer + virtual void Resize(gfx::Size size) = 0; + + GpuCommandBufferStub* stub() { return stub_; } + gpu::GpuScheduler* scheduler(); + int32 route_id() { return route_id_; } + + private: + // Weak pointer. The stub outlives this surface. + GpuCommandBufferStub* stub_; + int32 route_id_; + + DISALLOW_COPY_AND_ASSIGN(ImageTransportSurface); +}; + +#endif // defined(ENABLE_GPU) + +#endif // CONTENT_COMMON_GPU_EGL_IMAGE_TRANSPORT_SURFACE_LINUX_H_ diff --git a/content/content_common.gypi b/content/content_common.gypi index 42cfd32..9747f69 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -280,6 +280,20 @@ 'common/native_web_keyboard_event_views.cc', ], }], + ['touchui==1', { + 'sources': [ + 'common/gpu/image_transport_surface_linux.h', + 'common/gpu/image_transport_surface_linux.cc', + ], + 'include_dirs': [ + '<(DEPTH)/third_party/angle/include', + ], + 'link_settings': { + 'libraries': [ + '-lXcomposite', + ], + }, + }], ['enable_gpu==1', { 'dependencies': [ '../gpu/gpu.gyp:command_buffer_service', diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 812218b..63f73a9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -2528,7 +2528,7 @@ void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM( } void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) { -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(TOUCH_UI) // Make sure that we are done drawing to the back buffer before resizing. glFinish(); #endif @@ -2740,7 +2740,7 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { } info->MarkAsValid(); } else { - service_id = 0; + service_id = surface_->GetBackingFrameBufferObject(); } if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) { diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index fbdb16b..8809b05 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc @@ -68,7 +68,7 @@ bool GpuScheduler::InitializeCommon( if (!context->MakeCurrent(surface)) return false; -#if !defined(OS_MACOSX) +#if !defined(OS_MACOSX) && !defined(TOUCH_UI) // Set up swap interval for onscreen contexts. if (!surface->IsOffscreen()) { if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) @@ -129,7 +129,7 @@ bool GpuScheduler::SetParent(GpuScheduler* parent_scheduler, return decoder_->SetParent(NULL, 0); } -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) namespace { const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1; } @@ -156,11 +156,7 @@ void GpuScheduler::PutChanged() { #if defined(OS_MACOSX) bool do_rate_limiting = surface_.get() != NULL; -#elif defined(TOUCH_UI) - bool do_rate_limiting = back_surface_.get() != NULL; -#endif -#if defined(OS_MACOSX) || defined(TOUCH_UI) // Don't swamp the browser process with SwapBuffers calls it can't handle. DCHECK(!do_rate_limiting || swap_buffers_count_ - acknowledged_swap_buffers_count_ == 0); @@ -239,10 +235,7 @@ void GpuScheduler::ResizeOffscreenFrameBuffer(const gfx::Size& size) { } void GpuScheduler::SetResizeCallback(Callback1<gfx::Size>::Type* callback) { - wrapped_resize_callback_.reset(callback); - decoder_->SetResizeCallback( - NewCallback(this, - &GpuScheduler::WillResize)); + decoder_->SetResizeCallback(callback); } void GpuScheduler::SetSwapBuffersCallback( @@ -271,17 +264,11 @@ GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, decoder_(decoder), parser_(parser), unscheduled_count_(0), -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) swap_buffers_count_(0), acknowledged_swap_buffers_count_(0), #endif method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { } -void GpuScheduler::WillResize(gfx::Size size) { - if (wrapped_resize_callback_.get()) { - wrapped_resize_callback_->Run(size); - } -} - } // namespace gpu diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index 4ebbab9..4ff0f3d 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -24,8 +24,6 @@ #if defined(OS_MACOSX) #include "ui/gfx/surface/accelerated_surface_mac.h" -#elif defined(TOUCH_UI) -#include "ui/gfx/surface/accelerated_surface_linux.h" #endif namespace gfx { @@ -55,7 +53,8 @@ class GpuScheduler : public CommandBufferEngine { virtual ~GpuScheduler(); - // Perform platform specific and common initialization. + // Platform specific code to create GLContexts and GLSurfaces that are + // handed off to the next function. bool Initialize(gfx::PluginWindowHandle hwnd, const gfx::Size& size, bool software, @@ -64,6 +63,15 @@ class GpuScheduler : public CommandBufferEngine { const std::vector<int32>& attribs, gfx::GLShareGroup* share_group); + // Takes ownership of GLSurface and GLContext. + bool InitializeCommon( + const scoped_refptr<gfx::GLSurface>& surface, + const scoped_refptr<gfx::GLContext>& context, + const gfx::Size& size, + const gles2::DisallowedExtensions& disallowed_extensions, + const char* allowed_extensions, + const std::vector<int32>& attribs); + void Destroy(); void DestroyCommon(); @@ -93,7 +101,7 @@ class GpuScheduler : public CommandBufferEngine { // Asynchronously resizes an offscreen frame buffer. void ResizeOffscreenFrameBuffer(const gfx::Size& size); -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) // To prevent the GPU process from overloading the browser process, // we need to track the number of swap buffers calls issued and // acknowledged per on-screen context, and keep the GPU from getting @@ -104,9 +112,7 @@ class GpuScheduler : public CommandBufferEngine { uint64 acknowledged_swap_buffers_count() const; void set_acknowledged_swap_buffers_count( uint64 acknowledged_swap_buffers_count); -#endif -#if defined(OS_MACOSX) // Needed only on Mac OS X, which does not render into an on-screen // window and therefore requires the backing store to be resized // manually. Returns an opaque identifier for the new backing store. @@ -126,16 +132,6 @@ class GpuScheduler : public CommandBufferEngine { void DidDestroySurface(); #endif -#if defined(TOUCH_UI) - virtual void CreateBackSurface(const gfx::Size& size); - // Should not be back_surface_ or front_surface_. - virtual void ReleaseSurface(uint64 surface_id); - - // Returns the id of the surface (or 0 if no such surface has been created). - virtual uint64 GetBackSurfaceId(); - virtual uint64 GetFrontSurfaceId(); -#endif - // Sets a callback that is called when a glResizeCHROMIUM command // is processed. void SetResizeCallback(Callback1<gfx::Size>::Type* callback); @@ -155,17 +151,6 @@ class GpuScheduler : public CommandBufferEngine { // Get the GLES2Decoder associated with this scheduler. gles2::GLES2Decoder* decoder() const { return decoder_.get(); } - protected: - // Perform common initialization. Takes ownership of GLSurface and GLContext. - bool InitializeCommon( - const scoped_refptr<gfx::GLSurface>& surface, - const scoped_refptr<gfx::GLContext>& context, - const gfx::Size& size, - const gles2::DisallowedExtensions& disallowed_extensions, - const char* allowed_extensions, - const std::vector<int32>& attribs); - - private: // If a group is not passed in one will be created. GpuScheduler(CommandBuffer* command_buffer, @@ -173,10 +158,6 @@ class GpuScheduler : public CommandBufferEngine { CommandParser* parser); // Called via a callback just before we are supposed to call the - // user's resize callback. - void WillResize(gfx::Size size); - - // Called via a callback just before we are supposed to call the // user's swap buffers callback. void WillSwapBuffers(); @@ -193,22 +174,13 @@ class GpuScheduler : public CommandBufferEngine { scoped_ptr<Callback0::Type> scheduled_callback_; -#if defined(OS_MACOSX) || defined(TOUCH_UI) +#if defined(OS_MACOSX) uint64 swap_buffers_count_; uint64 acknowledged_swap_buffers_count_; -#endif - -#if defined(OS_MACOSX) scoped_ptr<AcceleratedSurface> surface_; -#elif defined(TOUCH_UI) - std::map<uint64, scoped_refptr<AcceleratedSurface> > - surfaces_; - scoped_refptr<AcceleratedSurface> back_surface_; - scoped_refptr<AcceleratedSurface> front_surface_; #endif ScopedRunnableMethodFactory<GpuScheduler> method_factory_; - scoped_ptr<Callback1<gfx::Size>::Type> wrapped_resize_callback_; scoped_ptr<Callback0::Type> wrapped_swap_buffers_callback_; scoped_ptr<Callback0::Type> command_processed_callback_; base::Callback<void(int32)> set_token_callback_; diff --git a/gpu/command_buffer/service/gpu_scheduler_linux.cc b/gpu/command_buffer/service/gpu_scheduler_linux.cc index fcbbd65..9312245 100644 --- a/gpu/command_buffer/service/gpu_scheduler_linux.cc +++ b/gpu/command_buffer/service/gpu_scheduler_linux.cc @@ -7,13 +7,6 @@ #include "ui/gfx/gl/gl_share_group.h" #include "ui/gfx/gl/gl_surface.h" -#if defined(TOUCH_UI) -#include "third_party/angle/include/EGL/egl.h" -#include "third_party/angle/include/EGL/eglext.h" -#include "ui/gfx/gl/gl_surface_egl.h" -#include "ui/gfx/gl/gl_bindings.h" -#endif - using ::base::SharedMemory; namespace gpu { @@ -26,18 +19,18 @@ bool GpuScheduler::Initialize( const char* allowed_extensions, const std::vector<int32>& attribs, gfx::GLShareGroup* share_group) { +#if defined(TOUCH_UI) + NOTIMPLEMENTED(); + return false; +#endif + // Create either a view or pbuffer based GLSurface. scoped_refptr<gfx::GLSurface> surface; -#if defined(TOUCH_UI) - surface = gfx::GLSurface::CreateOffscreenGLSurface(software, gfx::Size(1, 1)); -#else if (window) surface = gfx::GLSurface::CreateViewGLSurface(software, window); else surface = gfx::GLSurface::CreateOffscreenGLSurface(software, gfx::Size(1, 1)); -#endif - if (!surface.get()) { LOG(ERROR) << "GpuScheduler::Initialize failed.\n"; Destroy(); @@ -66,75 +59,9 @@ void GpuScheduler::Destroy() { } void GpuScheduler::WillSwapBuffers() { -#if defined(TOUCH_UI) - front_surface_.swap(back_surface_); - DCHECK_NE(front_surface_.get(), static_cast<AcceleratedSurface*>(NULL)); - - gfx::Size expected_size = front_surface_->size(); - if (!back_surface_.get() || back_surface_->size() != expected_size) { - wrapped_resize_callback_->Run(expected_size); - } else { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - back_surface_->texture(), - 0); - } - ++swap_buffers_count_; - glFlush(); -#endif if (wrapped_swap_buffers_callback_.get()) { wrapped_swap_buffers_callback_->Run(); } } -#if defined(TOUCH_UI) -uint64 GpuScheduler::GetBackSurfaceId() { - if (!back_surface_.get()) - return 0; - return back_surface_->pixmap(); -} - -uint64 GpuScheduler::GetFrontSurfaceId() { - if (!front_surface_.get()) - return 0; - return front_surface_->pixmap(); -} - -uint64 GpuScheduler::swap_buffers_count() const { - return swap_buffers_count_; -} - -uint64 GpuScheduler::acknowledged_swap_buffers_count() const { - return acknowledged_swap_buffers_count_; -} - -void GpuScheduler::set_acknowledged_swap_buffers_count( - uint64 acknowledged_swap_buffers_count) { - acknowledged_swap_buffers_count_ = acknowledged_swap_buffers_count; -} - -void GpuScheduler::CreateBackSurface(const gfx::Size& size) { - decoder()->ResizeOffscreenFrameBuffer(size); - decoder()->UpdateOffscreenFrameBufferSize(); - - back_surface_ = new AcceleratedSurface(size); - surfaces_[back_surface_->pixmap()] = back_surface_; - - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - back_surface_->texture(), - 0); - glFlush(); -} - -void GpuScheduler::ReleaseSurface(uint64 surface_id) { - DCHECK_NE(surfaces_[surface_id].get(), back_surface_.get()); - DCHECK_NE(surfaces_[surface_id].get(), front_surface_.get()); - surfaces_.erase(surface_id); -} - -#endif - } // namespace gpu diff --git a/ui/gfx/gl/generate_bindings.py b/ui/gfx/gl/generate_bindings.py index 34baccd..a71e96e 100644 --- a/ui/gfx/gl/generate_bindings.py +++ b/ui/gfx/gl/generate_bindings.py @@ -377,6 +377,10 @@ GLX_FUNCTIONS = [ 'Display* dpy, int screen, int* attribList'], ['GLXContext', ['glXCreateContext'], 'Display* dpy, XVisualInfo* vis, GLXContext shareList, int direct'], +['void', ['glXBindTexImageEXT'], + 'Display* dpy, GLXDrawable drawable, int buffer, int* attribList'], +['void', ['glXReleaseTexImageEXT'], + 'Display* dpy, GLXDrawable drawable, int buffer'], ['void', ['glXDestroyContext'], 'Display* dpy, GLXContext ctx'], ['int', ['glXMakeCurrent'], 'Display* dpy, GLXDrawable drawable, GLXContext ctx'], diff --git a/ui/gfx/gl/gl_context_cgl.cc b/ui/gfx/gl/gl_context_cgl.cc index 1629cec..9ba5b53 100644 --- a/ui/gfx/gl/gl_context_cgl.cc +++ b/ui/gfx/gl/gl_context_cgl.cc @@ -64,6 +64,7 @@ bool GLContextCGL::MakeCurrent(GLSurface* surface) { return false; } + surface->OnMakeCurrent(); return true; } diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc index f18d59f..a61e52b 100644 --- a/ui/gfx/gl/gl_context_egl.cc +++ b/ui/gfx/gl/gl_context_egl.cc @@ -95,6 +95,7 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) { return false; } + surface->OnMakeCurrent(); return true; } diff --git a/ui/gfx/gl/gl_context_glx.cc b/ui/gfx/gl/gl_context_glx.cc index aa863cc..0921037 100644 --- a/ui/gfx/gl/gl_context_glx.cc +++ b/ui/gfx/gl/gl_context_glx.cc @@ -171,6 +171,7 @@ bool GLContextGLX::MakeCurrent(GLSurface* surface) { return false; } + surface->OnMakeCurrent(); return true; } diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc index 2b45836..a4396d4 100644 --- a/ui/gfx/gl/gl_context_osmesa.cc +++ b/ui/gfx/gl/gl_context_osmesa.cc @@ -67,6 +67,7 @@ bool GLContextOSMesa::MakeCurrent(GLSurface* surface) { // Row 0 is at the top. OSMesaPixelStore(OSMESA_Y_UP, 0); + surface->OnMakeCurrent(); return true; } diff --git a/ui/gfx/gl/gl_context_wgl.cc b/ui/gfx/gl/gl_context_wgl.cc index 8533be7..7d14b91 100644 --- a/ui/gfx/gl/gl_context_wgl.cc +++ b/ui/gfx/gl/gl_context_wgl.cc @@ -82,6 +82,7 @@ bool GLContextWGL::MakeCurrent(GLSurface* surface) { return false; } + surface->OnMakeCurrent(); return true; } diff --git a/ui/gfx/gl/gl_surface.cc b/ui/gfx/gl/gl_surface.cc index 3e4cb7e..6242f80 100644 --- a/ui/gfx/gl/gl_surface.cc +++ b/ui/gfx/gl/gl_surface.cc @@ -21,4 +21,7 @@ unsigned int GLSurface::GetBackingFrameBufferObject() { return 0; } +void GLSurface::OnMakeCurrent() { +} + } // namespace gfx diff --git a/ui/gfx/gl/gl_surface.h b/ui/gfx/gl/gl_surface.h index 7a89d5b..5bd9180 100644 --- a/ui/gfx/gl/gl_surface.h +++ b/ui/gfx/gl/gl_surface.h @@ -47,6 +47,9 @@ class GLSurface : public base::RefCounted<GLSurface> { static bool InitializeOneOff(); + // Called after a context is made current with this surface. + virtual void OnMakeCurrent(); + #if !defined(OS_MACOSX) // Create a GL surface that renders directly to a view. static scoped_refptr<GLSurface> CreateViewGLSurface( diff --git a/ui/gfx/gl/gl_surface_glx.cc b/ui/gfx/gl/gl_surface_glx.cc index b584080..30cf490 100644 --- a/ui/gfx/gl/gl_surface_glx.cc +++ b/ui/gfx/gl/gl_surface_glx.cc @@ -104,6 +104,11 @@ NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::PluginWindowHandle window) config_(NULL) { } +NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() + : window_(0), + config_(NULL) { +} + NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { Destroy(); } diff --git a/ui/gfx/gl/gl_surface_glx.h b/ui/gfx/gl/gl_surface_glx.h index 54a52e0..7d8872c 100644 --- a/ui/gfx/gl/gl_surface_glx.h +++ b/ui/gfx/gl/gl_surface_glx.h @@ -52,8 +52,12 @@ class NativeViewGLSurfaceGLX : public GLSurfaceGLX { virtual void* GetHandle(); virtual void* GetConfig(); - private: + protected: + NativeViewGLSurfaceGLX(); + gfx::PluginWindowHandle window_; + + private: void* config_; DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceGLX); }; |