JuliaMultimedia / SimpleDirectMediaLayer.jl

SDL2
MIT License
81 stars 18 forks source link

Can not use SDL2_gfx primitives for renderering #68

Open OmegaLambda1998 opened 1 year ago

OmegaLambda1998 commented 1 year ago

Minimum working example:

julia> using SimpleDirectMediaLayer

julia> using SimpleDirectMediaLayer.LibSDL2

julia> window = SDL_CreateWindow("test", 0, 0, 500, 500, SDL_WINDOW_SHOWN)
Ptr{SDL_Window} @0x00000000012c1230

julia> renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)
Ptr{SDL_Renderer} @0x0000000001637bf0

julia> SimpleDirectMediaLayer.LibSDL2.rectangleRGBA(renderer, 10, 10, 50, 50, 255, 255, 255, 255)
ERROR: could not load symbol "rectangleRGBA":
/home/[redacted]/.julia/artifacts/8f20658b625a577cdc6b81980bbae941cb291139/lib/libSDL2.so: undefined symbol: rectangleRGBA
Stacktrace:
 [1] rectangleRGBA(renderer::Ptr{SDL_Renderer}, x1::Int64, y1::Int64, x2::Int64, y2::Int64, r::Int64, g::Int64, b::Int64, a::Int64)
   @ SimpleDirectMediaLayer.LibSDL2 ~/.julia/packages/SimpleDirectMediaLayer/wjMsP/src/LibSDL2.jl:6142
 [2] top-level scope
   @ REPL[5]:1

Not only does this not work, it also looks like the SDL2_gfx primitives are not exported. Strangely the SDL2_framerate objects (SDL_initFramerate, SDL_getFramerate, SDL_setFramerate, etc...) which are part of SDL2_gfx do exist!

Noremac11800 commented 11 months ago

I have the same problem. The generator does not appear to be including all of the functions in sdl_gfxPrimitives correctly. Trying to use any of the sdl_gfxPrimitive functions results in the error: ERROR: could not load symbol "some gfxPrimitive function name"

Has anyone come up with a fix for this yet?

Noremac11800 commented 11 months ago

Actually it appears that that isn't the problem. I believe that the problem lies in the initial bindings generated for SDL_gfx. This package SDL2_gfx_jll claims to have generated the bindings but clearly they are not working for the gfx_primitives functions. They may have to be regenerated and confirmed to work. The good news is that the original PR for adding the bindings into this repo should still work. But the SDL2_gfx_jll package will have to be updated on the registry to make the bindings work.

mpeters2 commented 10 months ago

Same here for thickLineRGBA()

mpeters2 commented 10 months ago

I noticed this in the generator.toml: export_symbol_prefixes = ["TTF_", "IMG_", "Mix_", "SDL_", "MIX_", "RW_", "AUDIO_", "KMOD_", "HAVE_", ]

I don't remotely understand how Clang.jl works, but none of the SDL2_gfx functions have prefixes. I wonder if that is the issue?

Kyjor commented 10 months ago

Has anyone found a workaround?

Kyjor commented 9 months ago

I found a workaround. It's not pretty, but it's better than nothing at the moment. If I get time, I would like to learn more as to actually fix it. First of all, I grabbed the sdl_gfx.dll file from https://github.com/Vladar4/sdl2_nim/blob/master/LINKS.md

Then I dropped it in my artifacts folder with my SDL2.dll file. If you can't find it through searching, you could just update one of the functions in LibSDL2.jl like this to print it out.

This file was at: C:\Users\kyjor\.julia\packages\SimpleDirectMediaLayer\wjMsP\src\LibSDL2.jl for me

function SDL_CreateRenderer(window, index, flags)
    println(libsdl2)
    ccall((:SDL_CreateRenderer, libsdl2), Ptr{SDL_Renderer}, (Ptr{SDL_Window}, Cint, Uint32), window, index, flags)
end

this returned C:\Users\kyjor\.julia\artifacts\a3822540351cc2f773be931a83adc5c844eee6f2\bin\SDL2.dll for me.

So once you dropped in your dll, go to all of the sdl_gfx functions, and change them to look like this:

function SDL_initFramerate(manager)
    ccall((:SDL_initFramerate, replace(libsdl2, "SDL2" => "SDL2_gfx")), Cvoid, (Ptr{FPSmanager},), manager)
end

instead of just libsdl2 as a parameter, change it to replace(libsdl2, "SDL2" => "SDL2_gfx")). This will use the SDL_gfx.dll instead of the SDL2.dll for these calls. I've only tested this with the framerate functions so far, and they worked for me. I hope this helps anyone. Like I said, it's a hack, and hopefully I can try and contribute a real fix.

Noremac11800 commented 9 months ago

@Kyjor Wow, nice work! I swear I tried basically that exact hack a few weeks ago. I'll attempt your hack when I get some free time. Thanks for finding a fix. Something is better than nothing. :)

Kyjor commented 9 months ago

No problem! Like I said, I've only tried it with the framerate functions so far, so your results may vary. I'll probably be trying to work with the actual drawing functions real soon. So if there's any gotchas, I'll let you know

Noremac11800 commented 9 months ago

Alright, so a quick update. I followed through (more carefully this time!) with your steps, and I can corroborate your results with my own. The frame-rate functions work as intended, however, when trying some of the graphics functions (I tried pixelRGBA, hlineRGBA, and circleRGBA), they are not working. On the bright side however, I am no longer getting the original error I was getting months ago which read along the lines of: could not load symbol "some gfxPrimitive function name".

So as far as I can tell, the package now has access to the SDL2_gfx functions, but for some reason the graphics primitives are not drawing. Unfortunately, this issue is still way above my current skillset, so if anyone has some further insight into how to get the drawing functions to work, that would be much appreciated.

Kyjor commented 9 months ago

@Noremac11800 can you send me a MWE of your code? I can try and mess with it.

Kyjor commented 9 months ago

@Noremac11800 Here's an example: 😄 https://gist.github.com/Kyjor/c6d9b82245f83311f10a5e4e8a41ca59 I just modified the basic.jl example. This is what it looks like for me: image

Noremac11800 commented 9 months ago

Hi @Kyjor, sorry for the late reply I've been a bit busy. A MWE of my code is essentially identical to yours. I used the basic.jl example also.

I just tested out your code (making sure to add the necessary replace(libsdl2, "SDL2" => "SDL2_gfx") lines to make your graphics functions work) and my code runs without errors, however the actual graphics are not drawn still.

I believe the issue lies in the way the sdl_gfx library is communicating with SDL2. Let me explain. Because I am using MacOS and not Windows, when I followed your original fix I had to retrieve the sdl_gfx library from an alternative location. A .dll will not work so I had to either find or build the correct .dylib library for sdl_gfx. In my haste, my best fix was to install the library via Homebrew with:

brew install sdl2_gfx

I then located the two associated dylibs in my brew Cellar and manually moved them into the .julia/artifacts... directory, containing the LibSDL2.dylib libraries.

For reasons that I do not understand, I don't think I was supposed to do that... When I run your minimal example code I get the following output in my terminal:

Class SDLApplication is implemented in both /Users/cam/.julia/artifacts/8fd700de383504a22db30fc7e4193dc1b1ee471e/lib/libSDL2-2.0.0.dylib (0x1061527e8) and /opt/homebrew/Cellar/sdl2/2.28.5/lib/libSDL2-2.0.0.dylib (0x1544b88e0). One of the two will be used. Which one is undefined.

So I think your fix is working perfectly fine and this issue is close to being resolved. The problem appears to be on my end due to a lack of understanding around dylibs. So I am going to have to toy around with my setup a bit to see if I can get the libraries to look in the right locations for the code.

Out of curiosity, I may go and attempt this on my Arch desktop machine instead of my Mac because I may have more luck there. MacOS usually isn't my first choice when it comes to development.

I appreciate all of your effort though :)

Noremac11800 commented 9 months ago

AHA! Another update. I just tried out the same process on my Arch machine and it worked flawlessly!

So for anyone who wants to know the steps I took:

  1. Install SimpleDirectMediaLayer.jl via Julia's pkg manager
  2. Install libSDL2_gfx via:
    sudo pacman -S sdl2_gfx
  3. Determine the correct artifacts directory where SDL2 is located in your ~/.julia directory. Mine was located at ~/.julia/artifacts/8f20658b625a577cdc6b81980bbae941cb291139/lib/
  4. Navigate to /usr/lib/ and copy the libSDL2_gfx.so file into the artifacts directory
  5. Navigate to ~/.julia/packages/SimpleDirectMediaLayer/wjMsP/src/ and modify your desired SDL2_gfx functions according to @Kyjor's advice above.
  6. Use @Kyjor's MWE code basic.jl here and replace the function calls with your own.

As far as making a better, more permanent fix, that's a problem for later. But as an immediate hack, this fix works perfectly fine.

Nice work @Kyjor! Thanks for all the help.

Kyjor commented 9 months ago

No problem @Noremac11800 ! Good luck!

Kyjor commented 9 months ago

75