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

Last change on this file since 494 was 494, checked in by Sam Hocevar, 11 years ago

style: remove trailing spaces, fix copyright statements.

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