Thanks for your quick feedback, I appreciate this.
Hans wrote:As a general rule, if you want smooth graphics without tearing, then you should use double-buffering. You can use true double-buffering via IIntuition->ChangeScreenBuffer(), or use vertical blanking interrupts and a blit from the back-buffer.
Ok.
The reason why I started with single buffering, was to keep the complexity and overhead down, especially as my blits moved so tiny, small areas of pixels. The graphics card should have no problems doing these operations during the vertical blanking period, before anything were displayed on the screen.
Double buffering wasn't something I wanted to use before absolutely necessary.
I have now added double buffering to my program using ChangeScreenBuffer(), but the scrolling still "refuse" to run perfect.
It runs smooth a second or 2 (it moves 1 pixel pr. WaitTOF), but suddenly it "freezes" 1/60th sec, and at the next frame it scrolls again (but 2 pixels instead of 1). After that it runs smooth for a while, then freezes and so on.
It doesn't matter if the scrolltext is far up on the screen, or at the bottom; the same thing happens each time (although, the time for when the "freezes" happens are random).
With single buffering, the freezes happens when placed high up on the screen, but not at the bottom.
I have tested the program without any other programs running at all (incl. Limpid Clock and CPUInfo), but the same thing happens.
I have tried with high task priority (+20), and even added a Forbid()-call (I know, I shouldn't use it. But I needed to test if it would help).
Nothing of this helped.
So; I suspect WaitTOF() isn't precise enough.
To check this, I have made a test program, where I measure how many microseconds it takes between each WaitTOF().
I am using ITimer->GetSysTime() for this, and the program prints the results in the shell after exit.
I have included the output from it at the bottom of this post.
What I see, is that within a period of 10 seconds, there are always a few "WaitTOF's" that takes either too long or too short time.
When I modify the testprogram to scroll parts of the screen, I see there is a connection between the "stalls" in the animation I see on the screen and the numbers in my list.
If you need the testprogram, just tell me, and I'll send it to you.
Hans wrote:AFAIK, Picasso96 doesn't support VBeamPos; that's a classic Amiga chipset thing.
Ok, I didn't know this. I believed this function returned the beam position regardless of the graphics hardware underneath.
Hans wrote:Are you sure that you are catching the VBL interrupt? I don't think that you even have access to the information required to know which interrupt to use. Plus, what if VBL interrupts are disabled? WaitTOF() and ChangeScreenBuffer() still work; your interrupt routine won't.
I am sure I have done it right according to how the vertical blanking interrupts should be setuped on the Classic.
But if things have changed in OS4 compared to the classic, there might of course be something I have overlooked.
The interrupt part of my program is "ported" from a program I have made on my classic Amiga, and is programmed according to what the ROM Kernel Ref. manuals says.
It works perfect on my Classic, and it works on OS4 (but not perfect. Some "tearing" every 3 seconds or so. That is, a horizontal "stripe" moving slowly in the vertical direction.).
Technically, the "intNum"-parameter passed to the AddIntServer, is INTB_VERTB.
The Interrupt structure's "ln_Type" passed to AddIntServer, is set to NT_INTERRUPT.
I wasn't aware of that vertical blanking interrupts in the OS ever could be disabled (it's enabled on my system, at least), as my thoughts were that any monitor needs some kind of a refresh on a given interval, even if the vertical blanking technique we know from the classic Amigas w/PAL/NTSC monitors not necessarily will be needed in certain setups.
Hans wrote:P.S. This message board also has a forums for developer topics. You'll see down the bottom of theindex page.
Ok. I'll have that in mind for the future, even if they are like this one (to address possible bugs).
// The list below shows how long intervals there is between each WaitTOF().
// I believe the correct duration in microseconds between 2 TOF's is: 1 000 000 / 60 = 16667 microsec.
// The "MicrosecDiff" shows the difference of the duration compared to the previous frame.
// When this number is too high, I see "freezes" in my animations on the screen.
// With frame, I mean each time the screen is refreshed. On my system, that is 1/60th second.
//
// Differences of several 1000's Microseconds are clearly visible as "freezes" in my screen scrolling.
// Differences less than 100 Microsecs are excluded from the list. as I don't expect them to do any "harm".
// CPU usage while running was 2-4%.
// PS: It seems like when 1 WaitTOF() takes longer than normal, the next one is shorter so the 2 in total consumes the expected time to "catch up".
// Test 1: Only TOF (no blitting etc.), 600 frames in total (10 seconds), task pri 0.
// No running programs in the background.
Frame #: 81, Microsec: 18070, MicrosecDiff: 1307
Frame #: 82, Microsec: 15460, MicrosecDiff: -2610
Frame #: 83, Microsec: 16770, MicrosecDiff: 1310
Frame #: 183, Microsec: 17392, MicrosecDiff: 628
Frame #: 184, Microsec: 16144, MicrosecDiff: -1248
Frame #: 185, Microsec: 16761, MicrosecDiff: 617
Frame #: 260, Microsec: 17240, MicrosecDiff: 472
Frame #: 261, Microsec: 16293, MicrosecDiff: -947
Frame #: 262, Microsec: 16767, MicrosecDiff: 474
Frame #: 558, Microsec: 21445, MicrosecDiff: 4673
Frame #: 559, Microsec: 12083, MicrosecDiff: -9362
Frame #: 560, Microsec: 16762, MicrosecDiff: 4679
// Test 2: Same test over again, but run with task priority +20
Frame #: 10, Microsec: 17377, MicrosecDiff: 615
Frame #: 11, Microsec: 16157, MicrosecDiff: -1220
Frame #: 12, Microsec: 16770, MicrosecDiff: 613
Frame #: 308, Microsec: 21586, MicrosecDiff: 4821
Frame #: 309, Microsec: 11949, MicrosecDiff: -9637
Frame #: 310, Microsec: 16770, MicrosecDiff: 4821
Frame #: 487, Microsec: 20853, MicrosecDiff: 4089
Frame #: 488, Microsec: 12678, MicrosecDiff: -8175
Frame #: 489, Microsec: 16766, MicrosecDiff: 4088
// Test 3: Same test, but with task pri 0
Frame #: 135, Microsec: 18039, MicrosecDiff: 1274
Frame #: 136, Microsec: 15497, MicrosecDiff: -2542
Frame #: 137, Microsec: 16758, MicrosecDiff: 1261
Frame #: 268, Microsec: 16687, MicrosecDiff: -159
Frame #: 314, Microsec: 17225, MicrosecDiff: 461
Frame #: 315, Microsec: 16314, MicrosecDiff: -911
Frame #: 316, Microsec: 16757, MicrosecDiff: 443