I’m using v2.0.5, and I cannot seem to get SDL_RenderSetClipRect() to work. It’s not clipping any further rendering. Does it only work on RenderCopy’s? Drawing Text and lineColor() seem unaffected?
Points, lines, rectangles, and textures should always be properly clipped by SDL_RenderSetClipRect
. I don’t remember any bugs with this function, but it may worth it to check if SDL 2.0.8 makes any difference.
Here’s a small test that draws the various primitives the render API provides. The lines, filled rectangles, and opaque texture should only be visible in the white area. Press C to deactivate clipping and press space to toggle the animation.
cliprecttest.c
#include <SDL.h>
#define NUM_POINTS 5
static int bounce(int x, int max)
{
x = x % (max * 2);
if (x < 0)
x = -x;
x -= max;
return x < 0 ? -x : x;
}
int main(int argc, char * argv[])
{
SDL_Window * window;
int i, width, height;
SDL_Renderer * renderer;
SDL_RendererInfo info;
SDL_Texture * texture;
SDL_version version;
SDL_Event e;
int done = 0;
int pause = 0;
int clip = 1;
Uint32 counter = 2048;
Uint32 prevticks = SDL_GetTicks();
SDL_Point points[NUM_POINTS];
SDL_Rect rectbg, rect1, rect2, recttex;
SDL_GetVersion(&version);
SDL_Log("Using SDL %d.%d.%d\n", version.major, version.minor, version.patch);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) < 0) {
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("SDL_RenderSetClipRect test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 500, SDL_WINDOW_RESIZABLE);
if (window == NULL){
SDL_Log("Failed to create window: %s", SDL_GetError());
SDL_Quit();
return 1;
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer == NULL){
SDL_Log("Failed to create renderer: %s", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
if (SDL_GetRendererInfo(renderer, &info) == 0) {
SDL_Log("Using renderer %s\n", info.name);
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 128, 128);
if (texture != NULL) {
int x, y;
Uint8 data[128 * 128 * 4] = {0};
for (y = -64; y < 63; y++) {
for (x = -64; x < 63; x++) {
int d = x*x + y*y;
if (d <= 3500) {
int o = (y + 64) * 128 * 4 + (x + 64) * 4;
data[o + 0] = bounce(d / 3 - 64, 128) + 127;
data[o + 1] = bounce(d / 2 + y * d / 100, 255);
data[o + 2] = bounce(d / 2 + x * d / 200, 255);
data[o + 3] = d > 3245 ? 3500 - d : 255;
}
}
}
SDL_UpdateTexture(texture, NULL, data, 128 * 4);
} else {
SDL_Log("Failed to create texture: %s", SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_GetWindowSize(window, &width, &height);
while (!done) {
if (!pause) {
Uint32 now = SDL_GetTicks();
counter += now - prevticks;
prevticks = now;
}
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
done = 1;
} else if (e.type == SDL_KEYDOWN) {
} else if (e.type == SDL_KEYUP) {
Uint32 sym = e.key.keysym.sym;
if (sym == SDLK_ESCAPE) {
done = 1;
} else if (sym == SDLK_c) {
clip = !clip;
prevticks = SDL_GetTicks();
} else if (sym == SDLK_SPACE) {
pause = !pause;
prevticks = SDL_GetTicks();
} else if (sym == SDLK_f) {
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
SDL_SetWindowFullscreen(window, SDL_FALSE);
} else {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
}
} else if (e.type == SDL_WINDOWEVENT) {
if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
SDL_GetWindowSize(window, &width, &height);
}
}
}
rectbg.x = width / 4 - 4;
rectbg.y = height / 4 - 4;
rectbg.w = width / 2 + 8;
rectbg.h = height / 2 + 8;
for (i = 0; i < NUM_POINTS; i++) {
points[i].x = bounce(counter * (i + 1) * 9 / (bounce(i - 3, 7) + 20), 4096) * (width - 1) / 4096;
points[i].y = bounce(counter * (i + 1) * 8 / (bounce(-i - 4, 8) + 20), 4096) * (height - 1) / 4096;
}
rect1.w = (width < height ? width : height) / 3;
rect1.h = rect1.w;
rect1.x = bounce(counter * 9 / 3, 4096) * (width - rect1.w) / 4096;
rect1.y = bounce(counter * 9 / 5, 4096) * (height - rect1.h) / 4096;
rect2.w = (width < height ? width : height) / 5;
rect2.h = rect2.w;
rect2.x = bounce(counter * 9 / 13, 4096) * (width - rect2.w) / 4096;
rect2.y = bounce(counter * 9 / 9, 4096) * (height - rect2.h) / 4096;
recttex.w = (width < height ? width : height) / 4;
recttex.h = recttex.w;
recttex.x = bounce(counter * -2 / 5, 4096) * (width - recttex.w) / 4096;
recttex.y = bounce(counter * 3 / 5, 4096) * (height - recttex.h) / 4096;
SDL_SetRenderDrawColor(renderer, 100, 50, 50, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderFillRect(renderer, &rectbg);
rectbg.x += 4;
rectbg.y += 4;
rectbg.w -= 8;
rectbg.h -= 8;
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderFillRect(renderer, &rectbg);
/* Clip on */
if (clip) {
SDL_RenderSetClipRect(renderer, &rectbg);
}
SDL_SetTextureAlphaMod(texture, 255);
SDL_RenderCopyEx(renderer, texture, NULL, &recttex, counter / 8.5, NULL, SDL_FLIP_NONE);
SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
SDL_RenderDrawLines(renderer, points, NUM_POINTS);
SDL_SetRenderDrawColor(renderer, 100, 100, 255, 255);
SDL_RenderFillRect(renderer, &rect1);
SDL_SetRenderDrawColor(renderer, 255, 100, 0, 255);
SDL_RenderFillRect(renderer, &rect2);
/* Clip off */
SDL_RenderSetClipRect(renderer, NULL);
SDL_SetTextureAlphaMod(texture, 10);
SDL_RenderCopyEx(renderer, texture, NULL, &recttex, counter / 8.5, NULL, SDL_FLIP_NONE);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDrawPoints(renderer, points, NUM_POINTS);
SDL_SetRenderDrawColor(renderer, 200, 200, 255, 255);
SDL_RenderDrawRect(renderer, &rect1);
SDL_SetRenderDrawColor(renderer, 255, 200, 100, 255);
SDL_RenderDrawRect(renderer, &rect2);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Should look like this: