Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / gfx / x / x11_types.cc
blob54a0816c65236121dd6852a21a87777f03b43efb
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 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count);
49 if (!formats)
50 return -1;
52 int bits_per_pixel = -1;
53 for (int i = 0; i < count; ++i) {
54 if (formats[i].depth == depth) {
55 bits_per_pixel = formats[i].bits_per_pixel;
56 break;
60 XFree(formats);
61 return bits_per_pixel;
64 void PutARGBImage(XDisplay* display,
65 void* visual, int depth,
66 XID pixmap, void* pixmap_gc,
67 const uint8* data,
68 int data_width, int data_height,
69 int src_x, int src_y,
70 int dst_x, int dst_y,
71 int copy_width, int copy_height) {
72 // TODO(scherkus): potential performance impact... consider passing in as a
73 // parameter.
74 int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth);
76 XImage image;
77 memset(&image, 0, sizeof(image));
79 image.width = data_width;
80 image.height = data_height;
81 image.format = ZPixmap;
82 image.byte_order = LSBFirst;
83 image.bitmap_unit = 8;
84 image.bitmap_bit_order = LSBFirst;
85 image.depth = depth;
86 image.bits_per_pixel = pixmap_bpp;
87 image.bytes_per_line = data_width * pixmap_bpp / 8;
89 if (pixmap_bpp == 32) {
90 image.red_mask = 0xff0000;
91 image.green_mask = 0xff00;
92 image.blue_mask = 0xff;
94 // If the X server depth is already 32-bits and the color masks match,
95 // then our job is easy.
96 Visual* vis = static_cast<Visual*>(visual);
97 if (image.red_mask == vis->red_mask &&
98 image.green_mask == vis->green_mask &&
99 image.blue_mask == vis->blue_mask) {
100 image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
101 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
102 src_x, src_y, dst_x, dst_y,
103 copy_width, copy_height);
104 } else {
105 // Otherwise, we need to shuffle the colors around. Assume red and blue
106 // need to be swapped.
108 // It's possible to use some fancy SSE tricks here, but since this is the
109 // slow path anyway, we do it slowly.
111 uint8_t* bitmap32 =
112 static_cast<uint8_t*>(malloc(4 * data_width * data_height));
113 if (!bitmap32)
114 return;
115 uint8_t* const orig_bitmap32 = bitmap32;
116 const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
117 for (int y = 0; y < data_height; ++y) {
118 for (int x = 0; x < data_width; ++x) {
119 const uint32_t pixel = *(bitmap_in++);
120 bitmap32[0] = (pixel >> 16) & 0xff; // Red
121 bitmap32[1] = (pixel >> 8) & 0xff; // Green
122 bitmap32[2] = pixel & 0xff; // Blue
123 bitmap32[3] = (pixel >> 24) & 0xff; // Alpha
124 bitmap32 += 4;
127 image.data = reinterpret_cast<char*>(orig_bitmap32);
128 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
129 src_x, src_y, dst_x, dst_y,
130 copy_width, copy_height);
131 free(orig_bitmap32);
133 } else if (pixmap_bpp == 16) {
134 // Some folks have VNC setups which still use 16-bit visuals and VNC
135 // doesn't include Xrender.
137 uint16_t* bitmap16 =
138 static_cast<uint16_t*>(malloc(2 * data_width * data_height));
139 if (!bitmap16)
140 return;
141 uint16_t* const orig_bitmap16 = bitmap16;
142 const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
143 for (int y = 0; y < data_height; ++y) {
144 for (int x = 0; x < data_width; ++x) {
145 const uint32_t pixel = *(bitmap_in++);
146 uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
147 ((pixel >> 5) & 0x07e0) |
148 ((pixel >> 3) & 0x001f);
149 *(bitmap16++) = out_pixel;
153 image.data = reinterpret_cast<char*>(orig_bitmap16);
154 image.red_mask = 0xf800;
155 image.green_mask = 0x07e0;
156 image.blue_mask = 0x001f;
158 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
159 src_x, src_y, dst_x, dst_y,
160 copy_width, copy_height);
161 free(orig_bitmap16);
162 } else {
163 LOG(FATAL) << "Sorry, we don't support your visual depth without "
164 "Xrender support (depth:" << depth
165 << " bpp:" << pixmap_bpp << ")";
169 } // namespace gfx