head 1.1; access; symbols libdrm-1_0_4:1.1; locks; strict; comment @# @; 1.1 date 2003.06.25.14.40.07; author jrfonseca; state Exp; branches; next ; desc @@ 1.1 log @Switch the source format to DocBook XML. @ text @ DRI Architecture Direct Rendering Module (DRM) What is the DRM? This is a kernel module that gives direct hardware access to &DRI; clients. This module deals with &DMA;, &AGP; memory management, resource locking, and secure hardware access. In order to support multiple, simultaneous 3D applications the 3D graphics hardware must be treated as a shared resource. Locking is required to provide mutual exclusion. &DMA; transfers and the &AGP; interface are used to send buffers of graphics commands to the hardware. Finally, there must be security to prevent out-of-control clients from crashing the hardware. Where does the DRM resides? Since internal Linux kernel interfaces and data structures may be changed at any time, &DRI; kernel modules must be specially compiled for a particular kernel version. The &DRI; kernel modules reside in the /lib/modules/.../kernel/drivers/char/drm directory. Normally, the X server automatically loads whatever &DRI; kernel modules are needed. For each 3D hardware driver there is a kernel module. &DRI; kernel modules are named device.o where device is a name such as tdfx, mga, r128, etc. The source code resides in xc/programs/Xserver/hw/xfree86/os-support/linux/drm/ . In what way does the DRM support the DRI? The &DRM; supports the &DRI; in three major ways: The &DRM; provides synchronized access to the graphics hardware. The direct rendering system has multiple entities (i.e., the X server, multiple direct-rendering clients, and the kernel) competing for direct access to the graphics hardware. Hardware that is currently available for PC-class machines will lock up if more than one entity is accessing the hardware (e.g., if two clients intermingle requests in the command &FIFO; or (on some hardware) if one client reads the framebuffer while another writes the command &FIFO;). The &DRM; provides a single per-device hardware lock to synchronize access to the hardware. The hardware lock may be required when the X server performs 2D rendering, when a direct-rendering client is performing a software fallback that must read or write the frame buffer, or when the kernel is dispatching &DMA; buffers. This hardware lock may not be required for all hardware (e.g., high-end hardware may be able to intermingle command requests from multiple clients) or for all implementations (e.g., one that uses a page fault mechanism instead of an explicit lock). In the later case, the &DRM; would be extended to provide support for this mechanism. For more details on the hardware lock requirements and a discussion of the performance implications and implementation details, please see FOM99. The &DRM; enforces the &DRI; security policy for access to the graphics hardware. The X server, running as root, usually obtains access to the frame buffer and &MMIO; regions on the graphics hardware by mapping these regions using /dev/mem. The direct-rendering clients, however, do not run as root, but still require similar mappings. Like /dev/mem, the &DRM; device interface allows clients to create these mappings, but with the following restrictions: The client may only map regions if it has a current connection to the X server. This forces direct-rendering clients to obey the normal X server security policy (e.g., using xauth). The client may only map regions if it can open /dev/drm?, which is only accessible by root and by a group specified in the XF86Config file (a file that only root can edit). This allows the system administrator to restrict direct rendering access to a group of trusted users. The client may only map regions that the X server allows to be mapped. The X server may also restrict those mappings to be read-only. This allows regions with security implications (e.g., those containing registers that can start DMA) to be restricted. The &DRM; provides a generic &DMA; engine. Most modern PC-class graphics hardware provides for &DMA; access to the command &FIFO;. Often, &DMA; access has been optimized so that it provides significantly better throughput than does &MMIO; access. For these cards, the &DRM; provides a &DMA; engine with the following features: The X server can specify multiple pools of different sized buffers which are allocated and locked down. The direct-rendering client maps these buffers into its virtual address space, using the &DRM; &API;. The direct-rendering client reserves some of these buffers from the &DRM;, fills the buffers with commands, and requests that the &DRM; send the buffers to the graphics hardware. Small buffers are used to ensure that the X server can get the lock between buffer dispatches, thereby providing X server interactivity. Typical 40MB/s PCI transfer rates may require 10000 4kB buffer dispatches per second. The &DRM; manages a queue of &DMA; buffers for each OpenGL GLXContext, and detects when a GLXContext switch is necessary. Hooks are provided so that a device-specific driver can perform the GLXContext switch in kernel-space, and a callback to the X server is provided when a device-specific driver is not available (for the SI, the callback mechanism is used because it provides an example of the most generic method for GLXContext switching). The &DRM; also performs simple scheduling of &DMA; buffer requests to prevent GLXContext thrashing. When a &DMA; is swapped a significant amount of data must be read from and/or written to the graphics device (between 4kB and 64kB for typical hardware). The &DMA; engine is generic in the sense that the X server provides information at run-time on how to perform &DMA; operations for the specific hardware installed on the machine. The X server does all of the hardware detection and setup. This allows easy bootstrapping for new graphics hardware under the &DRI;, while providing for later performance and capability enhancements through the use of a device-specific kernel driver. Is it possible to make an DRI driver without a DRM driver in a piece of hardware whereby we do all accelerations in PIO mode? The kernel provides three main things: the ability to wait on a contended lock (the waiting process is put to sleep), and to free the lock of a dead process; the ability to mmap areas of memory that non-root processes can't usually map; the ability to handle hardware interruptions and a &DMA; queue. All of these are hard to do outside the kernel, but they aren't required components of a &DRM; driver. For example, the tdfx driver doesn't use hardware interrupts at all — it is one of the simplest &DRM; drivers, and would be a good model for the hardware you are thinking about (in it's current form, it is quite generic). &DRI; was designed with a very wide range of hardware in mind, ranging from very low-end PC graphics cards through very high-end SGI-like hardware (which may not even need the lock). The &DRI; is an infrastructure or framework that is very flexible — most of the example drivers we have use hardware interrupts, but that isn't a requirement. Has the DRM driver support for or loading sub-drivers? Although the Faith99 states that the &DRM; driver has support for loading sub-drivers by calling drmCreateSub, Linus didn't like that approach. He wanted all drivers to be independent, so it went away. XFree86 DRI Aware DDX Driver What is the DDX Driver? For each type of graphics card there is an XFree86 2D (or DDX) driver which does initialization, manages the display and performs 2D rendering. XFree86 4.0 introduced a new device driver interface called XAA which should allow XFree86 drivers to be backward compatible with future versions of the Xserver. Each 2D driver has a bit of code to bootstrap the 3D/&DRI; features. Where does the DDX driver resides? The XFree86 drivers usually reside in the /usr/X11R6/lib/modules/drivers/ directory with names of the form *_drv.o. The XFree86 drivers source code resides in xc/programs/Xserver/hw/xfree86/drivers/ usually in a file *_dri.[ch]. DRI Extension What does the XFree86 DRI extension? The XFree86-DRI X server extension is basically used for communication between the other &DRI; components (the X server, the kernel module, libGL.so and the 3D &DRI; drivers). The XFree86-DRI module maintains DRI-specific data structures related to screens, windows, and rendering contexts. When the user moves a window, for example, the other &DRI; components need to be informed so that rendering appears in the right place. Where does the XFree86 DRI extension resides? The &DRI; extension module usually resides at /usr/X11R6/lib/modules/extensions/libdri.a. The &DRI; extension source code resides at xc/programs/Xserver/GL/dri/ . GLX Extension What does the XFree86 GLX extension? The &GLX; extension to the X server handles the server-side tasks of the &GLX; protocol. This involves setup of &GLX;-enhanced visuals, &GLX; context creation, context binding and context destruction. When using indirect rendering, the &GLX; extension decodes &GLX; command packets and dispatches them to the core rendering engine. Where does the XFree86 GLX resides? The &GLX; extension module usually resides at /usr/X11R6/lib/modules/extensions/libglx.a. The &GLX; extension source code resides at xc/programs/Xserver/GL/glx/ . GLcore Extension What does the GLcore extension? The GLcore module takes care of rendering for indirect or non-local clients. Currently, Mesa is used as a software renderer. In the future, indirect rendering will also be hardware accelerated. Where does the GLcore extension resides? The GLcore extension module usually resides at /usr/X11R6/lib/modules/extensions/libGLcore.a. The GLcore extension source code resides at xc/programs/Xserver/GL/mesa/src/ . If I run a GLX enabled OpenGL program on a remote system with the display set back to my machine, will the X server itself render the GLX requests through &DRI;? The X server will render the requests but not through the &DRI;. The rendering will be software only. Having the X server spawn a &DRI; client to process the requests is on the TODO list. What's the re a difference between local clients and remote clients? There is no difference as far as the client is concerned. The only difference is speed. The difference between direct and indirect rendering is that the former can't take place over the network. The &DRI; currently concentrates on the direct rendering case. The application still gets a fully functional OpenGL implementation which is all that's required by the specification. The fact is that the implementation is entirely in software, but that's completely legal. In fact, all implementations fall back to software when they can't handle the request in hardware. It's just that in this case — the implementation can't handle anything in hardware. Most people don't run &GLX; applications remotely, and/because most applications run very poorly when run remotely. It's not really the applications fault, OpenGL pushes around a lot of data. Therefore there hasn't been a lot of interest in hardware accelerated remote rendering and there's plenty to do local rendering. It is on the TODO list but at a low priority. The solution is actually fairly straight forward. When the X server gets a remote client, it forks off a small application that just reads &GLX; packets and then remakes the same OpenGL calls. This new application is then just a standard direct rendering client and the problem reduces to one already solved. Is there a difference between using indirect DRI rendering (e.g., with <envar>LIBGL_ALWAYS_INDIRECT</envar>) and just linking against the Mesa library? Yes. &DRI; libGL used in in indirect mode sends &GLX; protocol messages to the X server which are executed by the GLcore renderer. Stand-alone Mesa's non-&GLX;. It effectively translates OpenGL calls into Xlib calls. The GLcore renderer is based on Mesa. At this time the GLcore renderer can not take advantage of hardware acceleration. DRI without X Can DRI run without X? The first question you have to ask is whether you really should throw out X11. X11 does event handling, multiple windows, etc. It can also be made quite light weight. It's running in 600k on an IPAQ. If you decide you do need to throw out X, then you have to ask yourself if the DRI is the right solution for your problem. The DRI handles multiple 3D clients accessing hardware at the same time, sharing the same screen, in a robust and secure manner. If you don't need those properties the DRI isn't necessarily the right solution for you. If you get to this point, then it would be theoretically possible to remove the DRI from X11 and have it run without X11. There's no code to support that at this point, so it would require some significant work to do that. What would be the advantages of a non-X version of DRI? The main reasons one would be interested in a non-X version of DRI Pros Cons Eliminate any performance bottlenecks the XServer may be causing. Since we are 3D only, any extraneous locking/unlocking, periodic refreshes of the (hidden) 2D portion of the display, etc., will cause unexpected slowdowns. If the X server never does any drawing then the overhead is minimal. Locking is done around Glide operations. A lock check is a single Check And Set (CAS) instruction. Assuming your 3D window covers the X root, then there are no 2D portions to redisplay. Eliminate wasted system memory requirements. Yes, there will be some resources from the X server, but I think not much. Eliminate on-card font/pixmap/surface/etc caches that just waste memory. If you don't use them they aren't taking any resources. Right now, there is a small pixmap cache that's statically added to 2D. Removing that is a trivial code change. Making it dynamic (3D steals it away from 2D) is not too tough and a better solution than any static allocation. Eliminate the need for extra peripherals, such as mice. Allowing operations without a mouse should be trivial if it isn't a configuration option already. Reduction in the amount of software necessary to install/maintain on a customer's system. Certainly none of my customers would have been able to install XFree 4.0 on their own. XFree 4.0 installs with appropriate packaging are trivial. What you're saying is that no one has done the packaging work for you, and that's correct. If you create your own stripped DRI version you'll be in for a lot more packaging work on your own. The impact of the Xserver is on the 3D graphics pipeline is very little. Essentially none in the 3D pipeline. Some resources, but I think not much. Realize the CAS is in the driver, so you're looking at creating a custom version of that as well. I think effort spent avoiding the CAS, creating your own window system binding for GL, and moving the DRI functionality out of the X server would be much better spent optimizing Mesa and the driver instead. You have to focus resources where they provide the biggest payoff. I would like to make a X11 free access to 3d... Take a look to the embedded-1-branch in Mesa CVS repository. It's an project to get the DRI running directly on a console with the Radeon. If all you want is one window and only running OpenGL then this makes sense. Another option is to make the DRI work with TinyX. TinyX runs in 600k and gives you all of X. It should be a fairly straight forward project. As soon as you want more than one window, it makes a lot of sense to use the X framework that already exists. libGL What is libGL? OpenGL-based programs must link with the libGL library. libGL implements the GLX interface as well as the main OpenGL API entrypoints. When using indirect rendering, libGL creates GLX protocol messages and sends them to the X server via a socket. When using direct rendering, libGL loads the appropriate 3D &DRI; driver then dispatches OpenGL library calls directly to that driver. libGL also has the ability to support heterogeneous, multi-head configurations. That means one could have two or more graphics cards (of different types) in one system and libGL would allow an application program to use all of them simultaneously. Where does libGL reside? The GLcore extension source code resides at xc/lib/GL/GL/ . 3D Driver A &DRI; aware 3D driver currently based on Mesa. Where does the 3D Driver reside? Normally libGL loads 3D &DRI; drivers from the /usr/X11R6/lib/modules/dri directory but the search patch can be overridden by setting the LIBGL_DRIVERS_PATH environment variable. The &DRI; aware 3D driver resides in xc/lib/GL/mesa/src/drv Of what use is the Mesa code in the <filename class="directory">xc</filename> tree? Mesa is used to build some server side modules/libraries specifically for the benefit of the &DRI;. The libGL.so is the client side aspect of Mesa which works closely with the server side components of Mesa. The libGLU and libglut libraries are entirely client side things, and so they are distributed separately. Is there any documentation about the <function>XMesa*</function> calls? There is no documentation for those functions. However, one can point out a few things. First, despite the prolific use of the word Mesa in the client (and server) side &DRI; code, the &DRI; is not dependent on Mesa. It's a common misconception that the &DRI; was designed just for Mesa. It's just that the drivers that we at Precision Insight have done so far have Mesa at their core. Other groups are working on non-Mesa-based &DRI; drivers. In the client-side code, you could mentally replace the string XMesa with Driver or some other generic term. All the code below xc/lib/GL/mesa/ could be replaced by alternate code. libGL would still work. libGL.so has no knowledge whatsoever of Mesa. It's the drivers which it loads that have the Mesa code. On the server side there's more of the same. The XMesa code used for indirect/software rendering was originally borrowed from stand-alone Mesa and its pseudo &GLX; implementation. There are some crufty side-effects from that. How do X modules and X applications communicate? X modules are loaded like kernel modules, with symbol resolution at load time, and can thus call each other functions. For kernel modules, the communication between applications and modules is done via the /dev/* files. X applications call X libraries function which creates a packet and sends it to the server via sockets which processes it. That's all well documented in the standard X documentation. There are 3 ways 3D clients can communicate with the server or each other: Via the X protocol requests. There are &DRI; extensions. Via the SAREA (the shared memory segment) Via the kernel driver. What is the SAREA? It is a block of shared memory that is used to store internal device specific state but there's no simple answer to what, since it is used differently by each driver. It is shared among the X server and all the 3D clients. One piece that is common to all drivers is the upper layer of the lock. Reading the lock value out of the SAREA allows for fast locking. If there's contention the clients make an IOCTL call to resolve the lock. Beyond that it depends on the driver. The 3dfx driver only uses a few flags in the SAREA, one to indicate that the FIFO has been modified, one to indicate that the 3D state has been modified, and one to indicate texture state has been modified. That way the clients know how much state they need to update when a context switch occurs. Other drivers store more state in the SAREA. You can also store that state in the kernel driver. It's a design decision. So what values you put where will vary. Binary compatibility This section is about the binary compatability within the several parts that make a DRI driver. Contributed by Jens Owen. What does binary compatibility means? It means that that driver binaries made on previous releases should work with newer versions. Why is it so important? To avoid potential havoc. For example: If a user installs that latest version of XFree86 — they don't always know they need a new kernel module too — and end up running with the older ones. A vendor has intelectual property they don't want to release. Binary only components can be released, but they will need to support many different flavors of release. To support driver suite binary releases created by DRI development team. Binary compatibility in practice. Proper use of individual versioning components is important. The version number is comprised of three fields seperated by dots .. The first field is the major number, the second the minor number and the third is the patch level. Generally, the service provider sets the version number, and the initial revision is 1.0.0. The service user checks the versioning with logic like: if (major_number != major_expected || minor_number < minor_expected) { Report Incompatability Return Failure } If the interface between service provider and service user does not change, then the patch level is the only number that needs to be incremented in order to reflect internal bug fixes and/or updates. When interface changes are made, care should be taken to preserve the ability for the new service provider to still work with older service users. Incrementing the minor revision number will account for this type of interface change. This is the backwards compatability the we must strive for. In the event compatability must be destroyed, incrementing the major version number will be required. This option is highly discouraged. The following sections outline a list of service providers, and which components utilize these sections. Of the Device Specific Kernel DRM Driver... We have to maintain one direction of compatability in order to stay in the Linux kernel release. This can be acomplished by: semantic change should create a new IOCTL and leave support for the old semantics in the DRM module as well bumping the minor revision number to give a mechanism to know if the new semantics were available Check for different versions and fail gracefully is not a viable scenario acording to Linus. Even when we ignore this and break compatability completely — we have to use versioning properly or we don't even get warnings and disabling. We get CRASHES!!! Versioning set by (service provider): Kernel DRM Driver (programs/Xserver/hw/xfree86/os-support/<OS>/drm/kernel/<driver>_drv.c) Verisoning checked by (service user): 2D Driver (xc/programs/Xserver/hw/xfree86/drivers/<driver>/<driver>_dri.c) 3D Driver (xc/lib/GL/mesa/src/drv/<driver>/<driver>_screen.c) In the SAREA... This is not a service provider by itself, rather it's a communication mechanism used by service providers. The versioning of the service provider should reflect any changes to the SAREA. Additions to the end would typically result in a backwards compatable minor number bump. Removal of fields would result in an incompatible major number bump, and are highly discouraged. Of the 2D Driver... These are less likely to get out of sync as the DRM module — but it's still possible. Again, having good revision checking can save a lot of headaches later. If the versioning isn't accounted for we get hangs and crashes with mismatches. We need to account for older versions, but not necessarily fully support — we could fail gracefully —, although a driver suite supporter could decide to support older versions of one module or the other — at their options. For example, let's say a hardware vendor released a binary DDX module for a special video out mode, then it would be nice if the 3D open source component worked with that module for as many versions as the initial interface allowed. So, even though we did many updates and releases, the old closed-source binary still worked. Versioning set by (service provider): 2D Driver (programs/Xserver/hw/xfree86/drivers/<driver>/<driver>_dri.c) Versioning checked by: 3D Driver (lib/GL/mesa/src/drv/<driver>/<driver>_screen.c) Of the Device Independent DRM Library... Unlike the individual device dependent components in the kernel, this versioning reflects the overall DRM Library API supported by the libdrm.a component. A few device extensions were added to this API, and have since been converted to use the generic drmCommand mechanism. All new extensions should exclusively use drmCommand. The older existing device extensions are still available strictly for backwards compatability. The 3D Driver does not check this because this module is staticly linked, and consequently is always the matching version. Versioning set by (service provider): DRM Library (programs/Xserver/hw/xfree86/os-support/<os>/drm/xf86drm.c) Versioning checked by: 2D Driver (programs/Xserver/hw/xfree86/drivers/<driver>/<driver>_dri.c) Of the DRI Server Extension... This reflects the version of the DRI X11 protocol extension. Versioning set by (service provider): DRI Extension Module (programs/Xserver/GL/dri/dri.c) Versioning checked by: 3D Driver (lib/GL/mesa/src/drv/<driver>/<driver>_screen.c) Of the 3D Driver... The 3D driver is used by the libGL.so library. Versioning does not exist for this interface, yet. However, great care should be taken to not change the interface between the libGL.so library and the 3D drivers. @