xbmc/xbmc — pull request #2681 by theuni (2013-05-02 01:01:17+00:00)
Title: GUI Renderer abstraction and move to deferred rendering

This removes all render operations from guilib in favor of an abstracted scene-graph that receives batched render data for later render. When guilib has a texture/font ready for render, it packs up the data and adds it to the graph. At the end of each frame, that graph is evaluated by the renderer and drawn all in one go.

GL/GLES have been implemented, but directx is missing. Verified working on osx/linux/android. The scene-graph is very basic and intentionally non-robust. I think it wise to wait for a directx implementation before trying to settle on anything final.

Benefits:
- New renderers (not only dx/gl/gles) as our GUI is now completely independent of rendering code. Our current gl/gles renderers are implemented here, but directx is missing.

- We can be _MUCH_ smarter and more efficient with our rendering. We can look at an entire scene at once and decide to cull invisible objects or batch similar ones. Some of those things have been implemented here, but for the most part I tried to keep it similar to past behavior.

- Gives a big speedup when moving through the render loop, as we're now skipping lots of small graphics blocking operations.

- g_graphicsContext could be eliminated for the most part, since graphics operations are now asynchronous and threadsafe.

- Rendering could (and should) be moved to its own thread since all operations are now free of gui processing routines.

- Possible to include as an external api for plugins and binary add-ons so that they can use the renderer of their choice, and simply give us the results to display.

- Makes it much easier to decouple windowing from rendering, leading to the possibility of changing the renderer on the fly (gl/gles/glesv3).

- lots more :)

This does not re-implement our video renderers. I would like to have included those as well, but it's simply too much to knock out at once. Instead, the scene-graph was created in such a way that it can be rendered partially, multiple times. So for operations where we temporarily lose control of our renderer (video playback or visualizations for example), the flow looks like this:

- clear buffer
- run through the render loop, adding controls to the scene graph
- hit a render/video/fullscreen control
- render the current scene-graph
- let the video renderer do its thing
- finish the gui loop, adding controls to a fresh scene graph
- render the current scene-graph
- repeat

The result of the above is the same as our current implementation, it's just moved into different chunks. Playback/vis are confirmed working fine.

There are a few other changes in here as well including some shader optimizations and general rendering improvements. One of the big ones was making diffuse-color a per-texture rather than per-vertex feature, so that it can be sent once per texture.

Known issues:
- Missing directx support (the big one. hint ;)
- Somewhat broken dirty-region mode 1/2. Deferred rendering conflicts somewhat with the idea behind these modes.
- I'm sure I've missed a few render details

Implementing:
There is some basic doxy (see RenderSystem.h), but it remains to be seen if many changes are needed for directx. I've never touched it, so I'm not sure exactly how much it differs. In theory, it only requires adding upload/delete/render functions. For GL/GLES, it was basically just a c/p of the old texture rendering code, then a refactor to take advantage of the new functionality.
The renderer now takes on more responsibility for things that guilib used to handle, like clearing buffers, dirty-region handling, etc. I'll be very happy to help out with any porting questions.