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"
9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop.h"
11 #include "ui/gfx/x/x11_switches.h"
15 XDisplay
* GetXDisplay() {
16 static XDisplay
* display
= NULL
;
18 display
= OpenNewXDisplay();
22 XDisplay
* OpenNewXDisplay() {
23 #if defined(OS_CHROMEOS)
24 return XOpenDisplay(NULL
);
26 std::string display_str
= base::CommandLine::ForCurrentProcess()->
27 GetSwitchValueASCII(switches::kX11Display
);
28 return XOpenDisplay(display_str
.empty() ? NULL
: display_str
.c_str());
32 void PutARGBImage(XDisplay
* display
,
33 void* visual
, int depth
,
34 XID pixmap
, void* pixmap_gc
,
36 int width
, int height
) {
46 int BitsPerPixelForPixmapDepth(XDisplay
* dpy
, int depth
) {
48 XPixmapFormatValues
* formats
= XListPixmapFormats(dpy
, &count
);
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
;
61 return bits_per_pixel
;
64 void PutARGBImage(XDisplay
* display
,
65 void* visual
, int depth
,
66 XID pixmap
, void* pixmap_gc
,
68 int data_width
, int data_height
,
71 int copy_width
, int copy_height
) {
72 // TODO(scherkus): potential performance impact... consider passing in as a
74 int pixmap_bpp
= BitsPerPixelForPixmapDepth(display
, depth
);
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
;
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
);
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.
112 static_cast<uint8_t*>(malloc(4 * data_width
* data_height
));
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
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
);
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.
138 static_cast<uint16_t*>(malloc(2 * data_width
* data_height
));
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
);
163 LOG(FATAL
) << "Sorry, we don't support your visual depth without "
164 "Xrender support (depth:" << depth
165 << " bpp:" << pixmap_bpp
<< ")";