SDL_CreateRGBSurface

Started by
27 comments, last by LordSputnik 15 years, 8 months ago
Having solved my problem, I'm now printing off transparent text like there's no tomorrow... However, I've found that I can only print 8 or 9 letters using this function:
//Renders text onto a Rect in GL.
void SDL_GL_RenderText(char *text, 
                      TTF_Font *font,
                      SDL_Color color,
                      SDL_Color bgcolor,
                      SDL_Rect *location,
                      int alignment,int transp,textquality quality)
{
	SDL_Surface *initial;
	SDL_Surface *intermediary;
	SDL_Rect rect;
	int w,h;
	GLuint texture;
	
	/* Use SDL_TTF to render our text */
    if (quality == solid)
    {
        initial = TTF_RenderText_Solid(font, text, color);
    }
    else if (quality == shaded)
    {
        initial = TTF_RenderText_Shaded(font, text, color, bgcolor);
    }
    else if (quality == blended)
    {
        initial = TTF_RenderText_Blended(font, text, color);
    }
	
	/* Convert the rendered text to a known format */
   w = initial->w;
   h = initial->h;
   t_height = initial->h;
   t_width = initial->w;
   printf("SDL_GL_RENDER_TEXT: Text Height: %i Width: %i\n",h,w);

if((quality == shaded) && (transp = 1))
{
printf("Error: Cannot render shaded text as transparent!");  
}
   
   intermediary = SDL_CreateRGBSurface(0, w, h, 32, 
			0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);

   printf("SDL_GL_RENDER_TEXT: BREAKPOINT ALPHA\n");

   SDL_BlitSurface(initial, NULL, intermediary, NULL);

	/* Tell GL about our new texture */
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, 
			GL_UNSIGNED_BYTE, intermediary->pixels );
	
	/* GL_NEAREST looks horrible, if scaled... */
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	/* prepare to render our texture */
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texture);
	glColor3f(1.0f, 1.0f, 1.0f);

	
   printf("SDL_GL_RENDER_TEXT: BREAKPOINT EPSILON\n");	

	/* Draw a quad at location */
	switch(alignment)
	{
        case 0: //Left
        if(transp == 1)
        {
            DrawRectTransparent(location->x,location->y,(location->x + w),(location->y + h));
        }
        else
        {
            DrawRect(location->x,location->y,(location->x + w),(location->y + h));
        }
            break;
        case 1: //Center
        if(transp == 1)
        {
            DrawRectTransparent((location->x - (w/2)),location->y,(location->x + (w/2)),location->y + h);
        }
        else
        {
            DrawRect((location->x - (w/2)),location->y,(location->x + (w/2)),location->y + h);
        }
            break;
        case 2: //Right
        if(transp == 1)
        {
            DrawRectTransparent((location->x + w),(location->y + h),location->x,location->y);
        }
        else
        {
            DrawRect((location->x + w),(location->y + h),location->x,location->y);
        }
            break;
    }
	
   printf("SDL_GL_RENDER_TEXT: BREAKPOINT FREDDY\n");	

	/* Bad things happen if we delete the texture before it finishes */
	glFinish();

   printf("SDL_GL_RENDER_TEXT: BREAKPOINT GAMMA\n");	
	
	/* return the deltas in the unused w,h part of the rect */
	location->w = initial->w;
	location->h = initial->h;
	
   printf("SDL_GL_RENDER_TEXT: BREAKPOINT HALO\n");	

	/* Clean up */
	SDL_FreeSurface(initial);
	SDL_FreeSurface(intermediary);
	glDeleteTextures(1, &texture);

   printf("SDL_GL_RENDER_TEXT: BREAKPOINT INDIGO\n");	
}
Having identified the problem as being the SDL_CreateRGBSurface(), I was wondering if anyone could tell me how/where I'm going wrong, or if there's a much better way to do this. Thanks once more! Sputty.
Advertisement
What is your actual problem? ie. What happens when you try? Error message? A crash? Visual problem? Your hard disk gets formatted?
I am not sure your problem but here is how I render out a surface
It is similar to what you are trying to do


	void  Sprockets::SDL_GL_SurfaceToTexture(SDL_Surface * surface)	{		//need to refine this	if(m_GLTexture!=0)			{				 glDeleteTextures( 1, &m_GLTexture);				 m_iTextureH=0;				 m_iTextureW=0;				 m_GLTexture=0;			}		int h=NearestPowerOfTwo(surface->h);		int w=NearestPowerOfTwo(surface->w);		Uint32 rmask, gmask, bmask, amask;		SDL_Surface * temp = NULL;		SDL_Surface * tempalpha = NULL;		#if SDL_BYTEORDER == SDL_BIG_ENDIAN			rmask = 0xff000000;			gmask = 0x00ff0000;			bmask = 0x0000ff00;			amask = 0x000000ff;		#else			rmask = 0x000000ff;			gmask = 0x0000ff00;			bmask = 0x00ff0000;			amask = 0xff000000;		#endif	tempalpha = SDL_DisplayFormatAlpha(surface);	SDL_SetAlpha(surface, 0, SDL_ALPHA_TRANSPARENT);	temp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,32, bmask, gmask, rmask, amask);	CreateTexture(temp,tempalpha);	//SDL_UnlockSurface(temp);	SDL_FreeSurface(temp);	SDL_FreeSurface(tempalpha);	//return texture;}void Sprockets::CreateTexture(SDL_Surface * _baseSurface,SDL_Surface * _image){		int h=NearestPowerOfTwo(_image->h);		int w=NearestPowerOfTwo(_image->w);	if(_baseSurface && _image)	{		glGenTextures(1, &m_GLTexture);		glBindTexture(GL_TEXTURE_2D, m_GLTexture);		//SDL_LockSurface(temp);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,  GL_LINEAR);		glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, _baseSurface->pixels);		glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_image->w,_image->h,GL_BGRA,GL_UNSIGNED_BYTE,_image->pixels);		m_iTextureH=h;		m_iTextureW=w;	}	return;}
Black CloakEpee Engine.
What's actually happening is that I'm typing, and the letters are being converted from unicode to string(I know that that part isn't causing the error), then the text is rendered by TTF_Render_Solid, and then when I try to make a new surface to blit it on, a Segmentation Fault occurs, and SDL deploys its parachute.

I can render surfaces fine, as well as preset text. It's only when I type, and make a new quad each time the phrase is updated, that it starts crashing.
Any ideas? :)
I forgot to post the code, so I'll do that now:

	SDL_Surface *initial;	SDL_Surface *intermediary;	SDL_Rect rect;	char* textc;	int w,h;	GLuint texture;    textc = new char[text.size()+1];    strcpy (textc, text.c_str());			/* Use SDL_TTF to render our text */        if (quality == solid)        {        initial = TTF_RenderText_Solid(font, textc, color);        }        else if (quality == shaded)        {        initial = TTF_RenderText_Shaded(font, textc, color, bgcolor);        }        else if (quality == blended)        {        initial = TTF_RenderText_Blended(font, textc, color);        }		/* Convert the rendered text to a known format */   w = initial->w;   h = initial->h;   t_width = initial->w;   printf("SDL_GL_RENDER_TEXT: Text Height: %i Width: %i\n",h,w);if((quality == shaded) && (transp = 1)){printf("Error: Cannot render shaded text as transparent!");  }      intermediary = SDL_CreateRGBSurface(0, w, h, 32, 			0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);   SDL_BlitSurface(initial, NULL, intermediary, NULL);	/* Tell GL about our new texture */	glGenTextures(1, &texture);	glBindTexture(GL_TEXTURE_2D, texture);	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, 			GL_UNSIGNED_BYTE, intermediary->pixels );		/* GL_NEAREST looks horrible, if scaled... */	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	/* prepare to render our texture */	glEnable(GL_TEXTURE_2D);	glBindTexture(GL_TEXTURE_2D, texture);	glColor3f(1.0f, 1.0f, 1.0f);	/* Draw a quad at location */	switch(alignment)	{        case 0: //Left            DrawRect(location->x,location->y,(location->x + w),(location->y + h));            break;        case 1: //Center            DrawRect((location->x - (w/2)),location->y,(location->x + (w/2)),location->y + h);            break;        case 2: //Right            DrawRect((location->x + w),(location->y + h),location->x,location->y);            break;    }	/* Bad things happen if we delete the texture before it finishes */	glFinish();	/* return the deltas in the unused w,h part of the rect */	location->w = initial->w;	location->h = initial->h;		/* Clean up */	SDL_FreeSurface(initial);	SDL_FreeSurface(intermediary);	glDeleteTextures(1, &texture);


The CreateRGB is freezing it. I've noticed that when I press individual keys, or put a small delay in the main loop, the problem takes a lot longer to manifest...

Maybe CreateRGB is taking too long to run, and so my key pushes are crashing the program... Would finding a substitute to creating a new surface each time be the best way to move forward?

Anyway, any ideas as to the cause of the problem, or the best solution are much appreaciated, as always...

Thanks again,

Sputty.
I need to see how you are calling this or can you post a code snip it (that compiles) that has the same issue so we can compile and run it.

At this point I can only guess at your issue.
Are you opening the font each time?
Are you forgetting to close the font before you are reopening it?

Currently I do not see any issue with the way you are calling CreateRGB.
Black CloakEpee Engine.
I'll try to make a demo program for you by tomorrow... In the meantime, it's being called from this:

void PrintChat(string print,TTF_Font *printfont,int fr,int fg,int fb,int br,int bg,int bb,int x,int y,int align,int wrap){    SDL_Rect printloc;    char* printline;    int linesz = 0;    t_height = 0;    printloc.x = x;    printloc.y = y;    printf("Printing: %s",print.c_str());    int i;    if(print.compare((print.length()-(int)strlen("\n")),(int)strlen("\n"),"\n") == 0)    {        print = print.substr(0,(print.length()-(int)strlen("\n")));    }        char* printc = new char[print.size()+1];            strcpy (printc, print.c_str());       printline = strtok(printc, "\n");    while(printline != NULL && (print.compare((linesz+(int)strlen(printline)),(int)strlen("\n"),"\n") == 0))    {        linesz += ((int)strlen(printline)+(int)strlen("\n"));        printloc.y += TTF_FontLineSkip(printfont);                SDL_GL_RenderText(printline,printfont,SetRGB(fr,fg,fb),SetRGB(br,bg,bb),&printloc,align,1,solid);        printline = strtok(NULL,"\n");    }    if(printline != NULL)    {    linesz += (int)strlen("\n");    }    printline = new char [(print.length()-linesz)+1];printf("PRINTCHAT: STRCOPY!\n");            strcpy (printline,(print.substr(linesz-1,(print.length()-linesz)+1)).c_str());printf("PRINTCHAT: Loop Done! Printing: '%s'. LineSZ: %i\n",printline,linesz);            printloc.y += TTF_FontLineSkip(printfont);printf("PRINTCHAT: Rendering!\n");        SDL_GL_RenderText(printline,printfont,SetRGB(fr,fg,fb),SetRGB(br,bg,bb),&printloc,align,1,solid);        printf("T_Width: %i",t_width);printf("PRINTCHAT: Render Sucessful!\n");        SDL_GL_SwapBuffers();}


Which is being called everytime a key is pressed. The key is converted to unicode, and added to the chat buffer string, which is then passed as the first argument in the above function. I have the font that I use initialized globally outside the function (as TTF_Font* uifont), because I'm using it for more than one thing. I'm pretty sure it crashed on the CreateRGB... could it be that I'm calling it too frequently?
Ok, I made a sample program which demostrates the problem. It can be found here. Thanks once again! Try typing something long, and see how it crashes :/
I've downloaded the program and am playing around with it, and it doesn't appear to be crashing on SDL_CreateRGBSurface. It's actually crashing on SDL_FreeSurface(initial). Or, at least commenting out that line stops it from crashing. The 'initial' pointer must be getting corrupted along the way, and when you free it, it probably frees more than it's supposed to...

Oh, and the program is VERY laggy. The SDL documentation recommends you do not use SDL_EnableUNICODE( SDL_ENABLE ), as it slows everything WAY down. It's not too hard to just check for the letters yourself, and seeing as how it's many times faster, it's definitely worth it.

"UNICODE translation does create a slight overhead so don't enable it unless its needed."

[Edit:] Commenting out either of the two SDL_FreeSurface() lines stops it from crashing.

This topic is closed to new replies.

Advertisement