| 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..601350b1997ae0540d923800dfd3b1df3cf8109a
|
| --- /dev/null
|
| +++ b/ui/gfx/ozone/dri/gbm_surface_factory.cc
|
| @@ -0,0 +1,253 @@
|
| +// 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 <EGL/egl.h>
|
| +//#include <EGL/eglext.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;
|
| +}
|
| +
|
| +struct NativeBufferInfo {
|
| + gfx::Size size;
|
| + uint32_t fb;
|
| +};
|
| +
|
| +void NativeBufferInfoDestroy(gbm_bo* buffer, void* data) {
|
| + NativeBufferInfo* bd = static_cast<NativeBufferInfo*>(data);
|
| + delete bd;
|
| +}
|
| +
|
| +} // 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;
|
| +}
|
| +
|
| +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;
|
| +}
|
| +
|
| +gfx::VSyncProvider* GbmSurfaceFactory::GetVSyncProvider(
|
| + gfx::AcceleratedWidget w) {
|
| + return NULL;
|
| +}
|
| +
|
| +gfx::AcceleratedWidget GbmSurfaceFactory::CreateNativeBuffer(
|
| + gfx::Size size,
|
| + unsigned internalformat) {
|
| + gbm_bo* bo = gbm_bo_create(device_,
|
| + size.width(),
|
| + size.height(),
|
| + // GBM_BO_FORMAT_XRGB8888,
|
| + GBM_FORMAT_ARGB8888,
|
| + GBM_BO_USE_SCANOUT |
|
| + // GBM_BO_USE_CURSOR_64X64 |
|
| + GBM_BO_USE_RENDERING |
|
| + // GBM_BO_USE_WRITE |
|
| + 0);
|
| + NativeBufferInfo* info = new NativeBufferInfo;
|
| + info->size = size;
|
| + uint32_t bo_handle = gbm_bo_get_handle(bo).u32;
|
| + uint32_t stride = gbm_bo_get_stride(bo);
|
| + controller_->AddFramebuffer(24, 32, stride, bo_handle, &info->fb);
|
| + gbm_bo_set_user_data(bo, info, NativeBufferInfoDestroy);
|
| +
|
| + return reinterpret_cast<gfx::AcceleratedWidget>(bo);
|
| +}
|
| +
|
| +void GbmSurfaceFactory::SetOverlayPlane(int plane_id,
|
| + gfx::AcceleratedWidget handle,
|
| + const gfx::Rect& bounds) {
|
| + gbm_bo* bo = reinterpret_cast<gbm_bo*>(handle);
|
| + NativeBufferInfo* info =
|
| + static_cast<NativeBufferInfo*>(gbm_bo_get_user_data(bo));
|
| +
|
| + controller_->SetOverlayPlaneInfo(bounds, info->size, info->fb);
|
| +}
|
| +
|
| +
|
| +void GbmSurfaceFactory::CheckOverlaySupport(SurfaceCandidateList* surfaces) {
|
| + if ((surfaces->size() == 1 || surfaces->size() == 2) &&
|
| + (surfaces->at(0).format == RGBA || surfaces->at(0).format == RGBA)) {
|
| + surfaces->at(0).overlay_handled = true;
|
| + }
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// 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
|
|
|