// Copyright 2014 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. #include "ui/gl/gl_surface.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "ui/gfx/native_widget_types.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_osmesa.h" #include "ui/gl/gl_surface_stub.h" #include "ui/gl/scoped_make_current.h" #include "ui/ozone/public/surface_factory_ozone.h" #include "ui/ozone/public/surface_ozone_egl.h" namespace gfx { namespace { // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL { public: GLSurfaceOzoneEGL(scoped_ptr ozone_surface, AcceleratedWidget widget) : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()), ozone_surface_(ozone_surface.Pass()), widget_(widget) {} virtual bool Resize(const gfx::Size& size) OVERRIDE { if (!ozone_surface_->ResizeNativeWindow(size)) { if (!ReinitializeNativeSurface() || !ozone_surface_->ResizeNativeWindow(size)) return false; } return NativeViewGLSurfaceEGL::Resize(size); } virtual bool SwapBuffers() OVERRIDE { if (!NativeViewGLSurfaceEGL::SwapBuffers()) return false; return ozone_surface_->OnSwapBuffers(); } private: virtual ~GLSurfaceOzoneEGL() { Destroy(); // EGL surface must be destroyed before SurfaceOzone } bool ReinitializeNativeSurface() { scoped_ptr scoped_make_current; GLContext* current_context = GLContext::GetCurrent(); bool was_current = current_context && current_context->IsCurrent(this); if (was_current) { scoped_make_current.reset( new ui::ScopedMakeCurrent(current_context, this)); } Destroy(); ozone_surface_ = ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget( widget_).Pass(); if (!ozone_surface_) { LOG(ERROR) << "Failed to create native surface."; return false; } window_ = ozone_surface_->GetNativeWindow(); scoped_ptr vsync_provider = ozone_surface_->CreateVSyncProvider(); if (!Initialize(vsync_provider.Pass())) { LOG(ERROR) << "Failed to initialize."; return false; } return true; } // The native surface. Deleting this is allowed to free the EGLNativeWindow. scoped_ptr ozone_surface_; AcceleratedWidget widget_; DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL); }; } // namespace // static bool GLSurface::InitializeOneOffInternal() { switch (GetGLImplementation()) { case kGLImplementationEGLGLES2: if (!GLSurfaceEGL::InitializeOneOff()) { LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed."; return false; } return true; case kGLImplementationOSMesaGL: case kGLImplementationMockGL: return true; default: return false; } } // static scoped_refptr GLSurface::CreateViewGLSurface( gfx::AcceleratedWidget window) { if (GetGLImplementation() == kGLImplementationOSMesaGL) { scoped_refptr surface(new GLSurfaceOSMesaHeadless()); if (!surface->Initialize()) return NULL; return surface; } DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2); if (window != kNullAcceleratedWidget) { scoped_ptr surface_ozone = ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget( window); if (!surface_ozone) return NULL; scoped_ptr vsync_provider = surface_ozone->CreateVSyncProvider(); scoped_refptr surface = new GLSurfaceOzoneEGL(surface_ozone.Pass(), window); if (!surface->Initialize(vsync_provider.Pass())) return NULL; return surface; } else { scoped_refptr surface = new GLSurfaceStub(); if (surface->Initialize()) return surface; } return NULL; } // static scoped_refptr GLSurface::CreateOffscreenGLSurface( const gfx::Size& size) { switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { scoped_refptr surface(new GLSurfaceOSMesa(1, size)); if (!surface->Initialize()) return NULL; return surface; } case kGLImplementationEGLGLES2: { scoped_refptr surface; if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() && (size.width() == 0 && size.height() == 0)) { surface = new SurfacelessEGL(size); } else surface = new PbufferGLSurfaceEGL(size); if (!surface->Initialize()) return NULL; return surface; } default: NOTREACHED(); return NULL; } } EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay(); } } // namespace gfx