Index: content/common/gpu/image_transport_surface_linux.cc |
diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc |
index e0117e69172b1d55133d9953c0a8961de8a6f097..4a6437bc2f10e92a4323b47fbc89e5ea0faedf19 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 |
jonathan.backer
2011/09/21 20:27:36
Thanks.
|
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*/) { |
jonathan.backer
2011/09/21 20:27:36
Comment out param name? Haven't seen this before.
danakj
2011/09/21 20:58:20
It's in the C++ style guide for params that are no
|
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) |