| Summary: | SDL and OpenGL problem with possibly SDL_DisplayFormatAlpha | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Aleksandar Vidakovic <rebelscripts> |
| Component: | video | Assignee: | Ryan C. Gordon <icculus> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | major | ||
| Priority: | P2 | ||
| Version: | 1.2.14 | ||
| Hardware: | x86 | ||
| OS: | Windows 7 | ||
I just commented out the FreeImage(surface); line which is calling SDL_FreeSurface() after checking that the surface is not NULL. And now the exact same faulty memory management is behaving on Windows XP as well. Exactly the same. The same textures that are white rectangles under Windows 7 are now under XP. When I allow for SDL_FreeSurface to be called, then everything is normal under XP, while under Windows 7 the same white rectangles. I just need to add that when SDL_FreeSurface is not called, it behaves the same under all Windows: Windows XP, Windows Vista and Windows 7. Some rectangles are white, some are normal. And all 3 versions behave the same. This must be a SDL_FreeSurface bug, treating freed surfaces as valid and reusing them, not all but some. ... SDL_FreeSurface problem started with 1.2.12 version. 1.2.11 has no problems with SDL_FreeSurface, but is having display problems. Sorry about all of this. It was my fault. I had it compiled with MinGW 3.4.5 which did not complain about my programming error. When I switched to 4.4.1 version it immediately showed up. Everything is fine with SDL, sorry about all of this again. Regards and keep up the good work! |
Hello, Under XP everything is displayed properly, all the textures loaded from the surface into OpenGL texture are properly displayed. Under Windows 7 most of the textures are white rectangles, some are displayed correctly. The format of all images is 32bit with 8bit alpha. [code] SDLw = surface->w; SDLh = surface->h; Release(); // release the previous memory GLfloat coord[4]; if(surface) { SDL_Surface *temp = SDL_DisplayFormatAlpha(surface); if(temp) //if conversion succeeds, free old surface { FreeImage(surface); surface = temp; } else //can't convert, leave surface as is { Error(CRITICAL,"SDL_DisplayFormatAlpha failed: %s for image: %s",SDL_GetError(), imageFileName.c_str()); } origWidth = rWidth = static_cast<float>(surface->w); origHeight = rHeight = static_cast<float>(surface->h); rTexID = SurfaceToTexture(surface,coord); rTexMinX = coord[0]; rTexMinY = coord[1]; rTexMaxX = coord[2]; rTexMaxY = coord[3]; rImage = surface; // scale the image to the current resolution scale if( !DontScale && PEngine::scale != 1.0f ) { PermanentScale( PEngine::scale ); } [/code] here is the part where the image data is loaded into OpenGL texture: [code] GLuint texture; int w, h; SDL_Surface *temp; SDL_Rect area; Uint32 saved_flags; Uint8 saved_alpha; //expand width and height to nearest powers of 2 if( w % 2 != 0 || h % 2 != 0 ) { w = PowerOfTwo(surface->w); h = PowerOfTwo(surface->h); } if( texcoord != NULL ) { 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 } temp = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN //endian specific color masks 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); if(!temp) //failure in CreateRGBSurface return 0; //save alpha 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 surface (do not alter passed surface to allow this function to be used in special situations) area.x = 0; area.y = 0; area.w = static_cast<Sint16>(surface->w); area.h = static_cast<Sint16>(surface->h); int r = SDL_BlitSurface(surface, NULL, temp, &area); //restore saved alpha if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA) SDL_SetAlpha(surface, saved_flags, saved_alpha); // get the number of channels in the SDL surface GLint nOfColors = temp->format->BytesPerPixel; GLenum texture_format; if (nOfColors == 4) // contains an alpha channel { if (temp->format->Rmask == 0x000000ff) texture_format = GL_RGBA; else texture_format = GL_BGRA; } else if (nOfColors == 3) // no alpha channel { if (temp->format->Rmask == 0x000000ff) texture_format = GL_RGB; else texture_format = GL_BGR; } else { //printf("warning: the image is not truecolor.. this will probably break\n"); // this error should not go unhandled } //create the OpenGL texture glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, w, h, 0, texture_format, GL_UNSIGNED_BYTE, temp->pixels); //glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, w, h, 0, texture_format, GL_UNSIGNED_BYTE, temp->pixels); SDL_FreeSurface(temp); //temp surface no longer needed return texture; [/code]