Make QSGRenderer public for custom use?
Is there any reason why the QSGRenderer belongs to the private parts of Qt? I'm sure I don't fully comprehend its internals, but wouldn't it be nice if it was possible to use the QSGRenderer class itself in a custom render loop (i.e. for creating OpenGL driven games)?
The advantage of this is that you have more control over the rendering process. As it is, the QQuickWindow/-View controls the frame rate, which isn't desirable, at least not in the application I'm developing.
Yes it is too bad. "A lot of people have been calling for that or something technically similar":http://qt-project.org/forums/viewthread/16465/, but for the time being the scenegraph is kept exclusive to QML in order to promote it. There has been a lot of attempts to justify that with JS being needed, but truth is C++11 has provided everything that is needed to render QML, JS and the underlying V8 engine entirely optional, so it is a little sad that it is still mandatory and C++ is not even an option for working with the scenegraph, especially since more than 2/3 of the visitors of this forum have voted for it.
At this point I honestly cannot tell if QML is a late attempt to make Qt yet another trendy fad or a tool to conform people to one's proprietary way of doing things, something that unfortunately is very popular with companies that develop programming frameworks. The idea behind QtQuick is a good one, but its implementation is not that elegant and flexible, despite the fact QML is now over 4 years old and in the second iteration of QtQuick. The design has many weaknesses and many awkward rough edges. As few as the basic QML components are, they are bloated and not very flexible, and there is really no way to escape that since custom QQuickItems inherit it. As ridiculous as it may be, BB has done a better job at providing QML components than Qt.
The same idea can be implemented entirely using C++ - bindings can be implemented via lambda functions, LLVM JIT can be used to make the compilation process non-existent, and performance will be much better without wasting memory and CPU cycles on the JS engine and relying on it for bindings. Declarative markup can still be used, but the interpretation phase can be completely optional, but what is more - UIs can also be compiled to lightning fast stack allocated objects. Logic and UI abstraction is perfectly attainable without QML.
I honestly hope that whoever horse with blinds on is responsible for the direction Qt is developed in comes to his senses and if not to the community at least listen to reason and stop holding 99% of the recent new features in Qt as a tool to promote QML.
Thanks for your elaborate response. Being able to fully control the QQuick rendering process would be amazing and, like you said, it's strange it wasn't designed like this when they introduced QQuick 2.0.
Making the QQuickWindow/QQuickView more up to standards compared to QWidget/QGLWidget would solve my issues for the moment though. Disabling the frame rate control, allowing fullscreen windowed (I couldn't get it to work without it going entirely fullscreen) and integrating vertical synchronization are my current needs. I am more surprised by the lack of this sort of features than full control over QQuick. It might be more appropriate to discuss these matters in a new topic.
Looking at the "core API":https://qt.gitorious.org/qt/qtdeclarative/trees/4a9dccc3f5ead9a7210025ff725873431ec42c0a/src/quick/scenegraph/coreapi of the scenegraph it is hardly rocket science. The classes are not all that complex, and there is even some comments in the cpp.
The QSGRenderer is an abstract class, the render() method is not implemented, the default implementation in QSGDefaultRenderer is not all that complex to modify, but once all this is done I myself am a little unclear on how to use it. Especially on its own, without the QML/JS/V8 stack.
There has been a lot of "do it yourself" going on, and I am all for it but the resources to do it are lacking, no examples, no documentation - those are still needed for people who haven't developed the scenegraph themselves. Despite the strong interest in the community, no Qt insider has stepped forward with providing what is missing so we can actually "do it ourselves"...
From the scarce "documentation" related to the scenegrapgh:
bq. The scene graph is closely tied to Qt Quick 2.0 and can not be used stand-alone.
At this point it is unclear what this sentence means exactly...
Doesn't the QSGRenderer render a QQmlContext, which in turn is managed by a QQmlEngine that compiles the scripts, instantiates (through an incubator) objects and updates them? To me, this sounds like a logical separation.
Being able to control the rendering would be extremely useful, I agree.
In QtQuick1.x you basically could do this (with some effort), but in QtQuick2.x it's not (as far as I'm aware) possible right now. I agree that this is suboptimal.
Note that this particular discussion is entirely separate to the requests from the community to make the QtQuick primitives' API available as public C++ API (which have been answered a thousand times: we don't want to make the API public as that entails binary and source compatibility guarantees, which we don't want to make).
But, utcenter, as an aside, some of the assumptions you make are incorrect, I think. Gunnar can correct me if I'm wrong about any of the following, but my opinion is:
"but for the time being the scenegraph is kept exclusive to QML in order to promote it"
A) In order to promote QML? No... the scenegraph was written specifically for QML and exists for that purpose. It's not being "kept exclusive" for any reason other than that if we make certain things public API, then we limit our ability to change the internals (drastically if needed) to better fulfil its requirements. And it's requirements are: be the best rendering possible for QML.
"has been a lot of attempts to justify that with JS being needed"
A) I don't think the justification was made from a technical perspective (need JS for rendering? of course not), but instead from a language point of view. The QML language specification says that ecmascript expressions are supported in bindings and signal handlers, and in dynamic function declarations. You're right that we don't require V8 etc - but that's a different and unrelated question.
Some of your other comments are antagonistic too. Seriously, you are right that (for example) being able to do AOTC of QML would be nice - but we can (theoretically) achieve that without exposing C++ API (and therefore binding us with requirements to guarantee SC and BC) simply by disallowing certain things (eval(), prototype modification, dynamic function addition/modification at runtime, etc) and then having a good enough JS engine / compile-time expression evaluator to implement it. And, big news, this is being worked on! That's what v4vm eventually hopes to achieve. Have you contributed code to it?
Furthermore, you seem to be claiming that the Qt Project is somehow deliberately "not doing enough work" on some things (like components) or something. This is simply false. The fact is that there are manpower / resource constraints. If you want to see improvements, write the code and contribute it via gerrit. But please remember that just because you want something, or think that it would be useful, doesn't mean that the Qt Project has to agree with you. We have module maintainers for a good reason.
Anyway, we're getting off-topic here. Yes, Peter, I agree it would be very nice. Maybe talk to the guys in #qt-graphics on freenode to see what might be possible in this particular area. It'd be great if a good solution for this issue could be made possible.
But wasn't the scenegraph also developed for Qt? Qt... the C++ framework? It is not like it is a common practice for Qt to develop APIs in C++ that are not possible to use from C++, at least until now...
Not to mention there is an ample difference between "written especially for" and "written exclusively for". Doing something for a specific reason doesn't imply it is also exclusive to it. Atomic research was conducted especially to make an atomic bomb and drop it on innocent civilians, but luckily today this is not the only application - we also have clean nuclear power.
But I happen to know a common practice companies surely love to resort to - develop great features using C++ but "accidentally" left out the public interface to use those with C++ and only make it possible though their own language. Which is effectively using the API to promote a proprietary language by means of providing it with exclusive neat features.
I highly doubt locking away functionality can be justified for the sake of binary compatibility - all it takes to preserve it is a simple guideline to follow - keep classes the size of an int, dynamically allocate private data - and that's about it...
I will be more more than willing to contribute, but the way things are right now keeps my hands tied. I sure would love if there were the resources I need to be able to implement my concept on top of the scenegraph. It is not like you need JS to resolve simple expressions, even without compilation to native a rudimentary VM machine would be much easier to implement than plugging in an entire JS engine. But what's the point of doing that when the scenegraph can't be used directly?
I never really got a straight a reasonable answer to the question "Why was the scenegraph implemented in a way that doesn't allow standalone use and why there is no information on how to do that?" - and without a straight answer, I am forced to speculate, as much as I hate. I don't see any good reason for this except for the sake of promoting QML - "If you like the features and performance, you have to use QML".
Lets face it - the scenegraph is probably the best and most significant upgrade Qt has seen this past few years. And it just so happens that this entire feature, implemented in C++, has no public API to use with C++ and is instead locked out from direct use, and the only way to utilize it is to settle for QML...
You, much like many other people, seem to be trying to make this about me in some attempt to discredit it, like it is some personal whim that makes no sense, but once again I encourage you to go ahead and check the poll result. That thread is not about being able to instantiate existing QML components from C++, it is about the need of a modern hardware accelerated graphics API for C++, something currently absent from Qt, not because it doesn't exist but because a deliberate decision was made not to allow it.
And that decision, believe it or not, is directly preventing contributions to Qt in this area. I myself have plenty of ideas, but if I have to implement my own scenegraph then why even bother using Qt and contributing my work to a framework that is forcing me to reinvent the wheel, because it doesn't want me to be able to use the already existing wheel in that framework?
And I don't think I am asking for much - even without a public API, a few examples how to use the scenegraph standalone through the private one will honestly suffice - how to put a scenegraph in a QWindow, create and attach a few example nodes in a simple example project without using any of the QML related classes. That's all!
I'm sorry that you don't agree. It wasn't implemented that way, because it wasn't even being considered at the time. A technology was being developed, and it was decided that the enablers and surrounding code should be written specifically with that particular use-case and that technology in mind. Which was done.
No, it wasn't "kept private" or whatever in order to promote QML. It was designed specifically for QML, and developed in the leanest manner possible specifically for QML. As far as I am aware (again, it's not my area, so Gunnar can correct me if I'm wrong, which I may well be), no "architectural" thought was given into how it would work with widgets or how the interfaces should be exposed for C++ specific use cases. Instead, it was designed specifically and entirely with QML in mind.
You're claiming some conspiracy to keep things away from C++, but what I'm saying is that as soon as you start thinking about how to get things to work for multiple paradigms, you 1) take longer to develop everything, 2) you are tempted to make compromises to hit both use cases. You can argue that in some cases, neither of those two things happens - and in some cases, you're right. But you cannot argue that it never happens. And thus, when Qt5 came around, the scene graph was designed with QML in mind, full stop.
You might not like the decision - and it's ok not to like it. It's ok to ask for certain decisions which were made in the past to be revisited and maybe even changed! Fine. But it's not ok to claim it's a some corporate conspiracy... seriously, that's just insulting.
Locking away functionality can be justified for the sake of binary compatibility, especially if you don't have the resources to spend on maintaining a more abstract interface across multiple paradigms.
As for me trying to discredit you... I apologise if I offended you. I just think that you are misinterpreting the reasons for the decisions made.
I agree that certain decisions made have been preventing contributions to Qt. Sure. And maybe some of those decisions need to be revisited, now that the business environment has changed. Great. But can we please do so in a constructive, rather than antagonistic, fashion? There are very good reasons not to expose QtQuick and other QML-internal classes as public C++ types. But maybe the scene graph rendering stuff is mature enough to be exposed, now - ok, let's have that discussion on the mailing list now, so that we could consider it for 5.2, perhaps.
As for your last statement - I actually agree - we need more examples and code about those things. I personally don't have the expertise in that area, but Gunnar has written many blogs about related topics in the past, so I know his technical writing skills are excellent. Maybe he could whip up a few examples of what you want, and add them to the documentation? Ask him about that on #qt-graphics on freenode.
It just sounds odd to do something like a scene graph and intend such a narrow scope of application for it. Especially when it has the potential for a lot more. A little like making a car that can only move south... That lack of robustness isn't typical, so pardon my frustration with it and the suspicions it arouses, intensified by knowing the usual practice for many companies who do that exactly for the sake of establishing their own programming languages.
As I said before, binary compatibility can easily be preserved by following a simple guideline, and if for some reason someone leaves its boundaries it will be his solution that suffers, since the whole idea is to use the scenegraph to implement new features, not change what is already provided and working.
You may not have the expertise, but you do sound a little more on the inside, plus you probably do have an IRC client unlike me, so it may be a better idea if you are kind enough to ask Gunnar yourself, quite frankly I agree that his materials are very well structured and informative, and there is definite interest on the subject. So it would be great if you get him to agree to write a few examples - they will be valuable and appreciated regardless whether they get into the doc or not.
Yeah, that's understandable. I'll ping Gunnar and see what he says, but I can't promise anything, obviously.
Thanks, you've been very helpful.
Interesting thread :)
I'll try to clarify as best I can.
The Scene Graph - With this I refer to the code in qtdeclarative.git src/quick/scenegraph/coreapi. It is the minimal basic functionality of the scene graph, which is all public save for the renderer itself. The primary purpose of this API is to package OpenGL datastructures in a way that we can make use of in the renderer. In addition to the stuff in coreapi, there is a bit of convenience API which is also public in scenegraph/util like colorize materials, basic texture and rectangle node types and stuff like that. It was always my intention that this should be all publically accessible API, the only thing I was a little bit worried about was the renderer as different hardware will require different rendering strategies. Some prefer to minimize state changes, some prefer few glDraw commands, some prefer front-to-back sorting, etc. We have an adaptation API to replace the renderer on a per-hardware basis and to make this open to any future needs, the QSGRenderer class is private.
Qt Quick Item implementations - With this I refer to the QObjects which are behind Qt Quick object types, like Rectangle. These are private API, only accessible through QML. Behind the scenes, these object types create scene graph implementations of their own. This has been debated to death elsewhere, so I'll avoid from sharing my own opinions :)
Scene Graph Item Implementation - Behind each graphical Qt Quick object type, there is usually a custom QSGGeometryNode and QSGMaterial implementation. For instance, behind the Text, TextInput, TextArea object types, we have a GlyphNode. This is also where the Image type's texture implementation lies. Depending on hardware and platform, these can be swapped out through the "scene graph backend API":http://qt-project.org/doc/qt-5.0/qtquick/qtquick-visualcanvas-scenegraph.html#scene-graph-backend. Again, to make sure all of these can be done in an optimal manner on a per hardware basis, we these are private so we can adapt them to any future needs. On the other hand, if somebody is OK with using private API, it would make sense if each of these were instanitable without any dependency on other QtQuick stuff. That would make it possible to create a stand alone renderer and use the distance-field glyph node in it, for instance. Sadly, this is not the case today. I do like the idea though, so I'll make an effort to not make it any worse and slowly move in that direction.
Render Loop - This is a piece of code tying it all together. The QQuickWindow, the QML object scene, the animation system and the scene graph and the rendering. This also contains logic that will stop rendering when the window is obscured, seamlessly release and reconstruct the OpenGL context when the window is backgrounded and brought back, etc. We have two versions of this, one multithreaded that does the rendering on a background thread which we try to use and a single-threaded one which is used when doing OpenGL outside the GUI thread has problems. This is mostly on ANGLE these days, but X11's nouveau is another candidate as we're getting reports of problems there also. This is closely tied to Qt Quick and does not make sense stand alone and will remain private API.
Part of the reason for not making it possible to use the scene graph stand alone has been that without the convenience of the QML stack on top, the Qt Quick Items, the animation system and the scene graph item implementations, the coreapi is not all that useful. As it was stated above in this thread, it is not black magic. It only wraps OpenGL commands up into a couple of datastructures, which help us render the type of UI's we want people to make with Qt Quick.
While writing this, I noticed that QSGContext had made an appearance in QSGRenderer which breaks that "coreapi" is usable stand alone. That is not how it should be, so I'm working on a fix for that. I'll try to get a blog or something out on how to use QSGRenderer stand alone. QSGRenderer and the scene graph item implementations will continue to stay private API, but it is rather stable private API, so if you want to use it, you can. If you find benefit in it, it should at least be possible.
This is good news, I just read your post in the mailing lists, after double-checking that it is not an April's fool I'd say I am glad there is work being done in this direction and will be waiting for some examples.