source: abuse/trunk/src/sdlport/video-overlay.cpp @ 28

Last change on this file since 28 was 2, checked in by Sam Hocevar, 17 years ago
  • imported original 0.7.0 tarball
File size: 8.5 KB
Line 
1/************************
2 * video.c
3 * SDL port for Abuse
4 * by Anthony Kruize
5 ************************/
6
7#include <SDL.h>
8
9#include "filter.hpp"
10#include "globals.hpp"
11#include "system.h"
12#include "video.hpp"
13#include "macs.hpp"
14#include "image.hpp"
15#include "jmalloc.hpp"
16#include "setup.h"
17
18SDL_Surface *window = NULL, *surface = NULL;
19SDL_Overlay *overlay;
20image *screen = NULL;
21unsigned char current_background;
22
23extern unsigned int xres, yres;
24extern palette *lastl;
25extern flags_struct flags;
26
27unsigned short win_xres, win_yres;
28int win_xscale, win_yscale;
29
30
31// Forward declarations
32void blit_surface( SDL_Rect *srcrect, SDL_Rect *dstrect );
33
34//
35// set_mode()
36// Set the video mode
37//
38void set_mode( int mode, int argc, char **argv )
39{
40        const SDL_VideoInfo *vidInfo;
41        int vidFlags = SDL_HWPALETTE;
42
43        // Check for video capabilities
44        vidInfo = SDL_GetVideoInfo();
45        if( vidInfo->hw_available )
46        {
47                vidFlags |= SDL_HWSURFACE;
48        }
49        else
50        {
51                vidFlags |= SDL_SWSURFACE;
52        }
53        if( flags.fullscreen )
54        {
55                vidFlags |= SDL_FULLSCREEN;
56        }
57        if( flags.doublebuf )
58        {
59                vidFlags |= SDL_DOUBLEBUF;
60        }
61
62        // Calculate the window scale
63        win_xscale = (flags.xres << 16) / xres;
64        win_yscale = (flags.yres << 16) / yres;
65
66        // Set the icon for this window.  Looks nice on taskbars etc.
67        SDL_WM_SetIcon( SDL_LoadBMP("abuse.bmp"), NULL );
68
69        // Create the window
70        window = SDL_SetVideoMode( flags.xres, flags.yres, 0, vidFlags );
71        if( window == NULL )
72        {
73                printf( "Video : Unable to set video mode : %s\n", SDL_GetError() );
74                exit( 1 );
75        }
76
77        // Use overlays because they are faster for scaling
78        if( flags.overlay )
79        {
80                overlay = SDL_CreateYUVOverlay( xres, yres, SDL_UYVY_OVERLAY, window );
81        }
82
83        // Create the screen image
84        screen = new image( xres, yres, NULL, 2 );
85        if( screen == NULL )
86        {
87                // Our screen image is no good, we have to bail.
88                printf( "Video : Unable to create screen image.\n" );
89                exit( 1 );
90        }
91        screen->clear();
92
93        // Create our 8-bit surface
94        surface = SDL_CreateRGBSurface( SDL_SWSURFACE, window->w, window->h, 8, 0xff, 0xff, 0xff, 0xff );
95        if( surface == NULL )
96        {
97                // Our surface is no good, we have to bail.
98                printf( "Video : Unable to create 8-bit surface.\n" );
99                exit( 1 );
100        }
101
102        printf( "Video : Using a window of %dx%d %dbpp\n", window->w, window->h, window->format->BitsPerPixel );
103
104        // Set the window caption
105        SDL_WM_SetCaption( "Abuse-SDL", "Abuse-SDL" );
106
107        // Grab and hide the mouse cursor
108        SDL_ShowCursor( 0 );
109        if( flags.grabmouse )
110        {
111                SDL_WM_GrabInput( SDL_GRAB_ON );
112        }
113
114        update_dirty( screen );
115}
116
117//
118// close_graphics()
119// Shutdown the video mode
120//
121void close_graphics()
122{
123        if( lastl )
124        {
125                delete lastl;
126        }
127        lastl = NULL;
128        // Free our 8-bit surface
129        if( surface )
130        {
131                SDL_FreeSurface( surface );
132        }
133        // Free our overlay
134        if( overlay )
135        {
136                SDL_FreeYUVOverlay( overlay );
137        }
138        delete screen;
139}
140
141// put_part_image()
142// Draw only dirty parts of the image
143//
144void put_part_image( image *im, int x, int y, int x1, int y1, int x2, int y2 )
145{
146        int xs, xe, ys, ye;
147        SDL_Rect srcrect, dstrect;
148        int ii, jj;
149        int srcx, srcy, xstep, ystep;
150        Uint8 *dpixel;
151        Uint16 dinset;
152        int dest_addr, line_width;
153
154        if( y > (int)yres || x > (int)xres )
155        {
156                return;
157        }
158        CHECK( x1 >= 0 && x2 >= x1 && y1 >= 0 && y2 >= y1 );
159
160        // Adjust if we are trying to draw off the screen
161        if( x < 0 )
162        {
163                x1 += -x;
164                x = 0;
165        }
166        srcrect.x = x1;
167        if( x + ( x2 - x1 ) >= xres )
168        {
169                xe = xres - x + x1 - 1;
170        }
171        else
172        {
173                xe = x2;
174        }
175        if( y < 0 )
176        {
177                y1 += -y;
178                y = 0;
179        }
180        srcrect.y = y1;
181        if( y + ( y2 - y1 ) >= yres )
182        {
183                ye = yres - y + y1 - 1;
184        }
185        else
186        {
187                ye = y2;
188        }
189        if( srcrect.x >= xe || srcrect.y >= ye )
190                return;
191
192        if( SDL_LockYUVOverlay( overlay ) == -1 )
193        {
194                // we failed to lock
195                printf( "ERROR - Failed to lock overlay.\n" );
196                return;
197        }
198
199        // This is our old copying code, left here for now just in case I still nee it
200        // Set up our blit rectangle
201        dstrect.w = xe - xs;
202        dstrect.h = ye - ys;
203        dstrect.x = x;
204        dstrect.y = y;
205        line_width = xe - xs + 1;
206
207        if( SDL_LockYUVOverlay( overlay ) == -1 )
208        {
209                // we failed to lock
210                printf( "ERROR - Failed to lock overlay.\n" );
211                return;
212        }
213
214        // fill buffer with current surface
215/*      for( int ii = ys; ii <= ye; ii++ )
216        {
217//              dest_addr = ( (dstrect.y + ii - ys) * screen_width ) + dstrect.x;
218                dest_addr = ( (dstrect.y + ii - ys) * overlay->pitches[0] ) + dstrect.x;
219//              memcpy( &((char *)(surface->pixels))[dest_addr], im->scan_line( ii ) + xs, line_width );
220//              memcpy( &((char *)(overlay->pixels))[dest_addr], im->scan_line( ii ) + xs, line_width );
221        }*/
222        char blah = 0xff;
223        for( int ii = 0; ii < overlay->pitches[0] * 2; ii++ )
224        memcpy( &((char *)(overlay->pixels))[ii], ((char *)(&blah)), 1 );
225
226        SDL_UnlockYUVOverlay( overlay );
227
228/*      // Scale the image onto the surface
229        srcrect.w = xe - srcrect.x;
230        srcrect.h = ye - srcrect.y;
231        dstrect.x = ((x * win_xscale) >> 16);
232        dstrect.y = ((y * win_yscale) >> 16);
233        dstrect.w = ((srcrect.w * win_xscale) >> 16);
234        dstrect.h = ((srcrect.h * win_yscale) >> 16);
235
236        xstep = (srcrect.w << 16) / dstrect.w;
237        ystep = (srcrect.h << 16) / dstrect.h;
238
239        srcy = ((srcrect.y) << 16);
240        dinset = ((surface->w - dstrect.w)) * surface->format->BytesPerPixel;
241
242        // Lock the surface if necessary
243        if( SDL_MUSTLOCK( surface ) )
244        {
245                SDL_LockSurface( surface );
246        }
247        dpixel = (Uint8 *)surface->pixels;
248        dpixel += (dstrect.x + ((dstrect.y) * surface->w)) * surface->format->BytesPerPixel;
249
250        for( ii = 0; ii < dstrect.h; ii++ )
251        {
252                srcx = (srcrect.x << 16);
253                for( jj = 0; jj < dstrect.w; jj++ )
254                {
255                        memcpy( dpixel, im->scan_line( (srcy >> 16) ) + ((srcx >> 16) * surface->format->BytesPerPixel), surface->format->BytesPerPixel );
256                        dpixel += surface->format->BytesPerPixel;
257                        srcx += xstep;
258                }
259                dpixel += dinset;
260                srcy += ystep;
261        }
262
263        // Now unlock the surface if we locked it.
264        if( SDL_MUSTLOCK( surface ) )
265        {
266                SDL_UnlockSurface( surface );
267        } */
268
269        // Now blit the surface
270        blit_surface( &dstrect, &dstrect );
271}
272
273//
274// put_image()
275// Draw the entire image
276//
277void put_image( image * im, int x, int y )
278{
279        put_part_image( im, x, y, 0, 0, im->width() - 1, im->height() - 1 );
280}
281
282//
283// update_dirty_window()
284// Update the dirty parts of the window
285//
286void update_dirty_window( image *im, int xoff, int yoff )
287{
288        int count;
289        dirty_rect *dr, *q;
290        CHECK( im->special ); // make sure the image has the ability to contain dirty areas
291        if( im->special->keep_dirt == 0 )
292        {
293                put_image( im, xoff, yoff );
294        }
295        else
296        {
297                count = im->special->dirties.number_nodes();
298                if( !count )
299                        return;  // if nothing to update, return
300                dr = (dirty_rect *)( im->special->dirties.first() );
301                while( count > 0 )
302                {
303                        put_part_image( im, xoff + dr->dx1, yoff + dr->dy1, dr->dx1, dr->dy1, dr->dx2 + 1, dr->dy2 + 1 );
304                        q = dr;
305                        dr = (dirty_rect *)( dr->next() );
306                        im->special->dirties.unlink( ( linked_node *)q );
307                        delete q;
308                        count--;
309                }
310        }
311}
312
313//
314// update_dirty()
315// Update the dirty parts of the image
316//
317void update_dirty( image *im, int xoff, int yoff )
318{
319        update_dirty_window( im, xoff, yoff );
320}
321
322//
323// make_page()
324//
325void image::make_page( short width, short height, unsigned char *page_buffer )
326{
327        if( page_buffer )
328        {
329                data = page_buffer;
330        }
331        else
332        {
333                data = (unsigned char *)jmalloc( width * height, "image::data" );
334        }
335}
336
337//
338// delete_page()
339//
340void image::delete_page()
341{
342        if( !special || !special->static_mem )
343        {
344                jfree( data );
345        }
346}
347
348//
349// load()
350// Set the palette
351//
352void palette::load()
353{
354        if( lastl )
355        {
356                delete lastl;
357        }
358        lastl = copy();
359
360        // Force to only 256 colours.
361        // Shouldn't be needed, but best to be safe.
362        if( ncolors > 256 )
363        {
364                ncolors = 256;
365        }
366
367        SDL_Color colors[ncolors];
368        for( int ii = 0; ii < ncolors; ii++ )
369        {
370                colors[ii].r = red(ii);
371                colors[ii].g = green(ii);
372                colors[ii].b = blue(ii);
373        }
374        SDL_SetColors( surface, colors, 0, ncolors );
375        if( window->format->BitsPerPixel == 8 )
376        {
377                SDL_SetColors( window, colors, 0, ncolors );
378        }
379
380        // Now redraw the surface
381        blit_surface( NULL, NULL );
382}
383
384//
385// load_nice()
386//
387void palette::load_nice()
388{
389        load();
390}
391
392// ---- support functions ----
393
394void blit_surface( SDL_Rect *srcrect, SDL_Rect *dstrect)
395{
396        SDL_Surface *cvtsfc = SDL_ConvertSurface( surface, window->format, SDL_HWSURFACE );
397        if( cvtsfc == NULL )
398        {
399                // Our convert surface died...bad :(
400                return;
401        }
402
403        if( flags.overlay )
404        {
405                SDL_Rect or;
406                or.x = 0;
407                or.y = 0;
408                or.w = window->w;
409                or.h = window->h;
410                SDL_DisplayYUVOverlay( overlay, &or );
411        }
412
413//      SDL_BlitSurface( cvtsfc, srcrect, window, dstrect );
414        SDL_FreeSurface( cvtsfc );
415
416        // Flip the backbuffer to the front
417        if( flags.doublebuf )
418        {
419                SDL_Flip( window );
420        }
421        else
422        {
423                if( dstrect == NULL )
424                {
425                        SDL_UpdateRect( window, 0, 0, 0, 0 );
426                }
427                else
428                {
429                        SDL_UpdateRect( window, dstrect->x, dstrect->y, dstrect->w, dstrect->h );
430                }
431        }
432}
Note: See TracBrowser for help on using the repository browser.