Re: Polling loop good here???
- From: "Richard Cooper" <spamandviruses@xxxxxxxxxxxxxxxxx>
- Date: Wed, 31 Aug 2005 03:06:15 GMT
Hello... I'm the guy who posted the origional question to the linux-assembly mailing list.
I think DOOM doesn't synchronise to frames at all, or only if non-animated screens (like the menu) are displayed.
Actually, it turns out DOOM wouldn't be affected like I though. My problem has to do with displaying successive frames with totally different palettes. When DOOM changes it's palette, the new palette is perfectly valid for the old pixel data, in fact it doesn't change the pixel data at all, just the palette.
I'm displaying video converted to a series of 256 color images. Each has an optimized color palette just for that image, and so each image just looks like garbage when displayed with the palette from a different image.
So the problem I get is worse than just tearing, I get a bar of static-like stuff about 1/4 of the screen tall in every frame, which is drawn between the time the palette is changed and the time when the screen data is changed. The only way to get rid of it is to synchronize with the vertical retrace, so that the palette is changed when the CRT beam isn't drawing anything, and then the screen data is changed before the CRT beam gets to it.
Hmm, 0xA00000 is the address of the VGA framebuffer... using this as a hardcoded value and playing with /dev/mem doesn't seem like a very nice approach to me, considering a protected-mode OS.
Actually, it sets up the VGA registers itself, so it knows that the buffer is at A0000. It even uses A0000 for text modes instead of B8000.
It will limit you to the standard VGA modes,
Yep, but what can I do? I guess I could make it use VESA 2.0 or something, but documentation is so hard to find, and I'd have to find a lot of it. After being stuck with a VT-100 emulator for so long, even 320x240 is a joy to play with.
It might be just one of multiple supported modes, though.
Not really. It only does six modes, all VGA. 80x30 text, 80x40 text, 80x48 text, 80x60 text, 320x240x256 graphics, and 640x480x16 graphics. It's biggest thing is that it lets you do everything with the VGA. In text mode you can redefine font characters, change colors to anything (you get the full 18-bit color range to choose from), plus it uses 8-pixel wide fonts, instead of the standard 9-pixel wide VGA text mode, so ANSI-type graphics look really nice since characters like DOS's 176, 177 and 178 won't have that vertical space between them. (It doesn't have those characters, but you can define them if you want them.)
It's really quite nice for only being VGA.
You still require synchronisation for smooth, flickerless display be it 60Hz, 75Hz or 700,000,000Hz...
Actually, at 700Mhz, you wouldn't notice the tearing. This is because the display would so accurately reflect the contents of video memory that your program writing to the video memory effectively becomes the CRT beam. Thus it's always synchronized, because it's synchronized with itself.
But you're right, 75Hz is going to do it just like 60Hz.
Electricity...
Ok guys, here's how it goes.
120v RMS is 110v average is 170v peak.
So it really is 120v, because when you run it through a resistance, it generates as much heat as 120v DC would. However, back before the days of RMS (I guess) people just looked at the average voltage, which is to take all of the points over time (naturally of just the positive cycle) and average them together. This gives you 110v. So when you hear people say 120v, they're talking RMS (which is the correct one, BTW), when they say 110v, they're talking average voltage, and when they say 115v, they're just averaging the two numbers together because they don't know any better.
Now, when you have two 120 sources, 180 degrees apart, if you take one of them and use it with ground, you get 120v. This is because ground is 0v, and 120 minus 0 is 120. If you take both 120v sources and use them, whenever one is at it's peak 170v, the other is at it's peak of -170v. Using the RMS values, we just do 120 minus -120, and we get 240.
The 240 is at the same frequency that the 120 was at. Doubling the voltage doesn't magically double the frequency.
And I'd bet that Linux is providing this synchronization. Or at least the tools (like DirectX) to do it.
Linux won't synchronize anything. SVGAlib does polling, X aparently doesn't, SDL just passes the problem along to SVGAlib, X, or whatever it's using, and someone here said that framebuffer has an unimplemented IOCTL for it. So it looks like it's either poll or nothing.
Have the OS do it. I'm pretty sure that's the "right" way to do it.
Linux won't do it. Linux is a text mode OS. Actually, not even text mode. It's a VT-100 OS, right down to the backspace sending the delete code because it's in the place where the delete key "should" be.
I dunno. I bet on the VT-100 it was the key labeled "delete" that sent the delete code. Why couldn't Linus have used that logic and done it the right way?
It's probably not feasible to do this in windows or linux or other non-realtime OSes.
It turns out it can be done on 2.6 kernels. 2.4 kernels do 10ms timeslices, but because of a rounding mess in the kernel, any sleeping typically lasts for 20ms, useless for the 17ms refresh interval. 2.6 kernels use 1ms timeslices, and have a much improved rounding mess, so you can sleep for 15ms, which makes you sleep for 16ms, and so the program's running again just before the next retrace.
I wrote a test program, and it did pretty well, missing only 2 frames out of 3600. I still don't think it should have missed those two, as the system was completely idle, and the process running under "realtime scheduling," but it 99.94% works.
http://www.programmersheaven.com/zone7/cat128/1481.htmmentions "simulating retrace interrupt"
This is basically what I was trying to do. Since you can't get IRQs in Linux, I was trying using a Linux timer, but that didn't work because it wasn't accurate enough to be useful.
I'm not sure if, in fact, you technically have to "surrender" IRQ 2to "cascading" (is it still possible with the controllers hooked upin "cascade" to still get a plain old IRQ 2 that isn't destined forthe second slave 8259 controller?
No, but I believe the ISA bus pin which went to IRQ2 became the pin that went to IRQ9, so basically the IRQ was still there, just a different number now.
timers would simply not work: First, how do you "synch" them up in the first place?
Wait for vertical retrace, then start the timer.
Second, "chaos" rules and they'd go "out of synch"
The Programmable Interval Timer can be run in one-shot mode, where it simply waits the time you program it to, and then causes a single interrupt. So what you do is program it for a time before the vertical retrace (like maybe 500us before it), then go do something else. When the interrupt occurs, you watch for the vertical retrace. If it comes before that 500us, then next time you set the timer for a shorter interval, otherwise, you wait until the retrace, then set the timer for a longer interval. This way it stays synchronized, no matter what the retrace rate is, and even if it changes over time. Sure you're still doing some polling, but that way it's only using 3% of the CPU instead of 100%.
Also, how "healthy" is it to be "direct accessing" VGA hardware under Linux, anyhow? Being "multi-tasking" and the video a "shared resource", if you launch more than one program that tries the "direct access" to the video hardware, then does this cause some pretty nasty "conflicts"?
The kernel has some things placed in it just for X. (And I mean just for X, the comments in the source actually say things like "I'm not sure what this is supposed to do, but X seems to expect it to do this, so that's what we'll do.")
First you have to make sure the display is in a plain VGA mode. If you can open /dev/fb0, then you're in framebuffer mode, so you abort. If your stdin and stdout aren't pointing to a console TTY device, then you abort because you might be running in an xterm or over telnet or something.
Then you enter "graphics mode" which like everything in Linux is a misnomer. All this does is tell the kernel that when your console is active, it's not allowed to touch the VGA. It doesn't do anything else.
Then you tell the kernel that it's not allowed to switch consoles without your permission. So instead it'll send your program two signals, one when your console becomes active, and another when it wants to switch away from your console. It won't switch until you make a system call telling it that it's OK to do so.
Then you see what TTY you're running on, and if it's the currently active TTY, you read all of the VGA registers and memory and save them, and then replace them with what you want.
Later, when the user decides to switch consoles, the kernel sends you that signal. You then put the VGA device back like you found it, then tell the kernel it's OK to switch, and then it switches. Then you don't touch it while whatever else has it.
Later, the kernel tells you you're the active console again. So you once again save everything about the VGA device, and then put the VGA device in the mode you want it in, and start writing to it again.
Now it's not that simple, there's a lot of dumb *** and race conditions and crash protection you have to throw in there as well, otherwise you're going to have one flaky program that screws up the computer if the user does something as trivial as switch consoles too quickly, but it's certainly possible to do it without messing anything up. (Actually, it's just barely possible. Damn that kernel.)
This is what X and SVGAlib and everything else has to do to get graphics modes. The linux kernel is too good to have to do any sort of resource sharing for the video card, so any applications that want to use it just have to cooperate with eachother like that.
If anyone cares, the application under discussion here is here: http://xerse.nfshost.com/softer/
The email address I'm using is only good for another 8 days, then the domain it's on is going bye-bye. There's another address on my website, though.
.
- References:
- Polling loop good here???
- From: Frank Kotler
- Polling loop good here???
- Prev by Date: Re: f0dder's Fabulous Wait States.
- Next by Date: Re: f0dder's Fabulous Wait States.
- Previous by thread: Re: Polling loop good here???
- Next by thread: Webster hits 6,000,000!
- Index(es):