Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Unified Diff: ui/ozone/platform/drm/gpu/gbm_surfaceless.cc

Issue 2165303002: Convert Ozone GBM to use new surface API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ozone_impl
Patch Set: Add missing dep. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/ozone/platform/drm/gpu/gbm_surfaceless.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
diff --git a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 9631d28229886a1d6394be62c512613af9027bfa..2fe3306e323c97594ca1fd7af49bbc1cdee3eba3 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2016 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.
@@ -6,11 +6,12 @@
#include <utility>
+#include "base/bind.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/threading/worker_pool.h"
#include "base/trace_event/trace_event.h"
-#include "third_party/khronos/EGL/egl.h"
#include "ui/ozone/common/egl_util.h"
-#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
@@ -18,67 +19,232 @@
namespace ui {
-GbmSurfaceless::GbmSurfaceless(std::unique_ptr<DrmWindowProxy> window,
- GbmSurfaceFactory* surface_manager)
- : window_(std::move(window)), surface_manager_(surface_manager) {
- surface_manager_->RegisterSurface(window_->widget(), this);
+namespace {
+
+void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
+ eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+ EGL_FOREVER_KHR);
}
-GbmSurfaceless::~GbmSurfaceless() {
- surface_manager_->UnregisterSurface(window_->widget());
+} // namespace
+
+GbmSurfaceless::GbmSurfaceless(GbmSurfaceFactory* surface_factory,
+ std::unique_ptr<DrmWindowProxy> window,
+ gfx::AcceleratedWidget widget)
+ : SurfacelessEGL(gfx::Size()),
+ surface_factory_(surface_factory),
+ window_(std::move(window)),
+ widget_(widget),
+ has_implicit_external_sync_(
+ HasEGLExtension("EGL_ARM_implicit_external_sync")),
+ has_image_flush_external_(
+ HasEGLExtension("EGL_EXT_image_flush_external")),
+ weak_factory_(this) {
+ surface_factory_->RegisterSurface(window_->widget(), this);
+ unsubmitted_frames_.push_back(new PendingFrame());
}
void GbmSurfaceless::QueueOverlayPlane(const OverlayPlane& plane) {
planes_.push_back(plane);
}
-intptr_t GbmSurfaceless::GetNativeWindow() {
+bool GbmSurfaceless::Initialize(gl::GLSurface::Format format) {
+ if (!SurfacelessEGL::Initialize(format))
+ return false;
+ vsync_provider_ = base::MakeUnique<DrmVSyncProvider>(window_.get());
+ if (!vsync_provider_)
+ return false;
+ return true;
+}
+
+gfx::SwapResult GbmSurfaceless::SwapBuffers() {
NOTREACHED();
- return 0;
+ return gfx::SwapResult::SWAP_FAILED;
}
-bool GbmSurfaceless::ResizeNativeWindow(const gfx::Size& viewport_size) {
+bool GbmSurfaceless::ScheduleOverlayPlane(int z_order,
+ gfx::OverlayTransform transform,
+ gl::GLImage* image,
+ const gfx::Rect& bounds_rect,
+ const gfx::RectF& crop_rect) {
+ unsubmitted_frames_.back()->overlays.push_back(
+ gl::GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect));
return true;
}
-bool GbmSurfaceless::OnSwapBuffers() {
- NOTREACHED();
+bool GbmSurfaceless::IsOffscreen() {
return false;
}
-void GbmSurfaceless::OnSwapBuffersAsync(
+gfx::VSyncProvider* GbmSurfaceless::GetVSyncProvider() {
+ return vsync_provider_.get();
+}
+
+bool GbmSurfaceless::SupportsAsyncSwap() {
+ return true;
+}
+
+bool GbmSurfaceless::SupportsPostSubBuffer() {
+ return true;
+}
+
+gfx::SwapResult GbmSurfaceless::PostSubBuffer(int x,
+ int y,
+ int width,
+ int height) {
+ // The actual sub buffer handling is handled at higher layers.
+ NOTREACHED();
+ return gfx::SwapResult::SWAP_FAILED;
+}
+
+void GbmSurfaceless::SwapBuffersAsync(const SwapCompletionCallback& callback) {
+ TRACE_EVENT0("drm", "GbmSurfaceless::SwapBuffersAsync");
+ // If last swap failed, don't try to schedule new ones.
+ if (!last_swap_buffers_result_) {
+ callback.Run(gfx::SwapResult::SWAP_FAILED);
+ return;
+ }
+
+ glFlush();
+ unsubmitted_frames_.back()->Flush();
+
+ SwapCompletionCallback surface_swap_callback = base::Bind(
+ &GbmSurfaceless::SwapCompleted, weak_factory_.GetWeakPtr(), callback);
+
+ PendingFrame* frame = unsubmitted_frames_.back();
+ frame->callback = surface_swap_callback;
+ unsubmitted_frames_.push_back(new PendingFrame());
+
+ // TODO: the following should be replaced by a per surface flush as it gets
+ // implemented in GL drivers.
+ if (has_implicit_external_sync_ || has_image_flush_external_) {
+ EGLSyncKHR fence = InsertFence(has_implicit_external_sync_);
+ if (!fence) {
+ callback.Run(gfx::SwapResult::SWAP_FAILED);
+ return;
+ }
+
+ base::Closure fence_wait_task =
+ base::Bind(&WaitForFence, GetDisplay(), fence);
+
+ base::Closure fence_retired_callback =
+ base::Bind(&GbmSurfaceless::FenceRetired, weak_factory_.GetWeakPtr(),
+ fence, frame);
+
+ base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
+ fence_retired_callback, false);
+ return; // Defer frame submission until fence signals.
+ }
+
+ frame->ready = true;
+ SubmitFrame();
+}
+
+void GbmSurfaceless::PostSubBufferAsync(
+ int x,
+ int y,
+ int width,
+ int height,
const SwapCompletionCallback& callback) {
- TRACE_EVENT0("drm", "GbmSurfaceless::OnSwapBuffersAsync");
- window_->SchedulePageFlip(planes_, callback);
- planes_.clear();
+ // The actual sub buffer handling is handled at higher layers.
+ SwapBuffersAsync(callback);
}
-std::unique_ptr<gfx::VSyncProvider> GbmSurfaceless::CreateVSyncProvider() {
- return base::WrapUnique(new DrmVSyncProvider(window_.get()));
+EGLConfig GbmSurfaceless::GetConfig() {
+ if (!config_) {
+ EGLint config_attribs[] = {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_DONT_CARE,
+ EGL_NONE};
+ config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
+ }
+ return config_;
}
-bool GbmSurfaceless::IsUniversalDisplayLinkDevice() {
- return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish();
+GbmSurfaceless::~GbmSurfaceless() {
+ Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
+ surface_factory_->UnregisterSurface(window_->widget());
+}
+
+GbmSurfaceless::PendingFrame::PendingFrame() {}
+
+GbmSurfaceless::PendingFrame::~PendingFrame() {}
+
+bool GbmSurfaceless::PendingFrame::ScheduleOverlayPlanes(
+ gfx::AcceleratedWidget widget) {
+ for (const auto& overlay : overlays)
+ if (!overlay.ScheduleOverlayPlane(widget))
+ return false;
+ return true;
+}
+
+void GbmSurfaceless::PendingFrame::Flush() {
+ for (const auto& overlay : overlays)
+ overlay.Flush();
+}
+
+void GbmSurfaceless::SubmitFrame() {
+ DCHECK(!unsubmitted_frames_.empty());
+
+ if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
+ std::unique_ptr<PendingFrame> frame(unsubmitted_frames_.front());
+ unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
+ swap_buffers_pending_ = true;
+
+ if (!frame->ScheduleOverlayPlanes(widget_)) {
+ // |callback| is a wrapper for SwapCompleted(). Call it to properly
+ // propagate the failed state.
+ frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
+ return;
+ }
+
+ if (IsUniversalDisplayLinkDevice())
+ glFinish();
+
+ window_->SchedulePageFlip(planes_, frame->callback);
+ planes_.clear();
+ }
}
-void* /* EGLConfig */ GbmSurfaceless::GetEGLSurfaceConfig(
- const EglConfigCallbacks& egl) {
- EGLint config_attribs[] = {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_DONT_CARE,
- EGL_NONE};
- return ChooseEGLConfig(egl, config_attribs);
+EGLSyncKHR GbmSurfaceless::InsertFence(bool implicit) {
+ const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
+ EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
+ EGL_NONE};
+ return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR,
+ implicit ? attrib_list : NULL);
+}
+
+void GbmSurfaceless::FenceRetired(EGLSyncKHR fence, PendingFrame* frame) {
+ eglDestroySyncKHR(GetDisplay(), fence);
+ frame->ready = true;
+ SubmitFrame();
+}
+
+void GbmSurfaceless::SwapCompleted(const SwapCompletionCallback& callback,
+ gfx::SwapResult result) {
+ callback.Run(result);
+ swap_buffers_pending_ = false;
+ if (result == gfx::SwapResult::SWAP_FAILED) {
+ last_swap_buffers_result_ = false;
+ return;
+ }
+
+ SubmitFrame();
+}
+
+bool GbmSurfaceless::IsUniversalDisplayLinkDevice() {
+ return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish();
}
} // namespace ui
« no previous file with comments | « ui/ozone/platform/drm/gpu/gbm_surfaceless.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698