diff options
author | wjmaclean@google.com <wjmaclean@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-23 15:20:47 +0000 |
---|---|---|
committer | wjmaclean@google.com <wjmaclean@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-23 15:20:47 +0000 |
commit | c457bf3e7f797d06aace7ffa1a0b2e1393ec4009 (patch) | |
tree | a3d0dc37e3dceeefdc4a68f71f192a5732bdd9cd /content/common | |
parent | f96721bbd5f09d7e0ef305b42aa86a3b7ae0c298 (diff) | |
download | chromium_src-c457bf3e7f797d06aace7ffa1a0b2e1393ec4009.zip chromium_src-c457bf3e7f797d06aace7ffa1a0b2e1393ec4009.tar.gz chromium_src-c457bf3e7f797d06aace7ffa1a0b2e1393ec4009.tar.bz2 |
Implements OSMesaImageTransportSurface in the GPU for sending GLSurface from the GPU to the browser.
Implements AcceleratedSurfaceContainerTouchOSMesa in the browser's renderer for receiving a GLSurface contents and building a GLTexture in the browser for compositing.
BUG=
TEST=./out/Debug/chrome --use-gl=osmesa --show-fps-counter
Review URL: http://codereview.chromium.org/7980006
Patch from Dana Jansens <danakj@chromium.org>.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102500 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common')
-rw-r--r-- | content/common/gpu/DEPS | 1 | ||||
-rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.cc | 4 | ||||
-rw-r--r-- | content/common/gpu/gpu_messages.h | 21 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface_linux.cc | 214 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface_linux.h | 21 |
5 files changed, 220 insertions, 41 deletions
diff --git a/content/common/gpu/DEPS b/content/common/gpu/DEPS index 98cc1f3..428e3cd 100644 --- a/content/common/gpu/DEPS +++ b/content/common/gpu/DEPS @@ -7,4 +7,5 @@ include_rules = [ "+skia",
"+third_party/angle/include",
"+third_party/openmax",
+ "+third_party/mesa",
]
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index a53364a..d38d9c9 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -566,7 +566,7 @@ void GpuCommandBufferStub::OnResize(gfx::Size size) { // asynchronously. uint64 new_backing_store = accelerated_surface_->SetSurfaceSize(size); if (new_backing_store) { - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; + GpuHostMsg_AcceleratedSurfaceNew_Params params; params.renderer_id = renderer_id_; params.render_view_id = render_view_id_; params.window = handle_; @@ -574,7 +574,7 @@ void GpuCommandBufferStub::OnResize(gfx::Size size) { params.height = size.height(); params.identifier = new_backing_store; gpu_channel_manager->Send( - new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); + new GpuHostMsg_AcceleratedSurfaceNew(params)); } else { // TODO(kbr): figure out what to do here. It wouldn't be difficult // to support the compositor on 10.5, but the performance would be diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index f96a632..a6b96e4 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -31,7 +31,7 @@ IPC_STRUCT_BEGIN(GPUCreateCommandBufferConfig) IPC_STRUCT_END() #if defined(OS_MACOSX) -IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params) +IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceNew_Params) IPC_STRUCT_MEMBER(int32, renderer_id) IPC_STRUCT_MEMBER(int32, render_view_id) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) @@ -51,7 +51,7 @@ IPC_STRUCT_END() #endif #if defined(TOUCH_UI) -IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params) +IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceNew_Params) IPC_STRUCT_MEMBER(int32, renderer_id) IPC_STRUCT_MEMBER(int32, render_view_id) IPC_STRUCT_MEMBER(int32, width) @@ -158,8 +158,9 @@ 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_ROUTED1(AcceleratedSurfaceMsg_SetSurfaceACK, - uint64 /* surface_id */) +IPC_MESSAGE_ROUTED2(AcceleratedSurfaceMsg_NewACK, + uint64 /* surface_id */, + TransportDIB::Handle /* shared memory buffer */) // Tells the GPU process that the browser process handled the swap // buffers request with the given number. @@ -250,12 +251,12 @@ IPC_MESSAGE_CONTROL4(GpuHostMsg_ResizeView, #endif #if defined(OS_MACOSX) || defined(TOUCH_UI) -// This message is sent from the GPU process to the browser to indicate that a -// new backing store was allocated. The renderer ID and render view ID are -// needed in order to uniquely identify the RenderWidgetHostView on the -// browser side. -IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceSetIOSurface, - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params) +// This message is sent from the GPU process to the browser to notify about a +// new or resized surface in the GPU. The browser allocates any resources +// needed for it on its end and replies with an ACK containing any shared +// resources/identifiers to be used in the GPU. +IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceNew, + GpuHostMsg_AcceleratedSurfaceNew_Params) // This message notifies the browser process that the renderer // swapped the buffers associated with the given "window", which diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc index e0117e6..e7f304d 100644 --- a/content/common/gpu/image_transport_surface_linux.cc +++ b/content/common/gpu/image_transport_surface_linux.cc @@ -20,11 +20,13 @@ #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 "third_party/mesa/MesaLib/include/GL/osmesa.h" #include "ui/gfx/gl/gl_context.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/gl/gl_surface_osmesa.h" #include "ui/gfx/surface/accelerated_surface_linux.h" namespace { @@ -50,7 +52,8 @@ class EGLImageTransportSurface : public ImageTransportSurface, protected: // ImageTransportSurface implementation - virtual void OnSetSurfaceACK(uint64 surface_id) OVERRIDE; + virtual void OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) OVERRIDE; virtual void OnBuffersSwappedACK() OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; @@ -68,8 +71,8 @@ class EGLImageTransportSurface : public ImageTransportSurface, 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. +// We render to an off-screen (but mapped) window that the browser process will +// read from via XComposite class GLXImageTransportSurface : public ImageTransportSurface, public gfx::NativeViewGLSurfaceGLX { public: @@ -87,9 +90,10 @@ class GLXImageTransportSurface : public ImageTransportSurface, protected: // ImageTransportSurface implementation: - void OnSetSurfaceACK(uint64 surface_id) OVERRIDE; - void OnBuffersSwappedACK() OVERRIDE; - void OnResize(gfx::Size size) OVERRIDE; + virtual void OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) OVERRIDE; + virtual void OnBuffersSwappedACK() OVERRIDE; + virtual void OnResize(gfx::Size size) OVERRIDE; private: virtual ~GLXImageTransportSurface(); @@ -111,6 +115,47 @@ class GLXImageTransportSurface : public ImageTransportSurface, DISALLOW_COPY_AND_ASSIGN(GLXImageTransportSurface); }; +// We render to a hunk of shared memory that we get from the browser. +// Swapping buffers simply means telling the browser to read the contents +// of the memory. +class OSMesaImageTransportSurface : public ImageTransportSurface, + public gfx::GLSurfaceOSMesa { + public: + OSMesaImageTransportSurface(GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id); + + // gfx::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* GetHandle() OVERRIDE; + + protected: + // ImageTransportSurface implementation: + virtual void OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) OVERRIDE; + virtual void OnBuffersSwappedACK() OVERRIDE; + virtual void OnResize(gfx::Size size) OVERRIDE; + + private: + virtual ~OSMesaImageTransportSurface(); + + // Tell the browser to release the surface. + void ReleaseSurface(); + + scoped_ptr<TransportDIB> shared_mem_; + uint32 shared_id_; + gfx::Size size_; + + scoped_ptr<ImageTransportHelper> helper_; + + DISALLOW_COPY_AND_ASSIGN(OSMesaImageTransportSurface); +}; + EGLImageTransportSurface::EGLImageTransportSurface( GpuChannelManager* manager, int32 render_view_id, @@ -145,6 +190,8 @@ void EGLImageTransportSurface::Destroy() { PbufferGLSurfaceEGL::Destroy(); } +// Make sure that buffer swaps occur for the surface, so we can send the data +// to the actual onscreen surface in the browser bool EGLImageTransportSurface::IsOffscreen() { return false; } @@ -189,11 +236,11 @@ void EGLImageTransportSurface::OnResize(gfx::Size size) { 0); glFlush(); - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; + GpuHostMsg_AcceleratedSurfaceNew_Params params; params.width = size.width(); params.height = size.height(); params.identifier = back_surface_->pixmap(); - helper_->SendAcceleratedSurfaceSetIOSurface(params); + helper_->SendAcceleratedSurfaceNew(params); helper_->SetScheduled(false); } @@ -225,8 +272,8 @@ gfx::Size EGLImageTransportSurface::GetSize() { return back_surface_->size(); } -void EGLImageTransportSurface::OnSetSurfaceACK( - uint64 surface_id) { +void EGLImageTransportSurface::OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle /*surface_handle*/) { DCHECK_EQ(back_surface_->pixmap(), surface_id); helper_->SetScheduled(true); } @@ -331,11 +378,11 @@ void GLXImageTransportSurface::OnResize(gfx::Size size) { XResizeWindow(dpy, window_, size_.width(), size_.height()); XFlush(dpy); - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; + GpuHostMsg_AcceleratedSurfaceNew_Params params; params.width = size_.width(); params.height = size_.height(); params.identifier = window_; - helper_->SendAcceleratedSurfaceSetIOSurface(params); + helper_->SendAcceleratedSurfaceNew(params); helper_->SetScheduled(false); } @@ -363,8 +410,8 @@ void GLXImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { } } -void GLXImageTransportSurface::OnSetSurfaceACK( - uint64 surface_id) { +void GLXImageTransportSurface::OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle /*surface_handle*/) { DCHECK(!bound_); bound_ = true; helper_->SetScheduled(true); @@ -374,6 +421,117 @@ void GLXImageTransportSurface::OnBuffersSwappedACK() { helper_->SetScheduled(true); } +OSMesaImageTransportSurface::OSMesaImageTransportSurface( + GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id) + : gfx::GLSurfaceOSMesa(OSMESA_RGBA, gfx::Size(1, 1)), + size_(gfx::Size(1, 1)) { + helper_.reset(new ImageTransportHelper(this, + manager, + render_view_id, + renderer_id, + command_buffer_id)); +} + +OSMesaImageTransportSurface::~OSMesaImageTransportSurface() { + Destroy(); +} + +bool OSMesaImageTransportSurface::Initialize() { + if (!helper_->Initialize()) + return false; + return gfx::GLSurfaceOSMesa::Initialize(); +} + +void OSMesaImageTransportSurface::Destroy() { + if (shared_mem_.get()) + ReleaseSurface(); + + helper_->Destroy(); + gfx::GLSurfaceOSMesa::Destroy(); +} + +// Make sure that buffer swaps occur for the surface, so we can send the data +// to the actual onscreen surface in the browser +bool OSMesaImageTransportSurface::IsOffscreen() { + return false; +} + +void OSMesaImageTransportSurface::ReleaseSurface() { + GpuHostMsg_AcceleratedSurfaceRelease_Params params; + params.identifier = shared_id_; + helper_->SendAcceleratedSurfaceRelease(params); + + shared_mem_.reset(); + shared_id_ = 0; +} + +void OSMesaImageTransportSurface::OnResize(gfx::Size size) { + if (shared_mem_.get()) + ReleaseSurface(); + + // Now that the shared memory buffer is gone, we need to change OSMesa to + // point at something valid, so we'll let it point to the buffer in the super + // class. This would be really bad since that buffer has a different size, + // but we don't allow any drawing to take place until we reset the surface + // back to a new buffer of shared memory. + helper_->MakeCurrent(); + + size_ = size; + + GpuHostMsg_AcceleratedSurfaceNew_Params params; + params.width = size_.width(); + params.height = size_.height(); + params.identifier = 0; // id comes from the browser with the shared mem + helper_->SendAcceleratedSurfaceNew(params); + + helper_->SetScheduled(false); +} + +void OSMesaImageTransportSurface::OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) { + shared_id_ = surface_id; + shared_mem_.reset(TransportDIB::Map(surface_handle)); + DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); + + // When we get the shared memory buffer back we can use that for OSMesa to + // write in, so we give it to OSMesa. + helper_->MakeCurrent(); + + helper_->SetScheduled(true); +} + +bool OSMesaImageTransportSurface::SwapBuffers() { + DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); + + // Copy the OSMesa buffer to the shared memory + memcpy(shared_mem_->memory(), GetHandle(), size_.GetArea() * 4); + + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.surface_id = shared_id_; + helper_->SendAcceleratedSurfaceBuffersSwapped(params); + + helper_->SetScheduled(false); + return true; +} + +void OSMesaImageTransportSurface::OnBuffersSwappedACK() { + helper_->SetScheduled(true); +} + +gfx::Size OSMesaImageTransportSurface::GetSize() { + return size_; +} + +void* OSMesaImageTransportSurface::GetHandle() { + if (shared_mem_.get()) + return shared_mem_->memory(); + else + return GLSurfaceOSMesa::GetHandle(); +} + } // namespace // static @@ -396,6 +554,12 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( renderer_id, command_buffer_id); break; + case gfx::kGLImplementationOSMesaGL: + surface = new OSMesaImageTransportSurface(manager, + render_view_id, + renderer_id, + command_buffer_id); + break; default: NOTREACHED(); return NULL; @@ -441,8 +605,8 @@ void ImageTransportHelper::Destroy() { bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message) - IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_SetSurfaceACK, - OnSetSurfaceACK) + IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_NewACK, + OnNewSurfaceACK) IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BuffersSwappedACK, OnBuffersSwappedACK) IPC_MESSAGE_UNHANDLED(handled = false) @@ -458,12 +622,12 @@ void ImageTransportHelper::SendAcceleratedSurfaceRelease( manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); } -void ImageTransportHelper::SendAcceleratedSurfaceSetIOSurface( - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params) { +void ImageTransportHelper::SendAcceleratedSurfaceNew( + GpuHostMsg_AcceleratedSurfaceNew_Params params) { params.renderer_id = renderer_id_; params.render_view_id = render_view_id_; params.route_id = route_id_; - manager_->Send(new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); + manager_->Send(new GpuHostMsg_AcceleratedSurfaceNew(params)); } void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped( @@ -482,8 +646,9 @@ void ImageTransportHelper::SetScheduled(bool is_scheduled) { scheduler->SetScheduled(is_scheduled); } -void ImageTransportHelper::OnSetSurfaceACK(uint64 surface_id) { - surface_->OnSetSurfaceACK(surface_id); +void ImageTransportHelper::OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) { + surface_->OnNewSurfaceACK(surface_id, surface_handle); } void ImageTransportHelper::OnBuffersSwappedACK() { @@ -494,6 +659,13 @@ void ImageTransportHelper::Resize(gfx::Size size) { surface_->OnResize(size); } +bool ImageTransportHelper::MakeCurrent() { + gpu::gles2::GLES2Decoder* decoder = Decoder(); + if (!decoder) + return false; + return decoder->MakeCurrent(); +} + gpu::GpuScheduler* ImageTransportHelper::Scheduler() { GpuChannel* channel = manager_->LookupChannel(renderer_id_); if (!channel) diff --git a/content/common/gpu/image_transport_surface_linux.h b/content/common/gpu/image_transport_surface_linux.h index 3dddd959..b146ab0 100644 --- a/content/common/gpu/image_transport_surface_linux.h +++ b/content/common/gpu/image_transport_surface_linux.h @@ -12,12 +12,13 @@ #include "ipc/ipc_channel.h" #include "ipc/ipc_message.h" #include "ui/gfx/size.h" +#include "ui/gfx/surface/transport_dib.h" class GpuChannelManager; -struct GpuHostMsg_AcceleratedSurfaceRelease_Params; -struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params; +struct GpuHostMsg_AcceleratedSurfaceNew_Params; struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params; +struct GpuHostMsg_AcceleratedSurfaceRelease_Params; namespace gfx { class GLSurface; @@ -33,7 +34,8 @@ class GLES2Decoder; class ImageTransportSurface { public: - virtual void OnSetSurfaceACK(uint64 surface_id) = 0; + virtual void OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) = 0; virtual void OnBuffersSwappedACK() = 0; virtual void OnResize(gfx::Size size) = 0; @@ -63,22 +65,25 @@ class ImageTransportHelper : public IPC::Channel::Listener { // Helper send functions. Caller fills in the surface specific params // like size and surface id. The helper fills in the rest. - void SendAcceleratedSurfaceRelease( - GpuHostMsg_AcceleratedSurfaceRelease_Params params); - void SendAcceleratedSurfaceSetIOSurface( - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params); + void SendAcceleratedSurfaceNew( + GpuHostMsg_AcceleratedSurfaceNew_Params params); void SendAcceleratedSurfaceBuffersSwapped( GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params); + void SendAcceleratedSurfaceRelease( + GpuHostMsg_AcceleratedSurfaceRelease_Params params); // Whether or not we should execute more commands. void SetScheduled(bool is_scheduled); + // Make the surface's context current + bool MakeCurrent(); + private: gpu::GpuScheduler* Scheduler(); gpu::gles2::GLES2Decoder* Decoder(); // IPC::Message handlers. - void OnSetSurfaceACK(uint64 surface_id); + void OnNewSurfaceACK(uint64 surface_id, TransportDIB::Handle surface_handle); void OnBuffersSwappedACK(); // Backbuffer resize callback. |