mirror of
https://github.com/blawar/GLideN64.git
synced 2024-06-30 08:24:05 +00:00
784 lines
23 KiB
C
784 lines
23 KiB
C
![]() |
/*
|
||
|
Simple DirectMedia Layer
|
||
|
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||
|
|
||
|
This software is provided 'as-is', without any express or implied
|
||
|
warranty. In no event will the authors be held liable for any damages
|
||
|
arising from the use of this software.
|
||
|
|
||
|
Permission is granted to anyone to use this software for any purpose,
|
||
|
including commercial applications, and to alter it and redistribute it
|
||
|
freely, subject to the following restrictions:
|
||
|
|
||
|
1. The origin of this software must not be misrepresented; you must not
|
||
|
claim that you wrote the original software. If you use this software
|
||
|
in a product, an acknowledgment in the product documentation would be
|
||
|
appreciated but is not required.
|
||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||
|
misrepresented as being the original software.
|
||
|
3. This notice may not be removed or altered from any source distribution.
|
||
|
*/
|
||
|
|
||
|
#include <SDL_surface.h>
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
Uint8 *src;
|
||
|
int src_w, src_h;
|
||
|
int src_pitch;
|
||
|
int src_skip;
|
||
|
Uint8 *dst;
|
||
|
int dst_w, dst_h;
|
||
|
int dst_pitch;
|
||
|
int dst_skip;
|
||
|
SDL_PixelFormat *src_fmt;
|
||
|
SDL_PixelFormat *dst_fmt;
|
||
|
Uint8 *table;
|
||
|
int flags;
|
||
|
Uint32 colorkey;
|
||
|
Uint8 r, g, b, a;
|
||
|
} SDL_BlitInfo;
|
||
|
|
||
|
/* Blit mapping definition */
|
||
|
typedef struct SDL_BlitMap
|
||
|
{
|
||
|
SDL_Surface *dst;
|
||
|
int identity;
|
||
|
SDL_blit blit;
|
||
|
void *data;
|
||
|
SDL_BlitInfo info;
|
||
|
|
||
|
/* the version count matches the destination; mismatch indicates
|
||
|
an invalid mapping */
|
||
|
Uint32 dst_palette_version;
|
||
|
Uint32 src_palette_version;
|
||
|
} SDL_BlitMap;
|
||
|
|
||
|
typedef struct SDL_VideoInfo
|
||
|
{
|
||
|
Uint32 hw_available:1;
|
||
|
Uint32 wm_available:1;
|
||
|
Uint32 UnusedBits1:6;
|
||
|
Uint32 UnusedBits2:1;
|
||
|
Uint32 blit_hw:1;
|
||
|
Uint32 blit_hw_CC:1;
|
||
|
Uint32 blit_hw_A:1;
|
||
|
Uint32 blit_sw:1;
|
||
|
Uint32 blit_sw_CC:1;
|
||
|
Uint32 blit_sw_A:1;
|
||
|
Uint32 blit_fill:1;
|
||
|
Uint32 UnusedBits3:16;
|
||
|
Uint32 video_mem;
|
||
|
|
||
|
SDL_PixelFormat *vfmt;
|
||
|
|
||
|
int current_w;
|
||
|
int current_h;
|
||
|
} SDL_VideoInfo;
|
||
|
|
||
|
#define SDL_ANYFORMAT 0x00100000
|
||
|
#define SDL_HWPALETTE 0x00200000
|
||
|
#define SDL_FULLSCREEN 0x00800000
|
||
|
#define SDL_RESIZABLE 0x01000000
|
||
|
#define SDL_NOFRAME 0x02000000
|
||
|
#define SDL_OPENGL 0x04000000
|
||
|
#define SDL_HWSURFACE 0x08000001 /**< \note Not used */
|
||
|
|
||
|
#define SDL_BUTTON_WHEELUP 4
|
||
|
#define SDL_BUTTON_WHEELDOWN 5
|
||
|
|
||
|
int initialized_video = 0;
|
||
|
|
||
|
static SDL_Window *SDL_VideoWindow = NULL;
|
||
|
static SDL_Surface *SDL_WindowSurface = NULL;
|
||
|
static SDL_Surface *SDL_VideoSurface = NULL;
|
||
|
static SDL_Surface *SDL_ShadowSurface = NULL;
|
||
|
static SDL_Surface *SDL_PublicSurface = NULL;
|
||
|
static SDL_Rect SDL_VideoViewport;
|
||
|
static char *wm_title = NULL;
|
||
|
static Uint32 SDL_VideoFlags = 0;
|
||
|
static SDL_GLContext *SDL_VideoContext = NULL;
|
||
|
static SDL_Surface *SDL_VideoIcon;
|
||
|
|
||
|
static void
|
||
|
SDL_WM_SetCaption(const char *title, const char *icon)
|
||
|
{
|
||
|
if (wm_title) {
|
||
|
SDL_free(wm_title);
|
||
|
}
|
||
|
if (title) {
|
||
|
wm_title = SDL_strdup(title);
|
||
|
} else {
|
||
|
wm_title = NULL;
|
||
|
}
|
||
|
SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
GetVideoDisplay()
|
||
|
{
|
||
|
const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
|
||
|
if ( !variable ) {
|
||
|
variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
|
||
|
}
|
||
|
if ( variable ) {
|
||
|
return SDL_atoi(variable);
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static const SDL_VideoInfo *
|
||
|
SDL_GetVideoInfo(void)
|
||
|
{
|
||
|
static SDL_VideoInfo info;
|
||
|
SDL_DisplayMode mode;
|
||
|
|
||
|
/* Memory leak, compatibility code, who cares? */
|
||
|
if (!info.vfmt && SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode) == 0) {
|
||
|
info.vfmt = SDL_AllocFormat(mode.format);
|
||
|
info.current_w = mode.w;
|
||
|
info.current_h = mode.h;
|
||
|
}
|
||
|
return &info;
|
||
|
}
|
||
|
|
||
|
static SDL_Rect **
|
||
|
SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags)
|
||
|
{
|
||
|
int i, nmodes;
|
||
|
SDL_Rect **modes;
|
||
|
|
||
|
if (!initialized_video) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (!(flags & SDL_FULLSCREEN)) {
|
||
|
return (SDL_Rect **) (-1);
|
||
|
}
|
||
|
|
||
|
if (!format) {
|
||
|
format = SDL_GetVideoInfo()->vfmt;
|
||
|
}
|
||
|
|
||
|
/* Memory leak, but this is a compatibility function, who cares? */
|
||
|
nmodes = 0;
|
||
|
modes = NULL;
|
||
|
for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
|
||
|
SDL_DisplayMode mode;
|
||
|
int bpp;
|
||
|
|
||
|
SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
|
||
|
if (!mode.w || !mode.h) {
|
||
|
return (SDL_Rect **) (-1);
|
||
|
}
|
||
|
|
||
|
/* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
|
||
|
if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
|
||
|
bpp = SDL_BITSPERPIXEL(mode.format);
|
||
|
} else {
|
||
|
bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
|
||
|
}
|
||
|
|
||
|
if (bpp != format->BitsPerPixel) {
|
||
|
continue;
|
||
|
}
|
||
|
if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
|
||
|
&& modes[nmodes - 1]->h == mode.h) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
modes = (SDL_Rect**)SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
|
||
|
if (!modes) {
|
||
|
return NULL;
|
||
|
}
|
||
|
modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
|
||
|
if (!modes[nmodes]) {
|
||
|
return NULL;
|
||
|
}
|
||
|
modes[nmodes]->x = 0;
|
||
|
modes[nmodes]->y = 0;
|
||
|
modes[nmodes]->w = mode.w;
|
||
|
modes[nmodes]->h = mode.h;
|
||
|
++nmodes;
|
||
|
}
|
||
|
if (modes) {
|
||
|
modes[nmodes] = NULL;
|
||
|
}
|
||
|
return modes;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (screen == SDL_ShadowSurface) {
|
||
|
for (i = 0; i < numrects; ++i) {
|
||
|
SDL_BlitSurface(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
|
||
|
&rects[i]);
|
||
|
}
|
||
|
|
||
|
/* Fall through to video surface update */
|
||
|
screen = SDL_VideoSurface;
|
||
|
}
|
||
|
if (screen == SDL_VideoSurface) {
|
||
|
if (SDL_VideoViewport.x || SDL_VideoViewport.y) {
|
||
|
SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
|
||
|
SDL_Rect *stackrect;
|
||
|
const SDL_Rect *rect;
|
||
|
|
||
|
/* Offset all the rectangles before updating */
|
||
|
for (i = 0; i < numrects; ++i) {
|
||
|
rect = &rects[i];
|
||
|
stackrect = &stackrects[i];
|
||
|
stackrect->x = SDL_VideoViewport.x + rect->x;
|
||
|
stackrect->y = SDL_VideoViewport.y + rect->y;
|
||
|
stackrect->w = rect->w;
|
||
|
stackrect->h = rect->h;
|
||
|
}
|
||
|
SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, stackrects, numrects);
|
||
|
SDL_stack_free(stackrects);
|
||
|
} else {
|
||
|
SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, rects, numrects);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
|
||
|
{
|
||
|
if (screen) {
|
||
|
SDL_Rect rect;
|
||
|
|
||
|
/* Fill the rectangle */
|
||
|
rect.x = (int) x;
|
||
|
rect.y = (int) y;
|
||
|
rect.w = (int) (w ? w : screen->w);
|
||
|
rect.h = (int) (h ? h : screen->h);
|
||
|
SDL_UpdateRects(screen, 1, &rect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
SDL_Flip(SDL_Surface * screen)
|
||
|
{
|
||
|
SDL_UpdateRect(screen, 0, 0, 0, 0);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Calculate the pad-aligned scanline width of a surface
|
||
|
*/
|
||
|
static int
|
||
|
SDL_CalculatePitch(SDL_Surface * surface)
|
||
|
{
|
||
|
int pitch;
|
||
|
|
||
|
/* Surface should be 4-byte aligned for speed */
|
||
|
pitch = surface->w * surface->format->BytesPerPixel;
|
||
|
switch (surface->format->BitsPerPixel) {
|
||
|
case 1:
|
||
|
pitch = (pitch + 7) / 8;
|
||
|
break;
|
||
|
case 4:
|
||
|
pitch = (pitch + 1) / 2;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
pitch = (pitch + 3) & ~3; /* 4-byte aligning */
|
||
|
return (pitch);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
SDL_InvalidateMap(SDL_BlitMap * map)
|
||
|
{
|
||
|
if (!map) {
|
||
|
return;
|
||
|
}
|
||
|
if (map->dst) {
|
||
|
/* Release our reference to the surface - see the note below */
|
||
|
if (--map->dst->refcount <= 0) {
|
||
|
SDL_FreeSurface(map->dst);
|
||
|
}
|
||
|
}
|
||
|
map->dst = NULL;
|
||
|
map->src_palette_version = 0;
|
||
|
map->dst_palette_version = 0;
|
||
|
if (map->info.table) {
|
||
|
SDL_free(map->info.table);
|
||
|
map->info.table = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
SDL_GL_SwapBuffers(void)
|
||
|
{
|
||
|
SDL_GL_SwapWindow(SDL_VideoWindow);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
SDL_WM_ToggleFullScreen(SDL_Surface * surface)
|
||
|
{
|
||
|
int length;
|
||
|
void *pixels;
|
||
|
Uint8 *src, *dst;
|
||
|
int row;
|
||
|
int window_w;
|
||
|
int window_h;
|
||
|
|
||
|
if (!SDL_PublicSurface) {
|
||
|
SDL_SetError("SDL_SetVideoMode() hasn't been called");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Copy the old bits out */
|
||
|
length = SDL_PublicSurface->w * SDL_PublicSurface->format->BytesPerPixel;
|
||
|
pixels = SDL_malloc(SDL_PublicSurface->h * length);
|
||
|
if (pixels && SDL_PublicSurface->pixels) {
|
||
|
src = (Uint8*)SDL_PublicSurface->pixels;
|
||
|
dst = (Uint8*)pixels;
|
||
|
for (row = 0; row < SDL_PublicSurface->h; ++row) {
|
||
|
SDL_memcpy(dst, src, length);
|
||
|
src += SDL_PublicSurface->pitch;
|
||
|
dst += length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Do the physical mode switch */
|
||
|
if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
|
||
|
if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
|
||
|
} else {
|
||
|
if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
SDL_PublicSurface->flags |= SDL_FULLSCREEN;
|
||
|
}
|
||
|
|
||
|
/* Recreate the screen surface */
|
||
|
SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
|
||
|
if (!SDL_WindowSurface) {
|
||
|
/* We're totally hosed... */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Center the public surface in the window surface */
|
||
|
SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
|
||
|
SDL_VideoViewport.x = (window_w - SDL_VideoSurface->w)/2;
|
||
|
SDL_VideoViewport.y = (window_h - SDL_VideoSurface->h)/2;
|
||
|
SDL_VideoViewport.w = SDL_VideoSurface->w;
|
||
|
SDL_VideoViewport.h = SDL_VideoSurface->h;
|
||
|
|
||
|
/* Do some shuffling behind the application's back if format changes */
|
||
|
if (SDL_VideoSurface->format->format != SDL_WindowSurface->format->format) {
|
||
|
if (SDL_ShadowSurface) {
|
||
|
if (SDL_ShadowSurface->format->format == SDL_WindowSurface->format->format) {
|
||
|
/* Whee! We don't need a shadow surface anymore! */
|
||
|
SDL_VideoSurface->flags &= ~SDL_DONTFREE;
|
||
|
SDL_FreeSurface(SDL_VideoSurface);
|
||
|
SDL_free(SDL_ShadowSurface->pixels);
|
||
|
SDL_VideoSurface = SDL_ShadowSurface;
|
||
|
SDL_VideoSurface->flags |= SDL_PREALLOC;
|
||
|
SDL_ShadowSurface = NULL;
|
||
|
} else {
|
||
|
/* No problem, just change the video surface format */
|
||
|
SDL_FreeFormat(SDL_VideoSurface->format);
|
||
|
SDL_VideoSurface->format = SDL_WindowSurface->format;
|
||
|
SDL_VideoSurface->format->refcount++;
|
||
|
SDL_InvalidateMap(SDL_ShadowSurface->map);
|
||
|
}
|
||
|
} else {
|
||
|
/* We can make the video surface the shadow surface */
|
||
|
SDL_ShadowSurface = SDL_VideoSurface;
|
||
|
SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
|
||
|
SDL_ShadowSurface->pixels = SDL_malloc(SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
|
||
|
if (!SDL_ShadowSurface->pixels) {
|
||
|
/* Uh oh, we're hosed */
|
||
|
SDL_ShadowSurface = NULL;
|
||
|
return 0;
|
||
|
}
|
||
|
SDL_ShadowSurface->flags &= ~SDL_PREALLOC;
|
||
|
|
||
|
SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
|
||
|
SDL_VideoSurface->flags = SDL_ShadowSurface->flags;
|
||
|
SDL_VideoSurface->flags |= SDL_PREALLOC;
|
||
|
SDL_FreeFormat(SDL_VideoSurface->format);
|
||
|
SDL_VideoSurface->format = SDL_WindowSurface->format;
|
||
|
SDL_VideoSurface->format->refcount++;
|
||
|
SDL_VideoSurface->w = SDL_ShadowSurface->w;
|
||
|
SDL_VideoSurface->h = SDL_ShadowSurface->h;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Update the video surface */
|
||
|
SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
|
||
|
SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
|
||
|
SDL_VideoViewport.y * SDL_VideoSurface->pitch +
|
||
|
SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
|
||
|
SDL_SetClipRect(SDL_VideoSurface, NULL);
|
||
|
|
||
|
/* Copy the old bits back */
|
||
|
if (pixels) {
|
||
|
src = (Uint8*)pixels;
|
||
|
dst = (Uint8*)SDL_PublicSurface->pixels;
|
||
|
for (row = 0; row < SDL_PublicSurface->h; ++row) {
|
||
|
SDL_memcpy(dst, src, length);
|
||
|
src += length;
|
||
|
dst += SDL_PublicSurface->pitch;
|
||
|
}
|
||
|
SDL_Flip(SDL_PublicSurface);
|
||
|
SDL_free(pixels);
|
||
|
}
|
||
|
|
||
|
/* We're done! */
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ClearVideoSurface()
|
||
|
{
|
||
|
if (SDL_ShadowSurface) {
|
||
|
SDL_FillRect(SDL_ShadowSurface, NULL,
|
||
|
SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
|
||
|
}
|
||
|
SDL_FillRect(SDL_WindowSurface, NULL, 0);
|
||
|
SDL_UpdateWindowSurface(SDL_VideoWindow);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
|
||
|
{
|
||
|
int w, h;
|
||
|
|
||
|
/* We can't resize something we don't have... */
|
||
|
if (!SDL_VideoSurface) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* We probably have to recreate the window in fullscreen mode */
|
||
|
if (flags & SDL_FULLSCREEN) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* I don't think there's any change we can gracefully make in flags */
|
||
|
if (flags != SDL_VideoFlags) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* Resize the window */
|
||
|
SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
|
||
|
if (w != width || h != height) {
|
||
|
SDL_SetWindowSize(SDL_VideoWindow, width, height);
|
||
|
}
|
||
|
|
||
|
/* If we're in OpenGL mode, just resize the stub surface and we're done! */
|
||
|
if (flags & SDL_OPENGL) {
|
||
|
SDL_VideoSurface->w = width;
|
||
|
SDL_VideoSurface->h = height;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
|
||
|
if (!SDL_WindowSurface) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (SDL_VideoSurface->format != SDL_WindowSurface->format) {
|
||
|
return -1;
|
||
|
}
|
||
|
SDL_VideoSurface->w = width;
|
||
|
SDL_VideoSurface->h = height;
|
||
|
SDL_VideoSurface->pixels = SDL_WindowSurface->pixels;
|
||
|
SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
|
||
|
SDL_SetClipRect(SDL_VideoSurface, NULL);
|
||
|
|
||
|
if (SDL_ShadowSurface) {
|
||
|
SDL_ShadowSurface->w = width;
|
||
|
SDL_ShadowSurface->h = height;
|
||
|
SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
|
||
|
SDL_ShadowSurface->pixels =
|
||
|
SDL_realloc(SDL_ShadowSurface->pixels,
|
||
|
SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
|
||
|
SDL_SetClipRect(SDL_ShadowSurface, NULL);
|
||
|
SDL_InvalidateMap(SDL_ShadowSurface->map);
|
||
|
} else {
|
||
|
SDL_PublicSurface = SDL_VideoSurface;
|
||
|
}
|
||
|
|
||
|
ClearVideoSurface();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
SDL_CompatEventFilter(void *userdata, SDL_Event * event)
|
||
|
{
|
||
|
SDL_Event fake;
|
||
|
|
||
|
switch (event->type) {
|
||
|
case SDL_WINDOWEVENT:
|
||
|
switch (event->window.event) {
|
||
|
case SDL_WINDOWEVENT_CLOSE:
|
||
|
fake.type = SDL_QUIT;
|
||
|
SDL_PushEvent(&fake);
|
||
|
break;
|
||
|
}
|
||
|
case SDL_TEXTINPUT:
|
||
|
{
|
||
|
/* FIXME: Generate an old style key repeat event if needed */
|
||
|
//printf("TEXTINPUT: '%s'\n", event->text.text);
|
||
|
break;
|
||
|
}
|
||
|
case SDL_MOUSEMOTION:
|
||
|
{
|
||
|
event->motion.x -= SDL_VideoViewport.x;
|
||
|
event->motion.y -= SDL_VideoViewport.y;
|
||
|
break;
|
||
|
}
|
||
|
case SDL_MOUSEBUTTONDOWN:
|
||
|
case SDL_MOUSEBUTTONUP:
|
||
|
{
|
||
|
event->button.x -= SDL_VideoViewport.x;
|
||
|
event->button.y -= SDL_VideoViewport.y;
|
||
|
break;
|
||
|
}
|
||
|
case SDL_MOUSEWHEEL:
|
||
|
{
|
||
|
Uint8 button;
|
||
|
int x, y;
|
||
|
|
||
|
if (event->wheel.y == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SDL_GetMouseState(&x, &y);
|
||
|
|
||
|
if (event->wheel.y > 0) {
|
||
|
button = SDL_BUTTON_WHEELUP;
|
||
|
} else {
|
||
|
button = SDL_BUTTON_WHEELDOWN;
|
||
|
}
|
||
|
|
||
|
fake.button.button = button;
|
||
|
fake.button.x = x;
|
||
|
fake.button.y = y;
|
||
|
fake.button.windowID = event->wheel.windowID;
|
||
|
|
||
|
fake.type = SDL_MOUSEBUTTONDOWN;
|
||
|
fake.button.state = SDL_PRESSED;
|
||
|
SDL_PushEvent(&fake);
|
||
|
|
||
|
fake.type = SDL_MOUSEBUTTONUP;
|
||
|
fake.button.state = SDL_RELEASED;
|
||
|
SDL_PushEvent(&fake);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
|
||
|
{
|
||
|
int display = GetVideoDisplay();
|
||
|
const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
|
||
|
const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
|
||
|
if (window) {
|
||
|
if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
|
||
|
return;
|
||
|
}
|
||
|
if (SDL_strcmp(window, "center") == 0) {
|
||
|
center = window;
|
||
|
}
|
||
|
}
|
||
|
if (center) {
|
||
|
*x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
|
||
|
*y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static SDL_Surface *
|
||
|
SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
|
||
|
{
|
||
|
SDL_DisplayMode desktop_mode;
|
||
|
int display = GetVideoDisplay();
|
||
|
int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
|
||
|
int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
|
||
|
int window_w;
|
||
|
int window_h;
|
||
|
Uint32 window_flags;
|
||
|
Uint32 surface_flags;
|
||
|
|
||
|
if (!initialized_video) {
|
||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
|
||
|
return NULL;
|
||
|
}
|
||
|
initialized_video = 1;
|
||
|
}
|
||
|
|
||
|
SDL_GetDesktopDisplayMode(display, &desktop_mode);
|
||
|
|
||
|
if (width == 0) {
|
||
|
width = desktop_mode.w;
|
||
|
}
|
||
|
if (height == 0) {
|
||
|
height = desktop_mode.h;
|
||
|
}
|
||
|
if (bpp == 0) {
|
||
|
bpp = SDL_BITSPERPIXEL(desktop_mode.format);
|
||
|
}
|
||
|
|
||
|
/* See if we can simply resize the existing window and surface */
|
||
|
if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
|
||
|
return SDL_PublicSurface;
|
||
|
}
|
||
|
|
||
|
/* Destroy existing window */
|
||
|
SDL_PublicSurface = NULL;
|
||
|
if (SDL_ShadowSurface) {
|
||
|
SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
|
||
|
SDL_FreeSurface(SDL_ShadowSurface);
|
||
|
SDL_ShadowSurface = NULL;
|
||
|
}
|
||
|
if (SDL_VideoSurface) {
|
||
|
SDL_VideoSurface->flags &= ~SDL_DONTFREE;
|
||
|
SDL_FreeSurface(SDL_VideoSurface);
|
||
|
SDL_VideoSurface = NULL;
|
||
|
}
|
||
|
if (SDL_VideoContext) {
|
||
|
/* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
|
||
|
SDL_GL_DeleteContext(SDL_VideoContext);
|
||
|
SDL_VideoContext = NULL;
|
||
|
}
|
||
|
if (SDL_VideoWindow) {
|
||
|
SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
|
||
|
SDL_DestroyWindow(SDL_VideoWindow);
|
||
|
}
|
||
|
|
||
|
/* Set up the event filter */
|
||
|
if (!SDL_GetEventFilter(NULL, NULL)) {
|
||
|
SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
|
||
|
}
|
||
|
|
||
|
/* Create a new window */
|
||
|
window_flags = SDL_WINDOW_SHOWN;
|
||
|
if (flags & SDL_FULLSCREEN) {
|
||
|
window_flags |= SDL_WINDOW_FULLSCREEN;
|
||
|
}
|
||
|
if (flags & SDL_OPENGL) {
|
||
|
window_flags |= SDL_WINDOW_OPENGL;
|
||
|
}
|
||
|
if (flags & SDL_RESIZABLE) {
|
||
|
window_flags |= SDL_WINDOW_RESIZABLE;
|
||
|
}
|
||
|
if (flags & SDL_NOFRAME) {
|
||
|
window_flags |= SDL_WINDOW_BORDERLESS;
|
||
|
}
|
||
|
GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
|
||
|
SDL_VideoWindow =
|
||
|
SDL_CreateWindow(wm_title, window_x, window_y, width, height,
|
||
|
window_flags);
|
||
|
if (!SDL_VideoWindow) {
|
||
|
return NULL;
|
||
|
}
|
||
|
SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
|
||
|
|
||
|
window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
|
||
|
surface_flags = 0;
|
||
|
if (window_flags & SDL_WINDOW_FULLSCREEN) {
|
||
|
surface_flags |= SDL_FULLSCREEN;
|
||
|
}
|
||
|
if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
|
||
|
surface_flags |= SDL_OPENGL;
|
||
|
}
|
||
|
if (window_flags & SDL_WINDOW_RESIZABLE) {
|
||
|
surface_flags |= SDL_RESIZABLE;
|
||
|
}
|
||
|
if (window_flags & SDL_WINDOW_BORDERLESS) {
|
||
|
surface_flags |= SDL_NOFRAME;
|
||
|
}
|
||
|
|
||
|
SDL_VideoFlags = flags;
|
||
|
|
||
|
/* If we're in OpenGL mode, just create a stub surface and we're done! */
|
||
|
if (flags & SDL_OPENGL) {
|
||
|
SDL_VideoContext = (SDL_GLContext *)SDL_GL_CreateContext(SDL_VideoWindow);
|
||
|
if (!SDL_VideoContext) {
|
||
|
return NULL;
|
||
|
}
|
||
|
if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
|
||
|
return NULL;
|
||
|
}
|
||
|
SDL_VideoSurface =
|
||
|
SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
|
||
|
if (!SDL_VideoSurface) {
|
||
|
return NULL;
|
||
|
}
|
||
|
SDL_VideoSurface->flags |= surface_flags;
|
||
|
SDL_PublicSurface = SDL_VideoSurface;
|
||
|
return SDL_PublicSurface;
|
||
|
}
|
||
|
|
||
|
/* Create the screen surface */
|
||
|
SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
|
||
|
if (!SDL_WindowSurface) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Center the public surface in the window surface */
|
||
|
SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
|
||
|
SDL_VideoViewport.x = (window_w - width)/2;
|
||
|
SDL_VideoViewport.y = (window_h - height)/2;
|
||
|
SDL_VideoViewport.w = width;
|
||
|
SDL_VideoViewport.h = height;
|
||
|
|
||
|
SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
|
||
|
SDL_VideoSurface->flags |= surface_flags;
|
||
|
SDL_VideoSurface->flags |= SDL_DONTFREE;
|
||
|
SDL_FreeFormat(SDL_VideoSurface->format);
|
||
|
SDL_VideoSurface->format = SDL_WindowSurface->format;
|
||
|
SDL_VideoSurface->format->refcount++;
|
||
|
SDL_VideoSurface->w = width;
|
||
|
SDL_VideoSurface->h = height;
|
||
|
SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
|
||
|
SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
|
||
|
SDL_VideoViewport.y * SDL_VideoSurface->pitch +
|
||
|
SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
|
||
|
SDL_SetClipRect(SDL_VideoSurface, NULL);
|
||
|
|
||
|
/* Create a shadow surface if necessary */
|
||
|
if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
|
||
|
&& !(flags & SDL_ANYFORMAT)) {
|
||
|
SDL_ShadowSurface =
|
||
|
SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
|
||
|
if (!SDL_ShadowSurface) {
|
||
|
return NULL;
|
||
|
}
|
||
|
SDL_ShadowSurface->flags |= surface_flags;
|
||
|
SDL_ShadowSurface->flags |= SDL_DONTFREE;
|
||
|
|
||
|
/* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
|
||
|
if (SDL_ShadowSurface->format->palette) {
|
||
|
SDL_ShadowSurface->flags |= SDL_HWPALETTE;
|
||
|
//TODO SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
|
||
|
// SDL_ShadowSurface->format->BitsPerPixel);
|
||
|
}
|
||
|
SDL_FillRect(SDL_ShadowSurface, NULL,
|
||
|
SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
|
||
|
}
|
||
|
SDL_PublicSurface =
|
||
|
(SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
|
||
|
|
||
|
ClearVideoSurface();
|
||
|
|
||
|
/* We're finally done! */
|
||
|
return SDL_PublicSurface;
|
||
|
}
|