adamdruppe / arsd

This is a collection of modules that I've released over the years. Most of them stand alone, or have just one or two dependencies in here, so you don't have to download this whole repo.
http://arsd-official.dpldocs.info/arsd.html
530 stars 125 forks source link

Add Pixmap Presenter module #409

Closed 0xEAB closed 6 months ago

0xEAB commented 6 months ago

Pixel Presenter is a high-level display library for one specific scenario: Blitting fully-rendered frames to the screen. This is useful for software-rendered applications. Think of old-skool games, emulators etc.

adamdruppe commented 6 months ago

OK, my first thought is I like it! This is something simpledisplay itself started life to do - present an image you edit as pixels and it just works. simpledisplay's automaticallyStretchIfPossible (or whatever i called it) also works for this... and you might consider actually using that. If opengl is enabled and you use that setting i believe it wills et the glViewport to scale and adjust events to be scaled to the original size too.

But the main thing I'll wanna see is a complete example in the docs / embedded unittests that i can copy/paste to play with it.

0xEAB commented 6 months ago

OK, my first thought is I like it!

nice, thx :grin:

automaticallyStretchIfPossible (or whatever i called it) also works for this...

The issues with automaticallyScaleIfPossible that I see are:

complete example in the docs

Is on the todo list.

adamdruppe commented 6 months ago

An amusing fact: if this is merged before anything else is added, this will be the 100th .d file in the repository! and the 70th dub subpackage.

adamdruppe commented 6 months ago

any time you wanna lift the draft status ill hit merge to play with it a lil, we can of course do whatever follow ups are needed

0xEAB commented 6 months ago

There are two things I’d like to get done before that:

adamdruppe commented 6 months ago

just running the samples, the advanced exmple from the docs isnot closing when i hit x. i don't know why. this might indicate event loop exhaustion, i see a redrawNow in a timer that might be to blame; that'd include a vsync block and if the next timer is run before the next event processor (which isn't supposed to happen but it wouldn't be the first time i got that wrong inside simpledisplay) it could dominate the process.

changing that to redrawSchedule keeps things working smoothly. but prolly throws off the timing.

i'll take a bit more of a look later. probably a platform difference as im on my linux box testing rn.

0xEAB commented 6 months ago

the advanced exmple from the docs isnot closing when i hit x.

Does increasing the interval in return LoopCtrl.redrawIn(…); “fix” it?

im on my linux box testing rn.

I’ve developed this thing on Linux actually.

adamdruppe commented 6 months ago

Yeah, 17, 18, 19 all unreliable, but 20 works. It is probably coming out of the loop right on the edge of a vsync and by the time that's over it is time for it to go right back in.

I'll see what I can do on the sdpy side, a timer is not supposed to starve the rest of the loop anyway.

0xEAB commented 6 months ago

right on the edge of a vsync

Sounds totally plausible. Disabling vsync (presenter.tinker.vsync = false;) “resolves” the responsiveness issue (that occurs with very low intervals) on my machine.

adamdruppe commented 6 months ago

I can alleviate it on the sdpy side by setting forceXPending = true on the branch that replies to timer handlers.

Perhaps I should just go ahead and always poll XPending on each loop.

What happens is as you wait for vsync, the glx libraries reads off the X connection, meaning it will no longer have data for epoll to pick up. But, glx doesn't actually process the events; it just buffers them for later. But without epoll being triggered, it doesn't know to check that buffer, so they just sit there as the timer triggers again and restarts the situation.

XPending can trigger unnecessary extra system calls... I think I actually wan XEventsQueued(QueuedAlready) in the poll loop. I don't like polling functions like that but that seems to be the best way.

adamdruppe commented 6 months ago

actually.... it already does QueuedAlready at the top of the loop.... and, timer functions might write something to the output buffer... so that needs to be flushed, which XPending does. An extra non-blocking read isn't really a big deal, really, the UI is more important. so let's just do it.

adamdruppe commented 6 months ago

(i need to port this whole thing over to my new arsd.core event loop and ive been procrastinating because there are a LOT of little details in here accumulated over the years that i don't want to break. but on the other hand it could use a simplification pass after learning the lessons of what is and isn't important. sigh.)

adamdruppe commented 6 months ago

so im not gonna do it yet, but a full set of operator overloads on the PixelBuffer might eb fun

framebuffer[x, y] = Color.white; // ez enough

framebuffer[x .. x+5, y .. y + 4] = Color.blue; // a lot of code needed to enable this but it is cool when it works

framebuffer[x .. x+5, y .. y + 4] = (Color c, int x, int y) { return Color.blue; }; // a fragment shader?? lol prolly getting not worth but c'mon wouldn't it be amazing

0xEAB commented 6 months ago

port this whole thing over to my new arsd.core event loop

I’d be great to have more control over the event loop and timing. I’m not sure whether the timer used by LoopCtrl is actually nice. It gets the job done, but that’s about it, I guess…