Commit e86e411c authored by achaulk's avatar achaulk Committed by Commit bot

Add a new API to create a surfaceless GLSurface for Ozone

Reverting CreateViewGLSurface to creating a surface that works as expected

Chrome uses the new surfaceless API, all others use the old one

BUG=447798

Review URL: https://codereview.chromium.org/938873002

Cr-Commit-Position: refs/heads/master@{#318786}
parent 5f3145d5
...@@ -13,9 +13,13 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface( ...@@ -13,9 +13,13 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
const gfx::GLSurfaceHandle& handle) { const gfx::GLSurfaceHandle& handle) {
DCHECK(handle.handle); DCHECK(handle.handle);
DCHECK(handle.transport_type == gfx::NATIVE_DIRECT); DCHECK(handle.transport_type == gfx::NATIVE_DIRECT);
scoped_refptr<gfx::GLSurface> surface = scoped_refptr<gfx::GLSurface> surface;
gfx::GLSurface::CreateViewGLSurface(handle.handle); #if defined(USE_OZONE)
if (!surface.get()) surface = gfx::GLSurface::CreateSurfacelessViewGLSurface(handle.handle);
#endif
if (!surface)
surface = gfx::GLSurface::CreateViewGLSurface(handle.handle);
if (!surface)
return surface; return surface;
return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface( return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
manager, stub, surface.get())); manager, stub, surface.get()));
......
...@@ -314,6 +314,9 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, ...@@ -314,6 +314,9 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
message_loop_ = base::MessageLoop::current(); message_loop_ = base::MessageLoop::current();
gl_surface_ = gfx::GLSurface::CreateViewGLSurface(window_); gl_surface_ = gfx::GLSurface::CreateViewGLSurface(window_);
#if defined(USE_OZONE)
gl_surface_->Resize(platform_window_delegate_->GetSize());
#endif // defined(USE_OZONE)
screen_size_ = gl_surface_->GetSize(); screen_size_ = gl_surface_->GetSize();
gl_context_ = gfx::GLContext::CreateGLContext( gl_context_ = gfx::GLContext::CreateGLContext(
...@@ -364,7 +367,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, ...@@ -364,7 +367,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status; CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glBindFramebufferEXT(GL_FRAMEBUFFER, 0); glBindFramebufferEXT(GL_FRAMEBUFFER,
gl_surface_->GetBackingFrameBufferObject());
} }
// These vertices and texture coords. map (0,0) in the texture to the // These vertices and texture coords. map (0,0) in the texture to the
...@@ -504,6 +508,7 @@ void RenderingHelper::UnInitialize(base::WaitableEvent* done) { ...@@ -504,6 +508,7 @@ void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_); glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_);
} }
gl_surface_->Destroy();
gl_context_->ReleaseCurrent(gl_surface_.get()); gl_context_->ReleaseCurrent(gl_surface_.get());
gl_context_ = NULL; gl_context_ = NULL;
gl_surface_ = NULL; gl_surface_ = NULL;
...@@ -570,7 +575,8 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target, ...@@ -570,7 +575,8 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target,
glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
GLSetViewPort(area); GLSetViewPort(area);
RenderTexture(texture_target, texture_id); RenderTexture(texture_target, texture_id);
glBindFramebufferEXT(GL_FRAMEBUFFER, 0); glBindFramebufferEXT(GL_FRAMEBUFFER,
gl_surface_->GetBackingFrameBufferObject());
// Need to flush the GL commands before we return the tnumbnail texture to // Need to flush the GL commands before we return the tnumbnail texture to
// the decoder. // the decoder.
...@@ -661,7 +667,8 @@ void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb, ...@@ -661,7 +667,8 @@ void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
GL_RGBA, GL_RGBA,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
&rgba[0]); &rgba[0]);
glBindFramebufferEXT(GL_FRAMEBUFFER, 0); glBindFramebufferEXT(GL_FRAMEBUFFER,
gl_surface_->GetBackingFrameBufferObject());
rgb->resize(num_pixels * 3); rgb->resize(num_pixels * 3);
// Drop the alpha channel, but check as we go that it is all 0xff. // Drop the alpha channel, but check as we go that it is all 0xff.
bool solid = true; bool solid = true;
...@@ -698,7 +705,13 @@ void RenderingHelper::RenderContent() { ...@@ -698,7 +705,13 @@ void RenderingHelper::RenderContent() {
static_cast<base::WaitableEvent*>(NULL))); static_cast<base::WaitableEvent*>(NULL)));
} }
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); int tex_flip = 1;
#if defined(USE_OZONE)
// Ozone surfaceless renders flipped from normal GL, so there's no need to
// do an extra flip.
tex_flip = 0;
#endif // defined(USE_OZONE)
glUniform1i(glGetUniformLocation(program_, "tex_flip"), tex_flip);
// Frames that will be returned to the client (via the no_longer_needed_cb) // Frames that will be returned to the client (via the no_longer_needed_cb)
// after this vector falls out of scope at the end of this method. We need // after this vector falls out of scope at the end of this method. We need
......
...@@ -156,6 +156,15 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { ...@@ -156,6 +156,15 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
static scoped_refptr<GLSurface> CreateViewGLSurface( static scoped_refptr<GLSurface> CreateViewGLSurface(
gfx::AcceleratedWidget window); gfx::AcceleratedWidget window);
#if defined(USE_OZONE)
// Create a GL surface that renders directly into a window with surfaceless
// semantics - there is no default framebuffer and the primary surface must
// be presented as an overlay. If surfaceless mode is not supported or
// enabled it will return a null pointer.
static scoped_refptr<GLSurface> CreateSurfacelessViewGLSurface(
gfx::AcceleratedWidget window);
#endif // defined(USE_OZONE)
// Create a GL surface used for offscreen rendering. // Create a GL surface used for offscreen rendering.
static scoped_refptr<GLSurface> CreateOffscreenGLSurface( static scoped_refptr<GLSurface> CreateOffscreenGLSurface(
const gfx::Size& size); const gfx::Size& size);
......
...@@ -4,16 +4,20 @@ ...@@ -4,16 +4,20 @@
#include "ui/gl/gl_surface.h" #include "ui/gl/gl_surface.h"
#include "base/bind.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gl/gl_context.h" #include "ui/gl/gl_context.h"
#include "ui/gl/gl_image.h" #include "ui/gl/gl_image.h"
#include "ui/gl/gl_image_linux_dma_buffer.h"
#include "ui/gl/gl_implementation.h" #include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface_egl.h" #include "ui/gl/gl_surface_egl.h"
#include "ui/gl/gl_surface_osmesa.h" #include "ui/gl/gl_surface_osmesa.h"
#include "ui/gl/gl_surface_stub.h" #include "ui/gl/gl_surface_stub.h"
#include "ui/gl/scoped_binders.h"
#include "ui/gl/scoped_make_current.h" #include "ui/gl/scoped_make_current.h"
#include "ui/ozone/public/native_pixmap.h"
#include "ui/ozone/public/surface_factory_ozone.h" #include "ui/ozone/public/surface_factory_ozone.h"
#include "ui/ozone/public/surface_ozone_egl.h" #include "ui/ozone/public/surface_ozone_egl.h"
...@@ -157,7 +161,7 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { ...@@ -157,7 +161,7 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
return SwapBuffersAsync(callback); return SwapBuffersAsync(callback);
} }
private: protected:
~GLSurfaceOzoneSurfaceless() override { ~GLSurfaceOzoneSurfaceless() override {
Destroy(); // EGL surface must be destroyed before SurfaceOzone Destroy(); // EGL surface must be destroyed before SurfaceOzone
} }
...@@ -196,6 +200,155 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { ...@@ -196,6 +200,155 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
}; };
// This provides surface-like semantics implemented through surfaceless.
// A framebuffer is bound automatically.
class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl
: public GLSurfaceOzoneSurfaceless {
public:
GLSurfaceOzoneSurfacelessSurfaceImpl(
scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
AcceleratedWidget widget)
: GLSurfaceOzoneSurfaceless(ozone_surface.Pass(), widget),
fbo_(0),
current_surface_(0) {
for (auto& texture : textures_)
texture = 0;
}
unsigned int GetBackingFrameBufferObject() override { return fbo_; }
bool OnMakeCurrent(GLContext* context) override {
if (!fbo_) {
glGenFramebuffersEXT(1, &fbo_);
if (!fbo_)
return false;
glGenTextures(arraysize(textures_), textures_);
if (!CreatePixmaps())
return false;
}
BindFramebuffer();
glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
return SurfacelessEGL::OnMakeCurrent(context);
}
bool Resize(const gfx::Size& size) override {
if (size == GetSize())
return true;
return GLSurfaceOzoneSurfaceless::Resize(size) && CreatePixmaps();
}
bool SupportsPostSubBuffer() override { return false; }
bool SwapBuffers() override {
if (!images_[current_surface_]->ScheduleOverlayPlane(
widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
gfx::Rect(GetSize()), gfx::RectF(1, 1)))
return false;
if (!GLSurfaceOzoneSurfaceless::SwapBuffers())
return false;
current_surface_ ^= 1;
BindFramebuffer();
return true;
}
bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
if (!images_[current_surface_]->ScheduleOverlayPlane(
widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
gfx::Rect(GetSize()), gfx::RectF(1, 1)))
return false;
if (!GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback))
return false;
current_surface_ ^= 1;
BindFramebuffer();
return true;
}
void Destroy() override {
GLContext* current_context = GLContext::GetCurrent();
DCHECK(current_context && current_context->IsCurrent(this));
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
if (fbo_) {
glDeleteTextures(arraysize(textures_), textures_);
for (auto& texture : textures_)
texture = 0;
glDeleteFramebuffersEXT(1, &fbo_);
fbo_ = 0;
}
for (auto image : images_) {
if (image)
image->Destroy(true);
}
}
private:
class SurfaceImage : public GLImageLinuxDMABuffer {
public:
SurfaceImage(const gfx::Size& size, unsigned internalformat)
: GLImageLinuxDMABuffer(size, internalformat) {}
bool Initialize(scoped_refptr<ui::NativePixmap> pixmap,
gfx::GpuMemoryBuffer::Format format) {
base::FileDescriptor handle(pixmap->GetDmaBufFd(), false);
if (!GLImageLinuxDMABuffer::Initialize(handle, format,
pixmap->GetDmaBufPitch()))
return false;
pixmap_ = pixmap;
return true;
}
bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
int z_order,
gfx::OverlayTransform transform,
const gfx::Rect& bounds_rect,
const gfx::RectF& crop_rect) override {
return ui::SurfaceFactoryOzone::GetInstance()->ScheduleOverlayPlane(
widget, z_order, transform, pixmap_, bounds_rect, crop_rect);
}
private:
scoped_refptr<ui::NativePixmap> pixmap_;
};
~GLSurfaceOzoneSurfacelessSurfaceImpl() override {
DCHECK(!fbo_);
for (size_t i = 0; i < arraysize(textures_); i++)
DCHECK(!textures_[i]) << "texture " << i << " not released";
}
void BindFramebuffer() {
ScopedFrameBufferBinder fb(fbo_);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textures_[current_surface_], 0);
}
bool CreatePixmaps() {
if (!fbo_)
return true;
for (size_t i = 0; i < arraysize(textures_); i++) {
scoped_refptr<ui::NativePixmap> pixmap =
ui::SurfaceFactoryOzone::GetInstance()->CreateNativePixmap(
widget_, GetSize(), ui::SurfaceFactoryOzone::RGBA_8888,
ui::SurfaceFactoryOzone::SCANOUT);
if (!pixmap)
return false;
scoped_refptr<SurfaceImage> image = new SurfaceImage(GetSize(), GL_RGBA);
if (!image->Initialize(pixmap, gfx::GpuMemoryBuffer::Format::BGRA_8888))
return false;
images_[i] = image;
// Bind image to texture.
ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
return false;
}
return true;
}
GLuint fbo_;
GLuint textures_[2];
scoped_refptr<GLImage> images_[2];
int current_surface_;
DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl);
};
} // namespace } // namespace
// static // static
...@@ -216,6 +369,27 @@ bool GLSurface::InitializeOneOffInternal() { ...@@ -216,6 +369,27 @@ bool GLSurface::InitializeOneOffInternal() {
} }
} }
// static
scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
gfx::AcceleratedWidget window) {
if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
window != kNullAcceleratedWidget &&
GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) {
scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
ui::SurfaceFactoryOzone::GetInstance()
->CreateSurfacelessEGLSurfaceForWidget(window);
if (!surface_ozone)
return nullptr;
scoped_refptr<GLSurface> surface;
surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
if (surface->Initialize())
return surface;
}
return nullptr;
}
// static // static
scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
gfx::AcceleratedWidget window) { gfx::AcceleratedWidget window) {
...@@ -236,7 +410,8 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( ...@@ -236,7 +410,8 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
->CreateSurfacelessEGLSurfaceForWidget(window); ->CreateSurfacelessEGLSurfaceForWidget(window);
if (!surface_ozone) if (!surface_ozone)
return NULL; return NULL;
surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window); surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(surface_ozone.Pass(),
window);
} else { } else {
scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone = scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget( ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment