Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graphics #4

Open
jpcima opened this issue Nov 12, 2021 · 13 comments
Open

Graphics #4

jpcima opened this issue Nov 12, 2021 · 13 comments

Comments

@jpcima
Copy link
Owner

jpcima commented Nov 12, 2021

https://www.reaper.fm/sdk/js/gfx.php

Note (1): this appears to be the default font
https://int10h.org/oldschool-pc-fonts/fontlist/font?tandy1k-ii_200l

Note (2): gfx_showmenu is synchronous
this blocks @gfx from running, but not the entire host

@GavinRay97
Copy link

GavinRay97 commented Nov 19, 2021

Did you have a particular implementation plan here already?
Maybe myself or someone else in the community could help out.

EDIT: Nevermind, they map to this:
https://github.com/jpcima/ysfx/blob/8ef69f9d6bef85b1b7da7cfe66b9f777f536cf4c/thirdparty/WDL/source/WDL/eel2/eel_lice.h

I think the REAPER JSFX likely use SWELL, the WDL "Simple Windows Emulation Layer"
This is the foundational cross-platform GFX and windowing lib that REAPER itself is built with.

IE, for gfx.rect(), that might map to this:

https://github.com/justinfrankel/WDL/blob/master/WDL/swell/swell-gdi-generic.cpp#L279-L290

https://github.com/justinfrankel/WDL/blob/9bcb9595e4dd0a6f8fde3a944a564bfe1d36e702/WDL/swell/swell-gdi-lice.cpp#L739-L762

I am no expert though

For the JUCE example of using REAPER's embedded UI stuff, I had to figure out to draw the LICE bitmaps that REAPER hands to the render method into a JUCE component.

To do that is:
https://github.com/juce-framework/JUCE/blob/master/examples/Plugins/ReaperEmbeddedViewPluginDemo.h#L329-L384

void doPaint (reaper::REAPER_FXEMBED_IBitmap* bitmap)
    {
        if (bitmap == nullptr || drawInfo == nullptr || bitmap->getWidth() <= 0 || bitmap->getHeight() <= 0)
            return 0;

        Image img (juce::Image::PixelFormat::ARGB, bitmap->getWidth(), bitmap->getHeight(), true);
        Graphics g (img);

        Image::BitmapData imgData { img, Image::BitmapData::readOnly };
        const auto pixelsWidth = imgData.pixelStride * imgData.width;

        auto* px = bitmap->getBits();
        const auto rowSpan = bitmap->getRowSpan();
        const auto numRows = bitmap->getHeight();

        for (int y = 0; y < numRows; ++y)
            std::memcpy (px + (y * rowSpan), imgData.getLinePointer (y), (size_t) pixelsWidth);
    }

So maybe that eel_lice.h header can be re-used, and then a method like this used to draw it on the JUCE Editor component?
(REAPER_FXEMBED_IBitmap = LICE_IBitmap)

@jpcima
Copy link
Owner Author

jpcima commented Nov 19, 2021

Did you have a particular implementation plan here already?

Kind of yes, but it's not set in stone, there would be 2 ways to go at this problem.

  1. to import SWELL+Lice+eel_lice.h which implements all of gfx as software renderer
    There's a bit of practical difficulty make it build it though, not entirely as trivial as it sounds.

  2. to provide a library API which lets a user implement the entire graphics interface

only the method 2. would have the ability of accelerated rendering.
(decent candidates for JUCE's graphics contexts, which can render both to GL and raster)

@GavinRay97
Copy link

only the method 2. would have the ability of accelerated rendering.
(decent candidates for JUCE's graphics contexts, which can render both to GL and raster)

Probably better to do the second one, I've noticed you've also kept the core of it decoupled from JUCE which is nice given the flexibility of re-using it in other environments/context

@jpcima
Copy link
Owner Author

jpcima commented Nov 20, 2021

Probably better to do the second one, I've noticed you've also kept the core of it decoupled from JUCE which is nice given the flexibility of re-using it in other environments/context

It's a goal, given that this lib is not only for plugins but also for hosts, starting with Carla.

A thing about these graphics is they are modeled after Windows GDI software rendering.
I'd really like to get Lice in if that's possible. Some parts of Swell give problems
(eg. the windowing which pulls the Gdk dep and it's desired to avoid this)
It might get away with it, if linking it with a Swell subset which is restricted to the GDI code only.
That remains to verify.

@jpcima
Copy link
Owner Author

jpcima commented Nov 22, 2021

There is success so far with getting Lice into the master branch.
That means that drawing is going to be kept inside the library, which keeps the usage simple.

The library user should only provide the framebuffer of the window, and other information like mouse and key data, and Retina status.

@GavinRay97
Copy link

The library user should only provide the framebuffer of the window, and other information like mouse and key data, and Retina status.

What exactly is a framebuffer?

Is it something you can get from a window pointer/handle, like HWND on Windows or XID (now called Window I think) in X11 on Linux?

@jpcima
Copy link
Owner Author

jpcima commented Nov 23, 2021

The framebuffer is an image that keeps the pixel data in RAM memory.
The current master has it implemented, and shows how to use it together with a juce::Image.

This is checked working, which means the hardest work is done, next it will be about adding the graphics primitives. (which should be a copy-and-paste from eel_lice)

@GavinRay97
Copy link

The framebuffer is an image that keeps the pixel data in RAM memory. The current master has it implemented, and shows how to use it together with a juce::Image.

This is checked working, which means the hardest work is done, next it will be about adding the graphics primitives. (which should be a copy-and-paste from eel_lice)

We have liftoff! 🚀 Video clip below is incredible!
Build was done ~5 minutes ago:

X8dx0QVWC0.mp4
01T7F0Lenh.mp4

@jpcima
Copy link
Owner Author

jpcima commented Nov 24, 2021

Yes, I've added a few more right now but there still remains to do some major ones.
All I make so far is a tiny example, and not tried any actual plugins.
Any elaborate ones which are worth testing?

desc:000 gfx2

out_pin:out

@sample
spl=0.0;

@gfx 600 400
gfx_r=rand(1);
gfx_g=rand(1);
gfx_b=rand(1);

cx=rand(gfx_w);
cy=rand(gfx_h);
cr=rand(10)+5;
gfx_circle(cx, cy, cr, 1);

n=n+1;
(n<500)?(gfx_clear=-1.0):(gfx_clear=0.0;n=0);

@GavinRay97
Copy link

GavinRay97 commented Nov 24, 2021

Any elaborate ones which are worth testing?

@JoepVanlier ("Saike") sets the bar for JSFX development IMO, his plugins are probably the golden standard as far as unit testing:

Big repo of them here:

The ones under the Basics category would probably be good "first-goal" bars since they are more minimal in terms of UI than his other plugins:

There's also Geraint Luff's JSFX, which are fantastic:

@ghost
Copy link

ghost commented Nov 25, 2021

ReEQ is another one.
https://github.com/Justin-Johnson/ReJJ

@jpcima
Copy link
Owner Author

jpcima commented Nov 29, 2021

Graphics are mostly working now, needs just these few features such as cursor and popup.

@jpcima
Copy link
Owner Author

jpcima commented Dec 4, 2021

The status of gfx is supposed to be now implemented 100%.
The popup has needed a rewrite of gfx processing at plugin-side.
More precisely, the @gfx is allowed to block indefinitely (by gfx_showmenu), and so it can't happen on the main UI thread except by creating a modal loop; as a solution, @gfx has been moved into a background thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants