[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / ui / gfx / x / x11_types.cc
blobe74129e216a77cc8d2bd80c45c5f45a39fcc3672
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.
5 #include "ui/gfx/x/x11_types.h"
7 #include <X11/Xlib.h>
9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop.h"
11 #include "ui/gfx/x/x11_switches.h"
13 namespace gfx {
15 XDisplay* GetXDisplay() {
16 static XDisplay* display = NULL;
17 if (!display)
18 display = OpenNewXDisplay();
19 return display;
22 XDisplay* OpenNewXDisplay() {
23 #if defined(OS_CHROMEOS)
24 return XOpenDisplay(NULL);
25 #else
26 std::string display_str = base::CommandLine::ForCurrentProcess()->
27 GetSwitchValueASCII(switches::kX11Display);
28 return XOpenDisplay(display_str.empty() ? NULL : display_str.c_str());
29 #endif
32 void PutARGBImage(XDisplay* display,
33 void* visual, int depth,
34 XID pixmap, void* pixmap_gc,
35 const uint8* data,
36 int width, int height) {
37 PutARGBImage(display,
38 visual, depth,
39 pixmap, pixmap_gc,
40 data, width, height,
41 0, 0, // src_x, src_y
42 0, 0, // dst_x, dst_y
43 width, height);
46 int BitsPerPixelForPixmapDepth(XDisplay* dpy, int depth) {
47 int count;
48 XScopedPtr<XPixmapFormatValues[]> formats(XListPixmapFormats(dpy, &count));
49 if (!formats)
50 return -1;
52 for (int i = 0; i < count; ++i) {
53 if (formats[i].depth == depth)
54 return formats[i].bits_per_pixel;
57 return -1;
60 void PutARGBImage(XDisplay* display,
61 void* visual, int depth,
62 XID pixmap, void* pixmap_gc,
63 const uint8* data,
64 int data_width, int data_height,
65 int src_x, int src_y,
66 int dst_x, int dst_y,
67 int copy_width, int copy_height) {
68 // TODO(scherkus): potential performance impact... consider passing in as a
69 // parameter.
70 int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth);
72 XImage image;
73 memset(&image, 0, sizeof(image));
75 image.width = data_width;
76 image.height = data_height;
77 image.format = ZPixmap;
78 image.byte_order = LSBFirst;
79 image.bitmap_unit = 8;
80 image.bitmap_bit_order = LSBFirst;
81 image.depth = depth;
82 image.bits_per_pixel = pixmap_bpp;
83 image.bytes_per_line = data_width * pixmap_bpp / 8;
85 if (pixmap_bpp == 32) {
86 image.red_mask = 0xff0000;
87 image.green_mask = 0xff00;
88 image.blue_mask = 0xff;
90 // If the X server depth is already 32-bits and the color masks match,
91 // then our job is easy.
92 Visual* vis = static_cast<Visual*>(visual);
93 if (image.red_mask == vis->red_mask &&
94 image.green_mask == vis->green_mask &&
95 image.blue_mask == vis->blue_mask) {
96 image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
97 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
98 src_x, src_y, dst_x, dst_y,
99 copy_width, copy_height);
100 } else {
101 // Otherwise, we need to shuffle the colors around. Assume red and blue
102 // need to be swapped.
104 // It's possible to use some fancy SSE tricks here, but since this is the
105 // slow path anyway, we do it slowly.
107 uint8_t* bitmap32 =
108 static_cast<uint8_t*>(malloc(4 * data_width * data_height));
109 if (!bitmap32)
110 return;
111 uint8_t* const orig_bitmap32 = bitmap32;
112 const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
113 for (int y = 0; y < data_height; ++y) {
114 for (int x = 0; x < data_width; ++x) {
115 const uint32_t pixel = *(bitmap_in++);
116 bitmap32[0] = (pixel >> 16) & 0xff; // Red
117 bitmap32[1] = (pixel >> 8) & 0xff; // Green
118 bitmap32[2] = pixel & 0xff; // Blue
119 bitmap32[3] = (pixel >> 24) & 0xff; // Alpha
120 bitmap32 += 4;
123 image.data = reinterpret_cast<char*>(orig_bitmap32);
124 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
125 src_x, src_y, dst_x, dst_y,
126 copy_width, copy_height);
127 free(orig_bitmap32);
129 } else if (pixmap_bpp == 16) {
130 // Some folks have VNC setups which still use 16-bit visuals and VNC
131 // doesn't include Xrender.
133 uint16_t* bitmap16 =
134 static_cast<uint16_t*>(malloc(2 * data_width * data_height));
135 if (!bitmap16)
136 return;
137 uint16_t* const orig_bitmap16 = bitmap16;
138 const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
139 for (int y = 0; y < data_height; ++y) {
140 for (int x = 0; x < data_width; ++x) {
141 const uint32_t pixel = *(bitmap_in++);
142 uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
143 ((pixel >> 5) & 0x07e0) |
144 ((pixel >> 3) & 0x001f);
145 *(bitmap16++) = out_pixel;
149 image.data = reinterpret_cast<char*>(orig_bitmap16);
150 image.red_mask = 0xf800;
151 image.green_mask = 0x07e0;
152 image.blue_mask = 0x001f;
154 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
155 src_x, src_y, dst_x, dst_y,
156 copy_width, copy_height);
157 free(orig_bitmap16);
158 } else {
159 LOG(FATAL) << "Sorry, we don't support your visual depth without "
160 "Xrender support (depth:" << depth
161 << " bpp:" << pixmap_bpp << ")";
165 } // namespace gfx