UFO: Alien Invasion
r_sdl.cpp
Go to the documentation of this file.
1
6/*
7Copyright (C) 1997-2001 Id Software, Inc.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, 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
34static 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
72bool Rimp_Init (void)
73{
74 SDL_version version;
75 int attrValue;
76
77 Com_Printf("\n------- video initialization -------\n");
78
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
99
100#if SDL_VERSION_ATLEAST(2,0,0)
101 int screen = 0;
102 const int modes = SDL_GetNumDisplayModes(screen);
103 if (modes > 0) {
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 {
155
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
218bool 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
282void 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}
client_static_t cls
Definition: cl_main.cpp:83
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
#define GAME_TITLE
Definition: common.h:37
#define GAME_TITLE_LONG
Definition: common.h:38
#define ERR_FATAL
Definition: common.h:210
voidpf void * buf
Definition: ioapi.h:42
#define Mem_AllocTypeN(type, n)
Definition: mem.h:38
QGL_EXTERN GLint i
Definition: r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
local graphics definitions
cvar_t * r_driver
Definition: r_main.cpp:86
rconfig_t r_config
Definition: r_main.cpp:47
bool R_SetMode(void)
Definition: r_main.cpp:694
static void R_SetSDLIcon(void)
Definition: r_sdl.cpp:34
void Rimp_Shutdown(void)
Definition: r_sdl.cpp:282
bool R_InitGraphics(const viddefContext_t *context)
Init the SDL window.
Definition: r_sdl.cpp:218
r_sdl_config_t r_sdl_config
Definition: r_sdl.cpp:32
bool Rimp_Init(void)
Definition: r_sdl.cpp:72
#define OBJZERO(obj)
Definition: shared.h:178
#define MAX_VAR
Definition: shared.h:36
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
char * string
Definition: cvar.h:73
int numModes
Definition: r_sdl.h:31
rect_t * modes
Definition: r_sdl.h:30
int desktopHeight
Definition: r_sdl.h:34
int desktopWidth
Definition: r_sdl.h:33
int videoMemory
Definition: r_local.h:180
Contains the game screen context, everything that is needed to create the graphic context....
Definition: cl_video.h:43
unsigned width
Definition: cl_video.h:44
int swapinterval
Definition: cl_video.h:49
unsigned height
Definition: cl_video.h:45
bool fullscreen
Definition: cl_video.h:47
int Sys_Setenv(const char *name, const char *value)
set/unset environment variables (empty value removes it)
Definition: unix_shared.cpp:60