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 XScopedPtr
<XPixmapFormatValues
[]> formats(XListPixmapFormats(dpy
, &count
));
52 for (int i
= 0; i
< count
; ++i
) {
53 if (formats
[i
].depth
== depth
)
54 return formats
[i
].bits_per_pixel
;
60 void PutARGBImage(XDisplay
* display
,
61 void* visual
, int depth
,
62 XID pixmap
, void* pixmap_gc
,
64 int data_width
, int data_height
,
67 int copy_width
, int copy_height
) {
68 // TODO(scherkus): potential performance impact... consider passing in as a
70 int pixmap_bpp
= BitsPerPixelForPixmapDepth(display
, depth
);
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
;
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
);
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.
108 static_cast<uint8_t*>(malloc(4 * data_width
* data_height
));
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
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
);
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.
134 static_cast<uint16_t*>(malloc(2 * data_width
* data_height
));
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
);
159 LOG(FATAL
) << "Sorry, we don't support your visual depth without "
160 "Xrender support (depth:" << depth
161 << " bpp:" << pixmap_bpp
<< ")";