diff -ruN -x CVS SDL12/include/SDL_video.h SDL13/include/SDL_video.h --- SDL12/include/SDL_video.h 2006-01-31 23:28:46.000000000 -0800 +++ SDL13/include/SDL_video.h 2006-01-31 23:09:59.000000000 -0800 @@ -811,6 +811,66 @@ */ extern DECLSPEC void SDLCALL SDL_GL_SwapBuffers(void); +/* + * OpenGL render target support (render to texture) + * Everything in the render target structure is read-only + */ +typedef struct SDL_RenderTarget { + /* The texture which is associated with the render target */ + unsigned int texture; + + /* The format of the render target, GL_RGB or GL_RGBA */ + unsigned int format; + + /* The width and height in pixels of the texture data */ + int w, h; + + /* True if the target is the current draw target */ + int current; + + /* Implementation-specific data */ + void *gl_data; +} SDL_RenderTarget; + +/* + * Create a render target with the given size and attributes. + * The attrib parameter is a zero terminated list of SDL_GL_* attibutes, + * each followed by the associated value, or may be NULL for defaults. + * Currently this function does not create a new OpenGL context. + * + * This function returns NULL if a render target couldn't be created. + */ +extern DECLSPEC SDL_RenderTarget * SDLCALL SDL_GL_CreateRenderTarget(int width, int height, int *attrib); + +/* + * Get attribute information about the render target. + */ +extern DECLSPEC int SDLCALL SDL_GL_GetRenderTargetAttribute(SDL_RenderTarget *target, SDL_GLattr attrib, int* value); + +/* + * Set the texture that contains the color buffer of the render target + * after it is unlocked. The texture contents are only valid outside of + * the render target lock and unlock calls. + */ +extern DECLSPEC void SDLCALL SDL_GL_BindRenderTarget(SDL_RenderTarget *target, unsigned int texture); + +/* + * Set the render target as the current OpenGL draw target. + */ +extern DECLSPEC void SDLCALL SDL_GL_LockRenderTarget(SDL_RenderTarget *target); + +/* + * Set the screen as the current OpenGL draw target. + * If there is a texture bound to the render target, this texture is updated + * with the color buffer of the render target. + */ +extern DECLSPEC void SDLCALL SDL_GL_UnlockRenderTarget(SDL_RenderTarget *target); + +/* + * Release any resources associated with the target + */ +extern DECLSPEC void SDLCALL SDL_GL_FreeRenderTarget(SDL_RenderTarget *target); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* These functions allow interaction with the window manager, if any. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff -ruN -x CVS SDL12/src/main/beos/exports/SDL.exp SDL13/src/main/beos/exports/SDL.exp --- SDL12/src/main/beos/exports/SDL.exp 2006-01-31 23:30:33.000000000 -0800 +++ SDL13/src/main/beos/exports/SDL.exp 2004-12-19 14:38:47.000000000 -0800 @@ -181,6 +179,12 @@ _SDL_GL_SetAttribute _SDL_GL_GetAttribute _SDL_GL_SwapBuffers +_SDL_GL_CreateRenderTarget +_SDL_GL_GetRenderTargetAttribute +_SDL_GL_BindRenderTarget +_SDL_GL_LockRenderTarget +_SDL_GL_UnlockRenderTarget +_SDL_GL_FreeRenderTarget _SDL_WM_SetCaption _SDL_WM_GetCaption _SDL_WM_SetIcon diff -ruN -x CVS SDL12/src/main/macos/exports/SDL.x SDL13/src/main/macos/exports/SDL.x --- SDL12/src/main/macos/exports/SDL.x 2006-01-31 23:30:33.000000000 -0800 +++ SDL13/src/main/macos/exports/SDL.x 2004-12-19 14:38:47.000000000 -0800 @@ -179,6 +178,12 @@ SDL_GL_SetAttribute SDL_GL_GetAttribute SDL_GL_SwapBuffers + SDL_GL_CreateRenderTarget + SDL_GL_GetRenderTargetAttribute + SDL_GL_BindRenderTarget + SDL_GL_LockRenderTarget + SDL_GL_UnlockRenderTarget + SDL_GL_FreeRenderTarget SDL_WM_SetCaption SDL_WM_GetCaption SDL_WM_SetIcon diff -ruN -x CVS SDL12/src/main/macosx/exports/SDL.x SDL13/src/main/macosx/exports/SDL.x --- SDL12/src/main/macosx/exports/SDL.x 2006-01-31 23:30:33.000000000 -0800 +++ SDL13/src/main/macosx/exports/SDL.x 2004-12-19 14:38:47.000000000 -0800 @@ -179,6 +178,12 @@ _SDL_GL_SetAttribute _SDL_GL_GetAttribute _SDL_GL_SwapBuffers + _SDL_GL_CreateRenderTarget + _SDL_GL_GetRenderTargetAttribute + _SDL_GL_BindRenderTarget + _SDL_GL_LockRenderTarget + _SDL_GL_UnlockRenderTarget + _SDL_GL_FreeRenderTarget _SDL_WM_SetCaption _SDL_WM_GetCaption _SDL_WM_SetIcon diff -ruN -x CVS SDL12/src/main/win32/exports/SDL.def SDL13/src/main/win32/exports/SDL.def --- SDL12/src/main/win32/exports/SDL.def 2006-01-31 23:30:33.000000000 -0800 +++ SDL13/src/main/win32/exports/SDL.def 2004-12-19 14:38:47.000000000 -0800 @@ -181,6 +179,12 @@ SDL_GL_SetAttribute SDL_GL_GetAttribute SDL_GL_SwapBuffers + SDL_GL_CreateRenderTarget + SDL_GL_GetRenderTargetAttribute + SDL_GL_BindRenderTarget + SDL_GL_LockRenderTarget + SDL_GL_UnlockRenderTarget + SDL_GL_FreeRenderTarget SDL_WM_SetCaption SDL_WM_GetCaption SDL_WM_SetIcon diff -ruN -x CVS SDL12/src/video/quartz/SDL_QuartzGL.m SDL13/src/video/quartz/SDL_QuartzGL.m --- SDL12/src/video/quartz/SDL_QuartzGL.m 2005-12-06 06:36:39.000000000 -0800 +++ SDL13/src/video/quartz/SDL_QuartzGL.m 2006-01-31 23:10:13.000000000 -0800 @@ -239,8 +239,301 @@ return 0; } + + +typedef struct QZ_RenderTargetData { + CGLPixelFormatObj fmt; + CGLPBufferObj pbuffer; + CGLContextObj ctx; + long screen; +} QZ_RenderTargetData; + + +/* + * The PBuffer entry points aren't available before 10.3, and + * weak linking isn't available before 10.2, so we're forced to + * manually look up the relevant CGL functions in the framework + * and decide what to do from there...otherwise, we'd break + * binary compatibility with pre-Panther versions of the OS. --ryan. + */ +CGLError (*pCGLSetPBuffer)(CGLContextObj ctx, CGLPBufferObj pbuffer, unsigned long face, long level, long screen) = NULL; +CGLError (*pCGLCreatePBuffer)(long width, long height, unsigned long target, unsigned long internalFormat, long max_level, CGLPBufferObj *pbuffer) = NULL; +CGLError (*pCGLDestroyPBuffer)(CGLPBufferObj pbuffer) = NULL; +CGLError (*pCGLTexImagePBuffer)(CGLContextObj ctx, CGLPBufferObj pbuffer, unsigned long source) = NULL; + +static int LookupPBufferFuncs(_THIS) +{ + // Everything we need is in OpenGL.framework, so we can just reuse + // QZ_GL_GetProcAddress() for now... + #define QZ_GL_DOLOOKUP(sym) \ + { \ + p##sym = QZ_GL_GetProcAddress(this, #sym); \ + if (p##sym == NULL) return 0; \ + } + + QZ_GL_DOLOOKUP(CGLCreatePBuffer); + QZ_GL_DOLOOKUP(CGLDestroyPBuffer); + QZ_GL_DOLOOKUP(CGLSetPBuffer); + QZ_GL_DOLOOKUP(CGLTexImagePBuffer); + + #undef QZ_GL_LOOKUP + return 1; +} + +/* Create a render target with the given size and attributes. */ +int QZ_GL_CreateRenderTarget(_THIS, SDL_RenderTarget *target, int width, int height, int *attrib) +{ + int i = 0; + CGLError err = 0; + CGLPixelFormatAttribute attribs[64]; /* 64 seems nice. */ + long npix = 0; + QZ_RenderTargetData *render_target = NULL; + CGLContextObj ctx = [ gl_context cglContext ]; + + if (ctx == NULL) + return -1; + + render_target = (QZ_RenderTargetData *)malloc(sizeof(*render_target)); + if ( ! render_target ) { + SDL_OutOfMemory(); + return -1; + } + + target->gl_data = render_target; + memset(render_target, '\0', sizeof (*render_target)); + + attribs[i++] = kCGLPFAPBuffer; + attribs[i++] = kCGLPFAColorSize; + attribs[i++] = attrib[2*SDL_GL_RED_SIZE+1] + attrib[2*SDL_GL_GREEN_SIZE+1] + attrib[2*SDL_GL_BLUE_SIZE+1] + attrib[2*SDL_GL_ALPHA_SIZE+1]; + attribs[i++] = kCGLPFAAlphaSize; + attribs[i++] = attrib[2*SDL_GL_ALPHA_SIZE+1]; + attribs[i++] = kCGLPFADepthSize; + attribs[i++] = attrib[2*SDL_GL_DEPTH_SIZE+1]; + attribs[i++] = kCGLPFAStencilSize; + attribs[i++] = attrib[2*SDL_GL_STENCIL_SIZE+1]; + attribs[i++] = kCGLPFAAccumSize; + attribs[i++] = attrib[2*SDL_GL_ACCUM_RED_SIZE+1] + attrib[2*SDL_GL_ACCUM_GREEN_SIZE+1] + attrib[2*SDL_GL_ACCUM_BLUE_SIZE+1] + attrib[2*SDL_GL_ACCUM_ALPHA_SIZE+1]; + +/* !!! FIXME + attribs[i++] = GLX_STEREO; + attribs[i++] = attrib[2*SDL_GL_STEREO+1]; + attribs[i++] = GLX_BUFFER_SIZE; + attribs[i++] = attrib[2*SDL_GL_BUFFER_SIZE+1]; + attribs[i++] = GLX_DOUBLEBUFFER; + attribs[i++] = attrib[2*SDL_GL_DOUBLEBUFFER+1]; +*/ + + attribs[i++] = 0; + + err = CGLChoosePixelFormat(attribs, &render_target->fmt, &npix); + if ((err) || (render_target->fmt == NULL)) + return -1; + + err = CGLCreateContext(render_target->fmt, ctx, &render_target->ctx); + if (err) + return -1; + + CGLGetVirtualScreen(render_target->ctx, &render_target->screen); + + if (pCGLCreatePBuffer(width, height, GL_TEXTURE_2D, target->format, 0, &render_target->pbuffer)) + return -1; + + if (pCGLSetPBuffer(render_target->ctx, render_target->pbuffer, 0, 0, render_target->screen)) + return -1; + + return 0; +} + +/* Get attribute information about the render target. */ +int QZ_GL_GetRenderTargetAttribute(_THIS, SDL_RenderTarget *target, SDL_GLattr attrib, int* value) +{ + QZ_RenderTargetData *render_target = (QZ_RenderTargetData *) target->gl_data; + CGLPixelFormatAttribute attr; + long val = 0; + + switch( attrib ) { + case SDL_GL_RED_SIZE: + case SDL_GL_GREEN_SIZE: + case SDL_GL_BLUE_SIZE: + case SDL_GL_BUFFER_SIZE: + attr = kCGLPFAColorSize; /* !!! FIXME */ + break; + + case SDL_GL_ACCUM_RED_SIZE: + case SDL_GL_ACCUM_GREEN_SIZE: + case SDL_GL_ACCUM_BLUE_SIZE: + case SDL_GL_ACCUM_ALPHA_SIZE: + attr = kCGLPFAAccumSize; /* !!! FIXME */ + break; + + case SDL_GL_ALPHA_SIZE: + attr = kCGLPFAAlphaSize; + break; + + case SDL_GL_DEPTH_SIZE: + attr = kCGLPFADepthSize; + break; + + case SDL_GL_STENCIL_SIZE: + attr = kCGLPFAStencilSize; + break; + + case SDL_GL_DOUBLEBUFFER: /* !!! FIXME */ + case SDL_GL_STEREO: + *value = 0; + return 0; + + default: + return -1; + } + + if (CGLDescribePixelFormat(render_target->fmt, render_target->screen, attr, &val)) + return -1; + + switch (attrib) + { + case SDL_GL_RED_SIZE: + case SDL_GL_GREEN_SIZE: + case SDL_GL_BLUE_SIZE: + case SDL_GL_ACCUM_RED_SIZE: + case SDL_GL_ACCUM_GREEN_SIZE: + case SDL_GL_ACCUM_BLUE_SIZE: + case SDL_GL_ACCUM_ALPHA_SIZE: + *value = (int) (val / 4); /* !!! FIXME */ + break; + + default: + *value = (int) val; + break; + } + + return 0; +} + +/* Set the render target as the current OpenGL draw target. */ +void QZ_GL_LockRenderTarget(_THIS, SDL_RenderTarget *target) +{ + QZ_RenderTargetData *render_target = (QZ_RenderTargetData *) target->gl_data; + if (CGLSetCurrentContext(render_target->ctx)) + fprintf(stderr, "CGLSetCurrentContext failed!\n"); +} + +void QZ_GL_UnlockRenderTarget(_THIS, SDL_RenderTarget *target) +{ + QZ_RenderTargetData *render_target = (QZ_RenderTargetData *) target->gl_data; + + glFlush(); + + [ gl_context makeCurrentContext ]; + + /* Update the texture with the pbuffer contents... */ + + /* !!! FIXME: + * This doesn't need to be done every unlock; Apple's GL picks + * up pbuffer changes automatically, and only needs manual + * updates if you specify a different texture name or are using + * mipmaps. Are we taking a performance hit here? + */ + + if (target->texture) { + CGLContextObj ctx = [ gl_context cglContext ]; + GLenum gl_error; + glBindTexture(GL_TEXTURE_2D, target->texture); + gl_error = glGetError(); + if( gl_error != GL_NO_ERROR ) { + fprintf( stderr, "opengl error: %d (0x%4.4x)\n", gl_error, gl_error ); + } + if (pCGLTexImagePBuffer(ctx, render_target->pbuffer, GL_FRONT)) + fprintf(stderr, "CGLTexImagePBuffer failed!\n"); + } +} + +/* Release any resources associated with the target */ +void QZ_GL_FreeRenderTarget(_THIS, SDL_RenderTarget *target) +{ + QZ_RenderTargetData *render_target = (QZ_RenderTargetData *) target->gl_data; + if (render_target) + { + if (render_target->fmt) + CGLDestroyPixelFormat(render_target->fmt); + + if (render_target->pbuffer) + pCGLDestroyPBuffer(render_target->pbuffer); + + if (render_target->ctx) + CGLDestroyContext(render_target->ctx); + + free(render_target); + target->gl_data = NULL; + } +} + + +/* (stolen from the X11 target... --ryan.) */ +static int ExtensionSupported(const char *extension, const char *extensions) +{ + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = strchr(extension, ' '); + if ( where || *extension == '\0' ) + return 0; + + if ( ! extensions ) + return 0; + + /* It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, + * etc. */ + + start = extensions; + + for (;;) + { + where = strstr(start, extension); + if (!where) break; + + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') return 1; + + start = terminator; + } + + return 0; +} + +static void CheckExtensions(_THIS) +{ + const char *extensions = (const char *) glGetString(GL_EXTENSIONS); + + /* Currently, we only care about pbuffers for RenderTarget support... */ + if ( (ExtensionSupported("GL_APPLE_pixel_buffer", extensions)) && + (LookupPBufferFuncs(this)) ) { + this->GL_CreateRenderTarget = QZ_GL_CreateRenderTarget; + this->GL_GetRenderTargetAttribute = QZ_GL_GetRenderTargetAttribute; + this->GL_LockRenderTarget = QZ_GL_LockRenderTarget; + this->GL_UnlockRenderTarget = QZ_GL_UnlockRenderTarget; + this->GL_FreeRenderTarget = QZ_GL_FreeRenderTarget; + } else { + this->GL_CreateRenderTarget = NULL; + this->GL_GetRenderTargetAttribute = NULL; + this->GL_LockRenderTarget = NULL; + this->GL_UnlockRenderTarget = NULL ; + this->GL_FreeRenderTarget = NULL; + } +} + int QZ_GL_MakeCurrent (_THIS) { [ gl_context makeCurrentContext ]; + + /* Once the context is current, check extensions */ + if ( ! this->hidden->gl_extensions_checked ) { + CheckExtensions(this); + this->hidden->gl_extensions_checked = 1; + } + return 0; } diff -ruN -x CVS SDL12/src/video/quartz/SDL_QuartzVideo.h SDL13/src/video/quartz/SDL_QuartzVideo.h --- SDL12/src/video/quartz/SDL_QuartzVideo.h 2006-01-01 16:31:00.000000000 -0800 +++ SDL13/src/video/quartz/SDL_QuartzVideo.h 2006-01-31 23:10:13.000000000 -0800 @@ -84,6 +84,7 @@ CFArrayRef mode_list; /* list of available fullscreen modes */ CGDirectPaletteRef palette; /* palette of an 8-bit display */ NSOpenGLContext *gl_context; /* OpenGL rendering context */ + BOOL gl_extensions_checked; /* OpenGL extensions looked up? */ Uint32 width, height, bpp; /* frequently used data about the display */ Uint32 flags; /* flags for current mode, for teardown purposes */ Uint32 video_set; /* boolean; indicates if video was set correctly */ diff -ruN -x CVS SDL12/src/video/SDL_glfuncs.h SDL13/src/video/SDL_glfuncs.h --- SDL12/src/video/SDL_glfuncs.h 2006-01-31 23:41:48.000000000 -0800 +++ SDL13/src/video/SDL_glfuncs.h 2003-09-21 11:10:21.000000000 -0700 @@ -59,10 +59,10 @@ SDL_PROC_UNUSED(void,glCopyTexImage1D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border)) SDL_PROC_UNUSED(void,glCopyTexImage2D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)) SDL_PROC_UNUSED(void,glCopyTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)) -SDL_PROC_UNUSED(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC(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)) @@ -107,7 +107,7 @@ SDL_PROC_UNUSED(void,glGetDoublev,(GLenum pname, GLdouble *params)) SDL_PROC_UNUSED(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)) diff -ruN -x CVS SDL12/src/video/SDL_sysvideo.h SDL13/src/video/SDL_sysvideo.h --- SDL12/src/video/SDL_sysvideo.h 2006-01-31 22:32:16.000000000 -0800 +++ SDL13/src/video/SDL_sysvideo.h 2006-01-31 23:10:09.000000000 -0800 @@ -194,6 +194,19 @@ /* Swap the current buffers in double buffer mode. */ void (*GL_SwapBuffers)(_THIS); + /* Create a render target with the given size and attributes. */ + int (*GL_CreateRenderTarget)(_THIS, SDL_RenderTarget *target, int width, int height, int *attrib); + + /* Get attribute information about the render target. */ + int (*GL_GetRenderTargetAttribute)(_THIS, SDL_RenderTarget *target, SDL_GLattr attrib, int* value); + + /* Set the render target as the current OpenGL draw target. */ + void (*GL_LockRenderTarget)(_THIS, SDL_RenderTarget *target); + void (*GL_UnlockRenderTarget)(_THIS, SDL_RenderTarget *target); + + /* Release any resources associated with the target */ + void (*GL_FreeRenderTarget)(_THIS, SDL_RenderTarget *target); + /* OpenGL functions for SDL_OPENGLBLIT */ #ifdef HAVE_OPENGL #ifndef WIN32 diff -ruN -x CVS SDL12/src/video/SDL_video.c SDL13/src/video/SDL_video.c --- SDL12/src/video/SDL_video.c 2006-01-31 23:39:11.000000000 -0800 +++ SDL13/src/video/SDL_video.c 2006-01-31 23:10:09.000000000 -0800 @@ -1429,6 +1429,168 @@ } } +/* Create a render target with the given size and attributes. */ +SDL_RenderTarget *SDL_GL_CreateRenderTarget(int width, int height, int *attrib) +{ + SDL_VideoDevice *video = current_video; + SDL_RenderTarget *target; + + /* These are carefully ordered so they match the order of the enum */ + int complete_attrib[] = { + SDL_GL_RED_SIZE, 0, + SDL_GL_GREEN_SIZE, 0, + SDL_GL_BLUE_SIZE, 0, + SDL_GL_ALPHA_SIZE, 0, + SDL_GL_BUFFER_SIZE, 0, + SDL_GL_DOUBLEBUFFER, 0, + SDL_GL_DEPTH_SIZE, 0, + SDL_GL_STENCIL_SIZE, 0, + SDL_GL_ACCUM_RED_SIZE, 0, + SDL_GL_ACCUM_GREEN_SIZE, 0, + SDL_GL_ACCUM_BLUE_SIZE, 0, + SDL_GL_ACCUM_ALPHA_SIZE, 0, + SDL_GL_STEREO, 0, + 0 + }; + + if ( !video || + !SDL_PublicSurface || !(SDL_PublicSurface->flags & SDL_OPENGL) ) { + SDL_SetError("You must first set an OpenGL video mode"); + return(NULL); + } + + if ( !video->GL_CreateRenderTarget ) { + SDL_SetError("Render to texture not supported"); + return(NULL); + } + + /* Default attribute information comes from window */ + complete_attrib[2*SDL_GL_RED_SIZE+1] = video->gl_config.red_size; + complete_attrib[2*SDL_GL_GREEN_SIZE+1] = video->gl_config.green_size; + complete_attrib[2*SDL_GL_BLUE_SIZE+1] = video->gl_config.blue_size; + complete_attrib[2*SDL_GL_ALPHA_SIZE+1] = video->gl_config.alpha_size; + complete_attrib[2*SDL_GL_BUFFER_SIZE+1] = video->gl_config.buffer_size; + complete_attrib[2*SDL_GL_DOUBLEBUFFER+1] = video->gl_config.double_buffer; + complete_attrib[2*SDL_GL_DEPTH_SIZE+1] = video->gl_config.depth_size; + complete_attrib[2*SDL_GL_STENCIL_SIZE+1] = video->gl_config.stencil_size; + complete_attrib[2*SDL_GL_ACCUM_RED_SIZE+1] = video->gl_config.accum_red_size; + complete_attrib[2*SDL_GL_ACCUM_GREEN_SIZE+1] = video->gl_config.accum_green_size; + complete_attrib[2*SDL_GL_ACCUM_BLUE_SIZE+1] = video->gl_config.accum_blue_size; + complete_attrib[2*SDL_GL_ACCUM_ALPHA_SIZE+1] = video->gl_config.accum_alpha_size; + complete_attrib[2*SDL_GL_STEREO+1] = video->gl_config.stereo; +#if 0 /* FIXME - we need to use a separate context for this to work */ + /* Double buffer and stereo probably aren't what we want for a + * pbuffer, even if the window is using them, and possibly are + * not supported on some cards/drivers, so default to off */ + complete_attrib[2*SDL_GL_DOUBLEBUFFER+1] = GL_FALSE; + complete_attrib[2*SDL_GL_STEREO+1] = GL_FALSE; +#endif + + /* Copy attribute information from the parameters */ + if ( attrib ) { + int i, j; + for ( i = 0; attrib[i] || attrib[i+1]; i += 2 ) { + for ( j = 0; complete_attrib[j] || complete_attrib[j+1]; j += 2 ) { + if ( attrib[i] == complete_attrib[j] ) { + complete_attrib[i+1] = attrib[j+1]; + break; + } + } + } + } + + target = (SDL_RenderTarget *)malloc(sizeof(*target)); + if ( !target ) { + SDL_OutOfMemory(); + return(NULL); + } + memset(target, 0, sizeof(*target)); + + if ( complete_attrib[SDL_GL_ALPHA_SIZE] > 0 ) { + target->format = GL_RGBA; + } else { + target->format = GL_RGB; + } + target->w = width; + target->h = height; + + if ( video->GL_CreateRenderTarget(video, target, width, height, complete_attrib) < 0 ) { + SDL_GL_FreeRenderTarget(target); + return(NULL); + } + return(target); +} + +/* Get attribute information about the render target. */ +int SDL_GL_GetRenderTargetAttribute(SDL_RenderTarget *target, SDL_GLattr attrib, int* value) +{ + SDL_VideoDevice *video = current_video; + if ( !target ) { + SDL_SetError("Passed NULL render target"); + return -1; + } + return video->GL_GetRenderTargetAttribute(video, target, attrib, value); +} + +/* + * Set the texture that contains the color buffer of the render target + * after it is unlocked. The texture contents are only valid outside of + * the render target lock and unlock calls. + */ +void SDL_GL_BindRenderTarget(SDL_RenderTarget *target, unsigned int texture) +{ + SDL_VideoDevice *video = current_video; + +/* !!! FIXME: Apple's pbuffer extension can't use a texture that's + * !!! FIXME: previously been used for regular stuff (like TexImage2D). + */ +#ifndef MACOSX + video->glBindTexture(GL_TEXTURE_2D, texture); + video->glTexImage2D(GL_TEXTURE_2D, + 0, + target->format, + target->w, target->h, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + NULL); +#endif + target->texture = texture; +} + +/* Set the render target as the current OpenGL draw target. */ +void SDL_GL_LockRenderTarget(SDL_RenderTarget *target) +{ + SDL_VideoDevice *video = current_video; + if ( target && !target->current ) { + video->GL_LockRenderTarget(video, target); + target->current = 1; + } +} + +/* + * Set the screen as the current OpenGL draw target. + * If there is a texture bound to the render target, this texture is updated + * with the color buffer of the render target. + */ +void SDL_GL_UnlockRenderTarget(SDL_RenderTarget *target) +{ + SDL_VideoDevice *video = current_video; + if ( target && target->current ) { + video->GL_UnlockRenderTarget(video, target); + target->current = 0; + } +} + +/* Release any resources associated with the target */ +void SDL_GL_FreeRenderTarget(SDL_RenderTarget *target) +{ + SDL_VideoDevice *video = current_video; + SDL_GL_UnlockRenderTarget(target); + video->GL_FreeRenderTarget(video, target); + free(target); +} + /* * Sets/Gets the title and icon text of the display window, if any. */ diff -ruN -x CVS SDL12/src/video/wincommon/SDL_wingl.c SDL13/src/video/wincommon/SDL_wingl.c --- SDL12/src/video/wincommon/SDL_wingl.c 2006-02-01 00:06:26.000000000 -0800 +++ SDL13/src/video/wincommon/SDL_wingl.c 2006-01-31 23:10:14.000000000 -0800 @@ -155,6 +155,62 @@ } } + this->gl_data->WGL_ARB_pbuffer = 0; + if( ExtensionSupported("WGL_ARB_pbuffer", extensions) ) { + this->gl_data->wglCreatePbufferARB = + (HPBUFFERARB (WINAPI *)(HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList)) + this->gl_data->wglGetProcAddress("wglCreatePbufferARB"); + this->gl_data->wglGetPbufferDCARB = + (HDC (WINAPI *) (HPBUFFERARB hPbuffer)) + this->gl_data->wglGetProcAddress("wglGetPbufferDCARB"); + this->gl_data->wglReleasePbufferDCARB = + (int (WINAPI *)(HPBUFFERARB hPbuffer, HDC hDC)) + this->gl_data->wglGetProcAddress("wglReleasePbufferDCARB"); + this->gl_data->wglDestroyPbufferARB = + (BOOL (WINAPI *)(HPBUFFERARB hPbuffer)) + this->gl_data->wglGetProcAddress("wglDestroyPbufferARB"); + this->gl_data->wglQueryPbufferARB = + (BOOL (WINAPI *)(HPBUFFERARB hPbuffer, int iAttribute, int *piValue)) + this->gl_data->wglGetProcAddress("wglQueryPbufferARB"); + + if( (this->gl_data->wglCreatePbufferARB != NULL) && + (this->gl_data->wglGetPbufferDCARB != NULL) && + (this->gl_data->wglReleasePbufferDCARB != NULL) && + (this->gl_data->wglDestroyPbufferARB != NULL) && + (this->gl_data->wglQueryPbufferARB != NULL) ) { + this->gl_data->WGL_ARB_pbuffer = 1; + } + } + if( this->gl_data->WGL_ARB_pixel_format && + this->gl_data->WGL_ARB_pbuffer ) { + this->GL_CreateRenderTarget = WIN_GL_CreateRenderTarget; + this->GL_GetRenderTargetAttribute = WIN_GL_GetRenderTargetAttribute; + this->GL_LockRenderTarget = WIN_GL_LockRenderTarget; + this->GL_UnlockRenderTarget = WIN_GL_UnlockRenderTarget ; + this->GL_FreeRenderTarget = WIN_GL_FreeRenderTarget; + } else { + this->GL_CreateRenderTarget = NULL; + this->GL_GetRenderTargetAttribute = NULL; + this->GL_LockRenderTarget = NULL; + this->GL_UnlockRenderTarget = NULL ; + this->GL_FreeRenderTarget = NULL; + } + + this->gl_data->WGL_ARB_render_texture = 0; + if( ExtensionSupported("WGL_ARB_render_texture", extensions) ) { + this->gl_data->wglBindTexImageARB = + (BOOL (WINAPI *)(HPBUFFERARB hPbuffer, int iBuffer)) + this->gl_data->wglGetProcAddress("wglBindTexImageARB"); + this->gl_data->wglReleaseTexImageARB = + (BOOL (WINAPI *)(HPBUFFERARB hPbuffer, int iBuffer)) + this->gl_data->wglGetProcAddress("wglReleaseTexImageARB"); + + if( (this->gl_data->wglBindTexImageARB != NULL) && + (this->gl_data->wglReleaseTexImageARB != NULL) ) { + this->gl_data->WGL_ARB_render_texture = 1; + } + } + if ( hglrc ) { this->gl_data->wglMakeCurrent(NULL, NULL); this->gl_data->wglDeleteContext(hglrc); @@ -495,6 +552,295 @@ SwapBuffers(GL_hdc); } +typedef struct WIN_RenderTargetData { + int format; + HPBUFFERARB hPbuffer; + HDC hPbufferDC; + int buffer; + HGLRC hPbufferRC; +} WIN_RenderTargetData; + +static BOOL CreateRenderTarget(_THIS, SDL_RenderTarget *target) +{ + WIN_RenderTargetData *render_target = (WIN_RenderTargetData *)target->gl_data; + int i, pbAttribs[5]; + + i = 0; + if ( this->gl_data->WGL_ARB_render_texture ) { + pbAttribs[i++] = WGL_TEXTURE_FORMAT_ARB; + if ( target->format == GL_RGB ) { + pbAttribs[i++] = WGL_TEXTURE_RGB_ARB; + } else { + pbAttribs[i++] = WGL_TEXTURE_RGBA_ARB; + } + pbAttribs[i++] = WGL_TEXTURE_TARGET_ARB; + pbAttribs[i++] = WGL_TEXTURE_2D_ARB; + } + pbAttribs[i++] = 0; + + render_target->hPbuffer = this->gl_data->wglCreatePbufferARB(GL_hdc, render_target->format, target->w, target->h, pbAttribs); + if ( !render_target->hPbuffer ) { + SDL_SetError("Couldn't create pbuffer with desired attributes"); + return FALSE; + } + render_target->hPbufferDC = this->gl_data->wglGetPbufferDCARB(render_target->hPbuffer); + render_target->hPbufferRC = this->gl_data->wglCreateContext(render_target->hPbufferDC); + if (GL_FALSE==this->gl_data->wglShareLists(GL_hrc,render_target->hPbufferRC)) { + SDL_SetError("Couldn't share display lists and textures with main RC"); + } + return TRUE; +} + +static void DestroyRenderTarget(_THIS, SDL_RenderTarget *target) +{ + WIN_RenderTargetData *render_target = (WIN_RenderTargetData *)target->gl_data; + if (render_target->hPbufferRC) { + this->gl_data->wglDeleteContext(render_target->hPbufferRC); + } + if ( render_target->hPbuffer ) { + this->gl_data->wglReleasePbufferDCARB(render_target->hPbuffer, render_target->hPbufferDC); + this->gl_data->wglDestroyPbufferARB(render_target->hPbuffer); + render_target->hPbuffer = NULL; + } +} + +int WIN_GL_CreateRenderTarget(_THIS, SDL_RenderTarget *target, int width, int height, int *attrib) +{ + WIN_RenderTargetData *render_target; + /* 64 seems nice. */ + int i, attribs[64]; + float fAttribs[] = { 0 }; + unsigned int matching; + int formats[16]; + + /* Allocate memory for data */ + render_target = (WIN_RenderTargetData *)malloc(sizeof(*render_target)); + if ( ! render_target ) { + SDL_OutOfMemory(); + return(-1); + } + memset(render_target, 0, sizeof(*render_target)); + target->gl_data = render_target; + + /* setup WGL_ARB_pixel_format attribs */ + i = 0; + attribs[i++] = WGL_SUPPORT_OPENGL_ARB; + attribs[i++] = GL_TRUE; + attribs[i++] = WGL_DRAW_TO_PBUFFER_ARB; + attribs[i++] = GL_TRUE; + attribs[i++] = WGL_ACCELERATION_ARB; + attribs[i++] = WGL_FULL_ACCELERATION_ARB; + if ( this->gl_data->WGL_ARB_render_texture ) { + if ( attrib[2*SDL_GL_ALPHA_SIZE+1] > 0 ) { + attribs[i++] = WGL_BIND_TO_TEXTURE_RGBA_ARB; + attribs[i++] = GL_TRUE; + } else { + attribs[i++] = WGL_BIND_TO_TEXTURE_RGB_ARB; + attribs[i++] = GL_TRUE; + } + } + attribs[i++] = WGL_RED_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_RED_SIZE+1]; + attribs[i++] = WGL_GREEN_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_GREEN_SIZE+1]; + attribs[i++] = WGL_BLUE_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_BLUE_SIZE+1]; + + if ( attrib[2*SDL_GL_ALPHA_SIZE+1] ) { + attribs[i++] = WGL_ALPHA_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_ALPHA_SIZE+1]; + } + + attribs[i++] = WGL_DOUBLE_BUFFER_ARB; + attribs[i++] = attrib[2*SDL_GL_DOUBLEBUFFER+1]; + + attribs[i++] = WGL_DEPTH_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_DEPTH_SIZE+1]; + + if ( attrib[2*SDL_GL_STENCIL_SIZE+1] ) { + attribs[i++] = WGL_STENCIL_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_STENCIL_SIZE+1]; + } + + if ( attrib[2*SDL_GL_ACCUM_RED_SIZE+1] ) { + attribs[i++] = WGL_ACCUM_RED_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_ACCUM_RED_SIZE+1]; + } + + if ( attrib[2*SDL_GL_ACCUM_GREEN_SIZE+1] ) { + attribs[i++] = WGL_ACCUM_GREEN_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_ACCUM_GREEN_SIZE+1]; + } + + if ( attrib[2*SDL_GL_ACCUM_BLUE_SIZE+1] ) { + attribs[i++] = WGL_ACCUM_BLUE_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_ACCUM_BLUE_SIZE+1]; + } + + if ( attrib[2*SDL_GL_ACCUM_ALPHA_SIZE+1] ) { + attribs[i++] = WGL_ACCUM_ALPHA_BITS_ARB; + attribs[i++] = attrib[2*SDL_GL_ACCUM_ALPHA_SIZE+1]; + } + + if ( attrib[2*SDL_GL_STEREO+1] ) { + attribs[i++] = WGL_STEREO_ARB; + attribs[i++] = GL_TRUE; + } + + attribs[i++] = 0; + + /* Choose and set the closest available pixel format. Try to + * get more than one, since some drivers seem to return values + * that don't actually work? */ + if ( !this->gl_data->WGL_ARB_pixel_format || + !this->gl_data->wglChoosePixelFormatARB(GL_hdc, attribs, fAttribs, 16, formats, &matching) || + !matching ) { + SDL_SetError("No matching GL pixel format available"); + return(-1); + } + + for (i=0;iformat = formats[i]; + /* Create a pbuffer with the desired format */ + if ( !CreateRenderTarget(this, target) ) { + SDL_SetError("Couldn't create pbuffer with desired attributes"); + continue; + } else { + return (0); + } + } + SDL_SetError("Couldn't create pbuffer with desired attributes - giving up"); + return(-1); +} + +int WIN_GL_GetRenderTargetAttribute(_THIS, SDL_RenderTarget *target, SDL_GLattr attrib, int* value) +{ + WIN_RenderTargetData *render_target = (WIN_RenderTargetData *)target->gl_data; + int wgl_attrib; + + switch(attrib) { + case SDL_GL_RED_SIZE: + wgl_attrib = WGL_RED_BITS_ARB; + break; + case SDL_GL_GREEN_SIZE: + wgl_attrib = WGL_GREEN_BITS_ARB; + break; + case SDL_GL_BLUE_SIZE: + wgl_attrib = WGL_BLUE_BITS_ARB; + break; + case SDL_GL_ALPHA_SIZE: + wgl_attrib = WGL_ALPHA_BITS_ARB; + break; + case SDL_GL_DOUBLEBUFFER: + wgl_attrib = WGL_DOUBLE_BUFFER_ARB; + break; + case SDL_GL_BUFFER_SIZE: + wgl_attrib = WGL_COLOR_BITS_ARB; + break; + case SDL_GL_DEPTH_SIZE: + wgl_attrib = WGL_DEPTH_BITS_ARB; + break; + case SDL_GL_STENCIL_SIZE: + wgl_attrib = WGL_STENCIL_BITS_ARB; + break; + case SDL_GL_ACCUM_RED_SIZE: + wgl_attrib = WGL_ACCUM_RED_BITS_ARB; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB; + break; + case SDL_GL_STEREO: + wgl_attrib = WGL_STEREO_ARB; + break; + default: + return(-1); + } + this->gl_data->wglGetPixelFormatAttribivARB(render_target->hPbufferDC, render_target->format, 0, 1, &wgl_attrib, value); + + return 0; +} + +void WIN_GL_LockRenderTarget(_THIS, SDL_RenderTarget *target) +{ + WIN_RenderTargetData *render_target = (WIN_RenderTargetData *)target->gl_data; + int gone; + + /* Release the pbuffer so it can be rendered to */ + if ( target->texture && render_target->buffer ) { + this->gl_data->wglReleaseTexImageARB(render_target->hPbuffer, render_target->buffer); + } + + /* Make sure the pbuffer hasn't gone away */ + this->gl_data->wglQueryPbufferARB(render_target->hPbuffer, WGL_PBUFFER_LOST_ARB, &gone); + if ( gone ) { + DestroyRenderTarget(this, target); + CreateRenderTarget(this, target); + } + /* Set the draw target */ + this->gl_data->wglMakeCurrent(render_target->hPbufferDC, render_target->hPbufferRC); + +} + +void WIN_GL_UnlockRenderTarget(_THIS, SDL_RenderTarget *target) +{ + WIN_RenderTargetData *render_target = (WIN_RenderTargetData *)target->gl_data; + + /* Update the texture with the pbuffer contents */ + if ( target->texture ) { + if ( this->gl_data->WGL_ARB_render_texture ) { + int drawBuffer = 0; + this->glGetIntegerv(GL_DRAW_BUFFER, &drawBuffer); + /* Reset the draw target */ + this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc); + this->glBindTexture(GL_TEXTURE_2D, target->texture); + switch(drawBuffer) { + case GL_FRONT: + case GL_FRONT_LEFT: + render_target->buffer = WGL_FRONT_LEFT_ARB; + break; + case GL_FRONT_RIGHT: + render_target->buffer = WGL_FRONT_RIGHT_ARB; + break; + case GL_BACK: + case GL_BACK_LEFT: + render_target->buffer = WGL_BACK_LEFT_ARB; + break; + case GL_BACK_RIGHT: + render_target->buffer = WGL_BACK_RIGHT_ARB; + break; + default: + render_target->buffer = WGL_FRONT_LEFT_ARB; + break; + } + this->gl_data->wglBindTexImageARB(render_target->hPbuffer, render_target->buffer); + } else { + this->glBindTexture(GL_TEXTURE_2D, target->texture); + this->glCopyTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, 0, + 0, 0, + target->w, target->h); + /* Reset the draw target */ + this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc); + } + } + +} + +void WIN_GL_FreeRenderTarget(_THIS, SDL_RenderTarget *target) +{ + WIN_RenderTargetData *render_target = (WIN_RenderTargetData *)target->gl_data; + + DestroyRenderTarget(this, target); + free(render_target); +} + void WIN_GL_UnloadLibrary(_THIS) { if ( this->gl_config.driver_loaded ) { @@ -544,11 +890,14 @@ GetProcAddress(handle, "wglDeleteContext"); this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC)) GetProcAddress(handle, "wglMakeCurrent"); + this->gl_data->wglShareLists = (BOOL (WINAPI *)(HGLRC, HGLRC)) + GetProcAddress(handle, "wglShareLists"); if ( (this->gl_data->wglGetProcAddress == NULL) || (this->gl_data->wglCreateContext == NULL) || (this->gl_data->wglDeleteContext == NULL) || - (this->gl_data->wglMakeCurrent == NULL) ) { + (this->gl_data->wglMakeCurrent == NULL) || + (this->gl_data->wglShareLists == NULL) ) { SDL_SetError("Could not retrieve OpenGL functions"); FreeLibrary(handle); return -1; diff -ruN -x CVS SDL12/src/video/wincommon/SDL_wingl_c.h SDL13/src/video/wincommon/SDL_wingl_c.h --- SDL12/src/video/wincommon/SDL_wingl_c.h 2006-01-31 23:51:35.000000000 -0800 +++ SDL13/src/video/wincommon/SDL_wingl_c.h 2006-01-31 23:10:14.000000000 -0800 @@ -24,6 +24,13 @@ #include "SDL_sysvideo.h" +#ifdef HAVE_OPENGL + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif + +#endif /* HAVE_OPENGL */ struct SDL_PrivateGLData { int gl_active; /* to stop switching drivers while we have a valid context */ @@ -34,14 +41,15 @@ HGLRC GL_hrc; int pixel_format; int WGL_ARB_pixel_format; + int WGL_ARB_pbuffer; + int WGL_ARB_render_texture; void * (WINAPI *wglGetProcAddress)(const char *proc); HGLRC (WINAPI *wglCreateContext)(HDC hdc); - BOOL (WINAPI *wglDeleteContext)(HGLRC hglrc); - BOOL (WINAPI *wglMakeCurrent)(HDC hdc, HGLRC hglrc); + BOOL (WINAPI *wglShareLists)(HGLRC rc1, HGLRC rc2); BOOL (WINAPI *wglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, @@ -52,6 +60,16 @@ UINT nAttributes, const int *piAttributes, int *piValues); + + HPBUFFERARB (WINAPI *wglCreatePbufferARB)(HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *wglGetPbufferDCARB) (HPBUFFERARB hPbuffer); + int (WINAPI *wglReleasePbufferDCARB)(HPBUFFERARB hPbuffer, HDC hDC); + BOOL (WINAPI *wglDestroyPbufferARB)(HPBUFFERARB hPbuffer); + BOOL (WINAPI *wglQueryPbufferARB)(HPBUFFERARB hPbuffer, int iAttribute, int *piValue); + + BOOL (WINAPI *wglBindTexImageARB)(HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *wglReleaseTexImageARB)(HPBUFFERARB hPbuffer, int iBuffer); + #endif /* HAVE_OPENGL */ }; @@ -72,6 +90,11 @@ extern void WIN_GL_UnloadLibrary(_THIS); extern int WIN_GL_LoadLibrary(_THIS, const char* path); extern void *WIN_GL_GetProcAddress(_THIS, const char* proc); +extern int WIN_GL_CreateRenderTarget(_THIS, SDL_RenderTarget *target, int width, int height, int *attrib); +extern int WIN_GL_GetRenderTargetAttribute(_THIS, SDL_RenderTarget *target, SDL_GLattr attrib, int* value); +extern void WIN_GL_LockRenderTarget(_THIS, SDL_RenderTarget *target); +extern void WIN_GL_UnlockRenderTarget(_THIS, SDL_RenderTarget *target); +extern void WIN_GL_FreeRenderTarget(_THIS, SDL_RenderTarget *target); #endif #ifdef HAVE_OPENGL @@ -133,4 +156,27 @@ #define WGL_SAMPLES_ARB 0x2042 #endif +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_PBUFFER_LOST_ARB 0x2036 #endif + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#endif + +#endif /* HAVE_OPENGL */ diff -ruN -x CVS SDL12/src/video/x11/SDL_x11gl.c SDL13/src/video/x11/SDL_x11gl.c --- SDL12/src/video/x11/SDL_x11gl.c 2006-02-01 00:03:52.000000000 -0800 +++ SDL13/src/video/x11/SDL_x11gl.c 2006-02-01 00:10:12.000000000 -0800 @@ -219,6 +219,7 @@ } gl_active = 1; + gl_extensions_checked = 0; #else SDL_SetError("X11 driver not configured with OpenGL"); #endif @@ -248,6 +249,75 @@ #ifdef HAVE_OPENGL_X11 +static int ExtensionSupported(const char *extension, const char *extensions) +{ + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = strchr(extension, ' '); + if ( where || *extension == '\0' ) + return 0; + + if ( ! extensions ) + return 0; + + /* It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, + * etc. */ + + start = extensions; + + for (;;) + { + where = strstr(start, extension); + if (!where) break; + + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') return 1; + + start = terminator; + } + + return 0; +} + +static void CheckExtensions(_THIS) +{ + const char *extensions; + const char *glx_extensions; + + /* What extensions are available? */ + extensions = (const char *)this->glGetString(GL_EXTENSIONS); + if ( this->gl_data->glXQueryExtensionsString ) { + glx_extensions = (const char *)this->gl_data->glXQueryExtensionsString(GFX_Display, SDL_Screen); + } else { + glx_extensions = NULL; + } + + if ( ((this->gl_data->glx_version >= MAKE_GLX_VERSION(1, 3)) || + (ExtensionSupported("GLX_SGIX_fbconfig", glx_extensions) && + ExtensionSupported("GLX_SGIX_pbuffer", glx_extensions))) && + (this->gl_data->glXChooseFBConfigSGIX != NULL) && + (this->gl_data->glXGetFBConfigAttribSGIX != NULL) && + ((this->gl_data->glXCreateGLXPbufferSGIX != NULL) || + (this->gl_data->glXCreatePbuffer != NULL)) && + (this->gl_data->glXDestroyGLXPbufferSGIX != NULL) ) { + this->GL_CreateRenderTarget = X11_GL_CreateRenderTarget; + this->GL_GetRenderTargetAttribute = X11_GL_GetRenderTargetAttribute; + this->GL_LockRenderTarget = X11_GL_LockRenderTarget; + this->GL_UnlockRenderTarget = X11_GL_UnlockRenderTarget ; + this->GL_FreeRenderTarget = X11_GL_FreeRenderTarget; + } else { + this->GL_CreateRenderTarget = NULL; + this->GL_GetRenderTargetAttribute = NULL; + this->GL_LockRenderTarget = NULL; + this->GL_UnlockRenderTarget = NULL ; + this->GL_FreeRenderTarget = NULL; + } +} + /* Make the current context active */ int X11_GL_MakeCurrent(_THIS) { @@ -261,6 +331,12 @@ } pXSync( GFX_Display, False ); + /* Once the context is current, check extensions */ + if ( ! gl_extensions_checked ) { + CheckExtensions(this); + gl_extensions_checked = 1; + } + /* More Voodoo X server workarounds... Grr... */ SDL_Lock_EventThread(); X11_CheckDGAMouse(this); @@ -335,6 +411,266 @@ this->gl_data->glXSwapBuffers(GFX_Display, SDL_Window); } +typedef struct X11_RenderTargetData { + GLXFBConfigSGIX config; + GLXPbuffer pbuffer; +} X11_RenderTargetData; + +/* This is only used by X11_GL_CreateRenderTarget() */ +static int XErrorFlag = 0; +static int HandleXError( Display *dpy, XErrorEvent *event ) +{ + XErrorFlag = 1; + return 0; +} + +#ifdef DEBUG_FBCONFIG +void PrintFBConfigInfo(_THIS, GLXFBConfigSGIX fbConfig) +{ + int bufferSize, level, doubleBuffer, stereo, auxBuffers; + int redSize, greenSize, blueSize, alphaSize; + int depthSize, stencilSize; + int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize; + int drawableType, renderType, xRenderable, xVisual, id; + + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_BUFFER_SIZE, &bufferSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_LEVEL, &level); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_DOUBLEBUFFER, &doubleBuffer); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_STEREO, &stereo); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_AUX_BUFFERS, &auxBuffers); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_RED_SIZE, &redSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_GREEN_SIZE, &greenSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_BLUE_SIZE, &blueSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_ALPHA_SIZE, &alphaSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_DEPTH_SIZE, &depthSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_STENCIL_SIZE, &stencilSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_ACCUM_RED_SIZE, &accumRedSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_ACCUM_GREEN_SIZE, &accumGreenSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_ACCUM_BLUE_SIZE, &accumBlueSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_ACCUM_ALPHA_SIZE, &accumAlphaSize); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_DRAWABLE_TYPE_SGIX, &drawableType); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_RENDER_TYPE_SGIX, &renderType); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_X_RENDERABLE_SGIX, &xRenderable); + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_X_VISUAL_TYPE_EXT, &xVisual); + if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX)) + xVisual = -1; + this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, fbConfig, GLX_FBCONFIG_ID_SGIX, &id); + + printf("Id 0x%x\n", id); + printf(" Buffer Size: %d\n", bufferSize); + printf(" Level: %d\n", level); + printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no"); + printf(" Stereo: %s\n", stereo ? "yes" : "no"); + printf(" Aux Buffers: %d\n", auxBuffers); + printf(" Red Size: %d\n", redSize); + printf(" Green Size: %d\n", greenSize); + printf(" Blue Size: %d\n", blueSize); + printf(" Alpha Size: %d\n", alphaSize); + printf(" Depth Size: %d\n", depthSize); + printf(" Stencil Size: %d\n", stencilSize); + printf(" Accum Red Size: %d\n", accumRedSize); + printf(" Accum Green Size: %d\n", accumGreenSize); + printf(" Accum Blue Size: %d\n", accumBlueSize); + printf(" Accum Alpha Size: %d\n", accumAlphaSize); + printf(" Drawable Types: "); + if (drawableType & GLX_WINDOW_BIT_SGIX) printf("Window "); + if (drawableType & GLX_PIXMAP_BIT_SGIX) printf("Pixmap "); + if (drawableType & GLX_PBUFFER_BIT_SGIX) printf("PBuffer"); + printf("\n"); + printf(" Render Types: "); + if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA "); + if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI "); + printf("\n"); + printf(" X Renderable: %s\n", xRenderable ? "yes" : "no"); +} +#endif /* DEBUG_FBCONFIG */ + +int X11_GL_CreateRenderTarget(_THIS, SDL_RenderTarget *target, int width, int height, int *attrib) +{ + X11_RenderTargetData *render_target; + int (*oldHandler)(Display*, XErrorEvent*); + /* 64 seems nice. */ + int i, attribs[64]; + int pbAttribs[] = { + GLX_LARGEST_PBUFFER_SGIX, False, + GLX_PRESERVED_CONTENTS_SGIX, True, + GLX_PBUFFER_WIDTH, target->w, + GLX_PBUFFER_HEIGHT, target->h, + None + }; + int nConfigs; + GLXFBConfigSGIX *fbConfigs; + + /* Allocate memory for data */ + render_target = (X11_RenderTargetData *)malloc(sizeof(*render_target)); + if ( ! render_target ) { + SDL_OutOfMemory(); + return(-1); + } + render_target->pbuffer = None; + target->gl_data = render_target; + + /* Catch X protocol errors with our own error handler */ + oldHandler = pXSetErrorHandler( HandleXError ); + + /* Setup our GLX attributes */ + i = 0; + attribs[i++] = GLX_RENDER_TYPE_SGIX; + attribs[i++] = GLX_RGBA_BIT_SGIX; + attribs[i++] = GLX_DRAWABLE_TYPE_SGIX; + attribs[i++] = GLX_PBUFFER_BIT_SGIX; + attribs[i++] = GLX_RED_SIZE; + attribs[i++] = attrib[2*SDL_GL_RED_SIZE+1]; + attribs[i++] = GLX_GREEN_SIZE; + attribs[i++] = attrib[2*SDL_GL_GREEN_SIZE+1]; + attribs[i++] = GLX_BLUE_SIZE; + attribs[i++] = attrib[2*SDL_GL_BLUE_SIZE+1]; + attribs[i++] = GLX_ALPHA_SIZE; + attribs[i++] = attrib[2*SDL_GL_ALPHA_SIZE+1]; + attribs[i++] = GLX_BUFFER_SIZE; + attribs[i++] = attrib[2*SDL_GL_BUFFER_SIZE+1]; + attribs[i++] = GLX_DOUBLEBUFFER; + attribs[i++] = attrib[2*SDL_GL_DOUBLEBUFFER+1]; + attribs[i++] = GLX_DEPTH_SIZE; + attribs[i++] = attrib[2*SDL_GL_DEPTH_SIZE+1]; + attribs[i++] = GLX_STENCIL_SIZE; + attribs[i++] = attrib[2*SDL_GL_STENCIL_SIZE+1]; + attribs[i++] = GLX_ACCUM_RED_SIZE; + attribs[i++] = attrib[2*SDL_GL_ACCUM_RED_SIZE+1]; + attribs[i++] = GLX_ACCUM_GREEN_SIZE; + attribs[i++] = attrib[2*SDL_GL_ACCUM_GREEN_SIZE+1]; + attribs[i++] = GLX_ACCUM_BLUE_SIZE; + attribs[i++] = attrib[2*SDL_GL_ACCUM_BLUE_SIZE+1]; + attribs[i++] = GLX_ACCUM_ALPHA_SIZE; + attribs[i++] = attrib[2*SDL_GL_ACCUM_ALPHA_SIZE+1]; + attribs[i++] = GLX_STEREO; + attribs[i++] = attrib[2*SDL_GL_STEREO+1]; + attribs[i++] = None; + + /* Loop through available configs trying to create a pbuffer */ + fbConfigs = this->gl_data->glXChooseFBConfigSGIX(GFX_Display, SDL_Screen, attribs, &nConfigs); +#ifdef DEBUG_FBCONFIG + printf("%d configs found\n", nConfigs); + for ( i = 0; i < nConfigs; ++i ) { + PrintFBConfigInfo(this, fbConfigs[i]); + } +#endif + for ( i = 0; i < nConfigs; ++i ) { + XErrorFlag = 0; + if ( this->gl_data->glx_version >= MAKE_GLX_VERSION(1, 3) ) { + render_target->pbuffer = this->gl_data->glXCreatePbuffer(GFX_Display, fbConfigs[i], pbAttribs); + } else { + render_target->pbuffer = this->gl_data->glXCreateGLXPbufferSGIX(GFX_Display, fbConfigs[i], target->w, target->h, pbAttribs); + } + if ( XErrorFlag ) { + render_target->pbuffer = None; + } + if ( render_target->pbuffer != None ) { + render_target->config = fbConfigs[i]; + break; + } + } + + /* Restore original X error handler */ + pXSetErrorHandler( oldHandler ); + + /* Return an error if we couldn't create a pbuffer */ + if ( render_target->pbuffer == None ) { + SDL_SetError("Couldn't create pbuffer with desired attributes"); + return(-1); + } + return(0); +} + +int X11_GL_GetRenderTargetAttribute(_THIS, SDL_RenderTarget *target, SDL_GLattr attrib, int* value) +{ + X11_RenderTargetData *render_target = (X11_RenderTargetData *)target->gl_data; + int retval; + int glx_attrib = None; + + switch( attrib ) { + case SDL_GL_RED_SIZE: + glx_attrib = GLX_RED_SIZE; + break; + case SDL_GL_GREEN_SIZE: + glx_attrib = GLX_GREEN_SIZE; + break; + case SDL_GL_BLUE_SIZE: + glx_attrib = GLX_BLUE_SIZE; + break; + case SDL_GL_ALPHA_SIZE: + glx_attrib = GLX_ALPHA_SIZE; + break; + case SDL_GL_DOUBLEBUFFER: + glx_attrib = GLX_DOUBLEBUFFER; + break; + case SDL_GL_BUFFER_SIZE: + glx_attrib = GLX_BUFFER_SIZE; + break; + case SDL_GL_DEPTH_SIZE: + glx_attrib = GLX_DEPTH_SIZE; + break; + case SDL_GL_STENCIL_SIZE: + glx_attrib = GLX_STENCIL_SIZE; + break; + case SDL_GL_ACCUM_RED_SIZE: + glx_attrib = GLX_ACCUM_RED_SIZE; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + glx_attrib = GLX_ACCUM_GREEN_SIZE; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + glx_attrib = GLX_ACCUM_BLUE_SIZE; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + glx_attrib = GLX_ACCUM_ALPHA_SIZE; + break; + case SDL_GL_STEREO: + glx_attrib = GLX_STEREO; + break; + default: + return(-1); + } + + retval = this->gl_data->glXGetFBConfigAttribSGIX(GFX_Display, render_target->config, glx_attrib, value); + + return retval; +} + +void X11_GL_LockRenderTarget(_THIS, SDL_RenderTarget *target) +{ + X11_RenderTargetData *render_target = (X11_RenderTargetData *)target->gl_data; + /* Set the draw target */ + this->gl_data->glXMakeCurrent(GFX_Display, render_target->pbuffer, glx_context); + pXSync( GFX_Display, False ); +} + +void X11_GL_UnlockRenderTarget(_THIS, SDL_RenderTarget *target) +{ + /* Update the texture with the pbuffer contents */ + if ( target->texture ) { + this->glBindTexture(GL_TEXTURE_2D, target->texture); + this->glCopyTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, 0, + 0, 0, + target->w, target->h); + } + + /* Reset the draw target */ + this->gl_data->glXMakeCurrent(GFX_Display, SDL_Window, glx_context); + pXSync( GFX_Display, False ); +} + +void X11_GL_FreeRenderTarget(_THIS, SDL_RenderTarget *target) +{ + X11_RenderTargetData *render_target = (X11_RenderTargetData *)target->gl_data; + if ( render_target->pbuffer != None ) { + this->gl_data->glXDestroyGLXPbufferSGIX(GFX_Display, render_target->pbuffer); + } + free(render_target); +} + #endif /* HAVE_OPENGL_X11 */ void X11_GL_UnloadLibrary(_THIS) @@ -356,6 +692,12 @@ this->gl_data->glXMakeCurrent = NULL; this->gl_data->glXSwapBuffers = NULL; + this->gl_data->glXChooseFBConfigSGIX = NULL; + this->gl_data->glXGetFBConfigAttribSGIX = NULL; + this->gl_data->glXCreateGLXPbufferSGIX = NULL; + this->gl_data->glXDestroyGLXPbufferSGIX = NULL; + this->gl_data->glXCreatePbuffer = NULL; + this->gl_config.dll_handle = NULL; this->gl_config.driver_loaded = 0; } @@ -378,6 +720,33 @@ #define do_dlsym(x,y) do_dlsym(x, "_" y) #endif +static int GetGLXVersion(_THIS, void *handle) +{ + int glx_major_version, glx_minor_version; + + /* The ATI drivers put the correct version in the client string */ + const char *version_string; + const char *(*glXGetClientString)(Display *dpy, int name) = + (const char *(*)(Display *, int)) dlsym(handle, "glXGetClientString"); + Bool (*glXQueryVersion)(Display *dpy, int *major, int *minor) = + (Bool (*)(Display *, int *, int *)) dlsym(handle, "glXQueryVersion"); + + if ( glXGetClientString && + (version_string=glXGetClientString(GFX_Display, GLX_VERSION)) && + sscanf(version_string, "%d.%d", + &glx_major_version, + &glx_minor_version) ) { + return MAKE_GLX_VERSION(glx_major_version, glx_minor_version); + } + if ( glXQueryVersion && + glXQueryVersion(GFX_Display, + &glx_major_version, + &glx_minor_version) ) { + return MAKE_GLX_VERSION(glx_major_version, glx_minor_version); + } + return 0; +} + /* Passing a NULL path means load pointers from the application */ int X11_GL_LoadLibrary(_THIS, const char* path) { @@ -421,6 +790,9 @@ /* Unload the old driver and reset the pointers */ X11_GL_UnloadLibrary(this); + /* Try to figure out the GLX version */ + this->gl_data->glx_version = GetGLXVersion(this, handle); + /* Load new function pointers */ this->gl_data->glXGetProcAddress = (void *(*)(const GLubyte *)) do_dlsym(handle, "glXGetProcAddressARB"); @@ -439,6 +811,26 @@ this->gl_data->glXQueryExtensionsString = (const char *(*)(Display *, int)) do_dlsym(handle, "glXQueryExtensionsString"); + /* We don't compare below for this in case we don't have pbuffer extensions */ + if ( this->gl_data->glx_version >= MAKE_GLX_VERSION(1, 3) ) { + this->gl_data->glXChooseFBConfigSGIX = + (GLXFBConfigSGIX *(*)(Display*, int, int*, int*)) dlsym( handle, "glXChooseFBConfig" ); + this->gl_data->glXGetFBConfigAttribSGIX = + (int (*)(Display*, GLXFBConfigSGIX, int, int*)) dlsym( handle, "glXGetFBConfigAttrib" ); + this->gl_data->glXCreatePbuffer = + (GLXPbuffer (*)(Display*, GLXFBConfigSGIX, int*)) dlsym( handle, "glXCreatePbuffer" ); + this->gl_data->glXDestroyGLXPbufferSGIX = + (void (*)(Display*, GLXPbuffer)) dlsym( handle, "glXDestroyPbuffer" ); + } else { + this->gl_data->glXChooseFBConfigSGIX = + (GLXFBConfigSGIX *(*)(Display*, int, int*, int*)) dlsym( handle, "glXChooseFBConfigSGIX" ); + this->gl_data->glXGetFBConfigAttribSGIX = + (int (*)(Display*, GLXFBConfigSGIX, int, int*)) dlsym( handle, "glXGetFBConfigAttribSGIX" ); + this->gl_data->glXCreateGLXPbufferSGIX = + (GLXPbuffer (*)(Display*, GLXFBConfigSGIX, unsigned int, unsigned int, int*)) dlsym( handle, "glXCreateGLXPbufferSGIX" ); + this->gl_data->glXDestroyGLXPbufferSGIX = + (void (*)(Display*, GLXPbuffer)) dlsym( handle, "glXDestroyGLXPbufferSGIX" ); + } if ( (this->gl_data->glXChooseVisual == NULL) || (this->gl_data->glXCreateContext == NULL) || diff -ruN -x CVS SDL12/src/video/x11/SDL_x11gl_c.h SDL13/src/video/x11/SDL_x11gl_c.h --- SDL12/src/video/x11/SDL_x11gl_c.h 2006-02-01 00:09:04.000000000 -0800 +++ SDL13/src/video/x11/SDL_x11gl_c.h 2006-02-01 00:09:46.000000000 -0800 @@ -31,10 +31,21 @@ #include "SDL_sysvideo.h" +#ifndef GLX_SGIX_fbconfig +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +#endif + +#ifndef GLX_SGIX_pbuffer +typedef XID GLXPbufferSGIX; +#endif + struct SDL_PrivateGLData { int gl_active; /* to stop switching drivers while we have a valid context */ + int gl_extensions_checked; #ifdef HAVE_OPENGL_X11 +#define MAKE_GLX_VERSION(major, minor) ((major << 16) + minor) + int glx_version; GLXContext glx_context; /* Current GL context */ XVisualInfo* glx_visualinfo; /* XVisualInfo* returned by glXChooseVisual */ @@ -74,12 +85,48 @@ ( Display* dpy, int screen ); - + /* + * Support for GLX_SGIX_fbconfig and GLX_SGIX_pbuffer + */ + + GLXFBConfigSGIX *(*glXChooseFBConfigSGIX) + ( Display* dpy, + int screen, + int *attrib_list, + int *nelements ); + + int (*glXGetFBConfigAttribSGIX) + ( Display* dpy, + GLXFBConfigSGIX config, + int attribute, + int *value); + + GLXPbuffer (*glXCreateGLXPbufferSGIX) + ( Display* dpy, + GLXFBConfigSGIX config, + unsigned int width, + unsigned int height, + int *attrib_list ); + + void (*glXDestroyGLXPbufferSGIX) + ( Display* dpy, + GLXPbuffer pbuf ); + + /* + * Support for GLX 1.3 pbuffer support + */ + + GLXPbufferSGIX (*glXCreatePbuffer) + ( Display* dpy, + GLXFBConfigSGIX config, + int *attrib_list ); + #endif /* HAVE_OPENGL_X11 */ }; /* Old variable names */ #define gl_active (this->gl_data->gl_active) +#define gl_extensions_checked (this->gl_data->gl_extensions_checked) #define glx_context (this->gl_data->glx_context) #define glx_visualinfo (this->gl_data->glx_visualinfo) @@ -94,6 +141,37 @@ extern void X11_GL_SwapBuffers(_THIS); extern int X11_GL_LoadLibrary(_THIS, const char* path); extern void *X11_GL_GetProcAddress(_THIS, const char* proc); +extern int X11_GL_CreateRenderTarget(_THIS, SDL_RenderTarget *target, int width, int height, int *attrib); +extern int X11_GL_GetRenderTargetAttribute(_THIS, SDL_RenderTarget *target, SDL_GLattr attrib, int* value); +extern void X11_GL_LockRenderTarget(_THIS, SDL_RenderTarget *target); +extern void X11_GL_UnlockRenderTarget(_THIS, SDL_RenderTarget *target); +extern void X11_GL_FreeRenderTarget(_THIS, SDL_RenderTarget *target); #endif extern void X11_GL_UnloadLibrary(_THIS); +#ifdef HAVE_OPENGL + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#endif + +#endif /* HAVE_OPENGL */ diff -ruN -x CVS SDL12/test/configure.in SDL13/test/configure.in --- SDL12/test/configure.in 2004-11-26 08:16:50.000000000 -0800 +++ SDL13/test/configure.in 2004-12-19 14:38:48.000000000 -0800 @@ -22,11 +22,11 @@ case "$target" in *-*-cygwin* | *-*-mingw32*) MATHLIB="" - SYS_GL_LIBS="-lopengl32" + SYS_GL_LIBS="-lopengl32 -lglu32" ;; *-*-beos*) MATHLIB="" - SYS_GL_LIBS="-lGL" + SYS_GL_LIBS="-lGL -lGLU" ;; *-*-darwin* ) MATHLIB="" @@ -56,9 +56,9 @@ AC_PATH_XTRA if test x$have_x = xyes; then CFLAGS="$CFLAGS $X_CFLAGS" - SYS_GL_LIBS="$X_LIBS -lGL" + SYS_GL_LIBS="$X_LIBS -lGL -lGLU" else - SYS_GL_LIBS="-lGL" + SYS_GL_LIBS="-lGL -lGLU" fi ;; esac diff -ruN -x CVS SDL12/test/Makefile.am SDL13/test/Makefile.am --- SDL12/test/Makefile.am 2005-02-15 03:50:33.000000000 -0800 +++ SDL13/test/Makefile.am 2005-08-28 21:16:33.000000000 -0700 @@ -5,8 +5,8 @@ testhread testlock testerror testsem testtimer \ loopwave testcdrom testkeys testvidinfo checkkeys testwin graywin \ testsprite testbitmap testalpha testgamma testpalette testwm \ - threadwin testoverlay testoverlay2 testgl testdyngl testjoystick \ - testblitspeed + threadwin testoverlay testoverlay2 testgl testdyngl testrendertarget \ + testjoystick testblitspeed testalpha_SOURCES = testalpha.c testalpha_LDADD = @MATHLIB@ @@ -16,3 +16,5 @@ testpalette_LDADD = @MATHLIB@ testgl_SOURCES = testgl.c testgl_LDADD = @GL_LIBS@ @MATHLIB@ +testrendertarget_SOURCES = testrendertarget.c +testrendertarget_LDADD = @GL_LIBS@ @MATHLIB@ diff -ruN -x CVS SDL12/test/testrendertarget.c SDL13/test/testrendertarget.c --- SDL12/test/testrendertarget.c 1969-12-31 16:00:00.000000000 -0800 +++ SDL13/test/testrendertarget.c 2003-09-21 11:10:22.000000000 -0700 @@ -0,0 +1,734 @@ +/* + * NeHe Lesson 11 + * This code was created by Jeff Molofee '99 + * (ported to Linux/SDL by Ti Leggett '01) + * (modified to be a render target demo for SDL by Sam Lantinga '03) + * + * If you've found this code useful, please let me know. + * + * Visit Jeff at http://nehe.gamedev.net/ + * + * or for port-specific comments, questions, bugreports etc. + * email to leggett@eecs.tulane.edu + */ + +#include +#include +#include + +#include "SDL.h" + +#ifdef HAVE_OPENGL + +#include "SDL_opengl.h" + +/* screen width, height, and bit depth */ +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 +#define SCREEN_BPP 16 + +/* render target width, height */ +#define RENDERTARGET_WIDTH 256 +#define RENDERTARGET_HEIGHT 256 + +/* Set up some booleans */ +#define TRUE 1 +#define FALSE 0 + +/* This is our SDL surface */ +SDL_Surface *surface; + +GLfloat xrot; /* X Rotation */ +GLfloat yrot; /* Y Rotation */ +GLfloat zrot; /* Z Rotation */ + +float points[45][45][3]; /* The Points On The Grid Of Our "Wave" */ +int wiggle_count = 0; /* Counter Used To Control How Fast Flag Waves */ +GLfloat hold; /* Temporarily Holds A Floating Point Value */ + +GLuint texture[1]; /* Storage For One Texture */ +GLfloat textureCoords[4]; + +SDL_RenderTarget *RenderTarget = NULL; +GLuint RenderTargetTextureID; + +/* function to release/destroy our resources and restoring the old desktop */ +void Quit( int returnCode ) +{ + if ( RenderTarget ) { + SDL_GL_FreeRenderTarget(RenderTarget); + } + glDeleteTextures(1, texture); + glDeleteTextures( 1, &RenderTargetTextureID); + + /* clean up the window */ + SDL_Quit( ); + + /* and exit appropriately */ + exit( returnCode ); +} + +/* function to load in bitmap as a GL texture */ +static int power_of_two(int input) +{ + int value = 1; + + while ( value < input ) { + value <<= 1; + } + return value; +} +GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) +{ + GLuint texture; + int w, h; + SDL_Surface *image; + SDL_Rect area; + Uint32 saved_flags; + Uint8 saved_alpha; + + /* Use the surface width and height expanded to powers of 2 */ + w = power_of_two(surface->w); + h = power_of_two(surface->h); + texcoord[0] = 0.0f; /* Min X */ + texcoord[1] = 0.0f; /* Min Y */ + texcoord[2] = (GLfloat)surface->w / w; /* Max X */ + texcoord[3] = (GLfloat)surface->h / h; /* Max Y */ + + image = SDL_CreateRGBSurface( + SDL_SWSURFACE, + w, h, + 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#endif + ); + if ( image == NULL ) { + return 0; + } + + /* Save the alpha blending attributes */ + saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + saved_alpha = surface->format->alpha; + if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + SDL_SetAlpha(surface, 0, 0); + } + + /* Copy the surface into the GL texture image */ + area.x = 0; + area.y = 0; + area.w = surface->w; + area.h = surface->h; + SDL_BlitSurface(surface, &area, image, &area); + + /* Restore the alpha blending attributes */ + if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + SDL_SetAlpha(surface, saved_flags, saved_alpha); + } + + /* Create an OpenGL texture for the image */ + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + w, h, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + image->pixels); + SDL_FreeSurface(image); /* No longer needed */ + + return texture; +} +int LoadGLTextures( ) +{ + SDL_Surface *image = SDL_LoadBMP("sample.bmp"); + if ( image ) { + texture[0] = SDL_GL_LoadTexture(image, textureCoords); + return TRUE; + } + return FALSE; +} + +int CreateRenderTarget( ) +{ + /* Create the texture that will be bound to the render target */ + glGenTextures(1, &RenderTargetTextureID); + glBindTexture(GL_TEXTURE_2D, RenderTargetTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + /* Create the render target */ + RenderTarget = SDL_GL_CreateRenderTarget(RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, NULL); + if ( RenderTarget ) { + int value; + printf("Created render target:\n"); + SDL_GL_GetRenderTargetAttribute( RenderTarget, SDL_GL_RED_SIZE, &value ); + printf( "SDL_GL_RED_SIZE: %d\n", value); + SDL_GL_GetRenderTargetAttribute( RenderTarget, SDL_GL_GREEN_SIZE, &value ); + printf( "SDL_GL_GREEN_SIZE: %d\n", value); + SDL_GL_GetRenderTargetAttribute( RenderTarget, SDL_GL_BLUE_SIZE, &value ); + printf( "SDL_GL_BLUE_SIZE: %d\n", value); + SDL_GL_GetRenderTargetAttribute( RenderTarget, SDL_GL_ALPHA_SIZE, &value ); + printf( "SDL_GL_ALPHA_SIZE: %d\n", value); + SDL_GL_GetRenderTargetAttribute( RenderTarget, SDL_GL_DEPTH_SIZE, &value ); + printf( "SDL_GL_DEPTH_SIZE: %d\n", value ); + + SDL_GL_BindRenderTarget(RenderTarget, RenderTargetTextureID); + } else { + /* We can fake a render target in this demo by rendering to the + * screen and copying to a texture before we do normal rendering. + */ + printf("Failed to create render target, using screen buffer\n"); + + glBindTexture(GL_TEXTURE_2D, RenderTargetTextureID); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGB, + RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + NULL); + } + + return TRUE; +} + +/* to resize the window and reset our view */ +int resizeWindow( int width, int height ) +{ + /* Height / width ration */ + GLfloat ratio; + + /* Protect against a divide by zero */ + if ( height == 0 ) + height = 1; + + ratio = ( GLfloat )width / ( GLfloat )height; + + /* Setup our viewport. */ + glViewport( 0, 0, ( GLint )width, ( GLint )height ); + + /* change to the projection matrix and set our viewing volume. */ + glMatrixMode( GL_PROJECTION ); + glLoadIdentity( ); + + /* Set our perspective */ + gluPerspective( 45.0f, ratio, 0.1f, 100.0f ); + + /* Make sure we're chaning the model view and not the projection */ + glMatrixMode( GL_MODELVIEW ); + + /* Reset The View */ + glLoadIdentity( ); + + return( TRUE ); +} + +/* function to handle key press events */ +void handleKeyPress( SDL_keysym *keysym ) +{ + switch ( keysym->sym ) + { + case SDLK_ESCAPE: + /* ESC key was pressed */ + Quit( 0 ); + break; + case SDLK_F1: + /* F1 key was pressed + * this toggles fullscreen mode + */ + SDL_WM_ToggleFullScreen( surface ); + break; + default: + break; + } + + return; +} + +/* general OpenGL initialization function */ +int initGL( GLvoid ) +{ + int x, y; /* Loop variables */ + + /* Load in the texture */ + if ( !LoadGLTextures( ) ) + return FALSE; + + if ( !CreateRenderTarget( ) ) + return FALSE; + + /* Enable Texture Mapping ( NEW ) */ + glEnable( GL_TEXTURE_2D ); + + /* Enable smooth shading */ + glShadeModel( GL_SMOOTH ); + + /* Set the background black */ + glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); + + /* Depth buffer setup */ + glClearDepth( 1.0f ); + + /* Enables Depth Testing */ + glEnable( GL_DEPTH_TEST ); + + /* The Type Of Depth Test To Do */ + glDepthFunc( GL_LEQUAL ); + + /* Really Nice Perspective Calculations */ + glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); + + /* Fill the back with the texture. The front will only be wireline */ + glPolygonMode( GL_FRONT, GL_LINE ); + glPolygonMode( GL_BACK, GL_FILL ); + + /* Loop Through The X Plane */ + for ( x = 0; x < 45; x++ ) + { + /* Loop Through The Y Plane */ + for ( y = 0; y < 45; y++ ) + { + /* Apply The Wave To Our Mesh */ + points[x][y][0] = ( float )( ( x / 5.0f ) - 4.5f ); + points[x][y][1] = ( float )( ( y / 5.0f ) - 4.5f ); + points[x][y][2] = ( float )( sin( ( ( ( x / 5.0f ) * 40.0f ) / 360.0f ) * 3.141592654 * 2.0f ) ); + } + } + + return( TRUE ); +} + +int drawRenderTarget( GLvoid ) +{ + static int initialized = 0; + static GLfloat cubeModelView[16]; + static float color[8][3]= {{ 1.0, 1.0, 0.0}, + { 1.0, 0.0, 0.0}, + { 0.0, 0.0, 0.0}, + { 0.0, 1.0, 0.0}, + { 0.0, 1.0, 1.0}, + { 1.0, 1.0, 1.0}, + { 1.0, 0.0, 1.0}, + { 0.0, 0.0, 1.0}}; + static float cube[8][3]= {{ 0.5, 0.5, -0.5}, + { 0.5, -0.5, -0.5}, + {-0.5, -0.5, -0.5}, + {-0.5, 0.5, -0.5}, + {-0.5, 0.5, 0.5}, + { 0.5, 0.5, 0.5}, + { 0.5, -0.5, 0.5}, + {-0.5, -0.5, 0.5}}; + + /* Set initial state */ + if ( RenderTarget ) { + SDL_GL_LockRenderTarget(RenderTarget); + } + glPushAttrib( GL_ALL_ATTRIB_BITS ); /* Overkill, but safe */ + + if ( RenderTarget ) { + glViewport( 0, 0, RenderTarget->w, RenderTarget->h ); + } else { + glViewport( 0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT ); + } + + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + + glDisable( GL_FOG ); + glDisable( GL_BLEND ); + glDisable( GL_ALPHA_TEST ); + glDisable( GL_SCISSOR_TEST ); + glDisable( GL_STENCIL_TEST ); + glDisable( GL_CULL_FACE ); + + glShadeModel( GL_SMOOTH ); + glPolygonMode( GL_FRONT, GL_FILL ); + glPolygonMode( GL_BACK, GL_FILL ); + + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); + + /* Clear the background before we start */ + glClearColor( 0.0, 0.0, 0.0, 1.0 ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + /* Render the logo texture to the background */ + glEnable( GL_TEXTURE_2D ); + glDisable( GL_DEPTH_TEST ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity( ); + glOrtho( 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity( ); + + glBindTexture( GL_TEXTURE_2D, texture[0] ); + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2f(textureCoords[0], textureCoords[3]); + glVertex2f(0.0, 0.0); + glTexCoord2f(textureCoords[2], textureCoords[3]); + glVertex2f(1.0, 0.0); + glTexCoord2f(textureCoords[0], textureCoords[1]); + glVertex2f(0.0, 1.0); + glTexCoord2f(textureCoords[2], textureCoords[1]); + glVertex2f(1.0, 1.0); + glEnd(); + + /* Render the spinning cube */ + glDisable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glDepthFunc( GL_LESS ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity( ); + glOrtho( -2.0, 2.0, -2.0, 2.0, -20.0, 20.0 ); + + glMatrixMode( GL_MODELVIEW ); + if ( initialized ) { + glLoadMatrixf(cubeModelView); + glRotatef(5.0, 1.0, 1.0, 1.0); + } else { + glLoadIdentity(); + initialized = 1; + } + glGetFloatv( GL_MODELVIEW_MATRIX, cubeModelView); + + glBegin( GL_QUADS ); + + glColor3fv(color[0]); + glVertex3fv(cube[0]); + glColor3fv(color[1]); + glVertex3fv(cube[1]); + glColor3fv(color[2]); + glVertex3fv(cube[2]); + glColor3fv(color[3]); + glVertex3fv(cube[3]); + + glColor3fv(color[3]); + glVertex3fv(cube[3]); + glColor3fv(color[4]); + glVertex3fv(cube[4]); + glColor3fv(color[7]); + glVertex3fv(cube[7]); + glColor3fv(color[2]); + glVertex3fv(cube[2]); + + glColor3fv(color[0]); + glVertex3fv(cube[0]); + glColor3fv(color[5]); + glVertex3fv(cube[5]); + glColor3fv(color[6]); + glVertex3fv(cube[6]); + glColor3fv(color[1]); + glVertex3fv(cube[1]); + + glColor3fv(color[5]); + glVertex3fv(cube[5]); + glColor3fv(color[4]); + glVertex3fv(cube[4]); + glColor3fv(color[7]); + glVertex3fv(cube[7]); + glColor3fv(color[6]); + glVertex3fv(cube[6]); + + glColor3fv(color[5]); + glVertex3fv(cube[5]); + glColor3fv(color[0]); + glVertex3fv(cube[0]); + glColor3fv(color[3]); + glVertex3fv(cube[3]); + glColor3fv(color[4]); + glVertex3fv(cube[4]); + + glColor3fv(color[6]); + glVertex3fv(cube[6]); + glColor3fv(color[1]); + glVertex3fv(cube[1]); + glColor3fv(color[2]); + glVertex3fv(cube[2]); + glColor3fv(color[7]); + glVertex3fv(cube[7]); + + glEnd( ); + + /* Clean up */ + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + + glPopAttrib(); + + if ( RenderTarget ) { + /* Note that we could also use the glCopyTexSubImage2D trick below + * before unlocking the render target, but some drivers have an + * optimized path if you bind the texture beforehand. You could + * still use it if you wanted to get the depth or stencil buffers. + */ + SDL_GL_UnlockRenderTarget(RenderTarget); + } else { + /* Copy our rendering to the fake render target texture */ + glBindTexture( GL_TEXTURE_2D, RenderTargetTextureID ); + glCopyTexSubImage2D( GL_TEXTURE_2D, + 0, + 0, 0, + 0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT); + } + + { + /* Check for error conditions. */ + GLenum gl_error = glGetError( ); + + if( gl_error != GL_NO_ERROR ) { + fprintf( stderr, "testrendertarget: opengl error: %d (0x%4.4x)\n", gl_error, gl_error ); + } + } + + return( TRUE ); +} + +/* Here goes our drawing code */ +int drawGLScene( GLvoid ) +{ + /* These are to calculate our fps */ + static GLint T0 = 0; + static GLint Frames = 0; + + int x, y; /* Loop Variables */ + float f_x, f_y, f_xb, f_yb; /* Used To Break The Flag Into Tiny Quads */ + + /* Render into our render target texture */ + drawRenderTarget(); + + /* Clear The Screen And Depth Buffer */ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + /* Reset The Current Matrix */ + glLoadIdentity( ); + + /* Translate 17 Units Into The Screen */ + glTranslatef( 0.0f, 0.0f, -12.0f ); + + glRotatef( xrot, 1.0f, 0.0f, 0.0f ); /* Rotate On The X Axis */ + glRotatef( yrot, 0.0f, 1.0f, 0.0f ); /* Rotate On The Y Axis */ + glRotatef( zrot, 0.0f, 0.0f, 1.0f ); /* Rotate On The Z Axis */ + + glBindTexture( GL_TEXTURE_2D, RenderTargetTextureID ); /* Select Our Texture */ + + /* Start Drawing Our Quads */ + glBegin( GL_QUADS ); + /* Loop Through The X Plane 0-44 (45 Points) */ + for( x = 0; x < 44; x++ ) + { + /* Loop Through The Y Plane 0-44 (45 Points) */ + for( y = 0; y < 44; y++ ) + { + /* Create A Floating Point X Value */ + f_x = ( float )x / 44.0f; + /* Create A Floating Point Y Value */ + f_y = ( float )y / 44.0f; + /* Create A Floating Point Y Value+0.0227f */ + f_xb = ( float )( x + 1 ) / 44.0f; + /* Create A Floating Point Y Value+0.0227f */ + f_yb = ( float )( y + 1 ) / 44.0f; + + /* First Texture Coordinate (Bottom Left) */ + glTexCoord2f( f_x, f_y ); + glVertex3f( points[x][y][0], points[x][y][1], + points[x][y][2] ); + + /* Second Texture Coordinate (Top Left) */ + glTexCoord2f( f_x, f_yb ); + glVertex3f( points[x][y + 1][0], points[x][y + 1][1], + points[x][y + 1][2] ); + + /* Third Texture Coordinate (Top Right) */ + glTexCoord2f( f_xb, f_yb ); + glVertex3f( points[x + 1][y + 1][0], + points[x + 1][y + 1][1], + points[x + 1][y + 1][2] ); + + /* Fourth Texture Coordinate (Bottom Right) */ + glTexCoord2f( f_xb, f_y ); + glVertex3f( points[x + 1][y][0], points[x + 1][y][1], + points[x + 1][y][2] ); + } + } + glEnd( ); + + /* Used To Slow Down The Wave (Every 2nd Frame Only) */ + if( wiggle_count == 2 ) + { + /* Loop Through The Y Plane */ + for( y = 0; y < 45; y++ ) + { + /* Store Current Value One Left Side Of Wave */ + hold = points[0][y][2]; + /* Loop Through The X Plane */ + for( x = 0; x < 44; x++) + { + /* Current Wave Value Equals Value To The Right */ + points[x][y][2] = points[x + 1][y][2]; + } + /* Last Value Becomes The Far Left Stored Value */ + points[44][y][2] = hold; + } + wiggle_count = 0; /* Set Counter Back To Zero */ + } + wiggle_count++; /* Increase The Counter */ + + xrot += 0.3f; /* Increase The X Rotation Variable */ + yrot += 0.2f; /* Increase The Y Rotation Variable */ + zrot += 0.4f; /* Increase The Z Rotation Variable */ + + /* Draw it to the screen */ + SDL_GL_SwapBuffers( ); + + /* Gather our frames per second */ + Frames++; + { + GLint t = SDL_GetTicks(); + if (t - T0 >= 5000) { + GLfloat seconds = (t - T0) / 1000.0f; + GLfloat fps = Frames / seconds; + printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps); + T0 = t; + Frames = 0; + } + } + + return( TRUE ); +} + +int main( int argc, char **argv ) +{ + /* Flags to pass to SDL_SetVideoMode */ + int videoFlags; + /* main loop variable */ + int done = FALSE; + /* used to collect events */ + SDL_Event event; + /* whether or not the window is active */ + int isActive = TRUE; + + /* initialize SDL */ + if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) + { + fprintf( stderr, "Video initialization failed: %s\n", + SDL_GetError( ) ); + Quit( 1 ); + } + + /* the flags to pass to SDL_SetVideoMode */ + videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */ + videoFlags |= SDL_RESIZABLE; /* Enable window resizing */ + + /* Sets up OpenGL double buffering */ + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + /* get a SDL surface */ + surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, + videoFlags ); + + /* Verify there is a surface */ + if ( !surface ) + { + fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) ); + Quit( 1 ); + } + + /* initialize OpenGL */ + if ( !initGL( ) ) + { + fprintf( stderr, "Couldn't initialize textures\n"); + Quit( 1 ); + } + + /* resize the initial window */ + resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT ); + + /* wait for events */ + while ( !done ) + { + /* handle the events in the queue */ + + while ( SDL_PollEvent( &event ) ) + { + switch( event.type ) + { + case SDL_ACTIVEEVENT: + /* Something's happend with our focus + * If we lost focus or we are iconified, we + * shouldn't draw the screen + */ + if ( event.active.state & SDL_APPACTIVE ) { + if ( event.active.gain == 0 ) + isActive = FALSE; + else + isActive = TRUE; + } + break; + case SDL_VIDEORESIZE: + /* handle resize event */ + surface = SDL_SetVideoMode( event.resize.w, + event.resize.h, + 16, videoFlags ); + if ( !surface ) + { + fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) ); + Quit( 1 ); + } + resizeWindow( event.resize.w, event.resize.h ); + break; + case SDL_KEYDOWN: + /* handle key presses */ + handleKeyPress( &event.key.keysym ); + break; + case SDL_QUIT: + /* handle quit requests */ + done = TRUE; + break; + default: + break; + } + } + + /* draw the scene */ + if ( isActive ) + drawGLScene( ); + } + + /* clean ourselves up and exit */ + Quit( 0 ); + + /* Should never get here */ + return( 0 ); +} + +#else /* HAVE_OPENGL */ + +int main(int argc, char *argv[]) +{ + printf("No OpenGL support on this system\n"); + return 1; +} + +#endif /* HAVE_OPENGL */ diff -ruN -x CVS SDL12/WhatsNew SDL13/WhatsNew --- SDL12/WhatsNew 2004-01-08 08:01:07.000000000 -0800 +++ SDL13/WhatsNew 2004-02-22 20:53:34.000000000 -0800 @@ -3,6 +3,16 @@ Version 1.0: +1.3.0: + Added OpenGL render target support: + SDL_GL_CreateRenderTarget() + SDL_GL_GetRenderTargetAttribute() + SDL_GL_BindRenderTarget() + SDL_GL_LockRenderTarget() + SDL_GL_UnlockRenderTarget() + SDL_GL_FreeRenderTarget() + Added a new file test/testrendertarget.c as a render target demo + 1.2.7: Added CPU feature detection functions to SDL_cpuinfo.h: SDL_HasRDTSC(), SDL_HasMMX(), SDL_Has3DNow(), SDL_HasSSE(),