AROS and 3D graphics



This article describes the history of current state of OpenGL compatible 3D graphics support in AROS.

Situation until middle of 2008

In open source world, the most known implementation of OpenGL compatible API is the Mesa3D library. This library is present and used on Linux as well as on BSD and is implemented so that porting it to different systems is as simple as possible. The first port of Mesa3D library to AROS was done by Nick Andrews. This port itself was based on the StormMesa port done for AmigaOS.

The port consisted of version 6.5 of Mesa3D library together with software driver written to work under AROS using the WritePixelArray graphics function to output rendering into AROS windows or screens. This first attempt brought basic OpenGL API to AROS, however it also represented serious drawbacks.

Firstly, while the x86 CPU clocked @ 1.6 GHz speeds, it was still not enough to get performance from software driver needed for even simplest games to be useful. Secondly, the port of Mesa3D library was available as statically linked library, meaning that any applications linked with this library, would have to be released again if newer version of Mesa3D became available. Due to these problems, the port of Mesa3D library was excluded from AROS nightly builds and was not available for 3rd party developers.

Port of Mesa 7.0

Around middle of 2008, I became interested in OpenGL 3D graphics under AROS. The motivation for this was quite innocent - I wanted to have a MMORPG game Eternal Lands available for AROS so that it is the first AmigaOS-like system to have MMORPG game. The was however one problem - Eternal Lands is a OpenGL game, and AROS did not have (out of the box) OpenGL support.

The first step I took was to revive the old Mesa3D codes available in AROS repository. After talking with Nick and several trial and error sessions I built the existing port only to learn that Eternal Lands client requires OpenGL functions that are not available in Mesa3D 6.5. I had to port the latest available Mesa3D - the 7.0 version.

Things were however not that easy. The internal interfaces changed and the AROS driver which worked with Mesa3D 6.5 was no longer working with 7.0 version. This prompted me to write first lines of code for Mesa under AROS. Taking Nick's driver as a basic I implemented a new driver that was compatible with the 7.0 version. I also changed the way that drawing was done, making it faster at the expense of greater memory usage. When all was compiling nicely and the gears were rotating, I returned to Eternal Lands client...

... only to learn that the performance is very far from acceptable. On a 1.6 GHz CPU I was getting 1-4 frames, while people on stronger CPU's had 15 frames maximum. At first I though there is some obvious bugs with the code, but the more I searched the more I came into a conclusion that there is nothing wrong. What takes so much time are thousands upon thousands of floating point operations - something that the GPU is designed to do without problems, and a FPU barely manages.

Eventually I released the Eternal Lands client for AROS and it was playable even on my machine, but due to simplifications and hacks done, the graphics quality was very poor. I put the Mesa3D 7.0 port on the shelf, again not making it available for 3rd party developers.

Mesa as a shared library

During the next year I was working on various aspects of AROS. Around July 2009 however, inspired by some of Nick's prototypes, I started thinking about making mesa available as a shared library. The reasoning for this was that while at the time we didn't have the hardware drivers to power OpenGL applications, we might get have gotten them in future. If we made Mesa3D available as a shared library, people could right now start working on 3D applications which will take advantage of "future to come" hardware drivers the moment they will become available.

The first thing was to update the Mesa3D port to the latest version - 7.5. Few changes were needed as soon a build of static link library of Mesa was available. At this point things became interesting.

Mesa3D uses a global variable to represent a current rendering context. This works on Linux and other systems, because the shared libraries subsystem on those systems automatically takes care of making copies of such global objects per each user of library. This is not the case in AROS - here the library itself must be implement in a way that it takes care of per client objects itself. This presented a major problem. Mesa3D expects to have a global rendering context, but this context needs to be then different for each client.

The solution came from Nick idea and Staff Verhaegen work on ABI V1. The solution was to have this global rendering context created per Mesa3D library client and then made available to the library in CPU register. The library itself would be forbidden from using this register for anything. This way the pointer to the context is always available. The global context variable is them made to alway point to the CPU register. Even if task switch happens during execution of code in Mesa3D library, the CPU register will be preserved and restored later. This is how ABI V1 will made available the library base to all functions.

The shared version of mesa.library was released in August 2009. From that moment things accelerated.

Gallium3D softpipe driver

Another thing suggested by Nick was the Gallium3D. This is a new 3D driver architecture was supposed to be extremely portable and system agnostic. Encouraged with the success of Mesa3D shared library I started looking at the softpipe driver of Gallium3D. The softpipe driver is a software driver, pretty much as the driver we had so far for AROS. I hoped however that since this is a new architecture, this driver might be faster that the one we were using. I started porting it taking the Xlib binding as an example for AROS. Pretty soon I ran into first obstacle.

The Gallium3D softpipe was using SSE commands to speed up the floating point calculations. The problem was however, that the linux-i386 version of AROS which I was using for majority of development was not supporting saving status of SSE registers. This was resulting in crash each time a SSE command was called. The good thing however was that the pc-i386 version of AROS was supporting this, so after a few days I ported this functionality over to linux-i386 version.

The remaining work did not cause major problems and end of September 2009, I had the softpipe driver working.

It was 2 times slower than the original AROS driver. Failure, however was not an option, so that left me with only one direction - try to port those "extremely portable and system agnostic" hardware drivers I heard so much about to AROS.

Gallium3D nouveau driver - Gallium3D Bounty

First decision was - which driver to port: Intel, nVidia or Radeon. Back at that time, I had no idea what so ever how graphics card works so either of them seems like a giant task. I selected nVidia as I always liked the nVidia cards... or maybe because I liked the name. What ever the motives were, from time perspective I see that they were the most portable hardware drivers - so ideal to start with.

The very first thing I learned was that the nVidia drivers in Mesa3D library do not talk directly to hardware. They need another layer - called (D)irect (R)endering (M)anager. While the drivers in Mesa3D compiled without problems, this drm code was really OS specific. The second decision I had to take was - port the drm or write it from scratch for AROS. Initially I wanted to write it from scratch basing on AROS nvidia.hidd, but the more I dived into the code, the more I understood that this is not an option. Firstly, the drm code contained initialization and low level support for all families of nVidia cards - something that we don't have right now in nvidia.hidd. Secondly, the drm code for nVidia is still work in progress with many bugs. Even if I had the time to do the initial rewrite, updating to new version of drm codes would be a nightmare. Thus I selected to port drm to AROS.

Since I was going to port the drm code to take advantage of future updates, I might as well make it easier for me to apply those updates. Thus, I decided to modify the original code as little as possible - instead implementing Linux kernel functions that this code required. Hopefully it turned out that there are very few functions that need to be implemented - at least fewer than I initially expected.

After this work was done, and tests on several nVidia cards performed, I released a first alpha release of mesa.library with hardware acceleration in January 2010. This release brought support to GeForce 5XXX, 6XXX and 7XXX cards. Within days from the release, several 3D games were ported, showing the potential of 3D acceleration under AROS even though that the drivers themselves were still alpha and were missing several features.

Adding AGP support

After the first release, I decided to take some time off the bounty and work on a that that picked my interest. During the three months of working on the nVidia drivers, I learned enough about low level stuff to feel comfortable with how the drivers work over the PCI. What I became interested in was how drivers work over AGP bus.

I took some time to study the Linux AGP codes. While the codes differ from one motherboard chip-set manufacturer to another, they had some common parts and generally looked quite easy - a lot easier than I though.

First I wanted to get AGP running on my SiS motherboard. Looking at the Linux codes, I implement native AROS support and within a week had my GeForce 6200 card running in AGP mode. With this success, I asked the AROS community to help me bring support to other motherboard chip-sets. While I could write code taking knowledge from Linux code, I could not tests it all on my computer. Thanks to the reply of community, support was added for VIA and some Intel chip-sets. I also took an important lesson about CPU caches which helped me hunt down some longstanding problem in the nVidia driver itself.

Finally the AGP support was added the mesa.library and released to AROS community in February 2009

Make it work, make it right...

The result released so far, while working and usable to AROS community, from software design standpoint were unacceptable. The hardware driver was physically linked into the mesa.library and what's worse - it operated alongside existing VESA driver, probably just by pure luck. The hardware driver had to be extracted into separate module following the HIDD driver system of AROS. The software rasterizer (softpipe) also had to be placed in another module and there had to be a logic provided when to use hardware driver and when to fall back to the software driver.

The natural splitting point between Mesa and Gallium3D driver is the Gallium3D interface. Mesa contains a state tracker which operates on the Gallium3D interface. This interface however is a collection of structures having pointers to functions - a pretty decent approach for modeling interfaces in C. This however was not in line with the OOP concept provided by HIDD system. Looking at the complexity of Gallium3D interface and the frequency of changes, I rejected the idea of rewriting it to HIDD system - this would simply by a nightmare to maintain across newer versions of Mesa and Gallium3D. Instead I went for a simple HIDD interface which only provided two major functions - create a new Gallium3D pipe_screen and blit pipe_surface to BitMap. Once Mesa or any other client of Gallium3D would acquire pipe_screen via HIDD system it would continue using it directly as Gallium3D was designed. This was a perfect balance between following AROS design and making the system easy for intaking new versions.

The 2D driver

While the hardware 3D driver was now a separate module it was still operating only under VESA mode. Pretty soon in development it became clear to me that I won't be able to join the nouveau 3D driver with AROS existing 2D nVidia driver. I knew I will have to provide a new nVidia driver based on DRM backbone that was used by nouveau. I though it might be a time consuming task - good thing I was wrong.

When making sure 3D driver will work, I ported a large subset of DRM code to AROS. When I started writing the 2D driver it turned out that I have almost all pieces in place. The part missing was the initialization of BIOS and support for reading data via I2C. These components were pretty easy to add and soon I had a first version of the 2D driver. It was extremely slow... as all operations were being done pixel by pixel - without any kind of acceleration. This actually is a feature of AROS 2D drivers system - the base class has all complex operations implemented using PutPixel/GetPixel methods - while this is slow, it makes possible creating a working driver in no time. I liked this feature very much.

Once I had the driver stabilized, I started replacing "per pixel" complex functions with their accelerate versions. I based their implementation on existing AROS driver as well as on the X86 EXA driver. These tasks went also pretty smooth and soon AROS community had an accelerated 2D driver for nVidia cards working on anything from old GeForce 1 up to even newest GTS250! Thank you nouveau team for your work, for making it open and for letting AROS us it.

After a few more days, the 3D driver had been integrated with the 2D driver finishing the work. What this change also enabled was the 3D support for GeForce 8XXX and above. The code was there, but it didn't want to work with the VESA. Making it work on the DRM-controlled card allowed the 3D acceleration to execute correctly.

The modules were ready on 30th May 2010.

Final state

AROS now has some new components which unleash the power of modern nVidia cards:

  • mesa.library - obviously the implementation of OpenGL API
  • gallium.library - a module that is used by Gallium3D clients to acquire the pipe_screen objects. Current used by mesa.library, but in future - who knows! Maybe OpenVG, OpenCL and Cairo?
  • nouveau.hidd - a combined 2D and 3D driver for nVidia cards
  • softpipe.hidd - a software rendering driver to be used on non nVidia system

While the work on the bounty is done, I plan to continue back-porting newer versions of these components. As long as their are developed by their respective teams, they will make their way into AROS.

Copyright © 2017 All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.
Designed by Business wordpress themes and freepoker.