| Summary: | SDL_BlitSurface loses color information | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Uplink <advantis> |
| Component: | video | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | major | ||
| Priority: | P2 | ||
| Version: | 1.2.11 | ||
| Hardware: | x86 | ||
| OS: | Linux | ||
| Attachments: |
Screenshot showing Windows 98, Mac OS X, and Ubuntu
Screenshot of reported result Source code and sample images xdpyinfo on my Debian Etch system |
||
|
Description
Uplink
2007-02-22 09:50:43 UTC
Bugzilla is currently malfunctioning and I can't create an attachment. Here's the source code:
------------------------ CUT ------------------------
test.cpp:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#include <SDL.h>
#include <SDL_image.h>
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
const Uint32 rmask = 0xff000000;
const Uint32 gmask = 0x00ff0000;
const Uint32 bmask = 0x0000ff00;
const Uint32 amask = 0x000000ff;
const int rshift = 24, gshift = 16, bshift = 8, ashift = 0;
#else
const Uint32 rmask = 0x000000ff;
const Uint32 gmask = 0x0000ff00;
const Uint32 bmask = 0x00ff0000;
const Uint32 amask = 0xff000000;
const int rshift = 0, gshift = 8, bshift = 16, ashift = 24;
#endif
int main(int /*argc*/, char * /*argv*/[])
{
/* Initialize SDL */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
return(2);
}
/* Set a 640x480x8 video mode */
SDL_Surface *screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
SDL_GetError());
SDL_Quit();
return(2);
}
SDL_FillRect(screen, NULL, SDL_MapRGBA(screen->format, 255, 0, 255, 128));
SDL_Surface *pChild = IMG_Load("text-child.png");
SDL_Surface *pParent = IMG_Load("background.png");
SDL_BlitSurface(pParent, NULL, screen, NULL);
int X = 0, Y = 0, W = 320, H = 240;
SDL_Rect rect = {X, Y, W, H};
SDL_Surface* pTextSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32, rmask, gmask, bmask, amask);
SDL_Surface *Surface = screen;
bool WasSrcAlpha = (Surface->flags & SDL_SRCALPHA) != 0;
Uint8 WasAlpha = Surface->format->alpha;
SDL_SetAlpha(Surface, 0, 0);
SDL_BlitSurface(Surface, &rect, pTextSurface, NULL);
SDL_SetAlpha(Surface, WasSrcAlpha ? SDL_SRCALPHA : 0, WasAlpha);
//the problem is here:
SDL_BlitSurface(pChild, NULL, pTextSurface, NULL);
SDL_SetAlpha(pTextSurface, 0, 0);
SDL_BlitSurface(pTextSurface, NULL, Surface, NULL);
SDL_UpdateRect(screen, 0, 0, 0, 0);
SDL_Event event;
while (1)
{
if ( SDL_WaitEvent(&event) < 0 )
{
fprintf(stderr, "SDL_PullEvent() error: %s\n", SDL_GetError());
continue;
}
if(event.type == SDL_QUIT)
{
printf("done!\n");
break;
}
}
SDL_Quit();
return 0;
}
------------------------ CUT ------------------------
Makefile:
CXX=g++
CC=$(CXX)
CPPFLAGS=-W -Wall -pipe -ggdb3 -I/usr/include/SDL
CXXFLAGS=-I.
LDFLAGS=-L/usr/local/lib
LDLIBS=-lSDL -lSDL_image
#-lGL -lSGE -lGLU -lXrender
sources = test.cpp
all: $(sources:.cpp=.o)
$(CXX) -o test $+ $(LDFLAGS) $(LDLIBS)
clean:
rm -f test $(sources:.cpp=.o)
------------------------ CUT ------------------------
You'll also need to create two images: background.png and text-child.png, where text-child.png contains black text on transparent background.
I uploaded the archive here:
http://myfreefilehosting.com/f/6c2c932231_0.08MB
The is usually kept by the server for around a month before being deleted.
Can you describe what the problem actually is? Maybe add a screenshot of the correct behavior? I tested it on Windows 98, Mac OS X, and Ubuntu and got the same result each time. I'm attaching a screenshot. Created attachment 219 [details]
Screenshot showing Windows 98, Mac OS X, and Ubuntu
Created attachment 220 [details]
Screenshot of reported result
This is the screenshot of the result on my Debian Etch system. Under Ubuntu Dapper (SDL 1.2.9) the result seems to be correct (I didn't report this version of Ubuntu in the original post).
Created attachment 221 [details]
Source code and sample images
Since attachments work now, I'm posting the archive here too (I was lucky that the file sharing site kept the file for so long)
What's the output of xdpyinfo on your Debian Etch system? Created attachment 222 [details]
xdpyinfo on my Debian Etch system
Nevermind, looking closer I don't think it matters. Can you debug into SDL_BlitSurface(pChild, NULL, pTextSurface, NULL) and see what blitter it's actually using there? I don't seem to have a debug version of the SDL libs in Debian Etch so I can't step into the function and see what it's doing. I'll have to build one myself. Can you be more specific about what I should be looking for? When you step into the blit function you'll be going through code that looks at the source surface and the destination surface and picks a blit function to use. I'm curious which blit function it's choosing. For example on Mac OS X, SDL_UpperBlit goes into SDL_LowerBlit and then SDL_CalculateBlit eventually calls SDL_CalculateAlphaBlit() which assigns SDL_SoftBlit to surface->map->sw_blit. Then inside SDL_SoftBlit, the actual blit function ends up being BlitRGBtoRGBPixelAlphaMMX() I'm guessing you end up in the 3DNow! or C blitters which have a bug in them... So what processor do you have in your Debian system? I have an AMD Athlon 64 CPU (but the OS is 32bit) I bet you're hitting the 3DNow! codepath. I have an AMD system I can check it out on. Thanks! Strange, I tested this on my AMD system and it works fine. The blit function that's used is BlitRGBtoRGBPixelAlphaMMX3DNOW() Can you set a breakpoint at line 64 in test.cpp, and then when you hit it, set a breakpoint in SDL_SoftBlit and then step into the blit function to find out which it is? Do you know if you've compiled SDL as 32-bit or 64-bit code? Could the problem simply be that the assembly blitters are used in 64-bit mode? Bumping some bugs' priorities to P1 for consideration before the 1.2.12 release (though some may not be resolved for 1.2.12). --ryan. BlitRGBtoRGBPixelAlphaMMX3DNOW. This is the function called from SDL_SoftBlit on my system. But I ran the code on a Intel Pentium 4 running Ubuntu Feisty (SDL 1.2.11) and the result is the same. Later I'll try to see which blitter that CPU is using, as it doesn't have 3DNow! BTW, the Operating Systems are 32bit-only on both systems (the Pentium 4 I used doesn't have AMD64/EM64T instructions at all). On the Intel Pentium 4 machine the blitting function is BlitRGBtoRGBPixelAlphaMMX. Okay, then maybe the problem is in the load, somehow? Can you save out the text surface after it's loaded just to make sure it looks good? You can probably use SDL_SaveBMP(), and if that shows the problem you might be able to cut the test program down to "load file, save file, view" The text image has alpha information which a BMP can't store. I'll get some code that saves PNG from a SDL surface and use that. Any luck debugging this yet? You shouldn't actually need to save the alpha information to see whether the image is correct. Without alpha I believe the background will be black. Sorry, I didn't have the time to continue. I already have the code for saving as PNG from a SDL surface, but barely have the time to copy/paste it and do the test itself and other debugging. Saving the image as a PNG is important because the test is black, and displayed on a black background in BMP is just not useful. I'll try to get back to you in the following days. Saving the text image as PNG doesn't show any problems, so the image is loaded fine. My PNG-saving function only knows RGBA surfaces, so I saved the background.png image using SDL_SaveBMP. Again, no problem. So it's something else. In the following days I'll have a Kubuntu machine setup on the Internet. I can give you direct access to it once it's up and running. I logged into this system remotely and ran the test program with SDL 1.2.11, and the output was as described. I built SDL 1.2.12, and the output was fine. I suspect either the SDL 1.2.11 build was built with optimization bugs or the bug was fixed in SDL 1.2.12. Please reopen this bug if you can reproduce it with SDL 1.2.12. Thanks! BTW, I poked through the debian diffs there, and I see some suspicious patches that add a hermes MMX blitter and a bunch of PIC changes for hermes itself. I wonder if this is the culprit? Can you build your SDL 1.2.11 sources without the debian patches and see if that's it? Okay, I just compiled fresh SDL 1.2.11 and confirmed the bug exists, and fresh SDL 1.2.12 and confirmed the bug no longer exists. Woo! Thanks for the access to help me track this down! |