Getting a list of usable video modes...
Posted: Sat Feb 07, 2009 12:06 am
Hi,
Note: This post is a rant, not a question. I put it in this forum because it might contain information that's useful for other OS developers (or more likely, it might be a useful warning to anyone who's thinking of attempting something similar )...
I'm trying to write code that detects usable video modes during boot. Sounds fairly simple doesn't it?
The problem is that little word in the middle - "usable". The video mode needs to be supported by the monitor, and if it's not supported by the monitor it shouldn't be in my list of usable video modes; mostly because the OS automatically selects a video mode from this list and the user can't change to a different video mode unless they can see what they're doing.
Also, I only care about colour graphics modes - 4 bits per pixel planar graphics modes, and 8/15/16/24/32 bits per pixel graphics modes (I have no intention of supporting text mode or strange pixel formats like YUV, etc). If I can't find a usable graphics mode then there's no video after boot.
The saga begins here...
There was some ancient video cards and monitors - EGA, MCGA, CGA, etc. I'm not too concern about these, but I can use "Int 0x10, AX = 0x1A00" to determine which video modes the video card and monitor support. For old EGA video cards I can still support "320 * 200 * 16 colour" and "640 * 200 * 16 colour" video modes. For VGA I can support these same modes plus "640 * 350 * 16 colour", "640 * 480 * 16 colour" and "320 * 200 * 256 colour" video modes. For anything else (CGA, MCGA, etc) I'll give up with a "the video hardware isn't supported" message.
Next comes VGA/SVGA. For some old VGA and SVGA monitors it's possible to blow up the monitor by exceeding it's horizontal and/or vertical scanning frequency. For these monitors you're screwed - software has no way to figure out what the monitor supports (and if you're like me, the end user has lost the booklet that came with the monitor and has no idea either). Some old VGA and SVGA monitors don't blow up. However there's still no way to determine if a video mode is usable or not.
To fix this problem VESA introduced DDC (Display Data Channel) and EDID (Extended Display Identification Data). DDC is a hardware protocol (e.g. like RS232) that allows the monitor to talk to the video card. EDID defines the format of the data that the monitor sends to the video card. The entire purpose of EDID is to tell the video card what sort of monitor is connected and which video modes are supported. VESA also added a BIOS function that software can use to read the EDID from the monitor ("Int 0x10, AX=0x4F15, Bl=0x01").
I decided that if I can't get EDID then I can't assume that the monitor supports more than standard VGA resolutions, and I can only allow standard VGA video modes.
I also assumed that if I can get EDID then other software can also get EDID; and that VBE would use EDID for it's intended purpose - to prevent VBE from being used to set video modes that the monitor can't support. I was entirely wrong. For VBE, most (all AFAIK) video cards completely ignore EDID.
So what do I do now? I've got code to load all the EDID information into RAM, and I'm planning to use this information to restrict the list of modes returned by VBE so that only video modes that are supported by the monitor will end up in my list of usable video modes.
However, a video mode is more than just the horizontal and vertical resolution - there's also horizontal and vertical frequencies to worry about. For example, a monitor might support 1024 * 768 @ 60 Hz but might not support 1024 * 768 @ 70 Hz. The "Return VBE Mode Information" function only tells you what resolution (and colour depth) the video mode is but does *not* tell you what refresh rate you'll get; and therefore you've still got no way of knowing if the monitor supports the video mode.
For VBE version 3.0, the "Return VBE Mode Information" function will tell you the maximum pixel clock frequency for the video mode, which can be used to estimate the maximum vertical refresh rate you could end up with. That information is mostly useless because you still don't know the default pixel clock frequency (to allow you to estimate if the vertical refresh rate is supported by the monitor) and you still don't know the minimum pixel clock (to see if the entire range of possible vertical refresh rates are supported by the monitor).
For VBE 2.0 or later, you can pass a "CRTCInfoBlock" to VBE when you set the video mode (e.g. in an attempt to make sure the timings end up within the range supported by the monitor), but VBE chooses the closes frequency it supports and there's no way to tell if the closest frequency VBE supports is within the range of frequencies supported by the monitor, and no way to do this without setting the video mode first (and setting 50 different video modes during boot, one after the other, would look a little crappy - it might make the end user think the monitor is having an epileptic fit).
For VBE 3.0, Function 0x0B lets you get and set the pixel clock for any VBE video mode. This could be used to check if the video mode can be setup with timings that the monitor supports. This actually does sound like an answer to me (although it's a complex messy answer involving strange calculations and estimates based on other information that may or may not be present).
Finally, there's always bugs to consider. There's no guarantee that the video card's ROM and the monitor's EDID aren't full of bugs. Some OS's have a database of "corrected EDID", where the monitor's identification (PnP ID) is used to find out if there's replacement EDID information to use. Also, for some video cards I've seen reports that EDID may or may not work depending on where it's plugged in (e.g. if the monitor is connected to the video card's analogue/VGA connector then EDID works, but if the same monitor is connected to the same video card by the DVI connector instead then EDID doesn't exist).
To be honest, I'm tempted to dump all this mess and only allow standard VGA video modes. Unfortunately I know there won't be any native video device drivers for my OS for a very long time, and people just don't like using "640 * 480 * 16 colour" video mode when their hardware supports much better video modes.
*sigh*
Cheers,
Brendan
Note: This post is a rant, not a question. I put it in this forum because it might contain information that's useful for other OS developers (or more likely, it might be a useful warning to anyone who's thinking of attempting something similar )...
I'm trying to write code that detects usable video modes during boot. Sounds fairly simple doesn't it?
The problem is that little word in the middle - "usable". The video mode needs to be supported by the monitor, and if it's not supported by the monitor it shouldn't be in my list of usable video modes; mostly because the OS automatically selects a video mode from this list and the user can't change to a different video mode unless they can see what they're doing.
Also, I only care about colour graphics modes - 4 bits per pixel planar graphics modes, and 8/15/16/24/32 bits per pixel graphics modes (I have no intention of supporting text mode or strange pixel formats like YUV, etc). If I can't find a usable graphics mode then there's no video after boot.
The saga begins here...
There was some ancient video cards and monitors - EGA, MCGA, CGA, etc. I'm not too concern about these, but I can use "Int 0x10, AX = 0x1A00" to determine which video modes the video card and monitor support. For old EGA video cards I can still support "320 * 200 * 16 colour" and "640 * 200 * 16 colour" video modes. For VGA I can support these same modes plus "640 * 350 * 16 colour", "640 * 480 * 16 colour" and "320 * 200 * 256 colour" video modes. For anything else (CGA, MCGA, etc) I'll give up with a "the video hardware isn't supported" message.
Next comes VGA/SVGA. For some old VGA and SVGA monitors it's possible to blow up the monitor by exceeding it's horizontal and/or vertical scanning frequency. For these monitors you're screwed - software has no way to figure out what the monitor supports (and if you're like me, the end user has lost the booklet that came with the monitor and has no idea either). Some old VGA and SVGA monitors don't blow up. However there's still no way to determine if a video mode is usable or not.
To fix this problem VESA introduced DDC (Display Data Channel) and EDID (Extended Display Identification Data). DDC is a hardware protocol (e.g. like RS232) that allows the monitor to talk to the video card. EDID defines the format of the data that the monitor sends to the video card. The entire purpose of EDID is to tell the video card what sort of monitor is connected and which video modes are supported. VESA also added a BIOS function that software can use to read the EDID from the monitor ("Int 0x10, AX=0x4F15, Bl=0x01").
I decided that if I can't get EDID then I can't assume that the monitor supports more than standard VGA resolutions, and I can only allow standard VGA video modes.
I also assumed that if I can get EDID then other software can also get EDID; and that VBE would use EDID for it's intended purpose - to prevent VBE from being used to set video modes that the monitor can't support. I was entirely wrong. For VBE, most (all AFAIK) video cards completely ignore EDID.
So what do I do now? I've got code to load all the EDID information into RAM, and I'm planning to use this information to restrict the list of modes returned by VBE so that only video modes that are supported by the monitor will end up in my list of usable video modes.
However, a video mode is more than just the horizontal and vertical resolution - there's also horizontal and vertical frequencies to worry about. For example, a monitor might support 1024 * 768 @ 60 Hz but might not support 1024 * 768 @ 70 Hz. The "Return VBE Mode Information" function only tells you what resolution (and colour depth) the video mode is but does *not* tell you what refresh rate you'll get; and therefore you've still got no way of knowing if the monitor supports the video mode.
For VBE version 3.0, the "Return VBE Mode Information" function will tell you the maximum pixel clock frequency for the video mode, which can be used to estimate the maximum vertical refresh rate you could end up with. That information is mostly useless because you still don't know the default pixel clock frequency (to allow you to estimate if the vertical refresh rate is supported by the monitor) and you still don't know the minimum pixel clock (to see if the entire range of possible vertical refresh rates are supported by the monitor).
For VBE 2.0 or later, you can pass a "CRTCInfoBlock" to VBE when you set the video mode (e.g. in an attempt to make sure the timings end up within the range supported by the monitor), but VBE chooses the closes frequency it supports and there's no way to tell if the closest frequency VBE supports is within the range of frequencies supported by the monitor, and no way to do this without setting the video mode first (and setting 50 different video modes during boot, one after the other, would look a little crappy - it might make the end user think the monitor is having an epileptic fit).
For VBE 3.0, Function 0x0B lets you get and set the pixel clock for any VBE video mode. This could be used to check if the video mode can be setup with timings that the monitor supports. This actually does sound like an answer to me (although it's a complex messy answer involving strange calculations and estimates based on other information that may or may not be present).
Finally, there's always bugs to consider. There's no guarantee that the video card's ROM and the monitor's EDID aren't full of bugs. Some OS's have a database of "corrected EDID", where the monitor's identification (PnP ID) is used to find out if there's replacement EDID information to use. Also, for some video cards I've seen reports that EDID may or may not work depending on where it's plugged in (e.g. if the monitor is connected to the video card's analogue/VGA connector then EDID works, but if the same monitor is connected to the same video card by the DVI connector instead then EDID doesn't exist).
To be honest, I'm tempted to dump all this mess and only allow standard VGA video modes. Unfortunately I know there won't be any native video device drivers for my OS for a very long time, and people just don't like using "640 * 480 * 16 colour" video mode when their hardware supports much better video modes.
*sigh*
Cheers,
Brendan