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

Unified Diff: ui/gfx/ozone/impl/software_surface_factory_ozone.cc

Issue 26849004: [Ozone] Adding a software rendering implementation of SurfaceFactoryOzone (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added comments & fixed corner case Created 7 years, 2 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/gfx/ozone/impl/software_surface_factory_ozone.h ('k') | ui/gfx/ozone/surface_factory_ozone.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/ozone/impl/software_surface_factory_ozone.cc
diff --git a/ui/gfx/ozone/impl/software_surface_factory_ozone.cc b/ui/gfx/ozone/impl/software_surface_factory_ozone.cc
new file mode 100644
index 0000000000000000000000000000000000000000..01904072883eec057c7ea533b7cbbef585251a63
--- /dev/null
+++ b/ui/gfx/ozone/impl/software_surface_factory_ozone.cc
@@ -0,0 +1,282 @@
+// Copyright (c) 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/impl/software_surface_factory_ozone.h"
+
+#include <drm.h>
+#include <errno.h>
+#include <xf86drm.h>
+
+#include "base/message_loop/message_loop.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/ozone/impl/drm_skbitmap_ozone.h"
+#include "ui/gfx/ozone/impl/drm_wrapper_ozone.h"
+#include "ui/gfx/ozone/impl/hardware_display_controller_ozone.h"
+#include "ui/gfx/ozone/impl/software_surface_ozone.h"
+
+namespace gfx {
+
+namespace {
+
+const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
+
+const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
+
+// DRM callback on page flip events. This callback is triggered after the
+// page flip has happened and the backbuffer is now the new frontbuffer
+// The old frontbuffer is no longer used by the hardware and can be used for
+// future draw operations.
+//
+// |device| will contain a reference to the |SoftwareSurfaceOzone| object which
+// the event belongs to.
+//
+// TODO(dnicoara) When we have a FD handler for the DRM calls in the message
+// loop, we can move this function in the handler.
+void HandlePageFlipEvent(int fd,
+ unsigned int frame,
+ unsigned int seconds,
+ unsigned int useconds,
+ void* controller) {
+ static_cast<HardwareDisplayControllerOzone*>(controller)->get_surface()
+ ->SwapBuffers();
+}
+
+uint32_t GetCrtc(int fd, drmModeRes* resources, drmModeConnector* connector) {
+ // If the connector already has an encoder try to re-use.
+ if (connector->encoder_id) {
+ drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoder_id);
+ if (encoder) {
+ if (encoder->crtc_id) {
+ uint32_t crtc = encoder->crtc_id;
+ drmModeFreeEncoder(encoder);
+ return crtc;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ }
+
+ // Try to find an encoder for the connector.
+ for (int i = 0; i < connector->count_encoders; ++i) {
+ drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoders[i]);
+ if (!encoder)
+ continue;
+
+ for (int j = 0; j < resources->count_crtcs; ++j) {
+ // Check if the encoder is compatible with this CRTC
+ if (!(encoder->possible_crtcs & (1 << j)))
+ continue;
+
+ drmModeFreeEncoder(encoder);
+ return resources->crtcs[j];
+ }
+ }
+
+ return 0;
+}
+
+} // namespace
+
+SoftwareSurfaceFactoryOzone::SoftwareSurfaceFactoryOzone()
+ : drm_(),
+ state_(UNINITIALIZED),
+ controller_() {
+}
+
+SoftwareSurfaceFactoryOzone::~SoftwareSurfaceFactoryOzone() {
+ if (state_ == INITIALIZED)
+ ShutdownHardware();
+}
+
+SurfaceFactoryOzone::HardwareState
+SoftwareSurfaceFactoryOzone::InitializeHardware() {
+ CHECK(state_ == UNINITIALIZED);
+
+ // TODO(dnicoara): Short-cut right now. What we want is to look at all the
+ // graphics devices available and select the primary one.
+ drm_.reset(CreateWrapper());
+ if (drm_->get_fd() < 0) {
+ LOG(ERROR) << "Cannot open graphics card '"
+ << kDefaultGraphicsCardPath << "': " << strerror(errno);
+ state_ = FAILED;
+ return state_;
+ }
+
+ state_ = INITIALIZED;
+ return state_;
+}
+
+void SoftwareSurfaceFactoryOzone::ShutdownHardware() {
+ CHECK(state_ == INITIALIZED);
+
+ controller_.reset();
+ drm_.reset();
+
+ state_ = UNINITIALIZED;
+}
+
+gfx::AcceleratedWidget SoftwareSurfaceFactoryOzone::GetAcceleratedWidget() {
+ CHECK(state_ != FAILED);
+
+ // TODO(dnicoara) When there's more information on which display we want,
+ // then we can return the widget associated with the display.
+ // For now just assume we have 1 display device and return it.
+ if (!controller_.get())
+ controller_.reset(new HardwareDisplayControllerOzone());
+
+ // TODO(dnicoara) We only have 1 display for now, so only 1 AcceleratedWidget.
+ // When we'll support multiple displays this needs to be changed to return a
+ // different handle for every display.
+ return kDefaultWidgetHandle;
+}
+
+gfx::AcceleratedWidget SoftwareSurfaceFactoryOzone::RealizeAcceleratedWidget(
+ gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ // TODO(dnicoara) Once we can handle multiple displays this needs to be
+ // changed.
+ CHECK(w == kDefaultWidgetHandle);
+
+ CHECK(controller_->get_state() ==
+ HardwareDisplayControllerOzone::UNASSOCIATED);
+
+ // Until now the controller is just a stub. Initializing it will link it to a
+ // hardware display.
+ if (!InitializeControllerForPrimaryDisplay(drm_.get(), controller_.get())) {
+ LOG(ERROR) << "Failed to initialize controller";
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ // Create a surface suitable for the current controller.
+ SoftwareSurfaceOzone* surface = CreateSurface(controller_.get());
+
+ if (!surface->Initialize()) {
+ delete surface;
+ LOG(ERROR) << "Failed to initialize surface";
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ // Bind the surface to the controller. This will register the backing buffers
+ // with the hardware CRTC such that we can show the buffers. On success the
+ // controller takes ownership of the surface.
rjkroege 2013/10/16 21:42:13 In this kind of complicated ownership transferring
dnicoara 2013/10/17 14:26:19 Done. Thank you for the tip.
+ if (!controller_->BindSurfaceToController(surface)) {
+ delete surface;
+ LOG(ERROR) << "Failed to bind surface to controller";
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ return reinterpret_cast<gfx::AcceleratedWidget>(
+ surface->GetDrawableForWidget());
+}
+
+bool SoftwareSurfaceFactoryOzone::LoadEGLGLES2Bindings() {
+ return false;
+}
+
+bool SoftwareSurfaceFactoryOzone::AttemptToResizeAcceleratedWidget(
+ gfx::AcceleratedWidget w,
+ const gfx::Rect& bounds) {
+ return false;
+}
+
+bool SoftwareSurfaceFactoryOzone::SchedulePageFlip(gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ // TODO(dnicoara) Change this CHECK once we're running with the threaded
+ // compositor.
+ CHECK(base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI);
+
+ // TODO(dnicoara) Once we can handle multiple displays this needs to be
+ // changed.
+ CHECK(w == kDefaultWidgetHandle);
+
+ if (!controller_->SchedulePageFlip())
+ return false;
+
+ // Only wait for the page flip event to finish if it was properly scheduled.
+ //
+ // TODO(dnicoara) This requires the threaded compositor.
+ // The following call will wait for the page flip event to complete. This
+ // means that it will block until the next VSync. Ideally the wait should
+ // happen in the message loop. The message loop would then schedule the next
+ // draw event. Alternatively, the VSyncProvider could be used to schedule the
+ // next draw. Unfortunately, at this point, SoftwareOutputDevice does not
+ // provide any means to use any of the above solutions.
rjkroege 2013/10/16 21:42:13 You still say that WaitForPageFlipEvent needs thre
dnicoara 2013/10/17 14:26:19 Oh, I see where the lack of clarity is. Added more
+ WaitForPageFlipEvent(drm_->get_fd());
+
+ return true;
+}
+
+gfx::VSyncProvider* SoftwareSurfaceFactoryOzone::GetVSyncProvider(
+ gfx::AcceleratedWidget w) {
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SoftwareSurfaceFactoryOzone private
+
+SoftwareSurfaceOzone* SoftwareSurfaceFactoryOzone::CreateSurface(
+ HardwareDisplayControllerOzone* controller) {
+ return new SoftwareSurfaceOzone(controller);
+}
+
+DrmWrapperOzone* SoftwareSurfaceFactoryOzone::CreateWrapper() {
+ return new DrmWrapperOzone(kDefaultGraphicsCardPath);
+}
+
+bool SoftwareSurfaceFactoryOzone::InitializeControllerForPrimaryDisplay(
+ DrmWrapperOzone* drm,
+ HardwareDisplayControllerOzone* controller) {
+ CHECK(state_ == SurfaceFactoryOzone::INITIALIZED);
+
+ drmModeRes* resources = drmModeGetResources(drm->get_fd());
+
+ // Search for an active connector.
+ for (int i = 0; i < resources->count_connectors; ++i) {
+ drmModeConnector* connector = drmModeGetConnector(
+ drm->get_fd(),
+ resources->connectors[i]);
+
+ if (!connector)
+ continue;
+
+ if (connector->connection != DRM_MODE_CONNECTED ||
+ connector->count_modes == 0) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ uint32_t crtc = GetCrtc(drm->get_fd(), resources, connector);
+
+ if (!crtc)
+ continue;
+
+ // TODO(dnicoara) Select one mode for now. In the future we may need to
+ // save all the modes and allow the user to choose a specific mode. Or
+ // even some fullscreen applications may need to change the mode.
+ controller->SetControllerInfo(
+ drm,
+ connector->connector_id,
+ crtc,
+ connector->modes[0]);
+
+ drmModeFreeConnector(connector);
+
+ return true;
+ }
+
+ return false;
+}
+
+void SoftwareSurfaceFactoryOzone::WaitForPageFlipEvent(int fd) {
+ drmEventContext drm_event;
+ drm_event.version = DRM_EVENT_CONTEXT_VERSION;
+ drm_event.page_flip_handler = HandlePageFlipEvent;
+ drm_event.vblank_handler = NULL;
+
+ // Wait for the page-flip to complete.
+ drmHandleEvent(fd, &drm_event);
+}
+
+} // namespace gfx
« no previous file with comments | « ui/gfx/ozone/impl/software_surface_factory_ozone.h ('k') | ui/gfx/ozone/surface_factory_ozone.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698