viswapcontext.c 5.23 KB

/*====================================================================
 * viswapcontext.c
 *
 * Copyright 1995, Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
 * Inc.; the contents of this file may not be disclosed to third
 * parties, copied or duplicated in any form, in whole or in part,
 * without the prior written permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to
 * restrictions as set forth in subdivision (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS
 * 252.227-7013, and/or in similar or successor clauses in the FAR,
 * DOD or NASA FAR Supplement. Unpublished - rights reserved under the
 * Copyright Laws of the United States.
 *====================================================================*/

/**************************************************************************
 *
 *  $Revision: 1.1.1.2 $
 *  $Date: 2002/10/29 08:06:43 $
 *  $Source: /root/leakn64/depot/rf/sw/n64os20l/libultra/monegi/vi/viswapcontext.c,v $
 *
 **************************************************************************/


#include "osint.h"
#include "rcp.h"
#include "viint.h"
#include "assert.h"


/*
 * Name:   __osViSwapContext
 *
 * Description:
 *	Perform the actual VI context swap from the current to next context. 
 *	This is called by the VI manager thread upon receiving the vertical
 *	retrace interrupt (VRI). 
 *
 * Note:
 *	We assume that all the mode and attribute setting has been completed
 *	by the time this routine is called. Otherwise, garbage could be 
 *	displayed on the screen if VRI occurs while the __osViNext context is
 *	being manipulated. 
 *
 * Globals Referenced: 
 *	__osViCurr, __osViNext
 */
void
__osViSwapContext(void)
{

    register OSViMode 		*vm;
    register __OSViContext	*vc;
    u32				origin;
    u32				hStart;
    u32				vStart;
    u32				nomValue;
    u32				field = 0;

    /* 
     * In this routine, we don't bother to get the access token because we
     * assume that the user MUST complete the buffer swapping and mode setting 
     * by this time; otherwise, it's an error and garbage could be displayed on
     * the screen. We can but decide not to re-use the current context since
     * we want to let user know that we are experiencing graphics overrun.
     */

    vc = __osViNext;		/* We'll use the next VI context */
    vm = vc->modep;		/* Get pointer to the mode structure */

#ifdef _ULTRA64
    /*
     * Here, we reset vIntr field to 2 (in vitbl.c) to get the retrace 
     * interrupt right after vertical sync and in the correct field
     */
    field = IO_READ(VI_CURRENT_REG) & 0x01;	/* Get current field */

    /* Calculate the actual origin of the frame buffer */
    origin = osVirtualToPhysical(vc->framep) + vm->fldRegs[field].origin;
#endif

    /* Calculate the X-scale (if any) and adjust the origin accordingly */
    if (vc->state & VI_STATE_X_SCALE) {
        vc->x.scale |= (vm->comRegs.xScale & 0xFFFFF000);
    }
    else {
        vc->x.scale = vm->comRegs.xScale;
    }

    /* Calculate the Y-scale (if any) */
    if (vc->state & VI_STATE_Y_SCALE) {
        nomValue = vm->fldRegs[field].yScale & 0x0FFF;
        vc->y.scale = (u32)(vc->y.factor * (f32)nomValue);
        vc->y.scale |= (vm->fldRegs[field].yScale & 0xFFFFF000);
    }
    else {
        vc->y.scale = vm->fldRegs[field].yScale;
    }

    /* Calulate Vstart */
    vStart = vm->fldRegs[field].vStart - (__additional_scanline << 16)
      + __additional_scanline;

    hStart = vm->comRegs.hStart;

    /* Calculate the horizontal start (if black screen) */
    if (vc->state & VI_STATE_BLACK) {
        hStart = 0;
    }

    /* Repeat a line for the frame */
    if (vc->state & VI_STATE_REPEAT_LINE) {
        vc->y.scale = 0;
        origin = osVirtualToPhysical(vc->framep);
    }

    /* Fade between first 2 scan lines for the frame */
    if (vc->state & VI_STATE_FADE) {
        vc->y.scale = (u32)((vc->y.offset << 16) & 0x03FF0000);
        origin = osVirtualToPhysical(vc->framep);
    }

#ifdef _ULTRA64
    /* Update the hardware registers */
    IO_WRITE(VI_ORIGIN_REG,	origin);

    IO_WRITE(VI_WIDTH_REG,	vm->comRegs.width);
    IO_WRITE(VI_BURST_REG,	vm->comRegs.burst);
    IO_WRITE(VI_V_SYNC_REG,	vm->comRegs.vSync);
    IO_WRITE(VI_H_SYNC_REG,	vm->comRegs.hSync);
    IO_WRITE(VI_LEAP_REG,	vm->comRegs.leap);

    IO_WRITE(VI_H_START_REG,	hStart);
    IO_WRITE(VI_V_START_REG,	vStart);
    IO_WRITE(VI_V_BURST_REG,	vm->fldRegs[field].vBurst);
    IO_WRITE(VI_V_INTR_REG,	vm->fldRegs[field].vIntr);
    IO_WRITE(VI_X_SCALE_REG,	vc->x.scale);
    IO_WRITE(VI_Y_SCALE_REG,	vc->y.scale);
    IO_WRITE(VI_CONTROL_REG,	vc->control);	/* value set in osViSetMode */
#endif

    /*
     * Since this function is called by the VI manager thread (which runs
     * at a very high priority), we don't need to protect the 2 global VI
     * structures (i.e., __osViNext and __osViCurr).
     */
    /* 
     * Switch the two VI context "Next" and "Current" pointers
     */
    __osViNext = __osViCurr;
    __osViCurr = vc;

    /* 
     * Reset "Next" context to have same values as "Current" context at the 
     * beginning
     */
    *__osViNext = *__osViCurr;

}  /* __osViSwapContext */