| Index: ui/gfx/ozone/dri/gbm_surface_factory.cc
|
| diff --git a/ui/gfx/ozone/dri/gbm_surface_factory.cc b/ui/gfx/ozone/dri/gbm_surface_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c7d569d99694c0527ceca884741c26d9e232ebde
|
| --- /dev/null
|
| +++ b/ui/gfx/ozone/dri/gbm_surface_factory.cc
|
| @@ -0,0 +1,206 @@
|
| +// Copyright 2013 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/gfx/ozone/dri/gbm_surface_factory.h"
|
| +
|
| +#include <drm.h>
|
| +#include <errno.h>
|
| +#include <fcntl.h>
|
| +#include <xf86drm.h>
|
| +
|
| +#include "base/files/file_path.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/native_library.h"
|
| +#include "third_party/khronos/EGL/egl.h"
|
| +#include "third_party/khronos/EGL/eglext.h"
|
| +#include "third_party/mesa/src/src/gbm/main/gbm.h"
|
| +#include "third_party/skia/include/core/SkBitmapDevice.h"
|
| +#include "third_party/skia/include/core/SkCanvas.h"
|
| +#include "ui/gfx/ozone/dri/dri_wrapper.h"
|
| +#include "ui/gfx/ozone/dri/gbm_surface.h"
|
| +#include "ui/gfx/ozone/dri/hardware_display_controller.h"
|
| +#include "ui/gfx/ozone/dri/scanout_surface.h"
|
| +
|
| +namespace gfx {
|
| +
|
| +namespace {
|
| +
|
| +typedef EGLBoolean (*eglSwapBuffersProc)(EGLDisplay dpy, EGLSurface surface);
|
| +
|
| +static eglSwapBuffersProc g_native_egl_swap_buffers;
|
| +
|
| +EGLBoolean CustomEglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
|
| + EGLBoolean ret = g_native_egl_swap_buffers(dpy, surface);
|
| +
|
| + // TODO(dnicoara) Once we support multiple displays we need to keep a mapping
|
| + // between |surface| and AcceleratedWidgets such that we can select the
|
| + // widget based on the |surface|.
|
| + if (ret)
|
| + gfx::SurfaceFactoryOzone::GetInstance()->SchedulePageFlip(1);
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +GbmSurfaceFactory::GbmSurfaceFactory()
|
| + : DriSurfaceFactory(),
|
| + device_(NULL) {
|
| +}
|
| +
|
| +GbmSurfaceFactory::~GbmSurfaceFactory() {
|
| + if (state_ == INITIALIZED)
|
| + ShutdownHardware();
|
| +}
|
| +
|
| +SurfaceFactoryOzone::HardwareState
|
| +GbmSurfaceFactory::InitializeHardware() {
|
| + CHECK(state_ == UNINITIALIZED);
|
| +
|
| + if (DriSurfaceFactory::InitializeHardware() != INITIALIZED)
|
| + return state_;
|
| +
|
| + device_ = gbm_create_device(drm_->get_fd());
|
| +
|
| + if (!device_) {
|
| + LOG(ERROR) << "Cannot create GBM device";
|
| + state_ = FAILED;
|
| + return state_;
|
| + }
|
| +
|
| + // TODO(dnicoara) Figure out where this initialization needs to be done.
|
| + if (!controller_.get())
|
| + controller_.reset(new HardwareDisplayController());
|
| +
|
| + state_ = INITIALIZED;
|
| + return state_;
|
| +}
|
| +
|
| +void GbmSurfaceFactory::ShutdownHardware() {
|
| + CHECK(state_ == INITIALIZED);
|
| +
|
| + gbm_device_destroy(device_);
|
| + DriSurfaceFactory::ShutdownHardware();
|
| +}
|
| +
|
| +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) {
|
| + std::string error;
|
| + base::NativeLibrary gles_library = base::LoadNativeLibrary(
|
| + base::FilePath("libGLESv2.so.2"),
|
| + &error);
|
| + if (!gles_library) {
|
| + LOG(WARNING) << "Failed to load GLES library: " << error;
|
| + 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;
|
| + 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;
|
| +}
|
| +
|
| +bool GbmSurfaceFactory::AttemptToResizeAcceleratedWidget(
|
| + gfx::AcceleratedWidget w,
|
| + const gfx::Rect& bounds) {
|
| + return false;
|
| +}
|
| +
|
| +SkCanvas* GbmSurfaceFactory::GetCanvasForWidget(
|
| + gfx::AcceleratedWidget w) {
|
| + CHECK(state_ == INITIALIZED);
|
| + // TODO(dnicoara) Figure out how this is used and unhack.
|
| + static SkBitmapDevice* device = new SkBitmapDevice(
|
| + SkBitmap::kARGB_8888_Config,
|
| + controller_->get_mode().hdisplay,
|
| + controller_->get_mode().vdisplay);
|
| + static SkCanvas canvas(device);
|
| + return &canvas;
|
| +}
|
| +
|
| +bool GbmSurfaceFactory::SchedulePageFlip(gfx::AcceleratedWidget w) {
|
| + CHECK(state_ == INITIALIZED);
|
| +
|
| + // TODO(dnicoara) Once we can handle multiple displays this needs to be
|
| + // changed.
|
| + CHECK(w == 1);
|
| +
|
| + static_cast<GbmSurface*>(controller_->get_surface())
|
| + ->LockCurrentDrawable();
|
| + return DriSurfaceFactory::SchedulePageFlip(w);
|
| +}
|
| +
|
| +void* GbmSurfaceFactory::GetFunctionPointerFromNativeLibrary(
|
| + base::NativeLibrary library,
|
| + const char* name) {
|
| + void* function = SurfaceFactoryOzone::GetFunctionPointerFromNativeLibrary(
|
| + library,
|
| + name);
|
| +
|
| + if (strcmp(name, "eglSwapBuffers") == 0) {
|
| + g_native_egl_swap_buffers = reinterpret_cast<eglSwapBuffersProc>(function);
|
| + function = reinterpret_cast<void*>(CustomEglSwapBuffers);
|
| + }
|
| +
|
| + return function;
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// DriSurfaceFactory private
|
| +
|
| +ScanoutSurface* GbmSurfaceFactory::CreateSurface(
|
| + HardwareDisplayController* controller) {
|
| + return new GbmSurface(controller_.get(), device_);
|
| +}
|
| +
|
| +gfx::AcceleratedWidget GbmSurfaceFactory::GetNativeWidget(
|
| + ScanoutSurface* surface) {
|
| + return reinterpret_cast<gfx::AcceleratedWidget>(
|
| + static_cast<GbmSurface*>(surface)->get_native_surface());
|
| +}
|
| +
|
| +} // namespace gfx
|
|
|