I’m working on my first SDL program and I’m writing a terminal (telnet) application that uses bitmap fonts.
Most of the tutorials I’ve seen have been pretty basic about getting character cells on to the screen but nothing really addresses when the screen is full the best way to scroll the screen up and continue drawing on the bottom line in an efficient manner when multiple pages of text are sent to render and you need to scroll up the screen on a continuous basis.
I’ve tried several different techniques to find what works best for my situation, and I started out with Lazy Foo tutorials, which basically loads the Bitmap image into a Surface, moves it to a Texture right away. The font cells are then plotted to an array of SDL_Rects. This is nice and fast only if you are not changing the font (Characters) colors on the fly. In this case you have to grab the pixels (Copying from GPU back to CPU Memory) and change the colors but then you only have access to foreground colors not background colors. Also when change colors per character and doing either Create Texture, or Update Texture (to resend the from the CPU back to the GPU) for each character it’s very costly and slow.
After a lot of pain staking testing and research I found a much better way to handle bitmap fonts. Keep the bitmap in a surface, use SDL_Rect to clip out each character cell as needed, and change the foreground and background pixel colors as needed in a temp SDL_Rec and then plot each character to a new Surface on the fly. Once the screen is built, use SDL_SurfaceToTexture to then RenderCopy the texture to the screen. This works great, entire screens can be spit out very fast, aprox 40 ms. (usually 20ms to fill and plot the surface, 20ms more to Convert Surface to Texture).
The problem I’m having now is once the screen is full, I want to scroll everything up by 1 row, then write the next line at the bottom.
I’ve currently done this by keeping the Surface active after building the texture. Then using SDL_BlitSurface from the screenSurface to a temp scrollingSurface skipping the top row, then clearing and SDL_BlitSurface back to the screenSufare when then moves everything up one row.
Now this works perfectly, however once I hit the end of the screen and start scrolling, I have to run this for each new line. Basically SDL_BlitSurface the surface area I want to chop, then SurfaceToTexture, and Rendering each line by line to keep scrolling the screen up. This not very fast and the screen ends up scrolling a bit slow.
Does anyone have any suggestions on improvements or a better way to go about this to make it scroll up the screen faster?
Example of what I’m currently using to move the screen up:
void GraphicRenderer::ScrollScreenUp (SDL_Surface *src)
SDL_Rect pick, pick2;
// Skip first row Start Y after the Height of the first Row or Character Cell Height. pick.x = 0; pick.y = CHAR_HEIGHT; pick.w = SCREEN_WIDTH; pick.h = SCREEN_HEIGHT; // Set the Destination to plot back to the top of the screen. pick2.x = 0; pick2.y = 0; pick2.w = SCREEN_WIDTH; pick2.h = SCREEN_HEIGH; // Set temp scroll surface SDL_Surface *scrollSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,SCREEN_WIDTH, SCREEN_HEIGHT, 32, redMask, greenMask, blueMask, alphaMask); // Clear the scroll Surface, Fill With Black SDL_FillRect(scrollSurface, NULL, SDL_MapRGB(scrollSurface->format, 0, 0, 0)); // Copy Current Screen to Temp Scroll Surface SDL_BlitSurface(src,&pick,scrollSurface,NULL); // Clear the Current Screen Surface SDL_FillRect(src, NULL, SDL_MapRGB(src->format, 0, 0, 0)); // Copy Reposition Scroll Surface back to the Screen Surface SDL_BlitSurface(scrollSurface,NULL,src,&pick2); // Free the Temp Scroll Surface SDL_FreeSurface( scrollSurface ); // Converts Screen to Texture then runs SDL_RenderCopy's and SDL_RenderPresent. DrawScreen();