source: trunk/third/xscreensaver/hacks/bumps.c @ 20148

Revision 20148, 18.7 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- mode: C; tab-width: 4 -*-
2 * Bumps, Copyright (c) 2002 Shane Smit <CodeWeaver@DigitalLoom.org>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation.  No representations are made about the suitability of this
9 * software for any purpose.  It is provided "as is" without express or
10 * implied warranty.
11 *
12 * Module: "bumps.c"
13 * Tab Size: 4
14 *
15 * Description:
16 *  This is typical bump-mapping.  The actual bump map is generated by a screen
17 *  grab.  The light source is represented by a spotlight of random color. This
18 *  spotlight randomly traverses the bump map in a sinus pattern.
19 *
20 *  Essentially, it 3D-izes your desktop, based on color intensity.
21 *
22 * Modification History:
23 *  [10/01/99] - Shane Smit: Creation
24 *  [10/08/99] - Shane Smit: Port to C. (Ick)
25 *  [03/08/02] - Shane Smit: New movement code.
26 *  [09/12/02] - Shane Smit: MIT-SHM XImages.
27 *                                                       Thanks to Kennett Galbraith <http://www.Alpha-II.com/>
28 *                                                       for code optimization.
29 */
30
31#include "bumps.h"
32
33/* This function pointer will point to the appropriate PutPixel*() function below. */
34void (*MyPutPixel)( int8_ *, uint32_ );
35
36void PutPixel32( int8_ *pData, uint32_ pixel )
37{
38        *(uint32_ *)pData = pixel;
39}
40
41void PutPixel24( int8_ *pData, uint32_ pixel )
42{
43        pData[ 2 ] = ( pixel & 0x00FF0000 ) >> 16;
44        pData[ 1 ] = ( pixel & 0x0000FF00 ) >> 8;
45        pData[ 0 ] = ( pixel & 0x000000FF );
46}
47
48void PutPixel16( int8_ *pData, uint32_ pixel )
49{
50        *(uint16_ *)pData = (uint16_)pixel;
51}
52
53void PutPixel8( int8_ *pData, uint32_ pixel )
54{
55        *(uint8_ *)pData = (uint8_)pixel;
56}
57
58/* Creates the light map, which is a circular image... going from black around the edges
59 * to white in the center. */
60void CreateSpotLight( SSpotLight *pSpotLight, uint16_ iDiameter, uint16_ nColorCount )
61{
62        double nDist;
63        int16_ iDistX, iDistY;
64        uint8_ *pLOffset;
65       
66        pSpotLight->nFalloffDiameter = iDiameter;
67        pSpotLight->nFalloffRadius = pSpotLight->nFalloffDiameter / 2;
68        pSpotLight->nLightDiameter = iDiameter / 2;
69        pSpotLight->nLightRadius = pSpotLight->nLightDiameter / 2;
70#ifdef VERBOSE
71        printf( "%s: Falloff Diameter: %d\n", progclass, pSpotLight->nFalloffDiameter );
72        printf( "%s: Spot Light Diameter: %d\n", progclass, pSpotLight->nLightDiameter );
73#endif
74
75        pSpotLight->aLightMap = malloc( pSpotLight->nLightDiameter * pSpotLight->nLightDiameter * sizeof(uint8_) );
76
77        pLOffset = pSpotLight->aLightMap;
78        for( iDistY=-pSpotLight->nLightRadius; iDistY<pSpotLight->nLightRadius; ++iDistY )
79        {
80                for( iDistX=-pSpotLight->nLightRadius; iDistX<pSpotLight->nLightRadius; ++iDistX )
81                {
82                        nDist = sqrt( pow( iDistX+0.5F, 2 ) + pow( iDistY+0.5F, 2 ) );
83                        if( nDist / pSpotLight->nLightRadius <= 1.0f )
84                                *pLOffset = (uint8_)(nColorCount - ( ( nDist / pSpotLight->nLightRadius ) * ( nColorCount - 1 ) ));
85                        else
86                                *pLOffset = 0;
87
88                        ++pLOffset;
89                }
90        }
91               
92        /* Initialize movement variables.       */
93        pSpotLight->nAccelX = 0;
94        pSpotLight->nAccelY = 0;
95        pSpotLight->nVelocityX = ( RANDOM() % 2 ) ? pSpotLight->nVelocityMax : -pSpotLight->nVelocityMax;
96        pSpotLight->nVelocityY = ( RANDOM() % 2 ) ? pSpotLight->nVelocityMax : -pSpotLight->nVelocityMax;
97}
98
99
100/* Calculates the position of the spot light on the screen. */
101void CalcLightPos( SBumps *pBumps )
102{
103        SSpotLight *pSpotLight = &pBumps->SpotLight;
104        float nGravity;
105
106        /* X */
107        if( pSpotLight->nXPos < pSpotLight->nFalloffRadius )                                                    nGravity = 1.0f;
108        else if( pSpotLight->nXPos > pBumps->iWinWidth - pSpotLight->nFalloffRadius )   nGravity = -1.0f;
109        else                                                                                                                                                    nGravity = ( ( RANDOM() % 201 ) / 100.0f ) - 1.0f;
110               
111        pSpotLight->nAccelX += nGravity * ( pSpotLight->nAccelMax / 5.0f );
112        if( pSpotLight->nAccelX < -pSpotLight->nAccelMax )              pSpotLight->nAccelX = -pSpotLight->nAccelMax;
113        else if( pSpotLight->nAccelX > pSpotLight->nAccelMax )  pSpotLight->nAccelX = pSpotLight->nAccelMax;
114
115        pSpotLight->nVelocityX += pSpotLight->nAccelX;
116        if( pSpotLight->nVelocityX < -pSpotLight->nVelocityMax )                pSpotLight->nVelocityX = -pSpotLight->nVelocityMax;
117        else if( pSpotLight->nVelocityX > pSpotLight->nVelocityMax )    pSpotLight->nVelocityX = pSpotLight->nVelocityMax;
118
119        pSpotLight->nXPos += pSpotLight->nVelocityX;
120
121        /* Y */
122        if( pSpotLight->nYPos < pSpotLight->nFalloffRadius )                                                            nGravity = 1.0f;
123        else if( pSpotLight->nYPos > pBumps->iWinHeight - pSpotLight->nFalloffRadius )  nGravity = -1.0f;
124        else                                                                                                                                                    nGravity = ( ( RANDOM() % 201 ) / 100.0f ) - 1.0f;
125               
126        pSpotLight->nAccelY += nGravity * ( pSpotLight->nAccelMax / 5.0f );
127        if( pSpotLight->nAccelY < -pSpotLight->nAccelMax )              pSpotLight->nAccelY = -pSpotLight->nAccelMax;
128        else if( pSpotLight->nAccelY > pSpotLight->nAccelMax )  pSpotLight->nAccelY = pSpotLight->nAccelMax;
129
130        pSpotLight->nVelocityY += pSpotLight->nAccelY;
131        if( pSpotLight->nVelocityY < -pSpotLight->nVelocityMax )                pSpotLight->nVelocityY = -pSpotLight->nVelocityMax;
132        else if( pSpotLight->nVelocityY > pSpotLight->nVelocityMax )    pSpotLight->nVelocityY = pSpotLight->nVelocityMax;
133
134        pSpotLight->nYPos += pSpotLight->nVelocityY;
135}
136
137
138/* Main initialization function. */
139void CreateBumps( SBumps *pBumps, Display *pNewDisplay, Window NewWin )
140{
141        XWindowAttributes XWinAttribs;
142        XGCValues GCValues;
143        int32_ nGCFlags;
144        uint16_ iDiameter;
145
146        /* Make size and velocity a function of window size, so it appears the same at 100x60 as it does in 3200x1200. */
147        XGetWindowAttributes( pNewDisplay, NewWin, &XWinAttribs );
148        pBumps->iWinWidth = XWinAttribs.width;
149        pBumps->iWinHeight = XWinAttribs.height;
150        pBumps->SpotLight.nXPos = XWinAttribs.width / 2.0f;
151        pBumps->SpotLight.nYPos = XWinAttribs.height / 2.0f;
152        pBumps->SpotLight.nVelocityMax = ( ( XWinAttribs.width < XWinAttribs.height ) ? XWinAttribs.width : XWinAttribs.height ) / 140.0f;
153        pBumps->SpotLight.nAccelMax = pBumps->SpotLight.nVelocityMax / 10.0f;
154        pBumps->pDisplay = pNewDisplay;
155        pBumps->Win = NewWin;
156        pBumps->pXImage = NULL;
157       
158        iDiameter = ( ( pBumps->iWinWidth < pBumps->iWinHeight ) ? pBumps->iWinWidth : pBumps->iWinHeight ) / 2;
159
160#ifdef HAVE_XSHM_EXTENSION
161        pBumps->bUseShm = get_boolean_resource( "useSHM", "Boolean" );
162
163        if( pBumps->bUseShm )
164        {
165                pBumps->pXImage = create_xshm_image( pBumps->pDisplay, XWinAttribs.visual, XWinAttribs.depth,
166                                                                                         ZPixmap, NULL, &pBumps->XShmInfo, iDiameter, iDiameter );
167                if( !pBumps->pXImage )
168                {
169                        fprintf( stderr, "%s: Unable to create XShmImage.\n", progname );
170                        pBumps->bUseShm = False;
171                }
172        }
173#endif /* HAVE_XSHM_EXTENSION */
174        if( !pBumps->pXImage )
175        {
176                pBumps->pXImage = XCreateImage( pBumps->pDisplay, XWinAttribs.visual, XWinAttribs.depth,
177                                                                        ZPixmap, 0, NULL, iDiameter, iDiameter, BitmapPad( pBumps->pDisplay ), 0 );
178                pBumps->pXImage->data = malloc( pBumps->pXImage->bytes_per_line * pBumps->pXImage->height * sizeof(int8_) );
179        }
180
181        /* For speed, access the XImage data directly using my own PutPixel routine. */
182        switch( pBumps->pXImage->bits_per_pixel )
183        {
184                case 32:
185                        pBumps->bytesPerPixel = 4;
186                        MyPutPixel = PutPixel32;
187                        break;
188               
189                case 24:
190                        pBumps->bytesPerPixel = 3;
191                        MyPutPixel = PutPixel24;
192                        break;
193
194                case 16:
195                        pBumps->bytesPerPixel = 2;
196                        MyPutPixel = PutPixel16;
197                        break;
198
199                case 8:
200                        pBumps->bytesPerPixel = 1;
201                        MyPutPixel = PutPixel8;
202                        break;
203
204                default:
205                        fprintf( stderr, "%s: Unknown XImage depth.", progname );
206#ifdef HAVE_XSHM_EXTENSION
207                        if( pBumps->bUseShm )
208                                destroy_xshm_image( pBumps->pDisplay, pBumps->pXImage, &pBumps->XShmInfo );
209                        else
210#endif /* HAVE_XSHM_EXTENSION */
211                                XDestroyImage( pBumps->pXImage );
212                        exit( 1 );
213        }
214       
215        GCValues.function = GXcopy;
216        GCValues.subwindow_mode = IncludeInferiors;
217        nGCFlags = GCForeground | GCFunction;
218        if( use_subwindow_mode_p( XWinAttribs.screen, pBumps->Win ) ) /* See grabscreen.c */
219                nGCFlags |= GCSubwindowMode;
220        pBumps->GraphicsContext = XCreateGC( pBumps->pDisplay, pBumps->Win, nGCFlags, &GCValues );
221       
222        SetPalette( pBumps, &XWinAttribs );
223        CreateSpotLight( &pBumps->SpotLight, iDiameter, pBumps->nColorCount );
224        InitBumpMap( pBumps, &XWinAttribs );
225
226        XSetWindowBackground( pBumps->pDisplay, pBumps->Win, pBumps->aColors[ 0 ] );
227        XClearWindow (pBumps->pDisplay, pBumps->Win);
228}
229
230
231/* Creates a specialized phong shade palette. */
232void SetPalette( SBumps *pBumps, XWindowAttributes *pXWinAttribs )
233{
234        XColor BaseColor;
235        XColor Color;
236        char *sColor;                   /* Spotlight Color */
237        int16_ iColor;
238       
239        sColor = get_string_resource( "color", "Color" );
240
241        BaseColor.red = RANDOM() % 0xFFFF;
242        BaseColor.green = RANDOM() % 0xFFFF;
243        BaseColor.blue = RANDOM() % 0xFFFF;
244       
245        /* Make one color full intesity to avoid dark spotlights.       */
246        switch( RANDOM() % 3 )
247        {
248                case 0: BaseColor.red   = 0xFFFF;       break;
249                case 1: BaseColor.green = 0xFFFF;       break;
250                case 2: BaseColor.blue  = 0xFFFF;       break;
251        }
252
253        if( strcasecmp( sColor, "random" ) && !XParseColor( pBumps->pDisplay, pXWinAttribs->colormap, sColor, &BaseColor ) )
254                fprintf( stderr, "%s: color %s not found in database. Choosing random...\n", progname, sColor );
255
256#ifdef VERBOSE
257        printf( "%s: Spotlight color is <%d,%d,%d> RGB.\n", progclass, BaseColor.red, BaseColor.green, BaseColor.blue );
258#endif  /*  VERBOSE */
259
260        pBumps->nColorCount = get_integer_resource( "colorcount", "Integer" );
261        if( pBumps->nColorCount < 2 )   pBumps->nColorCount = 2;
262        if( pBumps->nColorCount > 128 ) pBumps->nColorCount = 128;
263
264        pBumps->aColors = malloc( pBumps->nColorCount * sizeof(uint32_ ) );
265
266        /* Creates a phong shade:                 / BaseColor  \                               Index/ColorCount
267         *                                                      PhongShade = | ------------ | Index + ( 65535 - BaseColor )^
268         *                                                                                \ ColorCount /                                                                                                */
269        pBumps->nColorCount--;
270        for( iColor=0; iColor<=pBumps->nColorCount; iColor++ )
271        {
272                Color.red   = (uint16_)( ( ( BaseColor.red   / (double)pBumps->nColorCount ) * iColor ) + pow( 0xFFFF - BaseColor.red,   iColor/(double)pBumps->nColorCount ) );
273                Color.green = (uint16_)( ( ( BaseColor.green / (double)pBumps->nColorCount ) * iColor ) + pow( 0xFFFF - BaseColor.green, iColor/(double)pBumps->nColorCount ) );
274                Color.blue  = (uint16_)( ( ( BaseColor.blue  / (double)pBumps->nColorCount ) * iColor ) + pow( 0xFFFF - BaseColor.blue,  iColor/(double)pBumps->nColorCount ) );
275
276                if( !XAllocColor( pBumps->pDisplay, pXWinAttribs->colormap, &Color ) )
277                {
278                        XFreeColors( pBumps->pDisplay, pXWinAttribs->colormap, pBumps->aColors, iColor, 0 );
279                        free( pBumps->aColors );
280                        pBumps->aColors = malloc( pBumps->nColorCount * sizeof(uint32_) );
281                        pBumps->nColorCount--;
282                        iColor = -1;
283                }
284                else
285                        pBumps->aColors[ iColor ] = Color.pixel;
286        }
287        pBumps->nColorCount++;
288
289#ifdef VERBOSE
290        printf( "%s: Allocated %d colors.\n", progclass, pBumps->nColorCount );
291#endif  /*  VERBOSE */
292
293        XSetWindowBackground( pBumps->pDisplay, pBumps->Win, pBumps->aColors[ 0 ] );
294}
295
296
297/* Grabs the current contents of the window to use an intensity-based bump map. */
298void InitBumpMap( SBumps *pBumps, XWindowAttributes *pXWinAttribs )
299{
300        XImage *pScreenImage;
301        XColor *aColors, *pColor;
302        uint8_ nSoften;
303        uint16_ iWidth, iHeight;
304        uint32_ nAverager;
305        uint16_ *pBump;
306        uint16_ maxHeight;
307        double softenMultiplier = 1.0f;
308        BOOL bInvert = (BOOL)get_boolean_resource( "invert", "Boolean" );
309    Pixmap p;
310
311        aColors = (XColor*)malloc( pBumps->iWinWidth * sizeof(XColor) );
312
313    p = XCreatePixmap(pBumps->pDisplay, pBumps->Win,
314                      pXWinAttribs->width, pXWinAttribs->height,
315                      pXWinAttribs->depth);
316    load_random_image (pXWinAttribs->screen, pBumps->Win, p, NULL);
317
318        pScreenImage = XGetImage( pBumps->pDisplay, p, 0, 0, pBumps->iWinWidth, pBumps->iWinHeight, ~0L, ZPixmap );
319    XFreePixmap (pBumps->pDisplay, p);
320
321        /* jwz: get the grabbed bits off the screen fast */
322        XClearWindow (pBumps->pDisplay, pBumps->Win);
323        XSync (pBumps->pDisplay, 0);
324
325        pBumps->aBumpMap = malloc( pBumps->iWinWidth * pBumps->iWinHeight * sizeof(uint16_) );
326       
327        nSoften = get_integer_resource( "soften", "Integer" );
328        while( nSoften-- )
329                softenMultiplier *= 1.0f + ( 1.0f / 3.0f );     /* Softening takes the max height down, so scale up to compensate. */
330        maxHeight = pBumps->SpotLight.nLightRadius * softenMultiplier;
331        nAverager = ( 3 * 0xFFFF ) / maxHeight;
332
333        pBump = pBumps->aBumpMap;
334        if( bInvert )   /* Funny, it's actually the 'else' that inverts the bump map... */
335        {
336                for( iHeight=0; iHeight<pBumps->iWinHeight; iHeight++ )
337                {
338                        pColor = aColors;
339                        for( iWidth=0; iWidth<pBumps->iWinWidth; iWidth++ )
340                                (pColor++)->pixel = XGetPixel( pScreenImage, iWidth, iHeight );
341
342                        XQueryColors( pBumps->pDisplay, pXWinAttribs->colormap, aColors, pBumps->iWinWidth );
343
344                        pColor = aColors;
345                        for( iWidth=pBumps->iWinWidth; iWidth; --iWidth, ++pColor, ++pBump )
346                                *pBump = ( ( pColor->red + pColor->green + pColor->blue ) / nAverager );
347                }
348        }
349        else
350        {
351                for( iHeight=0; iHeight<pBumps->iWinHeight; iHeight++ )
352                {
353                        pColor = aColors;
354                        for( iWidth=0; iWidth<pBumps->iWinWidth; iWidth++ )
355                                (pColor++)->pixel = XGetPixel( pScreenImage, iWidth, iHeight );
356
357                        XQueryColors( pBumps->pDisplay, pXWinAttribs->colormap, aColors, pBumps->iWinWidth );
358       
359                        pColor = aColors;
360                        for( iWidth=pBumps->iWinWidth; iWidth; --iWidth, ++pColor, ++pBump )
361                                *pBump = ( maxHeight - ( ( pColor->red + pColor->green + pColor->blue ) / nAverager ) );
362                }
363        }
364
365        XDestroyImage( pScreenImage );
366
367        nSoften = get_integer_resource( "soften", "Integer" );
368#ifdef VERBOSE
369        if( nSoften )   printf( "%s: Softening Bump Map %d time(s)...\n", progclass, nSoften );
370#endif
371        while( nSoften-- )
372                SoftenBumpMap( pBumps );
373
374        free( aColors );
375}
376
377/* Soften the bump map.  This is to avoid pixelated-looking ridges.
378 * |-----|-----|-----|
379 * |  0% |12.5%|  0% |  The adjacent pixels are averaged together
380 * |-----|-----|-----|  first.  Then than value is averaged with
381 * |12.5%| 50% |12.5%|  the pixel is question. This essentially weights
382 * |-----|-----|-----|  each pixel as shown on the left.
383 * |  0% |12.5%|  0% |
384 * |-----|-----|-----|
385 */
386void SoftenBumpMap( SBumps *pBumps )
387{
388        uint16_ *pOffset, *pTOffset;
389        uint32_ nHeight;
390        uint32_ iWidth, iHeight;
391        uint16_ *aTempBuffer = malloc( pBumps->iWinWidth * pBumps->iWinHeight * sizeof(uint16_) );
392
393        pOffset = pBumps->aBumpMap;
394        pTOffset = aTempBuffer;
395        for( iHeight=pBumps->iWinHeight; iHeight; --iHeight )
396        {
397                for( iWidth=pBumps->iWinWidth; iWidth; --iWidth, ++pOffset, ++pTOffset )
398                {
399                        if( iHeight==pBumps->iWinHeight || iHeight==1 ||
400                                iWidth==pBumps->iWinWidth || iWidth==1 )
401                        {
402                                *pTOffset = 0;
403                                continue;
404                        }
405
406                        nHeight = pOffset[ -pBumps->iWinWidth ];
407                        nHeight += pOffset[ 1 ];
408                        nHeight += pOffset[ pBumps->iWinWidth ];
409                        nHeight += pOffset[ -1 ];
410                        nHeight >>= 2;
411                        nHeight += pOffset[ 0 ];
412                        nHeight >>= 1;
413                        *pTOffset = nHeight;
414                }
415        }                                               
416
417        memcpy( pBumps->aBumpMap, aTempBuffer, pBumps->iWinWidth * pBumps->iWinHeight * sizeof(uint16_) );
418        free( aTempBuffer );
419}
420
421
422/* This is where we slap down some pixels... */
423void Execute( SBumps *pBumps )
424{
425        int32_ nLightXPos, nLightYPos;
426        int32_ iScreenX, iScreenY;
427        int32_ iLightX, iLightY;
428        uint16_ *pBOffset;
429        int8_ *pDOffset;
430        int32_ nX, nY;
431        uint16_ nColor;
432        int32_ nLightOffsetFar = pBumps->SpotLight.nFalloffDiameter - pBumps->SpotLight.nLightRadius;
433
434        CalcLightPos( pBumps );
435       
436        /* Offset to upper left hand corner. */
437        nLightXPos = pBumps->SpotLight.nXPos - pBumps->SpotLight.nFalloffRadius;
438        nLightYPos = pBumps->SpotLight.nYPos - pBumps->SpotLight.nFalloffRadius;
439       
440        for( iScreenY=nLightYPos, iLightY=-pBumps->SpotLight.nLightRadius; iLightY<nLightOffsetFar; ++iScreenY, ++iLightY )
441        {
442                if( iScreenY < 0 )                                                      continue;
443                else if( iScreenY >= pBumps->iWinHeight )       break;
444
445    /* warning: pointer targets in assignment differ in signedness
446       Should pDOffset be a int8?  I can't tell.  -jwz, 22-Jul-2003 */
447                pDOffset = (int8_ *) &pBumps->pXImage->data[ (iLightY+pBumps->SpotLight.nLightRadius) * pBumps->pXImage->bytes_per_line ];
448                pBOffset = pBumps->aBumpMap + ( iScreenY * pBumps->iWinWidth ) + nLightXPos;
449                for( iScreenX=nLightXPos, iLightX=-pBumps->SpotLight.nLightRadius; iLightX<nLightOffsetFar; ++iScreenX, ++iLightX, ++pBOffset, pDOffset+=pBumps->bytesPerPixel )
450                {
451                        if( iScreenX < 0 )                                                      continue;
452                        else if( iScreenX >= pBumps->iWinWidth )        break;
453                        else if( iScreenY == 0 || iScreenY >= pBumps->iWinHeight-2 ||
454                                         iScreenX == 0 || iScreenX >= pBumps->iWinWidth-2 )
455                        {
456                                MyPutPixel( pDOffset, pBumps->aColors[ 0 ] );
457                                continue;
458                        }
459
460                        /* That's right folks, all the magic of bump mapping occurs in these two lines.  (kinda disappointing, isn't it?) */
461                        nX = ( pBOffset[ 1 ] - pBOffset[ 0 ] ) + iLightX;
462                        nY = ( pBOffset[ pBumps->iWinWidth ] - pBOffset[ 0 ] ) + iLightY;
463
464                        if( nX<0 || nX>=pBumps->SpotLight.nLightDiameter
465                         || nY<0 || nY>=pBumps->SpotLight.nLightDiameter )
466                        {
467                                MyPutPixel( pDOffset, pBumps->aColors[ 0 ] );
468                                continue;
469                        }
470                               
471                        nColor = pBumps->SpotLight.aLightMap[ ( nY * pBumps->SpotLight.nLightDiameter ) + nX ];
472                        MyPutPixel( pDOffset, pBumps->aColors[ nColor ] );
473                }
474        }       
475
476        /* Allow the spotlight to go *slightly* off the screen by clipping the XImage. */
477        iLightX = iLightY = 0;  /* Use these for XImages X and Y now.   */
478        nX = nY = pBumps->SpotLight.nFalloffDiameter;   /* Use these for XImage width and height now.   */
479        if( nLightXPos < 0 )
480        {
481                iLightX = -nLightXPos;
482                nX -= iLightX;
483                nLightXPos = 0;
484        }
485        else if( nLightXPos + nX >= pBumps->iWinWidth )
486        {
487                nX -= ( nLightXPos + nX ) - pBumps->iWinWidth;
488        }
489       
490        if( nLightYPos < 0 )
491        {
492                iLightY = -nLightYPos;
493                nY -= iLightY;
494                nLightYPos = 0;
495        }
496        else if( nLightYPos + nY >= pBumps->iWinHeight )
497        {
498                nY -= ( nLightYPos + nY ) - pBumps->iWinHeight;
499        }
500       
501#ifdef HAVE_XSHM_EXTENSION
502        if( pBumps->bUseShm )
503                XShmPutImage( pBumps->pDisplay, pBumps->Win, pBumps->GraphicsContext, pBumps->pXImage, iLightX, iLightY, nLightXPos, nLightYPos,
504                                          nX, nY, False);
505        else
506#endif /* HAVE_XSHM_EXTENSION */
507                XPutImage( pBumps->pDisplay, pBumps->Win, pBumps->GraphicsContext, pBumps->pXImage, iLightX, iLightY, nLightXPos, nLightYPos,
508                                   nX, nY );
509       
510        XSync( pBumps->pDisplay, False );
511}
512
513
514/* Clean up */
515void DestroyBumps( SBumps *pBumps )
516{
517        DestroySpotLight( &pBumps->SpotLight );
518        free( pBumps->aColors );
519        free( pBumps->aBumpMap );
520#ifdef HAVE_XSHM_EXTENSION
521        if( pBumps->bUseShm )
522                destroy_xshm_image( pBumps->pDisplay, pBumps->pXImage, &pBumps->XShmInfo );
523        else
524#endif /* HAVE_XSHM_EXTENSION */
525                XDestroyImage( pBumps->pXImage );
526}
527
528
529/* All messages to the screensaver are processed here. */
530void screenhack( Display *pDisplay, Window Win )
531{
532        SBumps Bumps;
533        uint32_ iDelay;
534#ifdef VERBOSE
535        time_t Time = time( NULL );
536        uint16_ iFrame = 0;
537#endif  /*  VERBOSE */
538       
539        CreateBumps( &Bumps, pDisplay, Win );
540        iDelay = get_integer_resource( "delay", "Integer" );
541
542        while( 1 )
543        {
544                screenhack_handle_events( pDisplay );
545                Execute( &Bumps );
546                usleep( iDelay );
547
548#ifdef VERBOSE
549                iFrame++;
550                if( Time - time( NULL ) )
551                {
552                        printf( "FPS: %d\n", iFrame );
553                        Time = time( NULL );
554                        iFrame = 0;
555                }
556#endif  /*  VERBOSE */
557        }
558
559        DestroyBumps( &Bumps );
560}
561
562 
563/* vim: ts=4
564 */
Note: See TracBrowser for help on using the repository browser.