comparison src/SDL_compat.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
children c2a27da60b18
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /* This file contains functions for backwards compatibility with SDL 1.2 */
25
26 #include "SDL.h"
27 #include "SDL_syswm.h"
28
29 #include "video/SDL_sysvideo.h"
30 #include "video/SDL_pixels_c.h"
31
32
33 static SDL_WindowID SDL_VideoWindow;
34 static SDL_TextureID SDL_VideoTexture;
35 static SDL_Surface *SDL_VideoSurface;
36 static SDL_Surface *SDL_ShadowSurface;
37 static SDL_Surface *SDL_PublicSurface;
38 static char *wm_title;
39
40 char *
41 SDL_AudioDriverName(char *namebuf, int maxlen)
42 {
43 const char *name = SDL_GetCurrentAudioDriver();
44 if (name) {
45 SDL_strlcpy(namebuf, name, maxlen);
46 return namebuf;
47 }
48 return NULL;
49 }
50
51 char *
52 SDL_VideoDriverName(char *namebuf, int maxlen)
53 {
54 const char *name = SDL_GetCurrentVideoDriver();
55 if (name) {
56 SDL_strlcpy(namebuf, name, maxlen);
57 return namebuf;
58 }
59 return NULL;
60 }
61
62 const SDL_VideoInfo *
63 SDL_GetVideoInfo(void)
64 {
65 static SDL_VideoInfo info;
66
67 /* Memory leak, compatibility code, who cares? */
68 if (!info.vfmt && SDL_GetDesktopDisplayMode()) {
69 int bpp;
70 Uint32 Rmask, Gmask, Bmask, Amask;
71
72 SDL_PixelFormatEnumToMasks(SDL_GetDesktopDisplayMode()->format, &bpp,
73 &Rmask, &Gmask, &Bmask, &Amask);
74 info.vfmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
75 }
76 return &info;
77 }
78
79 int
80 SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags)
81 {
82 int i, actual_bpp = 0;
83
84 if (!SDL_GetVideoDevice()) {
85 return 0;
86 }
87
88 if (!(flags & SDL_FULLSCREEN)) {
89 return SDL_BITSPERPIXEL(SDL_GetDesktopDisplayMode()->format);
90 }
91
92 for (i = 0; i < SDL_GetNumDisplayModes(); ++i) {
93 const SDL_DisplayMode *mode = SDL_GetDisplayMode(i);
94 if (!mode->w || !mode->h || (width == mode->w && height == mode->h)) {
95 if (!mode->format) {
96 return bpp;
97 }
98 if (SDL_BITSPERPIXEL(mode->format) >= (Uint32) bpp) {
99 actual_bpp = SDL_BITSPERPIXEL(mode->format);
100 }
101 }
102 }
103 return actual_bpp;
104 }
105
106 SDL_Rect **
107 SDL_ListModes(SDL_PixelFormat * format, Uint32 flags)
108 {
109 int i, nmodes;
110 SDL_Rect **modes;
111
112 if (!SDL_GetVideoDevice()) {
113 return NULL;
114 }
115
116 if (!(flags & SDL_FULLSCREEN)) {
117 return (SDL_Rect **) (-1);
118 }
119
120 /* Memory leak, but this is a compatibility function, who cares? */
121 nmodes = 0;
122 modes = NULL;
123 for (i = 0; i < SDL_GetNumDisplayModes(); ++i) {
124 const SDL_DisplayMode *mode = SDL_GetDisplayMode(i);
125 if (!mode->w || !mode->h) {
126 return (SDL_Rect **) (-1);
127 }
128 if (SDL_BITSPERPIXEL(mode->format) != format->BitsPerPixel) {
129 continue;
130 }
131 if (nmodes > 0 && modes[nmodes - 1]->w == mode->w
132 && modes[nmodes - 1]->h == mode->h) {
133 continue;
134 }
135
136 modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
137 if (!modes) {
138 return NULL;
139 }
140 modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
141 if (!modes[nmodes]) {
142 return NULL;
143 }
144 modes[nmodes]->x = 0;
145 modes[nmodes]->y = 0;
146 modes[nmodes]->w = mode->w;
147 modes[nmodes]->h = mode->h;
148 ++nmodes;
149 }
150 if (modes) {
151 modes[nmodes] = NULL;
152 }
153 return modes;
154 }
155
156 static int
157 SDL_CompatEventFilter(void *userdata, SDL_Event * event)
158 {
159 SDL_Event fake;
160
161 switch (event->type) {
162 case SDL_WINDOWEVENT:
163 switch (event->window.event) {
164 case SDL_WINDOWEVENT_EXPOSED:
165 if (!SDL_HasEvent(SDL_VIDEOEXPOSEMASK)) {
166 fake.type = SDL_VIDEOEXPOSE;
167 SDL_PushEvent(&fake);
168 }
169 break;
170 case SDL_WINDOWEVENT_RESIZED:
171 fake.type = SDL_VIDEORESIZE;
172 fake.resize.w = event->window.data1;
173 fake.resize.h = event->window.data2;
174 SDL_PushEvent(&fake);
175 break;
176 case SDL_WINDOWEVENT_MINIMIZED:
177 fake.type = SDL_ACTIVEEVENT;
178 fake.active.gain = 0;
179 fake.active.state = SDL_APPACTIVE;
180 SDL_PushEvent(&fake);
181 break;
182 case SDL_WINDOWEVENT_RESTORED:
183 fake.type = SDL_ACTIVEEVENT;
184 fake.active.gain = 1;
185 fake.active.state = SDL_APPACTIVE;
186 SDL_PushEvent(&fake);
187 break;
188 case SDL_WINDOWEVENT_ENTER:
189 fake.type = SDL_ACTIVEEVENT;
190 fake.active.gain = 1;
191 fake.active.state = SDL_APPMOUSEFOCUS;
192 SDL_PushEvent(&fake);
193 break;
194 case SDL_WINDOWEVENT_LEAVE:
195 fake.type = SDL_ACTIVEEVENT;
196 fake.active.gain = 0;
197 fake.active.state = SDL_APPMOUSEFOCUS;
198 SDL_PushEvent(&fake);
199 break;
200 case SDL_WINDOWEVENT_FOCUS_GAINED:
201 fake.type = SDL_ACTIVEEVENT;
202 fake.active.gain = 1;
203 fake.active.state = SDL_APPINPUTFOCUS;
204 SDL_PushEvent(&fake);
205 break;
206 case SDL_WINDOWEVENT_FOCUS_LOST:
207 fake.type = SDL_ACTIVEEVENT;
208 fake.active.gain = 1;
209 fake.active.state = SDL_APPINPUTFOCUS;
210 SDL_PushEvent(&fake);
211 break;
212 case SDL_WINDOWEVENT_CLOSE:
213 fake.type = SDL_QUIT;
214 SDL_PushEvent(&fake);
215 break;
216 }
217 case SDL_KEYDOWN:
218 case SDL_KEYUP:
219 {
220 Uint32 unicode = 0;
221 if (event->key.type == SDL_KEYDOWN && event->key.keysym.sym < 256) {
222 unicode = event->key.keysym.sym;
223 if (unicode >= 'a' && unicode <= 'z') {
224 int shifted = !!(event->key.keysym.mod & KMOD_SHIFT);
225 int capslock = !!(event->key.keysym.mod & KMOD_CAPS);
226 if ((shifted ^ capslock) != 0) {
227 unicode = SDL_toupper(unicode);
228 }
229 }
230 }
231 if (unicode) {
232 event->key.keysym.unicode = unicode;
233 }
234 break;
235 }
236 case SDL_MOUSEWHEEL:
237 {
238 Uint8 button;
239 int selected;
240 int x, y;
241
242 selected = SDL_SelectMouse(event->wheel.which);
243 SDL_GetMouseState(&x, &y);
244 SDL_SelectMouse(selected);
245
246 if (event->wheel.motion > 0) {
247 button = SDL_BUTTON_WHEELUP;
248 } else {
249 button = SDL_BUTTON_WHEELDOWN;
250 }
251
252 fake.button.which = event->wheel.windowID;
253 fake.button.button = button;
254 fake.button.x = x;
255 fake.button.y = y;
256 fake.button.windowID = event->wheel.windowID;
257
258 fake.type = SDL_MOUSEBUTTONDOWN;
259 fake.button.state = SDL_PRESSED;
260 SDL_PushEvent(&fake);
261
262 fake.type = SDL_MOUSEBUTTONUP;
263 fake.button.state = SDL_RELEASED;
264 SDL_PushEvent(&fake);
265 break;
266 }
267
268 }
269 return 1;
270 }
271
272 static int
273 SDL_VideoPaletteChanged(void *userdata, SDL_Palette * palette)
274 {
275 if (userdata == SDL_ShadowSurface) {
276 /* If the shadow palette changed, make the changes visible */
277 if (!SDL_VideoSurface->format->palette) {
278 SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0);
279 }
280 }
281 if (userdata == SDL_VideoSurface) {
282 return SDL_SetDisplayPalette(palette->colors, 0, palette->ncolors);
283 }
284 return 0;
285 }
286
287 static void
288 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
289 {
290 const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
291 const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
292 if (window) {
293 if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
294 return;
295 }
296 if (SDL_strcmp(window, "center") == 0) {
297 center = window;
298 }
299 }
300 if (center) {
301 const SDL_DisplayMode *current = SDL_GetDesktopDisplayMode();
302 *x = (current->w - w) / 2;
303 *y = (current->h - h) / 2;
304 }
305 }
306
307 SDL_Surface *
308 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
309 {
310 const SDL_DisplayMode *desktop_mode;
311 SDL_DisplayMode mode;
312 int window_x = SDL_WINDOWPOS_UNDEFINED;
313 int window_y = SDL_WINDOWPOS_UNDEFINED;
314 Uint32 window_flags;
315 Uint32 desktop_format;
316 Uint32 desired_format;
317 Uint32 surface_flags;
318
319 if (!SDL_GetVideoDevice()) {
320 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
321 return NULL;
322 }
323 }
324
325 /* Destroy existing window */
326 SDL_PublicSurface = NULL;
327 if (SDL_ShadowSurface) {
328 SDL_FreeSurface(SDL_ShadowSurface);
329 SDL_ShadowSurface = NULL;
330 }
331 if (SDL_VideoSurface) {
332 SDL_DelPaletteWatch(SDL_VideoSurface->format->palette,
333 SDL_VideoPaletteChanged, NULL);
334 SDL_FreeSurface(SDL_VideoSurface);
335 SDL_VideoSurface = NULL;
336 }
337 if (SDL_VideoWindow) {
338 SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
339 }
340 SDL_DestroyWindow(SDL_VideoWindow);
341
342 /* Set up the event filter */
343 if (!SDL_GetEventFilter(NULL, NULL)) {
344 SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
345 }
346
347 /* Create a new window */
348 window_flags = SDL_WINDOW_SHOWN;
349 if (flags & SDL_FULLSCREEN) {
350 window_flags |= SDL_WINDOW_FULLSCREEN;
351 }
352 if (flags & SDL_OPENGL) {
353 window_flags |= SDL_WINDOW_OPENGL;
354 }
355 if (flags & SDL_RESIZABLE) {
356 window_flags |= SDL_WINDOW_RESIZABLE;
357 }
358 if (flags & SDL_NOFRAME) {
359 window_flags |= SDL_WINDOW_BORDERLESS;
360 }
361 GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
362 SDL_SetFullscreenDisplayMode(NULL);
363 SDL_VideoWindow =
364 SDL_CreateWindow(wm_title, window_x, window_y, width, height,
365 window_flags);
366 if (!SDL_VideoWindow) {
367 return NULL;
368 }
369
370 window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
371 surface_flags = 0;
372 if (window_flags & SDL_WINDOW_FULLSCREEN) {
373 surface_flags |= SDL_FULLSCREEN;
374 }
375 if (window_flags & SDL_WINDOW_OPENGL) {
376 surface_flags |= SDL_OPENGL;
377 }
378 if (window_flags & SDL_WINDOW_RESIZABLE) {
379 surface_flags |= SDL_RESIZABLE;
380 }
381 if (window_flags & SDL_WINDOW_BORDERLESS) {
382 surface_flags |= SDL_NOFRAME;
383 }
384
385 /* Set up the desired display mode */
386 desktop_mode = SDL_GetDesktopDisplayMode();
387 desktop_format = desktop_mode->format;
388 if (desktop_format && ((flags & SDL_ANYFORMAT)
389 || (bpp == SDL_BITSPERPIXEL(desktop_format)))) {
390 desired_format = desktop_format;
391 } else {
392 switch (bpp) {
393 case 0:
394 if (desktop_format) {
395 desired_format = desktop_format;
396 } else {
397 desired_format = SDL_PixelFormat_RGB888;
398 }
399 break;
400 case 8:
401 desired_format = SDL_PixelFormat_Index8;
402 break;
403 case 15:
404 desired_format = SDL_PixelFormat_RGB555;
405 break;
406 case 16:
407 desired_format = SDL_PixelFormat_RGB565;
408 break;
409 case 24:
410 desired_format = SDL_PixelFormat_RGB24;
411 break;
412 case 32:
413 desired_format = SDL_PixelFormat_RGB888;
414 break;
415 default:
416 SDL_SetError("Unsupported bpp in SDL_SetVideoMode()");
417 return NULL;
418 }
419 }
420 mode.format = desired_format;
421 mode.w = width;
422 mode.h = height;
423 mode.refresh_rate = 0;
424
425 /* Set the desired display mode */
426 if (flags & SDL_FULLSCREEN) {
427 if (SDL_SetFullscreenDisplayMode(&mode) < 0) {
428 return NULL;
429 }
430 }
431
432 /* If we're in OpenGL mode, just create a stub surface and we're done! */
433 if (flags & SDL_OPENGL) {
434 SDL_VideoSurface =
435 SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
436 if (!SDL_VideoSurface) {
437 return NULL;
438 }
439 SDL_VideoSurface->flags |= surface_flags;
440 SDL_PublicSurface = SDL_VideoSurface;
441 return SDL_PublicSurface;
442 }
443
444 /* Create a renderer for the window */
445 if (SDL_CreateRenderer(SDL_VideoWindow, -1, 0) < 0) {
446 return NULL;
447 }
448
449 /* Create a texture for the screen surface */
450 SDL_VideoTexture =
451 SDL_CreateTexture(desired_format, SDL_TextureAccess_Local, width,
452 height);
453 if (!SDL_VideoTexture) {
454 SDL_VideoTexture =
455 SDL_CreateTexture(0, SDL_TextureAccess_Local, width, height);
456 }
457 if (!SDL_VideoTexture) {
458 return NULL;
459 }
460
461 /* Create the screen surface */
462 SDL_VideoSurface = SDL_CreateRGBSurfaceFromTexture(SDL_VideoTexture);
463 if (!SDL_VideoSurface) {
464 return NULL;
465 }
466 SDL_VideoSurface->flags |= surface_flags;
467
468 /* Set a default screen palette */
469 if (SDL_VideoSurface->format->palette) {
470 SDL_VideoSurface->flags |= SDL_HWPALETTE;
471 SDL_DitherColors(SDL_VideoSurface->format->palette->colors,
472 SDL_VideoSurface->format->BitsPerPixel);
473 SDL_AddPaletteWatch(SDL_VideoSurface->format->palette,
474 SDL_VideoPaletteChanged, NULL);
475 SDL_SetPaletteColors(SDL_VideoSurface->format->palette,
476 SDL_VideoSurface->format->palette->colors, 0,
477 SDL_VideoSurface->format->palette->ncolors);
478 }
479
480 /* Create a shadow surface if necessary */
481 if (((bpp != SDL_VideoSurface->format->BitsPerPixel)
482 && !(flags & SDL_ANYFORMAT))
483 || ((SDL_VideoSurface->flags & SDL_HWSURFACE)
484 && !(flags & SDL_HWSURFACE))) {
485 if ((bpp == SDL_VideoSurface->format->BitsPerPixel)
486 || (flags & SDL_ANYFORMAT)) {
487 SDL_ShadowSurface =
488 SDL_CreateRGBSurface(0, width, height,
489 SDL_VideoSurface->format->BitsPerPixel,
490 SDL_VideoSurface->format->Rmask,
491 SDL_VideoSurface->format->Gmask,
492 SDL_VideoSurface->format->Bmask,
493 SDL_VideoSurface->format->Amask);
494 } else {
495 SDL_ShadowSurface =
496 SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
497 }
498 if (!SDL_ShadowSurface) {
499 return NULL;
500 }
501 SDL_ShadowSurface->flags |= surface_flags;
502
503 /* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
504 if (SDL_ShadowSurface->format->palette) {
505 SDL_ShadowSurface->flags |= SDL_HWPALETTE;
506 if (SDL_VideoSurface->format->palette) {
507 SDL_SetSurfacePalette(SDL_ShadowSurface,
508 SDL_VideoSurface->format->palette);
509 } else {
510 SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
511 SDL_ShadowSurface->format->BitsPerPixel);
512 }
513 }
514 }
515 SDL_PublicSurface =
516 (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
517
518 /* Clear the surface for display */
519 SDL_FillRect(SDL_PublicSurface, NULL, 0);
520
521 /* We're finally done! */
522 return SDL_PublicSurface;
523 }
524
525 SDL_Surface *
526 SDL_GetVideoSurface(void)
527 {
528 return SDL_PublicSurface;
529 }
530
531 SDL_Surface *
532 SDL_DisplayFormat(SDL_Surface * surface)
533 {
534 Uint32 flags;
535
536 if (!SDL_PublicSurface) {
537 SDL_SetError("No video mode has been set");
538 return NULL;
539 }
540
541 /* Set the flags appropriate for copying to display surface */
542 flags = SDL_SWSURFACE;
543 #ifdef AUTORLE_DISPLAYFORMAT
544 flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA));
545 flags |= SDL_RLEACCELOK;
546 #else
547 flags |=
548 surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK);
549 #endif
550 return SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags);
551 }
552
553 SDL_Surface *
554 SDL_DisplayFormatAlpha(SDL_Surface * surface)
555 {
556 SDL_PixelFormat *vf;
557 SDL_PixelFormat *format;
558 SDL_Surface *converted;
559 Uint32 flags;
560 /* default to ARGB8888 */
561 Uint32 amask = 0xff000000;
562 Uint32 rmask = 0x00ff0000;
563 Uint32 gmask = 0x0000ff00;
564 Uint32 bmask = 0x000000ff;
565
566 if (!SDL_PublicSurface) {
567 SDL_SetError("No video mode has been set");
568 return NULL;
569 }
570 vf = SDL_PublicSurface->format;
571
572 switch (vf->BytesPerPixel) {
573 case 2:
574 /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
575 For anything else (like ARGB4444) it doesn't matter
576 since we have no special code for it anyway */
577 if ((vf->Rmask == 0x1f) &&
578 (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
579 rmask = 0xff;
580 bmask = 0xff0000;
581 }
582 break;
583
584 case 3:
585 case 4:
586 /* Keep the video format, as long as the high 8 bits are
587 unused or alpha */
588 if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
589 rmask = 0xff;
590 bmask = 0xff0000;
591 }
592 break;
593
594 default:
595 /* We have no other optimised formats right now. When/if a new
596 optimised alpha format is written, add the converter here */
597 break;
598 }
599 format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
600 flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
601 flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
602 converted = SDL_ConvertSurface(surface, format, flags);
603 SDL_FreeFormat(format);
604 return converted;
605 }
606
607 int
608 SDL_Flip(SDL_Surface * screen)
609 {
610 SDL_UpdateRect(screen, 0, 0, 0, 0);
611 return 0;
612 }
613
614 void
615 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
616 {
617 if (screen) {
618 SDL_Rect rect;
619
620 /* Perform some checking */
621 if (w == 0)
622 w = screen->w;
623 if (h == 0)
624 h = screen->h;
625 if ((int) (x + w) > screen->w)
626 return;
627 if ((int) (y + h) > screen->h)
628 return;
629
630 /* Fill the rectangle */
631 rect.x = (Sint16) x;
632 rect.y = (Sint16) y;
633 rect.w = (Uint16) w;
634 rect.h = (Uint16) h;
635 SDL_UpdateRects(screen, 1, &rect);
636 }
637 }
638 void
639 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
640 {
641 int i;
642
643 if (screen == SDL_ShadowSurface) {
644 for (i = 0; i < numrects; ++i) {
645 SDL_LowerBlit(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
646 &rects[i]);
647 }
648
649 /* Fall through to video surface update */
650 screen = SDL_VideoSurface;
651 }
652 if (screen == SDL_VideoSurface) {
653 for (i = 0; i < numrects; ++i) {
654 SDL_RenderCopy(SDL_VideoTexture, &rects[i], &rects[i],
655 SDL_TextureBlendMode_None,
656 SDL_TextureScaleMode_None);
657 }
658 SDL_RenderPresent();
659 }
660 }
661
662 void
663 SDL_WM_SetCaption(const char *title, const char *icon)
664 {
665 if (wm_title) {
666 SDL_free(wm_title);
667 } else {
668 wm_title = SDL_strdup(title);
669 }
670 SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
671 }
672
673 void
674 SDL_WM_GetCaption(char **title, char **icon)
675 {
676 if (title) {
677 *title = wm_title;
678 }
679 if (icon) {
680 *icon = "";
681 }
682 }
683
684 void
685 SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
686 {
687 /* FIXME */
688 }
689
690 int
691 SDL_WM_IconifyWindow(void)
692 {
693 SDL_MinimizeWindow(SDL_VideoWindow);
694 return 0;
695 }
696
697 int
698 SDL_WM_ToggleFullScreen(SDL_Surface * surface)
699 {
700 if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
701 if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
702 return 0;
703 }
704 SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
705 } else {
706 if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
707 return 0;
708 }
709 SDL_PublicSurface->flags |= SDL_FULLSCREEN;
710 }
711 return 1;
712 }
713
714 SDL_GrabMode
715 SDL_WM_GrabInput(SDL_GrabMode mode)
716 {
717 if (mode != SDL_GRAB_QUERY) {
718 SDL_SetWindowGrab(SDL_VideoWindow, mode);
719 }
720 return (SDL_GrabMode) SDL_GetWindowGrab(SDL_VideoWindow);
721 }
722
723 void
724 SDL_WarpMouse(Uint16 x, Uint16 y)
725 {
726 SDL_WarpMouseInWindow(SDL_VideoWindow, x, y);
727 }
728
729 Uint8
730 SDL_GetAppState(void)
731 {
732 Uint8 state = 0;
733 Uint32 flags = 0;
734
735 flags = SDL_GetWindowFlags(SDL_VideoWindow);
736 if ((flags & SDL_WINDOW_SHOWN) && !(flags & SDL_WINDOW_MINIMIZED)) {
737 state |= SDL_APPACTIVE;
738 }
739 if (flags & SDL_WINDOW_INPUT_FOCUS) {
740 state |= SDL_APPINPUTFOCUS;
741 }
742 if (flags & SDL_WINDOW_MOUSE_FOCUS) {
743 state |= SDL_APPMOUSEFOCUS;
744 }
745 return state;
746 }
747
748 const SDL_version *
749 SDL_Linked_Version(void)
750 {
751 static SDL_version version;
752 SDL_VERSION(&version);
753 return &version;
754 }
755
756 int
757 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
758 int firstcolor, int ncolors)
759 {
760 return SDL_SetColors(surface, colors, firstcolor, ncolors);
761 }
762
763 int
764 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
765 int ncolors)
766 {
767 if (SDL_SetPaletteColors
768 (surface->format->palette, colors, firstcolor, ncolors) == 0) {
769 return 1;
770 } else {
771 return 0;
772 }
773 }
774
775 int
776 SDL_GetWMInfo(SDL_SysWMinfo * info)
777 {
778 return SDL_GetWindowWMInfo(SDL_VideoWindow, info);
779 }
780
781 #if 0
782 void
783 SDL_MoveCursor(int x, int y)
784 {
785 SDL_VideoDevice *_this = SDL_GetVideoDevice();
786
787 /* Erase and update the current mouse position */
788 if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
789 /* Erase and redraw mouse cursor in new position */
790 SDL_LockCursor();
791 SDL_EraseCursor(SDL_VideoSurface);
792 SDL_cursor->area.x = (x - SDL_cursor->hot_x);
793 SDL_cursor->area.y = (y - SDL_cursor->hot_y);
794 SDL_DrawCursor(SDL_VideoSurface);
795 SDL_UnlockCursor();
796 } else if (_this->MoveWMCursor) {
797 _this->MoveWMCursor(_this, x, y);
798 }
799 }
800
801 /* Keep track of the current cursor colors */
802 static int palette_changed = 1;
803 static Uint8 pixels8[2];
804
805 void
806 SDL_CursorPaletteChanged(void)
807 {
808 palette_changed = 1;
809 }
810
811 void
812 SDL_MouseRect(SDL_Rect * area)
813 {
814 SDL_VideoDevice *_this = SDL_GetVideoDevice();
815 int clip_diff;
816
817 *area = SDL_cursor->area;
818 if (area->x < 0) {
819 area->w += area->x;
820 area->x = 0;
821 }
822 if (area->y < 0) {
823 area->h += area->y;
824 area->y = 0;
825 }
826 clip_diff = (area->x + area->w) - SDL_VideoSurface->w;
827 if (clip_diff > 0) {
828 area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
829 }
830 clip_diff = (area->y + area->h) - SDL_VideoSurface->h;
831 if (clip_diff > 0) {
832 area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
833 }
834 }
835
836 static void
837 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
838 {
839 const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
840 int i, w, h;
841 Uint8 *data, datab;
842 Uint8 *mask, maskb;
843
844 data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
845 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
846 switch (screen->format->BytesPerPixel) {
847
848 case 1:
849 {
850 Uint8 *dst;
851 int dstskip;
852
853 if (palette_changed) {
854 pixels8[0] =
855 (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
856 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
857 palette_changed = 0;
858 }
859 dst = (Uint8 *) screen->pixels +
860 (SDL_cursor->area.y + area->y) * screen->pitch +
861 SDL_cursor->area.x;
862 dstskip = screen->pitch - area->w;
863
864 for (h = area->h; h; h--) {
865 for (w = area->w / 8; w; w--) {
866 maskb = *mask++;
867 datab = *data++;
868 for (i = 0; i < 8; ++i) {
869 if (maskb & 0x80) {
870 *dst = pixels8[datab >> 7];
871 }
872 maskb <<= 1;
873 datab <<= 1;
874 dst++;
875 }
876 }
877 dst += dstskip;
878 }
879 }
880 break;
881
882 case 2:
883 {
884 Uint16 *dst;
885 int dstskip;
886
887 dst = (Uint16 *) screen->pixels +
888 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
889 SDL_cursor->area.x;
890 dstskip = (screen->pitch / 2) - area->w;
891
892 for (h = area->h; h; h--) {
893 for (w = area->w / 8; w; w--) {
894 maskb = *mask++;
895 datab = *data++;
896 for (i = 0; i < 8; ++i) {
897 if (maskb & 0x80) {
898 *dst = (Uint16) pixels[datab >> 7];
899 }
900 maskb <<= 1;
901 datab <<= 1;
902 dst++;
903 }
904 }
905 dst += dstskip;
906 }
907 }
908 break;
909
910 case 3:
911 {
912 Uint8 *dst;
913 int dstskip;
914
915 dst = (Uint8 *) screen->pixels +
916 (SDL_cursor->area.y + area->y) * screen->pitch +
917 SDL_cursor->area.x * 3;
918 dstskip = screen->pitch - area->w * 3;
919
920 for (h = area->h; h; h--) {
921 for (w = area->w / 8; w; w--) {
922 maskb = *mask++;
923 datab = *data++;
924 for (i = 0; i < 8; ++i) {
925 if (maskb & 0x80) {
926 SDL_memset(dst, pixels[datab >> 7], 3);
927 }
928 maskb <<= 1;
929 datab <<= 1;
930 dst += 3;
931 }
932 }
933 dst += dstskip;
934 }
935 }
936 break;
937
938 case 4:
939 {
940 Uint32 *dst;
941 int dstskip;
942
943 dst = (Uint32 *) screen->pixels +
944 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
945 SDL_cursor->area.x;
946 dstskip = (screen->pitch / 4) - area->w;
947
948 for (h = area->h; h; h--) {
949 for (w = area->w / 8; w; w--) {
950 maskb = *mask++;
951 datab = *data++;
952 for (i = 0; i < 8; ++i) {
953 if (maskb & 0x80) {
954 *dst = pixels[datab >> 7];
955 }
956 maskb <<= 1;
957 datab <<= 1;
958 dst++;
959 }
960 }
961 dst += dstskip;
962 }
963 }
964 break;
965 }
966 }
967
968 static void
969 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
970 {
971 const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
972 int h;
973 int x, minx, maxx;
974 Uint8 *data, datab = 0;
975 Uint8 *mask, maskb = 0;
976 Uint8 *dst;
977 int dstbpp, dstskip;
978
979 data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
980 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
981 dstbpp = screen->format->BytesPerPixel;
982 dst = (Uint8 *) screen->pixels +
983 (SDL_cursor->area.y + area->y) * screen->pitch +
984 SDL_cursor->area.x * dstbpp;
985 dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
986
987 minx = area->x;
988 maxx = area->x + area->w;
989 if (screen->format->BytesPerPixel == 1) {
990 if (palette_changed) {
991 pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
992 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
993 palette_changed = 0;
994 }
995 for (h = area->h; h; h--) {
996 for (x = 0; x < SDL_cursor->area.w; ++x) {
997 if ((x % 8) == 0) {
998 maskb = *mask++;
999 datab = *data++;
1000 }
1001 if ((x >= minx) && (x < maxx)) {
1002 if (maskb & 0x80) {
1003 SDL_memset(dst, pixels8[datab >> 7], dstbpp);
1004 }
1005 }
1006 maskb <<= 1;
1007 datab <<= 1;
1008 dst += dstbpp;
1009 }
1010 dst += dstskip;
1011 }
1012 } else {
1013 for (h = area->h; h; h--) {
1014 for (x = 0; x < SDL_cursor->area.w; ++x) {
1015 if ((x % 8) == 0) {
1016 maskb = *mask++;
1017 datab = *data++;
1018 }
1019 if ((x >= minx) && (x < maxx)) {
1020 if (maskb & 0x80) {
1021 SDL_memset(dst, pixels[datab >> 7], dstbpp);
1022 }
1023 }
1024 maskb <<= 1;
1025 datab <<= 1;
1026 dst += dstbpp;
1027 }
1028 dst += dstskip;
1029 }
1030 }
1031 }
1032
1033 /* This handles the ugly work of converting the saved cursor background from
1034 the pixel format of the shadow surface to that of the video surface.
1035 This is only necessary when blitting from a shadow surface of a different
1036 pixel format than the video surface, and using a software rendered cursor.
1037 */
1038 static void
1039 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
1040 {
1041 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1042 SDL_BlitInfo info;
1043 SDL_loblit RunBlit;
1044
1045 /* Make sure we can steal the blit mapping */
1046 if (screen->map->dst != SDL_VideoSurface) {
1047 return;
1048 }
1049
1050 /* Set up the blit information */
1051 info.s_pixels = SDL_cursor->save[1];
1052 info.s_width = w;
1053 info.s_height = h;
1054 info.s_skip = 0;
1055 info.d_pixels = SDL_cursor->save[0];
1056 info.d_width = w;
1057 info.d_height = h;
1058 info.d_skip = 0;
1059 info.aux_data = screen->map->sw_data->aux_data;
1060 info.src = screen->format;
1061 info.table = screen->map->table;
1062 info.dst = SDL_VideoSurface->format;
1063 RunBlit = screen->map->sw_data->blit;
1064
1065 /* Run the actual software blit */
1066 RunBlit(&info);
1067 }
1068
1069 void
1070 SDL_DrawCursorNoLock(SDL_Surface * screen)
1071 {
1072 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1073 SDL_Rect area;
1074
1075 /* Get the mouse rectangle, clipped to the screen */
1076 SDL_MouseRect(&area);
1077 if ((area.w == 0) || (area.h == 0)) {
1078 return;
1079 }
1080
1081 /* Copy mouse background */
1082 {
1083 int w, h, screenbpp;
1084 Uint8 *src, *dst;
1085
1086 /* Set up the copy pointers */
1087 screenbpp = screen->format->BytesPerPixel;
1088 if ((screen == SDL_VideoSurface) ||
1089 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) {
1090 dst = SDL_cursor->save[0];
1091 } else {
1092 dst = SDL_cursor->save[1];
1093 }
1094 src = (Uint8 *) screen->pixels + area.y * screen->pitch +
1095 area.x * screenbpp;
1096
1097 /* Perform the copy */
1098 w = area.w * screenbpp;
1099 h = area.h;
1100 while (h--) {
1101 SDL_memcpy(dst, src, w);
1102 dst += w;
1103 src += screen->pitch;
1104 }
1105 }
1106
1107 /* Draw the mouse cursor */
1108 area.x -= SDL_cursor->area.x;
1109 area.y -= SDL_cursor->area.y;
1110 if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
1111 SDL_DrawCursorFast(screen, &area);
1112 } else {
1113 SDL_DrawCursorSlow(screen, &area);
1114 }
1115 }
1116
1117 void
1118 SDL_DrawCursor(SDL_Surface * screen)
1119 {
1120 /* Lock the screen if necessary */
1121 if (screen == NULL) {
1122 return;
1123 }
1124 if (SDL_MUSTLOCK(screen)) {
1125 if (SDL_LockSurface(screen) < 0) {
1126 return;
1127 }
1128 }
1129
1130 SDL_DrawCursorNoLock(screen);
1131
1132 /* Unlock the screen and update if necessary */
1133 if (SDL_MUSTLOCK(screen)) {
1134 SDL_UnlockSurface(screen);
1135 }
1136 if ((screen->flags & SDL_SCREEN_SURFACE) &&
1137 !(screen->flags & SDL_HWSURFACE)) {
1138 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1139 SDL_Window *window;
1140 SDL_Rect area;
1141
1142 window = SDL_GetWindowFromSurface(screen);
1143 if (!window) {
1144 return;
1145 }
1146
1147 SDL_MouseRect(&area);
1148
1149 if (_this->UpdateWindowSurface) {
1150 _this->UpdateWindowSurface(_this, window, 1, &area);
1151 }
1152 }
1153 }
1154
1155 void
1156 SDL_EraseCursorNoLock(SDL_Surface * screen)
1157 {
1158 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1159 SDL_Window *window;
1160 SDL_Rect area;
1161
1162 /* Get the window associated with the surface */
1163 window = SDL_GetWindowFromSurface(screen);
1164 if (!window || !window->surface) {
1165 return;
1166 }
1167
1168 /* Get the mouse rectangle, clipped to the screen */
1169 SDL_MouseRect(&area);
1170 if ((area.w == 0) || (area.h == 0)) {
1171 return;
1172 }
1173
1174 /* Copy mouse background */
1175 {
1176 int w, h, screenbpp;
1177 Uint8 *src, *dst;
1178
1179 /* Set up the copy pointers */
1180 screenbpp = screen->format->BytesPerPixel;
1181 if ((screen->flags & SDL_SCREEN_SURFACE) ||
1182 FORMAT_EQUAL(screen->format, window->surface->format)) {
1183 src = SDL_cursor->save[0];
1184 } else {
1185 src = SDL_cursor->save[1];
1186 }
1187 dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
1188 area.x * screenbpp;
1189
1190 /* Perform the copy */
1191 w = area.w * screenbpp;
1192 h = area.h;
1193 while (h--) {
1194 SDL_memcpy(dst, src, w);
1195 src += w;
1196 dst += screen->pitch;
1197 }
1198
1199 /* Perform pixel conversion on cursor background */
1200 if (src > SDL_cursor->save[1]) {
1201 SDL_ConvertCursorSave(screen, area.w, area.h);
1202 }
1203 }
1204 }
1205
1206 void
1207 SDL_EraseCursor(SDL_Surface * screen)
1208 {
1209 /* Lock the screen if necessary */
1210 if (screen == NULL) {
1211 return;
1212 }
1213 if (SDL_MUSTLOCK(screen)) {
1214 if (SDL_LockSurface(screen) < 0) {
1215 return;
1216 }
1217 }
1218
1219 SDL_EraseCursorNoLock(screen);
1220
1221 /* Unlock the screen and update if necessary */
1222 if (SDL_MUSTLOCK(screen)) {
1223 SDL_UnlockSurface(screen);
1224 }
1225 if ((screen->flags & SDL_SCREEN_SURFACE) &&
1226 !(screen->flags & SDL_HWSURFACE)) {
1227 SDL_VideoDevice *_this = SDL_GetVideoDevice();
1228 SDL_Window *window;
1229 SDL_Rect area;
1230
1231 window = SDL_GetWindowFromSurface(screen);
1232 if (!window) {
1233 return;
1234 }
1235
1236 SDL_MouseRect(&area);
1237
1238 if (_this->UpdateWindowSurface) {
1239 _this->UpdateWindowSurface(_this, window, 1, &area);
1240 }
1241 }
1242 }
1243
1244 /* Reset the cursor on video mode change
1245 FIXME: Keep track of all cursors, and reset them all.
1246 */
1247 void
1248 SDL_ResetCursor(void)
1249 {
1250 int savelen;
1251
1252 if (SDL_cursor) {
1253 savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
1254 SDL_cursor->area.x = 0;
1255 SDL_cursor->area.y = 0;
1256 SDL_memset(SDL_cursor->save[0], 0, savelen);
1257 }
1258 }
1259 #endif
1260
1261 struct private_yuvhwdata
1262 {
1263 Uint16 pitches[3];
1264 Uint8 *planes[3];
1265
1266 SDL_TextureID textureID;
1267 };
1268
1269 SDL_Overlay *
1270 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
1271 {
1272 SDL_Overlay *overlay;
1273 Uint32 texture_format;
1274
1275 if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
1276 SDL_SetError("YUV overlays are not supported in OpenGL mode");
1277 return NULL;
1278 }
1279
1280 if (display != SDL_PublicSurface) {
1281 SDL_SetError("YUV display is only supported on the screen surface");
1282 return NULL;
1283 }
1284
1285 switch (format) {
1286 case SDL_YV12_OVERLAY:
1287 texture_format = SDL_PixelFormat_YV12;
1288 break;
1289 case SDL_IYUV_OVERLAY:
1290 texture_format = SDL_PixelFormat_IYUV;
1291 break;
1292 case SDL_YUY2_OVERLAY:
1293 texture_format = SDL_PixelFormat_YUY2;
1294 break;
1295 case SDL_UYVY_OVERLAY:
1296 texture_format = SDL_PixelFormat_UYVY;
1297 break;
1298 case SDL_YVYU_OVERLAY:
1299 texture_format = SDL_PixelFormat_YVYU;
1300 break;
1301 default:
1302 SDL_SetError("Unknown YUV format");
1303 return NULL;
1304 }
1305
1306 overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
1307 if (!overlay) {
1308 SDL_OutOfMemory();
1309 return NULL;
1310 }
1311 SDL_zerop(overlay);
1312
1313 overlay->hwdata =
1314 (struct private_yuvhwdata *) SDL_malloc(sizeof(*overlay->hwdata));
1315 if (!overlay->hwdata) {
1316 SDL_free(overlay);
1317 SDL_OutOfMemory();
1318 return NULL;
1319 }
1320
1321 overlay->format = format;
1322 overlay->w = w;
1323 overlay->h = h;
1324 if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
1325 overlay->planes = 3;
1326 } else {
1327 overlay->planes = 1;
1328 }
1329 overlay->pitches = overlay->hwdata->pitches;
1330 overlay->pixels = overlay->hwdata->planes;
1331
1332 switch (format) {
1333 case SDL_YV12_OVERLAY:
1334 case SDL_IYUV_OVERLAY:
1335 overlay->pitches[0] = overlay->w;
1336 overlay->pitches[1] = overlay->w / 2;
1337 overlay->pitches[2] = overlay->w / 2;
1338 break;
1339 case SDL_YUY2_OVERLAY:
1340 case SDL_UYVY_OVERLAY:
1341 case SDL_YVYU_OVERLAY:
1342 overlay->pitches[0] = overlay->w * 2;
1343 break;
1344 }
1345
1346 overlay->hwdata->textureID =
1347 SDL_CreateTexture(texture_format, SDL_TextureAccess_Local, w, h);
1348 if (!overlay->hwdata->textureID) {
1349 SDL_FreeYUVOverlay(overlay);
1350 return NULL;
1351 }
1352
1353 return overlay;
1354 }
1355
1356 int
1357 SDL_LockYUVOverlay(SDL_Overlay * overlay)
1358 {
1359 void *pixels;
1360 int pitch;
1361 if (SDL_LockTexture(overlay->hwdata->textureID, NULL, 1, &pixels, &pitch)
1362 < 0) {
1363 return -1;
1364 }
1365 switch (overlay->format) {
1366 case SDL_YV12_OVERLAY:
1367 case SDL_IYUV_OVERLAY:
1368 overlay->pixels[0] = (Uint8 *) pixels;
1369 overlay->pixels[1] =
1370 overlay->pixels[0] + overlay->pitches[0] * overlay->h;
1371 overlay->pixels[2] =
1372 overlay->pixels[1] + overlay->pitches[1] * overlay->h;
1373 break;
1374 case SDL_YUY2_OVERLAY:
1375 case SDL_UYVY_OVERLAY:
1376 case SDL_YVYU_OVERLAY:
1377 overlay->pixels[0] = (Uint8 *) pixels;
1378 break;
1379 }
1380 return 0;
1381 }
1382
1383 void
1384 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
1385 {
1386 SDL_UnlockTexture(overlay->hwdata->textureID);
1387 }
1388
1389 int
1390 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
1391 {
1392 if (SDL_RenderCopy(overlay->hwdata->textureID, NULL, dstrect,
1393 SDL_TextureBlendMode_None,
1394 SDL_TextureScaleMode_Fast) < 0) {
1395 return -1;
1396 }
1397 SDL_RenderPresent();
1398 return 0;
1399 }
1400
1401 void
1402 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
1403 {
1404 if (overlay) {
1405 if (overlay->hwdata) {
1406 if (overlay->hwdata->textureID) {
1407 SDL_DestroyTexture(overlay->hwdata->textureID);
1408 }
1409 SDL_free(overlay->hwdata);
1410 }
1411 SDL_free(overlay);
1412 }
1413 }
1414
1415 /* vi: set ts=4 sw=4 expandtab: */