]> git.sesse.net Git - vlc/blob - modules/gui/skins2/x11/x11_display.cpp
* all: brand new skins interface ( still _experimental_) for x11 and
[vlc] / modules / gui / skins2 / x11 / x11_display.cpp
1 /*****************************************************************************
2  * x11_display.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: x11_display.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #ifdef X11_SKINS
26
27 #include <X11/Xutil.h>
28 #include <X11/extensions/shape.h>
29
30 #include "x11_display.hpp"
31 #include "../src/logger.hpp"
32
33
34 X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
35     m_gc( NULL )
36 {
37     // Open a connection to the X Server
38     m_pDisplay = XOpenDisplay( NULL );
39     if( m_pDisplay == NULL )
40     {
41         MSG_ERR( "Cannot open display" );
42         return;
43     }
44
45     // Load the XShape extension
46     int event, error;
47     XShapeQueryExtension( m_pDisplay, &event, &error );
48
49     // Get the display parameters
50     int screen = DefaultScreen( m_pDisplay );
51     int depth = DefaultDepth( m_pDisplay, screen );
52     int order = ImageByteOrder( m_pDisplay );
53
54     // Create a graphics context that doesn't generate GraphicsExpose events
55     XGCValues xgcvalues;
56     xgcvalues.graphics_exposures = False;
57     m_gc = XCreateGC( m_pDisplay, DefaultRootWindow( m_pDisplay ),
58                       GCGraphicsExposures, &xgcvalues );
59
60     // Template for looking up the XVisualInfo
61     XVisualInfo xVInfoTemplate;
62     xVInfoTemplate.screen = screen;
63     xVInfoTemplate.depth = depth;
64
65     XVisualInfo *pVInfo = NULL;
66     int vCount = 0;
67
68     switch( depth )
69     {
70         case 16:
71         case 24:
72         case 32:
73             // Get the TrueColor visual
74             xVInfoTemplate.c_class = TrueColor;
75             pVInfo = XGetVisualInfo( m_pDisplay, VisualScreenMask |
76                                      VisualDepthMask | VisualClassMask,
77                                      &xVInfoTemplate, &vCount );
78             if( pVInfo == NULL )
79             {
80                 msg_Err( getIntf(), "No TrueColor visual for depth %d",
81                          depth );
82                 m_pDisplay = NULL;
83                 break;
84             }
85             m_pVisual = pVInfo->visual;
86
87             // Compute the color shifts
88             getShifts( pVInfo->red_mask, m_redLeftShift, m_redRightShift );
89             getShifts( pVInfo->green_mask, m_greenLeftShift,
90                        m_greenRightShift );
91             getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
92
93             if( depth == 16 )
94             {
95                 if( order == MSBFirst )
96                 {
97                     makePixelImpl = &X11Display::makePixel16MSB;
98                 }
99                 else
100                 {
101                     makePixelImpl = &X11Display::makePixel16LSB;
102                 }
103                 m_pixelSize = 2;
104             }
105             else
106             {
107                 if( order == MSBFirst )
108                 {
109                     makePixelImpl = &X11Display::makePixel32MSB;
110                 }
111                 else
112                 {
113                     makePixelImpl = &X11Display::makePixel32LSB;
114                 }
115                 m_pixelSize = 4;
116             }
117             break;
118
119         default:
120             msg_Err( getIntf(), "Unsupported depth: %d bpp\n", depth );
121             m_pDisplay = NULL;
122             break;
123     }
124
125     // Free the visual info
126     if( pVInfo )
127     {
128         XFree( pVInfo );
129     }
130 }
131
132
133 X11Display::~X11Display()
134 {
135     if( m_gc )
136     {
137         XFreeGC( m_pDisplay, m_gc );
138     }
139     if( m_pDisplay )
140     {
141         XCloseDisplay( m_pDisplay );
142     }
143 }
144
145
146 void X11Display::getShifts( uint32_t mask, int &rLeftShift,
147                             int &rRightShift ) const
148 {
149     for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ )
150     {
151         mask >>= 1;
152     }
153     for( rRightShift = 8; (mask & 1) ; rRightShift--)
154     {
155         mask >>= 1;
156     }
157     if( rRightShift < 0 )
158     {
159         rLeftShift -= rRightShift;
160         rRightShift = 0;
161     }
162 }
163
164
165 void X11Display::makePixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
166                                  uint8_t b, uint8_t a ) const
167 {
168     // Get the current pixel value
169     uint16_t value = pPixel[1] | pPixel[0] << 8;
170
171     // Compute the new color values
172     uint16_t temp;
173     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
174     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
175     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
176     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
177     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
178     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
179
180     // Set the new pixel value
181     value =
182         ( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
183         ( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
184         ( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
185
186     pPixel[1] = value;
187     value >>= 8;
188     pPixel[0] = value;
189 }
190
191
192 void X11Display::makePixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
193                                  uint8_t b, uint8_t a ) const
194 {
195     // Get the current pixel value
196     uint16_t value = pPixel[0] | pPixel[1] << 8;
197
198     // Compute the new color values
199     uint16_t temp;
200     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
201     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
202     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
203     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
204     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
205     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
206
207     // Set the new pixel value
208     value =
209         ( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
210         ( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
211         ( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
212
213     pPixel[0] = value;
214     value >>= 8;
215     pPixel[1] = value;
216 }
217
218
219 void X11Display::makePixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
220                                  uint8_t b, uint8_t a ) const
221 {
222     // Get the current pixel value
223     uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
224                           pPixel[0] << 24;
225
226     // Compute the new color values
227     uint16_t temp;
228     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
229     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
230     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
231     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
232     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
233     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
234
235     // Set the new pixel value
236     value =
237         ( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
238         ( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
239         ( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
240
241     pPixel[3] = value;
242     value >>= 8;
243     pPixel[2] = value;
244     value >>= 8;
245     pPixel[1] = value;
246     value >>= 8;
247     pPixel[0] = value;
248 }
249
250
251 void X11Display::makePixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
252                                  uint8_t b, uint8_t a ) const
253 {
254     // Get the current pixel value
255     uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
256                           pPixel[3] << 24;
257
258     // Compute the new color values
259     uint16_t temp;
260     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
261     uint8_t red = ( temp * (255 - a) + r * a ) / 255;
262     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
263     uint8_t green = ( temp * (255 - a) + g * a ) / 255;
264     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
265     uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
266
267     // Set the new pixel value
268     value =
269         ( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
270         ( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
271         ( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
272
273     pPixel[0] = value;
274     value >>= 8;
275     pPixel[1] = value;
276     value >>= 8;
277     pPixel[2] = value;
278     value >>= 8;
279     pPixel[3] = value;
280 }
281
282
283 #endif