UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_sdl.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "r_local.h"
27 #include "r_main.h"
28 #include "r_sdl.h"
29 #include "../../ports/system.h"
30 #include "../client.h"
31 
33 
34 static void R_SetSDLIcon (void)
35 {
36 #ifndef _WIN32
37 #include "../../ports/linux/ufoicon.xbm"
38  SDL_Surface* icon = SDL_CreateRGBSurface(SDL_SWSURFACE, ufoicon_width, ufoicon_height, 8, 0, 0, 0, 0);
39  if (icon == nullptr)
40  return;
41 #if SDL_VERSION_ATLEAST(2,0,0)
42  SDL_SetColorKey(icon, SDL_TRUE, 0);
43 #else
44  SDL_SetColorKey(icon, SDL_SRCCOLORKEY, 0);
45 
46  SDL_Color color;
47  color.r = color.g = color.b = 255;
48  SDL_SetColors(icon, &color, 0, 1); /* just in case */
49 
50  color.r = color.b = 0;
51  color.g = 16;
52  SDL_SetColors(icon, &color, 1, 1);
53 #endif
54 
55  Uint8 *ptr = (Uint8 *)icon->pixels;
56  for (unsigned int i = 0; i < sizeof(ufoicon_bits); i++) {
57  for (unsigned int mask = 1; mask != 0x100; mask <<= 1) {
58  *ptr = (ufoicon_bits[i] & mask) ? 1 : 0;
59  ptr++;
60  }
61  }
62 
63 #if SDL_VERSION_ATLEAST(2,0,0)
64  SDL_SetWindowIcon(cls.window, icon);
65 #else
66  SDL_WM_SetIcon(icon, nullptr);
67 #endif
68  SDL_FreeSurface(icon);
69 #endif
70 }
71 
72 bool Rimp_Init (void)
73 {
74  SDL_version version;
75  int attrValue;
76 
77  Com_Printf("\n------- video initialization -------\n");
78 
79  OBJZERO(r_sdl_config);
80 
81  if (r_driver->string[0] != '\0') {
82  Com_Printf("I: using driver: %s\n", r_driver->string);
83  SDL_GL_LoadLibrary(r_driver->string);
84  }
85 
86  Sys_Setenv("SDL_VIDEO_CENTERED", "1");
87  Sys_Setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "0");
88 
89  if (SDL_WasInit(SDL_INIT_VIDEO) == 0) {
90  if (SDL_Init(SDL_INIT_VIDEO) < 0)
91  Com_Error(ERR_FATAL, "Video SDL_Init failed: %s", SDL_GetError());
92  }
93 
94  SDL_VERSION(&version)
95  Com_Printf("I: SDL version: %i.%i.%i\n", version.major, version.minor, version.patch);
96 
97  r_sdl_config.desktopWidth = 1024;
98  r_sdl_config.desktopHeight = 768;
99 
100 #if SDL_VERSION_ATLEAST(2,0,0)
101  int screen = 0;
102  const int modes = SDL_GetNumDisplayModes(screen);
103  if (modes > 0) {
104  r_sdl_config.modes = Mem_AllocTypeN(rect_t, modes);
105  for (int i = 0; i < modes; i++) {
106  SDL_DisplayMode displayMode;
107  SDL_GetDisplayMode(screen, i, &displayMode);
108  r_sdl_config.modes[i][0] = displayMode.w;
109  r_sdl_config.modes[i][1] = displayMode.h;
110  }
111  }
112 
113  const int displays = SDL_GetNumVideoDisplays();
114  Com_Printf("I: found %i display(s)\n", displays);
115 
116  SDL_DisplayMode displayMode;
117  if (SDL_GetDesktopDisplayMode(0, &displayMode) != -1) {
118  const char* name = SDL_GetPixelFormatName(displayMode.format);
119  Com_Printf("I: current desktop mode: %dx%d@%dHz (%s)\n",
120  displayMode.w, displayMode.h, displayMode.refresh_rate, name);
121  Com_Printf("I: video driver: %s\n", SDL_GetCurrentVideoDriver());
122  r_sdl_config.desktopWidth = displayMode.w;
123  r_sdl_config.desktopHeight = displayMode.h;
124  } else {
125  Com_Printf("E: failed to get the desktop mode\n");
126  }
127 
128  const int videoDrivers = SDL_GetNumVideoDrivers();
129  for (int i = 0; i < videoDrivers; ++i) {
130  Com_Printf("I: available driver: %s\n", SDL_GetVideoDriver(i));
131  }
132  Com_Printf("I: driver: %s\n", SDL_GetCurrentVideoDriver());
133 
134  SDL_SetModState(KMOD_NONE);
135  SDL_StopTextInput();
136 #else
137  const SDL_VideoInfo* info = SDL_GetVideoInfo();
138  if (info != nullptr) {
139  SDL_VideoInfo videoInfo;
140  SDL_PixelFormat pixelFormat;
141  SDL_Rect** modes;
142  Com_Printf("I: desktop depth: %ibpp\n", info->vfmt->BitsPerPixel);
143  r_config.videoMemory = info->video_mem;
144  Com_Printf("I: video memory: %i\n", r_config.videoMemory);
145  memcpy(&pixelFormat, info->vfmt, sizeof(pixelFormat));
146  memcpy(&videoInfo, info, sizeof(videoInfo));
147  videoInfo.vfmt = &pixelFormat;
148  modes = SDL_ListModes(videoInfo.vfmt, SDL_OPENGL | SDL_FULLSCREEN);
149  if (modes) {
150  if (modes == (SDL_Rect**)-1) {
151  Com_Printf("I: Available resolutions: any resolution is supported\n");
152  r_sdl_config.modes = nullptr;
153  } else {
154  for (r_sdl_config.numModes = 0; modes[r_sdl_config.numModes]; r_sdl_config.numModes++) {}
155 
156  r_sdl_config.modes = Mem_AllocTypeN(rect_t, r_sdl_config.numModes);
157  for (int i = 0; i < r_sdl_config.numModes; i++) {
158  r_sdl_config.modes[i][0] = modes[i]->w;
159  r_sdl_config.modes[i][1] = modes[i]->h;
160  }
161  }
162  } else {
163  Com_Printf("I: Could not get list of available resolutions\n");
164  }
165  }
166  char videoDriverName[MAX_VAR] = "";
167  SDL_VideoDriverName(videoDriverName, sizeof(videoDriverName));
168  Com_Printf("I: video driver: %s\n", videoDriverName);
169 #endif
170  if (r_sdl_config.numModes > 0) {
171  char buf[4096] = "";
172  Q_strcat(buf, sizeof(buf), "I: Available resolutions:");
173  for (int i = 0; i < r_sdl_config.numModes; i++) {
174  Q_strcat(buf, sizeof(buf), " %ix%i", r_sdl_config.modes[i][0], r_sdl_config.modes[i][1]);
175  }
176  Com_Printf("%s (%i)\n", buf, r_sdl_config.numModes);
177  }
178 
179  if (!R_SetMode())
180  Com_Error(ERR_FATAL, "Video subsystem failed to initialize");
181 
182 #if !SDL_VERSION_ATLEAST(2,0,0)
183  SDL_WM_SetCaption(GAME_TITLE, GAME_TITLE_LONG);
184 
185  /* we need this in the renderer because if we issue an vid_restart we have
186  * to set these values again, too */
187  SDL_EnableUNICODE(SDL_ENABLE);
188  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
189 #endif
190 
191  R_SetSDLIcon();
192 
193  if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &attrValue))
194  Com_Printf("I: got %d bits of stencil\n", attrValue);
195  if (!SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &attrValue))
196  Com_Printf("I: got %d bits of depth buffer\n", attrValue);
197  if (!SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &attrValue))
198  Com_Printf("I: got double buffer\n");
199  if (!SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &attrValue))
200  Com_Printf("I: got %d bits for red\n", attrValue);
201  if (!SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &attrValue))
202  Com_Printf("I: got %d bits for green\n", attrValue);
203  if (!SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &attrValue))
204  Com_Printf("I: got %d bits for blue\n", attrValue);
205  if (!SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &attrValue))
206  Com_Printf("I: got %d bits for alpha\n", attrValue);
207  if (!SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &attrValue))
208  Com_Printf("I: got multisample %s\n", attrValue != 0 ? "enabled" : "disabled");
209  if (!SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &attrValue))
210  Com_Printf("I: got %d multisample buffers\n", attrValue);
211 
212  return true;
213 }
214 
218 bool R_InitGraphics (const viddefContext_t* context)
219 {
220  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
221  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
222  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
223 
224  if (context->multisample > 0) {
225  Com_Printf("I: set multisample buffers to %i\n", context->multisample);
226  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
227  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, context->multisample);
228  } else {
229  Com_Printf("I: disable multisample buffers\n");
230  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
231  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
232  }
233 
234 #if SDL_VERSION_ATLEAST(2,0,0)
235 #ifdef GL_VERSION_ES_CM_1_0
236  /* Be sure to request GLES1 as we use GLES2 incompatible calls */
237  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
238  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
239 #endif
240  /* valid values are between -1 and 1 */
241  const int i = std::min(1, std::max(-1, context->swapinterval));
242  Com_Printf("I: set swap control to %i\n", i);
243  SDL_GL_SetSwapInterval(i);
244  uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
245 
246  if (context->fullscreen)
247  flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
248 
249  cls.window = SDL_CreateWindow(GAME_TITLE_LONG, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, context->width, context->height, flags);
250  if (!cls.window) {
251  const char* error = SDL_GetError();
252  Com_Printf("E: SDL_CreateWindow failed: %s\n", error);
253  SDL_ClearError();
254  return false;
255  }
256 
257  cls.context = SDL_GL_CreateContext(cls.window);
258 #else
259  /* valid values are between 0 and 2 */
260  const int i = std::min(2, std::max(0, context->swapinterval));
261  Com_Printf("I: set swap control to %i\n", i);
262  SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, i);
263  uint32_t flags = SDL_OPENGL;
264  if (context->fullscreen)
265  flags |= SDL_FULLSCREEN;
266  /*flags |= SDL_NOFRAME;*/
267 
268  SDL_Surface* screen = SDL_SetVideoMode(context->width, context->height, 0, flags);
269  if (!screen) {
270  const char* error = SDL_GetError();
271  Com_Printf("SDL SetVideoMode failed: %s\n", error);
272  SDL_ClearError();
273  return false;
274  }
275 #endif
276 
277  SDL_ShowCursor(SDL_DISABLE);
278 
279  return true;
280 }
281 
282 void Rimp_Shutdown (void)
283 {
284 #if SDL_VERSION_ATLEAST(2,0,0)
285  SDL_DestroyWindow(cls.window);
286  SDL_GL_DeleteContext(cls.context);
287 #endif
288  /* SDL on Android does not support multiple video init/deinit yet, however calling SDL_SetVideoMode() multiple times works */
289 #ifndef ANDROID
290  SDL_ShowCursor(SDL_ENABLE);
291 
292  if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO)
293  SDL_Quit();
294  else
295  SDL_QuitSubSystem(SDL_INIT_VIDEO);
296 #endif
297 }
#define Mem_AllocTypeN(type, n)
Definition: mem.h:38
bool R_SetMode(void)
Definition: r_main.cpp:694
bool Rimp_Init(void)
Definition: r_sdl.cpp:72
int swapinterval
Definition: cl_video.h:49
int Sys_Setenv(const char *name, const char *value)
set/unset environment variables (empty value removes it)
Definition: unix_shared.cpp:60
cvar_t * r_driver
Definition: r_main.cpp:86
int numModes
Definition: r_sdl.h:31
local graphics definitions
int desktopWidth
Definition: r_sdl.h:33
unsigned width
Definition: cl_video.h:44
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
rconfig_t r_config
Definition: r_main.cpp:47
Contains the game screen context, everything that is needed to create the graphic context...
Definition: cl_video.h:43
voidpf void * buf
Definition: ioapi.h:42
#define ERR_FATAL
Definition: common.h:210
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
int videoMemory
Definition: r_local.h:180
client_static_t cls
Definition: cl_main.cpp:83
#define GAME_TITLE_LONG
Definition: common.h:38
bool fullscreen
Definition: cl_video.h:47
#define OBJZERO(obj)
Definition: shared.h:178
#define MAX_VAR
Definition: shared.h:36
r_sdl_config_t r_sdl_config
Definition: r_sdl.cpp:32
#define GAME_TITLE
Definition: common.h:37
void Rimp_Shutdown(void)
Definition: r_sdl.cpp:282
#define ufoicon_width
rect_t * modes
Definition: r_sdl.h:30
static void R_SetSDLIcon(void)
Definition: r_sdl.cpp:34
QGL_EXTERN GLint i
Definition: r_gl.h:113
int desktopHeight
Definition: r_sdl.h:34
char * string
Definition: cvar.h:73
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
unsigned height
Definition: cl_video.h:45
bool R_InitGraphics(const viddefContext_t *context)
Init the SDL window.
Definition: r_sdl.cpp:218