Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / x11 / native_display_delegate_x11.cc
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/display/chromeos/x11/native_display_delegate_x11.h"
6
7 #include <X11/Xatom.h>
8 #include <X11/Xlib.h>
9 #include <X11/extensions/dpms.h>
10 #include <X11/extensions/Xrandr.h>
11 #include <X11/extensions/XInput2.h>
12
13 #include <utility>
14
15 #include "base/logging.h"
16 #include "base/stl_util.h"
17 #include "ui/display/chromeos/x11/display_mode_x11.h"
18 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
19 #include "ui/display/chromeos/x11/display_util_x11.h"
20 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
21 #include "ui/display/types/chromeos/native_display_observer.h"
22 #include "ui/display/util/x11/edid_parser_x11.h"
23 #include "ui/events/platform/platform_event_observer.h"
24 #include "ui/events/platform/platform_event_source.h"
25 #include "ui/gfx/geometry/rect.h"
26 #include "ui/gfx/x/x11_error_tracker.h"
27 #include "ui/gfx/x/x11_types.h"
28
29 namespace ui {
30
31 namespace {
32
33 // DPI measurements.
34 const float kMmInInch = 25.4;
35 const float kDpi96 = 96.0;
36 const float kPixelsToMmScale = kMmInInch / kDpi96;
37
38 const char kContentProtectionAtomName[] = "Content Protection";
39 const char kProtectionUndesiredAtomName[] = "Undesired";
40 const char kProtectionDesiredAtomName[] = "Desired";
41 const char kProtectionEnabledAtomName[] = "Enabled";
42
43 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) {
44   return output_info->nmode > 0 ? output_info->modes[0] : None;
45 }
46
47 XRRCrtcGamma* ResampleGammaRamp(XRRCrtcGamma* gamma_ramp, int gamma_ramp_size) {
48   if (gamma_ramp->size == gamma_ramp_size)
49     return gamma_ramp;
50
51 #define RESAMPLE(array, i, r) \
52   array[i] + (array[i + 1] - array[i]) * r / gamma_ramp_size
53
54   XRRCrtcGamma* resampled = XRRAllocGamma(gamma_ramp_size);
55   for (int i = 0; i < gamma_ramp_size; ++i) {
56     int base_index = gamma_ramp->size * i / gamma_ramp_size;
57     int remaining = gamma_ramp->size * i % gamma_ramp_size;
58     if (base_index < gamma_ramp->size - 1) {
59       resampled->red[i] = RESAMPLE(gamma_ramp->red, base_index, remaining);
60       resampled->green[i] = RESAMPLE(gamma_ramp->green, base_index, remaining);
61       resampled->blue[i] = RESAMPLE(gamma_ramp->blue, base_index, remaining);
62     } else {
63       resampled->red[i] = gamma_ramp->red[gamma_ramp->size - 1];
64       resampled->green[i] = gamma_ramp->green[gamma_ramp->size - 1];
65       resampled->blue[i] = gamma_ramp->blue[gamma_ramp->size - 1];
66     }
67   }
68
69 #undef RESAMPLE
70   XRRFreeGamma(gamma_ramp);
71   return resampled;
72 }
73
74 }  // namespace
75
76 ////////////////////////////////////////////////////////////////////////////////
77 // NativeDisplayDelegateX11::HelperDelegateX11
78
79 class NativeDisplayDelegateX11::HelperDelegateX11
80     : public NativeDisplayDelegateX11::HelperDelegate {
81  public:
82   HelperDelegateX11(NativeDisplayDelegateX11* delegate) : delegate_(delegate) {}
83   virtual ~HelperDelegateX11() {}
84
85   // NativeDisplayDelegateX11::HelperDelegate overrides:
86   virtual void UpdateXRandRConfiguration(const base::NativeEvent& event)
87       OVERRIDE {
88     XRRUpdateConfiguration(event);
89   }
90   virtual const std::vector<DisplaySnapshot*>& GetCachedDisplays() const
91       OVERRIDE {
92     return delegate_->cached_outputs_.get();
93   }
94   virtual void NotifyDisplayObservers() OVERRIDE {
95     FOR_EACH_OBSERVER(
96         NativeDisplayObserver, delegate_->observers_, OnConfigurationChanged());
97   }
98
99  private:
100   NativeDisplayDelegateX11* delegate_;
101
102   DISALLOW_COPY_AND_ASSIGN(HelperDelegateX11);
103 };
104
105 ////////////////////////////////////////////////////////////////////////////////
106 // NativeDisplayDelegateX11::PlatformEventObserverX11
107
108 class NativeDisplayDelegateX11::PlatformEventObserverX11
109     : public PlatformEventObserver {
110  public:
111   PlatformEventObserverX11(HelperDelegate* delegate);
112   virtual ~PlatformEventObserverX11();
113
114   // PlatformEventObserverX11:
115   virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
116   virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
117
118  private:
119   HelperDelegate* delegate_;  // Not owned.
120
121   DISALLOW_COPY_AND_ASSIGN(PlatformEventObserverX11);
122 };
123
124 NativeDisplayDelegateX11::PlatformEventObserverX11::PlatformEventObserverX11(
125     HelperDelegate* delegate)
126     : delegate_(delegate) {}
127
128 NativeDisplayDelegateX11::PlatformEventObserverX11::
129     ~PlatformEventObserverX11() {}
130
131 void NativeDisplayDelegateX11::PlatformEventObserverX11::WillProcessEvent(
132     const ui::PlatformEvent& event) {
133   // XI_HierarchyChanged events are special. There is no window associated with
134   // these events. So process them directly from here.
135   if (event->type == GenericEvent &&
136       event->xgeneric.evtype == XI_HierarchyChanged) {
137     VLOG(1) << "Received XI_HierarchyChanged event";
138     // Defer configuring outputs to not stall event processing.
139     // This also takes care of same event being received twice.
140     delegate_->NotifyDisplayObservers();
141   }
142 }
143
144 void NativeDisplayDelegateX11::PlatformEventObserverX11::DidProcessEvent(
145     const ui::PlatformEvent& event) {}
146
147 ////////////////////////////////////////////////////////////////////////////////
148 // NativeDisplayDelegateX11 implementation:
149
150 NativeDisplayDelegateX11::NativeDisplayDelegateX11()
151     : display_(gfx::GetXDisplay()),
152       window_(DefaultRootWindow(display_)),
153       screen_(NULL),
154       background_color_argb_(0) {}
155
156 NativeDisplayDelegateX11::~NativeDisplayDelegateX11() {
157   if (ui::PlatformEventSource::GetInstance()) {
158     ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(
159         platform_event_dispatcher_.get());
160     ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(
161         platform_event_observer_.get());
162   }
163
164   STLDeleteContainerPairSecondPointers(modes_.begin(), modes_.end());
165 }
166
167 void NativeDisplayDelegateX11::Initialize() {
168   int error_base_ignored = 0;
169   int xrandr_event_base = 0;
170   XRRQueryExtension(display_, &xrandr_event_base, &error_base_ignored);
171
172   helper_delegate_.reset(new HelperDelegateX11(this));
173   platform_event_dispatcher_.reset(new NativeDisplayEventDispatcherX11(
174       helper_delegate_.get(), xrandr_event_base));
175   platform_event_observer_.reset(
176       new PlatformEventObserverX11(helper_delegate_.get()));
177
178   if (ui::PlatformEventSource::GetInstance()) {
179     ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(
180         platform_event_dispatcher_.get());
181
182     // We can't do this with a root window listener because XI_HierarchyChanged
183     // messages don't have a target window.
184     ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(
185         platform_event_observer_.get());
186   }
187 }
188
189 void NativeDisplayDelegateX11::GrabServer() {
190   CHECK(!screen_) << "Server already grabbed";
191   XGrabServer(display_);
192   screen_ = XRRGetScreenResources(display_, window_);
193   CHECK(screen_);
194 }
195
196 void NativeDisplayDelegateX11::UngrabServer() {
197   CHECK(screen_) << "Server not grabbed";
198   XRRFreeScreenResources(screen_);
199   screen_ = NULL;
200   XUngrabServer(display_);
201   // crbug.com/366125
202   XFlush(display_);
203 }
204
205 void NativeDisplayDelegateX11::SyncWithServer() { XSync(display_, 0); }
206
207 void NativeDisplayDelegateX11::SetBackgroundColor(uint32_t color_argb) {
208   background_color_argb_ = color_argb;
209 }
210
211 void NativeDisplayDelegateX11::ForceDPMSOn() {
212   CHECK(DPMSEnable(display_));
213   CHECK(DPMSForceLevel(display_, DPMSModeOn));
214 }
215
216 std::vector<DisplaySnapshot*> NativeDisplayDelegateX11::GetDisplays() {
217   CHECK(screen_) << "Server not grabbed";
218
219   cached_outputs_.clear();
220   RRCrtc last_used_crtc = None;
221
222   InitModes();
223   for (int i = 0; i < screen_->noutput && cached_outputs_.size() < 2; ++i) {
224     RROutput output_id = screen_->outputs[i];
225     XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, output_id);
226     if (output_info->connection == RR_Connected) {
227       DisplaySnapshotX11* output =
228           InitDisplaySnapshot(output_id, output_info, &last_used_crtc, i);
229       cached_outputs_.push_back(output);
230     }
231     XRRFreeOutputInfo(output_info);
232   }
233
234   return cached_outputs_.get();
235 }
236
237 void NativeDisplayDelegateX11::AddMode(const DisplaySnapshot& output,
238                                        const DisplayMode* mode) {
239   CHECK(screen_) << "Server not grabbed";
240   CHECK(mode) << "Must add valid mode";
241
242   const DisplaySnapshotX11& x11_output =
243       static_cast<const DisplaySnapshotX11&>(output);
244   RRMode mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id();
245
246   VLOG(1) << "AddDisplayMode: output=" << x11_output.output()
247           << " mode=" << mode_id;
248   XRRAddOutputMode(display_, x11_output.output(), mode_id);
249 }
250
251 bool NativeDisplayDelegateX11::Configure(const DisplaySnapshot& output,
252                                          const DisplayMode* mode,
253                                          const gfx::Point& origin) {
254   const DisplaySnapshotX11& x11_output =
255       static_cast<const DisplaySnapshotX11&>(output);
256   RRMode mode_id = None;
257   if (mode)
258     mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id();
259
260   return ConfigureCrtc(
261       x11_output.crtc(), mode_id, x11_output.output(), origin.x(), origin.y());
262 }
263
264 bool NativeDisplayDelegateX11::ConfigureCrtc(RRCrtc crtc,
265                                              RRMode mode,
266                                              RROutput output,
267                                              int x,
268                                              int y) {
269   CHECK(screen_) << "Server not grabbed";
270   VLOG(1) << "ConfigureCrtc: crtc=" << crtc << " mode=" << mode
271           << " output=" << output << " x=" << x << " y=" << y;
272   // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a
273   // Status, which is typically 0 for failure and 1 for success. In
274   // actuality it returns a RRCONFIGSTATUS, which uses 0 for success.
275   if (XRRSetCrtcConfig(display_,
276                        screen_,
277                        crtc,
278                        CurrentTime,
279                        x,
280                        y,
281                        mode,
282                        RR_Rotate_0,
283                        (output && mode) ? &output : NULL,
284                        (output && mode) ? 1 : 0) != RRSetConfigSuccess) {
285     LOG(WARNING) << "Unable to configure CRTC " << crtc << ":"
286                  << " mode=" << mode << " output=" << output << " x=" << x
287                  << " y=" << y;
288     return false;
289   }
290
291   return true;
292 }
293
294 void NativeDisplayDelegateX11::CreateFrameBuffer(const gfx::Size& size) {
295   CHECK(screen_) << "Server not grabbed";
296   gfx::Size current_screen_size(
297       DisplayWidth(display_, DefaultScreen(display_)),
298       DisplayHeight(display_, DefaultScreen(display_)));
299
300   VLOG(1) << "CreateFrameBuffer: new=" << size.ToString()
301           << " current=" << current_screen_size.ToString();
302
303   DestroyUnusedCrtcs();
304
305   if (size == current_screen_size)
306     return;
307
308   gfx::Size min_screen_size(current_screen_size);
309   min_screen_size.SetToMin(size);
310   UpdateCrtcsForNewFramebuffer(min_screen_size);
311
312   int mm_width = size.width() * kPixelsToMmScale;
313   int mm_height = size.height() * kPixelsToMmScale;
314   XRRSetScreenSize(
315       display_, window_, size.width(), size.height(), mm_width, mm_height);
316   // We don't wait for root window resize, therefore this end up with drawing
317   // in the old window size, which we care during the boot.
318   DrawBackground();
319
320   // Don't redraw the background upon framebuffer change again. This should
321   // happen only once after boot.
322   background_color_argb_ = 0;
323 }
324
325 void NativeDisplayDelegateX11::AddObserver(NativeDisplayObserver* observer) {
326   observers_.AddObserver(observer);
327 }
328
329 void NativeDisplayDelegateX11::RemoveObserver(NativeDisplayObserver* observer) {
330   observers_.RemoveObserver(observer);
331 }
332
333 void NativeDisplayDelegateX11::InitModes() {
334   CHECK(screen_) << "Server not grabbed";
335
336   STLDeleteContainerPairSecondPointers(modes_.begin(), modes_.end());
337   modes_.clear();
338
339   for (int i = 0; i < screen_->nmode; ++i) {
340     const XRRModeInfo& info = screen_->modes[i];
341     float refresh_rate = 0.0f;
342     if (info.hTotal && info.vTotal) {
343       refresh_rate =
344           static_cast<float>(info.dotClock) /
345           (static_cast<float>(info.hTotal) * static_cast<float>(info.vTotal));
346     }
347
348     modes_.insert(
349         std::make_pair(info.id,
350                        new DisplayModeX11(gfx::Size(info.width, info.height),
351                                           info.modeFlags & RR_Interlace,
352                                           refresh_rate,
353                                           info.id)));
354   }
355 }
356
357 DisplaySnapshotX11* NativeDisplayDelegateX11::InitDisplaySnapshot(
358     RROutput id,
359     XRROutputInfo* info,
360     RRCrtc* last_used_crtc,
361     int index) {
362   int64_t display_id = 0;
363   bool has_display_id = GetDisplayId(
364       id, static_cast<uint8_t>(index), &display_id);
365
366   bool has_overscan = false;
367   GetOutputOverscanFlag(id, &has_overscan);
368
369   DisplayConnectionType type = GetDisplayConnectionTypeFromName(info->name);
370   if (type == DISPLAY_CONNECTION_TYPE_UNKNOWN)
371     LOG(ERROR) << "Unknown link type: " << info->name;
372
373   // Use the index as a valid display ID even if the internal
374   // display doesn't have valid EDID because the index
375   // will never change.
376   if (!has_display_id) {
377     if (type == DISPLAY_CONNECTION_TYPE_INTERNAL)
378       has_display_id = true;
379
380     // Fallback to output index.
381     display_id = index;
382   }
383
384   RRMode native_mode_id = GetOutputNativeMode(info);
385   RRMode current_mode_id = None;
386   gfx::Point origin;
387   if (info->crtc) {
388     XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display_, screen_, info->crtc);
389     current_mode_id = crtc_info->mode;
390     origin.SetPoint(crtc_info->x, crtc_info->y);
391     XRRFreeCrtcInfo(crtc_info);
392   }
393
394   RRCrtc crtc = None;
395   // Assign a CRTC that isn't already in use.
396   for (int i = 0; i < info->ncrtc; ++i) {
397     if (info->crtcs[i] != *last_used_crtc) {
398       crtc = info->crtcs[i];
399       *last_used_crtc = crtc;
400       break;
401     }
402   }
403
404   const DisplayMode* current_mode = NULL;
405   const DisplayMode* native_mode = NULL;
406   std::vector<const DisplayMode*> display_modes;
407
408   for (int i = 0; i < info->nmode; ++i) {
409     const RRMode mode = info->modes[i];
410     if (modes_.find(mode) != modes_.end()) {
411       display_modes.push_back(modes_.at(mode));
412
413       if (mode == current_mode_id)
414         current_mode = display_modes.back();
415       if (mode == native_mode_id)
416         native_mode = display_modes.back();
417     } else {
418       LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
419     }
420   }
421
422   DisplaySnapshotX11* output =
423       new DisplaySnapshotX11(display_id,
424                              has_display_id,
425                              origin,
426                              gfx::Size(info->mm_width, info->mm_height),
427                              type,
428                              IsOutputAspectPreservingScaling(id),
429                              has_overscan,
430                              GetDisplayName(id),
431                              display_modes,
432                              current_mode,
433                              native_mode,
434                              id,
435                              crtc,
436                              index);
437
438   VLOG(2) << "Found display " << cached_outputs_.size() << ":"
439           << " output=" << output << " crtc=" << crtc
440           << " current_mode=" << current_mode_id;
441
442   return output;
443 }
444
445 bool NativeDisplayDelegateX11::GetHDCPState(const DisplaySnapshot& output,
446                                             HDCPState* state) {
447   unsigned char* values = NULL;
448   int actual_format = 0;
449   unsigned long nitems = 0;
450   unsigned long bytes_after = 0;
451   Atom actual_type = None;
452   int success = 0;
453   RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output();
454   // TODO(kcwu): Use X11AtomCache to save round trip time of XInternAtom.
455   Atom prop = XInternAtom(display_, kContentProtectionAtomName, False);
456
457   bool ok = true;
458   // TODO(kcwu): Move this to x11_util (similar method calls in this file and
459   // output_util.cc)
460   success = XRRGetOutputProperty(display_,
461                                  output_id,
462                                  prop,
463                                  0,
464                                  100,
465                                  False,
466                                  False,
467                                  AnyPropertyType,
468                                  &actual_type,
469                                  &actual_format,
470                                  &nitems,
471                                  &bytes_after,
472                                  &values);
473   if (actual_type == None) {
474     LOG(ERROR) << "Property '" << kContentProtectionAtomName
475                << "' does not exist";
476     ok = false;
477   } else if (success == Success && actual_type == XA_ATOM &&
478              actual_format == 32 && nitems == 1) {
479     Atom value = reinterpret_cast<Atom*>(values)[0];
480     if (value == XInternAtom(display_, kProtectionUndesiredAtomName, False)) {
481       *state = HDCP_STATE_UNDESIRED;
482     } else if (value ==
483                XInternAtom(display_, kProtectionDesiredAtomName, False)) {
484       *state = HDCP_STATE_DESIRED;
485     } else if (value ==
486                XInternAtom(display_, kProtectionEnabledAtomName, False)) {
487       *state = HDCP_STATE_ENABLED;
488     } else {
489       LOG(ERROR) << "Unknown " << kContentProtectionAtomName
490                  << " value: " << value;
491       ok = false;
492     }
493   } else {
494     LOG(ERROR) << "XRRGetOutputProperty failed";
495     ok = false;
496   }
497   if (values)
498     XFree(values);
499
500   VLOG(3) << "HDCP state: " << ok << "," << *state;
501   return ok;
502 }
503
504 bool NativeDisplayDelegateX11::SetHDCPState(const DisplaySnapshot& output,
505                                             HDCPState state) {
506   Atom name = XInternAtom(display_, kContentProtectionAtomName, False);
507   Atom value = None;
508   switch (state) {
509     case HDCP_STATE_UNDESIRED:
510       value = XInternAtom(display_, kProtectionUndesiredAtomName, False);
511       break;
512     case HDCP_STATE_DESIRED:
513       value = XInternAtom(display_, kProtectionDesiredAtomName, False);
514       break;
515     default:
516       NOTREACHED() << "Invalid HDCP state: " << state;
517       return false;
518   }
519   gfx::X11ErrorTracker err_tracker;
520   unsigned char* data = reinterpret_cast<unsigned char*>(&value);
521   RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output();
522   XRRChangeOutputProperty(
523       display_, output_id, name, XA_ATOM, 32, PropModeReplace, data, 1);
524   if (err_tracker.FoundNewError()) {
525     LOG(ERROR) << "XRRChangeOutputProperty failed";
526     return false;
527   } else {
528     return true;
529   }
530 }
531
532 void NativeDisplayDelegateX11::DestroyUnusedCrtcs() {
533   CHECK(screen_) << "Server not grabbed";
534
535   for (int i = 0; i < screen_->ncrtc; ++i) {
536     bool in_use = false;
537     for (ScopedVector<DisplaySnapshot>::const_iterator it =
538              cached_outputs_.begin();
539          it != cached_outputs_.end();
540          ++it) {
541       DisplaySnapshotX11* x11_output = static_cast<DisplaySnapshotX11*>(*it);
542       if (screen_->crtcs[i] == x11_output->crtc()) {
543         in_use = true;
544         break;
545       }
546     }
547
548     if (!in_use)
549       ConfigureCrtc(screen_->crtcs[i], None, None, 0, 0);
550   }
551 }
552
553 void NativeDisplayDelegateX11::UpdateCrtcsForNewFramebuffer(
554     const gfx::Size& min_screen_size) {
555   CHECK(screen_) << "Server not grabbed";
556   // Setting the screen size will fail if any CRTC doesn't fit afterwards.
557   // At the same time, turning CRTCs off and back on uses up a lot of time.
558   // This function tries to be smart to avoid too many off/on cycles:
559   // - We set the new modes on CRTCs, if they fit in both the old and new
560   //   FBs, and park them at (0,0)
561   // - We disable the CRTCs we will need but don't fit in the old FB. Those
562   //   will be reenabled after the resize.
563   // We don't worry about the cached state of the outputs here since we are
564   // not interested in the state we are setting - we just try to get the CRTCs
565   // out of the way so we can rebuild the frame buffer.
566   gfx::Rect fb_rect(min_screen_size);
567   for (ScopedVector<DisplaySnapshot>::const_iterator it =
568            cached_outputs_.begin();
569        it != cached_outputs_.end();
570        ++it) {
571     DisplaySnapshotX11* x11_output = static_cast<DisplaySnapshotX11*>(*it);
572     const DisplayMode* mode_info = x11_output->current_mode();
573     RROutput output = x11_output->output();
574     RRMode mode = None;
575
576     if (mode_info) {
577       mode = static_cast<const DisplayModeX11*>(mode_info)->mode_id();
578
579       if (!fb_rect.Contains(gfx::Rect(mode_info->size()))) {
580         // In case our CRTC doesn't fit in common area of our current and about
581         // to be resized framebuffer, disable it.
582         // It'll get reenabled after we resize the framebuffer.
583         mode = None;
584         output = None;
585         mode_info = NULL;
586       }
587     }
588
589     ConfigureCrtc(x11_output->crtc(), mode, output, 0, 0);
590   }
591 }
592
593 bool NativeDisplayDelegateX11::IsOutputAspectPreservingScaling(RROutput id) {
594   bool ret = false;
595
596   Atom scaling_prop = XInternAtom(display_, "scaling mode", False);
597   Atom full_aspect_atom = XInternAtom(display_, "Full aspect", False);
598   if (scaling_prop == None || full_aspect_atom == None)
599     return false;
600
601   int nprop = 0;
602   Atom* props = XRRListOutputProperties(display_, id, &nprop);
603   for (int j = 0; j < nprop && !ret; j++) {
604     Atom prop = props[j];
605     if (scaling_prop == prop) {
606       unsigned char* values = NULL;
607       int actual_format;
608       unsigned long nitems;
609       unsigned long bytes_after;
610       Atom actual_type;
611       int success;
612
613       success = XRRGetOutputProperty(display_,
614                                      id,
615                                      prop,
616                                      0,
617                                      100,
618                                      False,
619                                      False,
620                                      AnyPropertyType,
621                                      &actual_type,
622                                      &actual_format,
623                                      &nitems,
624                                      &bytes_after,
625                                      &values);
626       if (success == Success && actual_type == XA_ATOM && actual_format == 32 &&
627           nitems == 1) {
628         Atom value = reinterpret_cast<Atom*>(values)[0];
629         if (full_aspect_atom == value)
630           ret = true;
631       }
632       if (values)
633         XFree(values);
634     }
635   }
636   if (props)
637     XFree(props);
638
639   return ret;
640 }
641
642
643 std::vector<ColorCalibrationProfile>
644 NativeDisplayDelegateX11::GetAvailableColorCalibrationProfiles(
645     const DisplaySnapshot& output) {
646   // TODO(mukai|marcheu): Checks the system data and fills the result.
647   // Note that the order would be Dynamic -> Standard -> Movie -> Reading.
648   return std::vector<ColorCalibrationProfile>();
649 }
650
651 bool NativeDisplayDelegateX11::SetColorCalibrationProfile(
652     const DisplaySnapshot& output,
653     ColorCalibrationProfile new_profile) {
654   const DisplaySnapshotX11& x11_output =
655       static_cast<const DisplaySnapshotX11&>(output);
656
657   XRRCrtcGamma* gamma_ramp = CreateGammaRampForProfile(x11_output, new_profile);
658
659   if (!gamma_ramp)
660     return false;
661
662   int gamma_ramp_size = XRRGetCrtcGammaSize(display_, x11_output.crtc());
663   XRRSetCrtcGamma(display_,
664                   x11_output.crtc(),
665                   ResampleGammaRamp(gamma_ramp, gamma_ramp_size));
666   XRRFreeGamma(gamma_ramp);
667   return true;
668 }
669
670 XRRCrtcGamma* NativeDisplayDelegateX11::CreateGammaRampForProfile(
671     const DisplaySnapshotX11& x11_output,
672     ColorCalibrationProfile new_profile) {
673   // TODO(mukai|marcheu): Creates the appropriate gamma ramp data from the
674   // profile enum. It would be served by the vendor.
675   return NULL;
676 }
677
678 void NativeDisplayDelegateX11::DrawBackground() {
679   if (!background_color_argb_)
680     return;
681   // Configuring CRTCs/Framebuffer clears the boot screen image.  Paint the
682   // same background color after updating framebuffer to minimize the
683   // duration of black screen at boot time.
684   XColor color;
685   Colormap colormap = DefaultColormap(display_, 0);
686   // XColor uses 16 bits per color.
687   color.red = (background_color_argb_ & 0x00FF0000) >> 8;
688   color.green = (background_color_argb_ & 0x0000FF00);
689   color.blue = (background_color_argb_ & 0x000000FF) << 8;
690   color.flags = DoRed | DoGreen | DoBlue;
691   XAllocColor(display_, colormap, &color);
692
693   GC gc = XCreateGC(display_, window_, 0, 0);
694   XSetForeground(display_, gc, color.pixel);
695   XSetFillStyle(display_, gc, FillSolid);
696   int width = DisplayWidth(display_, DefaultScreen(display_));
697   int height = DisplayHeight(display_, DefaultScreen(display_));
698   XFillRectangle(display_, window_, gc, 0, 0, width, height);
699   XFreeGC(display_, gc);
700   XFreeColors(display_, colormap, &color.pixel, 1, 0);
701 }
702
703 }  // namespace ui