source: abuse/trunk/src/sdl2port/video.cpp @ 731

Last change on this file since 731 was 731, checked in by jjsimpso, 8 years ago

sdlport: Add support for SDL2, inculding the game controller API. Configure
script will check for SDL2 and use it if present, otherwise it will fall
back to SDL v1. Some old SDL v1 features not implemented yet on SDL2, such
as saving screenshots.

core: Small change for SDL2 game controller API to disable the game
controller in the save/load game menu.

Summary of game controller API changes:

  • Enable with -gamepad
  • Tested with PS3 dualshock 3.
  • D-pad moves, right analog controls aiming
  • X: change weapon, []: jump, R1: fire, L1: special ability, /\:use/activate
  • All menu navigation requires the mouse, which is disabled during normal game play.
File size: 9.2 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#if defined HAVE_CONFIG_H
22#   include "config.h"
23#endif
24
25#include <SDL.h>
26
27#include "common.h"
28
29#include "filter.h"
30#include "video.h"
31#include "image.h"
32#include "setup.h"
33
34SDL_Window *window = NULL;
35SDL_Renderer *renderer = NULL;
36SDL_Surface *surface = NULL;
37SDL_Surface *rgba_surface = NULL;
38SDL_Texture *texture = NULL;
39image *main_screen = NULL;
40int win_xscale, win_yscale, mouse_xscale, mouse_yscale;
41int xres, yres;
42
43extern palette *lastl;
44extern flags_struct flags;
45
46static void update_window_part(SDL_Rect *rect);
47
48//
49// power_of_two()
50// Get the nearest power of two
51//
52static int power_of_two(int input)
53{
54    int value;
55    for(value = 1 ; value < input ; value <<= 1);
56    return value;
57}
58
59//
60// set_mode()
61// Set the video mode
62//
63void set_mode(int mode, int argc, char **argv)
64{
65    // Calculate the window scale
66    win_xscale = mouse_xscale = (flags.xres << 16) / xres;
67    win_yscale = mouse_yscale = (flags.yres << 16) / yres;
68
69    // force no scaling, let the hw do it
70    win_xscale = win_yscale = 1 << 16;
71
72    // Set the icon for this window.  Looks nice on taskbars etc.
73    //SDL_WM_SetIcon(SDL_LoadBMP("abuse.bmp"), NULL);
74
75    window = SDL_CreateWindow("Abuse",
76                              SDL_WINDOWPOS_UNDEFINED,
77                              SDL_WINDOWPOS_UNDEFINED,
78                              flags.xres, flags.yres,
79                              (flags.fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0));
80
81    if(window == NULL)
82    {
83        printf("Video : Unable to create window: %s\n", SDL_GetError());
84        exit(1);
85    }
86   
87    renderer = SDL_CreateRenderer(window, -1, 0);
88   
89    if(renderer == NULL)
90    {
91        printf("Video : Unable to create renderer: %s\n", SDL_GetError());
92        exit(1);
93    }
94
95    // This will make sure that the aspect ratio is maintained in fullscreen mode
96    SDL_RenderSetLogicalSize(renderer, flags.xres, flags.yres);
97
98    // Create the screen image
99    main_screen = new image(ivec2(xres, yres), NULL, 2);
100    if(main_screen == NULL)
101    {
102        // Our screen image is no good, we have to bail.
103        printf("Video : Unable to create screen image.\n");
104        exit(1);
105    }
106    main_screen->clear();
107
108    int w, h;
109   
110    // texture width/height should be power of 2
111    // FIXME: we can use GL_ARB_texture_non_power_of_two or
112    // GL_ARB_texture_rectangle to avoid the extra memory allocation
113    //w = power_of_two(xres);
114    //h = power_of_two(yres);
115    w = xres;
116    h = yres;
117
118    // create texture surface
119    texture = SDL_CreateTexture(renderer,
120                                SDL_PIXELFORMAT_ARGB8888,
121                                SDL_TEXTUREACCESS_STREAMING,
122                                w, h);
123
124    // Create our 8-bit surface
125    surface = SDL_CreateRGBSurface(0, xres, yres, 8, 0, 0, 0, 0);
126    if(surface == NULL)
127    {
128        // Our surface is no good, we have to bail.
129        printf("Video : Unable to create 8-bit surface.\n");
130        exit(1);
131    }
132
133    // Create our RGBA surface   
134    int bpp;
135    Uint32 rmask, gmask, bmask, amask;
136    SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, &bpp, &rmask, &gmask, &bmask, &amask);
137   
138    rgba_surface = SDL_CreateRGBSurface(0, xres, yres, bpp, rmask, gmask, bmask, amask);
139    if(rgba_surface == NULL)
140    {
141        // Our surface is no good, we have to bail.
142        printf("Video : Unable to create RGBA surface.\n");
143        exit(1);
144    }
145   
146    //printf("Video : %dx%d %dbpp\n", window->w, window->h, window->format->BitsPerPixel);
147    printf("Video : %dx%d %dbpp\n", flags.xres, flags.yres, bpp);
148
149    // Grab and hide the mouse cursor
150    SDL_ShowCursor(0);
151    if(flags.grabmouse)
152        SDL_SetWindowGrab(window, SDL_TRUE);
153
154    update_dirty(main_screen);
155}
156
157//
158// close_graphics()
159// Shutdown the video mode
160//
161void close_graphics()
162{
163    if(lastl)
164        delete lastl;
165    lastl = NULL;
166    // Free our 8-bit surface
167    if(surface)
168        SDL_FreeSurface(surface);
169
170    if(rgba_surface)
171        SDL_FreeSurface(rgba_surface);
172
173    if (texture)
174        SDL_DestroyTexture(texture);
175
176    delete main_screen;
177}
178
179// put_part_image()
180// Draw only dirty parts of the image
181//
182void put_part_image(image *im, int x, int y, int x1, int y1, int x2, int y2)
183{
184    int xe, ye;
185    SDL_Rect srcrect, dstrect;
186    int ii, jj;
187    int srcx, srcy, xstep, ystep;
188    Uint8 *dpixel;
189    Uint16 dinset;
190
191    if(y > yres || x > xres)
192        return;
193
194    CHECK(x1 >= 0 && x2 >= x1 && y1 >= 0 && y2 >= y1);
195
196    // Adjust if we are trying to draw off the screen
197    if(x < 0)
198    {
199        x1 += -x;
200        x = 0;
201    }
202    srcrect.x = x1;
203    if(x + (x2 - x1) >= xres)
204        xe = xres - x + x1 - 1;
205    else
206        xe = x2;
207
208    if(y < 0)
209    {
210        y1 += -y;
211        y = 0;
212    }
213    srcrect.y = y1;
214    if(y + (y2 - y1) >= yres)
215        ye = yres - y + y1 - 1;
216    else
217        ye = y2;
218
219    if(srcrect.x >= xe || srcrect.y >= ye)
220        return;
221
222    // Scale the image onto the surface
223    srcrect.w = xe - srcrect.x;
224    srcrect.h = ye - srcrect.y;
225    dstrect.x = ((x * win_xscale) >> 16);
226    dstrect.y = ((y * win_yscale) >> 16);
227    dstrect.w = ((srcrect.w * win_xscale) >> 16);
228    dstrect.h = ((srcrect.h * win_yscale) >> 16);
229
230    xstep = (srcrect.w << 16) / dstrect.w;
231    ystep = (srcrect.h << 16) / dstrect.h;
232
233    srcy = ((srcrect.y) << 16);
234    dinset = ((surface->w - dstrect.w)) * surface->format->BytesPerPixel;
235
236    // Lock the surface if necessary
237    if(SDL_MUSTLOCK(surface))
238        SDL_LockSurface(surface);
239
240    dpixel = (Uint8 *)surface->pixels;
241    dpixel += (dstrect.x + ((dstrect.y) * surface->w)) * surface->format->BytesPerPixel;
242
243    // Update surface part
244    if ((win_xscale==1<<16) && (win_yscale==1<<16)) // no scaling or hw scaling
245    {
246        srcy = srcrect.y;
247        dpixel = ((Uint8 *)surface->pixels) + y * surface->w + x ;
248        for(ii=0 ; ii < srcrect.h; ii++)
249        {
250            memcpy(dpixel, im->scan_line(srcy) + srcrect.x , srcrect.w);
251            dpixel += surface->w;
252            srcy ++;
253        }
254    }
255    else    // sw scaling
256    {
257        xstep = (srcrect.w << 16) / dstrect.w;
258        ystep = (srcrect.h << 16) / dstrect.h;
259
260        srcy = ((srcrect.y) << 16);
261        dinset = ((surface->w - dstrect.w)) * surface->format->BytesPerPixel;
262
263        dpixel = (Uint8 *)surface->pixels + (dstrect.x + ((dstrect.y) * surface->w)) * surface->format->BytesPerPixel;
264
265        for(ii = 0; ii < dstrect.h; ii++)
266        {
267            srcx = (srcrect.x << 16);
268            for(jj = 0; jj < dstrect.w; jj++)
269            {
270                memcpy(dpixel, im->scan_line((srcy >> 16)) + ((srcx >> 16) * surface->format->BytesPerPixel), surface->format->BytesPerPixel);
271                dpixel += surface->format->BytesPerPixel;
272                srcx += xstep;
273            }
274            dpixel += dinset;
275            srcy += ystep;
276        }
277//        dpixel += dinset;
278//        srcy += ystep;
279    }
280
281    // Unlock the surface if we locked it.
282    if(SDL_MUSTLOCK(surface))
283        SDL_UnlockSurface(surface);
284
285    // Now blit the surface
286    update_window_part(&dstrect);
287}
288
289//
290// load()
291// Set the palette
292//
293void palette::load()
294{
295    if(lastl)
296        delete lastl;
297    lastl = copy();
298
299    // Force to only 256 colours.
300    // Shouldn't be needed, but best to be safe.
301    if(ncolors > 256)
302        ncolors = 256;
303
304    SDL_Color colors[ncolors];
305    for(int ii = 0; ii < ncolors; ii++)
306    {
307        colors[ii].r = red(ii);
308        colors[ii].g = green(ii);
309        colors[ii].b = blue(ii);
310    }
311
312    SDL_SetPaletteColors(surface->format->palette, colors, 0, ncolors);
313
314    // Now redraw the surface
315    update_window_part(NULL);
316    update_window_done();
317}
318
319//
320// load_nice()
321//
322void palette::load_nice()
323{
324    load();
325}
326
327// ---- support functions ----
328
329void update_window_done()
330{
331    // opengl blit complete surface to window
332   
333    // convert color-indexed surface to RGBA surface
334    SDL_BlitSurface(surface, NULL, rgba_surface, NULL);
335
336    SDL_UpdateTexture(texture, NULL, rgba_surface->pixels, rgba_surface->pitch);
337   
338    SDL_RenderClear(renderer);
339    SDL_RenderCopy(renderer, texture, NULL, NULL);
340    SDL_RenderPresent(renderer);
341}
342
343static void update_window_part(SDL_Rect *rect)
344{
345    // no partial blit's in case of opengl
346    // complete blit + scaling just before flip
347    return;
348
349#if 0
350    SDL_BlitSurface(surface, rect, window, rect);
351
352    // no window update needed until end of run
353    if(flags.doublebuf)
354        return;
355
356    // update window part for single buffer
357    if(rect == NULL)
358        SDL_UpdateRect(window, 0, 0, 0, 0);
359    else
360        SDL_UpdateRect(window, rect->x, rect->y, rect->w, rect->h);
361#endif
362}
Note: See TracBrowser for help on using the repository browser.