Jump to content
IGNORED

How to avoid "screen tearing"


DZ-Jay

Recommended Posts

Here is a little context on how the mechanisms used to update the BACKTAB affect video composition.  In my opinion, understanding how the underlying hardware works can help address common problems by accounting for the limitations and behaviours of the system.


What Is Screen Tearing?

When large portions of the background scene need to be updated at once, say, for scrolling effects or other transitions, care should be taken to ensure that they happen consistently within a video frame.

 

Screen tearing is an anomalous effect whereas the screen is not updated completely or consistently, resulting in parts of the screen receiving the update, and other parts remaining in their previous state.  To the user, it looks like a video glitch or a jerky transition.

 

This effect is more noticeable during scrolling, giving the impression that parts of the screen are tearing themselves to one side, while the rest remains in place, hence the name.


Vertical Banking

At the start of each video frame -- right during Vertical Blanking (VBLANK), i.e., when the TV raster finishes one frame and is resetting back to the top to draw the next one -- an interrupt signal is sent to the CPU to give it a chance to update graphics RAM and other graphics elements like sprite registers and color modes.

 

IntyBASIC will handle the interrupt request for you, so you do not have to worry too much about it.  Just understand that the VBLANK interrupt represents to the hardware the start of the video frame composition.

 

This is what the WAIT statement does:  it tells IntyBASIC, I am done with the software side of video composition (i.e., game logic and state updates), so wait until the next interrupt to give the hardware a chance to do its part and draw the video frame.

 

The IntyBASIC interrupt handler takes care of "posting" all sprite and GRAM changes and such to the hardware, then returns control to your program.  You can consider the WAIT statement as your program's cue that a new game frame has started.

 

Background Table Buffering

The Intellivision video chip, the STIC, has an internal buffer that it uses to compose the video frame.  It populates it first by copying the Background Table (BACKTAB), then compositing sprites and other things on top.

 

The video buffer is loaded one background row at a time.  This starts shortly after the VBLANK interrupt.  The STIC waits a little bit after, then starts issuing regular interruptions to the CPU to load each row.  These requests are completely invisible to your program, and happen automatically at the hardware level.

 

The STIC buffer requests happen in "real time," while your program is executing.  It means that your program should update each BACKTAB row and have it ready by the time the STIC queries for it.  The entire BACKTAB doesn't have to be ready at once -- you just need to make sure that your updates keep ahead of the STIC buffer queries.

 

As mentioned before, your program has no control over the timing of the requests, and no visibility of when and how the STIC fetches each row during your program execution.

 

However there are a few things that we do know about how the hardware works, and we can use this insight to take advantage of the interaction:

  • The STIC buffer fetches each row on a regular schedule, so the timing is mostly deterministic (within some minor margin of tolerance to account for CPU response latency).
  • The fetch cycle always start at roughly the same point after the VBLANK interrupt, again making it mostly deterministic.
  • Rows are fetched occur from top to bottom, reading the BACKTAB in order.
  • The time between fetching one row and the next, is sufficient to allow the CPU to block-copy at least one full row, and be ready for the next one before the STIC gets to it.
  • The STIC will fetch one row at a time, and never look back until it does it again on the next frame.  This means that if a particular row was not updated by the time it is fetched, it will be missed and read as is.  This can lead to screen inconsistencies (i.e., tearing and shearing) because some rows may be updated and not others.

And there is one other very important point as well that is sometimes missed:

  • If the CPU is busy executing non-interruptible operations, and the sequence of these operations is long enough, the STIC buffer interrupt request may not get a chance to copy the next row.  When this happens, the row data from the previous frame will be used.  Once again, this may lead to visual glitches due to screen inconsistencies.

 

In IntyBASIC this may not be much of a problem since the compiler tries to avoid such long sequences of non-interruptible operations; but it is something to be aware of.

 

 

Recommendations

What all this means is that if you need to update large portions of the screen background at once, the best way to ensure it is done in one frame is to:

  • Start as early in the frame as possible, preferably right after the WAIT statement, which indicates a brand new frame has just started.
  • Copy BACKTAB data in row order, from top to bottom, left to right.
  • Make sure the copy cycle is fast enough to keep the program ahead of the STIC fetches

 

I hope this proves informative. :)

 

    dZ.

 

Edited by DZ-Jay
  • Like 1
  • Thanks 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...