Discussion:
[SDL] Inverting draw mode?
joymaker
2016-12-08 06:03:09 UTC
Permalink
I'm porting some legacy Mac code to SDL, since Apple Computer has yanked away the C++ interfaces from beneath me.

One thing I was using was the inverting draw mode. This means that the new image is drawn onto the window or drawing surface using an exclusive-or operation at the bit level. It has the convenient property that if you draw the same object onto the same surface twice in this mode, it vanishes, restoring the surface to its previous state. This has some cool artistic uses, and is also useful for compatibility with some legacy code.

I'm not seeing it in the documentation, and I'm aware that modern graphics cards may not encourage such an operation onto the screen, but it sure would be nice to be able to do this to a Texture. Is this at all supported? If not, I would urge its adoption as an additional "Blending mode".
rtrussell
2016-12-08 12:12:03 UTC
Permalink
Post by joymaker
Is this at all supported? If not, I would urge its adoption as an additional "Blending mode".
I rely on it. The solution I use is to force OpenGL (or GLES 1.0) when it's not the default:


Code:
SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengl") ;
window = SDL_CreateWindow(..., SDL_WINDOW_OPENGL...) ;


then you can enable the wanted drawing mode using:


Code:
glEnable (GL_COLOR_LOGIC_OP) ;
glLogicOp (GL_XOR) ;



Works perfectly for me on Windows, Linux, Mac OS and Android. It's unfortunate that support for glLogicOp was dropped from GLES 2.0 so on platforms which can't run full OpenGL you are forced to use the legacy GLES 1.0.

Richard.
Jonathan Dearborn
2016-12-08 14:36:54 UTC
Permalink
Does GLSL ES have bitwise operators? I would think you could invert in a
shader.

Jonny D
Post by joymaker
Is this at all supported? If not, I would urge its adoption as an
additional "Blending mode".
I rely on it. The solution I use is to force OpenGL (or GLES 1.0) when
SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengl") ;
window = SDL_CreateWindow(..., SDL_WINDOW_OPENGL...) ;
glEnable (GL_COLOR_LOGIC_OP) ;
glLogicOp (GL_XOR) ;
Works perfectly for me on Windows, Linux, Mac OS and Android. It's
unfortunate that support for glLogicOp was dropped from GLES 2.0 so on
platforms which can't run full OpenGL you are forced to use the legacy GLES
1.0.
Richard.
_______________________________________________
SDL mailing list
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
joymaker
2016-12-14 01:17:40 UTC
Permalink
EternalLands - that's what I was planning on doing anyway, I just didn't see any primitive operators with which to do it. What I don't want to do if I don't have to is reinvent the rectangle drawing primitive from scratch, just to do this.

Richard – thanks, that sounds like a good plan. So I think you're telling me that setting up the OpenGL LogicOp will modify ALL drawing done through the window, SDL primitives as well as OpenGL primitives. Right? (And is there any significant downside to specifying "opengl" as my driver, instead of the usual default?)

Thanks,
Ken
rtrussell
2016-12-14 09:19:58 UTC
Permalink
Post by joymaker
So I think you're telling me that setting up the OpenGL LogicOp will modify ALL drawing done through the window, SDL primitives as well as OpenGL primitives. Right?
Yes, SDL drawing operations such as SDL_RenderDrawPoint, SDL_RenderDrawLine and those in SDL_gfx will be affected by the LogicOp. For safety I would recommend enabling and setting the LogicOp only around such calls rather than leaving it active for longer periods, just in case it interferes with anything else in SDL.
Post by joymaker
(And is there any significant downside to specifying "opengl" as my driver, instead of the usual default?)
Only in Windows is OpenGL/GLES not the default, I think, and I've not noticed any significant impact from forcing its use.

Richard.
rtrussell
2016-12-14 09:55:29 UTC
Permalink
Here's the SDL_gfx demo modified to use exclusive-or plotting:


Code:
// Demo of exclusive-or plotting by Richard Russell http://www.rtrussell.co.uk/

#include <stdio.h>
#include "SDL2_gfxPrimitives.h"

#define WIDTH 640
#define HEIGHT 480
#define GL_COLOR_LOGIC_OP 0xBF2
#define GL_XOR 0x1506

#ifdef __WINDOWS__
void (__stdcall *glEnable) (int) ;
void (__stdcall *glLogicOp) (int) ;
void (__stdcall *glDisable) (int) ;
#else
void (*glEnable) (int) ;
void (*glLogicOp) (int) ;
void (*glDisable) (int) ;
#endif

int main(int argc, char* argv[])
{

if (SDL_Init(SDL_INIT_VIDEO))
{
printf ("SDL_Init Error: %s", SDL_GetError());
return 1;
}

SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengl") ;

SDL_Window *window = SDL_CreateWindow("SDL2_gfx test", 100, 100, WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
if (window == NULL)
{
printf ("SDL_CreateWindow Error: %s", SDL_GetError());
SDL_Quit();
return 2;
}

glLogicOp = SDL_GL_GetProcAddress("glLogicOp") ;
glEnable = SDL_GL_GetProcAddress("glEnable") ;
glDisable = SDL_GL_GetProcAddress("glDisable") ;

SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL)
{
SDL_DestroyWindow(window);
printf ("SDL_CreateRenderer Error: %s", SDL_GetError());
SDL_Quit();
return 3;
}

SDL_Event e;

int quit = 0;
while (!quit)
{
if (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
quit = 1;
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0xFF, 0xFF);
SDL_RenderClear(renderer);

glEnable (GL_COLOR_LOGIC_OP) ;
glLogicOp (GL_XOR) ;

thickLineColor(renderer, 0, 0, WIDTH, HEIGHT, 20, 0xFFFFFFFF) ;
thickLineColor(renderer, 0, HEIGHT, WIDTH, 0, 20, 0xFFFFFFFF) ;
circleColor(renderer, WIDTH/2, HEIGHT/2, 80, 0xFF00FF00);
filledCircleColor(renderer, WIDTH/2, HEIGHT/2, 60, 0xFF0000FF);

glDisable (GL_COLOR_LOGIC_OP) ;

SDL_RenderPresent(renderer);
SDL_Delay(10);
}

SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

Continue reading on narkive:
Loading...