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 static XDisplay* display = NULL;
16 display = XOpenDisplay(NULL);
20 void PutARGBImage(XDisplay* display,
21 void* visual, int depth,
22 XID pixmap, void* pixmap_gc,
24 int width, int height) {
34 int BitsPerPixelForPixmapDepth(XDisplay* dpy, int depth) {
36 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count);
40 int bits_per_pixel = -1;
41 for (int i = 0; i < count; ++i) {
42 if (formats[i].depth == depth) {
43 bits_per_pixel = formats[i].bits_per_pixel;
49 return bits_per_pixel;
52 void PutARGBImage(XDisplay* display,
53 void* visual, int depth,
54 XID pixmap, void* pixmap_gc,
56 int data_width, int data_height,
59 int copy_width, int copy_height) {
60 // TODO(scherkus): potential performance impact... consider passing in as a
62 int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth);
65 memset(&image, 0, sizeof(image));
67 image.width = data_width;
68 image.height = data_height;
69 image.format = ZPixmap;
70 image.byte_order = LSBFirst;
71 image.bitmap_unit = 8;
72 image.bitmap_bit_order = LSBFirst;
74 image.bits_per_pixel = pixmap_bpp;
75 image.bytes_per_line = data_width * pixmap_bpp / 8;
77 if (pixmap_bpp == 32) {
78 image.red_mask = 0xff0000;
79 image.green_mask = 0xff00;
80 image.blue_mask = 0xff;
82 // If the X server depth is already 32-bits and the color masks match,
83 // then our job is easy.
84 Visual* vis = static_cast<Visual*>(visual);
85 if (image.red_mask == vis->red_mask &&
86 image.green_mask == vis->green_mask &&
87 image.blue_mask == vis->blue_mask) {
88 image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
89 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
90 src_x, src_y, dst_x, dst_y,
91 copy_width, copy_height);
93 // Otherwise, we need to shuffle the colors around. Assume red and blue
94 // need to be swapped.
96 // It's possible to use some fancy SSE tricks here, but since this is the
97 // slow path anyway, we do it slowly.
100 static_cast<uint8_t*>(malloc(4 * data_width * data_height));
103 uint8_t* const orig_bitmap32 = bitmap32;
104 const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
105 for (int y = 0; y < data_height; ++y) {
106 for (int x = 0; x < data_width; ++x) {
107 const uint32_t pixel = *(bitmap_in++);
108 bitmap32[0] = (pixel >> 16) & 0xff; // Red
109 bitmap32[1] = (pixel >> 8) & 0xff; // Green
110 bitmap32[2] = pixel & 0xff; // Blue
111 bitmap32[3] = (pixel >> 24) & 0xff; // Alpha
115 image.data = reinterpret_cast<char*>(orig_bitmap32);
116 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
117 src_x, src_y, dst_x, dst_y,
118 copy_width, copy_height);
121 } else if (pixmap_bpp == 16) {
122 // Some folks have VNC setups which still use 16-bit visuals and VNC
123 // doesn't include Xrender.
126 static_cast<uint16_t*>(malloc(2 * data_width * data_height));
129 uint16_t* const orig_bitmap16 = bitmap16;
130 const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
131 for (int y = 0; y < data_height; ++y) {
132 for (int x = 0; x < data_width; ++x) {
133 const uint32_t pixel = *(bitmap_in++);
134 uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
135 ((pixel >> 5) & 0x07e0) |
136 ((pixel >> 3) & 0x001f);
137 *(bitmap16++) = out_pixel;
141 image.data = reinterpret_cast<char*>(orig_bitmap16);
142 image.red_mask = 0xf800;
143 image.green_mask = 0x07e0;
144 image.blue_mask = 0x001f;
146 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
147 src_x, src_y, dst_x, dst_y,
148 copy_width, copy_height);
151 LOG(FATAL) << "Sorry, we don't support your visual depth without "
152 "Xrender support (depth:" << depth
153 << " bpp:" << pixmap_bpp << ")";