| // 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/public/cpp/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/notification_surface.h" |
| #include "components/exo/notification_surface_manager.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" |
| #include "ui/wm/core/coordinate_conversion.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 { |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Display, public: |
| |
| Display::Display() : notification_surface_manager_(nullptr) {} |
| |
| Display::Display(NotificationSurfaceManager* notification_surface_manager) |
| : notification_surface_manager_(notification_surface_manager) {} |
| |
| 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::MakeUnique<SharedMemory>(handle); |
| } |
| |
| #if defined(USE_OZONE) |
| std::unique_ptr<Buffer> Display::CreateLinuxDMABufBuffer( |
| const gfx::Size& size, |
| gfx::BufferFormat format, |
| const std::vector<gfx::NativePixmapPlane>& planes, |
| std::vector<base::ScopedFD>&& fds) { |
| TRACE_EVENT1("exo", "Display::CreateLinuxDMABufBuffer", "size", |
| size.ToString()); |
| |
| gfx::GpuMemoryBufferHandle handle; |
| handle.type = gfx::OZONE_NATIVE_PIXMAP; |
| for (auto& fd : fds) |
| handle.native_pixmap_handle.fds.emplace_back(std::move(fd)); |
| |
| for (auto& plane : planes) |
| handle.native_pixmap_handle.planes.push_back(plane); |
| |
| 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::RGBA_8888, |
| gfx::BufferFormat::RGBX_8888}; |
| bool is_overlay_candidate = |
| std::find(std::begin(kOverlayFormats), std::end(kOverlayFormats), |
| format) != std::end(kOverlayFormats); |
| |
| return base::MakeUnique<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::MakeUnique<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->window()->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 in screen coordinates. |
| gfx::Point origin = position; |
| wm::ConvertPointToScreen( |
| ShellSurface::GetMainSurface(parent->GetWidget()->GetNativeWindow()) |
| ->window(), |
| &origin); |
| gfx::Rect initial_bounds(origin, gfx::Size(1, 1)); |
| |
| return base::MakeUnique<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::MakeUnique<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->window()->Contains(parent->window())) { |
| 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::MakeUnique<SubSurface>(surface, parent); |
| } |
| |
| std::unique_ptr<NotificationSurface> Display::CreateNotificationSurface( |
| Surface* surface, |
| const std::string& notification_id) { |
| TRACE_EVENT2("exo", "Display::CreateNotificationSurface", "surface", |
| surface->AsTracedValue(), "notification_id", notification_id); |
| |
| if (!notification_surface_manager_ || |
| notification_surface_manager_->GetSurface(notification_id)) { |
| DLOG(ERROR) << "Invalid notification id, id=" << notification_id; |
| return nullptr; |
| } |
| |
| return base::MakeUnique<NotificationSurface>(notification_surface_manager_, |
| surface, notification_id); |
| } |
| |
| } // namespace exo |