The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Inverting draw mode?
joymaker


Joined: 22 Nov 2016
Posts: 9
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".
Re: Inverting draw mode?
rtrussell


Joined: 10 Feb 2016
Posts: 88
joymaker wrote:
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.
Inverting draw mode?
Jonny D


Joined: 12 Sep 2009
Posts: 932
Does GLSL ES have bitwise operators?  I would think you could invert in a shader.

Jonny D


On Thu, Dec 8, 2016 at 7:12 AM, rtrussell wrote:
Quote:



joymaker wrote:

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.


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

EternalLands


Joined: 01 Dec 2016
Posts: 16
Reading from the video memory is always a bad idea.
Why don't you make your own screen buffer, do your drawing in it, then at the end you put it in a texture and render it?
joymaker


Joined: 22 Nov 2016
Posts: 9
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


Joined: 10 Feb 2016
Posts: 88
joymaker wrote:
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.

Quote:
(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


Joined: 10 Feb 2016
Posts: 88
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;
}