x11_types.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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. 4 5#include "ui/gfx/x/x11_types.h" 6 7#include <X11/Xlib.h> 8 9#include "base/message_loop/message_loop.h" 10 11namespace gfx { 12 13XDisplay* GetXDisplay() { 14 static XDisplay* display = NULL; 15 if (!display) 16 display = XOpenDisplay(NULL); 17 return display; 18} 19 20void PutARGBImage(XDisplay* display, 21 void* visual, int depth, 22 XID pixmap, void* pixmap_gc, 23 const uint8* data, 24 int width, int height) { 25 PutARGBImage(display, 26 visual, depth, 27 pixmap, pixmap_gc, 28 data, width, height, 29 0, 0, // src_x, src_y 30 0, 0, // dst_x, dst_y 31 width, height); 32} 33 34int BitsPerPixelForPixmapDepth(XDisplay* dpy, int depth) { 35 int count; 36 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); 37 if (!formats) 38 return -1; 39 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; 44 break; 45 } 46 } 47 48 XFree(formats); 49 return bits_per_pixel; 50} 51 52void PutARGBImage(XDisplay* display, 53 void* visual, int depth, 54 XID pixmap, void* pixmap_gc, 55 const uint8* data, 56 int data_width, int data_height, 57 int src_x, int src_y, 58 int dst_x, int dst_y, 59 int copy_width, int copy_height) { 60 // TODO(scherkus): potential performance impact... consider passing in as a 61 // parameter. 62 int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth); 63 64 XImage image; 65 memset(&image, 0, sizeof(image)); 66 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; 73 image.depth = depth; 74 image.bits_per_pixel = pixmap_bpp; 75 image.bytes_per_line = data_width * pixmap_bpp / 8; 76 77 if (pixmap_bpp == 32) { 78 image.red_mask = 0xff0000; 79 image.green_mask = 0xff00; 80 image.blue_mask = 0xff; 81 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); 92 } else { 93 // Otherwise, we need to shuffle the colors around. Assume red and blue 94 // need to be swapped. 95 // 96 // It's possible to use some fancy SSE tricks here, but since this is the 97 // slow path anyway, we do it slowly. 98 99 uint8_t* bitmap32 = 100 static_cast<uint8_t*>(malloc(4 * data_width * data_height)); 101 if (!bitmap32) 102 return; 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 112 bitmap32 += 4; 113 } 114 } 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); 119 free(orig_bitmap32); 120 } 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. 124 125 uint16_t* bitmap16 = 126 static_cast<uint16_t*>(malloc(2 * data_width * data_height)); 127 if (!bitmap16) 128 return; 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; 138 } 139 } 140 141 image.data = reinterpret_cast<char*>(orig_bitmap16); 142 image.red_mask = 0xf800; 143 image.green_mask = 0x07e0; 144 image.blue_mask = 0x001f; 145 146 XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, 147 src_x, src_y, dst_x, dst_y, 148 copy_width, copy_height); 149 free(orig_bitmap16); 150 } else { 151 LOG(FATAL) << "Sorry, we don't support your visual depth without " 152 "Xrender support (depth:" << depth 153 << " bpp:" << pixmap_bpp << ")"; 154 } 155} 156 157} // namespace gfx 158 159