<< Newer | Articles posted July 2006 |
A Peek Inside the New Renderer (part 1)
The new rendering system that was introduced at the start of the 0.106 development cycle represents a whole new way of thinking about video in MAME. This article is the first in an attempt to explain what's really going on behind the scenes.
The new system is generally rather object oriented, even though it is still written in straight C. There are a number of fundamental rendering objects that are used to describe what gets rendered to the screen. We'll first go over the objects, and then talk about how it all comes together.
One concept to keep in mind while reading this article is that the rendering system serves as a bridge between the MAME core and the OS-dependent code (the OSD layer). There are some objects that are primarily outward facing (i.e., operated on primarily by the OSD layer), and some objects that are primarily inward facing (i.e., operated on by other core components).
The core outward-facing object in the new rendering system is the render_target. A render_target is an object that communicates to the core exactly how the OSD layer would like the final video to look. The OSD layer is responsible at startup time (in the osd_init callback) for allocating one or more render_targets. In the most common case, there will be just one render_target allocated (though in the Windows code if you request more than one screen, then one render_target will be allocated per screen).
Each render_target contains information about the width, height, orientation, and pixel aspect ratio of the destination. For example, if you were running full screen on a 640x480 display, the OSD layer would allocate a render target and configure it with a width of 640, a height of 480, a standard orientation (no rotation), and a pixel aspect ratio of 1.0 (assuming your 640x480 was being displayed on a 4:3 screen). This information is used later by the MAME core when it is time to actually provide the data necessary to draw the final output.
On the opposite side of the fence, the core inward-facing object in the new system is the render_container. A render_container is an object that contains a list of items (lines, quads, or characters) to draw. There can be any number of render_containers in the system, but the current system simply allocates one render_container per screen in the game, and an extra render_container for the user interface. Code in the core is responsible for adding items to each render_container. For example, at video update time, the video.c module adds the bitmap for each screen to the render_container for that screen. In contrast, vector games don't have a bitmap, and so their update routines add a bunch of lines to the render_container to describe what should be displayed on its screen.
In addition to holding a list of items to draw, each render_container also holds several additional rendering parameters, including brightness, contrast, and gamma controls, as well as scaling and offsetting functions. When applied to screen-specific render_containers, these controls give most of the common adjustments present on an actual arcade screen. These controls are now (as of MAME 0.106u11) all available from the on-screen display menu, and work independently for each screen in the system.
So, given what's been described so far, there are two separate sets of objects for rendering. The first set is the collection of render_targets, which are allocated and managed by the OSD layer. The second set is the collection of render_containers, which are allocated and managed by the core. The obvious question is: how to these two sets of objects map to each other? That is, how do we get the contents of the render_containers to show up on the render_targets?
The answer is the layout_view. Each render_target object has an associated layout_view, which describes exactly how the video system should position and orient all the elements that go to make up the final video output. These elements can be items from one of four classes: backdrops, overlays, bezels, or screens. The first three types of elements are artwork pieces which are static, preloaded, and pre-scaled graphics that are intended to be intermixed with the screen elements. The screen elements specify the location and orientation of the render_container that holds the screen items.
There are several important implications of this setup. First, each render_target has its own layout_view, completely independent of any other render_targets. This means that you can have multiple render_targets active at a time, each with the same layout_view, or completely different layout_views. Second, there is only one render_container per screen in the system, but multiple layout_views can reference each screen. In fact, a single layout_view can even include multiple references to the same screen; this is how the "Cocktail" view works in the current system.
Where do layout_views come from? From layout (.lay) files. Layout files are fundamentally just XML descriptions of layout_views, and each layout file can contain descriptions of multiple layout_views. At startup, MAME will attempt to load layout files from multiple sources. All layout files that are found are effectively concatenated together into one big list of layout_views, which you can dynamically select at runtime in the new "Video Options" menu.
So, in summary: at startup, the rendering system creates render_containers for each game screen, and the OSD layer creates render_targets for each output screen. When a render_target is created, the selected layout files are loaded in order to create a list of layout_views. These layout_views describe how to intermix the render_containers for each game screen with artwork and other adornments to produce the final output in the render_target.
In the next part of this article, I'll talk a bit about how the graphics actually get assembled and what the mixing rules are.
Space Invaders: Overlay, Backdrop, or both?
As a few people have pointed out, when you try to use an overlay and a backdrop at the same time with the new renderer, you get some ugly results. I can fix the problem, but it will be somewhat complicated. But before I do, I would really like to know a definitive answer: are there any games that used an overlay on the monitor and then reflected that image onto a backdrop? I'm sure everyone will cry Space Invaders, yet after an admittedly small amount of searching, I can only find pictures of the game that are either (a) black & white on top of a backdrop, or (b) color with no backdrop.
So, I offer up the challenge: a picture or some other confirmation that Space Invaders did in fact ship with both an overlay and a backdrop in the same cabinet. Obviously shots from other MAME releases don't count.
Alternatively, if someone can prove any other games that had both, I would
be open to alternative proof from that direction.
MAME 0.106u10
As you might have noticed, the latest source patches are now available. If you want to try a precompiled binary version, I've made it available here on this site.
In this build I've fixed all the internal overlays to use the new system,
and updated all the games that were using dynamic artwork as well. In order
to try out these games, you will need to take the layouts from this
collection and copy them into the appropriate artwork from the mame.net site.
The New Video Landscape
A whole pile of stuff has changed during the 0.106 development cycle, and though we are a few weeks away from a real 0.107 release, it's probably time to sit down and have a little heart-to-heart about the video options.
Since its inception 9 years ago, MAME's video system has defaulted to a mode where it tries to change resolutions on you. And since the first port of the core to Windows 5 years ago, it has defaulted to using your graphics card to stretch the video to that resolution.
I'm sure a lot of you out there have taken a lot of time to tweak the current set of video options to make them work the way you like. But every once in a while, you need to take a step back and re-evaluate the situation. The current video system has been in place for 5 years now without much substantial change. And with the recent rewrite, you're almost certainly going to want to rethink the way you have things configured.
At the highest level, there are really three different ways you can configure
the new system. Placing yourself into one of these three categories will
help you get the initial settings right. From there, you can tweak with
the settings to figure out what works best.
Category 1: Bells and whistles. People who fall into this category
would include anyone with a modern system and a decent video card (decent
in this context means at least 16MB of VRAM and built in the last 5 years
or so -- we're not talking cutting edge here). Any decent video card will
be able to render the simple MAME graphics at pretty much any resolution
without breaking a sweat. Configure your desktop to the video mode you
want (preferably something high like 1024x768 or greater with a high refresh
rate, unless you are running on a fixed-mode LCD, in which case just match
what your LCD panel is), and tell MAME to leave the resolution alone. In
this day and age, there is little reason to switch resolutions at all,
unless you fall into Category 3, below. In this mode, you will have full
access to artwork options, and you'll get your artwork scaled to full resolution
and with full alpha blending effects. Vector games will look crisp, you
can use decent fonts, and you can see a whole lot more of the world when
using the graphics/tilemap viewer. This mode uses Direct3D, so you should
configure yourself like this:
-video d3d -noswitchres [-triplebuffer] [-nofilter]
The -noswitchres option tells MAME to just run at the current resolution.
Although you can let MAME pick a resolution for you, it doesn't really
make much sense in D3D mode, and in fact I may even remove that feature
altogether. To avoid tearing artifacts, I recommend using the -triplebuffer
option as well. Just make sure your monitor's refresh rate is higher than
the game you are running. If you dislike the blurry look of the graphics,
you can specify the -nofilter option to disable bilinear filtering, though
that will produce blocky artifacts. Alternatively, you can use the -prescale
option which is described at the end of this article.
Category 2: Like the old days. I really didn't even want to support
this mode at all, but certain vocal MAMEdevs would have skinned me alive
otherwise. People who fall into this category include those who have weak
systems that worked fine with previous versions of MAME, but who don't
run well with Direct3D rendering. (Note that just because Space Invaders
runs unthrottled at 2000fps with DirectDraw and 1000fps with Direct3D doesn't
mean that Direct3D is going to be a serious issue when playing at a regular
60fps, so if you're unsure, give the Direct3D route a try for a while.)
In this mode, MAME will draw the game screen and artwork at the game's
resolution, just like it did in MAME 0.106 and earlier; however, some artwork
options, such as -artcrop, won't work as you might expect, and some alpha
blending artwork modes (specifically overlays) won't work. MAME will then
use your video card to stretch the video to the proper aspect ratio.
-video ddraw -hwstretch [-switchres] [-triplebuffer]
The -switchres is optional here. If your video card is really ancient and
struggles expanding the screen to fit your desktop resolution, you might
want to turn it on. Again, to avoid tearing artifacts, I recommend using
the -triplebuffer option as well, but make sure your monitor's refresh
rate is higher than the game you are running (-switchres will do that for
you if you use it). If your video card produces blurry pixels which you
don't like, try the -prescale option described at the end of this article.
Category 3: Anal video mode types. These are the guys who have generally
built their own cabinets and set them up with a CRT display where they
have several dozen carefully hand-tweaked video modes that approximate
the original video modes the games ran at. They want MAME to pick that
hand-tweaked mode and use it, drawing one pixel on the screen for each
pixel in the original game. They don't give a whit about artwork or anything
other than the raw pixels going to the right place. Fortunately, you can
still configure MAME for this case as well:
-video ddraw -nohwstretch -switchres [-triplebuffer]
Obviously in this case, the -switchres is required. You also want to disable
hardware stretching, otherwise you won't get that "perfect" 1:1 pixel mapping.
Triple buffering may or may not help.
So, I recommend starting with these initial options and then tweaking from there. One additional option you might want to try in combination with the above is the -prescale option. -prescale takes an integer parameter from 1 to 8, and specifies a magnification amount by which the screen pixels are expanded before they are drawn to the screen. Why is this useful? And how much of a performance impact does it have? Well, that depends on the mode you are running in.
If you are running in Category 1 (-video d3d), then -prescale will use your video card to scale the game graphics up before rendering them to the screen. Depending on the video card, this is usually a small performance hit, but not too significant. The benefit is that each prescale factor reduces the blurriness of the pixels. -prescale 1 is the default, which does no scaling. -prescale 2 will double each pixel, -prescale 3 will triple each pixel, etc. For my money, -prescale 2 is sufficient, but people with super high resolution displays claim that larger -prescale factors work even better.
If you are running in Category 2 (-video ddraw -hwstretch), then -prescale will cause MAME to compose the screen graphics at the specified scale factor. This is unfortunately done in software, but carries the benefit that artwork, fonts, and the graphics viewer can take advantage of the additional resolution to produce nicer results. The end effect is that you will get less blurry pixels, just like the Category 1 case, plus higher quality artwork, fonts, and more visible area in the graphics viewer.
If you are running in Category 3 (-video ddraw -nohwstretch), then -prescale will cause MAME to pick a video mode that is the prescale factor times the raw screen resolution, and then MAME will, in software, compose the screen graphics at the specified scale factor. This has all the advantages of the Category 2 case, except that since there wasn't any pixel blurring to begin with, there is no additional crispness that comes about as a result.
Finally, you may be wondering about effects (and yes, scanlines are an "effect"). Well, let's take the band-aid off quickly:
Effects are not currently present in the video system and are not planned in the short term.
Ouch.
Are they gone forever? It's too early to say for sure. They present some unique problems. It's possible that if they do come back, they will only be available in Direct3D (Category 1) mode. For the next few versions of MAME, try living without them. Certainly, I want the video system as it currently stands to stabilize before even considering it.
I'll try to post a binary for u10 when it's available to let everyone play with the options a bit.
Seriously Impressed
I've been looking through the MAME source for games that were previously using the artwork system to dynamically update non-screen elements. I started off doing Turbo (as mentioned previously) and Discs of Tron, which a number of people have been asking about. There were a couple of glitches in the new system which showed up when I did the Discs of Tron artwork, so you will need to wait for u10 to actually use the layout file linked above and have it all working.
Then I moved on to Golly Ghost. Wow. Color me seriously impressed with the folks who put this one together. The quality of the artwork is very nice and it all works very well with the game graphics overlaid. And now that the artwork scales to your screen resolution (assuming you are using Direct3D), it looks absolutely amazing. Check it out!
I'm hoping to get a few more games updated, specifically Gorf, Spy Hunter, and Sky Diver, before I put out the next release.