Page 1 of 1

VBE: Best resolution, extreamly high resolution?

Posted: Wed Aug 25, 2010 9:59 am
by lemonyii
hi,
i've just been able to switch to some common resolution like 800*600*16 and 1024*768*32 through VBE, and fill the screen to be a color of comfortable green.
But i want to get the best suitable resolution through code(it very neccessarily for LCD,i think),
but the result is that i got some extreamly large resolution, like 2048*1536*24 in vmware, and sth no smaller in bochs.
Another problem is, when i switch to such extreamly large resolutions, the code of filling green doesn't work any more.
But in qemu, everything works, and the resolution is not too high, about 1280*1024 i think.
On my real machine, it works too, but my LCD inform me of sth like "Not best suitable resolution"(my SUMSUNG 943NW+ will zoom any resolution to fit the screen).
my code:

Code: Select all

change_vesa_mode:
	mov		ax,0x4f00
	mov		di,VbeInfoBlock
	int		0x10
	or		ah,ah
	jnz		change_vesa_mode
	mov		eax,[VbeInfoBlock.VideoModePtr]
	mov		si,ax
	shr		eax,16
	push	ax
.choose:
	pop		bx
	mov		ds,bx
	lodsw
	mov		bp,ax
	push	ds
	xor		bx,bx
	mov		ds,bx
	
	cmp		ax,0xffff	;last item, finish
	je		.do_switch
	mov		cx,ax
	mov		ax,0x4f01
	mov		di,VbeModeInfoBlock
	int		0x10
	or		ah,ah
	jnz		.choose
	mov		ax,[VbeModeInfoBlock.ModeAttributes]
	bt		ax,0	;supported?
	jnc		.choose
	bt		ax,7	;LFB?
	jnc		.choose
	;if the mode is better?
	cmp		byte [VbeModeInfoBlock.BitsPerPixel],16		;color depth > 16
	jb		.choose
	xor		eax,eax
	xor		ebx,ebx
	xor		ecx,ecx
	mov		ax,[VbeModeInfoBlock.XResolution]
	mov		bx,[VbeModeInfoBlock.YResolution]
	mov		cl,[VbeModeInfoBlock.BitsPerPixel]
	mul		ebx
	mov		ebx,ecx
	mul		ebx
	cmp		eax,[BestBits]
	jna		.choose		;not that better
	mov		[BestBits],eax
	mov		[BestMode],bp
	jmp		.choose

.do_switch:	
	;we need to get the ModeInfoBlock again for use
	mov		cx,[BestMode]
	or		cx,0x4000	;LFB
	mov		ax,0x4f01
	mov		di,VbeModeInfoBlock
	int		0x10
	or		ah,ah
	jnz		.do_switch
	;really switch
	mov		bx,[BestMode]
	mov		ax,0x4f02
	mov		di,0
	int		0x10
	or		ah,ah
	jz		.vbe_mode_done
	;if failed
	mov		dword [BestMode],0x4114
	mov		dword [BestBits],800*600*16
	jmp		.do_switch
.vbe_mode_done:

Code: Select all

	;fill the screen
	mov		ecx,[BestBits]	
	shr		ecx,5
	mov		edi,[VbeModeInfoBlock.PhysBasePtr]
	
	mov		eax,0x04000400
	cmp		byte [VbeModeInfoBlock.BitsPerPixel],16
	je		.fill_16_32
	mov		eax,0x00008000
	cmp		byte [VbeModeInfoBlock.BitsPerPixel],32
	je		.fill_16_32
	cmp		byte [VbeModeInfoBlock.BitsPerPixel],24
	je		.fill_24
	jmp		$
.fill_16_32:
	rep
	stosd
	jmp		.fill_done
.fill_24:
	stosd
	dec		edi
	loop	.fill_24
.fill_done:
Notice the BestBits in the code: BestBits = x*y*bpp.
and i think the reason why i can't fill the screen may be the LFB is at above 4G or sth wrong with it.
what i want to do now, is to get the best suitable resolution and ensure the screen filled green.
thanks,
lemonyii

Re: VBE: Best resolution, extreamly high resolution?

Posted: Wed Aug 25, 2010 3:47 pm
by Combuster
Since your previous posts were all about things you could find yourself, I'm going to send you on a homework trip:

This topic has been discussed before, and it's pointed to from the wiki. The subject is about getting a list of useful resolutions. There's a ton of valuable information in there which altogether makes sure there is no single correct answer to this question. Try to find it.

Off you go now.

Re: VBE: Best resolution, extreamly high resolution?

Posted: Wed Aug 25, 2010 7:57 pm
by Brendan
Hi,

For some types of monitors (e.g. LCD) the monitor has a native resolution (e.g. 1920 * 1080), and anything else is scaled to the native resolution. This scaling can cause a slightly blurry picture and unwanted artefacts.

In addition, different monitors support different video mode timings. For example, a monitor might support 800 * 600 at 60 frames per second, but might not support 800 * 600 at 75 frames per second.

In a lot of cases you can get information from the monitor called EDID (or "Extended Display Identification Data"). This will tell you which video mode timings the monitor supports, and which video mode timing/s are "preferred". For LCD monitors, the most preferred video mode timing corresponds to the monitor's native resolution.

Unfortunately, VBE sucks dog balls. The first problem is that (for most VBE cards) the video card doesn't use the monitor's EDID data at all, and will offer video modes that the monitor does not support. This means you have to (try to) get the monitor's EDID yourself and parse it, and filter out video modes that the monitor doesn't support.

The second problem is that VBE usually only offers you some video modes (and not all possible video modes), and the offered video modes are almost always intended for 4:3 monitors. Most LCD monitors are 16:10 or 16:9, which means that usually you can't use VBE to set the monitor's native resolution. Often you can't even get the horizontal or vertical resolution to match (so that scaling is only done in one direction rather than both directions).

The third problem is that VBE usually only tells you the resolution and colour depth; and doesn't tell you anything about the video mode's timing. For example, the monitor might support 800 * 600 at 60 frames per second but might not support 800 * 600 at 75 frames per second, and VBE might tell you about a 800 * 600 with 16 bits per pixel video mode, and you won't be able to tell if the video mode is 60 frames per second or 75 frames per second, and won't be able to reliably determine if the monitor supports it or not. The only way around this is to use the "CRTCInfoBlock structure" that was introduced by VBE 3.0 to force the video card to use a timing that is supported by the monitor; but unfortunately a lot of video cards don't support VBE 3.0 and some of the video cards that do support VBE 3.0 don't support the "CRTCInfoBlock structure" properly. You could also attempt to estimate the probability that a video mode will/won't work (and then choose a video mode that has the highest probability of working).

Also note that for some (very old) monitors and some notebook/laptops, you can't get EDID information from the monitor. This causes problems because it is possible to permanently damage some (very old, "VGA only") monitors and some notebook/laptops if you try to set a video mode that isn't supported. There are 2 video mode timings that have been designated as "safe video mode timings" by VESA (640 * 480 at 59.940 frames per second and 720 * 480 at 59.941 frames per second) that are meant to be supported by all monitors. If you can't get EDID information, then you should probably attempt to only allow these "safe video mode timings" to be used.

Of course it is also possible to ask the user - for example, create a list of video modes and ask the user to select one, and provide some sort of "Press enter if this video mode works" dialog box (e.g. with a 10 second time-out) so the user can tell you if the video mode works or not. This doesn't necessarily prevent the user from blowing up their monitor, and you'd probably also want to save the selected video mode somewhere (e.g. avoid annoying the user every time they boot by using the video mode they selected last time). This may not be easy either, because it means you need keyboard support, and unfortunately for too many modern computers the BIOS keyboard functions don't work when there's a USB keyboard. One way around that would be to display a list of video modes and ask the user to (try to) select one, but have a time-out so that if the user doesn't select a video mode (or can't select a video mode) then you auto-select one after the time-out expires. The other way would be to wait until the OS has it's USB and keyboard drivers running, but that implies setting a video mode after boot (rather than during boot, when the BIOS/VBE functions are easy to use), which can mean implementing support for virtual8086 mode and or a real mode emulator.

The easiest way would be to just use 640*480 (at the highest colour depth the video card supports), as this should be a "safe video mode timing". However, if you want to use high-resolution video modes and you want to do it "properly" then regardless of how you do it it will take a lot of work.


Cheers,

Brendan

Re: VBE: Best resolution, extreamly high resolution?

Posted: Thu Aug 26, 2010 12:46 am
by lemonyii
hi,
thank you for replying first.
after hours' hard work, the result is still disappointing.
my code (just modified some little place from previous,so some are ignored)

Code: Select all

	
change_vesa_mode:
.get_preferred_mode:
	mov		ax,0x4f15
	mov		bl,0x01
	mov		cx,00
	mov		dx,00
	mov		di,EDID
	int		0x10
	or		ah,ah
	jnz		.user_choose
	add		di,0x36		;di->preferred timing mode
	mov		ax,[di]
	or		ax,ax
	jz		.user_choose
	mov		al,[di+2]
	mov		ah,[di+4]
	shr		ah,4
	mov		[ScreenX],ax
	mov		al,[di+5]
	mov		ah,[di+7]
	shr		ah,4
	mov		[ScreenY],ax
.get_mode_list:
	....
.choose:
        ...
	;if the mode is better?
	cmp		byte [VbeModeInfoBlock.BitsPerPixel],16		;color depth >= 16
	jb		.choose
	mov		ax,[VbeModeInfoBlock.XResolution]
	mov		bx,[VbeModeInfoBlock.YResolution]
	cmp		ax,[ScreenX]
	jne		.choose
	cmp		bx,[ScreenY]
	jne		.choose
	;find it!
	mov		[BestMode],bp
	jmp		.do_switch	
.user_choose:
...(this part works properly)
	
.do_switch:	
...(no problem,i think)
[img]a.bmp[/img]
my idea is, get the preferred mode through EDID.DetailedTimingMode[0], store the x,y in somewhere (i don't know which is the HZ for Chinese translation is much too different from the original word, so ignored, if anyone can help).
But on vmware, qemu, bochs, the code turns out to be a failure. Some can't get EDID,some can't find matched resolution.(i forgot details)
what surprised me is that my real machine matched a 4:3 size(i dont know exactly which it is. but it should be 1440*900).
So i think, my code of get_preferred_mode failed.
what do you do to get it? and the HZ?
thanks,
lemonyii

Re: VBE: Best resolution, extreamly high resolution?

Posted: Thu Aug 26, 2010 1:55 am
by Solar
Looking at how much of a problem this seems to be, and given how often even Windows and Linux "guess" wrongly, why not just start in the lowest common denominator and let the user select the desired resolution, color depth, and timing?

(Sorry for this piece of non-constructivism, but ever since AmigaOS' 'ScreenMode' dialog, I felt the way other OS' handled the subject to be somewhat... faulty. Either you have a way to guess right 99.99% of the time, or you don't try to guess and let the user handle it - that's my opinion.)

Re: VBE: Best resolution, extreamly high resolution?

Posted: Thu Aug 26, 2010 4:00 am
by Brendan
Hi,
lemonyii wrote:my idea is, get the preferred mode through EDID.DetailedTimingMode[0], store the x,y in somewhere
There's about 5 different versions of the EDID structure. The detailed timing descriptors are mandatory for EDID 1.3 and EDID 1.4, but were optional in previous versions. However, even when the detailed timing descriptors are mandatory and must exist, nothing prevents the entries from being "present but unused".

Also, there are extensions to EDID. One of these is "VTB_EXT" (or the "VESA Video Timing Block Extensions Data Standard"), which can be used by the monitor for extra detailed timing descriptors and extra standard timing descriptions. There's also a pair of formulas - GTF (or "Generised Timing Formula") and CVT ("Coordinated Video Timings"). The monitor can tell you it supports any video mode that can be described by these formulas instead of listing every video mode it supports using other methods.

You should find a section of the EDID specification that says the order of preference for things (e.g. "Section 5. Timing Information Priority Order"). You should use this to find a preference for any/all video mode timings mentioned by EDID. Of course because VBE sucks (and you need to estimate most of the time instead), it's probably better to estimate the chance that the video mode will work and also estimate the preference.

However, you should also probably re-read my last post. For example, in theory there's probably several million different video mode timings (with different horizontal/vertical blanking, different clock rates, etc) that can all be described as "1024 * 768 with 60 frames per second". Just because you actually find a video mode that matches the monitor's preferred resolution doesn't mean that any of the timing is right or that the monitor supports the mode.

Finally, if you're using EDID then you should probably also support some way of overriding the EDID, and some way of allowing the user to supply their own EDID that's used if/when you can't get it from the video card.


Cheers,

Brendan

Re: VBE: Best resolution, extreamly high resolution?

Posted: Thu Aug 26, 2010 4:23 am
by Brendan
Hi,
Solar wrote:Looking at how much of a problem this seems to be, and given how often even Windows and Linux "guess" wrongly, why not just start in the lowest common denominator and let the user select the desired resolution, color depth, and timing?
Almost all of these problems are a direct result of VBE. If you're using a native video driver, then most of the problems disappear.
Solar wrote:(Sorry for this piece of non-constructivism, but ever since AmigaOS' 'ScreenMode' dialog, I felt the way other OS' handled the subject to be somewhat... faulty. Either you have a way to guess right 99.99% of the time, or you don't try to guess and let the user handle it - that's my opinion.)
Everything gets much easier when there's only one or 2 standard video devices to worry about, and no compatibility problems between the video card and the monitor. Once you shift to "anyone can make any video card" and "anyone can make any monitor" you rely on good standards to make sure things made by different companies work together, and let's be honest, VESA has a very long list of failures...


Cheers,

Brendan

Re: VBE: Best resolution, extreamly high resolution?

Posted: Thu Aug 26, 2010 4:54 am
by lemonyii
thank you!
i'm trying, and considering just let the user choose, or just set up a 640*480 and change it after the whole system started up, and load a video driver.
thanks,
lemonyii