6c4f62db989be3c6946efea4119f51c2532f8ff1
[platform/framework/web/crosswalk.git] / src / ui / gfx / x / x11_types.cc
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
11 namespace gfx {
12
13 XDisplay* GetXDisplay() {
14   static XDisplay* display = NULL;
15   if (!display)
16     display = XOpenDisplay(NULL);
17   return display;
18 }
19
20 void 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
34 int 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
52 void 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