comparison src/video/SDL_video.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents eacc5bc01d1c
children c2a27da60b18
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
25 25
26 #include "SDL.h" 26 #include "SDL.h"
27 #include "SDL_sysvideo.h" 27 #include "SDL_sysvideo.h"
28 #include "SDL_blit.h" 28 #include "SDL_blit.h"
29 #include "SDL_pixels_c.h" 29 #include "SDL_pixels_c.h"
30 #include "SDL_cursor_c.h" 30 #include "SDL_renderer_sw.h"
31 #include "../events/SDL_sysevents.h" 31 #include "../events/SDL_sysevents.h"
32 #include "../events/SDL_events_c.h" 32 #include "../events/SDL_events_c.h"
33 33
34 /* Available video drivers */ 34 /* Available video drivers */
35 static VideoBootStrap *bootstrap[] = { 35 static VideoBootStrap *bootstrap[] = {
36 #if SDL_VIDEO_DRIVER_QUARTZ 36 #if SDL_VIDEO_DRIVER_QUARTZ
37 &QZ_bootstrap, 37 &QZ_bootstrap,
38 #endif 38 #endif
39 #if SDL_VIDEO_DRIVER_X11 39 #if SDL_VIDEO_DRIVER_X11
40 &X11_bootstrap, 40 &X11_bootstrap,
41 #endif 41 #endif
42 #if SDL_VIDEO_DRIVER_DGA 42 #if SDL_VIDEO_DRIVER_DGA
43 &DGA_bootstrap, 43 &DGA_bootstrap,
44 #endif 44 #endif
45 #if SDL_VIDEO_DRIVER_NANOX 45 #if SDL_VIDEO_DRIVER_NANOX
46 &NX_bootstrap, 46 &NX_bootstrap,
47 #endif 47 #endif
48 #if SDL_VIDEO_DRIVER_IPOD 48 #if SDL_VIDEO_DRIVER_IPOD
49 &iPod_bootstrap, 49 &iPod_bootstrap,
50 #endif 50 #endif
51 #if SDL_VIDEO_DRIVER_QTOPIA 51 #if SDL_VIDEO_DRIVER_QTOPIA
52 &Qtopia_bootstrap, 52 &Qtopia_bootstrap,
53 #endif 53 #endif
54 #if SDL_VIDEO_DRIVER_WSCONS 54 #if SDL_VIDEO_DRIVER_WSCONS
55 &WSCONS_bootstrap, 55 &WSCONS_bootstrap,
56 #endif 56 #endif
57 #if SDL_VIDEO_DRIVER_FBCON 57 #if SDL_VIDEO_DRIVER_FBCON
58 &FBCON_bootstrap, 58 &FBCON_bootstrap,
59 #endif 59 #endif
60 #if SDL_VIDEO_DRIVER_DIRECTFB 60 #if SDL_VIDEO_DRIVER_DIRECTFB
61 &DirectFB_bootstrap, 61 &DirectFB_bootstrap,
62 #endif 62 #endif
63 #if SDL_VIDEO_DRIVER_PS2GS 63 #if SDL_VIDEO_DRIVER_PS2GS
64 &PS2GS_bootstrap, 64 &PS2GS_bootstrap,
65 #endif 65 #endif
66 #if SDL_VIDEO_DRIVER_GGI 66 #if SDL_VIDEO_DRIVER_GGI
67 &GGI_bootstrap, 67 &GGI_bootstrap,
68 #endif 68 #endif
69 #if SDL_VIDEO_DRIVER_VGL 69 #if SDL_VIDEO_DRIVER_VGL
70 &VGL_bootstrap, 70 &VGL_bootstrap,
71 #endif 71 #endif
72 #if SDL_VIDEO_DRIVER_SVGALIB 72 #if SDL_VIDEO_DRIVER_SVGALIB
73 &SVGALIB_bootstrap, 73 &SVGALIB_bootstrap,
74 #endif 74 #endif
75 #if SDL_VIDEO_DRIVER_GAPI 75 #if SDL_VIDEO_DRIVER_GAPI
76 &GAPI_bootstrap, 76 &GAPI_bootstrap,
77 #endif 77 #endif
78 #if SDL_VIDEO_DRIVER_WINDIB 78 #if SDL_VIDEO_DRIVER_WIN32
79 &WINDIB_bootstrap, 79 &WIN32_bootstrap,
80 #endif
81 #if SDL_VIDEO_DRIVER_DDRAW
82 &DIRECTX_bootstrap,
83 #endif 80 #endif
84 #if SDL_VIDEO_DRIVER_BWINDOW 81 #if SDL_VIDEO_DRIVER_BWINDOW
85 &BWINDOW_bootstrap, 82 &BWINDOW_bootstrap,
86 #endif 83 #endif
87 #if SDL_VIDEO_DRIVER_TOOLBOX 84 #if SDL_VIDEO_DRIVER_TOOLBOX
88 &TOOLBOX_bootstrap, 85 &TOOLBOX_bootstrap,
89 #endif 86 #endif
90 #if SDL_VIDEO_DRIVER_DRAWSPROCKET 87 #if SDL_VIDEO_DRIVER_DRAWSPROCKET
91 &DSp_bootstrap, 88 &DSp_bootstrap,
92 #endif 89 #endif
93 #if SDL_VIDEO_DRIVER_CYBERGRAPHICS 90 #if SDL_VIDEO_DRIVER_CYBERGRAPHICS
94 &CGX_bootstrap, 91 &CGX_bootstrap,
95 #endif 92 #endif
96 #if SDL_VIDEO_DRIVER_PHOTON 93 #if SDL_VIDEO_DRIVER_PHOTON
97 &ph_bootstrap, 94 &ph_bootstrap,
98 #endif 95 #endif
99 #if SDL_VIDEO_DRIVER_EPOC 96 #if SDL_VIDEO_DRIVER_EPOC
100 &EPOC_bootstrap, 97 &EPOC_bootstrap,
101 #endif 98 #endif
102 #if SDL_VIDEO_DRIVER_XBIOS 99 #if SDL_VIDEO_DRIVER_XBIOS
103 &XBIOS_bootstrap, 100 &XBIOS_bootstrap,
104 #endif 101 #endif
105 #if SDL_VIDEO_DRIVER_GEM 102 #if SDL_VIDEO_DRIVER_GEM
106 &GEM_bootstrap, 103 &GEM_bootstrap,
107 #endif 104 #endif
108 #if SDL_VIDEO_DRIVER_PICOGUI 105 #if SDL_VIDEO_DRIVER_PICOGUI
109 &PG_bootstrap, 106 &PG_bootstrap,
110 #endif 107 #endif
111 #if SDL_VIDEO_DRIVER_DC 108 #if SDL_VIDEO_DRIVER_DC
112 &DC_bootstrap, 109 &DC_bootstrap,
113 #endif 110 #endif
114 #if SDL_VIDEO_DRIVER_RISCOS 111 #if SDL_VIDEO_DRIVER_RISCOS
115 &RISCOS_bootstrap, 112 &RISCOS_bootstrap,
116 #endif 113 #endif
117 #if SDL_VIDEO_DRIVER_OS2FS 114 #if SDL_VIDEO_DRIVER_OS2FS
118 &OS2FSLib_bootstrap, 115 &OS2FSLib_bootstrap,
119 #endif 116 #endif
120 #if SDL_VIDEO_DRIVER_AALIB 117 #if SDL_VIDEO_DRIVER_AALIB
121 &AALIB_bootstrap, 118 &AALIB_bootstrap,
122 #endif 119 #endif
123 #if SDL_VIDEO_DRIVER_DUMMY 120 #if SDL_VIDEO_DRIVER_DUMMY
124 &DUMMY_bootstrap, 121 &DUMMY_bootstrap,
125 #endif 122 #endif
126 NULL 123 #if SDL_VIDEO_DRIVER_GLSDL
124 &glSDL_bootstrap,
125 #endif
126 NULL
127 }; 127 };
128 128
129 SDL_VideoDevice *current_video = NULL; 129 static SDL_VideoDevice *_this = NULL;
130 130
131 /* Various local functions */ 131 /* Various local functions */
132 int SDL_VideoInit(const char *driver_name, Uint32 flags); 132 int SDL_VideoInit(const char *driver_name, Uint32 flags);
133 void SDL_VideoQuit(void); 133 void SDL_VideoQuit(void);
134 void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects); 134
135 135 static int
136 static SDL_GrabMode SDL_WM_GrabInputOff(void); 136 cmpmodes(const void *A, const void *B)
137 #if SDL_VIDEO_OPENGL 137 {
138 static int lock_count = 0; 138 SDL_DisplayMode a = *(const SDL_DisplayMode *) A;
139 #endif 139 SDL_DisplayMode b = *(const SDL_DisplayMode *) B;
140 140
141 if (a.w != b.w) {
142 return b.w - a.w;
143 }
144 if (a.h != b.h) {
145 return b.h - a.h;
146 }
147 if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
148 return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
149 }
150 if (a.refresh_rate != b.refresh_rate) {
151 return b.refresh_rate - a.refresh_rate;
152 }
153 return 0;
154 }
155
156 int
157 SDL_GetNumVideoDrivers(void)
158 {
159 return SDL_arraysize(bootstrap) - 1;
160 }
161
162 const char *
163 SDL_GetVideoDriver(int index)
164 {
165 if (index >= 0 && index < SDL_GetNumVideoDrivers()) {
166 return bootstrap[index]->name;
167 }
168 return NULL;
169 }
141 170
142 /* 171 /*
143 * Initialize the video and event subsystems -- determine native pixel format 172 * Initialize the video and event subsystems -- determine native pixel format
144 */ 173 */
145 int SDL_VideoInit (const char *driver_name, Uint32 flags) 174 int
146 { 175 SDL_VideoInit(const char *driver_name, Uint32 flags)
147 SDL_VideoDevice *video; 176 {
148 int index; 177 SDL_VideoDevice *video;
149 int i; 178 int index;
150 SDL_PixelFormat vformat; 179 int i;
151 Uint32 video_flags; 180
152 181 /* Toggle the event thread flags, based on OS requirements */
153 /* Toggle the event thread flags, based on OS requirements */
154 #if defined(MUST_THREAD_EVENTS) 182 #if defined(MUST_THREAD_EVENTS)
155 flags |= SDL_INIT_EVENTTHREAD; 183 flags |= SDL_INIT_EVENTTHREAD;
156 #elif defined(CANT_THREAD_EVENTS) 184 #elif defined(CANT_THREAD_EVENTS)
157 if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) { 185 if ((flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD) {
158 SDL_SetError("OS doesn't support threaded events"); 186 SDL_SetError("OS doesn't support threaded events");
159 return(-1); 187 return -1;
160 } 188 }
161 #endif 189 #endif
162 190
163 /* Check to make sure we don't overwrite 'current_video' */ 191 /* Start the event loop */
164 if ( current_video != NULL ) { 192 if (SDL_StartEventLoop(flags) < 0) {
165 SDL_VideoQuit(); 193 return -1;
166 } 194 }
167 195
168 /* Select the proper video driver */ 196 /* Check to make sure we don't overwrite '_this' */
169 index = 0; 197 if (_this != NULL) {
170 video = NULL; 198 SDL_VideoQuit();
171 if ( driver_name != NULL ) { 199 }
172 #if 0 /* This will be replaced with a better driver selection API */ 200
173 if ( SDL_strrchr(driver_name, ':') != NULL ) { 201 /* Select the proper video driver */
174 index = atoi(SDL_strrchr(driver_name, ':')+1); 202 index = 0;
175 } 203 video = NULL;
176 #endif 204 if (driver_name != NULL) {
177 for ( i=0; bootstrap[i]; ++i ) { 205 for (i = 0; bootstrap[i]; ++i) {
178 if ( SDL_strncmp(bootstrap[i]->name, driver_name, 206 if (SDL_strncmp(bootstrap[i]->name, driver_name,
179 SDL_strlen(bootstrap[i]->name)) == 0 ) { 207 SDL_strlen(bootstrap[i]->name)) == 0) {
180 if ( bootstrap[i]->available() ) { 208 if (bootstrap[i]->available()) {
181 video = bootstrap[i]->create(index); 209 video = bootstrap[i]->create(index);
182 break; 210 }
183 } 211 break;
184 } 212 }
185 } 213 }
186 } else { 214 } else {
187 for ( i=0; bootstrap[i]; ++i ) { 215 for (i = 0; bootstrap[i]; ++i) {
188 if ( bootstrap[i]->available() ) { 216 if (bootstrap[i]->available()) {
189 video = bootstrap[i]->create(index); 217 video = bootstrap[i]->create(index);
190 if ( video != NULL ) { 218 if (video != NULL) {
191 break; 219 break;
192 } 220 }
193 } 221 }
194 } 222 }
195 } 223 }
196 if ( video == NULL ) { 224 if (video == NULL) {
197 SDL_SetError("No available video device"); 225 if (driver_name) {
198 return(-1); 226 SDL_SetError("%s not available", driver_name);
199 } 227 } else {
200 current_video = video; 228 SDL_SetError("No available video device");
201 current_video->name = bootstrap[i]->name; 229 }
202 230 return -1;
203 /* Do some basic variable initialization */ 231 }
204 video->screen = NULL; 232 _this = video;
205 video->shadow = NULL; 233 _this->name = bootstrap[i]->name;
206 video->visible = NULL; 234 _this->next_object_id = 1;
207 video->physpal = NULL; 235
208 video->gammacols = NULL; 236
209 video->gamma = NULL; 237 /* Set some very sane GL defaults */
210 video->wm_title = NULL; 238 _this->gl_config.driver_loaded = 0;
211 video->wm_icon = NULL; 239 _this->gl_config.dll_handle = NULL;
212 video->offset_x = 0; 240 _this->gl_config.red_size = 3;
213 video->offset_y = 0; 241 _this->gl_config.green_size = 3;
214 SDL_memset(&video->info, 0, (sizeof video->info)); 242 _this->gl_config.blue_size = 2;
215 243 _this->gl_config.alpha_size = 0;
216 video->displayformatalphapixel = NULL; 244 _this->gl_config.buffer_size = 0;
217 245 _this->gl_config.depth_size = 16;
218 /* Set some very sane GL defaults */ 246 _this->gl_config.stencil_size = 0;
219 video->gl_config.driver_loaded = 0; 247 _this->gl_config.double_buffer = 1;
220 video->gl_config.dll_handle = NULL; 248 _this->gl_config.accum_red_size = 0;
221 video->gl_config.red_size = 3; 249 _this->gl_config.accum_green_size = 0;
222 video->gl_config.green_size = 3; 250 _this->gl_config.accum_blue_size = 0;
223 video->gl_config.blue_size = 2; 251 _this->gl_config.accum_alpha_size = 0;
224 video->gl_config.alpha_size = 0; 252 _this->gl_config.stereo = 0;
225 video->gl_config.buffer_size = 0; 253 _this->gl_config.multisamplebuffers = 0;
226 video->gl_config.depth_size = 16; 254 _this->gl_config.multisamplesamples = 0;
227 video->gl_config.stencil_size = 0; 255 _this->gl_config.accelerated = -1; /* not known, don't set */
228 video->gl_config.double_buffer = 1; 256
229 video->gl_config.accum_red_size = 0; 257 /* Initialize the video subsystem */
230 video->gl_config.accum_green_size = 0; 258 if (_this->VideoInit(_this) < 0) {
231 video->gl_config.accum_blue_size = 0; 259 SDL_VideoQuit();
232 video->gl_config.accum_alpha_size = 0; 260 return -1;
233 video->gl_config.stereo = 0; 261 }
234 video->gl_config.multisamplebuffers = 0; 262
235 video->gl_config.multisamplesamples = 0; 263 /* Make sure some displays were added */
236 video->gl_config.accelerated = -1; /* not known, don't set */ 264 if (_this->num_displays == 0) {
237 video->gl_config.swap_control = -1; /* not known, don't set */ 265 SDL_SetError("The video driver did not add any displays");
238 266 SDL_VideoQuit();
239 /* Initialize the video subsystem */ 267 return (-1);
240 SDL_memset(&vformat, 0, sizeof(vformat)); 268 }
241 if ( video->VideoInit(video, &vformat) < 0 ) { 269
242 SDL_VideoQuit(); 270 /* The software renderer is always available */
243 return(-1); 271 for (i = 0; i < _this->num_displays; ++i) {
244 } 272 if (_this->displays[i].num_render_drivers > 0) {
245 273 SDL_AddRenderDriver(i, &SDL_SW_RenderDriver);
246 /* Create a zero sized video surface of the appropriate format */ 274 }
247 video_flags = SDL_SWSURFACE; 275 }
248 SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0, 276
249 vformat.BitsPerPixel, 277 /* We're ready to go! */
250 vformat.Rmask, vformat.Gmask, vformat.Bmask, 0); 278 return 0;
251 if ( SDL_VideoSurface == NULL ) { 279 }
252 SDL_VideoQuit(); 280
253 return(-1); 281 const char *
254 } 282 SDL_GetCurrentVideoDriver()
255 SDL_PublicSurface = NULL; /* Until SDL_SetVideoMode() */ 283 {
256 284 if (!_this) {
257 #if 0 /* Don't change the current palette - may be used by other programs. 285 return NULL;
258 * The application can't do anything with the display surface until 286 }
259 * a video mode has been set anyway. :) 287 return _this->name;
260 */ 288 }
261 /* If we have a palettized surface, create a default palette */ 289
262 if ( SDL_VideoSurface->format->palette ) { 290 SDL_VideoDevice *
263 SDL_PixelFormat *vf = SDL_VideoSurface->format; 291 SDL_GetVideoDevice()
264 SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); 292 {
265 video->SetColors(video, 293 return _this;
266 0, vf->palette->ncolors, vf->palette->colors); 294 }
267 } 295
268 #endif 296 int
269 video->info.vfmt = SDL_VideoSurface->format; 297 SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode)
270 298 {
271 /* Start the event loop */ 299 SDL_VideoDisplay display;
272 if ( SDL_StartEventLoop(flags) < 0 ) { 300
273 SDL_VideoQuit(); 301 SDL_zero(display);
274 return(-1); 302 if (desktop_mode) {
275 } 303 display.desktop_mode = *desktop_mode;
276 SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD); 304 }
277 305 display.current_mode = display.desktop_mode;
278 /* We're ready to go! */ 306
279 return(0); 307 return SDL_AddVideoDisplay(&display);
280 } 308 }
281 309
282 char *SDL_VideoDriverName(char *namebuf, int maxlen) 310 int
283 { 311 SDL_AddVideoDisplay(const SDL_VideoDisplay * display)
284 if ( current_video != NULL ) { 312 {
285 SDL_strlcpy(namebuf, current_video->name, maxlen); 313 SDL_VideoDisplay *displays;
286 return(namebuf); 314 int index = -1;
287 } 315
288 return(NULL); 316 displays =
289 } 317 SDL_realloc(_this->displays,
290 318 (_this->num_displays + 1) * sizeof(*displays));
291 /* 319 if (displays) {
292 * Get the current display surface 320 index = _this->num_displays++;
293 */ 321 displays[index] = *display;
294 SDL_Surface *SDL_GetVideoSurface(void) 322 displays[index].device = _this;
295 { 323 _this->displays = displays;
296 SDL_Surface *visible; 324 } else {
297 325 SDL_OutOfMemory();
298 visible = NULL; 326 }
299 if ( current_video ) { 327 return index;
300 visible = current_video->visible; 328 }
301 } 329
302 return(visible); 330 int
303 } 331 SDL_GetNumVideoDisplays(void)
304 332 {
305 /* 333 if (!_this) {
306 * Get the current information about the video hardware 334 return 0;
307 */ 335 }
308 const SDL_VideoInfo *SDL_GetVideoInfo(void) 336 return _this->num_displays;
309 { 337 }
310 const SDL_VideoInfo *info; 338
311 339 int
312 info = NULL; 340 SDL_SelectVideoDisplay(int index)
313 if ( current_video ) { 341 {
314 info = &current_video->info; 342 if (!_this) {
315 } 343 SDL_SetError("Video subsystem has not been initialized");
316 return(info); 344 return (-1);
317 } 345 }
318 346 if (index >= 0) {
319 /* 347 if (index >= _this->num_displays) {
320 * Return a pointer to an array of available screen dimensions for the 348 SDL_SetError("index must be in the range 0 - %d",
321 * given format, sorted largest to smallest. Returns NULL if there are 349 _this->num_displays - 1);
322 * no dimensions available for a particular format, or (SDL_Rect **)-1 350 return -1;
323 * if any dimension is okay for the given format. If 'format' is NULL, 351 }
324 * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt 352 _this->current_display = index;
325 */ 353 }
326 SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags) 354 return _this->current_display;
327 { 355 }
328 SDL_VideoDevice *video = current_video; 356
329 SDL_VideoDevice *this = current_video; 357 SDL_bool
330 SDL_Rect **modes; 358 SDL_AddDisplayMode(int displayIndex, const SDL_DisplayMode * mode)
331 359 {
332 modes = NULL; 360 SDL_VideoDisplay *display = &_this->displays[displayIndex];
333 if ( SDL_VideoSurface ) { 361 SDL_DisplayMode *modes;
334 if ( format == NULL ) { 362 int i, nmodes;
335 format = SDL_VideoSurface->format; 363
336 } 364 /* Make sure we don't already have the mode in the list */
337 modes = video->ListModes(this, format, flags); 365 modes = display->display_modes;
338 } 366 nmodes = display->num_display_modes;
339 return(modes); 367 for (i = nmodes; i--;) {
340 } 368 if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) {
341 369 return SDL_FALSE;
342 /* 370 }
343 * Check to see if a particular video mode is supported. 371 }
344 * It returns 0 if the requested mode is not supported under any bit depth, 372
345 * or returns the bits-per-pixel of the closest available mode with the 373 /* Go ahead and add the new mode */
346 * given width and height. If this bits-per-pixel is different from the 374 if (nmodes == display->max_display_modes) {
347 * one used when setting the video mode, SDL_SetVideoMode() will succeed, 375 modes =
348 * but will emulate the requested bits-per-pixel with a shadow surface. 376 SDL_realloc(modes,
349 */ 377 (display->max_display_modes + 32) * sizeof(*modes));
350 static Uint8 SDL_closest_depths[4][8] = { 378 if (!modes) {
351 /* 8 bit closest depth ordering */ 379 return SDL_FALSE;
352 { 0, 8, 16, 15, 32, 24, 0, 0 }, 380 }
353 /* 15,16 bit closest depth ordering */ 381 display->display_modes = modes;
354 { 0, 16, 15, 32, 24, 8, 0, 0 }, 382 display->max_display_modes += 32;
355 /* 24 bit closest depth ordering */ 383 }
356 { 0, 24, 32, 16, 15, 8, 0, 0 }, 384 modes[nmodes] = *mode;
357 /* 32 bit closest depth ordering */ 385 display->num_display_modes++;
358 { 0, 32, 16, 15, 24, 8, 0, 0 } 386
359 }; 387 return SDL_TRUE;
360 388 }
361 389
362 #ifdef __MACOS__ /* MPW optimization bug? */ 390 int
363 #define NEGATIVE_ONE 0xFFFFFFFF 391 SDL_GetNumDisplayModes()
364 #else 392 {
365 #define NEGATIVE_ONE -1 393 if (_this) {
366 #endif 394 SDL_VideoDisplay *display = &SDL_CurrentDisplay;
367 395 if (!display->num_display_modes && _this->GetDisplayModes) {
368 int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags) 396 _this->GetDisplayModes(_this);
369 { 397 SDL_qsort(display->display_modes, display->num_display_modes,
370 int table, b, i; 398 sizeof(SDL_DisplayMode), cmpmodes);
371 int supported; 399 }
372 SDL_PixelFormat format; 400 return display->num_display_modes;
373 SDL_Rect **sizes; 401 }
374 402 return 0;
375 /* Currently 1 and 4 bpp are not supported */ 403 }
376 if ( bpp < 8 || bpp > 32 ) { 404
377 return(0); 405 const SDL_DisplayMode *
378 } 406 SDL_GetDisplayMode(int index)
379 if ( (width <= 0) || (height <= 0) ) { 407 {
380 return(0); 408 if (index < 0 || index >= SDL_GetNumDisplayModes()) {
381 } 409 SDL_SetError("index must be in the range of 0 - %d",
382 410 SDL_GetNumDisplayModes() - 1);
383 /* Search through the list valid of modes */ 411 return NULL;
384 SDL_memset(&format, 0, sizeof(format)); 412 }
385 supported = 0; 413 return &SDL_CurrentDisplay.display_modes[index];
386 table = ((bpp+7)/8)-1; 414 }
387 SDL_closest_depths[table][0] = bpp; 415
388 SDL_closest_depths[table][7] = 0; 416 const SDL_DisplayMode *
389 for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) { 417 SDL_GetDesktopDisplayMode(void)
390 format.BitsPerPixel = SDL_closest_depths[table][b]; 418 {
391 sizes = SDL_ListModes(&format, flags); 419 if (_this) {
392 if ( sizes == (SDL_Rect **)0 ) { 420 return &SDL_CurrentDisplay.desktop_mode;
393 /* No sizes supported at this bit-depth */ 421 }
394 continue; 422 return NULL;
395 } else 423 }
396 if (sizes == (SDL_Rect **)NEGATIVE_ONE) { 424
397 /* Any size supported at this bit-depth */ 425 const SDL_DisplayMode *
398 supported = 1; 426 SDL_GetCurrentDisplayMode(void)
399 continue; 427 {
400 } else if (current_video->handles_any_size) { 428 if (_this) {
401 /* Driver can center a smaller surface to simulate fullscreen */ 429 return &SDL_CurrentDisplay.current_mode;
402 for ( i=0; sizes[i]; ++i ) { 430 }
403 if ((sizes[i]->w >= width) && (sizes[i]->h >= height)) { 431 return NULL;
404 supported = 1; /* this mode can fit the centered window. */ 432 }
405 break; 433
406 } 434 SDL_DisplayMode *
407 } 435 SDL_GetClosestDisplayMode(const SDL_DisplayMode * mode,
408 } else 436 SDL_DisplayMode * closest)
409 for ( i=0; sizes[i]; ++i ) { 437 {
410 if ((sizes[i]->w == width) && (sizes[i]->h == height)) { 438 Uint32 target_format;
411 supported = 1; 439 int target_refresh_rate;
412 break; 440 int i;
413 } 441 SDL_DisplayMode *current, *match;
414 } 442
415 } 443 if (!_this || !mode || !closest) {
416 if ( supported ) { 444 return NULL;
417 --b; 445 }
418 return(SDL_closest_depths[table][b]); 446
419 } else { 447 /* Default to the desktop format */
420 return(0); 448 if (mode->format) {
421 } 449 target_format = mode->format;
422 } 450 } else {
423 451 target_format = SDL_CurrentDisplay.desktop_mode.format;
424 /* 452 }
425 * Get the closest non-emulated video mode to the one requested 453
426 */ 454 /* Default to the desktop refresh rate */
427 static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags) 455 if (mode->refresh_rate) {
428 { 456 target_refresh_rate = mode->refresh_rate;
429 int table, b, i; 457 } else {
430 int supported; 458 target_refresh_rate = SDL_CurrentDisplay.desktop_mode.refresh_rate;
431 int native_bpp; 459 }
432 SDL_PixelFormat format; 460
433 SDL_Rect **sizes; 461 match = NULL;
434 462 for (i = 0; i < SDL_GetNumDisplayModes(); ++i) {
435 /* Check parameters */ 463 current = &SDL_CurrentDisplay.display_modes[i];
436 if ( *BitsPerPixel < 8 || *BitsPerPixel > 32 ) { 464
437 SDL_SetError("Invalid bits per pixel (range is {8...32})"); 465 if ((current->w && current->h) &&
438 return(0); 466 (current->w < mode->w || current->h < mode->h)) {
439 } 467 /* Out of sorted modes large enough here */
440 if ((*w <= 0) || (*h <= 0)) { 468 break;
441 SDL_SetError("Invalid width or height"); 469 }
442 return(0); 470 if (!match || current->w < match->w || current->h < match->h) {
443 } 471 match = current;
444 472 continue;
445 /* Try the original video mode, get the closest depth */ 473 }
446 native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags); 474 if (current->format != match->format) {
447 if ( native_bpp == *BitsPerPixel ) { 475 /* Sorted highest depth to lowest */
448 return(1); 476 if (current->format == target_format ||
449 } 477 (SDL_BITSPERPIXEL(current->format) >=
450 if ( native_bpp > 0 ) { 478 SDL_BITSPERPIXEL(target_format)
451 *BitsPerPixel = native_bpp; 479 && SDL_PIXELTYPE(current->format) ==
452 return(1); 480 SDL_PIXELTYPE(target_format))) {
453 } 481 match = current;
454 482 }
455 /* No exact size match at any depth, look for closest match */ 483 continue;
456 SDL_memset(&format, 0, sizeof(format)); 484 }
457 supported = 0; 485 if (current->refresh_rate != match->refresh_rate) {
458 table = ((*BitsPerPixel+7)/8)-1; 486 /* Sorted highest refresh to lowest */
459 SDL_closest_depths[table][0] = *BitsPerPixel; 487 if (current->refresh_rate >= target_refresh_rate) {
460 SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel; 488 match = current;
461 for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) { 489 }
462 int best; 490 }
463 491 }
464 format.BitsPerPixel = SDL_closest_depths[table][b]; 492 if (match) {
465 sizes = SDL_ListModes(&format, flags); 493 if (match->format) {
466 if ( sizes == (SDL_Rect **)0 ) { 494 closest->format = match->format;
467 /* No sizes supported at this bit-depth */ 495 } else {
468 continue; 496 closest->format = mode->format;
469 } 497 }
470 best=0; 498 if (match->w && match->h) {
471 for ( i=0; sizes[i]; ++i ) { 499 closest->w = match->w;
472 /* Mode with both dimensions bigger or equal than asked ? */ 500 closest->h = match->h;
473 if ((sizes[i]->w >= *w) && (sizes[i]->h >= *h)) { 501 } else {
474 /* Mode with any dimension smaller or equal than current best ? */ 502 closest->w = mode->w;
475 if ((sizes[i]->w <= sizes[best]->w) || (sizes[i]->h <= sizes[best]->h)) { 503 closest->h = mode->h;
476 /* Now choose the mode that has less pixels */ 504 }
477 if ((sizes[i]->w * sizes[i]->h) <= (sizes[best]->w * sizes[best]->h)) { 505 if (match->refresh_rate) {
478 best=i; 506 closest->refresh_rate = match->refresh_rate;
479 supported = 1; 507 } else {
480 } 508 closest->refresh_rate = mode->refresh_rate;
481 } 509 }
482 } 510 closest->driverdata = match->driverdata;
483 } 511
484 if (supported) { 512 /* Pick some reasonable defaults if the app and driver don't care */
485 *w=sizes[best]->w; 513 if (!closest->format) {
486 *h=sizes[best]->h; 514 closest->format = SDL_PixelFormat_RGB888;
487 *BitsPerPixel = SDL_closest_depths[table][b]; 515 }
488 } 516 if (!closest->w) {
489 } 517 closest->w = 640;
490 if ( ! supported ) { 518 }
491 SDL_SetError("No video mode large enough for %dx%d", *w, *h); 519 if (!closest->h) {
492 } 520 closest->h = 480;
493 return(supported); 521 }
494 } 522 return closest;
495 523 }
496 /* This should probably go somewhere else -- like SDL_surface.c */ 524 return NULL;
497 static void SDL_ClearSurface(SDL_Surface *surface) 525 }
498 { 526
499 Uint32 black; 527 int
500 528 SDL_SetDisplayMode(const SDL_DisplayMode * mode)
501 black = SDL_MapRGB(surface->format, 0, 0, 0); 529 {
502 SDL_FillRect(surface, NULL, black); 530 SDL_VideoDisplay *display;
503 if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) { 531 SDL_DisplayMode display_mode;
504 SDL_Flip(surface); 532 int i, ncolors;
505 SDL_FillRect(surface, NULL, black); 533
506 } 534 if (!_this) {
507 SDL_Flip(surface); 535 SDL_SetError("Video subsystem has not been initialized");
508 } 536 return -1;
509 537 }
510 /* 538
511 * Create a shadow surface suitable for fooling the app. :-) 539 if (!mode) {
512 */ 540 mode = SDL_GetDesktopDisplayMode();
513 static void SDL_CreateShadowSurface(int depth) 541 }
514 { 542 display = &SDL_CurrentDisplay;
515 Uint32 Rmask, Gmask, Bmask; 543 display_mode = *mode;
516 544
517 /* Allocate the shadow surface */ 545 /* Default to the current mode */
518 if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { 546 if (!display_mode.format) {
519 Rmask = (SDL_VideoSurface->format)->Rmask; 547 display_mode.format = display->current_mode.format;
520 Gmask = (SDL_VideoSurface->format)->Gmask; 548 }
521 Bmask = (SDL_VideoSurface->format)->Bmask; 549 if (!display_mode.w) {
522 } else { 550 display_mode.w = display->current_mode.w;
523 Rmask = Gmask = Bmask = 0; 551 }
524 } 552 if (!display_mode.h) {
525 SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 553 display_mode.h = display->current_mode.h;
526 SDL_VideoSurface->w, SDL_VideoSurface->h, 554 }
527 depth, Rmask, Gmask, Bmask, 0); 555 if (!display_mode.refresh_rate) {
528 if ( SDL_ShadowSurface == NULL ) { 556 display_mode.refresh_rate = display->current_mode.refresh_rate;
529 return; 557 }
530 } 558
531 559 /* Get a good video mode, the closest one possible */
532 /* 8-bit shadow surfaces report that they have exclusive palette */ 560 if (!SDL_GetClosestDisplayMode(&display_mode, &display_mode)) {
533 if ( SDL_ShadowSurface->format->palette ) { 561 SDL_SetError("No video mode large enough for %dx%d",
534 SDL_ShadowSurface->flags |= SDL_HWPALETTE; 562 display_mode.w, display_mode.h);
535 if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { 563 return -1;
536 SDL_memcpy(SDL_ShadowSurface->format->palette->colors, 564 }
537 SDL_VideoSurface->format->palette->colors, 565
538 SDL_VideoSurface->format->palette->ncolors* 566 /* See if there's anything left to do */
539 sizeof(SDL_Color)); 567 if (SDL_memcmp
540 } else { 568 (&display_mode, SDL_GetCurrentDisplayMode(),
541 SDL_DitherColors( 569 sizeof(display_mode)) == 0) {
542 SDL_ShadowSurface->format->palette->colors, depth); 570 return 0;
543 } 571 }
544 } 572
545 573 /* Actually change the display mode */
546 /* If the video surface is resizable, the shadow should say so */ 574 if (_this->SetDisplayMode(_this, &display_mode) < 0) {
547 if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) { 575 return -1;
548 SDL_ShadowSurface->flags |= SDL_RESIZABLE; 576 }
549 } 577 display->current_mode = display_mode;
550 /* If the video surface has no frame, the shadow should say so */ 578
551 if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) { 579 /* Set up a palette, if necessary */
552 SDL_ShadowSurface->flags |= SDL_NOFRAME; 580 if (SDL_ISPIXELFORMAT_INDEXED(display_mode.format)) {
553 } 581 ncolors = (1 << SDL_BITSPERPIXEL(display_mode.format));
554 /* If the video surface is fullscreen, the shadow should say so */ 582 } else {
555 if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { 583 ncolors = 0;
556 SDL_ShadowSurface->flags |= SDL_FULLSCREEN; 584 }
557 } 585 if ((!ncolors && display->palette) || (ncolors && !display->palette)
558 /* If the video surface is flippable, the shadow should say so */ 586 || (ncolors && ncolors != display->palette->ncolors)) {
559 if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { 587 if (display->palette) {
560 SDL_ShadowSurface->flags |= SDL_DOUBLEBUF; 588 SDL_FreePalette(display->palette);
561 } 589 display->palette = NULL;
562 return; 590 }
563 } 591 if (ncolors) {
564 592 display->palette = SDL_AllocPalette(ncolors);
565 #ifdef __QNXNTO__ 593 if (!display->palette) {
566 #include <sys/neutrino.h> 594 return -1;
567 #endif /* __QNXNTO__ */ 595 }
568 596 SDL_DitherColors(display->palette->colors,
569 /* 597 SDL_BITSPERPIXEL(display_mode.format));
570 * Set the requested video mode, allocating a shadow buffer if necessary. 598 }
571 */ 599 }
572 SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) 600
573 { 601 /* Move any fullscreen windows into position */
574 SDL_VideoDevice *video, *this; 602 for (i = 0; i < display->num_windows; ++i) {
575 SDL_Surface *prev_mode, *mode; 603 SDL_Window *window = &display->windows[i];
576 int video_w; 604 if (FULLSCREEN_VISIBLE(window)) {
577 int video_h; 605 SDL_SetWindowPosition(window->id,
578 int video_bpp; 606 ((display_mode.w - window->w) / 2),
579 int is_opengl; 607 ((display_mode.h - window->h) / 2));
580 SDL_GrabMode saved_grab; 608 }
581 609 }
582 /* Start up the video driver, if necessary.. 610
583 WARNING: This is the only function protected this way! 611 return 0;
584 */ 612 }
585 if ( ! current_video ) { 613
586 if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) { 614 int
587 return(NULL); 615 SDL_SetFullscreenDisplayMode(const SDL_DisplayMode * mode)
588 } 616 {
589 } 617 SDL_VideoDisplay *display;
590 this = video = current_video; 618 int i;
591 619
592 /* Default to the current width and height */ 620 if (!_this) {
593 if ( width == 0 ) { 621 SDL_SetError("Video subsystem has not been initialized");
594 width = video->info.current_w; 622 return -1;
595 } 623 }
596 if ( height == 0 ) { 624
597 height = video->info.current_h; 625 display = &SDL_CurrentDisplay;
598 } 626 if (mode) {
599 /* Default to the current video bpp */ 627 SDL_GetClosestDisplayMode(mode, &display->desired_mode);
600 if ( bpp == 0 ) { 628 display->fullscreen_mode = &display->desired_mode;
601 flags |= SDL_ANYFORMAT; 629 } else {
602 bpp = SDL_VideoSurface->format->BitsPerPixel; 630 display->fullscreen_mode = NULL;
603 } 631 }
604 632
605 /* Get a good video mode, the closest one possible */ 633 /* Actually set the mode if we have a fullscreen window visible */
606 video_w = width; 634 for (i = 0; i < display->num_windows; ++i) {
607 video_h = height; 635 SDL_Window *window = &display->windows[i];
608 video_bpp = bpp; 636 if (FULLSCREEN_VISIBLE(window)) {
609 if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) { 637 return SDL_SetDisplayMode(display->fullscreen_mode);
610 return(NULL); 638 }
611 } 639 }
612 640 return 0;
613 /* Check the requested flags */ 641 }
614 /* There's no palette in > 8 bits-per-pixel mode */ 642
615 if ( video_bpp > 8 ) { 643 const SDL_DisplayMode *
616 flags &= ~SDL_HWPALETTE; 644 SDL_GetFullscreenDisplayMode(void)
617 } 645 {
618 #if 0 646 if (_this) {
619 if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) { 647 return SDL_CurrentDisplay.fullscreen_mode;
620 /* There's no windowed double-buffering */ 648 }
621 flags &= ~SDL_DOUBLEBUF; 649 return NULL;
622 } 650 }
623 #endif 651
624 if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { 652 int
625 /* Use hardware surfaces when double-buffering */ 653 SDL_SetDisplayPalette(const SDL_Color * colors, int firstcolor, int ncolors)
626 flags |= SDL_HWSURFACE; 654 {
627 } 655 SDL_Palette *palette;
628 656 int status = 0;
629 is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL ); 657
630 if ( is_opengl ) { 658 if (!_this) {
631 /* These flags are for 2D video modes only */ 659 SDL_SetError("Video subsystem has not been initialized");
632 flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF); 660 return -1;
633 } 661 }
634 662 palette = SDL_CurrentDisplay.palette;
635 /* Reset the keyboard here so event callbacks can run */ 663 if (!palette) {
636 SDL_ResetKeyboard(); 664 SDL_SetError("Display mode does not have a palette");
637 SDL_ResetMouse(); 665 return -1;
638 SDL_cursorstate &= ~CURSOR_USINGSW; 666 }
639 667
640 /* Clean up any previous video mode */ 668 status = SDL_SetPaletteColors(palette, colors, firstcolor, ncolors);
641 if ( SDL_PublicSurface != NULL ) { 669
642 SDL_PublicSurface = NULL; 670 if (_this->SetDisplayPalette) {
643 } 671 if (_this->SetDisplayPalette(_this, palette) < 0) {
644 if ( SDL_ShadowSurface != NULL ) { 672 status = -1;
645 SDL_Surface *ready_to_go; 673 }
646 ready_to_go = SDL_ShadowSurface; 674 }
647 SDL_ShadowSurface = NULL; 675 return status;
648 SDL_FreeSurface(ready_to_go); 676 }
649 } 677
650 if ( video->physpal ) { 678 int
651 SDL_free(video->physpal->colors); 679 SDL_GetDisplayPalette(SDL_Color * colors, int firstcolor, int ncolors)
652 SDL_free(video->physpal); 680 {
653 video->physpal = NULL; 681 SDL_Palette *palette;
654 } 682
655 if( video->gammacols) { 683 if (!_this) {
656 SDL_free(video->gammacols); 684 SDL_SetError("Video subsystem has not been initialized");
657 video->gammacols = NULL; 685 return -1;
658 } 686 }
659 687
660 /* Save the previous grab state and turn off grab for mode switch */ 688 palette = SDL_CurrentDisplay.palette;
661 saved_grab = SDL_WM_GrabInputOff(); 689 if (!palette->ncolors) {
662 690 SDL_SetError("Display mode does not have a palette");
663 /* Try to set the video mode, along with offset and clipping */ 691 return -1;
664 prev_mode = SDL_VideoSurface; 692 }
665 SDL_LockCursor(); 693
666 SDL_VideoSurface = NULL; /* In case it's freed by driver */ 694 if (firstcolor < 0 || (firstcolor + ncolors) > palette->ncolors) {
667 mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags); 695 SDL_SetError("Palette indices are out of range");
668 if ( mode ) { /* Prevent resize events from mode change */ 696 return -1;
669 /* But not on OS/2 */ 697 }
670 #ifndef __OS2__ 698
671 SDL_PrivateResize(mode->w, mode->h); 699 SDL_memcpy(colors, &palette->colors[firstcolor],
672 #endif 700 ncolors * sizeof(*colors));
673 701 return 0;
674 /* Sam - If we asked for OpenGL mode, and didn't get it, fail */ 702 }
675 if ( is_opengl && !(mode->flags & SDL_OPENGL) ) { 703
676 mode = NULL; 704 SDL_WindowID
677 SDL_SetError("OpenGL not available"); 705 SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
678 } 706 {
679 } 707 const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
680 /* 708 SDL_WINDOW_OPENGL |
681 * rcg11292000 709 SDL_WINDOW_SHOWN |
682 * If you try to set an SDL_OPENGL surface, and fail to find a 710 SDL_WINDOW_BORDERLESS |
683 * matching visual, then the next call to SDL_SetVideoMode() 711 SDL_WINDOW_RESIZABLE |
684 * will segfault, since we no longer point to a dummy surface, 712 SDL_WINDOW_MAXIMIZED |
685 * but rather NULL. 713 SDL_WINDOW_MINIMIZED |
686 * Sam 11/29/00 714 SDL_WINDOW_INPUT_GRABBED);
687 * WARNING, we need to make sure that the previous mode hasn't 715 SDL_VideoDisplay *display;
688 * already been freed by the video driver. What do we do in 716 SDL_Window window;
689 * that case? Should we call SDL_VideoInit() again? 717 int num_windows;
690 */ 718 SDL_Window *windows;
691 SDL_VideoSurface = (mode != NULL) ? mode : prev_mode; 719
692 720 if (!_this) {
693 if ( (mode != NULL) && (!is_opengl) ) { 721 SDL_SetError("Video subsystem has not been initialized");
694 /* Sanity check */ 722 return 0;
695 if ( (mode->w < width) || (mode->h < height) ) { 723 }
696 SDL_SetError("Video mode smaller than requested"); 724
697 return(NULL); 725 SDL_zero(window);
698 } 726 window.id = _this->next_object_id++;
699 727 window.title = title ? SDL_strdup(title) : NULL;
700 /* If we have a palettized surface, create a default palette */ 728 window.x = x;
701 if ( mode->format->palette ) { 729 window.y = y;
702 SDL_PixelFormat *vf = mode->format; 730 window.w = w;
703 SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); 731 window.h = h;
704 video->SetColors(this, 0, vf->palette->ncolors, 732 window.flags = (flags & allowed_flags);
705 vf->palette->colors); 733 window.display = _this->current_display;
706 } 734
707 735 if (_this->CreateWindow && _this->CreateWindow(_this, &window) < 0) {
708 /* Clear the surface to black */ 736 if (window.title) {
709 video->offset_x = 0; 737 SDL_free(window.title);
710 video->offset_y = 0; 738 }
711 mode->offset = 0; 739 return 0;
712 SDL_SetClipRect(mode, NULL); 740 }
713 SDL_ClearSurface(mode); 741
714 742 display = &SDL_CurrentDisplay;
715 /* Now adjust the offsets to match the desired mode */ 743 num_windows = display->num_windows;
716 video->offset_x = (mode->w-width)/2; 744 windows =
717 video->offset_y = (mode->h-height)/2; 745 SDL_realloc(display->windows, (num_windows + 1) * sizeof(*windows));
718 mode->offset = video->offset_y*mode->pitch + 746 if (!windows) {
719 video->offset_x*mode->format->BytesPerPixel; 747 if (_this->DestroyWindow) {
720 #ifdef DEBUG_VIDEO 748 _this->DestroyWindow(_this, &window);
721 fprintf(stderr, 749 }
722 "Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n", 750 if (window.title) {
723 width, height, bpp, 751 SDL_free(window.title);
724 mode->w, mode->h, mode->format->BitsPerPixel, mode->offset); 752 }
725 #endif 753 return 0;
726 mode->w = width; 754 }
727 mode->h = height; 755 windows[num_windows] = window;
728 SDL_SetClipRect(mode, NULL); 756 display->windows = windows;
729 } 757 display->num_windows++;
730 SDL_ResetCursor(); 758
731 SDL_UnlockCursor(); 759 if (FULLSCREEN_VISIBLE(&window)) {
732 760 /* Hide any other fullscreen windows */
733 /* If we failed setting a video mode, return NULL... (Uh Oh!) */ 761 int i;
734 if ( mode == NULL ) { 762 for (i = 0; i < display->num_windows; ++i) {
735 return(NULL); 763 SDL_Window *other = &display->windows[i];
736 } 764 if (other->id != window.id && FULLSCREEN_VISIBLE(other)) {
737 765 SDL_MinimizeWindow(other->id);
738 /* If there is no window manager, set the SDL_NOFRAME flag */ 766 }
739 if ( ! video->info.wm_available ) { 767 }
740 mode->flags |= SDL_NOFRAME; 768 SDL_SetDisplayMode(display->fullscreen_mode);
741 } 769 }
742 770
743 /* Reset the mouse cursor and grab for new video mode */ 771 return window.id;
744 SDL_SetCursor(NULL); 772 }
745 if ( video->UpdateMouse ) { 773
746 video->UpdateMouse(this); 774 SDL_WindowID
747 } 775 SDL_CreateWindowFrom(const void *data)
748 SDL_WM_GrabInput(saved_grab); 776 {
749 SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */ 777 SDL_VideoDisplay *display;
750 778 SDL_Window window;
751 #if SDL_VIDEO_OPENGL 779 int num_windows;
752 /* Load GL symbols (before MakeCurrent, where we need glGetString). */ 780 SDL_Window *windows;
753 if ( flags & (SDL_OPENGL | SDL_OPENGLBLIT) ) { 781
754 782 if (!_this) {
755 #if defined(__QNXNTO__) && (_NTO_VERSION < 630) 783 SDL_SetError("Video subsystem has not been initialized");
756 #define __SDL_NOGETPROCADDR__ 784 return (0);
757 #elif defined(__MINT__) 785 }
758 #define __SDL_NOGETPROCADDR__ 786
759 #endif 787 SDL_zero(window);
760 #ifdef __SDL_NOGETPROCADDR__ 788 window.id = _this->next_object_id++;
761 #define SDL_PROC(ret,func,params) video->func=func; 789 window.display = _this->current_display;
762 #else 790
763 #define SDL_PROC(ret,func,params) \ 791 if (!_this->CreateWindowFrom ||
764 do { \ 792 _this->CreateWindowFrom(_this, &window, data) < 0) {
765 video->func = SDL_GL_GetProcAddress(#func); \ 793 return 0;
766 if ( ! video->func ) { \ 794 }
767 SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \ 795
768 return(NULL); \ 796 display = &SDL_CurrentDisplay;
769 } \ 797 num_windows = display->num_windows;
770 } while ( 0 ); 798 windows =
771 799 SDL_realloc(display->windows, (num_windows + 1) * sizeof(*windows));
772 #endif /* __SDL_NOGETPROCADDR__ */ 800 if (!windows) {
773 801 if (_this->DestroyWindow) {
774 #include "SDL_glfuncs.h" 802 _this->DestroyWindow(_this, &window);
775 #undef SDL_PROC 803 }
776 } 804 if (window.title) {
777 #endif /* SDL_VIDEO_OPENGL */ 805 SDL_free(window.title);
778 806 }
779 /* If we're running OpenGL, make the context current */ 807 return 0;
780 if ( (video->screen->flags & SDL_OPENGL) && 808 }
781 video->GL_MakeCurrent ) { 809 windows[num_windows] = window;
782 if ( video->GL_MakeCurrent(this) < 0 ) { 810 display->windows = windows;
783 return(NULL); 811 display->num_windows++;
784 } 812
785 } 813 return window.id;
786 814 }
787 /* Set up a fake SDL surface for OpenGL "blitting" */ 815
788 if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) { 816 SDL_Window *
789 /* Load GL functions for performing the texture updates */ 817 SDL_GetWindowFromID(SDL_WindowID windowID)
790 #if SDL_VIDEO_OPENGL 818 {
791 819 int i, j;
792 /* Create a software surface for blitting */ 820
793 #ifdef GL_VERSION_1_2 821 if (!_this) {
794 /* If the implementation either supports the packed pixels 822 return NULL;
795 extension, or implements the core OpenGL 1.2 API, it will 823 }
796 support the GL_UNSIGNED_SHORT_5_6_5 texture format. 824
797 */ 825 for (i = 0; i < _this->num_displays; ++i) {
798 if ( (bpp == 16) && 826 SDL_VideoDisplay *display = &_this->displays[i];
799 (SDL_strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") || 827 for (j = 0; j < display->num_windows; ++j) {
800 (SDL_atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f)) 828 SDL_Window *window = &display->windows[j];
801 ) { 829 if (window->id == windowID) {
802 video->is_32bit = 0; 830 return window;
803 SDL_VideoSurface = SDL_CreateRGBSurface( 831 }
804 flags, 832 }
805 width, 833 }
806 height, 834 return NULL;
807 16, 835 }
808 31 << 11, 836
809 63 << 5, 837 SDL_VideoDisplay *
810 31, 838 SDL_GetDisplayFromWindow(SDL_Window * window)
811 0 839 {
812 ); 840 if (!_this) {
813 } 841 return NULL;
814 else 842 }
815 #endif /* OpenGL 1.2 */ 843 return &_this->displays[window->display];
816 { 844 }
817 video->is_32bit = 1; 845
818 SDL_VideoSurface = SDL_CreateRGBSurface( 846 Uint32
819 flags, 847 SDL_GetWindowFlags(SDL_WindowID windowID)
820 width, 848 {
821 height, 849 SDL_Window *window = SDL_GetWindowFromID(windowID);
822 32, 850
823 #if SDL_BYTEORDER == SDL_LIL_ENDIAN 851 if (!window) {
824 0x000000FF, 852 return 0;
825 0x0000FF00, 853 }
826 0x00FF0000, 854 return window->flags;
827 0xFF000000 855 }
828 #else 856
829 0xFF000000, 857 void
830 0x00FF0000, 858 SDL_SetWindowTitle(SDL_WindowID windowID, const char *title)
831 0x0000FF00, 859 {
832 0x000000FF 860 SDL_Window *window = SDL_GetWindowFromID(windowID);
833 #endif 861
834 ); 862 if (!window) {
835 } 863 return;
836 if ( ! SDL_VideoSurface ) { 864 }
837 return(NULL); 865 if (window->title) {
838 } 866 SDL_free(window->title);
839 SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT; 867 }
840 868 window->title = SDL_strdup(title);
841 /* Free the original video mode surface (is this safe?) */ 869
842 SDL_FreeSurface(mode); 870 if (_this->SetWindowTitle) {
843 871 _this->SetWindowTitle(_this, window);
844 /* Set the surface completely opaque & white by default */ 872 }
845 SDL_memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch ); 873 }
846 video->glGenTextures( 1, &video->texture ); 874
847 video->glBindTexture( GL_TEXTURE_2D, video->texture ); 875 const char *
848 video->glTexImage2D( 876 SDL_GetWindowTitle(SDL_WindowID windowID)
849 GL_TEXTURE_2D, 877 {
850 0, 878 SDL_Window *window = SDL_GetWindowFromID(windowID);
851 video->is_32bit ? GL_RGBA : GL_RGB, 879
852 256, 880 if (!window) {
853 256, 881 return NULL;
854 0, 882 }
855 video->is_32bit ? GL_RGBA : GL_RGB, 883 return window->title;
856 #ifdef GL_VERSION_1_2 884 }
857 video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, 885
858 #else 886 void
859 GL_UNSIGNED_BYTE, 887 SDL_SetWindowData(SDL_WindowID windowID, void *userdata)
860 #endif 888 {
861 NULL); 889 SDL_Window *window = SDL_GetWindowFromID(windowID);
862 890
863 video->UpdateRects = SDL_GL_UpdateRectsLock; 891 if (!window) {
864 #else 892 return;
865 SDL_SetError("Somebody forgot to #define SDL_VIDEO_OPENGL"); 893 }
866 return(NULL); 894 window->userdata = userdata;
867 #endif 895 }
868 } 896
869 897 void *
870 /* Create a shadow surface if necessary */ 898 SDL_GetWindowData(SDL_WindowID windowID)
871 /* There are three conditions under which we create a shadow surface: 899 {
872 1. We need a particular bits-per-pixel that we didn't get. 900 SDL_Window *window = SDL_GetWindowFromID(windowID);
873 2. We need a hardware palette and didn't get one. 901
874 3. We need a software surface and got a hardware surface. 902 if (!window) {
875 */ 903 return NULL;
876 if ( !(SDL_VideoSurface->flags & SDL_OPENGL) && 904 }
877 ( 905 return window->userdata;
878 ( !(flags&SDL_ANYFORMAT) && 906 }
879 (SDL_VideoSurface->format->BitsPerPixel != bpp)) || 907
880 ( (flags&SDL_HWPALETTE) && 908 void
881 !(SDL_VideoSurface->flags&SDL_HWPALETTE)) || 909 SDL_SetWindowPosition(SDL_WindowID windowID, int x, int y)
882 /* If the surface is in hardware, video writes are visible 910 {
883 as soon as they are performed, so we need to buffer them 911 SDL_Window *window = SDL_GetWindowFromID(windowID);
884 */ 912
885 ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) && 913 if (!window) {
886 (SDL_VideoSurface->flags&SDL_HWSURFACE)) || 914 return;
887 ( (flags&SDL_DOUBLEBUF) && 915 }
888 (SDL_VideoSurface->flags&SDL_HWSURFACE) && 916
889 !(SDL_VideoSurface->flags&SDL_DOUBLEBUF)) 917 if (x != SDL_WINDOWPOS_UNDEFINED) {
890 ) ) { 918 window->x = x;
891 SDL_CreateShadowSurface(bpp); 919 }
892 if ( SDL_ShadowSurface == NULL ) { 920 if (y != SDL_WINDOWPOS_UNDEFINED) {
893 SDL_SetError("Couldn't create shadow surface"); 921 window->y = y;
894 return(NULL); 922 }
895 } 923
896 SDL_PublicSurface = SDL_ShadowSurface; 924 if (_this->SetWindowPosition) {
897 } else { 925 _this->SetWindowPosition(_this, window);
898 SDL_PublicSurface = SDL_VideoSurface; 926 }
899 } 927 }
900 video->info.vfmt = SDL_VideoSurface->format; 928
901 video->info.current_w = SDL_VideoSurface->w; 929 void
902 video->info.current_h = SDL_VideoSurface->h; 930 SDL_GetWindowPosition(SDL_WindowID windowID, int *x, int *y)
903 931 {
904 /* We're done! */ 932 SDL_Window *window = SDL_GetWindowFromID(windowID);
905 return(SDL_PublicSurface); 933
906 } 934 if (!window) {
907 935 return;
908 /* 936 }
909 * Convert a surface into the video pixel format. 937 if (x) {
910 */ 938 *x = window->x;
911 SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface) 939 }
912 { 940 if (y) {
913 Uint32 flags; 941 *y = window->y;
914 942 }
915 if ( ! SDL_PublicSurface ) { 943 }
916 SDL_SetError("No video mode has been set"); 944
917 return(NULL); 945 void
918 } 946 SDL_SetWindowSize(SDL_WindowID windowID, int w, int h)
919 /* Set the flags appropriate for copying to display surface */ 947 {
920 if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw) 948 SDL_Window *window = SDL_GetWindowFromID(windowID);
921 flags = SDL_HWSURFACE; 949
922 else 950 if (!window) {
923 flags = SDL_SWSURFACE; 951 return;
924 #ifdef AUTORLE_DISPLAYFORMAT 952 }
925 flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA)); 953
926 flags |= SDL_RLEACCELOK; 954 window->w = w;
927 #else 955 window->h = h;
928 flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK); 956
929 #endif 957 if (_this->SetWindowSize) {
930 return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags)); 958 _this->SetWindowSize(_this, window);
931 } 959 }
932 960 }
933 /* 961
934 * Convert a surface into a format that's suitable for blitting to 962 void
935 * the screen, but including an alpha channel. 963 SDL_GetWindowSize(SDL_WindowID windowID, int *w, int *h)
936 */ 964 {
937 SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface) 965 SDL_Window *window = SDL_GetWindowFromID(windowID);
938 { 966
939 SDL_PixelFormat *vf; 967 if (!window) {
940 SDL_PixelFormat *format; 968 return;
941 SDL_Surface *converted; 969 }
942 Uint32 flags; 970 if (w) {
943 /* default to ARGB8888 */ 971 *w = window->w;
944 Uint32 amask = 0xff000000; 972 }
945 Uint32 rmask = 0x00ff0000; 973 if (h) {
946 Uint32 gmask = 0x0000ff00; 974 *h = window->h;
947 Uint32 bmask = 0x000000ff; 975 }
948 976 }
949 if ( ! SDL_PublicSurface ) { 977
950 SDL_SetError("No video mode has been set"); 978 void
951 return(NULL); 979 SDL_ShowWindow(SDL_WindowID windowID)
952 } 980 {
953 vf = SDL_PublicSurface->format; 981 SDL_Window *window = SDL_GetWindowFromID(windowID);
954 982
955 switch(vf->BytesPerPixel) { 983 if (!window || (window->flags & SDL_WINDOW_SHOWN)) {
956 case 2: 984 return;
957 /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. 985 }
958 For anything else (like ARGB4444) it doesn't matter 986
959 since we have no special code for it anyway */ 987 SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0);
960 if ( (vf->Rmask == 0x1f) && 988
961 (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { 989 if (_this->ShowWindow) {
962 rmask = 0xff; 990 _this->ShowWindow(_this, window);
963 bmask = 0xff0000; 991 }
964 } 992 }
965 break; 993
966 994 void
967 case 3: 995 SDL_HideWindow(SDL_WindowID windowID)
968 case 4: 996 {
969 /* Keep the video format, as long as the high 8 bits are 997 SDL_Window *window = SDL_GetWindowFromID(windowID);
970 unused or alpha */ 998
971 if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) { 999 if (!window || !(window->flags & SDL_WINDOW_SHOWN)) {
972 rmask = 0xff; 1000 return;
973 bmask = 0xff0000; 1001 }
974 } 1002
975 break; 1003 SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0);
976 1004
977 default: 1005 if (_this->HideWindow) {
978 /* We have no other optimised formats right now. When/if a new 1006 _this->HideWindow(_this, window);
979 optimised alpha format is written, add the converter here */ 1007 }
980 break; 1008 }
981 } 1009
982 format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); 1010 void
983 flags = SDL_PublicSurface->flags & SDL_HWSURFACE; 1011 SDL_RaiseWindow(SDL_WindowID windowID)
984 flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); 1012 {
985 converted = SDL_ConvertSurface(surface, format, flags); 1013 SDL_Window *window = SDL_GetWindowFromID(windowID);
986 SDL_FreeFormat(format); 1014
987 return(converted); 1015 if (!window) {
988 } 1016 return;
989 1017 }
990 /* 1018
991 * Update a specific portion of the physical screen 1019 if (_this->RaiseWindow) {
992 */ 1020 _this->RaiseWindow(_this, window);
993 void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) 1021 }
994 { 1022 }
995 if ( screen ) { 1023
996 SDL_Rect rect; 1024 void
997 1025 SDL_MaximizeWindow(SDL_WindowID windowID)
998 /* Perform some checking */ 1026 {
999 if ( w == 0 ) 1027 SDL_Window *window = SDL_GetWindowFromID(windowID);
1000 w = screen->w; 1028
1001 if ( h == 0 ) 1029 if (!window || (window->flags & SDL_WINDOW_MAXIMIZED)) {
1002 h = screen->h; 1030 return;
1003 if ( (int)(x+w) > screen->w ) 1031 }
1004 return; 1032
1005 if ( (int)(y+h) > screen->h ) 1033 SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
1006 return; 1034
1007 1035 if (_this->MaximizeWindow) {
1008 /* Fill the rectangle */ 1036 _this->MaximizeWindow(_this, window);
1009 rect.x = (Sint16)x; 1037 }
1010 rect.y = (Sint16)y; 1038 }
1011 rect.w = (Uint16)w; 1039
1012 rect.h = (Uint16)h; 1040 void
1013 SDL_UpdateRects(screen, 1, &rect); 1041 SDL_MinimizeWindow(SDL_WindowID windowID)
1014 } 1042 {
1015 } 1043 SDL_Window *window = SDL_GetWindowFromID(windowID);
1016 void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects) 1044
1017 { 1045 if (!window || (window->flags & SDL_WINDOW_MINIMIZED)) {
1018 int i; 1046 return;
1019 SDL_VideoDevice *video = current_video; 1047 }
1020 SDL_VideoDevice *this = current_video; 1048
1021 1049 SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
1022 if ( (screen->flags & (SDL_OPENGL | SDL_OPENGLBLIT)) == SDL_OPENGL ) { 1050
1023 SDL_SetError("OpenGL active, use SDL_GL_SwapBuffers()"); 1051 if (_this->MinimizeWindow) {
1024 return; 1052 _this->MinimizeWindow(_this, window);
1025 } 1053 }
1026 if ( screen == SDL_ShadowSurface ) { 1054 }
1027 /* Blit the shadow surface using saved mapping */ 1055
1028 SDL_Palette *pal = screen->format->palette; 1056 void
1029 SDL_Color *saved_colors = NULL; 1057 SDL_RestoreWindow(SDL_WindowID windowID)
1030 if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) { 1058 {
1031 /* simulated 8bpp, use correct physical palette */ 1059 SDL_Window *window = SDL_GetWindowFromID(windowID);
1032 saved_colors = pal->colors; 1060
1033 if ( video->gammacols ) { 1061 if (!window
1034 /* gamma-corrected palette */ 1062 || (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
1035 pal->colors = video->gammacols; 1063 return;
1036 } else if ( video->physpal ) { 1064 }
1037 /* physical palette different from logical */ 1065
1038 pal->colors = video->physpal->colors; 1066 SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0);
1039 } 1067
1040 } 1068 if (_this->RestoreWindow) {
1041 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { 1069 _this->RestoreWindow(_this, window);
1042 SDL_LockCursor(); 1070 }
1043 SDL_DrawCursor(SDL_ShadowSurface); 1071 }
1044 for ( i=0; i<numrects; ++i ) { 1072
1045 SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 1073 int
1046 SDL_VideoSurface, &rects[i]); 1074 SDL_SetWindowFullscreen(SDL_WindowID windowID, int fullscreen)
1047 } 1075 {
1048 SDL_EraseCursor(SDL_ShadowSurface); 1076 SDL_Window *window = SDL_GetWindowFromID(windowID);
1049 SDL_UnlockCursor(); 1077
1050 } else { 1078 if (!window) {
1051 for ( i=0; i<numrects; ++i ) { 1079 return -1;
1052 SDL_LowerBlit(SDL_ShadowSurface, &rects[i], 1080 }
1053 SDL_VideoSurface, &rects[i]); 1081
1054 } 1082 if (fullscreen) {
1055 } 1083 fullscreen = SDL_WINDOW_FULLSCREEN;
1056 if ( saved_colors ) { 1084 }
1057 pal->colors = saved_colors; 1085 if ((window->flags & SDL_WINDOW_FULLSCREEN) == fullscreen) {
1058 } 1086 return 0;
1059 1087 }
1060 /* Fall through to video surface update */ 1088
1061 screen = SDL_VideoSurface; 1089 if (fullscreen) {
1062 } 1090 window->flags |= SDL_WINDOW_FULLSCREEN;
1063 if ( screen == SDL_VideoSurface ) { 1091
1064 /* Update the video surface */ 1092 if (FULLSCREEN_VISIBLE(window)) {
1065 if ( screen->offset ) { 1093 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
1066 for ( i=0; i<numrects; ++i ) { 1094
1067 rects[i].x += video->offset_x; 1095 /* Hide any other fullscreen windows */
1068 rects[i].y += video->offset_y; 1096 int i;
1069 } 1097 for (i = 0; i < display->num_windows; ++i) {
1070 video->UpdateRects(this, numrects, rects); 1098 SDL_Window *other = &display->windows[i];
1071 for ( i=0; i<numrects; ++i ) { 1099 if (other->id != windowID && FULLSCREEN_VISIBLE(other)) {
1072 rects[i].x -= video->offset_x; 1100 SDL_MinimizeWindow(other->id);
1073 rects[i].y -= video->offset_y; 1101 }
1074 } 1102 }
1075 } else { 1103
1076 video->UpdateRects(this, numrects, rects); 1104 SDL_SetDisplayMode(display->fullscreen_mode);
1077 } 1105 }
1078 } 1106 } else {
1079 } 1107 window->flags &= ~SDL_WINDOW_FULLSCREEN;
1080 1108
1081 /* 1109 if (FULLSCREEN_VISIBLE(window)) {
1082 * Performs hardware double buffering, if possible, or a full update if not. 1110 SDL_SetDisplayMode(NULL);
1083 */ 1111 }
1084 int SDL_Flip(SDL_Surface *screen) 1112 }
1085 { 1113 return 0;
1086 SDL_VideoDevice *video = current_video; 1114 }
1087 /* Copy the shadow surface to the video surface */ 1115
1088 if ( screen == SDL_ShadowSurface ) { 1116 void
1089 SDL_Rect rect; 1117 SDL_SetWindowGrab(SDL_WindowID windowID, int mode)
1090 SDL_Palette *pal = screen->format->palette; 1118 {
1091 SDL_Color *saved_colors = NULL; 1119 SDL_Window *window = SDL_GetWindowFromID(windowID);
1092 if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) { 1120
1093 /* simulated 8bpp, use correct physical palette */ 1121 if (!window || (!!mode == !!(window->flags & SDL_WINDOW_INPUT_GRABBED))) {
1094 saved_colors = pal->colors; 1122 return;
1095 if ( video->gammacols ) { 1123 }
1096 /* gamma-corrected palette */ 1124
1097 pal->colors = video->gammacols; 1125 if (mode) {
1098 } else if ( video->physpal ) { 1126 window->flags |= SDL_WINDOW_INPUT_GRABBED;
1099 /* physical palette different from logical */ 1127 } else {
1100 pal->colors = video->physpal->colors; 1128 window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
1101 } 1129 }
1102 } 1130
1103 1131 if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
1104 rect.x = 0; 1132 _this->SetWindowGrab(_this, window);
1105 rect.y = 0; 1133 }
1106 rect.w = screen->w; 1134 }
1107 rect.h = screen->h; 1135
1108 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { 1136 int
1109 SDL_LockCursor(); 1137 SDL_GetWindowGrab(SDL_WindowID windowID)
1110 SDL_DrawCursor(SDL_ShadowSurface); 1138 {
1111 SDL_LowerBlit(SDL_ShadowSurface, &rect, 1139 SDL_Window *window = SDL_GetWindowFromID(windowID);
1112 SDL_VideoSurface, &rect); 1140
1113 SDL_EraseCursor(SDL_ShadowSurface); 1141 if (!window) {
1114 SDL_UnlockCursor(); 1142 return 0;
1115 } else { 1143 }
1116 SDL_LowerBlit(SDL_ShadowSurface, &rect, 1144
1117 SDL_VideoSurface, &rect); 1145 return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
1118 } 1146 }
1119 if ( saved_colors ) { 1147
1120 pal->colors = saved_colors; 1148 void
1121 } 1149 SDL_OnWindowShown(SDL_Window * window)
1122 1150 {
1123 /* Fall through to video surface update */ 1151 }
1124 screen = SDL_VideoSurface; 1152
1125 } 1153 void
1126 if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { 1154 SDL_OnWindowHidden(SDL_Window * window)
1127 SDL_VideoDevice *this = current_video; 1155 {
1128 return(video->FlipHWSurface(this, SDL_VideoSurface)); 1156 }
1129 } else { 1157
1130 SDL_UpdateRect(screen, 0, 0, 0, 0); 1158 void
1131 } 1159 SDL_OnWindowFocusGained(SDL_Window * window)
1132 return(0); 1160 {
1133 } 1161 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
1134 1162
1135 static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors, 1163 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1136 int firstcolor, int ncolors) 1164 SDL_SetDisplayMode(display->fullscreen_mode);
1137 { 1165 }
1138 SDL_Palette *pal = screen->format->palette; 1166 if (display->gamma && _this->SetDisplayGammaRamp) {
1139 SDL_Palette *vidpal; 1167 _this->SetDisplayGammaRamp(_this, display->gamma);
1140 1168 }
1141 if ( colors != (pal->colors + firstcolor) ) { 1169 if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) {
1142 SDL_memcpy(pal->colors + firstcolor, colors, 1170 _this->SetWindowGrab(_this, window);
1143 ncolors * sizeof(*colors)); 1171 }
1144 } 1172 }
1145 1173
1146 vidpal = SDL_VideoSurface->format->palette; 1174 void
1147 if ( (screen == SDL_ShadowSurface) && vidpal ) { 1175 SDL_OnWindowFocusLost(SDL_Window * window)
1148 /* 1176 {
1149 * This is a shadow surface, and the physical 1177 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
1150 * framebuffer is also indexed. Propagate the 1178
1151 * changes to its logical palette so that 1179 if (window->flags & SDL_WINDOW_FULLSCREEN) {
1152 * updates are always identity blits 1180 SDL_MinimizeWindow(window->id);
1153 */ 1181 SDL_SetDisplayMode(NULL);
1154 SDL_memcpy(vidpal->colors + firstcolor, colors, 1182 }
1155 ncolors * sizeof(*colors)); 1183 if (display->gamma && _this->SetDisplayGammaRamp) {
1156 } 1184 _this->SetDisplayGammaRamp(_this, display->saved_gamma);
1157 SDL_FormatChanged(screen); 1185 }
1158 } 1186 if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) {
1159 1187 _this->SetWindowGrab(_this, window);
1160 static int SetPalette_physical(SDL_Surface *screen, 1188 }
1161 SDL_Color *colors, int firstcolor, int ncolors) 1189 }
1162 { 1190
1163 SDL_VideoDevice *video = current_video; 1191 SDL_WindowID
1164 int gotall = 1; 1192 SDL_GetFocusWindow(void)
1165 1193 {
1166 if ( video->physpal ) { 1194 SDL_VideoDisplay *display;
1167 /* We need to copy the new colors, since we haven't 1195 int i;
1168 * already done the copy in the logical set above. 1196
1169 */ 1197 if (!_this) {
1170 SDL_memcpy(video->physpal->colors + firstcolor, 1198 return 0;
1171 colors, ncolors * sizeof(*colors)); 1199 }
1172 } 1200
1173 if ( screen == SDL_ShadowSurface ) { 1201 display = &SDL_CurrentDisplay;
1174 if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) { 1202 for (i = 0; i < display->num_windows; ++i) {
1175 /* 1203 SDL_Window *window = &display->windows[i];
1176 * The real screen is also indexed - set its physical 1204
1177 * palette. The physical palette does not include the 1205 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
1178 * gamma modification, we apply it directly instead, 1206 return window->id;
1179 * but this only happens if we have hardware palette. 1207 }
1180 */ 1208 }
1181 screen = SDL_VideoSurface; 1209 return 0;
1182 } else { 1210 }
1183 /* 1211
1184 * The video surface is not indexed - invalidate any 1212 void
1185 * active shadow-to-video blit mappings. 1213 SDL_DestroyWindow(SDL_WindowID windowID)
1186 */ 1214 {
1187 if ( screen->map->dst == SDL_VideoSurface ) { 1215 int i, j;
1188 SDL_InvalidateMap(screen->map); 1216
1189 } 1217 if (!_this) {
1190 if ( video->gamma ) { 1218 return;
1191 if( ! video->gammacols ) { 1219 }
1192 SDL_Palette *pp = video->physpal; 1220
1193 if(!pp) 1221 /* Restore video mode, etc. */
1194 pp = screen->format->palette; 1222 SDL_SendWindowEvent(windowID, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
1195 video->gammacols = SDL_malloc(pp->ncolors 1223
1196 * sizeof(SDL_Color)); 1224 for (i = 0; i < _this->num_displays; ++i) {
1197 SDL_ApplyGamma(video->gamma, 1225 SDL_VideoDisplay *display = &_this->displays[i];
1198 pp->colors, 1226 for (j = 0; j < display->num_windows; ++j) {
1199 video->gammacols, 1227 SDL_Window *window = &display->windows[j];
1200 pp->ncolors); 1228 if (window->id != windowID) {
1201 } else { 1229 continue;
1202 SDL_ApplyGamma(video->gamma, colors, 1230 }
1203 video->gammacols 1231 if (window->renderer) {
1204 + firstcolor, 1232 SDL_DestroyRenderer(window->id);
1205 ncolors); 1233 }
1206 } 1234 if (_this->DestroyWindow) {
1207 } 1235 _this->DestroyWindow(_this, window);
1208 SDL_UpdateRect(screen, 0, 0, 0, 0); 1236 }
1209 } 1237 if (window->title) {
1210 } 1238 SDL_free(window->title);
1211 1239 }
1212 if ( screen == SDL_VideoSurface ) { 1240 if (j != display->num_windows - 1) {
1213 SDL_Color gcolors[256]; 1241 SDL_memcpy(&display->windows[i],
1214 1242 &display->windows[i + 1],
1215 if ( video->gamma ) { 1243 (display->num_windows - i - 1) * sizeof(*window));
1216 SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors); 1244 }
1217 colors = gcolors; 1245 --display->num_windows;
1218 } 1246 return;
1219 gotall = video->SetColors(video, firstcolor, ncolors, colors); 1247 }
1220 if ( ! gotall ) { 1248 }
1221 /* The video flags shouldn't have SDL_HWPALETTE, and 1249 }
1222 the video driver is responsible for copying back the 1250
1223 correct colors into the video surface palette. 1251 void
1224 */ 1252 SDL_AddRenderDriver(int displayIndex, const SDL_RenderDriver * driver)
1225 ; 1253 {
1226 } 1254 SDL_VideoDisplay *display = &_this->displays[displayIndex];
1227 SDL_CursorPaletteChanged(); 1255 SDL_RenderDriver *render_drivers;
1228 } 1256
1229 return gotall; 1257 render_drivers =
1230 } 1258 SDL_realloc(display->render_drivers,
1231 1259 (display->num_render_drivers +
1232 /* 1260 1) * sizeof(*render_drivers));
1233 * Set the physical and/or logical colormap of a surface: 1261 if (render_drivers) {
1234 * Only the screen has a physical colormap. It determines what is actually 1262 render_drivers[display->num_render_drivers] = *driver;
1235 * sent to the display. 1263 display->render_drivers = render_drivers;
1236 * The logical colormap is used to map blits to/from the surface. 1264 display->num_render_drivers++;
1237 * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL 1265 }
1238 * 1266 }
1239 * Return nonzero if all colours were set as requested, or 0 otherwise. 1267
1240 */ 1268 int
1241 int SDL_SetPalette(SDL_Surface *screen, int which, 1269 SDL_GetNumRenderers(void)
1242 SDL_Color *colors, int firstcolor, int ncolors) 1270 {
1243 { 1271 if (_this) {
1244 SDL_Palette *pal; 1272 return SDL_CurrentDisplay.num_render_drivers;
1245 int gotall; 1273 }
1246 int palsize; 1274 return 0;
1247 1275 }
1248 if ( ! current_video ) { 1276
1249 return 0; 1277 int
1250 } 1278 SDL_GetRendererInfo(int index, SDL_RendererInfo * info)
1251 if ( screen != SDL_PublicSurface ) { 1279 {
1252 /* only screens have physical palettes */ 1280 if (index < 0 || index >= SDL_GetNumRenderers()) {
1253 which &= ~SDL_PHYSPAL; 1281 SDL_SetError("index must be in the range of 0 - %d",
1254 } else if( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) { 1282 SDL_GetNumRenderers() - 1);
1255 /* hardware palettes required for split colormaps */ 1283 return -1;
1256 which |= SDL_PHYSPAL | SDL_LOGPAL; 1284 }
1257 } 1285 *info = SDL_CurrentDisplay.render_drivers[index].info;
1258 1286 return 0;
1259 /* Verify the parameters */ 1287 }
1260 pal = screen->format->palette; 1288
1261 if( !pal ) { 1289 int
1262 return 0; /* not a palettized surface */ 1290 SDL_CreateRenderer(SDL_WindowID windowID, int index, Uint32 flags)
1263 } 1291 {
1264 gotall = 1; 1292 SDL_Window *window = SDL_GetWindowFromID(windowID);
1265 palsize = 1 << screen->format->BitsPerPixel; 1293
1266 if ( ncolors > (palsize - firstcolor) ) { 1294 if (!window) {
1267 ncolors = (palsize - firstcolor); 1295 return 0;
1268 gotall = 0; 1296 }
1269 } 1297
1270 1298 if (index < 0) {
1271 if ( which & SDL_LOGPAL ) { 1299 int n = SDL_GetNumRenderers();
1272 /* 1300 for (index = 0; index < n; ++index) {
1273 * Logical palette change: The actual screen isn't affected, 1301 SDL_RenderDriver *driver =
1274 * but the internal colormap is altered so that the 1302 &SDL_CurrentDisplay.render_drivers[index];
1275 * interpretation of the pixel values (for blits etc) is 1303
1276 * changed. 1304 /* Skip minimal drivers in automatic scans */
1277 */ 1305 if (!(flags & SDL_Renderer_Minimal)
1278 SetPalette_logical(screen, colors, firstcolor, ncolors); 1306 && (driver->info.flags & SDL_Renderer_Minimal)) {
1279 } 1307 continue;
1280 if ( which & SDL_PHYSPAL ) { 1308 }
1281 SDL_VideoDevice *video = current_video; 1309 if ((driver->info.flags & flags) == flags) {
1282 /* 1310 break;
1283 * Physical palette change: This doesn't affect the 1311 }
1284 * program's idea of what the screen looks like, but changes 1312 }
1285 * its actual appearance. 1313 if (index == n) {
1286 */ 1314 SDL_SetError("Couldn't find matching render driver");
1287 if(!video) 1315 return -1;
1288 return gotall; /* video not yet initialized */ 1316 }
1289 if(!video->physpal && !(which & SDL_LOGPAL) ) { 1317 }
1290 /* Lazy physical palette allocation */ 1318
1291 int size; 1319 if (index >= SDL_GetNumRenderers()) {
1292 SDL_Palette *pp = SDL_malloc(sizeof(*pp)); 1320 SDL_SetError("index must be -1 or in the range of 0 - %d",
1293 if ( !pp ) { 1321 SDL_GetNumRenderers() - 1);
1294 return 0; 1322 return -1;
1295 } 1323 }
1296 current_video->physpal = pp; 1324
1297 pp->ncolors = pal->ncolors; 1325 /* Free any existing renderer */
1298 size = pp->ncolors * sizeof(SDL_Color); 1326 SDL_DestroyRenderer(windowID);
1299 pp->colors = SDL_malloc(size); 1327
1300 if ( !pp->colors ) { 1328 /* Create a new renderer instance */
1301 return 0; 1329 window->renderer =
1302 } 1330 SDL_CurrentDisplay.render_drivers[index].CreateRenderer(window,
1303 SDL_memcpy(pp->colors, pal->colors, size); 1331 flags);
1304 } 1332 if (!window->renderer) {
1305 if ( ! SetPalette_physical(screen, 1333 return -1;
1306 colors, firstcolor, ncolors) ) { 1334 }
1307 gotall = 0; 1335 SDL_CurrentDisplay.current_renderer = window->renderer;
1308 } 1336
1309 } 1337 return 0;
1310 return gotall; 1338 }
1311 } 1339
1312 1340 int
1313 int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor, 1341 SDL_SelectRenderer(SDL_WindowID windowID)
1314 int ncolors) 1342 {
1315 { 1343 SDL_Window *window = SDL_GetWindowFromID(windowID);
1316 return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, 1344
1317 colors, firstcolor, ncolors); 1345 if (!window || !window->renderer) {
1318 } 1346 return -1;
1319 1347 }
1320 /* 1348 SDL_CurrentDisplay.current_renderer = window->renderer;
1321 * Clean up the video subsystem 1349 return 0;
1322 */ 1350 }
1323 void SDL_VideoQuit (void) 1351
1324 { 1352 SDL_TextureID
1325 SDL_Surface *ready_to_go; 1353 SDL_CreateTexture(Uint32 format, int access, int w, int h)
1326 1354 {
1327 if ( current_video ) { 1355 int hash;
1328 SDL_VideoDevice *video = current_video; 1356 SDL_Renderer *renderer;
1329 SDL_VideoDevice *this = current_video; 1357 SDL_Texture *texture;
1330 1358
1331 /* Halt event processing before doing anything else */ 1359 if (!_this) {
1332 SDL_StopEventLoop(); 1360 return 0;
1333 1361 }
1334 /* Clean up allocated window manager items */ 1362
1335 if ( SDL_PublicSurface ) { 1363 renderer = SDL_CurrentDisplay.current_renderer;
1336 SDL_PublicSurface = NULL; 1364 if (!renderer || !renderer->CreateTexture) {
1337 } 1365 return 0;
1338 SDL_CursorQuit(); 1366 }
1339 1367
1340 /* Just in case... */ 1368 texture = (SDL_Texture *) SDL_malloc(sizeof(*texture));
1341 SDL_WM_GrabInputOff(); 1369 if (!texture) {
1342 1370 SDL_OutOfMemory();
1343 /* Clean up the system video */ 1371 return 0;
1344 video->VideoQuit(this); 1372 }
1345 1373
1346 /* Free any lingering surfaces */ 1374 SDL_zerop(texture);
1347 ready_to_go = SDL_ShadowSurface; 1375 texture->id = _this->next_object_id++;
1348 SDL_ShadowSurface = NULL; 1376 texture->format = format;
1349 SDL_FreeSurface(ready_to_go); 1377 texture->access = access;
1350 if ( SDL_VideoSurface != NULL ) { 1378 texture->w = w;
1351 ready_to_go = SDL_VideoSurface; 1379 texture->h = h;
1352 SDL_VideoSurface = NULL; 1380 texture->renderer = renderer;
1353 SDL_FreeSurface(ready_to_go); 1381
1354 } 1382 if (renderer->CreateTexture(renderer, texture) < 0) {
1355 SDL_PublicSurface = NULL; 1383 SDL_free(texture);
1356 1384 return 0;
1357 /* Clean up miscellaneous memory */ 1385 }
1358 if ( video->physpal ) { 1386
1359 SDL_free(video->physpal->colors); 1387 hash = (texture->id % SDL_arraysize(SDL_CurrentDisplay.textures));
1360 SDL_free(video->physpal); 1388 texture->next = SDL_CurrentDisplay.textures[hash];
1361 video->physpal = NULL; 1389 SDL_CurrentDisplay.textures[hash] = texture;
1362 } 1390
1363 if ( video->gammacols ) { 1391 return texture->id;
1364 SDL_free(video->gammacols); 1392 }
1365 video->gammacols = NULL; 1393
1366 } 1394 SDL_TextureID
1367 if ( video->gamma ) { 1395 SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface)
1368 SDL_free(video->gamma); 1396 {
1369 video->gamma = NULL; 1397 SDL_TextureID textureID;
1370 } 1398 Uint32 surface_flags = surface->flags;
1371 if ( video->wm_title != NULL ) { 1399 SDL_PixelFormat *fmt = surface->format;
1372 SDL_free(video->wm_title); 1400 Uint8 alpha;
1373 video->wm_title = NULL; 1401 SDL_Rect bounds;
1374 } 1402 SDL_Surface dst;
1375 if ( video->wm_icon != NULL ) { 1403 int bpp;
1376 SDL_free(video->wm_icon); 1404 Uint32 Rmask, Gmask, Bmask, Amask;
1377 video->wm_icon = NULL; 1405
1378 } 1406 if (!surface) {
1379 1407 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
1380 /* Finish cleaning up video subsystem */ 1408 return 0;
1381 video->free(this); 1409 }
1382 current_video = NULL; 1410
1383 } 1411 if (format) {
1384 return; 1412 if (!SDL_PixelFormatEnumToMasks
1413 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
1414 SDL_SetError("Unknown pixel format");
1415 return 0;
1416 }
1417 } else {
1418 if (fmt->Amask || !(surface_flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA))) {
1419 bpp = fmt->BitsPerPixel;
1420 Rmask = fmt->Rmask;
1421 Gmask = fmt->Gmask;
1422 Bmask = fmt->Bmask;
1423 Amask = fmt->Amask;
1424 } else {
1425 /* Need a format with alpha */
1426 bpp = 32;
1427 Rmask = 0x00FF0000;
1428 Gmask = 0x0000FF00;
1429 Bmask = 0x000000FF;
1430 Amask = 0xFF000000;
1431 }
1432 format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
1433 if (!format) {
1434 SDL_SetError("Unknown pixel format");
1435 return 0;
1436 }
1437 }
1438
1439 textureID = SDL_CreateTexture(format, access, surface->w, surface->h);
1440 if (!textureID) {
1441 return 0;
1442 }
1443
1444 /* Set up a destination surface for the texture update */
1445 SDL_zero(dst);
1446 dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
1447 if (!dst.format) {
1448 SDL_DestroyTexture(textureID);
1449 return 0;
1450 }
1451 dst.w = surface->w;
1452 dst.h = surface->h;
1453 if (SDL_LockTexture(textureID, NULL, 1, &dst.pixels, &dst.pitch) == 0) {
1454 dst.flags |= SDL_PREALLOC;
1455 } else {
1456 dst.pitch = SDL_CalculatePitch(&dst);
1457 dst.pixels = SDL_malloc(dst.h * dst.pitch);
1458 if (!dst.pixels) {
1459 SDL_DestroyTexture(textureID);
1460 SDL_FreeFormat(dst.format);
1461 SDL_OutOfMemory();
1462 return 0;
1463 }
1464 }
1465
1466 /* Copy the palette if any */
1467 if (SDL_ISPIXELFORMAT_INDEXED(format)) {
1468 if (fmt->palette) {
1469 SDL_SetTexturePalette(textureID, fmt->palette->colors, 0,
1470 fmt->palette->ncolors);
1471 SDL_SetSurfacePalette(&dst, fmt->palette);
1472 } else {
1473 dst.format->palette =
1474 SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format)));
1475 if (!dst.format->palette) {
1476 SDL_DestroyTexture(textureID);
1477 SDL_FreeFormat(dst.format);
1478 return 0;
1479 }
1480 SDL_DitherColors(dst.format->palette->colors,
1481 SDL_BITSPERPIXEL(format));
1482 }
1483 }
1484
1485 /* Make the texture transparent if the surface has colorkey */
1486 if (surface_flags & SDL_SRCCOLORKEY) {
1487 int row;
1488 int length = dst.w * dst.format->BytesPerPixel;
1489 Uint8 *p = (Uint8 *) dst.pixels;
1490 for (row = 0; row < dst.h; ++row) {
1491 SDL_memset(p, 0, length);
1492 p += dst.pitch;
1493 }
1494 }
1495
1496 /* Copy over the alpha channel */
1497 if (surface_flags & SDL_SRCALPHA) {
1498 if (fmt->Amask) {
1499 surface->flags &= ~SDL_SRCALPHA;
1500 } else {
1501 /* FIXME: Need to make sure the texture has an alpha channel
1502 * and copy 'alpha' into the texture alpha channel.
1503 */
1504 alpha = surface->format->alpha;
1505 SDL_SetAlpha(surface, 0, 0);
1506 }
1507 }
1508
1509 /* Copy over the image data */
1510 bounds.x = 0;
1511 bounds.y = 0;
1512 bounds.w = surface->w;
1513 bounds.h = surface->h;
1514 SDL_LowerBlit(surface, &bounds, &dst, &bounds);
1515
1516 /* Clean up the original surface */
1517 if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
1518 Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
1519 if (fmt->Amask) {
1520 surface->flags |= SDL_SRCALPHA;
1521 } else {
1522 SDL_SetAlpha(surface, aflags, alpha);
1523 }
1524 }
1525
1526 /* Update the texture */
1527 if (dst.flags & SDL_PREALLOC) {
1528 SDL_UnlockTexture(textureID);
1529 } else {
1530 SDL_UpdateTexture(textureID, NULL, dst.pixels, dst.pitch);
1531 SDL_free(dst.pixels);
1532 }
1533 SDL_FreeFormat(dst.format);
1534
1535 return textureID;
1536 }
1537
1538 static __inline__ SDL_Texture *
1539 SDL_GetTextureFromID(SDL_TextureID textureID)
1540 {
1541 int hash;
1542 SDL_Texture *texture;
1543
1544 if (!_this) {
1545 return NULL;
1546 }
1547
1548 hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures));
1549 for (texture = SDL_CurrentDisplay.textures[hash]; texture;
1550 texture = texture->next) {
1551 if (texture->id == textureID) {
1552 return texture;
1553 }
1554 }
1555 return NULL;
1556 }
1557
1558 int
1559 SDL_QueryTexture(SDL_TextureID textureID, Uint32 * format, int *access,
1560 int *w, int *h)
1561 {
1562 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1563
1564 if (!texture) {
1565 return -1;
1566 }
1567
1568 if (format) {
1569 *format = texture->format;
1570 }
1571 if (access) {
1572 *access = texture->access;
1573 }
1574 if (w) {
1575 *w = texture->w;
1576 }
1577 if (h) {
1578 *h = texture->h;
1579 }
1580 return 0;
1581 }
1582
1583 int
1584 SDL_QueryTexturePixels(SDL_TextureID textureID, void **pixels, int *pitch)
1585 {
1586 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1587 SDL_Renderer *renderer;
1588
1589 if (!texture) {
1590 return -1;
1591 }
1592
1593 renderer = texture->renderer;
1594 if (!renderer->QueryTexturePixels) {
1595 return -1;
1596 }
1597 return renderer->QueryTexturePixels(renderer, texture, pixels, pitch);
1598 }
1599
1600 int
1601 SDL_SetTexturePalette(SDL_TextureID textureID, const SDL_Color * colors,
1602 int firstcolor, int ncolors)
1603 {
1604 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1605 SDL_Renderer *renderer;
1606
1607 if (!texture) {
1608 return -1;
1609 }
1610
1611 renderer = texture->renderer;
1612 if (!renderer->SetTexturePalette) {
1613 return -1;
1614 }
1615 return renderer->SetTexturePalette(renderer, texture, colors, firstcolor,
1616 ncolors);
1617 }
1618
1619 int
1620 SDL_GetTexturePalette(SDL_TextureID textureID, SDL_Color * colors,
1621 int firstcolor, int ncolors)
1622 {
1623 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1624 SDL_Renderer *renderer;
1625
1626 if (!texture) {
1627 return -1;
1628 }
1629
1630 renderer = texture->renderer;
1631 if (!renderer->GetTexturePalette) {
1632 return -1;
1633 }
1634 return renderer->GetTexturePalette(renderer, texture, colors, firstcolor,
1635 ncolors);
1636 }
1637
1638 int
1639 SDL_UpdateTexture(SDL_TextureID textureID, const SDL_Rect * rect,
1640 const void *pixels, int pitch)
1641 {
1642 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1643 SDL_Renderer *renderer;
1644 SDL_Rect full_rect;
1645
1646 if (!texture) {
1647 return -1;
1648 }
1649
1650 renderer = texture->renderer;
1651 if (!renderer->UpdateTexture) {
1652 return -1;
1653 }
1654
1655 if (!rect) {
1656 full_rect.x = 0;
1657 full_rect.y = 0;
1658 full_rect.w = texture->w;
1659 full_rect.h = texture->h;
1660 rect = &full_rect;
1661 }
1662
1663 return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
1664 }
1665
1666 int
1667 SDL_LockTexture(SDL_TextureID textureID, const SDL_Rect * rect, int markDirty,
1668 void **pixels, int *pitch)
1669 {
1670 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1671 SDL_Renderer *renderer;
1672 SDL_Rect full_rect;
1673
1674 if (!texture) {
1675 return -1;
1676 }
1677
1678 renderer = texture->renderer;
1679 if (!renderer->LockTexture) {
1680 return -1;
1681 }
1682
1683 if (!rect) {
1684 full_rect.x = 0;
1685 full_rect.y = 0;
1686 full_rect.w = texture->w;
1687 full_rect.h = texture->h;
1688 rect = &full_rect;
1689 }
1690
1691 return renderer->LockTexture(renderer, texture, rect, markDirty, pixels,
1692 pitch);
1693 }
1694
1695 void
1696 SDL_UnlockTexture(SDL_TextureID textureID)
1697 {
1698 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1699 SDL_Renderer *renderer;
1700
1701 if (!texture) {
1702 return;
1703 }
1704
1705 renderer = texture->renderer;
1706 if (!renderer->UnlockTexture) {
1707 return;
1708 }
1709 renderer->UnlockTexture(renderer, texture);
1710 }
1711
1712 void
1713 SDL_DirtyTexture(SDL_TextureID textureID, int numrects,
1714 const SDL_Rect * rects)
1715 {
1716 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1717 SDL_Renderer *renderer;
1718
1719 if (!texture) {
1720 return;
1721 }
1722
1723 renderer = texture->renderer;
1724 if (!renderer->DirtyTexture) {
1725 return;
1726 }
1727 renderer->DirtyTexture(renderer, texture, numrects, rects);
1728 }
1729
1730 void
1731 SDL_SelectRenderTexture(SDL_TextureID textureID)
1732 {
1733 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1734 SDL_Renderer *renderer;
1735
1736 if (!texture || texture->access != SDL_TextureAccess_Render) {
1737 return;
1738 }
1739 renderer = texture->renderer;
1740 if (!renderer->SelectRenderTexture) {
1741 return;
1742 }
1743 renderer->SelectRenderTexture(renderer, texture);
1744 }
1745
1746 int
1747 SDL_RenderFill(const SDL_Rect * rect, Uint32 color)
1748 {
1749 SDL_Renderer *renderer;
1750 SDL_Window *window;
1751 SDL_Rect real_rect;
1752
1753 if (!_this) {
1754 return -1;
1755 }
1756
1757 renderer = SDL_CurrentDisplay.current_renderer;
1758 if (!renderer || !renderer->RenderFill) {
1759 return -1;
1760 }
1761
1762 window = SDL_GetWindowFromID(renderer->window);
1763 real_rect.x = 0;
1764 real_rect.y = 0;
1765 real_rect.w = window->w;
1766 real_rect.h = window->h;
1767 if (rect) {
1768 if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
1769 return 0;
1770 }
1771 }
1772 rect = &real_rect;
1773
1774 return renderer->RenderFill(renderer, rect, color);
1775 }
1776
1777 int
1778 SDL_RenderCopy(SDL_TextureID textureID, const SDL_Rect * srcrect,
1779 const SDL_Rect * dstrect, int blendMode, int scaleMode)
1780 {
1781 SDL_Texture *texture = SDL_GetTextureFromID(textureID);
1782 SDL_Renderer *renderer;
1783 SDL_Window *window;
1784 SDL_Rect real_srcrect;
1785 SDL_Rect real_dstrect;
1786
1787 if (!texture || texture->renderer != SDL_CurrentDisplay.current_renderer) {
1788 return -1;
1789 }
1790
1791 renderer = SDL_CurrentDisplay.current_renderer;
1792 if (!renderer || !renderer->RenderCopy) {
1793 return -1;
1794 }
1795
1796 /* FIXME: implement clipping */
1797 window = SDL_GetWindowFromID(renderer->window);
1798 real_srcrect.x = 0;
1799 real_srcrect.y = 0;
1800 real_srcrect.w = texture->w;
1801 real_srcrect.h = texture->h;
1802 real_dstrect.x = 0;
1803 real_dstrect.y = 0;
1804 real_dstrect.w = window->w;
1805 real_dstrect.h = window->h;
1806 if (!srcrect) {
1807 srcrect = &real_srcrect;
1808 }
1809 if (!dstrect) {
1810 dstrect = &real_dstrect;
1811 }
1812
1813 return renderer->RenderCopy(renderer, texture, srcrect, dstrect,
1814 blendMode, scaleMode);
1815 }
1816
1817 int
1818 SDL_RenderReadPixels(const SDL_Rect * rect, void *pixels, int pitch)
1819 {
1820 SDL_Renderer *renderer;
1821 SDL_Rect full_rect;
1822
1823 if (!_this) {
1824 return -1;
1825 }
1826
1827 renderer = SDL_CurrentDisplay.current_renderer;
1828 if (!renderer || !renderer->RenderReadPixels) {
1829 return -1;
1830 }
1831
1832 if (!rect) {
1833 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
1834 full_rect.x = 0;
1835 full_rect.y = 0;
1836 full_rect.w = window->w;
1837 full_rect.h = window->h;
1838 rect = &full_rect;
1839 }
1840
1841 return renderer->RenderReadPixels(renderer, rect, pixels, pitch);
1842 }
1843
1844 int
1845 SDL_RenderWritePixels(const SDL_Rect * rect, const void *pixels, int pitch)
1846 {
1847 SDL_Renderer *renderer;
1848 SDL_Rect full_rect;
1849
1850 if (!_this) {
1851 return -1;
1852 }
1853
1854 renderer = SDL_CurrentDisplay.current_renderer;
1855 if (!renderer || !renderer->RenderWritePixels) {
1856 return -1;
1857 }
1858
1859 if (!rect) {
1860 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
1861 full_rect.x = 0;
1862 full_rect.y = 0;
1863 full_rect.w = window->w;
1864 full_rect.h = window->h;
1865 rect = &full_rect;
1866 }
1867
1868 return renderer->RenderWritePixels(renderer, rect, pixels, pitch);
1869 }
1870
1871 void
1872 SDL_RenderPresent(void)
1873 {
1874 SDL_Renderer *renderer;
1875
1876 if (!_this) {
1877 return;
1878 }
1879
1880 renderer = SDL_CurrentDisplay.current_renderer;
1881 if (!renderer || !renderer->RenderPresent) {
1882 return;
1883 }
1884
1885 renderer->RenderPresent(renderer);
1886 }
1887
1888 void
1889 SDL_DestroyTexture(SDL_TextureID textureID)
1890 {
1891 int hash;
1892 SDL_Texture *prev, *texture;
1893 SDL_Renderer *renderer;
1894
1895 if (!_this) {
1896 return;
1897 }
1898
1899 /* Look up the texture in the hash table */
1900 hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures));
1901 prev = NULL;
1902 for (texture = SDL_CurrentDisplay.textures[hash]; texture;
1903 prev = texture, texture = texture->next) {
1904 if (texture->id == textureID) {
1905 break;
1906 }
1907 }
1908 if (!texture) {
1909 return;
1910 }
1911
1912 /* Unlink the texture from the list */
1913 if (prev) {
1914 prev->next = texture->next;
1915 } else {
1916 SDL_CurrentDisplay.textures[hash] = texture->next;
1917 }
1918
1919 /* Free the texture */
1920 renderer = texture->renderer;
1921 renderer->DestroyTexture(renderer, texture);
1922 SDL_free(texture);
1923 }
1924
1925 void
1926 SDL_DestroyRenderer(SDL_WindowID windowID)
1927 {
1928 SDL_Window *window = SDL_GetWindowFromID(windowID);
1929 SDL_Renderer *renderer;
1930 int i;
1931
1932 if (!window) {
1933 return;
1934 }
1935
1936 renderer = window->renderer;
1937 if (!renderer) {
1938 return;
1939 }
1940
1941 /* Free existing textures for this renderer */
1942 for (i = 0; i < SDL_arraysize(SDL_CurrentDisplay.textures); ++i) {
1943 SDL_Texture *texture;
1944 SDL_Texture *prev = NULL;
1945 SDL_Texture *next;
1946 for (texture = SDL_CurrentDisplay.textures[i]; texture;
1947 texture = next) {
1948 next = texture->next;
1949 if (texture->renderer == renderer) {
1950 if (prev) {
1951 prev->next = next;
1952 } else {
1953 SDL_CurrentDisplay.textures[i] = next;
1954 }
1955 renderer->DestroyTexture(renderer, texture);
1956 SDL_free(texture);
1957 } else {
1958 prev = texture;
1959 }
1960 }
1961 }
1962
1963 /* Free the renderer instance */
1964 renderer->DestroyRenderer(renderer);
1965
1966 /* Clear references */
1967 window->renderer = NULL;
1968 if (SDL_CurrentDisplay.current_renderer == renderer) {
1969 SDL_CurrentDisplay.current_renderer = NULL;
1970 }
1971 }
1972
1973 void
1974 SDL_VideoQuit(void)
1975 {
1976 int i, j;
1977
1978 if (!_this) {
1979 return;
1980 }
1981
1982 /* Halt event processing before doing anything else */
1983 SDL_StopEventLoop();
1984
1985 /* Clean up the system video */
1986 for (i = _this->num_displays; i--;) {
1987 SDL_VideoDisplay *display = &_this->displays[i];
1988 for (j = display->num_windows; j--;) {
1989 SDL_DestroyWindow(display->windows[i].id);
1990 }
1991 if (display->windows) {
1992 SDL_free(display->windows);
1993 display->windows = NULL;
1994 }
1995 display->num_windows = 0;
1996 }
1997 _this->VideoQuit(_this);
1998
1999 for (i = _this->num_displays; i--;) {
2000 SDL_VideoDisplay *display = &_this->displays[i];
2001 for (j = display->num_display_modes; j--;) {
2002 if (display->display_modes[j].driverdata) {
2003 SDL_free(display->display_modes[j].driverdata);
2004 display->display_modes[j].driverdata = NULL;
2005 }
2006 }
2007 if (display->display_modes) {
2008 SDL_free(display->display_modes);
2009 display->display_modes = NULL;
2010 }
2011 if (display->desktop_mode.driverdata) {
2012 SDL_free(display->desktop_mode.driverdata);
2013 display->desktop_mode.driverdata = NULL;
2014 }
2015 if (display->palette) {
2016 SDL_FreePalette(display->palette);
2017 display->palette = NULL;
2018 }
2019 if (display->gamma) {
2020 SDL_free(display->gamma);
2021 }
2022 if (display->driverdata) {
2023 SDL_free(display->driverdata);
2024 }
2025 }
2026 if (_this->displays) {
2027 SDL_free(_this->displays);
2028 _this->displays = NULL;
2029 }
2030 _this->free(_this);
2031 _this = NULL;
1385 } 2032 }
1386 2033
1387 /* Load the GL driver library */ 2034 /* Load the GL driver library */
1388 int SDL_GL_LoadLibrary(const char *path) 2035 int
1389 { 2036 SDL_GL_LoadLibrary(const char *path)
1390 SDL_VideoDevice *video = current_video; 2037 {
1391 SDL_VideoDevice *this = current_video; 2038 int retval;
1392 int retval; 2039
1393 2040 retval = -1;
1394 retval = -1; 2041 if (_this == NULL) {
1395 if ( video == NULL ) { 2042 SDL_SetError("Video subsystem has not been initialized");
1396 SDL_SetError("Video subsystem has not been initialized"); 2043 } else {
1397 } else { 2044 if (_this->GL_LoadLibrary) {
1398 if ( video->GL_LoadLibrary ) { 2045 retval = _this->GL_LoadLibrary(_this, path);
1399 retval = video->GL_LoadLibrary(this, path); 2046 } else {
1400 } else { 2047 SDL_SetError("No dynamic GL support in video driver");
1401 SDL_SetError("No dynamic GL support in video driver"); 2048 }
1402 } 2049 }
1403 } 2050 return (retval);
1404 return(retval); 2051 }
1405 } 2052
1406 2053 void *
1407 void *SDL_GL_GetProcAddress(const char* proc) 2054 SDL_GL_GetProcAddress(const char *proc)
1408 { 2055 {
1409 SDL_VideoDevice *video = current_video; 2056 void *func;
1410 SDL_VideoDevice *this = current_video; 2057
1411 void *func; 2058 func = NULL;
1412 2059 if (_this->GL_GetProcAddress) {
1413 func = NULL; 2060 if (_this->gl_config.driver_loaded) {
1414 if ( video->GL_GetProcAddress ) { 2061 func = _this->GL_GetProcAddress(_this, proc);
1415 if ( video->gl_config.driver_loaded ) { 2062 } else {
1416 func = video->GL_GetProcAddress(this, proc); 2063 SDL_SetError("No GL driver has been loaded");
1417 } else { 2064 }
1418 SDL_SetError("No GL driver has been loaded"); 2065 } else {
1419 } 2066 SDL_SetError("No dynamic GL support in video driver");
1420 } else { 2067 }
1421 SDL_SetError("No dynamic GL support in video driver"); 2068 return func;
1422 }
1423 return func;
1424 } 2069 }
1425 2070
1426 /* Set the specified GL attribute for setting up a GL video mode */ 2071 /* Set the specified GL attribute for setting up a GL video mode */
1427 int SDL_GL_SetAttribute( SDL_GLattr attr, int value ) 2072 int
1428 { 2073 SDL_GL_SetAttribute(SDL_GLattr attr, int value)
1429 int retval; 2074 {
1430 SDL_VideoDevice *video = current_video; 2075 int retval;
1431 2076
1432 retval = 0; 2077 retval = 0;
1433 switch (attr) { 2078 switch (attr) {
1434 case SDL_GL_RED_SIZE: 2079 case SDL_GL_RED_SIZE:
1435 video->gl_config.red_size = value; 2080 _this->gl_config.red_size = value;
1436 break; 2081 break;
1437 case SDL_GL_GREEN_SIZE: 2082 case SDL_GL_GREEN_SIZE:
1438 video->gl_config.green_size = value; 2083 _this->gl_config.green_size = value;
1439 break; 2084 break;
1440 case SDL_GL_BLUE_SIZE: 2085 case SDL_GL_BLUE_SIZE:
1441 video->gl_config.blue_size = value; 2086 _this->gl_config.blue_size = value;
1442 break; 2087 break;
1443 case SDL_GL_ALPHA_SIZE: 2088 case SDL_GL_ALPHA_SIZE:
1444 video->gl_config.alpha_size = value; 2089 _this->gl_config.alpha_size = value;
1445 break; 2090 break;
1446 case SDL_GL_DOUBLEBUFFER: 2091 case SDL_GL_DOUBLEBUFFER:
1447 video->gl_config.double_buffer = value; 2092 _this->gl_config.double_buffer = value;
1448 break; 2093 break;
1449 case SDL_GL_BUFFER_SIZE: 2094 case SDL_GL_BUFFER_SIZE:
1450 video->gl_config.buffer_size = value; 2095 _this->gl_config.buffer_size = value;
1451 break; 2096 break;
1452 case SDL_GL_DEPTH_SIZE: 2097 case SDL_GL_DEPTH_SIZE:
1453 video->gl_config.depth_size = value; 2098 _this->gl_config.depth_size = value;
1454 break; 2099 break;
1455 case SDL_GL_STENCIL_SIZE: 2100 case SDL_GL_STENCIL_SIZE:
1456 video->gl_config.stencil_size = value; 2101 _this->gl_config.stencil_size = value;
1457 break; 2102 break;
1458 case SDL_GL_ACCUM_RED_SIZE: 2103 case SDL_GL_ACCUM_RED_SIZE:
1459 video->gl_config.accum_red_size = value; 2104 _this->gl_config.accum_red_size = value;
1460 break; 2105 break;
1461 case SDL_GL_ACCUM_GREEN_SIZE: 2106 case SDL_GL_ACCUM_GREEN_SIZE:
1462 video->gl_config.accum_green_size = value; 2107 _this->gl_config.accum_green_size = value;
1463 break; 2108 break;
1464 case SDL_GL_ACCUM_BLUE_SIZE: 2109 case SDL_GL_ACCUM_BLUE_SIZE:
1465 video->gl_config.accum_blue_size = value; 2110 _this->gl_config.accum_blue_size = value;
1466 break; 2111 break;
1467 case SDL_GL_ACCUM_ALPHA_SIZE: 2112 case SDL_GL_ACCUM_ALPHA_SIZE:
1468 video->gl_config.accum_alpha_size = value; 2113 _this->gl_config.accum_alpha_size = value;
1469 break; 2114 break;
1470 case SDL_GL_STEREO: 2115 case SDL_GL_STEREO:
1471 video->gl_config.stereo = value; 2116 _this->gl_config.stereo = value;
1472 break; 2117 break;
1473 case SDL_GL_MULTISAMPLEBUFFERS: 2118 case SDL_GL_MULTISAMPLEBUFFERS:
1474 video->gl_config.multisamplebuffers = value; 2119 _this->gl_config.multisamplebuffers = value;
1475 break; 2120 break;
1476 case SDL_GL_MULTISAMPLESAMPLES: 2121 case SDL_GL_MULTISAMPLESAMPLES:
1477 video->gl_config.multisamplesamples = value; 2122 _this->gl_config.multisamplesamples = value;
1478 break; 2123 break;
1479 case SDL_GL_ACCELERATED_VISUAL: 2124 case SDL_GL_ACCELERATED_VISUAL:
1480 video->gl_config.accelerated = value; 2125 _this->gl_config.accelerated = value;
1481 break; 2126 break;
1482 case SDL_GL_SWAP_CONTROL: 2127 default:
1483 video->gl_config.swap_control = value; 2128 SDL_SetError("Unknown OpenGL attribute");
1484 break; 2129 retval = -1;
1485 default: 2130 break;
1486 SDL_SetError("Unknown OpenGL attribute"); 2131 }
1487 retval = -1; 2132 return (retval);
1488 break;
1489 }
1490 return(retval);
1491 } 2133 }
1492 2134
1493 /* Retrieve an attribute value from the windowing system. */ 2135 /* Retrieve an attribute value from the windowing system. */
1494 int SDL_GL_GetAttribute(SDL_GLattr attr, int* value) 2136 int
1495 { 2137 SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
1496 int retval = -1; 2138 {
1497 SDL_VideoDevice* video = current_video; 2139 int retval = -1;
1498 SDL_VideoDevice* this = current_video; 2140
1499 2141 if (_this->GL_GetAttribute) {
1500 if ( video->GL_GetAttribute ) { 2142 retval = _this->GL_GetAttribute(_this, attr, value);
1501 retval = this->GL_GetAttribute(this, attr, value); 2143 } else {
1502 } else { 2144 *value = 0;
1503 *value = 0; 2145 SDL_SetError("GL_GetAttribute not supported");
1504 SDL_SetError("GL_GetAttribute not supported"); 2146 }
1505 } 2147 return retval;
1506 return retval;
1507 } 2148 }
1508 2149
1509 /* Perform a GL buffer swap on the current GL context */ 2150 /* Perform a GL buffer swap on the current GL context */
1510 void SDL_GL_SwapBuffers(void) 2151 void
1511 { 2152 SDL_GL_SwapBuffers(void)
1512 SDL_VideoDevice *video = current_video; 2153 {
1513 SDL_VideoDevice *this = current_video; 2154 // FIXME: Track the current window context - do we provide N contexts, and match them to M windows, or is there a one-to-one mapping?
1514 2155 _this->GL_SwapBuffers(_this);
1515 if ( video->screen->flags & SDL_OPENGL ) { 2156 }
1516 video->GL_SwapBuffers(this); 2157
1517 } else { 2158 #if 0 // FIXME
1518 SDL_SetError("OpenGL video mode has not been set");
1519 }
1520 }
1521
1522 /* Update rects with locking */
1523 void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
1524 {
1525 SDL_GL_Lock();
1526 SDL_GL_UpdateRects(numrects, rects);
1527 SDL_GL_Unlock();
1528 }
1529
1530 /* Update rects without state setting and changing (the caller is responsible for it) */
1531 void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
1532 {
1533 #if SDL_VIDEO_OPENGL
1534 SDL_VideoDevice *this = current_video;
1535 SDL_Rect update, tmp;
1536 int x, y, i;
1537
1538 for ( i = 0; i < numrects; i++ )
1539 {
1540 tmp.y = rects[i].y;
1541 tmp.h = rects[i].h;
1542 for ( y = 0; y <= rects[i].h / 256; y++ )
1543 {
1544 tmp.x = rects[i].x;
1545 tmp.w = rects[i].w;
1546 for ( x = 0; x <= rects[i].w / 256; x++ )
1547 {
1548 update.x = tmp.x;
1549 update.y = tmp.y;
1550 update.w = tmp.w;
1551 update.h = tmp.h;
1552
1553 if ( update.w > 256 )
1554 update.w = 256;
1555
1556 if ( update.h > 256 )
1557 update.h = 256;
1558
1559 this->glFlush();
1560 this->glTexSubImage2D(
1561 GL_TEXTURE_2D,
1562 0,
1563 0,
1564 0,
1565 update.w,
1566 update.h,
1567 this->is_32bit? GL_RGBA : GL_RGB,
1568 #ifdef GL_VERSION_1_2
1569 this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
1570 #else
1571 GL_UNSIGNED_BYTE,
1572 #endif
1573 (Uint8 *)this->screen->pixels +
1574 this->screen->format->BytesPerPixel * update.x +
1575 update.y * this->screen->pitch );
1576
1577 this->glFlush();
1578 /*
1579 * Note the parens around the function name:
1580 * This is because some OpenGL implementations define glTexCoord etc
1581 * as macros, and we don't want them expanded here.
1582 */
1583 this->glBegin(GL_TRIANGLE_STRIP);
1584 (this->glTexCoord2f)( 0.0, 0.0 );
1585 (this->glVertex2i)( update.x, update.y );
1586 (this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );
1587 (this->glVertex2i)( update.x + update.w, update.y );
1588 (this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
1589 (this->glVertex2i)( update.x, update.y + update.h );
1590 (this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );
1591 (this->glVertex2i)( update.x + update.w , update.y + update.h );
1592 this->glEnd();
1593
1594 tmp.x += 256;
1595 tmp.w -= 256;
1596 }
1597 tmp.y += 256;
1598 tmp.h -= 256;
1599 }
1600 }
1601 #endif
1602 }
1603
1604 /* Lock == save current state */
1605 void SDL_GL_Lock()
1606 {
1607 #if SDL_VIDEO_OPENGL
1608 lock_count--;
1609 if (lock_count==-1)
1610 {
1611 SDL_VideoDevice *this = current_video;
1612
1613 this->glPushAttrib( GL_ALL_ATTRIB_BITS ); /* TODO: narrow range of what is saved */
1614 #ifdef GL_CLIENT_PIXEL_STORE_BIT
1615 this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
1616 #endif
1617
1618 this->glEnable(GL_TEXTURE_2D);
1619 this->glEnable(GL_BLEND);
1620 this->glDisable(GL_FOG);
1621 this->glDisable(GL_ALPHA_TEST);
1622 this->glDisable(GL_DEPTH_TEST);
1623 this->glDisable(GL_SCISSOR_TEST);
1624 this->glDisable(GL_STENCIL_TEST);
1625 this->glDisable(GL_CULL_FACE);
1626
1627 this->glBindTexture( GL_TEXTURE_2D, this->texture );
1628 this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
1629 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1630 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1631 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1632 this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1633
1634 this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
1635 this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1636 (this->glColor4f)(1.0, 1.0, 1.0, 1.0); /* Solaris workaround */
1637
1638 this->glViewport(0, 0, this->screen->w, this->screen->h);
1639 this->glMatrixMode(GL_PROJECTION);
1640 this->glPushMatrix();
1641 this->glLoadIdentity();
1642
1643 this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
1644
1645 this->glMatrixMode(GL_MODELVIEW);
1646 this->glPushMatrix();
1647 this->glLoadIdentity();
1648 }
1649 #endif
1650 }
1651
1652 /* Unlock == restore saved state */
1653 void SDL_GL_Unlock()
1654 {
1655 #if SDL_VIDEO_OPENGL
1656 lock_count++;
1657 if (lock_count==0)
1658 {
1659 SDL_VideoDevice *this = current_video;
1660
1661 this->glPopMatrix();
1662 this->glMatrixMode(GL_PROJECTION);
1663 this->glPopMatrix();
1664
1665 this->glPopClientAttrib();
1666 this->glPopAttrib();
1667 }
1668 #endif
1669 }
1670
1671 /*
1672 * Sets/Gets the title and icon text of the display window, if any.
1673 */
1674 void SDL_WM_SetCaption (const char *title, const char *icon)
1675 {
1676 SDL_VideoDevice *video = current_video;
1677 SDL_VideoDevice *this = current_video;
1678
1679 if ( video ) {
1680 if ( title ) {
1681 if ( video->wm_title ) {
1682 SDL_free(video->wm_title);
1683 }
1684 video->wm_title = SDL_strdup(title);
1685 }
1686 if ( icon ) {
1687 if ( video->wm_icon ) {
1688 SDL_free(video->wm_icon);
1689 }
1690 video->wm_icon = SDL_strdup(icon);
1691 }
1692 if ( (title || icon) && (video->SetCaption != NULL) ) {
1693 video->SetCaption(this, video->wm_title,video->wm_icon);
1694 }
1695 }
1696 }
1697 void SDL_WM_GetCaption (char **title, char **icon)
1698 {
1699 SDL_VideoDevice *video = current_video;
1700
1701 if ( video ) {
1702 if ( title ) {
1703 *title = video->wm_title;
1704 }
1705 if ( icon ) {
1706 *icon = video->wm_icon;
1707 }
1708 }
1709 }
1710
1711 /* Utility function used by SDL_WM_SetIcon(); 2159 /* Utility function used by SDL_WM_SetIcon();
1712 * flags & 1 for color key, flags & 2 for alpha channel. */ 2160 * flags & 1 for color key, flags & 2 for alpha channel. */
1713 static void CreateMaskFromColorKeyOrAlpha(SDL_Surface *icon, Uint8 *mask, int flags) 2161 static void
1714 { 2162 CreateMaskFromColorKeyOrAlpha(SDL_Surface * icon, Uint8 * mask, int flags)
1715 int x, y; 2163 {
1716 Uint32 colorkey; 2164 int x, y;
2165 Uint32 colorkey;
1717 #define SET_MASKBIT(icon, x, y, mask) \ 2166 #define SET_MASKBIT(icon, x, y, mask) \
1718 mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8))) 2167 mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
1719 2168
1720 colorkey = icon->format->colorkey; 2169 colorkey = icon->format->colorkey;
1721 switch (icon->format->BytesPerPixel) { 2170 switch (icon->format->BytesPerPixel) {
1722 case 1: { Uint8 *pixels; 2171 case 1:
1723 for ( y=0; y<icon->h; ++y ) { 2172 {
1724 pixels = (Uint8 *)icon->pixels + y*icon->pitch; 2173 Uint8 *pixels;
1725 for ( x=0; x<icon->w; ++x ) { 2174 for (y = 0; y < icon->h; ++y) {
1726 if ( *pixels++ == colorkey ) { 2175 pixels = (Uint8 *) icon->pixels + y * icon->pitch;
1727 SET_MASKBIT(icon, x, y, mask); 2176 for (x = 0; x < icon->w; ++x) {
1728 } 2177 if (*pixels++ == colorkey) {
1729 } 2178 SET_MASKBIT(icon, x, y, mask);
1730 } 2179 }
1731 } 2180 }
1732 break; 2181 }
1733 2182 }
1734 case 2: { Uint16 *pixels; 2183 break;
1735 for ( y=0; y<icon->h; ++y ) { 2184
1736 pixels = (Uint16 *)icon->pixels + 2185 case 2:
1737 y*icon->pitch/2; 2186 {
1738 for ( x=0; x<icon->w; ++x ) { 2187 Uint16 *pixels;
1739 if ( (flags & 1) && *pixels == colorkey ) { 2188 for (y = 0; y < icon->h; ++y) {
1740 SET_MASKBIT(icon, x, y, mask); 2189 pixels = (Uint16 *) icon->pixels + y * icon->pitch / 2;
1741 } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) { 2190 for (x = 0; x < icon->w; ++x) {
1742 SET_MASKBIT(icon, x, y, mask); 2191 if ((flags & 1) && *pixels == colorkey) {
1743 } 2192 SET_MASKBIT(icon, x, y, mask);
1744 pixels++; 2193 } else if ((flags & 2)
1745 } 2194 && (*pixels & icon->format->Amask) == 0) {
1746 } 2195 SET_MASKBIT(icon, x, y, mask);
1747 } 2196 }
1748 break; 2197 pixels++;
1749 2198 }
1750 case 4: { Uint32 *pixels; 2199 }
1751 for ( y=0; y<icon->h; ++y ) { 2200 }
1752 pixels = (Uint32 *)icon->pixels + 2201 break;
1753 y*icon->pitch/4; 2202
1754 for ( x=0; x<icon->w; ++x ) { 2203 case 4:
1755 if ( (flags & 1) && *pixels == colorkey ) { 2204 {
1756 SET_MASKBIT(icon, x, y, mask); 2205 Uint32 *pixels;
1757 } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) { 2206 for (y = 0; y < icon->h; ++y) {
1758 SET_MASKBIT(icon, x, y, mask); 2207 pixels = (Uint32 *) icon->pixels + y * icon->pitch / 4;
1759 } 2208 for (x = 0; x < icon->w; ++x) {
1760 pixels++; 2209 if ((flags & 1) && *pixels == colorkey) {
1761 } 2210 SET_MASKBIT(icon, x, y, mask);
1762 } 2211 } else if ((flags & 2)
1763 } 2212 && (*pixels & icon->format->Amask) == 0) {
1764 break; 2213 SET_MASKBIT(icon, x, y, mask);
1765 } 2214 }
2215 pixels++;
2216 }
2217 }
2218 }
2219 break;
2220 }
1766 } 2221 }
1767 2222
1768 /* 2223 /*
1769 * Sets the window manager icon for the display window. 2224 * Sets the window manager icon for the display window.
1770 */ 2225 */
1771 void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask) 2226 void
1772 { 2227 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
1773 SDL_VideoDevice *video = current_video; 2228 {
1774 SDL_VideoDevice *this = current_video; 2229 if (icon && _this->SetIcon) {
1775 2230 /* Generate a mask if necessary, and create the icon! */
1776 if ( icon && video->SetIcon ) { 2231 if (mask == NULL) {
1777 /* Generate a mask if necessary, and create the icon! */ 2232 int mask_len = icon->h * (icon->w + 7) / 8;
1778 if ( mask == NULL ) { 2233 int flags = 0;
1779 int mask_len = icon->h*(icon->w+7)/8; 2234 mask = (Uint8 *) SDL_malloc(mask_len);
1780 int flags = 0; 2235 if (mask == NULL) {
1781 mask = (Uint8 *)SDL_malloc(mask_len); 2236 return;
1782 if ( mask == NULL ) { 2237 }
1783 return; 2238 SDL_memset(mask, ~0, mask_len);
1784 } 2239 if (icon->flags & SDL_SRCCOLORKEY)
1785 SDL_memset(mask, ~0, mask_len); 2240 flags |= 1;
1786 if ( icon->flags & SDL_SRCCOLORKEY ) flags |= 1; 2241 if (icon->flags & SDL_SRCALPHA)
1787 if ( icon->flags & SDL_SRCALPHA ) flags |= 2; 2242 flags |= 2;
1788 if( flags ) { 2243 if (flags) {
1789 CreateMaskFromColorKeyOrAlpha(icon, mask, flags); 2244 CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
1790 } 2245 }
1791 video->SetIcon(video, icon, mask); 2246 _this->SetIcon(_this, icon, mask);
1792 SDL_free(mask); 2247 SDL_free(mask);
1793 } else { 2248 } else {
1794 video->SetIcon(this, icon, mask); 2249 _this->SetIcon(_this, icon, mask);
1795 } 2250 }
1796 } 2251 }
1797 } 2252 }
1798 2253 #endif
1799 /* 2254
1800 * Grab or ungrab the keyboard and mouse input. 2255 SDL_bool
1801 * This function returns the final grab mode after calling the 2256 SDL_GetWindowWMInfo(SDL_WindowID windowID, struct SDL_SysWMinfo *info)
1802 * driver dependent function. 2257 {
1803 */ 2258 SDL_Window *window = SDL_GetWindowFromID(windowID);
1804 static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode) 2259
1805 { 2260 if (!window || !_this->GetWindowWMInfo) {
1806 SDL_VideoDevice *video = current_video; 2261 return SDL_FALSE;
1807 SDL_VideoDevice *this = current_video; 2262 }
1808 2263 return (_this->GetWindowWMInfo(_this, window, info));
1809 /* Only do something if we have support for grabs */ 2264 }
1810 if ( video->GrabInput == NULL ) { 2265
1811 return(video->input_grab); 2266 /* vi: set ts=4 sw=4 expandtab: */
1812 }
1813
1814 /* If the final grab mode if off, only then do we actually grab */
1815 #ifdef DEBUG_GRAB
1816 printf("SDL_WM_GrabInputRaw(%d) ... ", mode);
1817 #endif
1818 if ( mode == SDL_GRAB_OFF ) {
1819 if ( video->input_grab != SDL_GRAB_OFF ) {
1820 mode = video->GrabInput(this, mode);
1821 }
1822 } else {
1823 if ( video->input_grab == SDL_GRAB_OFF ) {
1824 mode = video->GrabInput(this, mode);
1825 }
1826 }
1827 if ( mode != video->input_grab ) {
1828 video->input_grab = mode;
1829 if ( video->CheckMouseMode ) {
1830 video->CheckMouseMode(this);
1831 }
1832 }
1833 #ifdef DEBUG_GRAB
1834 printf("Final mode %d\n", video->input_grab);
1835 #endif
1836
1837 /* Return the final grab state */
1838 if ( mode >= SDL_GRAB_FULLSCREEN ) {
1839 mode -= SDL_GRAB_FULLSCREEN;
1840 }
1841 return(mode);
1842 }
1843 SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode)
1844 {
1845 SDL_VideoDevice *video = current_video;
1846
1847 /* If the video isn't initialized yet, we can't do anything */
1848 if ( ! video ) {
1849 return SDL_GRAB_OFF;
1850 }
1851
1852 /* Return the current mode on query */
1853 if ( mode == SDL_GRAB_QUERY ) {
1854 mode = video->input_grab;
1855 if ( mode >= SDL_GRAB_FULLSCREEN ) {
1856 mode -= SDL_GRAB_FULLSCREEN;
1857 }
1858 return(mode);
1859 }
1860
1861 #ifdef DEBUG_GRAB
1862 printf("SDL_WM_GrabInput(%d) ... ", mode);
1863 #endif
1864 /* If the video surface is fullscreen, we always grab */
1865 if ( mode >= SDL_GRAB_FULLSCREEN ) {
1866 mode -= SDL_GRAB_FULLSCREEN;
1867 }
1868 if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
1869 mode += SDL_GRAB_FULLSCREEN;
1870 }
1871 return(SDL_WM_GrabInputRaw(mode));
1872 }
1873 static SDL_GrabMode SDL_WM_GrabInputOff(void)
1874 {
1875 SDL_GrabMode mode;
1876
1877 /* First query the current grab state */
1878 mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
1879
1880 /* Now explicitly turn off input grab */
1881 SDL_WM_GrabInputRaw(SDL_GRAB_OFF);
1882
1883 /* Return the old state */
1884 return(mode);
1885 }
1886
1887 /*
1888 * Iconify the window in window managed environments.
1889 * A successful iconification will result in an SDL_APPACTIVE loss event.
1890 */
1891 int SDL_WM_IconifyWindow(void)
1892 {
1893 SDL_VideoDevice *video = current_video;
1894 SDL_VideoDevice *this = current_video;
1895 int retval;
1896
1897 retval = 0;
1898 if ( video->IconifyWindow ) {
1899 retval = video->IconifyWindow(this);
1900 }
1901 return(retval);
1902 }
1903
1904 /*
1905 * Toggle fullscreen mode
1906 */
1907 int SDL_WM_ToggleFullScreen(SDL_Surface *surface)
1908 {
1909 SDL_VideoDevice *video = current_video;
1910 SDL_VideoDevice *this = current_video;
1911 int toggled;
1912
1913 toggled = 0;
1914 if ( SDL_PublicSurface && (surface == SDL_PublicSurface) &&
1915 video->ToggleFullScreen ) {
1916 if ( surface->flags & SDL_FULLSCREEN ) {
1917 toggled = video->ToggleFullScreen(this, 0);
1918 if ( toggled ) {
1919 SDL_VideoSurface->flags &= ~SDL_FULLSCREEN;
1920 SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
1921 }
1922 } else {
1923 toggled = video->ToggleFullScreen(this, 1);
1924 if ( toggled ) {
1925 SDL_VideoSurface->flags |= SDL_FULLSCREEN;
1926 SDL_PublicSurface->flags |= SDL_FULLSCREEN;
1927 }
1928 }
1929 /* Double-check the grab state inside SDL_WM_GrabInput() */
1930 if ( toggled ) {
1931 SDL_WM_GrabInput(video->input_grab);
1932 }
1933 }
1934 return(toggled);
1935 }
1936
1937 /*
1938 * Get some platform dependent window manager information
1939 */
1940 int SDL_GetWMInfo (SDL_SysWMinfo *info)
1941 {
1942 SDL_VideoDevice *video = current_video;
1943 SDL_VideoDevice *this = current_video;
1944
1945 if ( video && video->GetWMInfo ) {
1946 return(video->GetWMInfo(this, info));
1947 } else {
1948 return(0);
1949 }
1950 }