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/message_loop/message_loop.h"
13 XDisplay
* GetXDisplay() {
14 return base::MessagePumpForUI::GetDefaultXDisplay();
17 void PutARGBImage(XDisplay
* display
,
18 void* visual
, int depth
,
19 XID pixmap
, void* pixmap_gc
,
21 int width
, int height
) {
31 int BitsPerPixelForPixmapDepth(XDisplay
* dpy
, int depth
) {
33 XPixmapFormatValues
* formats
= XListPixmapFormats(dpy
, &count
);
37 int bits_per_pixel
= -1;
38 for (int i
= 0; i
< count
; ++i
) {
39 if (formats
[i
].depth
== depth
) {
40 bits_per_pixel
= formats
[i
].bits_per_pixel
;
46 return bits_per_pixel
;
49 void PutARGBImage(XDisplay
* display
,
50 void* visual
, int depth
,
51 XID pixmap
, void* pixmap_gc
,
53 int data_width
, int data_height
,
56 int copy_width
, int copy_height
) {
57 // TODO(scherkus): potential performance impact... consider passing in as a
59 int pixmap_bpp
= BitsPerPixelForPixmapDepth(display
, depth
);
62 memset(&image
, 0, sizeof(image
));
64 image
.width
= data_width
;
65 image
.height
= data_height
;
66 image
.format
= ZPixmap
;
67 image
.byte_order
= LSBFirst
;
68 image
.bitmap_unit
= 8;
69 image
.bitmap_bit_order
= LSBFirst
;
71 image
.bits_per_pixel
= pixmap_bpp
;
72 image
.bytes_per_line
= data_width
* pixmap_bpp
/ 8;
74 if (pixmap_bpp
== 32) {
75 image
.red_mask
= 0xff0000;
76 image
.green_mask
= 0xff00;
77 image
.blue_mask
= 0xff;
79 // If the X server depth is already 32-bits and the color masks match,
80 // then our job is easy.
81 Visual
* vis
= static_cast<Visual
*>(visual
);
82 if (image
.red_mask
== vis
->red_mask
&&
83 image
.green_mask
== vis
->green_mask
&&
84 image
.blue_mask
== vis
->blue_mask
) {
85 image
.data
= const_cast<char*>(reinterpret_cast<const char*>(data
));
86 XPutImage(display
, pixmap
, static_cast<GC
>(pixmap_gc
), &image
,
87 src_x
, src_y
, dst_x
, dst_y
,
88 copy_width
, copy_height
);
90 // Otherwise, we need to shuffle the colors around. Assume red and blue
91 // need to be swapped.
93 // It's possible to use some fancy SSE tricks here, but since this is the
94 // slow path anyway, we do it slowly.
97 static_cast<uint8_t*>(malloc(4 * data_width
* data_height
));
100 uint8_t* const orig_bitmap32
= bitmap32
;
101 const uint32_t* bitmap_in
= reinterpret_cast<const uint32_t*>(data
);
102 for (int y
= 0; y
< data_height
; ++y
) {
103 for (int x
= 0; x
< data_width
; ++x
) {
104 const uint32_t pixel
= *(bitmap_in
++);
105 bitmap32
[0] = (pixel
>> 16) & 0xff; // Red
106 bitmap32
[1] = (pixel
>> 8) & 0xff; // Green
107 bitmap32
[2] = pixel
& 0xff; // Blue
108 bitmap32
[3] = (pixel
>> 24) & 0xff; // Alpha
112 image
.data
= reinterpret_cast<char*>(orig_bitmap32
);
113 XPutImage(display
, pixmap
, static_cast<GC
>(pixmap_gc
), &image
,
114 src_x
, src_y
, dst_x
, dst_y
,
115 copy_width
, copy_height
);
118 } else if (pixmap_bpp
== 16) {
119 // Some folks have VNC setups which still use 16-bit visuals and VNC
120 // doesn't include Xrender.
123 static_cast<uint16_t*>(malloc(2 * data_width
* data_height
));
126 uint16_t* const orig_bitmap16
= bitmap16
;
127 const uint32_t* bitmap_in
= reinterpret_cast<const uint32_t*>(data
);
128 for (int y
= 0; y
< data_height
; ++y
) {
129 for (int x
= 0; x
< data_width
; ++x
) {
130 const uint32_t pixel
= *(bitmap_in
++);
131 uint16_t out_pixel
= ((pixel
>> 8) & 0xf800) |
132 ((pixel
>> 5) & 0x07e0) |
133 ((pixel
>> 3) & 0x001f);
134 *(bitmap16
++) = out_pixel
;
138 image
.data
= reinterpret_cast<char*>(orig_bitmap16
);
139 image
.red_mask
= 0xf800;
140 image
.green_mask
= 0x07e0;
141 image
.blue_mask
= 0x001f;
143 XPutImage(display
, pixmap
, static_cast<GC
>(pixmap_gc
), &image
,
144 src_x
, src_y
, dst_x
, dst_y
,
145 copy_width
, copy_height
);
148 LOG(FATAL
) << "Sorry, we don't support your visual depth without "
149 "Xrender support (depth:" << depth
150 << " bpp:" << pixmap_bpp
<< ")";