| Summary: | Image flipped vertically when rendering on texture | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Alain <alain.bonnefoy> |
| Component: | render | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | major | ||
| Priority: | P2 | CC: | alain.bonnefoy, ant, sylvain.becker |
| Version: | 2.0.9 | ||
| Hardware: | All | ||
| OS: | Linux | ||
Just tried an it seems to happen at least with opengl, es, es2, but not with software renderer.
it seems that changing the target texture doesn't set "viewport_dirty" and so the projection isn't modified.
Changing (not a patch) :
data->drawstate.viewport_dirty = SDL_TRUE;
to FALSE in SDL_render_gles2.c
proves that it would work
Not sure where the best place to fix this,
maybe setting viewport_dirty in GLES2_SetRenderTarget() ?
--- a/src/render/opengles2/SDL_render_gles2.c Sat Feb 23 09:36:56 2019 +0100
+++ b/src/render/opengles2/SDL_render_gles2.c Fri Mar 08 15:13:41 2019 +0100
@@ -1761,6 +1762,9 @@
return SDL_SetError("glFramebufferTexture2D() failed");
}
}
+
+ data->drawstate.viewport_dirty = SDL_TRUE;
+
return 0;
}
Could also be done at the beginning of GLES2_RunCommandQueue
like metal renderer does
--- a/src/render/opengles2/SDL_render_gles2.c Sat Feb 23 09:36:56 2019 +0100
+++ b/src/render/opengles2/SDL_render_gles2.c Fri Mar 08 15:21:30 2019 +0100
@@ -1206,6 +1207,7 @@
return -1;
}
+ data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
Which makes me think there is big difference between Metal and GL renderers. For Metal renderer: METAL_DrawStateCache is created and used only in RunCommandQueue For GL renderers: GLES2_DrawStateCache belongs to the GLES2_RenderData and is available anytime. Which looks more complicated. This happens for me on Windows openGL, but only with the current source (HG). The 2.0.9 DLL works OK on Windows. I have tested and fixed on linux for gl, gles2, gles https://hg.libsdl.org/SDL/rev/6a60a1e87d10 Please try also on your side Hello, Many many thanks for looking at this issue so quickly. I greatly appreciate! I need to ask my electronic board provider to rebuild it to be sure to test it in situation. I hope I'll get back to you very soon. Alain |
Hello, I'm using the SDL 2.0.9 with patch 12581 (for eGalax touchscreen support), on Linux with openglES2, with or without X server. I just noticed that when I render an image directly on screen everything is working fine but when I render this image on a texture and then this texture on screen, the result is flipped vertically. The test case is this one: #include <stdio.h> #include <stdlib.h> #include <SDL2/SDL.h> #include <SDL2/SDL_events.h> #include <SDL2/SDL_image.h> SDL_Texture *WID_loadTexture( SDL_Renderer *renderer, char *name) { SDL_Texture *texture = NULL; if(renderer == NULL) { printf("%s\n", SDL_GetError()); SDL_ClearError(); return NULL; } SDL_Surface* surface = IMG_Load( name ); if (surface == NULL) { printf("%s\n", SDL_GetError()); } else { texture = SDL_CreateTextureFromSurface( renderer, surface ); if (texture == NULL) { printf("%s\n", SDL_GetError()); SDL_ClearError(); return NULL; } SDL_FreeSurface( surface ); } return texture; } int main(void) { SDL_Window *WID_main_window; SDL_Renderer *WID_main_renderer; SDL_Event sdlevt; if ( SDL_Init( SDL_INIT_EVERYTHING) < 0 ) { exit(-1); } int video_driver_index = 1; int renderer_index = 1; SDL_RendererInfo info; setenv("SDL_VIDEODRIVER",SDL_GetVideoDriver(video_driver_index),1); SDL_GetRenderDriverInfo(renderer_index,&info); if(SDL_SetHint(SDL_HINT_RENDER_DRIVER, info.name) != SDL_TRUE) { printf("SDL_SetHint %s\n", SDL_GetError()); exit(-1); } if ((WID_main_window = SDL_CreateWindow("icoone", 0, 0, 1024, 768, SDL_WINDOW_SHOWN)) == NULL) { exit(-1); } if ((WID_main_renderer = SDL_CreateRenderer(WID_main_window, renderer_index, info.flags)) == NULL) { exit(-1); } if (SDL_SetRenderTarget(WID_main_renderer, NULL) != 0) { printf("SDL_SetRenderTarget %s\n", SDL_GetError()); exit(-1); } SDL_SetRenderDrawColor(WID_main_renderer, 0x80, 0x80, 0x80, SDL_ALPHA_OPAQUE); SDL_Texture *drawingTexture; if ((drawingTexture = SDL_CreateTexture(WID_main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 1024, 768)) == NULL) { printf("SDL_CreateTexture %s\n", SDL_GetError()); exit(-1); } SDL_Texture *backgroundImage; if ((backgroundImage = WID_loadTexture(WID_main_renderer, "visage.jpg")) == NULL) { exit(-1); } SDL_RenderClear(WID_main_renderer); if (SDL_SetRenderTarget(WID_main_renderer, NULL) != 0) { fprintf(stderr, "SDL_SetRenderTarget error %s\n", SDL_GetError()); exit(-1); } if (SDL_RenderCopy( WID_main_renderer, backgroundImage, NULL, NULL) != 0) { fprintf(stderr, "SDL_RenderCopy error %s\n", SDL_GetError()); exit(-1); } SDL_RenderPresent(WID_main_renderer); SDL_Delay(2000); SDL_RenderClear(WID_main_renderer); if (SDL_SetRenderTarget(WID_main_renderer, drawingTexture) != 0) { fprintf(stderr, "SDL_SetRenderTarget error %s\n", SDL_GetError()); exit(-1); } if (SDL_RenderCopy( WID_main_renderer, backgroundImage, NULL, NULL) != 0) { fprintf(stderr, "SDL_RenderCopy error %s\n", SDL_GetError()); exit(-1); } if (SDL_SetRenderTarget(WID_main_renderer, NULL) != 0) { fprintf(stderr, "SDL_SetRenderTarget error %s\n", SDL_GetError()); exit(-1); } if (SDL_RenderCopy( WID_main_renderer, drawingTexture, NULL, NULL) != 0) { fprintf(stderr, "SDL_RenderCopy error %s\n", SDL_GetError()); exit(-1); } SDL_RenderPresent(WID_main_renderer); int loop = 1; while (loop) { SDL_PollEvent(&sdlevt); if ( sdlevt.type == SDL_QUIT ) { loop = 0; } SDL_Delay(50); SDL_FlushEvent(SDL_MOUSEMOTION); } SDL_DestroyTexture(backgroundImage); SDL_DestroyRenderer(WID_main_renderer); SDL_DestroyWindow(WID_main_window); SDL_Quit(); return EXIT_SUCCESS; } The image is here https://i.imgur.com/Gg4IBM2.jpg Alain