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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/gfx/ozone/impl/software_surface_factory_ozone.h"
6
7 #include <drm.h>
8 #include <errno.h>
9 #include <xf86drm.h>
10
11 #include "base/message_loop/message_loop.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13 #include "third_party/skia/include/core/SkDevice.h"
14 #include "ui/gfx/native_widget_types.h"
15 #include "ui/gfx/ozone/impl/drm_skbitmap_ozone.h"
16 #include "ui/gfx/ozone/impl/drm_wrapper_ozone.h"
17 #include "ui/gfx/ozone/impl/hardware_display_controller_ozone.h"
18 #include "ui/gfx/ozone/impl/software_surface_ozone.h"
19
20 namespace gfx {
21
22 namespace {
23
24 const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
25
26 const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
27
28 // DRM callback on page flip events. This callback is triggered after the
29 // page flip has happened and the backbuffer is now the new frontbuffer
30 // The old frontbuffer is no longer used by the hardware and can be used for
31 // future draw operations.
32 //
33 // |device| will contain a reference to the |SoftwareSurfaceOzone| object which
34 // the event belongs to.
35 //
36 // TODO(dnicoara) When we have a FD handler for the DRM calls in the message
37 // loop, we can move this function in the handler.
38 void HandlePageFlipEvent(int fd,
39 unsigned int frame,
40 unsigned int seconds,
41 unsigned int useconds,
42 void* controller) {
43 static_cast<HardwareDisplayControllerOzone*>(controller)->get_surface()
44 ->SwapBuffers();
45 }
46
47 uint32_t GetCrtc(int fd, drmModeRes* resources, drmModeConnector* connector) {
48 // If the connector already has an encoder try to re-use.
49 if (connector->encoder_id) {
50 drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoder_id);
51 if (encoder) {
52 if (encoder->crtc_id) {
53 uint32_t crtc = encoder->crtc_id;
54 drmModeFreeEncoder(encoder);
55 return crtc;
56 }
57 drmModeFreeEncoder(encoder);
58 }
59 }
60
61 // Try to find an encoder for the connector.
62 for (int i = 0; i < connector->count_encoders; ++i) {
63 drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoders[i]);
64 if (!encoder)
65 continue;
66
67 for (int j = 0; j < resources->count_crtcs; ++j) {
68 // Check if the encoder is compatible with this CRTC
69 if (!(encoder->possible_crtcs & (1 << j)))
70 continue;
71
72 drmModeFreeEncoder(encoder);
73 return resources->crtcs[j];
74 }
75 }
76
77 return 0;
78 }
79
80 } // namespace
81
82 SoftwareSurfaceFactoryOzone::SoftwareSurfaceFactoryOzone()
83 : drm_(),
84 state_(UNINITIALIZED),
85 controller_() {
86 }
87
88 SoftwareSurfaceFactoryOzone::~SoftwareSurfaceFactoryOzone() {
89 if (state_ == INITIALIZED)
90 ShutdownHardware();
91 }
92
93 SurfaceFactoryOzone::HardwareState
94 SoftwareSurfaceFactoryOzone::InitializeHardware() {
95 CHECK(state_ == UNINITIALIZED);
96
97 // TODO(dnicoara): Short-cut right now. What we want is to look at all the
98 // graphics devices available and select the primary one.
99 drm_.reset(CreateWrapper());
100 if (drm_->get_fd() < 0) {
101 LOG(ERROR) << "Cannot open graphics card '"
102 << kDefaultGraphicsCardPath << "': " << strerror(errno);
103 state_ = FAILED;
104 return state_;
105 }
106
107 state_ = INITIALIZED;
108 return state_;
109 }
110
111 void SoftwareSurfaceFactoryOzone::ShutdownHardware() {
112 CHECK(state_ == INITIALIZED);
113
114 controller_.reset();
115 drm_.reset();
116
117 state_ = UNINITIALIZED;
118 }
119
120 gfx::AcceleratedWidget SoftwareSurfaceFactoryOzone::GetAcceleratedWidget() {
121 CHECK(state_ != FAILED);
122
123 // TODO(dnicoara) When there's more information on which display we want,
124 // then we can return the widget associated with the display.
125 // For now just assume we have 1 display device and return it.
126 if (!controller_.get())
127 controller_.reset(new HardwareDisplayControllerOzone());
128
129 // TODO(dnicoara) We only have 1 display for now, so only 1 AcceleratedWidget.
130 // When we'll support multiple displays this needs to be changed to return a
131 // different handle for every display.
132 return kDefaultWidgetHandle;
133 }
134
135 gfx::AcceleratedWidget SoftwareSurfaceFactoryOzone::RealizeAcceleratedWidget(
136 gfx::AcceleratedWidget w) {
137 CHECK(state_ == INITIALIZED);
138 // TODO(dnicoara) Once we can handle multiple displays this needs to be
139 // changed.
140 CHECK(w == kDefaultWidgetHandle);
141
142 CHECK(controller_->get_state() ==
143 HardwareDisplayControllerOzone::UNASSOCIATED);
144
145 // Until now the controller is just a stub. Initializing it will link it to a
146 // hardware display.
147 if (!InitializeControllerForPrimaryDisplay(drm_.get(), controller_.get())) {
148 LOG(ERROR) << "Failed to initialize controller";
149 return gfx::kNullAcceleratedWidget;
150 }
151
152 // Create a surface suitable for the current controller.
153 SoftwareSurfaceOzone* surface = CreateSurface(controller_.get());
154
155 if (!surface->Initialize()) {
156 delete surface;
157 LOG(ERROR) << "Failed to initialize surface";
158 return gfx::kNullAcceleratedWidget;
159 }
160
161 // Bind the surface to the controller. This will register the backing buffers
162 // with the hardware CRTC such that we can show the buffers. On success the
163 // 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.
164 if (!controller_->BindSurfaceToController(surface)) {
165 delete surface;
166 LOG(ERROR) << "Failed to bind surface to controller";
167 return gfx::kNullAcceleratedWidget;
168 }
169
170 return reinterpret_cast<gfx::AcceleratedWidget>(
171 surface->GetDrawableForWidget());
172 }
173
174 bool SoftwareSurfaceFactoryOzone::LoadEGLGLES2Bindings() {
175 return false;
176 }
177
178 bool SoftwareSurfaceFactoryOzone::AttemptToResizeAcceleratedWidget(
179 gfx::AcceleratedWidget w,
180 const gfx::Rect& bounds) {
181 return false;
182 }
183
184 bool SoftwareSurfaceFactoryOzone::SchedulePageFlip(gfx::AcceleratedWidget w) {
185 CHECK(state_ == INITIALIZED);
186 // TODO(dnicoara) Change this CHECK once we're running with the threaded
187 // compositor.
188 CHECK(base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI);
189
190 // TODO(dnicoara) Once we can handle multiple displays this needs to be
191 // changed.
192 CHECK(w == kDefaultWidgetHandle);
193
194 if (!controller_->SchedulePageFlip())
195 return false;
196
197 // Only wait for the page flip event to finish if it was properly scheduled.
198 //
199 // TODO(dnicoara) This requires the threaded compositor.
200 // The following call will wait for the page flip event to complete. This
201 // means that it will block until the next VSync. Ideally the wait should
202 // happen in the message loop. The message loop would then schedule the next
203 // draw event. Alternatively, the VSyncProvider could be used to schedule the
204 // next draw. Unfortunately, at this point, SoftwareOutputDevice does not
205 // 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
206 WaitForPageFlipEvent(drm_->get_fd());
207
208 return true;
209 }
210
211 gfx::VSyncProvider* SoftwareSurfaceFactoryOzone::GetVSyncProvider(
212 gfx::AcceleratedWidget w) {
213 return NULL;
214 }
215
216 ////////////////////////////////////////////////////////////////////////////////
217 // SoftwareSurfaceFactoryOzone private
218
219 SoftwareSurfaceOzone* SoftwareSurfaceFactoryOzone::CreateSurface(
220 HardwareDisplayControllerOzone* controller) {
221 return new SoftwareSurfaceOzone(controller);
222 }
223
224 DrmWrapperOzone* SoftwareSurfaceFactoryOzone::CreateWrapper() {
225 return new DrmWrapperOzone(kDefaultGraphicsCardPath);
226 }
227
228 bool SoftwareSurfaceFactoryOzone::InitializeControllerForPrimaryDisplay(
229 DrmWrapperOzone* drm,
230 HardwareDisplayControllerOzone* controller) {
231 CHECK(state_ == SurfaceFactoryOzone::INITIALIZED);
232
233 drmModeRes* resources = drmModeGetResources(drm->get_fd());
234
235 // Search for an active connector.
236 for (int i = 0; i < resources->count_connectors; ++i) {
237 drmModeConnector* connector = drmModeGetConnector(
238 drm->get_fd(),
239 resources->connectors[i]);
240
241 if (!connector)
242 continue;
243
244 if (connector->connection != DRM_MODE_CONNECTED ||
245 connector->count_modes == 0) {
246 drmModeFreeConnector(connector);
247 continue;
248 }
249
250 uint32_t crtc = GetCrtc(drm->get_fd(), resources, connector);
251
252 if (!crtc)
253 continue;
254
255 // TODO(dnicoara) Select one mode for now. In the future we may need to
256 // save all the modes and allow the user to choose a specific mode. Or
257 // even some fullscreen applications may need to change the mode.
258 controller->SetControllerInfo(
259 drm,
260 connector->connector_id,
261 crtc,
262 connector->modes[0]);
263
264 drmModeFreeConnector(connector);
265
266 return true;
267 }
268
269 return false;
270 }
271
272 void SoftwareSurfaceFactoryOzone::WaitForPageFlipEvent(int fd) {
273 drmEventContext drm_event;
274 drm_event.version = DRM_EVENT_CONTEXT_VERSION;
275 drm_event.page_flip_handler = HandlePageFlipEvent;
276 drm_event.vblank_handler = NULL;
277
278 // Wait for the page-flip to complete.
279 drmHandleEvent(fd, &drm_event);
280 }
281
282 } // namespace gfx
OLDNEW
« 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