From 0e4dcc23d9d4aaa70c2fcf12a3cf79c291b01c82 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 1 May 2006 06:58:33 +0000 Subject: [PATCH] glSDL support --- Makefile.dc | 1 + configure.in | 20 + include/SDL_config.h.in | 1 + include/SDL_config_amiga.h | 1 + include/SDL_config_dreamcast.h | 1 + include/SDL_config_macos.h | 1 + include/SDL_config_macosx.h | 1 + include/SDL_config_win32.h | 3 + include/SDL_video.h | 2 +- src/video/SDL_blit.c | 2 +- src/video/SDL_glfuncs.h | 18 +- src/video/SDL_sysvideo.h | 5 +- src/video/SDL_video.c | 25 +- src/video/bwindow/SDL_BWin.h | 2 +- src/video/bwindow/SDL_sysvideo.cc | 6 +- src/video/cybergfx/SDL_cgximage.c | 2 +- src/video/cybergfx/SDL_cgxvideo.c | 18 +- src/video/dc/SDL_dcvideo.c | 8 +- src/video/gem/SDL_gemvideo.c | 4 +- src/video/glsdl/SDL_glsdl.c | 2573 +++++++++++++++++++++++++++ src/video/glsdl/SDL_glsdl.h | 38 + src/video/maccommon/SDL_macevents.c | 2 +- src/video/macdsp/SDL_dspvideo.c | 8 +- src/video/macrom/SDL_romvideo.c | 4 +- src/video/photon/SDL_ph_image.c | 6 +- src/video/photon/SDL_ph_modes.c | 4 +- src/video/photon/SDL_ph_mouse.c | 4 +- src/video/photon/SDL_ph_video.c | 4 +- src/video/qtopia/SDL_sysvideo.cc | 2 +- src/video/quartz/SDL_QuartzVideo.m | 16 +- src/video/quartz/SDL_QuartzWM.m | 4 +- src/video/quartz/SDL_QuartzWindow.m | 8 +- src/video/wincommon/SDL_lowvideo.h | 14 +- src/video/wincommon/SDL_sysevents.c | 2 +- src/video/windib/SDL_dibvideo.c | 10 +- src/video/windx5/SDL_dx5events.c | 2 +- src/video/windx5/SDL_dx5video.c | 16 +- src/video/x11/SDL_x11events.c | 2 +- src/video/x11/SDL_x11image.c | 2 +- src/video/x11/SDL_x11modes.c | 4 +- src/video/x11/SDL_x11video.c | 16 +- src/video/xbios/SDL_xbios.c | 6 +- test/testblitspeed.c | 1 - 43 files changed, 2757 insertions(+), 112 deletions(-) create mode 100644 src/video/glsdl/SDL_glsdl.c create mode 100644 src/video/glsdl/SDL_glsdl.h diff --git a/Makefile.dc b/Makefile.dc index 553f0ebb0..e225825c8 100644 --- a/Makefile.dc +++ b/Makefile.dc @@ -55,6 +55,7 @@ SRCS = \ src/video/dummy/SDL_nullevents.c \ src/video/dummy/SDL_nullmouse.c \ src/video/dummy/SDL_nullvideo.c \ + src/video/glsdl/SDL_glsdl.c \ src/video/SDL_blit.c \ src/video/SDL_blit_0.c \ src/video/SDL_blit_1.c \ diff --git a/configure.in b/configure.in index 2cc19f822..dbb926c45 100644 --- a/configure.in +++ b/configure.in @@ -1459,6 +1459,20 @@ CheckMacGL() fi } +dnl Find glSDL +CheckglSDL() +{ + AC_ARG_ENABLE(video-glsdl, +[ --enable-video-glsdl use glSDL video driver [default=yes]], + , enable_video_glsdl=yes) + AC_MSG_CHECKING(for glSDL support) + AC_MSG_RESULT($video_opengl) + if test x$video_opengl = xyes -a x$enable_video_glsdl = xyes; then + AC_DEFINE(SDL_VIDEO_DRIVER_GLSDL) + SOURCES="$SOURCES $srcdir/src/video/glsdl/*.c" + fi +} + dnl Check for Mesa offscreen rendering CheckAtariOSMesa() { @@ -2080,6 +2094,7 @@ case "$host" in CheckQtopia CheckPicoGUI CheckOpenGLX11 + CheckglSDL CheckInputEvents CheckTslib CheckUSBHID @@ -2178,6 +2193,7 @@ case "$host" in CheckPHOTON CheckX11 CheckOpenGLX11 + CheckglSDL CheckPTHREAD # Set up files for the audio library if test x$enable_audio = xyes; then @@ -2215,6 +2231,7 @@ case "$host" in CheckDummyAudio CheckWIN32 CheckWIN32GL + CheckglSDL CheckDIRECTX CheckNASM # Set up files for the audio library @@ -2279,6 +2296,7 @@ case "$host" in CheckNASM CheckBWINDOW CheckBeGL + CheckglSDL # Set up files for the audio library if test x$enable_audio = xyes; then AC_DEFINE(SDL_AUDIO_DRIVER_BAUDIO) @@ -2356,6 +2374,7 @@ case "$host" in CheckX11 CheckMacGL CheckOpenGLX11 + CheckglSDL CheckPTHREAD CheckAltivec @@ -2417,6 +2436,7 @@ case "$host" in CheckAtariAudio CheckAtariLdg CheckAtariOSMesa + CheckglSDL CheckPTH # Set up files for the audio library if test x$enable_threads = xyes -a x$enable_pth = xyes; then diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index e556b2094..dafd52a18 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -262,6 +262,7 @@ #undef SDL_VIDEO_DRIVER_GAPI #undef SDL_VIDEO_DRIVER_GEM #undef SDL_VIDEO_DRIVER_GGI +#undef SDL_VIDEO_DRIVER_GLSDL #undef SDL_VIDEO_DRIVER_IPOD #undef SDL_VIDEO_DRIVER_NANOX #undef SDL_VIDEO_DRIVER_OS2FS diff --git a/include/SDL_config_amiga.h b/include/SDL_config_amiga.h index 23e086192..8daef6827 100644 --- a/include/SDL_config_amiga.h +++ b/include/SDL_config_amiga.h @@ -73,6 +73,7 @@ /* Enable various video drivers */ #define SDL_VIDEO_DRIVER_CYBERGRAPHICS 1 #define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_GLSDL 1 /* Enable OpenGL support */ #define SDL_VIDEO_OPENGL 1 diff --git a/include/SDL_config_dreamcast.h b/include/SDL_config_dreamcast.h index 9cbeea316..cf76dabfb 100644 --- a/include/SDL_config_dreamcast.h +++ b/include/SDL_config_dreamcast.h @@ -102,5 +102,6 @@ typedef unsigned long uintptr_t; /* Enable various video drivers */ #define SDL_VIDEO_DRIVER_DC 1 #define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_GLSDL 1 #endif /* _SDL_config_dreamcast_h */ diff --git a/include/SDL_config_macos.h b/include/SDL_config_macos.h index 261fc828f..b1404cbe6 100644 --- a/include/SDL_config_macos.h +++ b/include/SDL_config_macos.h @@ -90,6 +90,7 @@ typedef unsigned long uintptr_t; /* Enable various video drivers */ #define SDL_VIDEO_DRIVER_DUMMY 1 #define SDL_VIDEO_DRIVER_DRAWSPROCKET 1 +#define SDL_VIDEO_DRIVER_GLSDL 1 #define SDL_VIDEO_DRIVER_TOOLBOX 1 /* Enable OpenGL support */ diff --git a/include/SDL_config_macosx.h b/include/SDL_config_macosx.h index 5fc332fb1..05335a1d4 100644 --- a/include/SDL_config_macosx.h +++ b/include/SDL_config_macosx.h @@ -116,6 +116,7 @@ /* Enable various video drivers */ #define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_GLSDL 1 #define SDL_VIDEO_DRIVER_QUARTZ 1 /* Enable OpenGL support */ diff --git a/include/SDL_config_win32.h b/include/SDL_config_win32.h index 3f02fcca3..806a8039a 100644 --- a/include/SDL_config_win32.h +++ b/include/SDL_config_win32.h @@ -155,6 +155,9 @@ typedef unsigned int uintptr_t; #define SDL_VIDEO_DRIVER_DDRAW 1 #endif #define SDL_VIDEO_DRIVER_DUMMY 1 +#ifndef _WIN32_WCE +#define SDL_VIDEO_DRIVER_GLSDL 1 +#endif #define SDL_VIDEO_DRIVER_WINDIB 1 /* Enable OpenGL support */ diff --git a/include/SDL_video.h b/include/SDL_video.h index b6dcbbfc5..a39e30abd 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -124,7 +124,7 @@ typedef struct SDL_Surface { #define SDL_DOUBLEBUF 0x40000000 /* Set up double-buffered video mode */ #define SDL_FULLSCREEN 0x80000000 /* Surface is a full screen display */ #define SDL_OPENGL 0x00000002 /* Create an OpenGL rendering context */ -#define SDL_OPENGLBLIT_OBSOLETE 0x0000000A /* Obsolete, do not use! */ +#define SDL_INTERNALOPENGL 0x00000008 /* SDL uses OpenGL internally for this window */ #define SDL_RESIZABLE 0x00000010 /* This video mode may be resized */ #define SDL_NOFRAME 0x00000020 /* No window caption or edge frame */ /* Used internally (read-only) */ diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index d3fb7783e..73922ae01 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -281,7 +281,7 @@ int SDL_CalculateBlit(SDL_Surface *surface) video->CheckHWBlit(this, surface, surface->map->dst); } } - + /* Get the blit function index, based on surface mode */ /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ blit_index = 0; diff --git a/src/video/SDL_glfuncs.h b/src/video/SDL_glfuncs.h index fb2d96487..e423f1be2 100644 --- a/src/video/SDL_glfuncs.h +++ b/src/video/SDL_glfuncs.h @@ -30,7 +30,7 @@ SDL_PROC_UNUSED(void,glColor3i,(GLint,GLint,GLint)) SDL_PROC_UNUSED(void,glColor3iv,(const GLint*)) SDL_PROC_UNUSED(void,glColor3s,(GLshort,GLshort,GLshort)) SDL_PROC_UNUSED(void,glColor3sv,(const GLshort*)) -SDL_PROC_UNUSED(void,glColor3ub,(GLubyte,GLubyte,GLubyte)) +SDL_PROC(void,glColor3ub,(GLubyte,GLubyte,GLubyte)) SDL_PROC_UNUSED(void,glColor3ubv,(const GLubyte*)) SDL_PROC_UNUSED(void,glColor3ui,(GLuint,GLuint,GLuint)) SDL_PROC_UNUSED(void,glColor3uiv,(const GLuint*)) @@ -46,7 +46,7 @@ SDL_PROC_UNUSED(void,glColor4i,(GLint,GLint,GLint,GLint)) SDL_PROC_UNUSED(void,glColor4iv,(const GLint*)) SDL_PROC_UNUSED(void,glColor4s,(GLshort,GLshort,GLshort,GLshort)) SDL_PROC_UNUSED(void,glColor4sv,(const GLshort*)) -SDL_PROC_UNUSED(void,glColor4ub,(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)) +SDL_PROC(void,glColor4ub,(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)) SDL_PROC_UNUSED(void,glColor4ubv,(const GLubyte *v)) SDL_PROC_UNUSED(void,glColor4ui,(GLuint red, GLuint green, GLuint blue, GLuint alpha)) SDL_PROC_UNUSED(void,glColor4uiv,(const GLuint *v)) @@ -62,14 +62,14 @@ SDL_PROC_UNUSED(void,glCopyTexSubImage1D,(GLenum target, GLint level, GLint xoff SDL_PROC_UNUSED(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)) SDL_PROC_UNUSED(void,glCullFace,(GLenum mode)) SDL_PROC_UNUSED(void,glDeleteLists,(GLuint list, GLsizei range)) -SDL_PROC_UNUSED(void,glDeleteTextures,(GLsizei n, const GLuint *textures)) +SDL_PROC(void,glDeleteTextures,(GLsizei n, const GLuint *textures)) SDL_PROC_UNUSED(void,glDepthFunc,(GLenum func)) SDL_PROC_UNUSED(void,glDepthMask,(GLboolean flag)) SDL_PROC_UNUSED(void,glDepthRange,(GLclampd zNear, GLclampd zFar)) SDL_PROC(void,glDisable,(GLenum cap)) SDL_PROC_UNUSED(void,glDisableClientState,(GLenum array)) SDL_PROC_UNUSED(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count)) -SDL_PROC_UNUSED(void,glDrawBuffer,(GLenum mode)) +SDL_PROC(void,glDrawBuffer,(GLenum mode)) SDL_PROC_UNUSED(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)) SDL_PROC_UNUSED(void,glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) SDL_PROC_UNUSED(void,glEdgeFlag,(GLboolean flag)) @@ -92,7 +92,7 @@ SDL_PROC_UNUSED(void,glEvalMesh2,(GLenum mode, GLint i1, GLint i2, GLint j1, GLi SDL_PROC_UNUSED(void,glEvalPoint1,(GLint i)) SDL_PROC_UNUSED(void,glEvalPoint2,(GLint i, GLint j)) SDL_PROC_UNUSED(void,glFeedbackBuffer,(GLsizei size, GLenum type, GLfloat *buffer)) -SDL_PROC_UNUSED(void,glFinish,(void)) +SDL_PROC(void,glFinish,(void)) SDL_PROC(void,glFlush,(void)) SDL_PROC_UNUSED(void,glFogf,(GLenum pname, GLfloat param)) SDL_PROC_UNUSED(void,glFogfv,(GLenum pname, const GLfloat *params)) @@ -105,9 +105,9 @@ SDL_PROC(void,glGenTextures,(GLsizei n, GLuint *textures)) SDL_PROC_UNUSED(void,glGetBooleanv,(GLenum pname, GLboolean *params)) SDL_PROC_UNUSED(void,glGetClipPlane,(GLenum plane, GLdouble *equation)) SDL_PROC_UNUSED(void,glGetDoublev,(GLenum pname, GLdouble *params)) -SDL_PROC_UNUSED(GLenum,glGetError,(void)) +SDL_PROC(GLenum,glGetError,(void)) SDL_PROC_UNUSED(void,glGetFloatv,(GLenum pname, GLfloat *params)) -SDL_PROC_UNUSED(void,glGetIntegerv,(GLenum pname, GLint *params)) +SDL_PROC(void,glGetIntegerv,(GLenum pname, GLint *params)) SDL_PROC_UNUSED(void,glGetLightfv,(GLenum light, GLenum pname, GLfloat *params)) SDL_PROC_UNUSED(void,glGetLightiv,(GLenum light, GLenum pname, GLint *params)) SDL_PROC_UNUSED(void,glGetMapdv,(GLenum target, GLenum query, GLdouble *v)) @@ -240,7 +240,7 @@ SDL_PROC_UNUSED(void,glRasterPos4iv,(const GLint *v)) SDL_PROC_UNUSED(void,glRasterPos4s,(GLshort x, GLshort y, GLshort z, GLshort w)) SDL_PROC_UNUSED(void,glRasterPos4sv,(const GLshort *v)) SDL_PROC_UNUSED(void,glReadBuffer,(GLenum mode)) -SDL_PROC_UNUSED(void,glReadPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)) +SDL_PROC(void,glReadPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)) SDL_PROC_UNUSED(void,glRectd,(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)) SDL_PROC_UNUSED(void,glRectdv,(const GLdouble *v1, const GLdouble *v2)) SDL_PROC_UNUSED(void,glRectf,(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)) @@ -311,7 +311,7 @@ SDL_PROC(void,glTexParameteri,(GLenum target, GLenum pname, GLint param)) SDL_PROC_UNUSED(void,glTexParameteriv,(GLenum target, GLenum pname, const GLint *params)) SDL_PROC_UNUSED(void,glTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels)) SDL_PROC(void,glTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) -SDL_PROC_UNUSED(void,glTranslated,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC(void,glTranslated,(GLdouble x, GLdouble y, GLdouble z)) SDL_PROC_UNUSED(void,glTranslatef,(GLfloat x, GLfloat y, GLfloat z)) SDL_PROC_UNUSED(void,glVertex2d,(GLdouble x, GLdouble y)) SDL_PROC_UNUSED(void,glVertex2dv,(const GLdouble *v)) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index e1568a7db..3714ad172 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -119,7 +119,7 @@ struct SDL_VideoDevice { /* The pixel format used when SDL_CreateRGBSurface creates SDL_HWSURFACEs with alpha */ SDL_PixelFormat* displayformatalphapixel; - + /* Allocates a surface in video memory */ int (*AllocHWSurface)(_THIS, SDL_Surface *surface); @@ -407,6 +407,9 @@ extern VideoBootStrap AALIB_bootstrap; #if SDL_VIDEO_DRIVER_DUMMY extern VideoBootStrap DUMMY_bootstrap; #endif +#if SDL_VIDEO_DRIVER_GLSDL +extern VideoBootStrap glSDL_bootstrap; +#endif /* This is the current video device */ extern SDL_VideoDevice *current_video; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 07eb1230b..eae847a09 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -122,6 +122,9 @@ static VideoBootStrap *bootstrap[] = { #endif #if SDL_VIDEO_DRIVER_DUMMY &DUMMY_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GLSDL + &glSDL_bootstrap, #endif NULL }; @@ -575,12 +578,6 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) int is_opengl; SDL_GrabMode saved_grab; - /* Handle obsolete flags */ - if ( (flags & SDL_OPENGLBLIT_OBSOLETE) == SDL_OPENGLBLIT_OBSOLETE ) { - SDL_SetError("SDL_OPENGLBLIT is no longer supported"); - return(NULL); - } - /* Start up the video driver, if necessary.. WARNING: This is the only function protected this way! */ @@ -613,8 +610,12 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) } /* Check the requested flags */ - /* There's no palette in > 8 bits-per-pixel mode */ + if ( flags & SDL_INTERNALOPENGL ) { + SDL_SetError("SDL_INTERNALOPENGL is for internal use only"); + return(NULL); + } if ( video_bpp > 8 ) { + /* There's no palette in > 8 bits-per-pixel mode */ flags &= ~SDL_HWPALETTE; } #if 0 @@ -632,6 +633,8 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) if ( is_opengl ) { /* These flags are for 2D video modes only */ flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF); + /* This flag tells the backends to treat the surface accordingly */ + flags |= SDL_INTERNALOPENGL; } /* Reset the keyboard here so event callbacks can run */ @@ -674,7 +677,7 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) #endif /* Sam - If we asked for OpenGL mode, and didn't get it, fail */ - if ( is_opengl && !(mode->flags & SDL_OPENGL) ) { + if ( is_opengl && !(mode->flags & SDL_INTERNALOPENGL) ) { mode = NULL; SDL_SetError("OpenGL not available"); } @@ -752,7 +755,7 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) #if SDL_VIDEO_OPENGL /* Load GL symbols (before MakeCurrent, where we need glGetString). */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { #if defined(__QNXNTO__) && (_NTO_VERSION < 630) #define __SDL_NOGETPROCADDR__ @@ -779,7 +782,7 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) #endif /* SDL_VIDEO_OPENGL */ /* If we're running OpenGL, make the context current */ - if ( (video->screen->flags & SDL_OPENGL) && + if ( (video->screen->flags & SDL_INTERNALOPENGL) && video->GL_MakeCurrent ) { if ( video->GL_MakeCurrent(this) < 0 ) { return(NULL); @@ -1431,7 +1434,7 @@ void SDL_GL_SwapBuffers(void) SDL_VideoDevice *video = current_video; SDL_VideoDevice *this = current_video; - if ( video->screen->flags & SDL_OPENGL ) { + if ( video->screen->flags & SDL_INTERNALOPENGL ) { video->GL_SwapBuffers(this); } else { SDL_SetError("OpenGL video mode has not been set"); diff --git a/src/video/bwindow/SDL_BWin.h b/src/video/bwindow/SDL_BWin.h index a6d3ef8d9..a927b3598 100644 --- a/src/video/bwindow/SDL_BWin.h +++ b/src/video/bwindow/SDL_BWin.h @@ -219,7 +219,7 @@ class SDL_BWin : public BDirectWindow retval = 0; Lock(); - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { #if SDL_VIDEO_OPENGL if ( SDL_GLView == NULL ) { SDL_GLView = new BGLView(Bounds(), "SDL GLView", diff --git a/src/video/bwindow/SDL_sysvideo.cc b/src/video/bwindow/SDL_sysvideo.cc index 18e305ad4..36f08e722 100644 --- a/src/video/bwindow/SDL_sysvideo.cc +++ b/src/video/bwindow/SDL_sysvideo.cc @@ -525,7 +525,7 @@ SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, current->flags |= SDL_NOFRAME; SDL_Win->SetLook(B_NO_BORDER_WINDOW_LOOK); } else { - if ( (flags & SDL_RESIZABLE) && !(flags & SDL_OPENGL) ) { + if ( (flags & SDL_RESIZABLE) && !(flags & SDL_INTERNALOPENGL) ) { current->flags |= SDL_RESIZABLE; /* We don't want opaque resizing (TM). :-) */ SDL_Win->SetFlags(B_OUTLINE_RESIZE); @@ -534,8 +534,8 @@ SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, } } - if ( flags & SDL_OPENGL ) { - current->flags |= SDL_OPENGL; + if ( flags & SDL_INTERNALOPENGL ) { + current->flags |= SDL_INTERNALOPENGL; current->pitch = 0; current->pixels = NULL; _this->UpdateRects = NULL; diff --git a/src/video/cybergfx/SDL_cgximage.c b/src/video/cybergfx/SDL_cgximage.c index 3e8938efe..862d1a2f4 100644 --- a/src/video/cybergfx/SDL_cgximage.c +++ b/src/video/cybergfx/SDL_cgximage.c @@ -135,7 +135,7 @@ int CGX_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) CGX_DestroyImage(this, screen); - if ( flags & SDL_OPENGL ) { /* No image when using GL */ + if ( flags & SDL_INTERNALOPENGL ) { /* No image when using GL */ retval = 0; } else { retval = CGX_SetupImage(this, screen); diff --git a/src/video/cybergfx/SDL_cgxvideo.c b/src/video/cybergfx/SDL_cgxvideo.c index a723dc274..a04fe4ad7 100644 --- a/src/video/cybergfx/SDL_cgxvideo.c +++ b/src/video/cybergfx/SDL_cgxvideo.c @@ -598,7 +598,7 @@ void CGX_DestroyWindow(_THIS, SDL_Surface *screen) /* Clean up OpenGL */ if ( screen ) { - screen->flags &= ~SDL_OPENGL; + screen->flags &= ~SDL_INTERNALOPENGL; } if ( screen && (screen->flags & SDL_FULLSCREEN) ) { @@ -687,7 +687,7 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, /* questo l'ho spostato nell'apertura dello schermo, in quanto su Amiga le finestre hanno il pixel mode degli schermi. */ - /*if ( flags & SDL_OPENGL ) { + /*if ( flags & SDL_INTERNALOPENGL ) { SDL_SetError("OpenGL not supported by the Amiga SDL!"); return -1; } @@ -800,7 +800,7 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, { /* Create GimmeZeroZero window when OpenGL is used */ unsigned long gzz = FALSE; - if( flags & SDL_OPENGL ) { + if( flags & SDL_INTERNALOPENGL ) { gzz = TRUE; } @@ -840,7 +840,7 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, /* Set our colormaps when not setting a GL mode */ /* - if ( ! (flags & SDL_OPENGL) ) { + if ( ! (flags & SDL_INTERNALOPENGL) ) { XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); } */ @@ -861,18 +861,18 @@ int CGX_CreateWindow(_THIS, SDL_Surface *screen, CGX_ResizeImage(this, screen, flags); /* Make OpenGL Context if needed*/ - if(flags & SDL_OPENGL) { + if(flags & SDL_INTERNALOPENGL) { if(this->gl_data->gl_active == 0) { if(CGX_GL_Init(this) < 0) return -1; else - screen->flags |= SDL_OPENGL; + screen->flags |= SDL_INTERNALOPENGL; } else { if(CGX_GL_Update(this) < 0) return -1; else - screen->flags |= SDL_OPENGL; + screen->flags |= SDL_INTERNALOPENGL; } } } @@ -1066,7 +1066,7 @@ static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, /* Set up the X11 window */ saved_flags = current->flags; - if (SDL_Window && (saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL) + if (SDL_Window && (saved_flags&SDL_INTERNALOPENGL) == (flags&SDL_INTERNALOPENGL) && bpp == current->format->BitsPerPixel && !needcreate) { if (CGX_ResizeWindow(this, current, width, height, flags) < 0) { current = NULL; @@ -1082,7 +1082,7 @@ static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, #if 0 /* Set up the new mode framebuffer */ if ( ((current->w != width) || (current->h != height)) || - ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { + ((saved_flags&SDL_INTERNALOPENGL) != (flags&SDL_INTERNALOPENGL)) ) { current->w = width; current->h = height; current->pitch = SDL_CalculatePitch(current); diff --git a/src/video/dc/SDL_dcvideo.c b/src/video/dc/SDL_dcvideo.c index 3d884c339..813e0f6ae 100644 --- a/src/video/dc/SDL_dcvideo.c +++ b/src/video/dc/SDL_dcvideo.c @@ -167,7 +167,7 @@ SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) case 16: return &vid_modes; case 32: - if (!(flags & SDL_OPENGL)) + if (!(flags & SDL_INTERNALOPENGL)) return &vid_modes; default: return NULL; @@ -220,7 +220,7 @@ SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, Gmask = 0x0000ff00; Bmask = 0x000000ff; #if SDL_VIDEO_OPENGL - if (!(flags & SDL_OPENGL)) + if (!(flags & SDL_INTERNALOPENGL)) #endif break; default: @@ -252,9 +252,9 @@ SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, current->pixels = vram_s; #if SDL_VIDEO_OPENGL - if (flags & SDL_OPENGL) { + if (flags & SDL_INTERNALOPENGL) { this->gl_config.driver_loaded = 1; - current->flags = SDL_FULLSCREEN | SDL_OPENGL; + current->flags = SDL_FULLSCREEN | SDL_INTERNALOPENGL; current->pixels = NULL; pvr_inited = 1; pvr_init(¶ms); diff --git a/src/video/gem/SDL_gemvideo.c b/src/video/gem/SDL_gemvideo.c index d517f5432..7e49d8181 100644 --- a/src/video/gem/SDL_gemvideo.c +++ b/src/video/gem/SDL_gemvideo.c @@ -804,14 +804,14 @@ SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, } #if SDL_VIDEO_OPENGL - if (flags & SDL_OPENGL) { + if (flags & SDL_INTERNALOPENGL) { if (!SDL_AtariGL_Init(this, current)) { GEM_FreeBuffers(this); SDL_SetError("Can not create OpenGL context"); return NULL; } - modeflags |= SDL_OPENGL; + modeflags |= SDL_INTERNALOPENGL; } #endif diff --git a/src/video/glsdl/SDL_glsdl.c b/src/video/glsdl/SDL_glsdl.c new file mode 100644 index 000000000..b30d93fbb --- /dev/null +++ b/src/video/glsdl/SDL_glsdl.c @@ -0,0 +1,2573 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * glSDL "SDL-over-OpenGL" video driver implemented by + * David Olofson and + * Stephane Marchesin + */ +#include + +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" + +#include "SDL_glsdl.h" + +#undef DEBUG_GLSDL +#undef DEBUG_GLSDL_CHOP +#define FAKE_MAXTEXSIZE 256 +#undef GLSDL_GRAPHICAL_DEBUG + +/* Initialization/Query functions */ + +/* Hardware surface functions */ +static int glSDL_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static int glSDL_AllocHWSurface(_THIS, SDL_Surface *surface); +static int glSDL_LockHWSurface(_THIS, SDL_Surface *surface); +static int glSDL_FlipHWSurface(_THIS, SDL_Surface *surface); +static void glSDL_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void glSDL_FreeHWSurface(_THIS, SDL_Surface *surface); +static int glSDL_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); +static int glSDL_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int glSDL_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int glSDL_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha); +static int glSDL_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **glSDL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static void glSDL_VideoQuit(_THIS); +static void glSDL_UpdateRects(_THIS, int numrects, SDL_Rect *rects); +static SDL_Surface* glSDL_SetVideoMode(_THIS, SDL_Surface *current,int width, int height, int bpp, Uint32 flags); + +#define IS_GLSDL_SURFACE(s) ((s) && glSDL_GetTexInfo(s)) + +#define LOGIC_W(s) ( IS_GLSDL_SURFACE(this,s) ? TEXINFO(s)->lw : (s)->w ) +#define LOGIC_H(s) ( IS_GLSDL_SURFACE(this,s) ? TEXINFO(s)->lh : (s)->h ) + +#define GLSDL_NOTEX (~0) + +/* + * Special version for glSDL, which ignores the fake SDL_HWSURFACE + * flags, so we don't have SDL calling us back whenever we want to + * do some internal blitting... + */ +static void glSDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_BlitInfo info; + + if(srcrect) + if(!srcrect->w || !srcrect->h) + return; + + /* Check to make sure the blit mapping is valid */ + if ( (src->map->dst != dst) || + (src->map->dst->format_version != + src->map->format_version) ) + if ( SDL_MapSurface(src, dst) < 0 ) + return; + + /* Set up the blit information */ + if(srcrect) + { + info.s_pixels = (Uint8 *) src->pixels + + (Uint16) srcrect->y * src->pitch + + (Uint16) srcrect->x * src->format->BytesPerPixel; + info.s_width = srcrect->w; + info.s_height = srcrect->h; + } + else + { + info.s_pixels = (Uint8 *) src->pixels; + info.s_width = src->w; + info.s_height = src->h; + } + info.s_skip = src->pitch - info.s_width * src->format->BytesPerPixel; + if(dstrect) + { + info.d_pixels = (Uint8 *) dst->pixels + + (Uint16) dstrect->y * dst->pitch + + (Uint16) dstrect->x * dst->format->BytesPerPixel; + /* + * NOTE: SDL_SoftBlit() uses the 'dstrect' for this! + * This version is more like SDL_BlitSurface(). + */ + info.d_width = srcrect->w; + info.d_height = srcrect->h; + } + else + { + info.d_pixels = (Uint8 *) dst->pixels; + info.d_width = dst->w; + info.d_height = dst->h; + } + info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel; + info.aux_data = src->map->sw_data->aux_data; + info.src = src->format; + info.table = src->map->table; + info.dst = dst->format; + + src->map->sw_data->blit(&info); +} + + +/* + * Another special version. Doesn't lock/unlock, and doesn't mess + * with flags and stuff. It just converts the surface, period. + * Does not convert into palletized formats. + */ +static SDL_Surface *glSDL_ConvertSurface (SDL_Surface *surface, + SDL_PixelFormat *format, Uint32 flags) +{ + SDL_Surface *convert; + Uint32 colorkey = 0; + Uint8 alpha = 0; + Uint32 surface_flags; + SDL_Rect bounds; + + /* Create a new surface with the desired format */ + convert = SDL_CreateRGBSurface(flags, + surface->w, surface->h, format->BitsPerPixel, + format->Rmask, format->Gmask, format->Bmask, format->Amask); + if ( convert == NULL ) { + return(NULL); + } + + /* Save the original surface color key and alpha */ + surface_flags = surface->flags; + if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + /* Convert colourkeyed surfaces to RGBA if requested */ + if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY + && format->Amask) { + surface_flags &= ~SDL_SRCCOLORKEY; + } else { + colorkey = surface->format->colorkey; + SDL_SetColorKey(surface, 0, 0); + } + } + if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + /* Copy over the alpha channel to RGBA if requested */ + if ( format->Amask ) { + surface->flags &= ~SDL_SRCALPHA; + } else { + alpha = surface->format->alpha; + SDL_SetAlpha(surface, 0, 0); + } + } + + /* Copy over the image data */ + bounds.x = 0; + bounds.y = 0; + bounds.w = surface->w; + bounds.h = surface->h; + glSDL_SoftBlit(surface, &bounds, convert, &bounds); + + /* Clean up the original surface, and update converted surface */ + if ( convert != NULL ) { + SDL_SetClipRect(convert, &surface->clip_rect); + } + if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK); + if ( convert != NULL ) { + Uint8 keyR, keyG, keyB; + + SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); + SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK), + SDL_MapRGB(convert->format, keyR, keyG, keyB)); + } + SDL_SetColorKey(surface, cflags, colorkey); + } + if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + if ( convert != NULL ) { + SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK), + alpha); + } + if ( format->Amask ) { + surface->flags |= SDL_SRCALPHA; + } else { + SDL_SetAlpha(surface, aflags, alpha); + } + } + + /* We're ready to go! */ + return(convert); +} + + +/*---------------------------------------------------------- + Some OpenGL function wrappers + ----------------------------------------------------------*/ + +static struct +{ + int do_blend; + int do_texture; + GLuint texture; + GLenum sfactor, dfactor; +} glstate; + +static void glSDL_reset(void) +{ + glstate.do_blend = -1; + glstate.do_blend = -1; + glstate.texture = GLSDL_NOTEX; + glstate.sfactor = 0xffffffff; + glstate.dfactor = 0xffffffff; +} + +static __inline__ void glSDL_do_blend(_THIS, int on) +{ + if(glstate.do_blend == on) + return; + + if(on) + this->glEnable(GL_BLEND); + else + this->glDisable(GL_BLEND); + glstate.do_blend = on; +} + +static __inline__ void glSDL_do_texture(_THIS, int on) +{ + if(glstate.do_texture == on) + return; + + if(on) + this->glEnable(GL_TEXTURE_2D); + else + this->glDisable(GL_TEXTURE_2D); + glstate.do_texture = on; +} + +static __inline__ void glSDL_blendfunc(_THIS, GLenum sfactor, GLenum dfactor) +{ + if((sfactor == glstate.sfactor) && (dfactor == glstate.dfactor)) + return; + + this->glBlendFunc(sfactor, dfactor); + + glstate.sfactor = sfactor; + glstate.dfactor = dfactor; +} + +static __inline__ void glSDL_texture(_THIS, GLuint tx) +{ + if(tx == glstate.texture) + return; + + this->glBindTexture(GL_TEXTURE_2D, tx); + glstate.texture = tx; +} + + + + +/*---------------------------------------------------------- + glSDL specific data types + ----------------------------------------------------------*/ + +typedef enum +{ + GLSDL_TM_SINGLE, + GLSDL_TM_HORIZONTAL, + GLSDL_TM_VERTICAL, + GLSDL_TM_HUGE +} GLSDL_TileModes; + + +typedef struct private_hwdata +{ + /* Size of surface in logic screen pixels */ + int lw, lh; + + int textures; + GLuint *texture; + int texsize; /* width/height of OpenGL texture */ + GLSDL_TileModes tilemode; + int tilew, tileh; /* At least one must equal texsize! */ + int tilespertex; + SDL_Rect virt; /* Total size of assembled surface */ + + /* Area of surface to upload when/after unlocking */ + SDL_Rect invalid_area; + + int temporary; /* Throw away after one use. */ + + SDL_Surface* next; /* The next Surface in our linked list of hardware surfaces ; == NULL if first surface */ + SDL_Surface* prev; /* The prev Surface in our linked list of hardware surfaces ; == NULL if last surface */ +} private_hwdata; + +/* some function prototypes */ +static void glSDL_Invalidate(SDL_Surface *surface, SDL_Rect *area); +static void glSDL_SetLogicSize(_THIS, SDL_Surface *surface, int w, int h); +static private_hwdata *glSDL_UploadSurface(_THIS, SDL_Surface *surface); +static private_hwdata *glSDL_GetTexInfo(SDL_Surface *surface); +static void glSDL_init_formats(_THIS); +static private_hwdata *glSDL_AddTexInfo(_THIS, SDL_Surface *surface); +static void glSDL_RemoveTexInfo(_THIS, SDL_Surface *surface); +static void glSDL_UnloadTexture(_THIS, private_hwdata *txi); +static int glSDL_BlitGL(_THIS, SDL_Surface *src, + SDL_Rect *srcrect, SDL_Rect *dstrect); + +/* some variables */ +static GLint maxtexsize = -1; +static SDL_PixelFormat *RGBfmt = NULL; +static SDL_PixelFormat *RGBAfmt = NULL; +static void *mirrorbuf = NULL; +/* the raw 888 opengl surface, hidden from the application */ +SDL_Surface* OpenGL_Surface; + +/* pointer to the beggining of the list used for memory allocation */ +SDL_Surface* first = NULL; + +#ifdef DEBUG_GLSDL +static __inline__ int GLERET(const char *txt) +{ + fprintf(stderr, "glSDL ERROR: '%s'\n", txt); + return -1; +} +static __inline__ void GLERR(const char *txt) +{ + fprintf(stderr, "glSDL ERROR: '%s'\n", txt); +} +#else +#define GLERET(x) (-1) +#define GLERR(x) +#endif + +static SDL_VideoDevice underlying_device; +static int old_screen_flags; + +/* + * List of video drivers known to support OpenGL + * The purpose of this is to make glSDL "portable" across + * all video backends that support OpenGL + */ +static VideoBootStrap *opengl_bootstrap = +#if SDL_VIDEO_DRIVER_QUARTZ + &QZ_bootstrap; +#elif SDL_VIDEO_DRIVER_X11 + &X11_bootstrap; +#elif SDL_VIDEO_DRIVER_WINDIB + &WINDIB_bootstrap; +#elif SDL_VIDEO_DRIVER_BWINDOW + &BWINDOW_bootstrap; +#elif SDL_VIDEO_DRIVER_TOOLBOX + &TOOLBOX_bootstrap; +#elif SDL_VIDEO_DRIVER_CYBERGRAPHICS + &CGX_bootstrap; +#elif SDL_VIDEO_DRIVER_PHOTON + &ph_bootstrap; +#elif SDL_VIDEO_DRIVER_DC + &DC_bootstrap; +#else + NULL; +#endif + +static int glSDL_Available(void) +{ +#ifdef DEBUG_GLSDL + fprintf(stderr,"available\n"); +#endif + if (opengl_bootstrap==NULL) + return 0; + return (opengl_bootstrap->available()); +} + +static void glSDL_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +/* Create a glSDL device */ +static SDL_VideoDevice* glSDL_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; +#ifdef DEBUG_GLSDL + fprintf(stderr,"entering createdevice\n"); +#endif + + /* Create the device with the underlying driver */ + device = opengl_bootstrap->create(devindex); + + /* Save the video device contents for future use */ + SDL_memcpy(&underlying_device,device,sizeof(SDL_VideoDevice)); + + /* Hook glSDL on the video device */ + device->VideoInit = glSDL_VideoInit; + device->ListModes = glSDL_ListModes; + device->VideoQuit = glSDL_VideoQuit; + device->UpdateRects = glSDL_UpdateRects; + device->FillHWRect = glSDL_FillHWRect; + device->SetHWColorKey = glSDL_SetHWColorKey; + device->SetHWAlpha = glSDL_SetHWAlpha; + device->AllocHWSurface = glSDL_AllocHWSurface; + device->LockHWSurface = glSDL_LockHWSurface; + device->UnlockHWSurface = glSDL_UnlockHWSurface; + device->FlipHWSurface = glSDL_FlipHWSurface; + device->FreeHWSurface = glSDL_FreeHWSurface; + device->CheckHWBlit = glSDL_CheckHWBlit; + device->SetColors = glSDL_SetColors; + device->SetVideoMode = glSDL_SetVideoMode; + device->info.hw_available=1; + device->info.blit_hw=1; + device->info.blit_hw_CC=1; + device->info.blit_hw_A=1; + device->info.blit_sw=1; + device->info.blit_sw_CC=1; + device->info.blit_sw_A=1; + device->info.blit_fill=1; + + /* These functions are not supported by glSDL, so we NULLify them */ + device->SetGamma = NULL; + device->GetGamma = NULL; + device->SetGammaRamp = NULL; + device->GetGammaRamp = NULL; + device->ToggleFullScreen = NULL; + + device->free = glSDL_DeleteDevice; + +#ifdef DEBUG_GLSDL + fprintf(stderr,"leaving createdevice\n"); +#endif + + return device; +} + +/* Our bootstraping structure */ +VideoBootStrap glSDL_bootstrap = { + "glSDL", "glSDL - SDL over OpenGL", + glSDL_Available, glSDL_CreateDevice +}; + +static int glSDL_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int r; + printf("glSDL videoinit\n"); +#ifdef DEBUG_GLSDL + fprintf(stderr,"videoinit\n"); +#endif + r=underlying_device.VideoInit(this,vformat); + this->info.hw_available=1; + this->info.blit_hw=1; + this->info.blit_hw_CC=1; + this->info.blit_hw_A=1; + this->info.blit_sw=1; + this->info.blit_sw_CC=1; + this->info.blit_sw_A=1; + this->info.blit_fill=1; + + return r; +} + +SDL_Rect **glSDL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return((SDL_Rect **)-1); +} + +static void glSDL_VideoQuit(_THIS) +{ + SDL_Surface* scr; + + /* free all hwdata structures */ + while(first!=NULL) + glSDL_RemoveTexInfo(this, first); + + SDL_free(mirrorbuf); + mirrorbuf = NULL; + + SDL_FreeFormat(RGBfmt); + SDL_FreeFormat(RGBAfmt); + RGBfmt = RGBAfmt = NULL; + + SDL_FreeFormat(this->displayformatalphapixel); + this->displayformatalphapixel = NULL; + + SDL_FreeSurface(OpenGL_Surface); + OpenGL_Surface = NULL; + + /* restore the flags to gracefully exit from fullscreen */ + this->screen->flags = old_screen_flags; + + /* keep the screen */ + scr=this->screen; + + /* we cleaned up our stuff, now restore the underlying video driver */ + SDL_memcpy(this,&underlying_device,sizeof(SDL_VideoDevice)); + + this->screen=scr; + + /* call the underlying video driver's VideoQuit function */ + this->VideoQuit(this); +} + +static SDL_Surface* glSDL_SetVideoMode(_THIS, SDL_Surface *current,int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface* hooked_screen; + int i; + int flag_doublebuf=0; + + if (opengl_bootstrap==NULL) + { + GLERR("No bootstrap for glSDL compiled in !\n"); + return NULL; + } + + /* we don't have OpenGL */ + if ((flags&SDL_INTERNALOPENGL)==SDL_INTERNALOPENGL) + { + GLERR("OpenGL video modes are not supported by glSDL !\n"); + return(NULL); + } + + /* + * Adjust the flags + */ + flags &= ~SDL_HWPALETTE; + flags |= SDL_INTERNALOPENGL; + + /* remember whether the user requested DOUBLEBUF */ + + if (flags&SDL_DOUBLEBUF) + { + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); + flag_doublebuf=1; + } + else + { + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,0); + flag_doublebuf=0; + } + + hooked_screen = underlying_device.SetVideoMode(this,current,width,height,0,flags); + + if (!hooked_screen) + { + GLERR("Unable to open an OpenGL window !\n"); + return(NULL); + } + + /* save the screen flags for restore time */ + old_screen_flags = hooked_screen->flags; + +#ifdef DEBUG_GLSDL + fprintf(stderr,"got %d bpp\n",bpp); +#endif + + /* setup the public surface format + * glSDL always returns the bpp its asked + */ + switch(bpp) + { + case 32: + this->is_32bit = 1; + this->screen = SDL_CreateRGBSurface(flags, width, height, bpp, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0x00000000 +#else + 0x0000FF00, + 0x00FF0000, + 0xFF000000, + 0x00000000 +#endif + ); + break; + case 24: + this->is_32bit = 0; + this->screen = SDL_CreateRGBSurface(flags, width, height, bpp, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0x00000000 +#else + 0x0000FF00, + 0x00FF0000, + 0xFF000000, + 0x00000000 +#endif + ); + break; + case 16: + this->is_32bit = 0; + this->screen = SDL_CreateRGBSurface(flags, width, height, bpp, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x0000F800, + 0x000007E0, + 0x0000001F, + 0x00000000 +#else + 0x0000001F, + 0x000007E0, + 0x0000F800, + 0x00000000 +#endif + ); + break; + case 15: + this->is_32bit = 0; + this->screen = SDL_CreateRGBSurface(flags, width, height, bpp, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x00007C00, + 0x000003E0, + 0x0000001F, + 0x00000000 +#else + 0x0000001F, + 0x000003E0, + 0x00007C00, + 0x00000000 +#endif + ); + break; + case 8: + default: + this->is_32bit = 0; + this->screen = SDL_CreateRGBSurface(flags, width, height, bpp, 0, 0, 0, 0); + /* give it a default palette if 8 bpp + * note : SDL already takes care of the palette for 4 bits & 1 bit surfaces + */ +/* if (bpp==8) + { + this->screen->format->palette->ncolors=255; + SDL_DitherColors(this->screen->format->palette->colors,bpp); + }*/ + break; + } + + /* also, we add SDL_HWSURFACE all the time, and let SDL create a shadow surface accordingly */ + this->screen->flags = hooked_screen->flags | SDL_HWSURFACE | SDL_INTERNALOPENGL; + /* add SDL_DOUBLEBUF if it was requested */ + if (flag_doublebuf) + this->screen->flags|=SDL_DOUBLEBUF; + + /* Tell SDL the alpha pixel format we'd like to have */ + this->displayformatalphapixel = SDL_AllocFormat(32, +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#else + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#endif + ); + + /* Now create the raw OpenGL surface */ + OpenGL_Surface = SDL_CreateRGBSurface(flags, width, height, 24, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0x00000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x00000000 +#endif + ); + + /* Here we have to setup OpenGL funcs ourselves */ +#ifndef __QNXNTO__ +#define SDL_PROC(ret,func,params) \ + do { \ + this->func = SDL_GL_GetProcAddress(#func); \ + if ( ! this->func ) { \ + SDL_SetError("Couldn't load GL function: %s\n", #func); \ + return(NULL); \ + } \ + } while ( 0 ); +#else +#define SDL_PROC(ret,func,params) this->func=func; +#endif /* __QNXNTO__ */ +#include "../SDL_glfuncs.h" +#undef SDL_PROC + + if ( this->GL_MakeCurrent(this) < 0 ) + return(NULL); +#define SDL_PROC(ret,func,params) \ + do { \ + this->func = SDL_GL_GetProcAddress(#func); \ + if ( ! this->func ) { \ + SDL_SetError("Couldn't load GL function: %s\n", #func); \ + return(NULL); \ + } \ + } while ( 0 ); +#include "../SDL_glfuncs.h" +#undef SDL_PROC + + +#ifdef FAKE_MAXTEXSIZE + maxtexsize = FAKE_MAXTEXSIZE; +#else + this->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); +#endif +#ifdef DEBUG_GLSDL + fprintf(stderr, "glSDL: Max texture size: %d\n", maxtexsize); +#endif + + glSDL_init_formats(this); + + if (flag_doublebuf) + this->glDrawBuffer(GL_BACK); + else + this->glDrawBuffer(GL_FRONT); + + this->glDisable(GL_DITHER); + + if(glSDL_AddTexInfo(this, this->screen) < 0) + { + GLERR("HookDevice() failed to add info to screen surface!"); + return NULL; + } + + glSDL_SetLogicSize(this, this->screen, + this->screen->w, this->screen->h); + + glSDL_do_texture(this, 0); + glSDL_do_blend(this, 0); + + for(i = 0; i < 1+flag_doublebuf; ++i) + { + this->glBegin(GL_TRIANGLE_FAN); + this->glColor3ub(0, 0, 0); + this->glVertex2i(0, 0); + this->glVertex2i(this->screen->w, 0); + this->glVertex2i(this->screen->w, this->screen->h); + this->glVertex2i(0, this->screen->h); + this->glEnd(); + if(!i) + this->GL_SwapBuffers(this); + } + + mirrorbuf = SDL_malloc(this->screen->h * this->screen->pitch); + if(!mirrorbuf) + { + GLERR("HookDevice() failed to allocate temp buffer for mirroring!"); + return NULL; + } + + return this->screen; +} + +static int glSDL_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* We don't need to fill this one */ + return 0; +} + + +#ifdef DEBUG_GLSDL +static void glSDL_print_glerror(_THIS, int point) +{ + const char *err = ""; + switch(this->glGetError()) + { + case GL_NO_ERROR: + return; + case GL_INVALID_ENUM: + err = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + err = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + err = "GL_INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + err = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + err = "GL_STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + err = "GL_OUT_OF_MEMORY"; + default: + break; + } + fprintf(stderr,"OpenGL error \"%s\" at point %d.\n", err, point); +} +#endif + +/* Get texinfo for a surface. */ +static __inline__ private_hwdata *glSDL_GetTexInfo(SDL_Surface *surface) +{ + if(!surface) + return NULL; + return surface->hwdata; +} + + +/* Allocate a "blank" texinfo for a suface. */ +static private_hwdata *glSDL_AllocTexInfo(SDL_Surface *surface) +{ + private_hwdata *txi; + if(!surface) + return NULL; + + txi = glSDL_GetTexInfo(surface); + if(txi) + return txi; /* There already is one! --> */ + + /* ...and hook a new texinfo struct up to it. */ + txi = (private_hwdata *)SDL_calloc(1, sizeof(private_hwdata)); + if(!txi) + { + GLERR("AllocTexInfo(): Failed allocating TexInfo struct!"); + return NULL; + } + txi->temporary = 1; +#ifdef DEBUG_GLSDL + fprintf(stderr, "glSDL: Allocated TexInfo %p.\n", txi); +#endif + return txi; +} + + +static void glSDL_FreeTexInfo(_THIS, private_hwdata *txi) +{ + if(!txi) + return; + + glSDL_UnloadTexture(this, txi); + SDL_free(txi->texture); + SDL_free(txi); +#ifdef DEBUG_GLSDL + fprintf(stderr, "glSDL: Freed TexInfo %p.\n", txi); +#endif +} + + +/* Detach and free the texinfo of a surface. */ +static void glSDL_RemoveTexInfo(_THIS, SDL_Surface *surface) +{ + SDL_Surface *next,*prev; + if(!glSDL_GetTexInfo(surface)) + return; + + /* maintain our doubly linked list */ + next=surface->hwdata->next; + prev=surface->hwdata->prev; + if (prev!=NULL) + { + prev->hwdata->next = next; + } + else + { + first = next; + } + if (next!=NULL) + { + next->hwdata->prev = prev; + } + + glSDL_FreeTexInfo(this, surface->hwdata); + surface->hwdata = NULL; +} + + +/* + * Calculate chopping/tiling of a surface to + * fit it into the smallest possible OpenGL + * texture. + */ +static int glSDL_CalcChop(private_hwdata *txi) +{ + int rows, vw, vh; + int vertical = 0; + int texsize; + int lastw, lasth, minsize; + + vw = txi->virt.w; + vh = txi->virt.h; + +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "w=%d, h=%d ", vw, vh); +#endif + if(vh > vw) + { + int t = vw; + vw = vh; + vh = t; + vertical = 1; +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "(vertical) \t"); +#endif + } + + /* + * Check whether this is a "huge" surface - at least one dimension + * must be <= than the maximum texture size, or we'll have to chop + * in both directions. + */ +#ifdef DEBUG_GLSDL + if(maxtexsize < 0) + return GLERET("glSDL_CalcChop() called before OpenGL init!"); +#endif + if(vh > maxtexsize) + { + /* + * Very simple hack for now; we just tile + * both ways with maximum size textures. + */ + texsize = maxtexsize; + + txi->tilemode = GLSDL_TM_HUGE; + txi->texsize = texsize; + txi->tilew = texsize; + txi->tileh = texsize; + txi->tilespertex = 1; + + /* Calculate number of textures needed */ + txi->textures = (vw + texsize - 1) / texsize; + txi->textures *= (vh + texsize - 1) / texsize; + txi->texture = SDL_malloc(txi->textures * sizeof(int)); + SDL_memset(txi->texture, -1, txi->textures * sizeof(int)); +#ifdef DEBUG_GLSDL + fprintf(stderr, "two-way tiling; textures=%d\n", txi->textures); +#endif + if(!txi->texture) + { + fprintf(stderr, "glSDL: INTERNAL ERROR: Failed to allocate" + " texture name table!\n"); + return -3; + } + return 0; + } + + /* Calculate minimum size */ + rows = 1; + lastw = vw; + lasth = vh; + minsize = lastw > lasth ? lastw : lasth; + while(1) + { + int w, h, size; + ++rows; + w = vw / rows; + h = rows * vh; + size = w > h ? w : h; + if(size >= minsize) + { + --rows; + break; + } + lastw = w; + lasth = h; + minsize = size; + } + if(minsize > maxtexsize) + { + /* Handle multiple textures for very wide/tall surfaces. */ + minsize = maxtexsize; + rows = (vw + minsize-1) / minsize; + } +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "==> minsize=%d ", minsize); + fprintf(stderr, "(rows=%d) \t", rows); +#endif + + /* Recalculate with nearest higher power-of-2 width. */ + for(texsize = 1; texsize < minsize; texsize <<= 1) + ; + txi->texsize = texsize; + rows = (vw + texsize-1) / texsize; +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "==> texsize=%d (rows=%d) \t", texsize, rows); +#endif + + /* Calculate number of tiles per texture */ + txi->tilespertex = txi->texsize / vh; +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "tilespertex=%d \t", txi->tilespertex); +#endif + + /* Calculate number of textures needed */ + txi->textures = (rows + txi->tilespertex-1) / txi->tilespertex; + txi->texture = (GLuint *)SDL_malloc(txi->textures * sizeof(GLuint)); + SDL_memset(txi->texture, GLSDL_NOTEX, txi->textures * sizeof(GLuint)); +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "textures=%d, ", txi->textures); +#endif + if(!txi->texture) + return GLERET("Failed to allocate texture name table!"); + + /* Set up tile size. (Only one axis supported here!) */ + if(1 == rows) + { + txi->tilemode = GLSDL_TM_SINGLE; + if(vertical) + { + txi->tilew = vh; + txi->tileh = vw; + } + else + { + txi->tilew = vw; + txi->tileh = vh; + } + } + else if(vertical) + { + txi->tilemode = GLSDL_TM_VERTICAL; + txi->tilew = vh; + txi->tileh = texsize; + } + else + { + txi->tilemode = GLSDL_TM_HORIZONTAL; + txi->tilew = texsize; + txi->tileh = vh; + } + +#ifdef DEBUG_GLSDL_CHOP + fprintf(stderr, "tilew=%d, tileh=%d\n", txi->tilew, txi->tileh); +#endif + return 0; +} + + +/* Create a temporary TexInfo struct for an SDL_Surface */ +static private_hwdata *glSDL_CreateTempTexInfo(_THIS, SDL_Surface *surface) +{ + private_hwdata *txi; + if(!surface) + { + GLERR("CreateTempTexInfo(); no surface!"); + return NULL; + } + if(IS_GLSDL_SURFACE(surface)) + return glSDL_GetTexInfo(surface); /* Do nothing */ + + txi = glSDL_AllocTexInfo(surface); + if(!txi) + { + GLERR("CreateTempTexInfo(); Could not alloc TexInfo!"); + return NULL; + } + txi->virt.w = txi->lw = surface->w; + txi->virt.h = txi->lh = surface->h; + + if(glSDL_CalcChop(txi) < 0) + { + glSDL_FreeTexInfo(this, txi); + GLERR("CreateTempTexInfo(); CalcChop() failed!"); + return NULL; + } + + return txi; +} + +/* Add a glSDL_TexInfo struct to an SDL_Surface */ +static private_hwdata *glSDL_AddTexInfo(_THIS, SDL_Surface *surface) +{ + private_hwdata *txi = glSDL_CreateTempTexInfo(this, surface); + if(!txi) + return NULL; + + /* Connect the surface to the new TexInfo. */ + txi->temporary = 0; + surface->hwdata = txi; + + /* add this new surface in front of the list of hw surfaces */ + txi->next = first; + txi->prev = NULL; + first = surface; + if (txi->next!=NULL) + { + txi->next->hwdata->prev=surface; + } + + SDL_SetClipRect(surface, &txi->virt); + return txi; +} + + +/* Create a surface of the prefered OpenGL RGB texture format */ +/*static SDL_Surface *glSDL_CreateRGBSurface(int w, int h) +{ + SDL_Surface *s; + Uint32 rmask, gmask, bmask; + int bits = 24; +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + rmask = 0x000000FF; + gmask = 0x0000FF00; + bmask = 0x00FF0000; +#else + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; +#endif + s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, + bits, rmask, gmask, bmask, 0); + if(s) + s->flags |= SDL_HWACCEL; + + return s; +} +*/ + +/* Create a surface of the prefered OpenGL RGBA texture format */ +static SDL_Surface *glSDL_CreateRGBASurface(int w, int h) +{ + SDL_Surface *s; + Uint32 rmask, gmask, bmask, amask; + int bits = 32; +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + rmask = 0x000000FF; + gmask = 0x0000FF00; + bmask = 0x00FF0000; + amask = 0xFF000000; +#else + rmask = 0xFF000000; + gmask = 0x00FF0000; + bmask = 0x0000FF00; + amask = 0x000000FF; +#endif + s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, + bits, rmask, gmask, bmask, amask); + if(s) + s->flags |= SDL_HWACCEL; + + return s; +} + + +static void glSDL_init_formats(_THIS) +{ + RGBfmt = SDL_AllocFormat(24, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0); +#else + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0); +#endif + RGBAfmt = SDL_AllocFormat(32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF); +#endif +} + + +static int glSDL_FormatIsOk(SDL_Surface *surface) +{ + SDL_PixelFormat *pf; + if(!surface) + return 1; /* Well, there ain't much we can do anyway... */ + + pf = surface->format; + + /* Colorkeying requires an alpha channel! */ + if(surface->flags & SDL_SRCCOLORKEY) + if(!pf->Amask) + return 0; + + /* We need pitch == (width * BytesPerPixel) for glTex[Sub]Image2D() */ + if(surface->pitch != (surface->w * pf->BytesPerPixel)) + return 0; + + if(pf->Amask) + { + if(pf->BytesPerPixel != RGBAfmt->BytesPerPixel) + return 0; + if(pf->Rmask != RGBAfmt->Rmask) + return 0; + if(pf->Gmask != RGBAfmt->Gmask) + return 0; + if(pf->Bmask != RGBAfmt->Bmask) + return 0; + if(pf->Amask != RGBAfmt->Amask) + return 0; + } + else + { + if(pf->BytesPerPixel != RGBfmt->BytesPerPixel) + return 0; + if(pf->Rmask != RGBfmt->Rmask) + return 0; + if(pf->Gmask != RGBfmt->Gmask) + return 0; + if(pf->Bmask != RGBfmt->Bmask) + return 0; + } + return 1; +} + +static void glSDL_key2alpha(SDL_Surface *surface) +{ + int x, y; + Uint32 ckey = surface->format->colorkey; + +#ifdef DEBUG_GLSDL + fprintf(stderr,"glSDL_key2alpha()\n"); +#endif + for(y = 0; y < surface->h; ++y) + { + Uint32 *px = (Uint32 *)((char *)surface->pixels + y*surface->pitch); + for(x = 0; x < surface->w; ++x) + if(px[x] == ckey) + px[x] = 0; + } +} + + + +/*---------------------------------------------------------- + SDL style API + ----------------------------------------------------------*/ + +static int glSDL_FlipHWSurface(_THIS, SDL_Surface *surface) +{ +#ifdef GLSDL_GRAPHICAL_DEBUG + this->glDisable(GL_TEXTURE_2D); + this->glBegin(GL_LINE_LOOP); + this->glColor4ub(0, 0, 255, 128); + this->glVertex2i(0,0); + this->glVertex2i(surface->w,0); + this->glVertex2i(surface->w,surface->h); + this->glVertex2i(0,surface->h); + this->glEnd(); + this->glEnable(GL_TEXTURE_2D); +#endif + if (this->screen->flags&SDL_DOUBLEBUF) + this->GL_SwapBuffers(this); + else + this->glFinish(); + return 0; +} + + +static void glSDL_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ +#ifdef GLSDL_GRAPHICAL_DEBUG + int i; + this->glDisable(GL_TEXTURE_2D); + for(i=0;iglColor4ub(255, 0, 0, 128); + this->glBegin(GL_LINE_LOOP); + this->glVertex2i(rects[i].x,rects[i].y); + this->glVertex2i(rects[i].x+rects[i].w,rects[i].y); + this->glVertex2i(rects[i].x+rects[i].w,rects[i].y+rects[i].h); + this->glVertex2i(rects[i].x,rects[i].y+rects[i].h); + this->glEnd(); + } + this->glEnable(GL_TEXTURE_2D); +#endif + if (this->screen->flags&SDL_DOUBLEBUF) + this->GL_SwapBuffers(this); + else + this->glFinish(); +} + + +static int glSDL_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + surface->flags |= (SDL_HWSURFACE|SDL_HWACCEL); + + surface->pixels = SDL_malloc(surface->h*surface->pitch); + if ( surface->pixels == NULL ) { + SDL_FreeSurface(surface); + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(surface->pixels, 0, surface->h*surface->pitch); + return 0; +} + + +static void glSDL_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if(!surface) + return; + glSDL_RemoveTexInfo(this, surface); +} + + +static int glSDL_LockHWSurface(_THIS, SDL_Surface *surface) +{ + int y; + + if(!surface) + return -1; + +#ifdef DEBUG_GLSDL + fprintf(stderr, "glSDL: Lock Surface.\n"); +#endif + + if(SDL_VideoSurface == surface) + { + glSDL_Invalidate(surface, NULL); + this->glPixelStorei(GL_UNPACK_ROW_LENGTH, + surface->pitch / + surface->format->BytesPerPixel); + this->glReadPixels(0, 0, OpenGL_Surface->w, OpenGL_Surface->h, + GL_RGB, + GL_UNSIGNED_BYTE, + OpenGL_Surface->pixels); + for(y = 0; y < OpenGL_Surface->h / 2; ++y) + { + void *upper = (Uint8 *)OpenGL_Surface->pixels + + OpenGL_Surface->pitch * y; + void *lower = (Uint8 *)OpenGL_Surface->pixels + + OpenGL_Surface->pitch * (OpenGL_Surface->h - y - 1); + SDL_memcpy(mirrorbuf, upper, OpenGL_Surface->pitch); + SDL_memcpy(upper, lower, OpenGL_Surface->pitch); + SDL_memcpy(lower, mirrorbuf, OpenGL_Surface->pitch); + } + /* the mapping has to be invalidated on 8bpp video surfaces in case of a hw palette change. + * Now if someone could tell me why this is not handled by SDL... */ + if (SDL_VideoSurface->format->BitsPerPixel==8) + SDL_InvalidateMap(OpenGL_Surface->map); + + /* convert this raw surface to the application-requested format + * FIXME this is sometimes overkill, we could use glPixelStore smartly + * But this would be slow anyway :) */ + + glSDL_SoftBlit(OpenGL_Surface, NULL, SDL_VideoSurface, NULL); + } + else + glSDL_Invalidate(surface, NULL); + + return 0; +} + + +static void glSDL_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + private_hwdata *txi; + + if(!surface) + return; + + /* upload this surface ONLY if this is a glSDL surface + * because sometimes (during displayformating for ex.) surfaces are unlocked that aren't glSDL + */ + if(!IS_GLSDL_SURFACE(surface)) + return; + +#ifdef DEBUG_GLSDL + fprintf(stderr, "glSDL: Unlock Surface.\n"); +#endif + + txi = glSDL_UploadSurface(this, surface); + + if(!txi) + { + GLERR("glSDL_UnlockHWSurface() failed to upload surface!"); + return; + } + if(txi->temporary) + { + GLERR("Weirdness... glSDL_UnlockHWSurface() got a temporary TexInfo."); + return; + } + if(surface == SDL_VideoSurface) + glSDL_BlitGL(this, SDL_VideoSurface, NULL, NULL); +} + + +static int glSDL_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + /* + * If an application does this *after* SDL_DisplayFormat, + * we're basically screwed, unless we want to do an + * in-place surface conversion hack here. + * + * What we do is just kill the glSDL texinfo... No big + * deal in most cases, as glSDL only converts once anyway, + * *unless* you keep modifying the surface. + */ + if(IS_GLSDL_SURFACE(surface)) + glSDL_RemoveTexInfo(this, surface); + return 0; +} + + +static int glSDL_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) +{ + /* + * If an application does this *after* SDL_DisplayFormat, + * we're basically screwed, unless we want to do an + * in-place surface conversion hack here. + * + * What we do is just kill the glSDL texinfo... No big + * deal in most cases, as glSDL only converts once anyway, + * *unless* you keep modifying the surface. + */ + if(IS_GLSDL_SURFACE(surface)) + glSDL_RemoveTexInfo(this, surface); + return 0; +} + +static SDL_bool glSDL_SetClipRect(_THIS, SDL_Surface *surface, SDL_Rect *rect) +{ + SDL_bool res; + if(!surface) + return SDL_FALSE; + + res = SDL_SetClipRect(surface, rect); + if(!res) + return SDL_FALSE; + + rect = &surface->clip_rect; + + if(surface == SDL_VideoSurface) + { + SDL_Rect r; + float xscale, yscale; + private_hwdata *txi; + + r.x = rect->x; + r.y = rect->y; + r.w = rect->w; + r.h = rect->h; + SDL_SetClipRect(surface, rect); + + txi = glSDL_GetTexInfo(surface); + if(!txi) + return GLERET("SetClipRect(): Could not get TexInfo!"); + + this->glViewport(rect->x, + surface->h - (rect->y + rect->h), + rect->w, + rect->h); + /* + * Note that this projection is upside down in + * relation to the OpenGL coordinate system. + */ + this->glMatrixMode(GL_PROJECTION); + this->glLoadIdentity(); + xscale = (float)txi->lw / (float)surface->w; + yscale = (float)txi->lh / (float)surface->h; + this->glOrtho( xscale*(float)rect->x, + xscale*(float)(rect->w+rect->x), + yscale*(float)(rect->h+rect->y), + yscale*(float)rect->y, + -1.0, 1.0); + return SDL_TRUE; + } + return res; +} + +static int glSDL_BlitFromGL(_THIS, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_Rect sr, dr; + + /* In case the destination has an OpenGL texture... */ + glSDL_Invalidate(dst, dstrect); + + /* Abuse the fake screen buffer a little. */ + this->glPixelStorei(GL_UNPACK_ROW_LENGTH, SDL_VideoSurface->pitch / + SDL_VideoSurface->format->BytesPerPixel); + if(srcrect) + this->glReadPixels(srcrect->x, OpenGL_Surface->h - (srcrect->y + srcrect->h - 1), + srcrect->w, srcrect->h, + GL_RGB, GL_UNSIGNED_BYTE, OpenGL_Surface->pixels); + else + this->glReadPixels(0, 0, OpenGL_Surface->w, OpenGL_Surface->h, + GL_RGB, GL_UNSIGNED_BYTE, OpenGL_Surface->pixels); + sr = *srcrect; + dr = *dstrect; + glSDL_SoftBlit(OpenGL_Surface, &sr, dst, &dr); + return 0; +} + +static __inline__ void glSDL_BlitGL_single(_THIS, private_hwdata *txi, + float sx1, float sy1, SDL_Rect *dst, unsigned char alpha) +{ + float sx2, sy2, texscale; + if(!txi->textures) + return; + if(-1 == txi->texture[0]) + return; + glSDL_texture(this, txi->texture[0]); + + texscale = 1.0 / (float)txi->texsize; + sx2 = (sx1 + (float)dst->w) * texscale; + sy2 = (sy1 + (float)dst->h) * texscale; + sx1 *= texscale; + sy1 *= texscale; + +#ifdef GLSDL_GRAPHICAL_DEBUG + this->glDisable(GL_TEXTURE_2D); + this->glBegin(GL_LINE_LOOP); + this->glColor4ub(0, 255, 0, 128); + this->glVertex2i(dst->x, dst->y); + this->glVertex2i(dst->x + dst->w, dst->y); + this->glVertex2i(dst->x + dst->w, dst->y + dst->h); + this->glVertex2i(dst->x, dst->y + dst->h); + this->glEnd(); + this->glEnable(GL_TEXTURE_2D); +#endif + + this->glBegin(GL_TRIANGLE_FAN); + this->glColor4ub(255, 255, 255, alpha); + this->glTexCoord2f(sx1, sy1); + this->glVertex2i(dst->x, dst->y); + this->glTexCoord2f(sx2, sy1); + this->glVertex2i(dst->x + dst->w, dst->y); + this->glTexCoord2f(sx2, sy2); + this->glVertex2i(dst->x + dst->w, dst->y + dst->h); + this->glTexCoord2f(sx1, sy2); + this->glVertex2i(dst->x, dst->y + dst->h); + this->glEnd(); +} + + +static void glSDL_BlitGL_htile(_THIS, private_hwdata *txi, + float sx1, float sy1, SDL_Rect *dst, unsigned char alpha) +{ + int tex; + float tile, sx2, sy2, yo; + float texscale = 1.0 / (float)txi->texsize; + float tileh = (float)txi->tileh * texscale; + sx2 = (sx1 + (float)dst->w) * texscale; + sy2 = (sy1 + (float)dst->h) * texscale; + sx1 *= texscale; + sy1 *= texscale; + tile = floor(sx1); + tex = (int)tile / txi->tilespertex; + yo = ((int)tile % txi->tilespertex) * tileh; + + if(tex >= txi->textures) + return; + if(-1 == txi->texture[tex]) + return; + glSDL_texture(this, txi->texture[tex]); + + while(tile < sx2) + { + int tdx1 = dst->x; + int tdx2 = dst->x + dst->w; + float tsx1 = sx1 - tile; + float tsx2 = sx2 - tile; + + /* Clip to current tile */ + if(tsx1 < 0.0) + { + tdx1 -= tsx1 * txi->texsize; + tsx1 = 0.0; + } + if(tsx2 > 1.0) + { + tdx2 -= (tsx2 - 1.0) * txi->texsize; + tsx2 = 1.0; + } + + /* Maybe select next texture? */ + if(yo + tileh > 1.0) + { + ++tex; + if(tex >= txi->textures) + return; + if(-1 == txi->texture[tex]) + return; + glSDL_texture(this, txi->texture[tex]); + yo = 0.0; + } + +#ifdef GLSDL_GRAPHICAL_DEBUG + this->glDisable(GL_TEXTURE_2D); + this->glBegin(GL_LINE_LOOP); + this->glColor4ub(0, 255, 0, 128); + this->glVertex2i(tdx1, dst->y); + this->glVertex2i(tdx2, dst->y); + this->glVertex2i(tdx2, dst->y + dst->h); + this->glVertex2i(tdx1, dst->y + dst->h); + this->glEnd(); + this->glEnable(GL_TEXTURE_2D); +#endif + + this->glBegin(GL_TRIANGLE_FAN); + this->glColor4ub(255, 255, 255, alpha); + this->glTexCoord2f(tsx1, yo + sy1); + this->glVertex2i(tdx1, dst->y); + this->glTexCoord2f(tsx2, yo + sy1); + this->glVertex2i(tdx2, dst->y); + this->glTexCoord2f(tsx2, yo + sy2); + this->glVertex2i(tdx2, dst->y + dst->h); + this->glTexCoord2f(tsx1, yo + sy2); + this->glVertex2i(tdx1, dst->y + dst->h); + this->glEnd(); + tile += 1.0; + yo += tileh; + } +} + + +static void glSDL_BlitGL_vtile(_THIS, private_hwdata *txi, + float sx1, float sy1, SDL_Rect *dst, unsigned char alpha) +{ + int tex; + float tile, sx2, sy2, xo; + float texscale = 1.0 / (float)txi->texsize; + float tilew = (float)txi->tilew * texscale; + sx2 = (sx1 + (float)dst->w) * texscale; + sy2 = (sy1 + (float)dst->h) * texscale; + sx1 *= texscale; + sy1 *= texscale; + tile = floor(sy1); + tex = (int)tile / txi->tilespertex; + xo = ((int)tile % txi->tilespertex) * tilew; + + if(tex >= txi->textures) + return; + if(-1 == txi->texture[tex]) + return; + glSDL_texture(this, txi->texture[tex]); + + while(tile < sy2) + { + int tdy1 = dst->y; + int tdy2 = dst->y + dst->h; + float tsy1 = sy1 - tile; + float tsy2 = sy2 - tile; + + /* Clip to current tile */ + if(tsy1 < 0.0) + { + tdy1 -= tsy1 * txi->texsize; + tsy1 = 0.0; + } + if(tsy2 > 1.0) + { + tdy2 -= (tsy2 - 1.0) * txi->texsize; + tsy2 = 1.0; + } + + /* Maybe select next texture? */ + if(xo + tilew > 1.0) + { + ++tex; + if(tex >= txi->textures) + return; + if(-1 == txi->texture[tex]) + return; + glSDL_texture(this, txi->texture[tex]); + xo = 0.0; + } + +#ifdef GLSDL_GRAPHICAL_DEBUG + this->glDisable(GL_TEXTURE_2D); + this->glBegin(GL_LINE_LOOP); + this->glColor4ub(0, 255, 0, 128); + this->glVertex2i(dst->x, tdy1); + this->glVertex2i(dst->x + dst->w, tdy1); + this->glVertex2i(dst->x + dst->w, tdy2); + this->glVertex2i(dst->x, tdy2); + this->glEnd(); + this->glEnable(GL_TEXTURE_2D); +#endif + + this->glBegin(GL_TRIANGLE_FAN); + this->glColor4ub(255, 255, 255, alpha); + this->glTexCoord2f(xo + sx1, tsy1); + this->glVertex2i(dst->x, tdy1); + this->glTexCoord2f(xo + sx2, tsy1); + this->glVertex2i(dst->x + dst->w, tdy1); + this->glTexCoord2f(xo + sx2, tsy2); + this->glVertex2i(dst->x + dst->w, tdy2); + this->glTexCoord2f(xo + sx1, tsy2); + this->glVertex2i(dst->x, tdy2); + this->glEnd(); + + tile += 1.0; + xo += tilew; + } +} + + +static void glSDL_BlitGL_hvtile(_THIS, SDL_Surface *src, private_hwdata *txi, + float sx1, float sy1, SDL_Rect *dst, unsigned char alpha) +{ + int x, y, last_tex, tex; + float sx2, sy2; + float texscale = 1.0 / (float)txi->texsize; + int tilesperrow = (src->w + txi->tilew - 1) / txi->tilew; + sx2 = (sx1 + (float)dst->w) * texscale; + sy2 = (sy1 + (float)dst->h) * texscale; + sx1 *= texscale; + sy1 *= texscale; + + last_tex = tex = floor(sy1) * tilesperrow + floor(sx1); + if(tex >= txi->textures) + return; + if(-1 == txi->texture[tex]) + return; + glSDL_texture(this, txi->texture[tex]); + + for(y = floor(sy1); y < sy2; ++y) + { + int tdy1 = dst->y; + int tdy2 = dst->y + dst->h; + float tsy1 = sy1 - y; + float tsy2 = sy2 - y; + + /* Clip to current tile */ + if(tsy1 < 0.0) + { + tdy1 -= tsy1 * txi->texsize; + tsy1 = 0.0; + } + if(tsy2 > 1.0) + { + tdy2 -= (tsy2 - 1.0) * txi->texsize; + tsy2 = 1.0; + } + for(x = floor(sx1); x < sx2; ++x) + { + int tdx1 = dst->x; + int tdx2 = dst->x + dst->w; + float tsx1 = sx1 - x; + float tsx2 = sx2 - x; + + /* Clip to current tile */ + if(tsx1 < 0.0) + { + tdx1 -= tsx1 * txi->texsize; + tsx1 = 0.0; + } + if(tsx2 > 1.0) + { + tdx2 -= (tsx2 - 1.0) * txi->texsize; + tsx2 = 1.0; + } + + /* Select texture */ + tex = y * tilesperrow + x; + if(tex != last_tex) + { + if(tex >= txi->textures) + return; + if(-1 == txi->texture[tex]) + return; + glSDL_texture(this, txi->texture[tex]); + last_tex = tex; + } + +#ifdef GLSDL_GRAPHICAL_DEBUG + this->glDisable(GL_TEXTURE_2D); + this->glBegin(GL_LINE_LOOP); + this->glColor4ub(0, 255, 0, 128); + this->glVertex2i(tdx1, tdy1); + this->glVertex2i(tdx2, tdy1); + this->glVertex2i(tdx2, tdy2); + this->glVertex2i(tdx1, tdy2); + this->glEnd(); + this->glEnable(GL_TEXTURE_2D); +#endif + + this->glBegin(GL_TRIANGLE_FAN); + this->glColor4ub(255, 255, 255, alpha); + this->glTexCoord2f(tsx1, tsy1); + this->glVertex2i(tdx1, tdy1); + this->glTexCoord2f(tsx2, tsy1); + this->glVertex2i(tdx2, tdy1); + this->glTexCoord2f(tsx2, tsy2); + this->glVertex2i(tdx2, tdy2); + this->glTexCoord2f(tsx1, tsy2); + this->glVertex2i(tdx1, tdy2); + this->glEnd(); + } + } +} + +/* + * Calculate the actual blit rectangle and source offset + * for a blit from a rectangle in a surface with specified + * size to a surface with a cliprect. + * + * In: rect source rectangle + * w, h source surface size + * (x, y) destination coordinate + * clip destination clip rectangle + * + * Out: (x, y) source top-left offset + * rect destination rectangle + * + * Returns 1 if the result is visible, otherwise 0. + */ +static __inline__ int blitclip(SDL_Rect *rect, int w, int h, + int *x, int *y, SDL_Rect *clip) +{ + int sx1, sy1, sx2, sy2; + int dx1, dy1, dx2, dy2; + + /* Get source and destination coordinates */ + sx1 = rect->x; + sy1 = rect->y; + sx2 = sx1 + rect->w; + sy2 = sy1 + rect->h; + dx1 = *x; + dy1 = *y; + + /* Keep source rect inside source surface */ + if(sx1 < 0) + { + dx1 -= sx1; + sx1 = 0; + } + if(sy1 < 0) + { + dy1 -= sy1; + sy1 = 0; + } + if(sx2 > w) + sx2 = w; + if(sy2 > h) + sy2 = h; + + /* Cull blits from void space */ + if(sx1 >= sx2 || sy1 >= sy2) + return 0; + + /* Calculate destination lower-right */ + dx2 = dx1 + (sx2 - sx1); + dy2 = dy1 + (sy2 - sy1); + + /* Clip to destination cliprect */ + if(dx1 < clip->x) + { + sx1 += clip->x - dx1; + dx1 = clip->x; + } + if(dy1 < clip->y) + { + sy1 += clip->y - dy1; + dy1 = clip->y; + } + if(dx2 > clip->x + clip->w) + dx2 = clip->x + clip->w; + if(dy2 > clip->y + clip->h) + dy2 = clip->y + clip->h; + + /* Cull nop/off-screen blits */ + if(dx1 >= dx2 || dy1 >= dy2) + return 0; + + *x = sx1; + *y = sy1; + rect->x = dx1; + rect->y = dy1; + rect->w = dx2 - dx1; + rect->h = dy2 - dy1; + return 1; +} + +static int glSDL_BlitGL(_THIS, SDL_Surface *src, + SDL_Rect *srcrect, SDL_Rect *dstrect) +{ + private_hwdata *txi; + float x1, y1; + unsigned char alpha; + SDL_Rect d; + int x, y; + SDL_Rect r; + + if(!src) + return GLERET("BlitGL(): No src surface!"); + + /* Get source and destination coordinates */ + if(srcrect) + r = *srcrect; + else + { + r.x = r.y = 0; + r.w = src->w; + r.h = src->h; + } + if(dstrect) + { + x = dstrect->x; + y = dstrect->y; + } + else + x = y = 0; + + /* Clip! */ + if(!blitclip(&r, src->w, src->h, &x, &y, &this->screen->clip_rect)) + { + if(dstrect) + dstrect->w = dstrect->h = 0; + return 0; + } + + /* Write back the resulting cliprect */ + if(dstrect) + *dstrect = r; + + /* Make sure we have a source with a valid texture */ + txi = glSDL_UploadSurface(this, src); + if(!txi) + return GLERET("BlitGL(): Could not get a TexInfo!"); + + /* Set up blending */ + if(src->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY)) + { + glSDL_blendfunc(this, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glSDL_do_blend(this, 1); + } + else + glSDL_do_blend(this, 0); + + /* Enable texturing */ + glSDL_do_texture(this, 1); + + /* Calculate texcoords */ + if(!srcrect) + srcrect = &txi->virt; + x1 = (float)srcrect->x; + y1 = (float)srcrect->y; + + /* Calculate screen coords. */ + if(dstrect) + { + d.x = dstrect->x; + d.y = dstrect->y; + d.w = (int)(srcrect->w * (float)txi->lw / (float)txi->virt.w); + d.h = (int)(srcrect->h * (float)txi->lh / (float)txi->virt.h); + } + else + { + d.x = 0; + d.y = 0; + d.w = (int)(srcrect->w * (float)txi->lw / (float)txi->virt.w); + d.h = (int)(srcrect->h * (float)txi->lh / (float)txi->virt.h); + } + + /* + * Note that we actually *prevent* the use of "full surface alpha" + * and alpha channel in combination - to stay SDL 2D compatible. + */ + if ((src->flags & SDL_SRCALPHA)&&(src->format->Amask)) + alpha = 255; + else + alpha = src->format->alpha; + + /* Render! */ + switch(txi->tilemode) + { + case GLSDL_TM_SINGLE: + glSDL_BlitGL_single(this, txi, x1, y1, + &d, + alpha); + break; + case GLSDL_TM_HORIZONTAL: + glSDL_BlitGL_htile(this, txi, x1, y1, + &d, + alpha); + break; + case GLSDL_TM_VERTICAL: + glSDL_BlitGL_vtile(this, txi, x1, y1, + &d, + alpha); + break; + case GLSDL_TM_HUGE: + glSDL_BlitGL_hvtile(this, src, txi, x1, y1, + &d, + alpha); + break; + } + + if(txi->temporary) + glSDL_FreeTexInfo(this, txi); + + return 0; +} + + +static int glSDL_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_Surface *vs; + + if(!src) + return GLERET("HWAccelBlit(): No src surface!"); + if(!dst) + return GLERET("HWAccelBlit(): No dst surface!"); + + /* + * Figure out what to do: + * screen->screen: glSDL_BlitFromGL() + glSDL_BlitGL() + * surface->screen: glSDL_BlitGL() + * screen->surface: glSDL_BlitFromGL() + * surface->surface: glSDL_SoftBlit() + */ + vs = SDL_VideoSurface; + if(src == vs) + { + if(dst == vs) + { + /* +FIXME: Try glCopyPixels() instead... + */ + glSDL_BlitFromGL(current_video, srcrect, vs, dstrect); + return glSDL_BlitGL(current_video, vs, + srcrect, dstrect); + } + else + { + return glSDL_BlitFromGL(current_video, srcrect, + dst, dstrect); + } + } + else + { + if(dst == vs) + { + return glSDL_BlitGL(current_video, src, + srcrect, dstrect); + } + else + { + glSDL_Invalidate(dst, dstrect); + glSDL_SoftBlit(src, srcrect, dst, dstrect); + return 0; + } + } +} + + +static int glSDL_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + SDL_Surface *vs = SDL_VideoSurface; + int dx1, dy1, dx2, dy2; + Uint32 r, g, b; + Uint8 br,bg,bb; + + /* + * Some ugly reverse conversion for compatibility... + * (We must do this before losing the dst pointer, + * as the pixel formats of the screen and + * SDL_VideoSurface may differ!) + */ + + if (dst->format->palette) + { + /* this a paletted color */ + SDL_GetRGB(color,dst->format,&br,&bg,&bb); + } + else + { + /* this a RGB color */ + r = color & dst->format->Rmask; + r = r >> dst->format->Rshift; + r = r << dst->format->Rloss; + br = r; + + g = color & dst->format->Gmask; + g = g >> dst->format->Gshift; + g = g << dst->format->Gloss; + bg = g; + + b = color & dst->format->Bmask; + b = b >> dst->format->Bshift; + b = b << dst->format->Bloss; + bb = b; + } + + if(vs != dst) + { + /* draw a rect offscreen */ + glSDL_Invalidate(dst, dstrect); + /* software-fill the surface by faking it as a SW_SURFACE */ + dst->flags&=~SDL_HWSURFACE; + SDL_FillRect(dst,dstrect,color); + dst->flags|=SDL_HWSURFACE; + } + else + { + /* draw a rect onscreen */ + glSDL_do_texture(this, 0); + glSDL_do_blend(this, 0); + + dx1 = dstrect->x; + dy1 = dstrect->y; + dx2 = dx1 + dstrect->w; + dy2 = dy1 + dstrect->h; + + this->glBegin(GL_TRIANGLE_FAN); + this->glColor3ub(br, bg, bb); + this->glVertex2i(dx1, dy1); + this->glVertex2i(dx2, dy1); + this->glVertex2i(dx2, dy2); + this->glVertex2i(dx1, dy2); + this->glEnd(); + } + return 0; +} + +static int glSDL_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + src->flags |= SDL_HWACCEL; + src->map->hw_blit = glSDL_HWAccelBlit; + return 1; +} + + +static SDL_Surface *glSDL_DisplayFormat(SDL_Surface *surface) +{ + SDL_Surface *tmp; + int use_rgba = (surface->flags & SDL_SRCCOLORKEY) || + ((surface->flags & SDL_SRCALPHA) && + surface->format->Amask); +#ifdef DEBUG_GLSDL + fprintf(stderr,"#### glSDL_DisplayFormat()\n"); +#endif + if(use_rgba) + tmp = glSDL_ConvertSurface(surface, RGBAfmt, SDL_SWSURFACE); + else + tmp = glSDL_ConvertSurface(surface, RGBfmt, SDL_SWSURFACE); + if(!tmp) + { + GLERR("glSDL_DisplayFormat() could not convert surface!"); + return NULL; + } + SDL_SetAlpha(tmp, 0, 0); + + if(surface->flags & SDL_SRCCOLORKEY) + { + /* + * We drop colorkey data here, but we have to, + * or we'll run into trouble when converting, + * in particular from indexed color formats. + */ + SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, + surface->format->colorkey); + glSDL_key2alpha(tmp); + SDL_SetColorKey(tmp, 0, 0); + } + + return tmp; +} + + +static SDL_Surface *glSDL_DisplayFormatAlpha(SDL_Surface *surface) +{ + SDL_Surface *s, *tmp; + tmp = glSDL_ConvertSurface(surface, RGBAfmt, SDL_SWSURFACE); +#ifdef DEBUG_GLSDL + fprintf(stderr,"#### glSDL_DisplayFormatAlpha()\n"); +#endif + if(!tmp) + return NULL; + + SDL_SetAlpha(tmp, 0, 0); + SDL_SetColorKey(tmp, 0, 0); + s = glSDL_CreateRGBASurface(surface->w, surface->h); + if(!s) + { + SDL_FreeSurface(tmp); + return NULL; + } + glSDL_SoftBlit(tmp, NULL, s, NULL); + SDL_FreeSurface(tmp); + + if(surface->flags & SDL_SRCCOLORKEY) + { + SDL_SetColorKey(s, SDL_SRCCOLORKEY, + surface->format->colorkey); + glSDL_key2alpha(s); + SDL_SetColorKey(s, 0, 0); + } + + if(surface->flags & SDL_SRCALPHA) + SDL_SetAlpha(s, SDL_SRCALPHA, + surface->format->alpha); + return s; +} + + +/*---------------------------------------------------------- + glSDL specific API extensions + ----------------------------------------------------------*/ + +static void glSDL_Invalidate(SDL_Surface *surface, SDL_Rect *area) +{ + private_hwdata *txi; + if(!surface) + return; + txi = glSDL_GetTexInfo(surface); + if(!txi) + return; + if(!area) + { + txi->invalid_area.x = 0; + txi->invalid_area.y = 0; + txi->invalid_area.w = surface->w; + txi->invalid_area.h = surface->h; + return; + } + txi->invalid_area = *area; +} + + +static void glSDL_SetLogicSize(_THIS, SDL_Surface *surface, int w, int h) +{ + SDL_Rect r; + private_hwdata *txi; + if(!IS_GLSDL_SURFACE(surface)) + return; + + txi = glSDL_GetTexInfo(surface); + + txi->lw = w; + txi->lh = h; + + if(SDL_VideoSurface != surface) + return; + + r.x = r.y = 0; + r.w = w; + r.h = h; + glSDL_SetClipRect(this, surface, &r); + + this->glMatrixMode(GL_MODELVIEW); + this->glLoadIdentity(); + this->glTranslated(0.0f, 0.0f, 0.0f); + + this->glDisable(GL_DEPTH_TEST); + this->glDisable(GL_CULL_FACE); + + glSDL_reset(); +} + +static int glSDL_InitTexture(_THIS, SDL_Surface *datasurf, private_hwdata *txi, int tex) +{ + this->glGenTextures(1, (GLuint *)&txi->texture[tex]); + this->glBindTexture(GL_TEXTURE_2D, txi->texture[tex]); + glstate.texture = txi->texture[tex]; + this->glPixelStorei(GL_UNPACK_ROW_LENGTH, datasurf->pitch / + datasurf->format->BytesPerPixel); + this->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + this->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + this->glTexImage2D(GL_TEXTURE_2D, 0, + datasurf->format->Amask ? GL_RGBA8 : GL_RGB8, + txi->texsize, txi->texsize, 0, + datasurf->format->Amask ? GL_RGBA : GL_RGB, + GL_UNSIGNED_BYTE, NULL); +#ifdef DEBUG_GLSDL + glSDL_print_glerror(this, 1); +#endif + return 0; +} + + +/* Image tiled horizontally (wide surface), or not at all */ +static int glSDL_UploadHoriz(_THIS, SDL_Surface *datasurf, private_hwdata *txi) +{ + int bpp = datasurf->format->BytesPerPixel; + int res; + int tex = 0; + int fromx = 0; + int toy = txi->texsize; /* To init first texture */ + while(1) + { + int thistw = datasurf->w - fromx; + if(thistw > txi->tilew) + thistw = txi->tilew; + else if(thistw <= 0) + break; + if(toy + txi->tileh > txi->texsize) + { + toy = 0; + res = glSDL_InitTexture(this, datasurf, txi, tex); + if(res < 0) + return res; + ++tex; + } + this->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, toy, + thistw, txi->tileh, + datasurf->format->Amask ? GL_RGBA : GL_RGB, + GL_UNSIGNED_BYTE, + (char *)datasurf->pixels + bpp * fromx); +#ifdef DEBUG_GLSDL + glSDL_print_glerror(this, 2); +#endif + fromx += txi->tilew; + toy += txi->tileh; + } + return 0; +} + + +/* Image tiled vertically (tall surface) */ +static int glSDL_UploadVert(_THIS, SDL_Surface *datasurf, private_hwdata *txi) +{ + int res; + int tex = 0; + int fromy = 0; + int tox = txi->texsize; /* To init first texture */ + while(1) + { + int thisth = datasurf->h - fromy; + if(thisth > txi->tileh) + thisth = txi->tileh; + else if(thisth <= 0) + break; + if(tox + txi->tilew > txi->texsize) + { + tox = 0; + res = glSDL_InitTexture(this, datasurf, txi, tex); + if(res < 0) + return res; + ++tex; + } + this->glTexSubImage2D(GL_TEXTURE_2D, 0, tox, 0, + txi->tilew, thisth, + datasurf->format->Amask ? GL_RGBA : GL_RGB, + GL_UNSIGNED_BYTE, + (char *)datasurf->pixels + datasurf->pitch * fromy); +#ifdef DEBUG_GLSDL + glSDL_print_glerror(this, 3); +#endif + fromy += txi->tileh; + tox += txi->tilew; + } + return 0; +} + + +/* Image tiled two-way (huge surface) */ +static int glSDL_UploadHuge(_THIS, SDL_Surface *datasurf, private_hwdata *txi) +{ + int bpp = datasurf->format->BytesPerPixel; + int res; + int tex = 0; + int y = 0; + while(y < datasurf->h) + { + int x; + int thisth = datasurf->h - y; + if(thisth > txi->tileh) + thisth = txi->tileh; + x = 0; + while(x < datasurf->w) + { + int thistw = datasurf->w - x; + if(thistw > txi->tilew) + thistw = txi->tilew; + res = glSDL_InitTexture(this, datasurf, txi, tex++); + if(res < 0) + return res; + this->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + thistw, thisth, + datasurf->format->Amask ? GL_RGBA : GL_RGB, + GL_UNSIGNED_BYTE, + (char *)datasurf->pixels + + datasurf->pitch * y + bpp * x); +#ifdef DEBUG_GLSDL + fprintf(stderr,"glTexSubImage(x = %d, y = %d, w = %d, h = %d)\n", + x, y, thistw, thisth); + glSDL_print_glerror(this, 4); +#endif + x += txi->tilew; + } + y += txi->tileh; + } + return 0; +} + + +/* Upload all textures for a surface. */ +static int glSDL_UploadTextures(_THIS, SDL_Surface *datasurf, private_hwdata *txi) +{ + switch(txi->tilemode) + { + case GLSDL_TM_SINGLE: + case GLSDL_TM_HORIZONTAL: + glSDL_UploadHoriz(this, datasurf, txi); + break; + case GLSDL_TM_VERTICAL: + glSDL_UploadVert(this, datasurf, txi); + break; + case GLSDL_TM_HUGE: + glSDL_UploadHuge(this, datasurf, txi); + break; + } + return 0; +} + + +/* + * IMPORTANT: + * This function will try various ways of giving you + * a TexInfo, and will succeed most of the time. + * + * However, the TexInfo returned may be temporary, + * (as opposed to connected to 'surface'). A temporary + * TexInfo must be used only once and then thrown away, + * since it means that glSDL cannot track changes in + * the pixel data of 'texture'. + */ +static private_hwdata *glSDL_UploadSurface(_THIS, SDL_Surface *surface) +{ + int i; + int converted = 0; + private_hwdata *txi = glSDL_GetTexInfo(surface); + + if(IS_GLSDL_SURFACE(surface)) + { + /* + * Ok, this is a glSDL surface, and it *might* be + * in texture memory already. If so, it may need + * an update. + */ + if(txi->invalid_area.w) + { + glSDL_UnloadTexture(this, txi); + } + else + { + int missing = 0; + if(txi->textures) + { + for(i = 0; i < txi->textures; ++i) + if(GLSDL_NOTEX == txi->texture[i]) + { + missing = 1; + break; + } + if(!missing) + return txi; /* They're already there! */ + } + } + } + else + { + /* + * Nope, this isn't (yet) a glSDL surface. Let's + * try to either make it one, or set up a temporary + * TexInfo for it, valid for only one blit. + */ + if( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) + { + txi = glSDL_AddTexInfo(this, surface); + if(!txi) + { + GLERR("UploadSurface(): Could not add TexInfo!"); + return NULL; + } + surface->flags |= SDL_HWSURFACE; + surface->flags |= SDL_HWACCEL; + } + else + { + /* + * FIXME + * here if the surface is small enough, it's a good + * candidate for a blit using glDrawPixels instead + * of a texture blit + */ + txi = glSDL_CreateTempTexInfo(this, surface); + if(!txi) + { + GLERR("UploadSurface(): Could not create temp TexInfo!"); + return NULL; + } + } + } + + if(txi->texsize > maxtexsize) + { + /* This surface wasn't tiled properly... */ + if(txi->temporary) + glSDL_FreeTexInfo(this, txi); + GLERR("UploadSurface(): Too large texture!"); + return NULL; + } + + /* + * Kludge: Convert if not of preferred RGB or RGBA format. + * + * Conversion should only be done when *really* needed. + * That is, it should rarely have to be done with OpenGL + * 1.2+. + * + * Besides, any surface that's been SDL_DisplayFormat()ed + * should already be in the best known OpenGL format - + * preferably one that makes DMA w/o conversion possible. + */ + if(!glSDL_FormatIsOk(surface)) + { +#ifdef DEBUG_GLSDL + fprintf(stderr, "glSDL: WARNING: On-the-fly conversion performed!\n"); +#endif + converted = 1; + /* NOTE: We forget about the original surface here. */ + if(surface->format->Amask) + surface = glSDL_DisplayFormatAlpha(surface); + else + surface = glSDL_DisplayFormat(surface); + if(!surface) + { + GLERR("UploadSurface(): Could not convert surface!"); + if(txi->temporary) + glSDL_FreeTexInfo(this, txi); + return NULL; + } + } + + glSDL_UploadTextures(this, surface, txi); + + if(converted) + SDL_FreeSurface(surface); + + return txi; +} + + +static void glSDL_UnloadTexture(_THIS, private_hwdata *txi) +{ + int i; + for(i = 0; i < txi->textures; ++i) + if(txi->texture[i] != GLSDL_NOTEX) + this->glDeleteTextures(1, &txi->texture[i]); + SDL_memset(&txi->invalid_area, 0, sizeof(txi->invalid_area)); +} diff --git a/src/video/glsdl/SDL_glsdl.h b/src/video/glsdl/SDL_glsdl.h new file mode 100644 index 000000000..ff1bea5e0 --- /dev/null +++ b/src/video/glsdl/SDL_glsdl.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * glSDL "SDL-over-OpenGL" video driver implemented by + * David Olofson and + * Stephane Marchesin + */ + +#ifndef _SDL_gl_h +#define _SDL_gl_h + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#endif /* _SDL_gl_h */ diff --git a/src/video/maccommon/SDL_macevents.c b/src/video/maccommon/SDL_macevents.c index 0e4f813e2..3077df934 100644 --- a/src/video/maccommon/SDL_macevents.c +++ b/src/video/maccommon/SDL_macevents.c @@ -382,7 +382,7 @@ static int Mac_HandleEvents(_THIS, int wait4it) case updateEvt: { BeginUpdate(SDL_Window); #if SDL_VIDEO_OPENGL - if (SDL_VideoSurface->flags & SDL_OPENGL) + if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) SDL_GL_SwapBuffers(); else #endif diff --git a/src/video/macdsp/SDL_dspvideo.c b/src/video/macdsp/SDL_dspvideo.c index f0df4e920..331402656 100644 --- a/src/video/macdsp/SDL_dspvideo.c +++ b/src/video/macdsp/SDL_dspvideo.c @@ -722,7 +722,7 @@ static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current) { - if ( current->flags & SDL_OPENGL ) { + if ( current->flags & SDL_INTERNALOPENGL ) { Mac_GL_Quit (this); } @@ -918,14 +918,14 @@ static SDL_Surface *DSp_SetVideoMode(_THIS, } - if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) ) + if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_INTERNALOPENGL) ) DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL); #endif if (bpp == 8) current->flags |= SDL_HWPALETTE; - if (flags & SDL_OPENGL) { + if (flags & SDL_INTERNALOPENGL) { Rect rect; RGBColor rgb = { 0.0, 0.0, 0.0 }; @@ -960,7 +960,7 @@ static SDL_Surface *DSp_SetVideoMode(_THIS, return NULL; } - current->flags |= SDL_OPENGL; + current->flags |= SDL_INTERNALOPENGL; } return current; diff --git a/src/video/macrom/SDL_romvideo.c b/src/video/macrom/SDL_romvideo.c index 32cbbb9e6..23804fa65 100644 --- a/src/video/macrom/SDL_romvideo.c +++ b/src/video/macrom/SDL_romvideo.c @@ -583,9 +583,9 @@ static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, SelectWindow(SDL_Window); /* Handle OpenGL support */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { if ( Mac_GL_Init(this) == 0 ) { - current->flags |= SDL_OPENGL; + current->flags |= SDL_INTERNALOPENGL; } else { current = NULL; } diff --git a/src/video/photon/SDL_ph_image.c b/src/video/photon/SDL_ph_image.c index 199ad9ef1..52b4bdeaa 100644 --- a/src/video/photon/SDL_ph_image.c +++ b/src/video/photon/SDL_ph_image.c @@ -315,7 +315,7 @@ int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen) if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0) { - screen->flags &= ~SDL_OPENGL; + screen->flags &= ~SDL_INTERNALOPENGL; return -1; } @@ -328,7 +328,7 @@ void ph_DestroyImage(_THIS, SDL_Surface* screen) { #if SDL_VIDEO_OPENGL - if ((screen->flags & SDL_OPENGL)==SDL_OPENGL) + if (screen->flags & SDL_INTERNALOPENGL) { if (oglctx) { @@ -486,7 +486,7 @@ int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags) ph_DestroyImage(this, screen); #if SDL_VIDEO_OPENGL - if ((flags & SDL_OPENGL)==SDL_OPENGL) + if (flags & SDL_INTERNALOPENGL) { setupresult=ph_SetupOpenGLImage(this, screen); } diff --git a/src/video/photon/SDL_ph_modes.c b/src/video/photon/SDL_ph_modes.c index 2e6f12810..4fde57eb9 100644 --- a/src/video/photon/SDL_ph_modes.c +++ b/src/video/photon/SDL_ph_modes.c @@ -309,7 +309,7 @@ int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode) if (this->screen) { - if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL) + if (this->screen->flags & SDL_INTERNALOPENGL) { #if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) return 0; /* 6.3.0 */ @@ -345,7 +345,7 @@ int ph_LeaveFullScreen(_THIS) if (currently_fullscreen) { - if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)) + if ((this->screen) && (this->screen->flags & SDL_INTERNALOPENGL)) { #if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) return 0; diff --git a/src/video/photon/SDL_ph_mouse.c b/src/video/photon/SDL_ph_mouse.c index e0868bc8e..5a8d436ef 100644 --- a/src/video/photon/SDL_ph_mouse.c +++ b/src/video/photon/SDL_ph_mouse.c @@ -126,10 +126,10 @@ int ph_ShowWMCursor(_THIS, WMcursor* cursor) } /* looks like photon can't draw mouse cursor in direct mode */ - if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + if (this->screen->flags & SDL_FULLSCREEN) { /* disable the fake mouse in the fullscreen OpenGL mode */ - if ((this->screen->flags & SDL_OPENGL) == SDL_OPENGL) + if (this->screen->flags & SDL_INTERNALOPENGL) { cursor=NULL; } diff --git a/src/video/photon/SDL_ph_video.c b/src/video/photon/SDL_ph_video.c index ad6266ee8..f1990015a 100644 --- a/src/video/photon/SDL_ph_video.c +++ b/src/video/photon/SDL_ph_video.c @@ -475,12 +475,12 @@ static SDL_Surface* ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int return NULL; } - if ((current->flags & SDL_OPENGL)==SDL_OPENGL) + if (current->flags & SDL_INTERNALOPENGL) { #if !SDL_VIDEO_OPENGL /* if no built-in OpenGL support */ SDL_SetError("ph_SetVideoMode(): no OpenGL support, you need to recompile SDL.\n"); - current->flags &= ~SDL_OPENGL; + current->flags &= ~SDL_INTERNALOPENGL; return NULL; #endif /* SDL_VIDEO_OPENGL */ } diff --git a/src/video/qtopia/SDL_sysvideo.cc b/src/video/qtopia/SDL_sysvideo.cc index c556d79d3..805e88233 100644 --- a/src/video/qtopia/SDL_sysvideo.cc +++ b/src/video/qtopia/SDL_sysvideo.cc @@ -296,7 +296,7 @@ extern "C" { } else { SDL_SetError("Unsupported resolution, %dx%d\n", width, height); } - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { SDL_SetError("OpenGL not supported"); return(NULL); } diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m index 8fe4b737d..8fb05f826 100644 --- a/src/video/quartz/SDL_QuartzVideo.m +++ b/src/video/quartz/SDL_QuartzVideo.m @@ -379,7 +379,7 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { Release the OpenGL context Do this first to avoid trash on the display before fade */ - if ( mode_flags & SDL_OPENGL ) { + if ( mode_flags & SDL_INTERNALOPENGL ) { QZ_TearDownOpenGL (this); CGLSetFullScreen (NULL); @@ -406,7 +406,7 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { window_view = nil; /* Release the OpenGL context */ - if ( mode_flags & SDL_OPENGL ) + if ( mode_flags & SDL_INTERNALOPENGL ) QZ_TearDownOpenGL (this); } @@ -512,7 +512,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) current->flags |= SDL_HWPALETTE; /* Setup OpenGL for a fullscreen context */ - if (flags & SDL_OPENGL) { + if (flags & SDL_INTERNALOPENGL) { CGLError err; CGLContextObj ctx; @@ -535,7 +535,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) [ gl_context flushBuffer ]; - current->flags |= SDL_OPENGL; + current->flags |= SDL_INTERNALOPENGL; } /* If we don't hide menu bar, it will get events and interrupt the program */ @@ -609,8 +609,8 @@ other blitting while waiting on the VBL (and hence results in higher framerates) QZ_UnsetVideoMode (this, TRUE); } else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || - (mode_flags & SDL_OPENGL) || - (flags & SDL_OPENGL) ) { + (mode_flags & SDL_INTERNALOPENGL) || + (flags & SDL_INTERNALOPENGL) ) { QZ_UnsetVideoMode (this, TRUE); } } @@ -708,7 +708,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) } /* For OpenGL, we bind the context to a subview */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { if (fade_token != kCGDisplayFadeReservationInvalidToken) { @@ -725,7 +725,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) [ window_view release ]; [ gl_context makeCurrentContext]; [ qz_window makeKeyAndOrderFront:nil ]; - current->flags |= SDL_OPENGL; + current->flags |= SDL_INTERNALOPENGL; } /* For 2D, we set the subview to an NSQuickDrawView */ else { diff --git a/src/video/quartz/SDL_QuartzWM.m b/src/video/quartz/SDL_QuartzWM.m index a3aa3ed23..adf8bfb0b 100644 --- a/src/video/quartz/SDL_QuartzWM.m +++ b/src/video/quartz/SDL_QuartzWM.m @@ -147,7 +147,7 @@ void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { *p = [ window_view convertPoint:*p toView: nil ]; /* We need a workaround in OpenGL mode */ - if ( SDL_VideoSurface->flags & SDL_OPENGL ) { + if ( SDL_VideoSurface->flags & SDL_INTERNALOPENGL ) { p->y = [window_view frame].size.height - p->y; } } @@ -165,7 +165,7 @@ void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { *p = [ window_view convertPoint:*p fromView: nil ]; /* We need a workaround in OpenGL mode */ - if ( SDL_VideoSurface != NULL && (SDL_VideoSurface->flags & SDL_OPENGL) ) { + if ( SDL_VideoSurface != NULL && (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) ) { p->y = [window_view frame].size.height - p->y; } } diff --git a/src/video/quartz/SDL_QuartzWindow.m b/src/video/quartz/SDL_QuartzWindow.m index ffbf1eadf..247cdf572 100644 --- a/src/video/quartz/SDL_QuartzWindow.m +++ b/src/video/quartz/SDL_QuartzWindow.m @@ -55,7 +55,7 @@ @implementation SDL_QuartzWindow /* we override these methods to fix the miniaturize animation/dock icon bug */ - (void)miniaturize:(id)sender { - if (SDL_VideoSurface->flags & SDL_OPENGL) { + if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) { /* Future: Grab framebuffer and put into NSImage @@ -86,7 +86,7 @@ - (void)display SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; /* make sure pixels are fully opaque */ - if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) + if (! ( SDL_VideoSurface->flags & SDL_INTERNALOPENGL ) ) QZ_SetPortAlphaOpaque (); /* save current visible SDL surface */ @@ -126,7 +126,7 @@ - (void)setFrame:(NSRect)frameRect display:(BOOL)flag SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); /* If not OpenGL, we have to update the pixels and pitch */ - if ( ! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) { + if ( ! ( SDL_VideoSurface->flags & SDL_INTERNALOPENGL ) ) { CGrafPtr thePort = [ window_view qdPort ]; LockPortBits ( thePort ); @@ -164,7 +164,7 @@ - (void)appWillUnhide:(NSNotification*)note if ( this ) { /* make sure pixels are fully opaque */ - if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) + if (! ( SDL_VideoSurface->flags & SDL_INTERNALOPENGL ) ) QZ_SetPortAlphaOpaque (); /* save current visible SDL surface */ diff --git a/src/video/wincommon/SDL_lowvideo.h b/src/video/wincommon/SDL_lowvideo.h index eb8d9581b..002c4546e 100644 --- a/src/video/wincommon/SDL_lowvideo.h +++ b/src/video/wincommon/SDL_lowvideo.h @@ -51,17 +51,17 @@ #define WINDIB_FULLSCREEN() \ ( \ SDL_VideoSurface && \ - ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \ - (((SDL_VideoSurface->flags & SDL_OPENGL ) == SDL_OPENGL ) || \ - ((SDL_strcmp(this->name, "windib") == 0) || \ - (SDL_strcmp(this->name, "gapi") == 0))) \ + (SDL_VideoSurface->flags & SDL_FULLSCREEN) && \ + ((SDL_VideoSurface->flags & SDL_INTERNALOPENGL) || \ + ((SDL_strcmp(this->name, "windib") == 0) || \ + (SDL_strcmp(this->name, "gapi") == 0))) \ ) #define DDRAW_FULLSCREEN() \ ( \ SDL_VideoSurface && \ - ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \ - ((SDL_VideoSurface->flags & SDL_OPENGL ) != SDL_OPENGL ) && \ - (SDL_strcmp(this->name, "directx") == 0) \ + (SDL_VideoSurface->flags & SDL_FULLSCREEN) && \ + (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) && \ + (SDL_strcmp(this->name, "directx") == 0) \ ) #define DINPUT_FULLSCREEN() DDRAW_FULLSCREEN() diff --git a/src/video/wincommon/SDL_sysevents.c b/src/video/wincommon/SDL_sysevents.c index 584c18463..c7aaa2fdd 100644 --- a/src/video/wincommon/SDL_sysevents.c +++ b/src/video/wincommon/SDL_sysevents.c @@ -684,7 +684,7 @@ LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) hdc = BeginPaint(SDL_Window, &ps); if ( current_video->screen && - !(current_video->screen->flags & SDL_OPENGL) ) { + !(current_video->screen->flags & SDL_INTERNALOPENGL) ) { WIN_WinPAINT(current_video, hdc); } EndPaint(SDL_Window, &ps); diff --git a/src/video/windib/SDL_dibvideo.c b/src/video/windib/SDL_dibvideo.c index cae20a87a..9fe443b3e 100644 --- a/src/video/windib/SDL_dibvideo.c +++ b/src/video/windib/SDL_dibvideo.c @@ -484,7 +484,7 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, Uint32 Rmask, Gmask, Bmask; /* Clean up any GL context that may be hanging around */ - if ( current->flags & SDL_OPENGL ) { + if ( current->flags & SDL_INTERNALOPENGL ) { WIN_GL_ShutDown(this); } SDL_resizing = 1; @@ -686,7 +686,7 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, if ( screen_bmp != NULL ) { DeleteObject(screen_bmp); } - if ( ! (flags & SDL_OPENGL) ) { + if ( ! (flags & SDL_INTERNALOPENGL) ) { BOOL is16bitmode = (video->format->BytesPerPixel == 2); /* Suss out the bitmap info header */ @@ -814,11 +814,11 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, SDL_resizing = 0; /* Set up for OpenGL */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { if ( WIN_GL_SetupWindow(this) < 0 ) { return(NULL); } - video->flags |= SDL_OPENGL; + video->flags |= SDL_INTERNALOPENGL; } /* JC 14 Mar 2006 @@ -1035,7 +1035,7 @@ void DIB_VideoQuit(_THIS) ShowWindow(SDL_Window, SW_HIDE); } #endif - if ( this->screen->flags & SDL_OPENGL ) { + if ( this->screen->flags & SDL_INTERNALOPENGL ) { WIN_GL_ShutDown(this); } this->screen->pixels = NULL; diff --git a/src/video/windx5/SDL_dx5events.c b/src/video/windx5/SDL_dx5events.c index 068a47baa..26cbd11dd 100644 --- a/src/video/windx5/SDL_dx5events.c +++ b/src/video/windx5/SDL_dx5events.c @@ -299,7 +299,7 @@ static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf) } /* If we are in windowed mode, Windows is taking care of the mouse */ - if ( (SDL_PublicSurface->flags & SDL_OPENGL) || + if ( (SDL_PublicSurface->flags & SDL_INTERNALOPENGL) || !(SDL_PublicSurface->flags & SDL_FULLSCREEN) ) { return; } diff --git a/src/video/windx5/SDL_dx5video.c b/src/video/windx5/SDL_dx5video.c index aa83ab9c0..5f26de86c 100644 --- a/src/video/windx5/SDL_dx5video.c +++ b/src/video/windx5/SDL_dx5video.c @@ -1031,19 +1031,19 @@ SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, #ifndef NO_CHANGEDISPLAYSETTINGS /* Unset any previous OpenGL fullscreen mode */ - if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) == - (SDL_OPENGL|SDL_FULLSCREEN) ) { + if ( (current->flags & (SDL_INTERNALOPENGL|SDL_FULLSCREEN)) == + (SDL_INTERNALOPENGL|SDL_FULLSCREEN) ) { ChangeDisplaySettings(NULL, 0); } #endif /* Clean up any GL context that may be hanging around */ - if ( current->flags & SDL_OPENGL ) { + if ( current->flags & SDL_INTERNALOPENGL ) { WIN_GL_ShutDown(this); } /* If we are setting a GL mode, use GDI, not DirectX (yuck) */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { Uint32 Rmask, Gmask, Bmask; /* Recalculate the bitmasks if necessary */ @@ -1215,7 +1215,7 @@ SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, if ( WIN_GL_SetupWindow(this) < 0 ) { return(NULL); } - video->flags |= SDL_OPENGL; + video->flags |= SDL_INTERNALOPENGL; return(video); } @@ -2361,13 +2361,13 @@ void DX5_VideoQuit(_THIS) /* If we're fullscreen GL, we need to reset the display */ if ( this->screen != NULL ) { #ifndef NO_CHANGEDISPLAYSETTINGS - if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) == - (SDL_OPENGL|SDL_FULLSCREEN) ) { + if ( (this->screen->flags & (SDL_INTERNALOPENGL|SDL_FULLSCREEN)) == + (SDL_INTERNALOPENGL|SDL_FULLSCREEN) ) { ChangeDisplaySettings(NULL, 0); ShowWindow(SDL_Window, SW_HIDE); } #endif - if ( this->screen->flags & SDL_OPENGL ) { + if ( this->screen->flags & SDL_INTERNALOPENGL ) { WIN_GL_ShutDown(this); } } diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index dd914c335..764d0ea4e 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -562,7 +562,7 @@ printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xco } } else { /* OpenGL windows need to know about the change */ - if ( SDL_VideoSurface->flags & SDL_OPENGL ) { + if ( SDL_VideoSurface->flags & SDL_INTERNALOPENGL ) { SDL_PrivateExpose(); } } diff --git a/src/video/x11/SDL_x11image.c b/src/video/x11/SDL_x11image.c index a2d011d6b..9f38c86a0 100644 --- a/src/video/x11/SDL_x11image.c +++ b/src/video/x11/SDL_x11image.c @@ -185,7 +185,7 @@ int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) int retval; X11_DestroyImage(this, screen); - if ( flags & SDL_OPENGL ) { /* No image when using GL */ + if ( flags & SDL_INTERNALOPENGL ) { /* No image when using GL */ retval = 0; } else { retval = X11_SetupImage(this, screen); diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 9b2708e3a..a763d8b67 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -914,7 +914,7 @@ int X11_EnterFullScreen(_THIS) /* We may need to refresh the screen at this point (no backing store) We also don't get an event, which is why we explicitly refresh. */ if ( this->screen ) { - if ( this->screen->flags & SDL_OPENGL ) { + if ( this->screen->flags & SDL_INTERNALOPENGL ) { SDL_PrivateExpose(); } else { X11_RefreshDisplay(this); @@ -976,7 +976,7 @@ int X11_LeaveFullScreen(_THIS) /* We may need to refresh the screen at this point (no backing store) We also don't get an event, which is why we explicitly refresh. */ if ( this->screen ) { - if ( this->screen->flags & SDL_OPENGL ) { + if ( this->screen->flags & SDL_INTERNALOPENGL ) { SDL_PrivateExpose(); } else { X11_RefreshDisplay(this); diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 38919c7f2..46bbf76d6 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -585,7 +585,7 @@ static void X11_DestroyWindow(_THIS, SDL_Surface *screen) { /* Clean up OpenGL */ if ( screen ) { - screen->flags &= ~SDL_OPENGL; + screen->flags &= ~SDL_INTERNALOPENGL; } X11_GL_Shutdown(this); @@ -791,7 +791,7 @@ static int X11_CreateWindow(_THIS, SDL_Surface *screen, } /* find out which visual we are going to use */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { XVisualInfo *vi; vi = X11_GL_GetVisual(this); @@ -904,7 +904,7 @@ static int X11_CreateWindow(_THIS, SDL_Surface *screen, /* Create (or use) the X11 display window */ if ( !SDL_windowid ) { - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { if ( X11_GL_CreateWindow(this, w, h) < 0 ) { return(-1); } @@ -927,11 +927,11 @@ static int X11_CreateWindow(_THIS, SDL_Surface *screen, | PointerMotionMask | ExposureMask )); } /* Create the graphics context here, once we have a window */ - if ( flags & SDL_OPENGL ) { + if ( flags & SDL_INTERNALOPENGL ) { if ( X11_GL_CreateContext(this) < 0 ) { return(-1); } else { - screen->flags |= SDL_OPENGL; + screen->flags |= SDL_INTERNALOPENGL; } } else { XGCValues gcv; @@ -946,7 +946,7 @@ static int X11_CreateWindow(_THIS, SDL_Surface *screen, } /* Set our colormaps when not setting a GL mode */ - if ( ! (flags & SDL_OPENGL) ) { + if ( ! (flags & SDL_INTERNALOPENGL) ) { XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); if( !SDL_windowid ) { XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap); @@ -1063,7 +1063,7 @@ SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, /* Set up the X11 window */ saved_flags = current->flags; - if ( (SDL_Window) && ((saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)) + if ( (SDL_Window) && ((saved_flags&SDL_INTERNALOPENGL) == (flags&SDL_INTERNALOPENGL)) && (bpp == current->format->BitsPerPixel) && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) { if (X11_ResizeWindow(this, current, width, height, flags) < 0) { @@ -1079,7 +1079,7 @@ SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, /* Set up the new mode framebuffer */ if ( ((current->w != width) || (current->h != height)) || - ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { + ((saved_flags&SDL_INTERNALOPENGL) != (flags&SDL_INTERNALOPENGL)) ) { current->w = width; current->h = height; current->pitch = SDL_CalculatePitch(current); diff --git a/src/video/xbios/SDL_xbios.c b/src/video/xbios/SDL_xbios.c index 5d3994d91..a1c9fa999 100644 --- a/src/video/xbios/SDL_xbios.c +++ b/src/video/xbios/SDL_xbios.c @@ -574,7 +574,7 @@ static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, XBIOS_screens[0]=(void *) (( (long) XBIOS_screensmem[0]+256) & 0xFFFFFF00UL); #if SDL_VIDEO_OPENGL - if (flags & SDL_OPENGL) { + if (flags & SDL_INTERNALOPENGL) { if (this->gl_config.double_buffer) { flags |= SDL_DOUBLEBUF; } @@ -618,14 +618,14 @@ static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, XBIOS_fbnum = 0; #if SDL_VIDEO_OPENGL - if (flags & SDL_OPENGL) { + if (flags & SDL_INTERNALOPENGL) { if (!SDL_AtariGL_Init(this, current)) { XBIOS_FreeBuffers(this); SDL_SetError("Can not create OpenGL context"); return NULL; } - modeflags |= SDL_OPENGL; + modeflags |= SDL_INTERNALOPENGL; } #endif diff --git a/test/testblitspeed.c b/test/testblitspeed.c index f5dff6b3e..be74b8d0f 100644 --- a/test/testblitspeed.c +++ b/test/testblitspeed.c @@ -116,7 +116,6 @@ static void output_surface_details(const char *name, SDL_Surface *surface) append_sdl_surface_flag(surface, f, sizeof (f), SDL_DOUBLEBUF); append_sdl_surface_flag(surface, f, sizeof (f), SDL_FULLSCREEN); append_sdl_surface_flag(surface, f, sizeof (f), SDL_OPENGL); - append_sdl_surface_flag(surface, f, sizeof (f), SDL_OPENGLBLIT); append_sdl_surface_flag(surface, f, sizeof (f), SDL_RESIZABLE); append_sdl_surface_flag(surface, f, sizeof (f), SDL_NOFRAME); append_sdl_surface_flag(surface, f, sizeof (f), SDL_HWACCEL);