|
@@ -172,129 +172,64 @@ typedef struct {
|
|
int bytes_per_pixel;
|
|
int bytes_per_pixel;
|
|
} SDL_WindowTextureData;
|
|
} SDL_WindowTextureData;
|
|
|
|
|
|
-static SDL_bool
|
|
|
|
-ShouldUseTextureFramebuffer()
|
|
|
|
-{
|
|
|
|
- const char *hint;
|
|
|
|
-
|
|
|
|
- /* If there's no native framebuffer support then there's no option */
|
|
|
|
- if (!_this->CreateWindowFramebuffer) {
|
|
|
|
- return SDL_TRUE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* If this is the dummy driver there is no texture support */
|
|
|
|
- if (_this->is_dummy) {
|
|
|
|
- return SDL_FALSE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* See if the user or application wants a specific behavior */
|
|
|
|
- hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
|
|
|
|
- if (hint) {
|
|
|
|
- if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
|
|
|
|
- return SDL_FALSE;
|
|
|
|
- } else {
|
|
|
|
- return SDL_TRUE;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Each platform has different performance characteristics */
|
|
|
|
-#if defined(__WIN32__)
|
|
|
|
- /* GDI BitBlt() is way faster than Direct3D dynamic textures right now.
|
|
|
|
- */
|
|
|
|
- return SDL_FALSE;
|
|
|
|
-
|
|
|
|
-#elif defined(__MACOSX__)
|
|
|
|
- /* Mac OS X uses OpenGL as the native fast path (for cocoa and X11) */
|
|
|
|
- return SDL_TRUE;
|
|
|
|
-
|
|
|
|
-#elif defined(__LINUX__)
|
|
|
|
- /* Properly configured OpenGL drivers are faster than MIT-SHM */
|
|
|
|
-#if SDL_VIDEO_OPENGL
|
|
|
|
- /* Ugh, find a way to cache this value! */
|
|
|
|
- {
|
|
|
|
- SDL_Window *window;
|
|
|
|
- SDL_GLContext context;
|
|
|
|
- SDL_bool hasAcceleratedOpenGL = SDL_FALSE;
|
|
|
|
-
|
|
|
|
- window = SDL_CreateWindow("OpenGL test", -32, -32, 32, 32, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
|
|
|
|
- if (window) {
|
|
|
|
- context = SDL_GL_CreateContext(window);
|
|
|
|
- if (context) {
|
|
|
|
- const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
|
|
|
|
- const char *vendor = NULL;
|
|
|
|
-
|
|
|
|
- glGetStringFunc = SDL_GL_GetProcAddress("glGetString");
|
|
|
|
- if (glGetStringFunc) {
|
|
|
|
- vendor = (const char *) glGetStringFunc(GL_VENDOR);
|
|
|
|
- }
|
|
|
|
- /* Add more vendors here at will... */
|
|
|
|
- if (vendor &&
|
|
|
|
- (SDL_strstr(vendor, "ATI Technologies") ||
|
|
|
|
- SDL_strstr(vendor, "NVIDIA"))) {
|
|
|
|
- hasAcceleratedOpenGL = SDL_TRUE;
|
|
|
|
- }
|
|
|
|
- SDL_GL_DeleteContext(context);
|
|
|
|
- }
|
|
|
|
- SDL_DestroyWindow(window);
|
|
|
|
- }
|
|
|
|
- return hasAcceleratedOpenGL;
|
|
|
|
- }
|
|
|
|
-#elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
|
|
|
- /* Let's be optimistic about this! */
|
|
|
|
- return SDL_TRUE;
|
|
|
|
-#else
|
|
|
|
- return SDL_FALSE;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-#else
|
|
|
|
- /* Play it safe, assume that if there is a framebuffer driver that it's
|
|
|
|
- optimized for the current platform.
|
|
|
|
- */
|
|
|
|
- return SDL_FALSE;
|
|
|
|
-#endif
|
|
|
|
-}
|
|
|
|
|
|
|
|
static int
|
|
static int
|
|
-SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
|
|
|
|
|
|
+SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
|
|
{
|
|
{
|
|
- SDL_WindowTextureData *data;
|
|
|
|
|
|
+ SDL_RendererInfo info;
|
|
|
|
+ SDL_WindowTextureData *data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
|
|
|
|
+ int i;
|
|
|
|
|
|
- data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
|
|
|
|
if (!data) {
|
|
if (!data) {
|
|
SDL_Renderer *renderer = NULL;
|
|
SDL_Renderer *renderer = NULL;
|
|
- int i;
|
|
|
|
const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
|
|
const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
|
|
-
|
|
|
|
- /* Check to see if there's a specific driver requested */
|
|
|
|
- if (hint && *hint != '0' && *hint != '1' &&
|
|
|
|
|
|
+ const SDL_bool specific_accelerated_renderer = (
|
|
|
|
+ hint && *hint != '0' && *hint != '1' &&
|
|
SDL_strcasecmp(hint, "true") != 0 &&
|
|
SDL_strcasecmp(hint, "true") != 0 &&
|
|
SDL_strcasecmp(hint, "false") != 0 &&
|
|
SDL_strcasecmp(hint, "false") != 0 &&
|
|
- SDL_strcasecmp(hint, "software") != 0) {
|
|
|
|
|
|
+ SDL_strcasecmp(hint, "software") != 0
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ /* Check to see if there's a specific driver requested */
|
|
|
|
+ if (specific_accelerated_renderer) {
|
|
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
|
|
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
|
|
- SDL_RendererInfo info;
|
|
|
|
SDL_GetRenderDriverInfo(i, &info);
|
|
SDL_GetRenderDriverInfo(i, &info);
|
|
if (SDL_strcasecmp(info.name, hint) == 0) {
|
|
if (SDL_strcasecmp(info.name, hint) == 0) {
|
|
renderer = SDL_CreateRenderer(window, i, 0);
|
|
renderer = SDL_CreateRenderer(window, i, 0);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!renderer) {
|
|
|
|
|
|
+ if (!renderer) {
|
|
|
|
+ return SDL_SetError("Requested renderer for " SDL_HINT_FRAMEBUFFER_ACCELERATION " is not available");
|
|
|
|
+ } else if (SDL_GetRendererInfo(renderer, &info) == -1) {
|
|
|
|
+ SDL_DestroyRenderer(renderer);
|
|
|
|
+ return SDL_SetError("Requested renderer for " SDL_HINT_FRAMEBUFFER_ACCELERATION " is not available");
|
|
|
|
+ } else if ((info.flags & SDL_RENDERER_ACCELERATED) == 0) {
|
|
|
|
+ SDL_DestroyRenderer(renderer);
|
|
|
|
+ return SDL_SetError("Requested renderer for " SDL_HINT_FRAMEBUFFER_ACCELERATION " is not accelerated");
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
|
|
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
|
|
- SDL_RendererInfo info;
|
|
|
|
SDL_GetRenderDriverInfo(i, &info);
|
|
SDL_GetRenderDriverInfo(i, &info);
|
|
if (SDL_strcmp(info.name, "software") != 0) {
|
|
if (SDL_strcmp(info.name, "software") != 0) {
|
|
renderer = SDL_CreateRenderer(window, i, 0);
|
|
renderer = SDL_CreateRenderer(window, i, 0);
|
|
- if (renderer) {
|
|
|
|
- break;
|
|
|
|
|
|
+ if (renderer && (SDL_GetRendererInfo(renderer, &info) == 0) && (info.flags & SDL_RENDERER_ACCELERATED)) {
|
|
|
|
+ break; /* this will work. */
|
|
|
|
+ }
|
|
|
|
+ if (renderer) { /* wasn't accelerated, etc, skip it. */
|
|
|
|
+ SDL_DestroyRenderer(renderer);
|
|
|
|
+ renderer = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ if (!renderer) {
|
|
|
|
+ return SDL_SetError("No hardware accelerated renderers available");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- if (!renderer) {
|
|
|
|
- return SDL_SetError("No hardware accelerated renderers available");
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ /* Both of these checks should be handled above. */
|
|
|
|
+ SDL_assert(renderer != NULL);
|
|
|
|
+ SDL_assert(info.flags & SDL_RENDERER_ACCELERATED);
|
|
|
|
|
|
/* Create the data after we successfully create the renderer (bug #1116) */
|
|
/* Create the data after we successfully create the renderer (bug #1116) */
|
|
data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
|
|
data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
|
|
@@ -305,6 +240,10 @@ SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * f
|
|
SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
|
|
SDL_SetWindowData(window, SDL_WINDOWTEXTUREDATA, data);
|
|
|
|
|
|
data->renderer = renderer;
|
|
data->renderer = renderer;
|
|
|
|
+ } else {
|
|
|
|
+ if (SDL_GetRendererInfo(data->renderer, &info) == -1) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* Free any old texture and pixel data */
|
|
/* Free any old texture and pixel data */
|
|
@@ -315,23 +254,14 @@ SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * f
|
|
SDL_free(data->pixels);
|
|
SDL_free(data->pixels);
|
|
data->pixels = NULL;
|
|
data->pixels = NULL;
|
|
|
|
|
|
- {
|
|
|
|
- SDL_RendererInfo info;
|
|
|
|
- Uint32 i;
|
|
|
|
|
|
+ /* Find the first format without an alpha channel */
|
|
|
|
+ *format = info.texture_formats[0];
|
|
|
|
|
|
- if (SDL_GetRendererInfo(data->renderer, &info) < 0) {
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Find the first format without an alpha channel */
|
|
|
|
- *format = info.texture_formats[0];
|
|
|
|
-
|
|
|
|
- for (i = 0; i < info.num_texture_formats; ++i) {
|
|
|
|
- if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
|
|
|
|
- !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
|
|
|
|
- *format = info.texture_formats[i];
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ for (i = 0; i < (int) info.num_texture_formats; ++i) {
|
|
|
|
+ if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
|
|
|
|
+ !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
|
|
|
|
+ *format = info.texture_formats[i];
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -413,28 +343,6 @@ SDL_DestroyWindowTexture(SDL_VideoDevice *unused, SDL_Window * window)
|
|
SDL_free(data);
|
|
SDL_free(data);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-/* This will switch the video backend from using a software surface to
|
|
|
|
- using a GPU texture through the 2D render API, if we think this would
|
|
|
|
- be more efficient. This only checks once, on demand. */
|
|
|
|
-static void
|
|
|
|
-PrepareWindowFramebuffer()
|
|
|
|
-{
|
|
|
|
- /* Add the renderer framebuffer emulation if desired */
|
|
|
|
- if (_this->checked_texture_framebuffer) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- _this->checked_texture_framebuffer = SDL_TRUE;
|
|
|
|
-
|
|
|
|
- if (ShouldUseTextureFramebuffer()) {
|
|
|
|
- _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
|
|
|
|
- _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
|
|
|
|
- _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
static int
|
|
static int
|
|
cmpmodes(const void *A, const void *B)
|
|
cmpmodes(const void *A, const void *B)
|
|
{
|
|
{
|
|
@@ -2554,15 +2462,53 @@ SDL_CreateWindowFramebuffer(SDL_Window * window)
|
|
int pitch;
|
|
int pitch;
|
|
int bpp;
|
|
int bpp;
|
|
Uint32 Rmask, Gmask, Bmask, Amask;
|
|
Uint32 Rmask, Gmask, Bmask, Amask;
|
|
|
|
+ SDL_bool created_framebuffer = SDL_FALSE;
|
|
|
|
|
|
- PrepareWindowFramebuffer();
|
|
|
|
|
|
+ /* This will switch the video backend from using a software surface to
|
|
|
|
+ using a GPU texture through the 2D render API, if we think this would
|
|
|
|
+ be more efficient. This only checks once, on demand. */
|
|
|
|
+ if (!_this->checked_texture_framebuffer) {
|
|
|
|
+ SDL_bool attempt_texture_framebuffer = SDL_TRUE;
|
|
|
|
|
|
- if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
|
|
|
|
- return NULL;
|
|
|
|
|
|
+ if (_this->is_dummy) { /* dummy driver never has GPU support, of course. */
|
|
|
|
+ attempt_texture_framebuffer = SDL_FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #if defined(__WIN32__) /* GDI BitBlt() is way faster than Direct3D dynamic textures right now. (!!! FIXME: is this still true?) */
|
|
|
|
+ else if ((_this->CreateWindowFramebuffer != NULL) && (SDL_strcmp(_this->name, "windows") == 0)) {
|
|
|
|
+ attempt_texture_framebuffer = SDL_FALSE;
|
|
|
|
+ }
|
|
|
|
+ #endif
|
|
|
|
+
|
|
|
|
+ if (attempt_texture_framebuffer) {
|
|
|
|
+ if (SDL_CreateWindowTexture(_this, window, &format, &pixels, &pitch) == -1) {
|
|
|
|
+ /* !!! FIXME: if this failed halfway (made renderer, failed to make texture, etc),
|
|
|
|
+ !!! FIXME: we probably need to clean this up so it doesn't interfere with
|
|
|
|
+ !!! FIXME: a software fallback at the system level (can we blit to an
|
|
|
|
+ !!! FIXME: OpenGL window? etc). */
|
|
|
|
+ } else {
|
|
|
|
+ /* future attempts will just try to use a texture framebuffer. */
|
|
|
|
+ /* !!! FIXME: maybe we shouldn't override these but check if we used a texture
|
|
|
|
+ !!! FIXME: framebuffer at the right places; is it feasible we could have an
|
|
|
|
+ !!! FIXME: accelerated OpenGL window and a second ends up in software? */
|
|
|
|
+ _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
|
|
|
|
+ _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
|
|
|
|
+ _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
|
|
|
|
+ created_framebuffer = SDL_TRUE;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _this->checked_texture_framebuffer = SDL_TRUE; /* don't check this again. */
|
|
}
|
|
}
|
|
|
|
|
|
- if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
|
|
|
|
- return NULL;
|
|
|
|
|
|
+ if (!created_framebuffer) {
|
|
|
|
+ if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (window->surface) {
|
|
if (window->surface) {
|