8 ms·
Minimal Cross-Platform Graphics
- panzerboiler 4y agoPerfect companion for this C graphics library: https://github.com/tsoding/olive.c https://github.com/tsoding/olive.c
- abainbridge 4y agoI used to use a timer to limit the frame rate to 60 Hz too. But on Windows, I found that DwmFlush() seems to act like WaitVSync(), so I've been using that in preference for years now. I think this is undocumented behaviour. I guess what it actually does is wait until the compositor is ready for another frame. To be able to call that function, I LoadLibrary("dwmapi.dll"), and then GetProcAddress(dwm, "DwmFlush").
- suby 4y agoWhy not just use VSync?
- sylware 4y agoIf I am not too much mistaken, because on some hardware (mobile), there is no vsync feedback. vsync feedback support has to be queried (look at vulkan API/wayland API). Usually it is called "presentation" something.
- abainbridge 4y agoHow would I do that? I think there is any such function in the Win32 API.
- formerly_proven 4y ago> Issues a flush call that blocks the caller until the next present, when all of the Microsoft DirectX surface updates that are currently outstanding have been made. DWM always runs with vsync so presents never happen more frequently than screen refreshes.
- Const-me 4y agoI think this needs much more complexity to be useful. For the rendering, ideally it needs GPU support. Input needs much more work, here's an overview for Windows: http://blog.ngedit.com/2005/06/13/whats-broken-in-the-wm_keydownwm_char-input-model/ http://blog.ngedit.com/2005/06/13/whats-broken-in-the-wm_key... Windows' Sleep() function has default resolution 15.6ms, that's not enough for realtime rendering, and relatively hard to fix, ideally need a modern OS and a waitable timer created with high resolution flag. Here's my attempt at making something similar, couple years ago: https://github.com/Const-me/Vrmac https://github.com/Const-me/Vrmac
- bob1029 4y ago> Windows' Sleep() function has default resolution 15.6ms, that's not enough for realtime rendering, and relatively hard to fix Very easy to fix. Call this at the start of your real-time process: https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod https://learn.microsoft.com/en-us/windows/win32/api/timeapi/... Use an argument of 1, and windows will come knocking at ~1Khz. This is extremely effective in my experience. Allows you to do some pretty crazy stuff on 1 thread.
- bitwize 4y agoNo direct access to the command buffers of the GPU? No matrix transform routines? No colorspaces besides RGB? Absolute non-starter.
- Const-me 4y ago> direct access to the command buffers of the GPU Impossible given the platform limitations at that time, on Linux that code works on top of GLES 3.1. I didn't want too many Windows-only features there. > No matrix transform routines? There's no need for that. That library is for C#, which includes these routines in the standard library of the language for many years now, since .NET core 1.0: https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix4x4 https://learn.microsoft.com/en-us/dotnet/api/system.numerics...
- 4y ago
- unwind 4y agoVery cool! This example I think needs editing: memset(f->buf, rgb, f->width*f->height*sizeoof(uint32_t)); it's described as a way to "fill the complete framebuffer with a solid colour", but 'rgb' is shown in the previous snipped to be 'uint32_t'. That is not how 'memset()' [1] works, it will only use the least significant 8 bits of the 'int'-typed value argument. So it would use whatever blue bits where in 'rgb', only. For clearing (all zero) it's usable, and then I would recommend writing it as: memset(f->buf, 0, f->width * f->height * sizeof *f->buf); this both fixes the typo ("sizeoof" sounds like a C lecturer being punched in the guts), and avoids duplicating the type and instead inferring it from the actual object, which is more DRY and a style I've been advocating for ... years. [1]: https://man7.org/linux/man-pages/man3/memset.3.html https://man7.org/linux/man-pages/man3/memset.3.html
- aa-jv 4y agoFine, but at least fix this bug: .. (sizeof *f->buf) .. Because otherwise thats one stray space char away from a bad day ..
- dahart 4y agoOr ... sizeof(*f->buf)? I’d forgotten that sizeof even allows dropping the parens, but isn’t that asking for trouble? “sizeof a <op> b” is sometimes parsed as “sizeof(a) <op> b” and sometimes as “sizeof(a <op> b) depending on the precedence of operator <op>. Is there any downside to always using parens and writing sizeof() like a function call?
- unwind 4y agoSure, many people like that style, I don't. But no, I don't think there are any downsides, but there is this notion that things should look like what they are, which is popular in C. With parens, I would suggest spaces to make it sizeof (*f->buf) that makes it look less like a function call in many styles.
- torstenvl 4y agoVery, very cool. Already played doom on it. Maybe I can get my nephew interested in playing with this!
- torstenvl 4y agoPro-tip: Doom is available on Steam for $5. Just in case you want to avoid the DMCA nastygram I got from my ISP this morning. *cringe*
- HexDecOctBin 4y agoIs there any similar tutorial for XCB? Most documentation only covers libx11, and trying to extrapolate libxcb usage from that is tricky at best and heisenbug-prone at worst.
- enriquto 4y agoThis is extremely useful, and the page is beautifully written. Some people write absurd electron behemoths, and then there's this jewel of elegance. Could this be compiled as an αpε? Such a thing would make many heads explode.
- abainbridge 4y agoI think the Xlib dependency would prevent compilation as an αpε. I put some effort into doing X11 from scratch (without Xlib or Xcb) to make this possible. Or at least, my aim was to be able to build with musl libc and generate a single executable that would run on many different Linuxes. https://github.com/abainbridge/deadfrog-lib/blob/master/src/df_window_x11.cpp https://github.com/abainbridge/deadfrog-lib/blob/master/src/.... It is janky though.
- 082349872349872 4y agoOne advantage of speaking X directly for small projects is that one can allocate fixed ids.
- csdvrx 4y agoSuper interesting! > It is janky though So what? It can be improved :) Would you like to try to make an APE out of it? It would then be not just different Linuxes, but also MacOS and Windows, a bit like https://x410.dev/ https://x410.dev/ or the free software vcxserv https://sourceforge.net/projects/vcxsrv/ https://sourceforge.net/projects/vcxsrv/ We have discord. You should join us! FWIW I'm currently working on a DNS server with nice extra features like Multicast for mDNS/Bonjour: it could be used to publish the X server DISPLAY and make it accessible via service-discovery
- bananaboy 4y agoVery nice! I like that it's a single header. I wrote something similar although it's not single header, doesn't do audio, and no X11 backend https://github.com/samizzo/pixie https://github.com/samizzo/pixie. I use mine as a backend for Windows ports of MS-DOS demos that I make.
- kefir 4y agoVery similar to minifb: https://github.com/emoon/minifb https://github.com/emoon/minifb, https://docs.rs/minifb/latest/minifb/ https://docs.rs/minifb/latest/minifb/, https://news.ycombinator.com/item?id=24172362 https://news.ycombinator.com/item?id=24172362
- DrNosferatu 4y ago"raylib" comes to mind, as it is a graphics library also inspired by the Borland BGI graphics library. - Anyone with experience in it / any possible synergies? [https://en.wikipedia.org/wiki/Raylib https://en.wikipedia.org/wiki/Raylib]
- brabel 4y agoWonderful. I really wanted something like this to do Graphic the "hard way", also the most fun way... I was trying to use Tcl-TK for that but this seems a lot lower level, perfect for what I wanted to do which is to write a small GUI toolkit for tiny apps.
- pavlov 4y agoWriting pixels into an RGBA framebuffer in main memory is fun, but it's also the easy and slow way to do graphics. The hard way these days is to figure out how to use a modern GPU to do the rendering you need. It's almost always several orders of magnitude faster.
- kragen 4y agowriting pixels into an rgba framebuffer in main memory is still plenty fast to do a full-screen animation at 60 hertz tho the benefit of the gpu is no longer (since maybe late last millennium) that you don't have the memory bandwidth to your framebuffer; it's that you can do a lot of computation per pixel typically the gpu advantage is only about an order of magnitude tho
- jacereda 4y agoNot so minimal, but if you need GPU rendering I wrote this: https://github.com/jacereda/glcv https://github.com/jacereda/glcv
- jacereda 4y agoAnd a couple of wrappers (probably bitrotten) https://github.com/search?q=user%3Ajacereda+glcv https://github.com/search?q=user%3Ajacereda+glcv
- detrites 4y agoA similar x-platform library called TiGR (Tiny GRaphics): https://github.com/erkkah/tigr https://github.com/erkkah/tigr Brief discussion: https://news.ycombinator.com/item?id=34310208 https://news.ycombinator.com/item?id=34310208
- imadr 4y agoI did something similar to load an image in windows/linux https://imadr.me/cross-platform-window-in-c/ https://imadr.me/cross-platform-window-in-c/
- ibebrett86 4y agoIf anyone is interested in getting into zig, we made a library that has similar goals (and can run on WASM in the browser): https://github.com/ibebrett/zigzag https://github.com/ibebrett/zigzag
- kragen 4y agosince everyone else is posting links to their similar libraries, i thought i'd post mine too, https://gitlab.com/kragen/bubbleos/-/tree/master/yeso https://gitlab.com/kragen/bubbleos/-/tree/master/yeso it's probably a bit more efficient than fenster on x-windows because it uses shared memory, and i think the programming interface is a little nicer (see the readme above for code examples) apps i've written in yeso include an adm-3a terminal emulator, a tetris game, a raytracer, an rpn calculator, a fractal explorer, and so on i haven't ported yeso to win32/64, macos, android, or the browser canvas yet, just x-windows, the linux framebuffer (partly), and a window system implemented in yeso called wercam it includes bindings for c, python (via cffi), and lua (via luajit's ffi), and presumably you could use it from zig or rust in the same way as fenster, but i haven't tried
- nuc1e0n 4y agoThis is very cool, but if I were doing such things I'd just use SDL (https://www.libsdl.org/ https://www.libsdl.org/)
- synergy20 4y agoBasically a bare-metal SDL2? well done.