blob: fe356978d130854df39c4e217a55e608035b5b64 [file] [log] [blame]
// Copyright 2015 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 "components/exo/display.h"
#include <iterator>
#include <utility>
#include "ash/common/shell_window_ids.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "components/exo/shared_memory.h"
#include "components/exo/shell_surface.h"
#include "components/exo/sub_surface.h"
#include "components/exo/surface.h"
#include "ui/views/widget/widget.h"
#if defined(USE_OZONE)
#include <GLES2/gl2extchromium.h>
#include "components/exo/buffer.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/aura/env.h"
#endif
namespace exo {
const char kUseExoSurfaceLayer[] = "use-exo-surface-layer";
////////////////////////////////////////////////////////////////////////////////
// Display, public:
Display::Display() {
Surface::SetUseSurfaceLayer(
base::CommandLine::ForCurrentProcess()->HasSwitch(kUseExoSurfaceLayer));
}
Display::~Display() {}
std::unique_ptr<Surface> Display::CreateSurface() {
TRACE_EVENT0("exo", "Display::CreateSurface");
return base::WrapUnique(new Surface);
}
std::unique_ptr<SharedMemory> Display::CreateSharedMemory(
const base::SharedMemoryHandle& handle,
size_t size) {
TRACE_EVENT1("exo", "Display::CreateSharedMemory", "size", size);
if (!base::SharedMemory::IsHandleValid(handle))
return nullptr;
return base::WrapUnique(new SharedMemory(handle));
}
#if defined(USE_OZONE)
std::unique_ptr<Buffer> Display::CreateLinuxDMABufBuffer(
base::ScopedFD fd,
const gfx::Size& size,
gfx::BufferFormat format,
int stride) {
TRACE_EVENT1("exo", "Display::CreateLinuxDMABufBuffer", "size",
size.ToString());
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::OZONE_NATIVE_PIXMAP;
handle.native_pixmap_handle.fds.emplace_back(
base::FileDescriptor(std::move(fd)));
handle.native_pixmap_handle.strides_and_offsets.emplace_back(stride, 0);
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
aura::Env::GetInstance()
->context_factory()
->GetGpuMemoryBufferManager()
->CreateGpuMemoryBufferFromHandle(handle, size, format);
if (!gpu_memory_buffer) {
LOG(ERROR) << "Failed to create GpuMemoryBuffer from handle";
return nullptr;
}
// Using zero-copy for optimal performance.
bool use_zero_copy = true;
// List of overlay formats that are known to be supported.
// TODO(reveman): Determine this at runtime.
const gfx::BufferFormat kOverlayFormats[] = {gfx::BufferFormat::BGRX_8888};
bool is_overlay_candidate =
std::find(std::begin(kOverlayFormats), std::end(kOverlayFormats),
format) != std::end(kOverlayFormats);
return base::WrapUnique(new Buffer(
std::move(gpu_memory_buffer), GL_TEXTURE_EXTERNAL_OES,
// COMMANDS_COMPLETED queries are required by native pixmaps.
GL_COMMANDS_COMPLETED_CHROMIUM, use_zero_copy, is_overlay_candidate));
}
#endif
std::unique_ptr<ShellSurface> Display::CreateShellSurface(Surface* surface) {
TRACE_EVENT1("exo", "Display::CreateShellSurface", "surface",
surface->AsTracedValue());
if (surface->HasSurfaceDelegate()) {
DLOG(ERROR) << "Surface has already been assigned a role";
return nullptr;
}
return base::WrapUnique(
new ShellSurface(surface, nullptr, gfx::Rect(), true /* activatable */,
ash::kShellWindowId_DefaultContainer));
}
std::unique_ptr<ShellSurface> Display::CreatePopupShellSurface(
Surface* surface,
ShellSurface* parent,
const gfx::Point& position) {
TRACE_EVENT2("exo", "Display::CreatePopupShellSurface", "surface",
surface->AsTracedValue(), "parent", parent->AsTracedValue());
if (surface->Contains(parent->GetWidget()->GetNativeWindow())) {
DLOG(ERROR) << "Parent is contained within surface's hierarchy";
return nullptr;
}
if (surface->HasSurfaceDelegate()) {
DLOG(ERROR) << "Surface has already been assigned a role";
return nullptr;
}
// Determine the initial bounds for popup. |position| is relative to the
// parent's main surface origin and initial bounds are relative to the
// container origin.
gfx::Rect initial_bounds(position, gfx::Size(1, 1));
aura::Window::ConvertRectToTarget(
ShellSurface::GetMainSurface(parent->GetWidget()->GetNativeWindow()),
parent->GetWidget()->GetNativeWindow()->parent(), &initial_bounds);
return base::WrapUnique(
new ShellSurface(surface, parent, initial_bounds, false /* activatable */,
ash::kShellWindowId_DefaultContainer));
}
std::unique_ptr<ShellSurface> Display::CreateRemoteShellSurface(
Surface* surface,
int container) {
TRACE_EVENT2("exo", "Display::CreateRemoteShellSurface", "surface",
surface->AsTracedValue(), "container", container);
if (surface->HasSurfaceDelegate()) {
DLOG(ERROR) << "Surface has already been assigned a role";
return nullptr;
}
return base::WrapUnique(new ShellSurface(surface, nullptr, gfx::Rect(1, 1),
true /* activatable */, container));
}
std::unique_ptr<SubSurface> Display::CreateSubSurface(Surface* surface,
Surface* parent) {
TRACE_EVENT2("exo", "Display::CreateSubSurface", "surface",
surface->AsTracedValue(), "parent", parent->AsTracedValue());
if (surface->Contains(parent)) {
DLOG(ERROR) << "Parent is contained within surface's hierarchy";
return nullptr;
}
if (surface->HasSurfaceDelegate()) {
DLOG(ERROR) << "Surface has already been assigned a role";
return nullptr;
}
return base::WrapUnique(new SubSurface(surface, parent));
}
} // namespace exo