| 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 8ae534d275b417bcee04f34f8c8df0315d866123..79579845a4a3f62bb2661a71b3051b9b03ca0967 100644
|
| --- a/content/common/gpu/image_transport_surface_linux.cc
|
| +++ b/content/common/gpu/image_transport_surface_linux.cc
|
| @@ -4,902 +4,7 @@
|
|
|
| #include "content/common/gpu/image_transport_surface.h"
|
|
|
| -// This conflicts with the defines in Xlib.h and must come first.
|
| -#include "content/common/gpu/gpu_messages.h"
|
| -
|
| -#include <X11/Xlib.h>
|
| -#include <X11/extensions/Xcomposite.h>
|
| -#include <map>
|
| -#include <vector>
|
| -
|
| -// Note: these must be included before anything that includes gl_bindings.h
|
| -// They're effectively standard library headers.
|
| -#include "third_party/khronos/EGL/egl.h"
|
| -#include "third_party/khronos/EGL/eglext.h"
|
| -#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/debug/trace_event.h"
|
| -#include "base/memory/weak_ptr.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 "content/common/gpu/texture_image_transport_surface.h"
|
| -#include "gpu/command_buffer/service/gpu_scheduler.h"
|
| -#include "ui/gfx/rect.h"
|
| -#include "ui/gl/gl_bindings.h"
|
| -#include "ui/gl/gl_context.h"
|
| -#include "ui/gl/gl_implementation.h"
|
| -#include "ui/gl/gl_surface_egl.h"
|
| -#include "ui/gl/gl_surface_glx.h"
|
| -#include "ui/gl/gl_surface_osmesa.h"
|
| -
|
| -namespace {
|
| -
|
| -class ScopedDisplayLock {
|
| - public:
|
| - ScopedDisplayLock(Display* display): display_(display) {
|
| - XLockDisplay(display_);
|
| - }
|
| -
|
| - ~ScopedDisplayLock() {
|
| - XUnlockDisplay(display_);
|
| - }
|
| -
|
| - private:
|
| - Display* display_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ScopedDisplayLock);
|
| -};
|
| -
|
| -// The GL context associated with the surface must be current when
|
| -// an instance is created or destroyed.
|
| -class EGLAcceleratedSurface : public base::RefCounted<EGLAcceleratedSurface> {
|
| - public:
|
| - explicit EGLAcceleratedSurface(const gfx::Size& size);
|
| - const gfx::Size& size() const { return size_; }
|
| - uint32 pixmap() const { return pixmap_; }
|
| - uint32 texture() const { return texture_; }
|
| -
|
| - private:
|
| - ~EGLAcceleratedSurface();
|
| -
|
| - gfx::Size size_;
|
| - void* image_;
|
| - uint32 pixmap_;
|
| - uint32 texture_;
|
| -
|
| - friend class base::RefCounted<EGLAcceleratedSurface>;
|
| - DISALLOW_COPY_AND_ASSIGN(EGLAcceleratedSurface);
|
| -};
|
| -
|
| -// 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 base::SupportsWeakPtr<EGLImageTransportSurface> {
|
| - public:
|
| - EGLImageTransportSurface(GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub);
|
| -
|
| - // gfx::GLSurface implementation
|
| - virtual bool Initialize() OVERRIDE;
|
| - virtual void Destroy() OVERRIDE;
|
| - virtual bool IsOffscreen() OVERRIDE;
|
| - virtual bool SwapBuffers() OVERRIDE;
|
| - virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
|
| - virtual std::string GetExtensions() OVERRIDE;
|
| - virtual gfx::Size GetSize() OVERRIDE;
|
| - virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
|
| - virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
|
| - virtual void SetBackbufferAllocation(bool allocated) OVERRIDE;
|
| - virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
|
| -
|
| - protected:
|
| - // ImageTransportSurface implementation
|
| - virtual void OnNewSurfaceACK(
|
| - uint64 surface_handle, TransportDIB::Handle shm_handle) OVERRIDE;
|
| - virtual void OnBufferPresented(uint32 sync_point) OVERRIDE;
|
| - virtual void OnResizeViewACK() OVERRIDE;
|
| - virtual void OnResize(gfx::Size size) OVERRIDE;
|
| -
|
| - private:
|
| - virtual ~EGLImageTransportSurface() OVERRIDE;
|
| - void ReleaseSurface(scoped_refptr<EGLAcceleratedSurface>* surface);
|
| - void SendBuffersSwapped();
|
| - void SendPostSubBuffer(int x, int y, int width, int height);
|
| -
|
| - // Tracks the current buffer allocation state.
|
| - bool backbuffer_suggested_allocation_;
|
| - bool frontbuffer_suggested_allocation_;
|
| -
|
| - // The expected size when visible.
|
| - gfx::Size visible_size_;
|
| -
|
| - uint32 fbo_id_;
|
| -
|
| - scoped_refptr<EGLAcceleratedSurface> back_surface_;
|
| - scoped_refptr<EGLAcceleratedSurface> front_surface_;
|
| - gfx::Rect previous_damage_rect_;
|
| -
|
| - // Whether or not we've successfully made the surface current once.
|
| - bool made_current_;
|
| -
|
| - scoped_ptr<ImageTransportHelper> helper_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(EGLImageTransportSurface);
|
| -};
|
| -
|
| -// 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 base::SupportsWeakPtr<GLXImageTransportSurface> {
|
| - public:
|
| - GLXImageTransportSurface(GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub);
|
| -
|
| - // gfx::GLSurface implementation:
|
| - virtual bool Initialize() OVERRIDE;
|
| - virtual void Destroy() OVERRIDE;
|
| - virtual bool SwapBuffers() OVERRIDE;
|
| - virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
|
| - virtual std::string GetExtensions();
|
| - virtual gfx::Size GetSize() OVERRIDE;
|
| - virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
|
| - virtual void SetBackbufferAllocation(bool allocated) OVERRIDE;
|
| - virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
|
| -
|
| - protected:
|
| - // ImageTransportSurface implementation:
|
| - virtual void OnNewSurfaceACK(
|
| - uint64 surface_handle, TransportDIB::Handle shm_handle) OVERRIDE;
|
| - virtual void OnBufferPresented(uint32 sync_point) OVERRIDE;
|
| - virtual void OnResizeViewACK() OVERRIDE;
|
| - virtual void OnResize(gfx::Size size) OVERRIDE;
|
| -
|
| - private:
|
| - virtual ~GLXImageTransportSurface();
|
| -
|
| - // Tell the browser to release the surface.
|
| - void ReleaseSurface();
|
| -
|
| - void SendBuffersSwapped();
|
| - void SendPostSubBuffer(int x, int y, int width, int height);
|
| -
|
| - void ResizeSurface(gfx::Size size);
|
| -
|
| - // Tracks the current buffer allocation state.
|
| - bool backbuffer_suggested_allocation_;
|
| - bool frontbuffer_suggested_allocation_;
|
| -
|
| - XID dummy_parent_;
|
| - gfx::Size size_;
|
| -
|
| - // Whether or not the image has been bound on the browser side.
|
| - bool bound_;
|
| -
|
| - // Whether or not we need to send a resize on the next swap.
|
| - bool needs_resize_;
|
| -
|
| - // Whether or not we've successfully made the surface current once.
|
| - bool made_current_;
|
| -
|
| - scoped_ptr<ImageTransportHelper> helper_;
|
| -
|
| - 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,
|
| - GpuCommandBufferStub* stub);
|
| -
|
| - // gfx::GLSurface implementation:
|
| - virtual bool Initialize() OVERRIDE;
|
| - virtual void Destroy() OVERRIDE;
|
| - virtual bool IsOffscreen() OVERRIDE;
|
| - virtual bool SwapBuffers() OVERRIDE;
|
| - virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
|
| - virtual std::string GetExtensions() OVERRIDE;
|
| - virtual gfx::Size GetSize() OVERRIDE;
|
| -
|
| - protected:
|
| - // ImageTransportSurface implementation:
|
| - virtual void OnNewSurfaceACK(
|
| - uint64 surface_handle, TransportDIB::Handle shm_handle) OVERRIDE;
|
| - virtual void OnBufferPresented(uint32 sync_point) OVERRIDE;
|
| - virtual void OnResizeViewACK() 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);
|
| -};
|
| -
|
| -EGLAcceleratedSurface::EGLAcceleratedSurface(const gfx::Size& size)
|
| - : size_(size), texture_(0) {
|
| - Display* dpy = gfx::GLSurfaceEGL::GetNativeDisplay();
|
| - EGLDisplay edpy = gfx::GLSurfaceEGL::GetHardwareDisplay();
|
| -
|
| - XID window = XDefaultRootWindow(dpy);
|
| - XWindowAttributes gwa;
|
| - bool success = XGetWindowAttributes(dpy, window, &gwa);
|
| - DCHECK(success);
|
| - pixmap_ = XCreatePixmap(
|
| - dpy, window, size_.width(), size_.height(), gwa.depth);
|
| -
|
| - image_ = eglCreateImageKHR(
|
| - edpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
|
| - reinterpret_cast<void*>(pixmap_), NULL);
|
| -
|
| - glGenTextures(1, &texture_);
|
| -
|
| - GLint current_texture = 0;
|
| - glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
|
| -
|
| - glBindTexture(GL_TEXTURE_2D, texture_);
|
| - 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);
|
| - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
|
| -
|
| - glBindTexture(GL_TEXTURE_2D, current_texture);
|
| -}
|
| -
|
| -EGLAcceleratedSurface::~EGLAcceleratedSurface() {
|
| - glDeleteTextures(1, &texture_);
|
| - eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_);
|
| - XFreePixmap(gfx::GLSurfaceEGL::GetNativeDisplay(), pixmap_);
|
| -}
|
| -
|
| -EGLImageTransportSurface::EGLImageTransportSurface(
|
| - GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub)
|
| - : gfx::PbufferGLSurfaceEGL(false, gfx::Size(16, 16)),
|
| - backbuffer_suggested_allocation_(true),
|
| - frontbuffer_suggested_allocation_(true),
|
| - fbo_id_(0),
|
| - made_current_(false) {
|
| - helper_.reset(new ImageTransportHelper(this,
|
| - manager,
|
| - stub,
|
| - gfx::kNullPluginWindow));
|
| -}
|
| -
|
| -EGLImageTransportSurface::~EGLImageTransportSurface() {
|
| - Destroy();
|
| -}
|
| -
|
| -bool EGLImageTransportSurface::Initialize() {
|
| - if (!helper_->Initialize())
|
| - return false;
|
| - return gfx::PbufferGLSurfaceEGL::Initialize();
|
| -}
|
| -
|
| -void EGLImageTransportSurface::Destroy() {
|
| - if (back_surface_.get())
|
| - ReleaseSurface(&back_surface_);
|
| - if (front_surface_.get())
|
| - ReleaseSurface(&front_surface_);
|
| -
|
| - helper_->Destroy();
|
| - gfx::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;
|
| -}
|
| -
|
| -bool EGLImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
|
| - if (made_current_)
|
| - return true;
|
| -
|
| - if (!context->HasExtension("EGL_KHR_image") &&
|
| - !context->HasExtension("EGL_KHR_image_pixmap")) {
|
| - DLOG(ERROR) << "EGLImage from X11 pixmap not supported";
|
| - return false;
|
| - }
|
| -
|
| - glGenFramebuffersEXT(1, &fbo_id_);
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_);
|
| -
|
| - // Creating 16x16 (instead of 1x1) to work around ARM Mali driver issue
|
| - // (see https://code.google.com/p/chrome-os-partner/issues/detail?id=9445)
|
| - OnResize(gfx::Size(16, 16));
|
| -
|
| - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
|
| - if (status != GL_FRAMEBUFFER_COMPLETE) {
|
| - DLOG(ERROR) << "Framebuffer incomplete.";
|
| - return false;
|
| - }
|
| -
|
| - made_current_ = true;
|
| - return true;
|
| -}
|
| -
|
| -unsigned int EGLImageTransportSurface::GetBackingFrameBufferObject() {
|
| - return fbo_id_;
|
| -}
|
| -
|
| -void EGLImageTransportSurface::SetBackbufferAllocation(bool allocated) {
|
| - if (backbuffer_suggested_allocation_ == allocated)
|
| - return;
|
| - backbuffer_suggested_allocation_ = allocated;
|
| -
|
| - if (backbuffer_suggested_allocation_)
|
| - OnResize(visible_size_);
|
| - else
|
| - ReleaseSurface(&back_surface_);
|
| -}
|
| -
|
| -void EGLImageTransportSurface::SetFrontbufferAllocation(bool allocated) {
|
| - if (frontbuffer_suggested_allocation_ == allocated)
|
| - return;
|
| - frontbuffer_suggested_allocation_ = allocated;
|
| -}
|
| -
|
| -void EGLImageTransportSurface::ReleaseSurface(
|
| - scoped_refptr<EGLAcceleratedSurface>* surface) {
|
| - if (surface->get()) {
|
| - GpuHostMsg_AcceleratedSurfaceRelease_Params params;
|
| - params.identifier = (*surface)->pixmap();
|
| - helper_->SendAcceleratedSurfaceRelease(params);
|
| - *surface = NULL;
|
| - }
|
| -}
|
| -
|
| -void EGLImageTransportSurface::OnResize(gfx::Size size) {
|
| - visible_size_ = size;
|
| - back_surface_ = new EGLAcceleratedSurface(size);
|
| -
|
| - GLint previous_fbo_id = 0;
|
| - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previous_fbo_id);
|
| -
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
|
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
|
| - GL_COLOR_ATTACHMENT0,
|
| - GL_TEXTURE_2D,
|
| - back_surface_->texture(),
|
| - 0);
|
| - glFlush();
|
| -
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id);
|
| -
|
| - GpuHostMsg_AcceleratedSurfaceNew_Params params;
|
| - params.width = size.width();
|
| - params.height = size.height();
|
| - params.surface_handle = back_surface_->pixmap();
|
| - helper_->SendAcceleratedSurfaceNew(params);
|
| -
|
| - helper_->SetScheduled(false);
|
| -}
|
| -
|
| -bool EGLImageTransportSurface::SwapBuffers() {
|
| - DCHECK(backbuffer_suggested_allocation_);
|
| - if (!frontbuffer_suggested_allocation_)
|
| - return true;
|
| - front_surface_.swap(back_surface_);
|
| - DCHECK_NE(front_surface_.get(), static_cast<EGLAcceleratedSurface*>(NULL));
|
| - helper_->DeferToFence(base::Bind(
|
| - &EGLImageTransportSurface::SendBuffersSwapped,
|
| - AsWeakPtr()));
|
| -
|
| - gfx::Size expected_size = front_surface_->size();
|
| - if (!back_surface_.get() || back_surface_->size() != expected_size) {
|
| - OnResize(expected_size);
|
| - } else {
|
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
|
| - GL_COLOR_ATTACHMENT0,
|
| - GL_TEXTURE_2D,
|
| - back_surface_->texture(),
|
| - 0);
|
| - }
|
| - previous_damage_rect_ = gfx::Rect(front_surface_->size());
|
| - return true;
|
| -}
|
| -
|
| -void EGLImageTransportSurface::SendBuffersSwapped() {
|
| - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
|
| - params.surface_handle = front_surface_->pixmap();
|
| - helper_->SendAcceleratedSurfaceBuffersSwapped(params);
|
| - helper_->SetScheduled(false);
|
| -}
|
| -
|
| -bool EGLImageTransportSurface::PostSubBuffer(
|
| - int x, int y, int width, int height) {
|
| - DCHECK(backbuffer_suggested_allocation_);
|
| - if (!frontbuffer_suggested_allocation_)
|
| - return true;
|
| - // If we are recreating the frontbuffer with this swap, make sure we are
|
| - // drawing a full frame.
|
| - DCHECK(front_surface_.get() ||
|
| - (!x && !y && gfx::Size(width, height) == visible_size_));
|
| - DCHECK_NE(back_surface_.get(), static_cast<EGLAcceleratedSurface*>(NULL));
|
| - gfx::Size expected_size = back_surface_->size();
|
| - bool surfaces_same_size = front_surface_.get() &&
|
| - front_surface_->size() == expected_size;
|
| -
|
| - const gfx::Rect new_damage_rect(x, y, width, height);
|
| -
|
| - // An empty damage rect is a successful no-op.
|
| - if (new_damage_rect.IsEmpty())
|
| - return true;
|
| -
|
| - if (surfaces_same_size) {
|
| - std::vector<gfx::Rect> regions_to_copy;
|
| - GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy);
|
| -
|
| - GLint previous_texture_id = 0;
|
| - glGetIntegerv(GL_ACTIVE_TEXTURE, &previous_texture_id);
|
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
|
| - GL_COLOR_ATTACHMENT0,
|
| - GL_TEXTURE_2D,
|
| - front_surface_->texture(),
|
| - 0);
|
| - glBindTexture(GL_TEXTURE_2D, back_surface_->texture());
|
| -
|
| - for (size_t i = 0; i < regions_to_copy.size(); ++i) {
|
| - const gfx::Rect& region_to_copy = regions_to_copy[i];
|
| - if (!region_to_copy.IsEmpty()) {
|
| - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(),
|
| - region_to_copy.y(), region_to_copy.x(), region_to_copy.y(),
|
| - region_to_copy.width(), region_to_copy.height());
|
| - }
|
| - }
|
| - glBindTexture(GL_TEXTURE_2D, previous_texture_id);
|
| - }
|
| -
|
| - front_surface_.swap(back_surface_);
|
| -
|
| - if (!surfaces_same_size) {
|
| - DCHECK(new_damage_rect == gfx::Rect(expected_size));
|
| - OnResize(expected_size);
|
| - }
|
| -
|
| - helper_->DeferToFence(base::Bind(
|
| - &EGLImageTransportSurface::SendPostSubBuffer,
|
| - AsWeakPtr(), x, y, width, height));
|
| -
|
| - previous_damage_rect_ = new_damage_rect;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void EGLImageTransportSurface::SendPostSubBuffer(
|
| - int x, int y, int width, int height) {
|
| - GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
|
| - params.surface_handle = front_surface_->pixmap();
|
| - params.x = x;
|
| - params.y = y;
|
| - params.width = width;
|
| - params.height = height;
|
| -
|
| - helper_->SendAcceleratedSurfacePostSubBuffer(params);
|
| - helper_->SetScheduled(false);
|
| -}
|
| -
|
| -std::string EGLImageTransportSurface::GetExtensions() {
|
| - std::string extensions = gfx::GLSurface::GetExtensions();
|
| - extensions += extensions.empty() ? "" : " ";
|
| - extensions += "GL_CHROMIUM_front_buffer_cached ";
|
| - extensions += "GL_CHROMIUM_post_sub_buffer";
|
| - return extensions;
|
| -}
|
| -
|
| -gfx::Size EGLImageTransportSurface::GetSize() {
|
| - return back_surface_->size();
|
| -}
|
| -
|
| -void EGLImageTransportSurface::OnNewSurfaceACK(
|
| - uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) {
|
| - DCHECK_EQ(back_surface_->pixmap(), surface_handle);
|
| - helper_->SetScheduled(true);
|
| -}
|
| -
|
| -void EGLImageTransportSurface::OnBufferPresented(uint32 sync_point) {
|
| - helper_->SetScheduled(true);
|
| -}
|
| -
|
| -void EGLImageTransportSurface::OnResizeViewACK() {
|
| - NOTREACHED();
|
| -}
|
| -
|
| -GLXImageTransportSurface::GLXImageTransportSurface(
|
| - GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub)
|
| - : gfx::NativeViewGLSurfaceGLX(),
|
| - backbuffer_suggested_allocation_(true),
|
| - frontbuffer_suggested_allocation_(true),
|
| - dummy_parent_(0),
|
| - size_(1, 1),
|
| - bound_(false),
|
| - needs_resize_(false),
|
| - made_current_(false) {
|
| - helper_.reset(new ImageTransportHelper(this,
|
| - manager,
|
| - stub,
|
| - gfx::kNullPluginWindow));
|
| -}
|
| -
|
| -GLXImageTransportSurface::~GLXImageTransportSurface() {
|
| - Destroy();
|
| -}
|
| -
|
| -bool GLXImageTransportSurface::Initialize() {
|
| - // Create a dummy window to host the real window.
|
| - Display* dpy = static_cast<Display*>(GetDisplay());
|
| - ScopedDisplayLock lock(dpy);
|
| -
|
| - XSetWindowAttributes swa;
|
| - 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
|
| - 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;
|
| - XWindowEvent(dpy, window_, StructureNotifyMask, &event);
|
| - if (event.type == MapNotify && event.xmap.window == window_)
|
| - break;
|
| - }
|
| - XSelectInput(dpy, window_, NoEventMask);
|
| -
|
| - // Manual setting must be used to avoid unnecessary rendering by server.
|
| - XCompositeRedirectWindow(dpy, window_, CompositeRedirectManual);
|
| - OnResize(size_);
|
| -
|
| - if (!helper_->Initialize())
|
| - return false;
|
| - return gfx::NativeViewGLSurfaceGLX::Initialize();
|
| -}
|
| -
|
| -void GLXImageTransportSurface::Destroy() {
|
| - if (bound_)
|
| - ReleaseSurface();
|
| -
|
| - if (window_) {
|
| - Display* dpy = static_cast<Display*>(GetDisplay());
|
| - XDestroyWindow(dpy, window_);
|
| - XDestroyWindow(dpy, dummy_parent_);
|
| - }
|
| -
|
| - helper_->Destroy();
|
| - gfx::NativeViewGLSurfaceGLX::Destroy();
|
| -}
|
| -
|
| -void GLXImageTransportSurface::ReleaseSurface() {
|
| - DCHECK(bound_);
|
| - GpuHostMsg_AcceleratedSurfaceRelease_Params params;
|
| - params.identifier = window_;
|
| - helper_->SendAcceleratedSurfaceRelease(params);
|
| - bound_ = false;
|
| -}
|
| -
|
| -void GLXImageTransportSurface::SetBackbufferAllocation(bool allocated) {
|
| - if (backbuffer_suggested_allocation_ == allocated)
|
| - return;
|
| - backbuffer_suggested_allocation_ = allocated;
|
| -
|
| - if (backbuffer_suggested_allocation_)
|
| - ResizeSurface(size_);
|
| - else
|
| - ResizeSurface(gfx::Size(1,1));
|
| -}
|
| -
|
| -void GLXImageTransportSurface::SetFrontbufferAllocation(bool allocated) {
|
| - if (frontbuffer_suggested_allocation_ == allocated)
|
| - return;
|
| - frontbuffer_suggested_allocation_ = allocated;
|
| -
|
| - // We recreate frontbuffer by recreating backbuffer and swapping.
|
| - // But we release frontbuffer by telling UI to release its handle on it.
|
| - if (!frontbuffer_suggested_allocation_ && bound_)
|
| - ReleaseSurface();
|
| -}
|
| -
|
| -void GLXImageTransportSurface::ResizeSurface(gfx::Size size) {
|
| - Display* dpy = static_cast<Display*>(GetDisplay());
|
| - XResizeWindow(dpy, window_, size.width(), size.height());
|
| - glXWaitX();
|
| - // Seems necessary to perform a swap after a resize
|
| - // in order to resize the front and back buffers (Intel driver bug).
|
| - // This doesn't always happen with scissoring enabled, so do it now.
|
| - if (gfx::g_GLX_MESA_copy_sub_buffer && gfx::GLSurface::GetCurrent() == this)
|
| - gfx::NativeViewGLSurfaceGLX::SwapBuffers();
|
| - needs_resize_ = true;
|
| -}
|
| -
|
| -void GLXImageTransportSurface::OnResize(gfx::Size size) {
|
| - TRACE_EVENT0("gpu", "GLXImageTransportSurface::OnResize");
|
| - size_ = size;
|
| - ResizeSurface(size_);
|
| -}
|
| -
|
| -bool GLXImageTransportSurface::SwapBuffers() {
|
| - DCHECK(backbuffer_suggested_allocation_);
|
| - if (!frontbuffer_suggested_allocation_)
|
| - return true;
|
| - gfx::NativeViewGLSurfaceGLX::SwapBuffers();
|
| - helper_->DeferToFence(base::Bind(
|
| - &GLXImageTransportSurface::SendBuffersSwapped,
|
| - AsWeakPtr()));
|
| -
|
| - if (needs_resize_) {
|
| - GpuHostMsg_AcceleratedSurfaceNew_Params params;
|
| - params.width = size_.width();
|
| - params.height = size_.height();
|
| - params.surface_handle = window_;
|
| - helper_->SendAcceleratedSurfaceNew(params);
|
| - bound_ = true;
|
| - needs_resize_ = false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void GLXImageTransportSurface::SendBuffersSwapped() {
|
| - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
|
| - params.surface_handle = window_;
|
| - helper_->SendAcceleratedSurfaceBuffersSwapped(params);
|
| - helper_->SetScheduled(false);
|
| -}
|
| -
|
| -bool GLXImageTransportSurface::PostSubBuffer(
|
| - int x, int y, int width, int height) {
|
| - DCHECK(backbuffer_suggested_allocation_);
|
| - if (!frontbuffer_suggested_allocation_)
|
| - return true;
|
| - gfx::NativeViewGLSurfaceGLX::PostSubBuffer(x, y, width, height);
|
| - helper_->DeferToFence(base::Bind(
|
| - &GLXImageTransportSurface::SendPostSubBuffer,
|
| - AsWeakPtr(), x, y, width, height));
|
| -
|
| - if (needs_resize_) {
|
| - GpuHostMsg_AcceleratedSurfaceNew_Params params;
|
| - params.width = size_.width();
|
| - params.height = size_.height();
|
| - params.surface_handle = window_;
|
| - helper_->SendAcceleratedSurfaceNew(params);
|
| - bound_ = true;
|
| - needs_resize_ = false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void GLXImageTransportSurface::SendPostSubBuffer(
|
| - int x, int y, int width, int height) {
|
| - GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
|
| - params.surface_handle = window_;
|
| - params.x = x;
|
| - params.y = y;
|
| - params.width = width;
|
| - params.height = height;
|
| -
|
| - helper_->SendAcceleratedSurfacePostSubBuffer(params);
|
| - helper_->SetScheduled(false);
|
| -}
|
| -
|
| -std::string GLXImageTransportSurface::GetExtensions() {
|
| - std::string extensions = gfx::NativeViewGLSurfaceGLX::GetExtensions();
|
| - extensions += extensions.empty() ? "" : " ";
|
| - extensions += "GL_CHROMIUM_front_buffer_cached";
|
| - return extensions;
|
| -}
|
| -
|
| -gfx::Size GLXImageTransportSurface::GetSize() {
|
| - return size_;
|
| -}
|
| -
|
| -bool GLXImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
|
| - if (made_current_)
|
| - return true;
|
| -
|
| - // Check for driver support.
|
| - Display* dpy = static_cast<Display*>(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) {
|
| - DLOG(ERROR) << "Pixmap from window not supported.";
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - context->SetSwapInterval(0);
|
| -
|
| - made_current_ = true;
|
| - return true;
|
| -}
|
| -
|
| -void GLXImageTransportSurface::OnNewSurfaceACK(
|
| - uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) {
|
| -}
|
| -
|
| -void GLXImageTransportSurface::OnBufferPresented(uint32 sync_point) {
|
| - helper_->SetScheduled(true);
|
| -}
|
| -
|
| -void GLXImageTransportSurface::OnResizeViewACK() {
|
| - NOTREACHED();
|
| -}
|
| -
|
| -OSMesaImageTransportSurface::OSMesaImageTransportSurface(
|
| - GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub)
|
| - : gfx::GLSurfaceOSMesa(OSMESA_RGBA, gfx::Size(1, 1)),
|
| - size_(gfx::Size(1, 1)) {
|
| - helper_.reset(new ImageTransportHelper(this,
|
| - manager,
|
| - stub,
|
| - gfx::kNullPluginWindow));
|
| -}
|
| -
|
| -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) {
|
| - shared_mem_.reset();
|
| - shared_id_ = 0;
|
| -
|
| - GLSurfaceOSMesa::Resize(size);
|
| -
|
| - // Now that we resized/reallocated the memory buffer, we need to change
|
| - // what OSMesa is pointing at to the new buffer.
|
| - helper_->MakeCurrent();
|
| -
|
| - size_ = size;
|
| -
|
| - GpuHostMsg_AcceleratedSurfaceNew_Params params;
|
| - params.width = size_.width();
|
| - params.height = size_.height();
|
| - params.surface_handle = 0; // id comes from the browser with the shared mem
|
| - helper_->SendAcceleratedSurfaceNew(params);
|
| -
|
| - helper_->SetScheduled(false);
|
| -}
|
| -
|
| -void OSMesaImageTransportSurface::OnNewSurfaceACK(
|
| - uint64 surface_handle, TransportDIB::Handle shm_handle) {
|
| - shared_id_ = surface_handle;
|
| - shared_mem_.reset(TransportDIB::Map(shm_handle));
|
| - DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
|
| -
|
| - helper_->SetScheduled(true);
|
| -}
|
| -
|
| -void OSMesaImageTransportSurface::OnResizeViewACK() {
|
| - NOTREACHED();
|
| -}
|
| -
|
| -bool OSMesaImageTransportSurface::SwapBuffers() {
|
| - DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
|
| -
|
| - // Copy the OSMesa buffer to the shared memory
|
| - glFinish();
|
| - memcpy(shared_mem_->memory(), GetHandle(), size_.GetArea() * 4);
|
| -
|
| - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
|
| - params.surface_handle = shared_id_;
|
| - helper_->SendAcceleratedSurfaceBuffersSwapped(params);
|
| -
|
| - helper_->SetScheduled(false);
|
| - return true;
|
| -}
|
| -
|
| -bool OSMesaImageTransportSurface::PostSubBuffer(
|
| - int x, int y, int width, int height) {
|
| - DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
|
| -
|
| - // Copy the OSMesa buffer to the shared memory
|
| - glFinish();
|
| -
|
| - int flipped_y = GetSize().height() - y - height;
|
| -
|
| - for (int row = 0; row < height; ++row) {
|
| - int mem_offset = ((flipped_y + row) * size_.width() + x);
|
| - int32* dest_address = static_cast<int32*>(shared_mem_->memory()) +
|
| - mem_offset;
|
| - int32* src_address = static_cast<int32*>(GetHandle()) + mem_offset;
|
| - memcpy(dest_address, src_address, width * 4);
|
| - }
|
| -
|
| - GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
|
| - params.surface_handle = shared_id_;
|
| - params.x = x;
|
| - params.y = y;
|
| - params.width = width;
|
| - params.height = height;
|
| - helper_->SendAcceleratedSurfacePostSubBuffer(params);
|
| -
|
| - helper_->SetScheduled(false);
|
| - return true;
|
| -}
|
| -
|
| -std::string OSMesaImageTransportSurface::GetExtensions() {
|
| - std::string extensions = gfx::GLSurface::GetExtensions();
|
| - extensions += extensions.empty() ? "" : " ";
|
| - extensions += "GL_CHROMIUM_front_buffer_cached ";
|
| - extensions += "GL_CHROMIUM_post_sub_buffer";
|
| - return extensions;
|
| -}
|
| -
|
| -void OSMesaImageTransportSurface::OnBufferPresented(uint32 sync_point) {
|
| - helper_->SetScheduled(true);
|
| -}
|
| -
|
| -gfx::Size OSMesaImageTransportSurface::GetSize() {
|
| - return size_;
|
| -}
|
| -
|
| -} // namespace
|
|
|
| // static
|
| scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
|
| @@ -909,24 +14,8 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
|
| scoped_refptr<gfx::GLSurface> surface;
|
| if (!handle.handle) {
|
| DCHECK(handle.transport);
|
| - if (!handle.parent_client_id) {
|
| - switch (gfx::GetGLImplementation()) {
|
| - case gfx::kGLImplementationDesktopGL:
|
| - surface = new GLXImageTransportSurface(manager, stub);
|
| - break;
|
| - case gfx::kGLImplementationEGLGLES2:
|
| - surface = new EGLImageTransportSurface(manager, stub);
|
| - break;
|
| - case gfx::kGLImplementationOSMesaGL:
|
| - surface = new OSMesaImageTransportSurface(manager, stub);
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - return NULL;
|
| - }
|
| - } else {
|
| - surface = new TextureImageTransportSurface(manager, stub, handle);
|
| - }
|
| + DCHECK(handle.parent_client_id);
|
| + surface = new TextureImageTransportSurface(manager, stub, handle);
|
| } else {
|
| surface = gfx::GLSurface::CreateViewGLSurface(false, handle.handle);
|
| if (!surface.get())
|
|
|