Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

x11_display.cpp

00001 /*****************************************************************************
00002  * x11_display.cpp
00003  *****************************************************************************
00004  * Copyright (C) 2003 the VideoLAN team
00005  * $Id: x11_display.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet     <[email protected]>
00008  *          Olivier Teulière <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 #ifdef X11_SKINS
00026 
00027 #include <X11/Xlib.h>
00028 #include <X11/Xutil.h>
00029 #include <X11/extensions/shape.h>
00030 
00031 #include "x11_display.hpp"
00032 #include "../src/logger.hpp"
00033 
00034 // Macro to compute a pixel value
00035 #define PUT_PIXEL(value, r, g, b, type) \
00036     value = \
00037         ( ((type)r >> m_redRightShift) << m_redLeftShift ) | \
00038         ( ((type)g >> m_greenRightShift) << m_greenLeftShift ) | \
00039         ( ((type)b >> m_blueRightShift) << m_blueLeftShift );
00040 
00041 // Macro to blend a pixel with another color
00042 #define BLEND_PIXEL(value, r, g, b, a, type) \
00043     uint16_t temp; \
00044     temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift)); \
00045     uint8_t red = r + ( temp * (255 - a) ) / 255; \
00046     temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift)); \
00047     uint8_t green = g + ( temp * (255 - a) ) / 255; \
00048     temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift)); \
00049     uint8_t blue = b + ( temp * (255 - a) ) / 255; \
00050     PUT_PIXEL(value, red, green, blue, type)
00051 
00052 
00053 X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
00054     m_mainWindow( 0 ), m_gc( NULL ), m_colormap( 0 )
00055 {
00056     // Open a connection to the X Server
00057     m_pDisplay = XOpenDisplay( NULL );
00058 
00059     if( m_pDisplay == NULL )
00060     {
00061         MSG_ERR( "Cannot open display" );
00062         return;
00063     }
00064 
00065     // Load the XShape extension
00066     int event, error;
00067     XShapeQueryExtension( m_pDisplay, &event, &error );
00068 
00069     // Get the display parameters
00070     int screen = DefaultScreen( m_pDisplay );
00071     int depth = DefaultDepth( m_pDisplay, screen );
00072     int order = ImageByteOrder( m_pDisplay );
00073     Window root = DefaultRootWindow( m_pDisplay );
00074 
00075     // Template for looking up the XVisualInfo
00076     XVisualInfo xVInfoTemplate;
00077     xVInfoTemplate.screen = screen;
00078     xVInfoTemplate.depth = depth;
00079 
00080     XVisualInfo *pVInfo = NULL;
00081     int vCount = 0;
00082 
00083     switch( depth )
00084     {
00085         case 8:
00086             xVInfoTemplate.c_class = DirectColor;
00087             // Get the DirectColor visual
00088             pVInfo = XGetVisualInfo( m_pDisplay, VisualScreenMask |
00089                                      VisualClassMask, &xVInfoTemplate,
00090                                      &vCount );
00091             if( pVInfo == NULL )
00092             {
00093                 msg_Err( getIntf(), "no DirectColor visual available" );
00094                 m_pDisplay = NULL;
00095                 break;
00096             }
00097             m_pVisual = pVInfo->visual;
00098 
00099             // Compute the color shifts
00100             getShifts( pVInfo->red_mask, m_redLeftShift, m_redRightShift );
00101             getShifts( pVInfo->green_mask, m_greenLeftShift,
00102                        m_greenRightShift );
00103             getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
00104 
00105             // Create a color map
00106             m_colormap = XCreateColormap( m_pDisplay, root,
00107                     DefaultVisual( m_pDisplay, screen ), AllocAll );
00108 
00109             // Create the palette
00110             XColor pColors[255];
00111             for( uint16_t i = 0; i < 255; i++ )
00112             {
00113                 // kludge: colors are indexed reversely because color 255 seems
00114                 // to bereserved for black even if we try to set it to white
00115                 pColors[i].pixel = 254-i;
00116                 pColors[i].pad   = 0;
00117                 pColors[i].flags = DoRed | DoGreen | DoBlue;
00118                 pColors[i].red   =
00119                     (i >> m_redLeftShift) << (m_redRightShift + 8);
00120                 pColors[i].green =
00121                     (i >> m_greenLeftShift) << (m_greenRightShift + 8);
00122                 pColors[i].blue  =
00123                     (i >> m_blueLeftShift) << (m_blueRightShift + 8);
00124             }
00125             XStoreColors( m_pDisplay, m_colormap, pColors, 255 );
00126             blendPixelImpl = &X11Display::blendPixel8;
00127             putPixelImpl = &X11Display::putPixel8;
00128             m_pixelSize = 1;
00129             break;
00130 
00131         case 15:
00132         case 16:
00133         case 24:
00134         case 32:
00135             // Get the TrueColor visual
00136             xVInfoTemplate.c_class = TrueColor;
00137             pVInfo = XGetVisualInfo( m_pDisplay, VisualScreenMask |
00138                                      VisualDepthMask | VisualClassMask,
00139                                      &xVInfoTemplate, &vCount );
00140             if( pVInfo == NULL )
00141             {
00142                 msg_Err( getIntf(), "No TrueColor visual for depth %d",
00143                          depth );
00144                 m_pDisplay = NULL;
00145                 break;
00146             }
00147             m_pVisual = pVInfo->visual;
00148 
00149             // Compute the color shifts
00150             getShifts( pVInfo->red_mask, m_redLeftShift, m_redRightShift );
00151             getShifts( pVInfo->green_mask, m_greenLeftShift,
00152                        m_greenRightShift );
00153             getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
00154 
00155             if( depth == 15 || depth == 16 )
00156             {
00157                 if( order == MSBFirst )
00158                 {
00159                     blendPixelImpl = &X11Display::blendPixel16MSB;
00160                     putPixelImpl = &X11Display::putPixel16MSB;
00161                 }
00162                 else
00163                 {
00164                     blendPixelImpl = &X11Display::blendPixel16LSB;
00165                     putPixelImpl = &X11Display::putPixel16LSB;
00166                 }
00167                 m_pixelSize = 2;
00168             }
00169             else
00170             {
00171                 if( order == MSBFirst )
00172                 {
00173                     blendPixelImpl = &X11Display::blendPixel32MSB;
00174                     putPixelImpl = &X11Display::putPixel32MSB;
00175                 }
00176                 else
00177                 {
00178                     blendPixelImpl = &X11Display::blendPixel32LSB;
00179                     putPixelImpl = &X11Display::putPixel32LSB;
00180                 }
00181                 m_pixelSize = 4;
00182             }
00183             break;
00184 
00185         default:
00186             msg_Err( getIntf(), "Unsupported depth: %d bpp\n", depth );
00187             m_pDisplay = NULL;
00188             break;
00189     }
00190 
00191     // Free the visual info
00192     if( pVInfo )
00193     {
00194         XFree( pVInfo );
00195     }
00196 
00197     // Create a graphics context that doesn't generate GraphicsExpose events
00198     if( m_pDisplay )
00199     {
00200         XGCValues xgcvalues;
00201         xgcvalues.graphics_exposures = False;
00202         m_gc = XCreateGC( m_pDisplay, root, GCGraphicsExposures, &xgcvalues );
00203 
00204         // Create a parent window to have a single task in the task bar
00205         XSetWindowAttributes attr;
00206         m_mainWindow = XCreateWindow( m_pDisplay, root, 0, 0, 1, 1, 0, 0,
00207                                       InputOutput, CopyFromParent, 0, &attr );
00208 
00209         // Changing decorations
00210         struct {
00211             unsigned long flags;
00212             unsigned long functions;
00213             unsigned long decorations;
00214             long input_mode;
00215             unsigned long status;
00216         } motifWmHints;
00217         Atom hints_atom = XInternAtom( m_pDisplay, "_MOTIF_WM_HINTS", False );
00218         motifWmHints.flags = 2;    // MWM_HINTS_DECORATIONS;
00219         motifWmHints.decorations = 0;
00220         XChangeProperty( m_pDisplay, m_mainWindow, hints_atom, hints_atom, 32,
00221                          PropModeReplace, (unsigned char *)&motifWmHints,
00222                          sizeof( motifWmHints ) / sizeof( long ) );
00223 
00224         // Change the window title
00225         XStoreName( m_pDisplay, m_mainWindow, "VLC Media Player" );
00226 
00227         // Receive map notify events
00228         XSelectInput( m_pDisplay, m_mainWindow, StructureNotifyMask );
00229 
00230         // Set an empty mask for the window
00231         Region mask = XCreateRegion();
00232         XShapeCombineRegion( m_pDisplay, m_mainWindow, ShapeBounding, 0, 0,
00233                              mask, ShapeSet );
00234         XDestroyRegion( mask );
00235 
00236         // Map the window
00237         XMapWindow( m_pDisplay, m_mainWindow);
00238 
00239         // Move it outside the screen to avoid seeing it in workspace selector
00240         XMoveWindow( m_pDisplay, m_mainWindow, -10, -10 );
00241     }
00242 }
00243 
00244 
00245 X11Display::~X11Display()
00246 {
00247     if( m_mainWindow )
00248     {
00249         XDestroyWindow( m_pDisplay, m_mainWindow );
00250     }
00251     if( m_gc )
00252     {
00253         XFreeGC( m_pDisplay, m_gc );
00254     }
00255     if( m_colormap )
00256     {
00257         XFreeColormap( m_pDisplay, m_colormap );
00258     }
00259     if( m_pDisplay )
00260     {
00261         XCloseDisplay( m_pDisplay );
00262     }
00263 }
00264 
00265 
00266 void X11Display::getShifts( uint32_t mask, int &rLeftShift,
00267                             int &rRightShift ) const
00268 {
00269     for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ )
00270     {
00271         mask >>= 1;
00272     }
00273     for( rRightShift = 8; (mask & 1) ; rRightShift--)
00274     {
00275         mask >>= 1;
00276     }
00277     if( rRightShift < 0 )
00278     {
00279         rLeftShift -= rRightShift;
00280         rRightShift = 0;
00281     }
00282 }
00283 
00284 
00285 void X11Display::blendPixel8( uint8_t *pPixel, uint8_t r, uint8_t g,
00286                               uint8_t b, uint8_t a ) const
00287 {
00288     uint8_t value = 255 - *pPixel;
00289 
00290     BLEND_PIXEL(value, r, g, b, a, uint8_t)
00291 
00292     *pPixel = 255 - value;
00293 }
00294 
00295 
00296 void X11Display::blendPixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00297                                   uint8_t b, uint8_t a ) const
00298 {
00299     uint16_t value = pPixel[1] | pPixel[0] << 8;
00300 
00301     BLEND_PIXEL(value, r, g, b, a, uint16_t)
00302 
00303     pPixel[1] = value; value >>= 8;
00304     pPixel[0] = value;
00305 }
00306 
00307 
00308 void X11Display::blendPixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00309                                   uint8_t b, uint8_t a ) const
00310 {
00311     uint16_t value = pPixel[0] | pPixel[1] << 8;
00312 
00313     BLEND_PIXEL(value, r, g, b, a, uint16_t)
00314 
00315     pPixel[0] = value; value >>= 8;
00316     pPixel[1] = value;
00317 }
00318 
00319 
00320 void X11Display::blendPixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00321                                   uint8_t b, uint8_t a ) const
00322 {
00323     uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
00324                           pPixel[0] << 24;
00325 
00326     BLEND_PIXEL(value, r, g, b, a, uint32_t)
00327 
00328     pPixel[3] = value; value >>= 8;
00329     pPixel[2] = value; value >>= 8;
00330     pPixel[1] = value; value >>= 8;
00331     pPixel[0] = value;
00332 }
00333 
00334 
00335 void X11Display::blendPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00336                                   uint8_t b, uint8_t a ) const
00337 {
00338     uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
00339                           pPixel[3] << 24;
00340 
00341     BLEND_PIXEL(value, r, g, b, a, uint32_t)
00342 
00343     pPixel[0] = value; value >>= 8;
00344     pPixel[1] = value; value >>= 8;
00345     pPixel[2] = value; value >>= 8;
00346     pPixel[3] = value;
00347 }
00348 
00349 
00350 void X11Display::putPixel8( uint8_t *pPixel, uint8_t r, uint8_t g,
00351                             uint8_t b, uint8_t a ) const
00352 {
00353     uint8_t value = 255 - *pPixel;
00354 
00355     PUT_PIXEL(value, r, g, b, uint8_t)
00356 
00357     *pPixel = 255 - value;
00358 }
00359 
00360 
00361 void X11Display::putPixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00362                                 uint8_t b, uint8_t a ) const
00363 {
00364     uint16_t value = pPixel[1] | pPixel[0] << 8;
00365 
00366     PUT_PIXEL(value, r, g, b, uint16_t)
00367 
00368     pPixel[1] = value; value >>= 8;
00369     pPixel[0] = value;
00370 }
00371 
00372 
00373 void X11Display::putPixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00374                                 uint8_t b, uint8_t a ) const
00375 {
00376     uint16_t value = pPixel[0] | pPixel[1] << 8;
00377 
00378     PUT_PIXEL(value, r, g, b, uint16_t)
00379 
00380     pPixel[0] = value; value >>= 8;
00381     pPixel[1] = value;
00382 }
00383 
00384 
00385 void X11Display::putPixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00386                                 uint8_t b, uint8_t a ) const
00387 {
00388     uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
00389                           pPixel[0] << 24;
00390 
00391     PUT_PIXEL(value, r, g, b, uint32_t)
00392 
00393     pPixel[3] = value; value >>= 8;
00394     pPixel[2] = value; value >>= 8;
00395     pPixel[1] = value; value >>= 8;
00396     pPixel[0] = value;
00397 }
00398 
00399 
00400 void X11Display::putPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
00401                                 uint8_t b, uint8_t a ) const
00402 {
00403     uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
00404                           pPixel[3] << 24;
00405 
00406     PUT_PIXEL(value, r, g, b, uint32_t)
00407 
00408     pPixel[0] = value; value >>= 8;
00409     pPixel[1] = value; value >>= 8;
00410     pPixel[2] = value; value >>= 8;
00411     pPixel[3] = value;
00412 }
00413 
00414 
00415 unsigned long X11Display::getPixelValue( uint8_t r, uint8_t g, uint8_t b )
00416     const
00417 {
00418     unsigned long value;
00419 
00420     PUT_PIXEL(value, r, g, b, uint32_t)
00421 
00422     if( m_pixelSize == 1 )
00423     {
00424         return 255 - value;
00425     }
00426     else
00427     {
00428         return value;
00429     }
00430 }
00431 
00432 
00433 #endif

Generated on Tue Dec 20 10:14:44 2005 for vlc-0.8.4a by  doxygen 1.4.2