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

Side by Side Diff: ui/ozone/platform/drm/gpu/drm_device.cc

Issue 1285183008: Ozone integration. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: add missing license header Created 5 years, 4 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
OLDNEW
(Empty)
1 // Copyright 2014 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/ozone/platform/drm/gpu/drm_device.h"
6
7 #include <fcntl.h>
8 #include <sys/mman.h>
9 #include <unistd.h>
10 #include <xf86drm.h>
11 #include <xf86drmMode.h>
12
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/task_runner.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/trace_event/trace_event.h"
20 #include "third_party/skia/include/core/SkImageInfo.h"
21 #include "ui/display/types/gamma_ramp_rgb_entry.h"
22 #include "ui/ozone/platform/drm/common/drm_util.h"
23 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"
24
25 #if defined(USE_DRM_ATOMIC)
26 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h"
27 #endif
28
29 namespace ui {
30
31 namespace {
32
33 typedef base::Callback<void(uint32_t /* frame */,
34 uint32_t /* seconds */,
35 uint32_t /* useconds */,
36 uint64_t /* id */)> DrmEventHandler;
37
38 bool DrmCreateDumbBuffer(int fd,
39 const SkImageInfo& info,
40 uint32_t* handle,
41 uint32_t* stride) {
42 struct drm_mode_create_dumb request;
43 memset(&request, 0, sizeof(request));
44 request.width = info.width();
45 request.height = info.height();
46 request.bpp = info.bytesPerPixel() << 3;
47 request.flags = 0;
48
49 if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) {
50 VPLOG(2) << "Cannot create dumb buffer";
51 return false;
52 }
53
54 // The driver may choose to align the last row as well. We don't care about
55 // the last alignment bits since they aren't used for display purposes, so
56 // just check that the expected size is <= to what the driver allocated.
57 DCHECK_LE(info.getSafeSize(request.pitch), request.size);
58
59 *handle = request.handle;
60 *stride = request.pitch;
61 return true;
62 }
63
64 bool DrmDestroyDumbBuffer(int fd, uint32_t handle) {
65 struct drm_mode_destroy_dumb destroy_request;
66 memset(&destroy_request, 0, sizeof(destroy_request));
67 destroy_request.handle = handle;
68 return !drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
69 }
70
71 bool ProcessDrmEvent(int fd, const DrmEventHandler& callback) {
72 char buffer[1024];
73 int len = read(fd, buffer, sizeof(buffer));
74 if (len == 0)
75 return false;
76
77 if (len < static_cast<int>(sizeof(drm_event))) {
78 PLOG(ERROR) << "Failed to read DRM event";
79 return false;
80 }
81
82 int idx = 0;
83 while (idx < len) {
84 DCHECK_LE(static_cast<int>(sizeof(drm_event)), len - idx);
85 drm_event event;
86 memcpy(&event, &buffer[idx], sizeof(event));
87 switch (event.type) {
88 case DRM_EVENT_FLIP_COMPLETE: {
89 DCHECK_LE(static_cast<int>(sizeof(drm_event_vblank)), len - idx);
90 drm_event_vblank vblank;
91 memcpy(&vblank, &buffer[idx], sizeof(vblank));
92 callback.Run(vblank.sequence, vblank.tv_sec, vblank.tv_usec,
93 vblank.user_data);
94 } break;
95 case DRM_EVENT_VBLANK:
96 break;
97 default:
98 NOTREACHED();
99 break;
100 }
101
102 idx += event.length;
103 }
104
105 return true;
106 }
107
108 bool CanQueryForResources(int fd) {
109 drm_mode_card_res resources;
110 memset(&resources, 0, sizeof(resources));
111 // If there is no error getting DRM resources then assume this is a
112 // modesetting device.
113 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources);
114 }
115
116 } // namespace
117
118 class DrmDevice::PageFlipManager
119 : public base::RefCountedThreadSafe<DrmDevice::PageFlipManager> {
120 public:
121 PageFlipManager() : next_id_(0) {}
122
123 void OnPageFlip(uint32_t frame,
124 uint32_t seconds,
125 uint32_t useconds,
126 uint64_t id) {
127 auto it =
128 std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id));
129 if (it == callbacks_.end()) {
130 LOG(WARNING) << "Could not find callback for page flip id=" << id;
131 return;
132 }
133
134 DrmDevice::PageFlipCallback callback = it->callback;
135 callbacks_.erase(it);
136 callback.Run(frame, seconds, useconds);
137 }
138
139 uint64_t GetNextId() { return next_id_++; }
140
141 void RegisterCallback(uint64_t id,
142 const DrmDevice::PageFlipCallback& callback) {
143 callbacks_.push_back({id, callback});
144 }
145
146 private:
147 friend class base::RefCountedThreadSafe<DrmDevice::PageFlipManager>;
148 ~PageFlipManager() {}
149
150 struct PageFlip {
151 uint64_t id;
152 DrmDevice::PageFlipCallback callback;
153 };
154
155 struct FindCallback {
156 FindCallback(uint64_t id) : id(id) {}
157
158 bool operator()(const PageFlip& flip) const { return flip.id == id; }
159
160 uint64_t id;
161 };
162
163 uint64_t next_id_;
164
165 std::vector<PageFlip> callbacks_;
166
167 DISALLOW_COPY_AND_ASSIGN(PageFlipManager);
168 };
169
170 class DrmDevice::IOWatcher
171 : public base::RefCountedThreadSafe<DrmDevice::IOWatcher>,
172 public base::MessagePumpLibevent::Watcher {
173 public:
174 IOWatcher(int fd,
175 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
176 const scoped_refptr<DrmDevice::PageFlipManager>& page_flip_manager)
177 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
178 io_task_runner_(io_task_runner),
179 page_flip_manager_(page_flip_manager),
180 paused_(true),
181 fd_(fd) {}
182
183 void SetPaused(bool paused) {
184 if (paused_ == paused)
185 return;
186
187 paused_ = paused;
188 base::WaitableEvent done(false, false);
189 io_task_runner_->PostTask(
190 FROM_HERE, base::Bind(&IOWatcher::SetPausedOnIO, this, &done));
191 done.Wait();
192 }
193
194 void Shutdown() {
195 if (!paused_)
196 io_task_runner_->PostTask(FROM_HERE,
197 base::Bind(&IOWatcher::UnregisterOnIO, this));
198 }
199
200 private:
201 friend class base::RefCountedThreadSafe<IOWatcher>;
202
203 ~IOWatcher() override {}
204
205 void RegisterOnIO() {
206 DCHECK(base::MessageLoopForIO::IsCurrent());
207 base::MessageLoopForIO::current()->WatchFileDescriptor(
208 fd_, true, base::MessageLoopForIO::WATCH_READ, &controller_, this);
209 }
210
211 void UnregisterOnIO() {
212 DCHECK(base::MessageLoopForIO::IsCurrent());
213 controller_.StopWatchingFileDescriptor();
214 }
215
216 void SetPausedOnIO(base::WaitableEvent* done) {
217 DCHECK(base::MessageLoopForIO::IsCurrent());
218 if (paused_)
219 UnregisterOnIO();
220 else
221 RegisterOnIO();
222 done->Signal();
223 }
224
225 void OnPageFlipOnIO(uint32_t frame,
226 uint32_t seconds,
227 uint32_t useconds,
228 uint64_t id) {
229 main_task_runner_->PostTask(
230 FROM_HERE,
231 base::Bind(&DrmDevice::PageFlipManager::OnPageFlip, page_flip_manager_,
232 frame, seconds, useconds, id));
233 }
234
235 // base::MessagePumpLibevent::Watcher overrides:
236 void OnFileCanReadWithoutBlocking(int fd) override {
237 DCHECK(base::MessageLoopForIO::IsCurrent());
238 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd);
239
240 if (!ProcessDrmEvent(
241 fd, base::Bind(&DrmDevice::IOWatcher::OnPageFlipOnIO, this)))
242 UnregisterOnIO();
243 }
244
245 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
246
247 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
248 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
249
250 scoped_refptr<DrmDevice::PageFlipManager> page_flip_manager_;
251
252 base::MessagePumpLibevent::FileDescriptorWatcher controller_;
253
254 bool paused_;
255 int fd_;
256
257 DISALLOW_COPY_AND_ASSIGN(IOWatcher);
258 };
259
260 DrmDevice::DrmDevice(const base::FilePath& device_path, base::File file)
261 : device_path_(device_path),
262 file_(file.Pass()),
263 page_flip_manager_(new PageFlipManager()) {
264 }
265
266 DrmDevice::~DrmDevice() {
267 if (watcher_)
268 watcher_->Shutdown();
269 }
270
271 bool DrmDevice::Initialize(bool use_atomic) {
272 // Ignore devices that cannot perform modesetting.
273 if (!CanQueryForResources(file_.GetPlatformFile())) {
274 VLOG(2) << "Cannot query for resources for '" << device_path_.value()
275 << "'";
276 return false;
277 }
278
279 #if defined(USE_DRM_ATOMIC)
280 // Use atomic only if the build, kernel & flags all allow it.
281 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1))
282 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic());
283 #endif // defined(USE_DRM_ATOMIC)
284
285 if (!plane_manager_)
286 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
287 if (!plane_manager_->Initialize(this)) {
288 LOG(ERROR) << "Failed to initialize the plane manager for "
289 << device_path_.value();
290 plane_manager_.reset();
291 return false;
292 }
293
294 return true;
295 }
296
297 void DrmDevice::InitializeTaskRunner(
298 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
299 DCHECK(!task_runner_);
300 task_runner_ = task_runner;
301 watcher_ =
302 new IOWatcher(file_.GetPlatformFile(), task_runner_, page_flip_manager_);
303 }
304
305 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) {
306 DCHECK(file_.IsValid());
307 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id));
308 }
309
310 bool DrmDevice::SetCrtc(uint32_t crtc_id,
311 uint32_t framebuffer,
312 std::vector<uint32_t> connectors,
313 drmModeModeInfo* mode) {
314 DCHECK(file_.IsValid());
315 DCHECK(!connectors.empty());
316 DCHECK(mode);
317
318 TRACE_EVENT2("drm", "DrmDevice::SetCrtc", "crtc", crtc_id, "size",
319 gfx::Size(mode->hdisplay, mode->vdisplay).ToString());
320 return !drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, framebuffer, 0, 0,
321 vector_as_array(&connectors), connectors.size(), mode);
322 }
323
324 bool DrmDevice::SetCrtc(drmModeCrtc* crtc, std::vector<uint32_t> connectors) {
325 DCHECK(file_.IsValid());
326 // If there's no buffer then the CRTC was disabled.
327 if (!crtc->buffer_id)
328 return DisableCrtc(crtc->crtc_id);
329
330 DCHECK(!connectors.empty());
331
332 TRACE_EVENT1("drm", "DrmDevice::RestoreCrtc", "crtc", crtc->crtc_id);
333 return !drmModeSetCrtc(file_.GetPlatformFile(), crtc->crtc_id,
334 crtc->buffer_id, crtc->x, crtc->y,
335 vector_as_array(&connectors), connectors.size(),
336 &crtc->mode);
337 }
338
339 bool DrmDevice::DisableCrtc(uint32_t crtc_id) {
340 DCHECK(file_.IsValid());
341 TRACE_EVENT1("drm", "DrmDevice::DisableCrtc", "crtc", crtc_id);
342 return !drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, 0, 0, 0, NULL, 0,
343 NULL);
344 }
345
346 ScopedDrmConnectorPtr DrmDevice::GetConnector(uint32_t connector_id) {
347 DCHECK(file_.IsValid());
348 TRACE_EVENT1("drm", "DrmDevice::GetConnector", "connector", connector_id);
349 return ScopedDrmConnectorPtr(
350 drmModeGetConnector(file_.GetPlatformFile(), connector_id));
351 }
352
353 bool DrmDevice::AddFramebuffer(uint32_t width,
354 uint32_t height,
355 uint8_t depth,
356 uint8_t bpp,
357 uint32_t stride,
358 uint32_t handle,
359 uint32_t* framebuffer) {
360 DCHECK(file_.IsValid());
361 TRACE_EVENT1("drm", "DrmDevice::AddFramebuffer", "handle", handle);
362 return !drmModeAddFB(file_.GetPlatformFile(), width, height, depth, bpp,
363 stride, handle, framebuffer);
364 }
365
366 bool DrmDevice::RemoveFramebuffer(uint32_t framebuffer) {
367 DCHECK(file_.IsValid());
368 TRACE_EVENT1("drm", "DrmDevice::RemoveFramebuffer", "framebuffer",
369 framebuffer);
370 return !drmModeRmFB(file_.GetPlatformFile(), framebuffer);
371 }
372
373 bool DrmDevice::PageFlip(uint32_t crtc_id,
374 uint32_t framebuffer,
375 bool is_sync,
376 const PageFlipCallback& callback) {
377 DCHECK(file_.IsValid());
378 TRACE_EVENT2("drm", "DrmDevice::PageFlip", "crtc", crtc_id, "framebuffer",
379 framebuffer);
380
381 if (watcher_)
382 watcher_->SetPaused(is_sync);
383
384 // NOTE: Calling drmModeSetCrtc will immediately update the state, though
385 // callbacks to already scheduled page flips will be honored by the kernel.
386 uint64_t id = page_flip_manager_->GetNextId();
387 if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer,
388 DRM_MODE_PAGE_FLIP_EVENT, reinterpret_cast<void*>(id))) {
389 // If successful the payload will be removed by a PageFlip event.
390 page_flip_manager_->RegisterCallback(id, callback);
391
392 // If the flip was requested synchronous or if no watcher has been installed
393 // yet, then synchronously handle the page flip events.
394 if (is_sync || !watcher_) {
395 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile());
396
397 ProcessDrmEvent(
398 file_.GetPlatformFile(),
399 base::Bind(&PageFlipManager::OnPageFlip, page_flip_manager_));
400 }
401
402 return true;
403 }
404
405 return false;
406 }
407
408 bool DrmDevice::PageFlipOverlay(uint32_t crtc_id,
409 uint32_t framebuffer,
410 const gfx::Rect& location,
411 const gfx::Rect& source,
412 int overlay_plane) {
413 DCHECK(file_.IsValid());
414 TRACE_EVENT2("drm", "DrmDevice::PageFlipOverlay", "crtc", crtc_id,
415 "framebuffer", framebuffer);
416 return !drmModeSetPlane(file_.GetPlatformFile(), overlay_plane, crtc_id,
417 framebuffer, 0, location.x(), location.y(),
418 location.width(), location.height(), source.x(),
419 source.y(), source.width(), source.height());
420 }
421
422 ScopedDrmFramebufferPtr DrmDevice::GetFramebuffer(uint32_t framebuffer) {
423 DCHECK(file_.IsValid());
424 TRACE_EVENT1("drm", "DrmDevice::GetFramebuffer", "framebuffer", framebuffer);
425 return ScopedDrmFramebufferPtr(
426 drmModeGetFB(file_.GetPlatformFile(), framebuffer));
427 }
428
429 ScopedDrmPropertyPtr DrmDevice::GetProperty(drmModeConnector* connector,
430 const char* name) {
431 TRACE_EVENT2("drm", "DrmDevice::GetProperty", "connector",
432 connector->connector_id, "name", name);
433 for (int i = 0; i < connector->count_props; ++i) {
434 ScopedDrmPropertyPtr property(
435 drmModeGetProperty(file_.GetPlatformFile(), connector->props[i]));
436 if (!property)
437 continue;
438
439 if (strcmp(property->name, name) == 0)
440 return property.Pass();
441 }
442
443 return ScopedDrmPropertyPtr();
444 }
445
446 bool DrmDevice::SetProperty(uint32_t connector_id,
447 uint32_t property_id,
448 uint64_t value) {
449 DCHECK(file_.IsValid());
450 return !drmModeConnectorSetProperty(file_.GetPlatformFile(), connector_id,
451 property_id, value);
452 }
453
454 bool DrmDevice::GetCapability(uint64_t capability, uint64_t* value) {
455 DCHECK(file_.IsValid());
456 return !drmGetCap(file_.GetPlatformFile(), capability, value);
457 }
458
459 ScopedDrmPropertyBlobPtr DrmDevice::GetPropertyBlob(drmModeConnector* connector,
460 const char* name) {
461 DCHECK(file_.IsValid());
462 TRACE_EVENT2("drm", "DrmDevice::GetPropertyBlob", "connector",
463 connector->connector_id, "name", name);
464 for (int i = 0; i < connector->count_props; ++i) {
465 ScopedDrmPropertyPtr property(
466 drmModeGetProperty(file_.GetPlatformFile(), connector->props[i]));
467 if (!property)
468 continue;
469
470 if (strcmp(property->name, name) == 0 &&
471 property->flags & DRM_MODE_PROP_BLOB)
472 return ScopedDrmPropertyBlobPtr(drmModeGetPropertyBlob(
473 file_.GetPlatformFile(), connector->prop_values[i]));
474 }
475
476 return ScopedDrmPropertyBlobPtr();
477 }
478
479 bool DrmDevice::SetCursor(uint32_t crtc_id,
480 uint32_t handle,
481 const gfx::Size& size) {
482 DCHECK(file_.IsValid());
483 TRACE_EVENT1("drm", "DrmDevice::SetCursor", "handle", handle);
484 return !drmModeSetCursor(file_.GetPlatformFile(), crtc_id, handle,
485 size.width(), size.height());
486 }
487
488 bool DrmDevice::MoveCursor(uint32_t crtc_id, const gfx::Point& point) {
489 DCHECK(file_.IsValid());
490 return !drmModeMoveCursor(file_.GetPlatformFile(), crtc_id, point.x(),
491 point.y());
492 }
493
494 bool DrmDevice::CreateDumbBuffer(const SkImageInfo& info,
495 uint32_t* handle,
496 uint32_t* stride) {
497 DCHECK(file_.IsValid());
498
499 TRACE_EVENT0("drm", "DrmDevice::CreateDumbBuffer");
500 return DrmCreateDumbBuffer(file_.GetPlatformFile(), info, handle, stride);
501 }
502
503 bool DrmDevice::DestroyDumbBuffer(uint32_t handle) {
504 DCHECK(file_.IsValid());
505 TRACE_EVENT1("drm", "DrmDevice::DestroyDumbBuffer", "handle", handle);
506 return DrmDestroyDumbBuffer(file_.GetPlatformFile(), handle);
507 }
508
509 bool DrmDevice::MapDumbBuffer(uint32_t handle, size_t size, void** pixels) {
510 struct drm_mode_map_dumb map_request;
511 memset(&map_request, 0, sizeof(map_request));
512 map_request.handle = handle;
513 if (drmIoctl(file_.GetPlatformFile(), DRM_IOCTL_MODE_MAP_DUMB,
514 &map_request)) {
515 PLOG(ERROR) << "Cannot prepare dumb buffer for mapping";
516 return false;
517 }
518
519 *pixels = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED,
520 file_.GetPlatformFile(), map_request.offset);
521 if (*pixels == MAP_FAILED) {
522 PLOG(ERROR) << "Cannot mmap dumb buffer";
523 return false;
524 }
525
526 return true;
527 }
528
529 bool DrmDevice::UnmapDumbBuffer(void* pixels, size_t size) {
530 return !munmap(pixels, size);
531 }
532
533 bool DrmDevice::CloseBufferHandle(uint32_t handle) {
534 struct drm_gem_close close_request;
535 memset(&close_request, 0, sizeof(close_request));
536 close_request.handle = handle;
537 return !drmIoctl(file_.GetPlatformFile(), DRM_IOCTL_GEM_CLOSE,
538 &close_request);
539 }
540
541 bool DrmDevice::CommitProperties(drmModePropertySet* properties,
542 uint32_t flags,
543 bool is_sync,
544 bool test_only,
545 const PageFlipCallback& callback) {
546 #if defined(USE_DRM_ATOMIC)
547 if (test_only)
548 flags |= DRM_MODE_ATOMIC_TEST_ONLY;
549 else
550 flags |= DRM_MODE_PAGE_FLIP_EVENT;
551 uint64_t id = page_flip_manager_->GetNextId();
552 if (!drmModePropertySetCommit(file_.GetPlatformFile(), flags,
553 reinterpret_cast<void*>(id), properties)) {
554 if (test_only)
555 return true;
556 page_flip_manager_->RegisterCallback(id, callback);
557
558 // If the flip was requested synchronous or if no watcher has been installed
559 // yet, then synchronously handle the page flip events.
560 if (is_sync || !watcher_) {
561 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile());
562
563 ProcessDrmEvent(
564 file_.GetPlatformFile(),
565 base::Bind(&PageFlipManager::OnPageFlip, page_flip_manager_));
566 }
567 return true;
568 }
569 #endif // defined(USE_DRM_ATOMIC)
570 return false;
571 }
572
573 bool DrmDevice::SetCapability(uint64_t capability, uint64_t value) {
574 DCHECK(file_.IsValid());
575 return !drmSetClientCap(file_.GetPlatformFile(), capability, value);
576 }
577
578 bool DrmDevice::SetMaster() {
579 TRACE_EVENT1("drm", "DrmDevice::SetMaster", "path", device_path_.value());
580 DCHECK(file_.IsValid());
581 return (drmSetMaster(file_.GetPlatformFile()) == 0);
582 }
583
584 bool DrmDevice::DropMaster() {
585 TRACE_EVENT1("drm", "DrmDevice::DropMaster", "path", device_path_.value());
586 DCHECK(file_.IsValid());
587 return (drmDropMaster(file_.GetPlatformFile()) == 0);
588 }
589
590 bool DrmDevice::SetGammaRamp(uint32_t crtc_id,
591 const std::vector<GammaRampRGBEntry>& lut) {
592 ScopedDrmCrtcPtr crtc = GetCrtc(crtc_id);
593
594 // TODO(robert.bradford) resample the incoming ramp to match what the kernel
595 // expects.
596 if (static_cast<size_t>(crtc->gamma_size) != lut.size()) {
597 LOG(ERROR) << "Gamma table size mismatch: supplied " << lut.size()
598 << " expected " << crtc->gamma_size;
599 }
600
601 std::vector<uint16_t> r, g, b;
602 r.reserve(lut.size());
603 g.reserve(lut.size());
604 b.reserve(lut.size());
605
606 for (size_t i = 0; i < lut.size(); ++i) {
607 r.push_back(lut[i].r);
608 g.push_back(lut[i].g);
609 b.push_back(lut[i].b);
610 }
611
612 DCHECK(file_.IsValid());
613 TRACE_EVENT0("drm", "DrmDevice::SetGamma");
614 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0],
615 &g[0], &b[0]) == 0);
616 }
617
618 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/drm/gpu/drm_device.h ('k') | ui/ozone/platform/drm/gpu/drm_device_generator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698