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

Side by Side Diff: ui/gfx/ozone/impl/dri_surface_factory.cc

Issue 62953003: Support removal of DRI platform (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix use_ozone=0 Created 7 years, 1 month 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 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/dri_surface_factory.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/dri_skbitmap.h"
16 #include "ui/gfx/ozone/impl/dri_surface.h"
17 #include "ui/gfx/ozone/impl/dri_wrapper.h"
18 #include "ui/gfx/ozone/impl/hardware_display_controller.h"
19
20 namespace gfx {
21
22 namespace {
23
24 const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
25 const char kDPMSProperty[] = "DPMS";
26
27 const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
28
29 // DRM callback on page flip events. This callback is triggered after the
30 // page flip has happened and the backbuffer is now the new frontbuffer
31 // The old frontbuffer is no longer used by the hardware and can be used for
32 // future draw operations.
33 //
34 // |device| will contain a reference to the |DriSurface| object which
35 // the event belongs to.
36 //
37 // TODO(dnicoara) When we have a FD handler for the DRM calls in the message
38 // loop, we can move this function in the handler.
39 void HandlePageFlipEvent(int fd,
40 unsigned int frame,
41 unsigned int seconds,
42 unsigned int useconds,
43 void* controller) {
44 static_cast<HardwareDisplayController*>(controller)->get_surface()
45 ->SwapBuffers();
46 }
47
48 uint32_t GetDriProperty(int fd, drmModeConnector* connector, const char* name) {
49 for (int i = 0; i < connector->count_props; ++i) {
50 drmModePropertyPtr property = drmModeGetProperty(fd, connector->props[i]);
51 if (!property)
52 continue;
53
54 if (strcmp(property->name, name) == 0) {
55 uint32_t id = property->prop_id;
56 drmModeFreeProperty(property);
57 return id;
58 }
59
60 drmModeFreeProperty(property);
61 }
62 return 0;
63 }
64
65 uint32_t GetCrtc(int fd, drmModeRes* resources, drmModeConnector* connector) {
66 // If the connector already has an encoder try to re-use.
67 if (connector->encoder_id) {
68 drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoder_id);
69 if (encoder) {
70 if (encoder->crtc_id) {
71 uint32_t crtc = encoder->crtc_id;
72 drmModeFreeEncoder(encoder);
73 return crtc;
74 }
75 drmModeFreeEncoder(encoder);
76 }
77 }
78
79 // Try to find an encoder for the connector.
80 for (int i = 0; i < connector->count_encoders; ++i) {
81 drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoders[i]);
82 if (!encoder)
83 continue;
84
85 for (int j = 0; j < resources->count_crtcs; ++j) {
86 // Check if the encoder is compatible with this CRTC
87 if (!(encoder->possible_crtcs & (1 << j)))
88 continue;
89
90 drmModeFreeEncoder(encoder);
91 return resources->crtcs[j];
92 }
93 }
94
95 return 0;
96 }
97
98 } // namespace
99
100 DriSurfaceFactory::DriSurfaceFactory()
101 : drm_(),
102 state_(UNINITIALIZED),
103 controller_() {
104 }
105
106 DriSurfaceFactory::~DriSurfaceFactory() {
107 if (state_ == INITIALIZED)
108 ShutdownHardware();
109 }
110
111 SurfaceFactoryOzone::HardwareState
112 DriSurfaceFactory::InitializeHardware() {
113 CHECK(state_ == UNINITIALIZED);
114
115 // TODO(dnicoara): Short-cut right now. What we want is to look at all the
116 // graphics devices available and select the primary one.
117 drm_.reset(CreateWrapper());
118 if (drm_->get_fd() < 0) {
119 LOG(ERROR) << "Cannot open graphics card '"
120 << kDefaultGraphicsCardPath << "': " << strerror(errno);
121 state_ = FAILED;
122 return state_;
123 }
124
125 state_ = INITIALIZED;
126 return state_;
127 }
128
129 void DriSurfaceFactory::ShutdownHardware() {
130 CHECK(state_ == INITIALIZED);
131
132 controller_.reset();
133 drm_.reset();
134
135 state_ = UNINITIALIZED;
136 }
137
138 gfx::AcceleratedWidget DriSurfaceFactory::GetAcceleratedWidget() {
139 CHECK(state_ != FAILED);
140
141 // TODO(dnicoara) When there's more information on which display we want,
142 // then we can return the widget associated with the display.
143 // For now just assume we have 1 display device and return it.
144 if (!controller_.get())
145 controller_.reset(new HardwareDisplayController());
146
147 // TODO(dnicoara) We only have 1 display for now, so only 1 AcceleratedWidget.
148 // When we'll support multiple displays this needs to be changed to return a
149 // different handle for every display.
150 return kDefaultWidgetHandle;
151 }
152
153 gfx::AcceleratedWidget DriSurfaceFactory::RealizeAcceleratedWidget(
154 gfx::AcceleratedWidget w) {
155 CHECK(state_ == INITIALIZED);
156 // TODO(dnicoara) Once we can handle multiple displays this needs to be
157 // changed.
158 CHECK(w == kDefaultWidgetHandle);
159
160 CHECK(controller_->get_state() ==
161 HardwareDisplayController::UNASSOCIATED);
162
163 // Until now the controller is just a stub. Initializing it will link it to a
164 // hardware display.
165 if (!InitializeControllerForPrimaryDisplay(drm_.get(), controller_.get())) {
166 LOG(ERROR) << "Failed to initialize controller";
167 return gfx::kNullAcceleratedWidget;
168 }
169
170 // Create a surface suitable for the current controller.
171 scoped_ptr<DriSurface> surface(CreateSurface(controller_.get()));
172
173 if (!surface->Initialize()) {
174 LOG(ERROR) << "Failed to initialize surface";
175 return gfx::kNullAcceleratedWidget;
176 }
177
178 // Bind the surface to the controller. This will register the backing buffers
179 // with the hardware CRTC such that we can show the buffers. The controller
180 // takes ownership of the surface.
181 if (!controller_->BindSurfaceToController(surface.Pass())) {
182 LOG(ERROR) << "Failed to bind surface to controller";
183 return gfx::kNullAcceleratedWidget;
184 }
185
186 return reinterpret_cast<gfx::AcceleratedWidget>(controller_->get_surface());
187 }
188
189 bool DriSurfaceFactory::LoadEGLGLES2Bindings(
190 AddGLLibraryCallback add_gl_library,
191 SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
192 return false;
193 }
194
195 bool DriSurfaceFactory::AttemptToResizeAcceleratedWidget(
196 gfx::AcceleratedWidget w,
197 const gfx::Rect& bounds) {
198 return false;
199 }
200
201 bool DriSurfaceFactory::SchedulePageFlip(gfx::AcceleratedWidget w) {
202 CHECK(state_ == INITIALIZED);
203 // TODO(dnicoara) Change this CHECK once we're running with the threaded
204 // compositor.
205 CHECK(base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI);
206
207 // TODO(dnicoara) Once we can handle multiple displays this needs to be
208 // changed.
209 CHECK(w == kDefaultWidgetHandle);
210
211 if (!controller_->SchedulePageFlip())
212 return false;
213
214 // Only wait for the page flip event to finish if it was properly scheduled.
215 //
216 // TODO(dnicoara) The following call will wait for the page flip event to
217 // complete. This means that it will block until the next VSync. Ideally the
218 // wait should happen in the message loop. The message loop would then
219 // schedule the next draw event. Alternatively, the VSyncProvider could be
220 // used to schedule the next draw. Unfortunately, at this point,
221 // DriOutputDevice does not provide any means to use any of the above
222 // solutions. Note that if the DRM callback does not schedule the next draw,
223 // then some sort of synchronization needs to take place since starting a new
224 // draw before the page flip happened is considered an error. However we can
225 // not use any lock constructs unless we're using the threaded compositor.
226 // Note that the following call does not use any locks, so it is safe to be
227 // made on the UI thread (thought not ideal).
228 WaitForPageFlipEvent(drm_->get_fd());
229
230 return true;
231 }
232
233 SkCanvas* DriSurfaceFactory::GetCanvasForWidget(
234 gfx::AcceleratedWidget w) {
235 CHECK(state_ == INITIALIZED);
236 return reinterpret_cast<DriSurface*>(w)->GetDrawableForWidget();
237 }
238
239 gfx::VSyncProvider* DriSurfaceFactory::GetVSyncProvider(
240 gfx::AcceleratedWidget w) {
241 return NULL;
242 }
243
244 ////////////////////////////////////////////////////////////////////////////////
245 // DriSurfaceFactory private
246
247 DriSurface* DriSurfaceFactory::CreateSurface(
248 HardwareDisplayController* controller) {
249 return new DriSurface(controller);
250 }
251
252 DriWrapper* DriSurfaceFactory::CreateWrapper() {
253 return new DriWrapper(kDefaultGraphicsCardPath);
254 }
255
256 bool DriSurfaceFactory::InitializeControllerForPrimaryDisplay(
257 DriWrapper* drm,
258 HardwareDisplayController* controller) {
259 CHECK(state_ == SurfaceFactoryOzone::INITIALIZED);
260
261 drmModeRes* resources = drmModeGetResources(drm->get_fd());
262
263 // Search for an active connector.
264 for (int i = 0; i < resources->count_connectors; ++i) {
265 drmModeConnector* connector = drmModeGetConnector(
266 drm->get_fd(),
267 resources->connectors[i]);
268
269 if (!connector)
270 continue;
271
272 if (connector->connection != DRM_MODE_CONNECTED ||
273 connector->count_modes == 0) {
274 drmModeFreeConnector(connector);
275 continue;
276 }
277
278 uint32_t crtc = GetCrtc(drm->get_fd(), resources, connector);
279
280 if (!crtc)
281 continue;
282
283 uint32_t dpms_property_id = GetDriProperty(drm->get_fd(),
284 connector,
285 kDPMSProperty);
286
287 // TODO(dnicoara) Select one mode for now. In the future we may need to
288 // save all the modes and allow the user to choose a specific mode. Or
289 // even some fullscreen applications may need to change the mode.
290 controller->SetControllerInfo(
291 drm,
292 connector->connector_id,
293 crtc,
294 dpms_property_id,
295 connector->modes[0]);
296
297 drmModeFreeConnector(connector);
298
299 return true;
300 }
301
302 return false;
303 }
304
305 void DriSurfaceFactory::WaitForPageFlipEvent(int fd) {
306 drmEventContext drm_event;
307 drm_event.version = DRM_EVENT_CONTEXT_VERSION;
308 drm_event.page_flip_handler = HandlePageFlipEvent;
309 drm_event.vblank_handler = NULL;
310
311 // Wait for the page-flip to complete.
312 drmHandleEvent(fd, &drm_event);
313 }
314
315 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/ozone/impl/dri_surface_factory.h ('k') | ui/gfx/ozone/impl/dri_surface_factory_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698