blob: 5eb93fc427ee7cc6355427436f2bcaa356714786 [file] [log] [blame]
// 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/ozone/platform/dri/gbm_surface_factory.h"
#include <EGL/egl.h>
#include <gbm.h>
#include "base/files/file_path.h"
#include "ui/ozone/platform/dri/buffer_data.h"
#include "ui/ozone/platform/dri/dri_vsync_provider.h"
#include "ui/ozone/platform/dri/gbm_surface.h"
#include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/scanout_surface.h"
#include "ui/ozone/platform/dri/screen_manager.h"
#include "ui/ozone/public/surface_ozone_egl.h"
namespace ui {
namespace {
class GbmSurfaceAdapter : public ui::SurfaceOzoneEGL {
public:
GbmSurfaceAdapter(const base::WeakPtr<HardwareDisplayController>& controller);
virtual ~GbmSurfaceAdapter();
// SurfaceOzoneEGL:
virtual intptr_t GetNativeWindow() OVERRIDE;
virtual bool ResizeNativeWindow(const gfx::Size& viewport_size) OVERRIDE;
virtual bool OnSwapBuffers() OVERRIDE;
virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE;
private:
base::WeakPtr<HardwareDisplayController> controller_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceAdapter);
};
GbmSurfaceAdapter::GbmSurfaceAdapter(
const base::WeakPtr<HardwareDisplayController>& controller)
: controller_(controller) {}
GbmSurfaceAdapter::~GbmSurfaceAdapter() {}
intptr_t GbmSurfaceAdapter::GetNativeWindow() {
if (!controller_)
return 0;
return reinterpret_cast<intptr_t>(
static_cast<GbmSurface*>(controller_->surface())->native_surface());
}
bool GbmSurfaceAdapter::ResizeNativeWindow(const gfx::Size& viewport_size) {
NOTIMPLEMENTED();
return false;
}
bool GbmSurfaceAdapter::OnSwapBuffers() {
if (!controller_)
return false;
static_cast<GbmSurface*>(controller_->surface())->LockCurrentDrawable();
if (controller_->SchedulePageFlip()) {
controller_->WaitForPageFlipEvent();
return true;
}
return false;
}
scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() {
return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
}
} // namespace
GbmSurfaceFactory::GbmSurfaceFactory(DriWrapper* dri,
gbm_device* device,
ScreenManager* screen_manager)
: DriSurfaceFactory(dri, screen_manager),
device_(device) {}
GbmSurfaceFactory::~GbmSurfaceFactory() {}
intptr_t GbmSurfaceFactory::GetNativeDisplay() {
CHECK(state_ == INITIALIZED);
return reinterpret_cast<intptr_t>(device_);
}
const int32* GbmSurfaceFactory::GetEGLSurfaceProperties(
const int32* desired_list) {
static const int32 kConfigAttribs[] = {
EGL_BUFFER_SIZE, 32,
EGL_ALPHA_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
return kConfigAttribs;
}
bool GbmSurfaceFactory::LoadEGLGLES2Bindings(
AddGLLibraryCallback add_gl_library,
SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
base::NativeLibraryLoadError error;
base::NativeLibrary gles_library = base::LoadNativeLibrary(
base::FilePath("libGLESv2.so.2"),
&error);
if (!gles_library) {
LOG(WARNING) << "Failed to load GLES library: " << error.ToString();
return false;
}
base::NativeLibrary egl_library = base::LoadNativeLibrary(
base::FilePath("libEGL.so.1"),
&error);
if (!egl_library) {
LOG(WARNING) << "Failed to load EGL library: " << error.ToString();
base::UnloadNativeLibrary(gles_library);
return false;
}
GLGetProcAddressProc get_proc_address =
reinterpret_cast<GLGetProcAddressProc>(
base::GetFunctionPointerFromNativeLibrary(
egl_library, "eglGetProcAddress"));
if (!get_proc_address) {
LOG(ERROR) << "eglGetProcAddress not found.";
base::UnloadNativeLibrary(egl_library);
base::UnloadNativeLibrary(gles_library);
return false;
}
set_gl_get_proc_address.Run(get_proc_address);
add_gl_library.Run(egl_library);
add_gl_library.Run(gles_library);
return true;
}
scoped_ptr<ui::SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget(
gfx::AcceleratedWidget w) {
CHECK(state_ == INITIALIZED);
ResetCursor(w);
return scoped_ptr<ui::SurfaceOzoneEGL>(
new GbmSurfaceAdapter(screen_manager_->GetDisplayController(w)));
}
gfx::NativeBufferOzone GbmSurfaceFactory::CreateNativeBuffer(
gfx::Size size,
BufferFormat format) {
uint32_t gbm_format = 0;
switch (format) {
case SurfaceFactoryOzone::UNKNOWN:
return 0;
// TODO(alexst): Setting this to XRGB for now to allow presentation
// as a primary plane but disallowing overlay transparency. Address this
// to allow both use cases.
case SurfaceFactoryOzone::RGBA_8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
case SurfaceFactoryOzone::RGB_888:
gbm_format = GBM_FORMAT_RGB888;
break;
}
gbm_bo* buffer_object =
gbm_bo_create(device_,
size.width(),
size.height(),
gbm_format,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!buffer_object)
return 0;
BufferData* data = BufferData::CreateData(drm_, buffer_object);
DCHECK(data) << "Failed to associate the buffer with the controller";
return reinterpret_cast<gfx::NativeBufferOzone>(buffer_object);
}
} // namespace ui