-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
please add commandline option to render design to image #11
Comments
This is a bit tricky to get right as it's highly OS dependent. I started on the code for doing this properly in the visitor branch (tests/cgalpngtest.cc), but so far it only works on Mac OS X. Help porting this to Linux&Windows would be welcome :) |
kintel: thx for your efforts, it would be really nice if it can be done... Maybe i can test something on Linux, but i don't feel like porting it myself, because i have no experiences with OpenGL (or whatever you use) and therefore no idea how to do it. I thought that it would be as simple as calling some OpenGL function to dump the bitmap from (hidden) window... |
I think that Linux version is most important because this feature will be usefull especially on Linux servers (like thingiverse.com which often fails to render .scad files properly right now...) |
" I thought that it would be as simple as calling some OpenGL function to dump the bitmap from (hidden) window..." I thought the same thing. But it is not so easy. In OpenGL, there are lots of ways to do offscreen rendering, but most of them don't work or are deprecated (Auxiliary Buffers, Pixmaps, PBuffers). The 'accepted' way is using a Framebuffer Object, but you need a working OpenGL Context to do that. How do you get an OpenGL Context? You normally would open a window, which we don't want to do. In Mac OSX, Marius was able to get a context without a window (i think) by using NSOpenGLContext and the NSOpenGLPFAPixelBuffer attribute. Linux doesn't have that. It has GLX and X11, and glXCreateContext. You have to worry about if you are on GLX 1.2 or 1.3, and whether your OpenGL driver supports the EXT version of the Framebuffer Object or the ARB version. Alot of this is not documented very well. As far as I can tell, these linux functions also require an X server to be up and running. There is a theoretical possibility to do things completely in software rendering with something called "OS Mesa" but that has it's own complications. (and some might say, what about the shell variable LBGL_ALWAYS_SOFTWARE =1 ? It doesn't always work) I could be wrong but it's what I have figured out so far. |
Oh, forgot to mention glXCreateNewContext is for GLX 1.3, and glXCreateContext is for GLX 1.2. Both require different setup-routines to be gone through. |
@donbright i am sure that i saw some kind of fake X server (xfb,xvfb,tightvnc which are ugly that you need another process to e running, but i guess it's not big problem if you really need it) or some way to redirect X connection to null for cases like this. but it's still not completely portable. I think that you can make some portable solution that will make the window flash shortly on the screen before you'll figure out how to do this. BTW isn't it possible to create hidden window? will this still need X connection? will it still initialize glx context? Can't you check how the glx context is created in routine for creating window? |
This seems to be working:
but i am not sure if xterm is really running on background or if it waits for some handshake/negotiation from xserver... |
Harvie thanks for the ideas, can you run OpenGL over netcat? The best I have been able to do so far (in my visitortests fork) is to create a GLXPixmap, and create a Context using that, sort of like Marius does in his Mac OSX work. I don't know if this will work with a 'fake' X server. It works on my machine but it won't work in a VMWARE linux session (openscad itself works fine in a VMWARE linux session). |
Just for another example of how non-trivial this is, here is an example of a bug in Mozilla, they are trying to do Offscreen OpenGL. It has 103 comments and spans 10 months, for one single bug. There are numerous duplicate bugs linked to as well. Basically, some implementations of a certain GLX setup function do not report failure, other than printing a "bad drawable" message to the screen, which it's hard for a program to detect at runtime (you generally don't read your own output buffers, if you did, youd have to then re-print them yourself, and deal with buffering issues yourself?). https://bugzilla.mozilla.org/show_bug.cgi?id=589546 It's not impossible, it's just slow going. |
it also seems to be hardware-dependent capability :-( can't we just switch opengl to "software" (CPU) rendering mode to simplify the things? I think that we do not need to render picture extremely fast as we don't need realtime rotation, etc.. he answer is "no, it's not". However, it is very widely supported on most modern cards and chips, so you really need to research your user base, find out more about what hardware they have, and write your code to target that hardware. |
Even with software rendering you have to open an OpenGL context into your software renderer, and there is no standard way to do that. OSMesa might work but it introduces yet-another-library dependency that you would have to specially-compile to get OpenSCAD running. Here are some examples of problems others have had with OSMESA: http://learningwebgl.com/blog/?p=2266 Note the 'underworld' project doesn't use OSMESA on its Mac port, even though theoretically it should be 'easier'. |
How about something like the following code? AFAIU, a PBuffer context is a hardware-accelerated context which enables us to create and render to e.g. FBOs without having to have visual pixels. #include <GL/gl.h> int main(void)
} |
Marius: I tried that on a VMWARE installed with Ubuntu 10 - it segfaults during the call to glXCreatePBuffer. IIRC there's even a document somewhere that says 'this might never work'. I think a solution might be to XCreateWindow and then never call XMapWindow, so it is "hidden". (I shoulda listened to Harvie at the top of this thread. ) then create the FBO off of that. But there is still the issue of GLX versions that are not compatible, for example Mesa on Ubuntu 10 inside VMWARE claims to be GLX 1.4 on glxinfo, but if you try to use the FBConfig VisualInfo setup functions like glXChooseFBConfig, (which were introduced in GLX 1.3), it doesn't work. You can verify this by apt-get source mesa-utils (the Mesa demos) and trying to run glxgears-fbconfigs and glxgears-pixmaps. Both break under Mesa shipped with Ubuntu 10 under VMWARE, while plain old glxgears (using GLX setup functions that existed in GLX 1.2) it works fine. But if you try to run a program using FRAMEBUFFER_EXT using GLX 1.2 setup functions, sometimes it doesnt work even though your glx driver says it supports FRAMEBUFFER_EXT (like on my machine). And sometimes it will complain with a "Application calling GLX 1.3 function "glxCreatePixmap" when GLX 1.3 is not supported! This is an application bug!" if you use the 1.3 functions (other things besides glxCreatePixmap can cause this). Also, sometimes the GLX creation functions don't return an error and don't return NULL like they theoretically should. I know some people say 'tell users to upgrade their drivers'. But Openscad (via QT's GL) works so damned well in so many places, I would hate to think to have an situation with an Openscad that doesn't work in "command line" mode but does work in full QT mode. |
My intuition tells me that the reason glXCreatePBuffer crashes is that that function in question isn't bound yet, and that you must first query if PBuffers are supported and use glxGetProcAddress() to bind the function before calling it. I'm too busy with other things to look into this atm., but if you play around a bit and point me to a git repos/branch with misc. failing attempst, I could investigate further. ...in a week or two that is. |
i have it working inside of VMWARE now with MESA and on my "real machine". I copied some ideas from glxgears, it uses XCreateWindow, avoids GLXCreatexxx, and does not Map the window, making it invisible. The FBO setup then proceeds as normal. https://github.com/donbright/openscad/blob/visitortests/tests/OffscreenContext.cc |
here is an experimental proof of concept of rendering without any X server, at all, using OSMESA. https://github.com/donbright/openscad/tree/headless i tested the 'cgalpngtest' on a few examples, after killing X and bringing up a console window. It worked without any X server at all. There are a lot of problems to work out. Using the OSMesa method, it might be impossible to have a single binary that can both be an ordinary interactive windowed program, and also have a 'command line option' to render to a file. The problem seems to be that once you link a binary to OSMESA, all your GL calls go to OSMESA, not to the graphics card OpenGL driver. This is according to bjacques page at gnashdev : http://www.gnashdev.org/?q=node/46 So, what is the solution? Do you have two binaries, one called openscad, the other called openscad-headless, and put them in the same distribution? What about windows, where openscad is statically linked? Doesnt that double the size of your distribution? What if you had three binaries? Openscad-headless, openscad-window, and openscad, with the latter being just a frontend to the other two? Again, what about Windows? Am I wrong about a binary being unable to switch back and forth from OSMESA rendering to hardware rendering? Also, what do the command line options look like? openscad --headless --cgal sphere.scad --output sphere.png ?????? Anyways. Its possible. Im not going to pursue it further until i can finish the Regression Tests thing. (porting to Windows, which i have done, but i dont have a Windows machine that has FRAMEBUFFER extensions on its OpenGL card to test it on) |
@donbright nice :-) actually... my initial thought was the classical unix-way (have backend headless binary and frontend windowed binary that will use it to do all the work), but i guess right now it's bit problematic (in means of performance) to make realtime rendering (and eg.: rotating) this way (if backend can't do direct rendering to screen). |
Theoretically i guess you could dynamically graphics drivers, for headless mode it does dlload() for OSMESA, and for GUI mode, it does dlload() for GLX, ordinary Mesa + OpenGL drivers. Now, you still have to link-in QT to do this (and i dont think you can dynamically load QT?), which means it will also link in some X11 drivers. Does linking QT also link in OpenGL drivers? i dont know. |
How about to have multiple dynamically linkable (OpenGL API compatible) libraries that we'll be able to select using comandline argument (and possibly using GUI too), where some of features will be dependent on library that you will choose? |
Sorry if i was misleading, i forgot to mention that dynamic loading all of that stuff is highly non-trivial. SDL loads X11 dynamically, and some games load GL dynamically, but i dont know if anything does all that and also interacts with QT + QT-GL at the same time - im guessing its practically impossible. It would be vastly, vastly easier to just have two different worker-binaries, and a third wrapper-binary that just forks off the appropriate worker-binary and runs it. But i dont know if thats appropriate for this project. More questions: do users want OpenCSG rendering from commandline, or just CGAL rendering? Does OpenCSG even work in OSMESA? Would it be OK to have two separate distributions, one headless and one GUI, or is it better to have one fat download with both versions included? What do you do about the inevitable incompatabilities between OSMESA and people's hardware? i.e. they look at something in their QT-openscad gui, then they render it from a headless commandline in OSMESA, and it winds up looking different.. how do you handle that issue? Would it be easier to just tell people they have to have a windowing system up-and-running to use openscad, even in the 'dump to file' mode on a server, and forget about OSMESA alltogether? What about Xvfb, does it even work with OpenGL and OpenCSG? What do users want, what would they prefer? |
On Oct 13, 2011, at 03:39 AM, donbright wrote:
For the test framework, I'd like to see both. -Marius |
Ok... here is another method. It works using a 'virtual' X server called Xvfb. export DISPLAY=:2 This still requires X libraries to be installed, but you don't have to have a running X server, monitor, etc. It can all be done through a terminal. I have used it to run 'make test' on a box that I only had shell access to. |
although i should mention that parallell running of the tests (ctest -j) causes Xvfb to segfault. perhaps each test could spawn it's own Xvfb?...but something tells me osmesa is a 'cleaner' way to go. |
if anyone is reading this in future, its nice to know that if you use Xvnc instead of Xvfb, it doesnt crash so much. |
And what about making framework for multiple CGAL rendering backends (other than OpenGL) implemented as plugins? Is it possible? @donbright have you tried it like this? xvfb-run cgalpngtest sphere.scad out.png |
thanks for the tip about xvfb-run , someone should add that to the documentation. |
my patch above will enable png's to be rendered from the command line using the CGAL renderer. please see the pull request for more info. thank you on headless machines, for some reason xvfb-run does not work. you have to run Xvfb then set your DISPLAY env. variable like you would with any other X program running on a headless server. |
Testing that on my Debian7 VM, I found I still need the "GALLIUM_DRIVER=softpipe" as at least the llvm driver version used there produces horrible render errors in some cases (e.g. example006.scad). |
@rewolff im confused.... is this machine you are on using some kind of proprietary GL driver? as far as i know, all OpenGL on linux, hardware accellerated or not, goes through Mesa, unless there is some proprietary driver involved. not sure why you have to create a symlink to libGL.so .... i would consider that a bug in the build scripts that we should be able to fix somehow..... but i dont really understand what is going on. .. |
The machine has an NVIDIA card. I'm not sure what driver it uses. Could be the proprietary one. |
thanks for those details.... I googled a bit and found some folks with similar issues...
http://forums.fedoraforum.org/showthread.php?t=284088
ubuntuforums.org/archive/index.php/t-1822396.html Needs some more research to be sure i guess. |
Excuse me, but why was this closed? I can't see any resolution. |
This was closed 4 years ago, I guess the bitmap export was implemented at that time. The feature itself is extensively used in the test framework for years now and documented in the manual, so what's wrong with closing it? If there's some additional feature request, I'd suggest to create a new issue. |
They are deliberate references to this issue. Each pull request and issue is automatically given a number by GitHub and you can reference them in comments with # as shorthand for the full URL. |
@t-paul but it still can't be run without X server... |
What gives you that impression? It works fine for me without an X server. |
|
Well, that's what's commonly called complete requirements, I guess :-). @nophead is normally running on Windows I think and there is indeed no X-Server needed. So the topic is platform specific and also as discussed above not simple to solve for the Linux platform (not sure about macOS and if anyone cares for that). Still the image export feature does exist, works on all platforms and is used by a number of people on Linux servers. I think it would be nice to remove the need for Xvfb or Xvnc for headless operation but that should go into another ticket and may take a while as it probably needs quite some changes in the display code. |
This might solve the issue in the future: https://www.phoronix.com/scan.php?page=news_item&px=Virtual-KMS-VKMS-Linux-4.19 |
OpenSCAD uses OpenGL to render images. To get OpenGL to render you need a "GL Context" Inside the GUI it uses QT toolkit's OpenGL widget to get a GL context. You do not need a physical GPU to make a GL Context. On linux/bsd the GLX calls are made using a library called libopengl.so, and you set the environment variable LIBGL_ALWAYS_SOFTWARE=1 you can force it into 'software rendering', where it basically does what a GPU does, but on a normal CPU instead. If you do have a GPU, then opengl.so will talk to the driver for your GPU. Now, drivers on linux are kind of a nightmare because, unlike most hardware in linux, there are two kinds of drivers in linux for GPU/vidcards. There's open source driver, then there's proprietary driver. You can get open source driver for AMD, but also Proprietary if you want. Intel has open source drivers - alot of them are crap because they crash (google i950 or i915 crash sometime). But they are open source. They all go into the Mesa project. But Nvidia. Nvidia. People think Linux Torvalds is a mean person for flipping off Nvidia in public and using curse words. Well, I agree.... its a bit uncalled for. however. Nvidia doesnt ship open source drivers for linux. They ship binary blobs in packages that try to overlay the linux distro with their own files. As you can imagine, things get bungled up alot, with file naming conventions, automatic updates of the OS, etc etc etc etc. On top of this, Nvidia's proprietary drivers are not actually drivers. Nvidias drivers are actually massive patch/shim jobs for buggy games coming out of sweatshops where they intimidate people to work 100 hours a week in permanent "death march" programming sessions. Nvidia ships what are essentially game updates out, but they call them drivers. It is just depressing. But the other point of this paragraph is that.... if it doesnt work on Nvidia drivers, its going to most of the time be a packaging issue, an installation issue, etc. Its not something isolated to one program like OpenSCAD. But anyways. All of that, software or hardware rendering, open source or proprietary driver, MESA or not, on linux/bsd, that is still using GLX to get an OpenGL Context, which still needs X11. Now, there is a theoretical possibility to get a GL Context without X, that of something called Offscreen Mesa, which is a version of the Mesa GL library, that can render GL calls without X. Unfortunately, Offscreen Mesa has always been a little bit obscure, a bit unintegrated properly into distributions, for example. By default Mesa does not build the Offscreen Mesa version of itself. You have to rebuild the entire Mesa package to make it work. But it gets a bit confused about the naming of the libraries and such. Its not easy. Here is the other thing about OpenGL. OpenGL programs really really depend on a library called GLEW. GLEW has issues with Offscreen Mesa as well. I have experimented with specially modifying and re-buidling GLEW and Offscreen Mesa to be able to render in OpenSCAD in command line without X. I had it working actually. There was someone who very nicely gave me a login account on an old Sun Sparc machine where i played with this. The problem is that making an experimental working build of openscad, based on highly modified GLEW and Offscreen Mesa, that renders without X is a whole different ballgame than working with several different projects to upstream some weird bizarre set of patches for something that almost nobody cares about. I'm not going to be able to persuade GLEW to re-do it's entire build system, nor Mesa to re-do theirs. for a tiny use case like this. There are other ways to get a GL context without GLX on linux/bsd... but ... they require you to use 'newer' style OpenGL. OpenSCAD's OpenGL is actually largely from CGAL and OpenCSG, and they are both really old. Really old. Lastly, OpenGL itself is dying, as Apple has stopped updating/supporting (which means they will likely remove eventually), and the industry is moving to Vulkan. You cannot 'port from OpenGL to Vulkan', you have to write thousands of lines of code to replace OpenGL functions, and then port on top of that, because Vulkan doesnt provide high level operations like OpenGL did. That's probably the only way to survive long term. (Or hope someone writes an 'Old Opengl on top of Vulkan' library). @Harvie VirtualKMS might be helpful, but it is very vague in that phoronix link about what its relationship to OpenGL, or even Vulkan, will be. If it can provide a GL Context without X, then it would be nice. I'm doubting it tho. |
@donbright does that work on Windows? I'm doing RDP remote desktop and OpenGL is intermittently working. |
@donbright can't find the article, but i've read that VKMS is exactly for this. To provide virtual display on headless servers including GPU acceleration. It's made to enable multiple containers/VMs to use GPU. |
@MichaelAtOz someone, somewhere, a long time ago, posted how to copy Mesa's version of opengl32.dll into the same directory as OpenSCAD, and IIRC, it did allow the enabling of software rendering on Windows (which would be detectably by looking into openscad help/lib info). It was kind of one of those things, since hardly anybody uses it, its not very polished. I have experimented it on a few windows boxes but i think it was hit and miss. (Mesa can use some weird assembly language optimization that is invalid on some CPUs.) |
Just for the record, this might be usefull: VirGL virtual OpenGL renderer, which allows virtual machines without GPU to run software dependent on opengl acceleration. |
as root
Debian 8, Debian 9, Debian 10 Tested. |
@unique1984 But will this work on VM without proper opengl HW? |
As far as i tried, virtualbox headless and digitalocean headless machines gave me something. VirtualBox Debian 10 & With my OpenScadPhpConnector DigitalOcean Console (ssh without -X) Last one is OpenScad's GUI on my Notebook |
I think it would be usefull to have commandline option that will allow us to non-interactively render scad design to some bitmap image file (also sending image to stdout can be usefull in some cases). note that there should be some way to define angle of view (like ctrl+[0-9] does or exact angle).
THX ;-)
The text was updated successfully, but these errors were encountered: