filename | src/pvr2/pvr2.c |
changeset | 304:2855cf8709a5 |
prev | 295:6637664291a8 |
next | 335:fb890e1814c0 |
author | nkeynes |
date | Sun Jan 21 11:28:43 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Enable blend by default - remove toggle on tex-alpha bit as its just plain wrong Implement UV clamping |
file | annotate | diff | log | raw |
1.1 --- a/src/pvr2/pvr2.c Tue Jan 16 10:34:46 2007 +00001.2 +++ b/src/pvr2/pvr2.c Sun Jan 21 11:28:43 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: pvr2.c,v 1.40 2007-01-16 10:34:46 nkeynes Exp $1.6 + * $Id: pvr2.c,v 1.41 2007-01-18 11:13:12 nkeynes Exp $1.7 *1.8 * PVR2 (Video) Core module implementation and MMIO registers.1.9 *1.10 @@ -30,14 +30,16 @@1.12 char *video_base;1.14 +#define HPOS_PER_FRAME 01.15 +#define HPOS_PER_LINECOUNT 11.16 +1.17 static void pvr2_init( void );1.18 static void pvr2_reset( void );1.19 static uint32_t pvr2_run_slice( uint32_t );1.20 static void pvr2_save_state( FILE *f );1.21 static int pvr2_load_state( FILE *f );1.22 static void pvr2_update_raster_posn( uint32_t nanosecs );1.23 -static void pvr2_schedule_line_event( int eventid, int line );1.24 -static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines );1.25 +static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines, int line_time_ns );1.26 uint32_t pvr2_get_sync_status();1.28 void pvr2_display_frame( void );1.29 @@ -66,6 +68,10 @@1.30 uint32_t line_count;1.31 uint32_t line_remainder;1.32 uint32_t cycles_run; /* Cycles already executed prior to main time slice */1.33 + uint32_t irq_hpos_line;1.34 + uint32_t irq_hpos_line_count;1.35 + uint32_t irq_hpos_mode;1.36 + uint32_t irq_hpos_time_ns; /* Time within the line */1.37 uint32_t irq_vpos1;1.38 uint32_t irq_vpos2;1.39 uint32_t odd_even_field; /* 1 = odd, 0 = even */1.40 @@ -89,12 +95,19 @@1.41 int video_buffer_idx = 0;1.43 /**1.44 - * Event handler for the retrace callback (fires on line 0 normally)1.45 + * Event handler for the hpos callback1.46 */1.47 -static void pvr2_retrace_callback( int eventid ) {1.48 +static void pvr2_hpos_callback( int eventid ) {1.49 asic_event( eventid );1.50 pvr2_update_raster_posn(sh4r.slice_cycle);1.51 - pvr2_schedule_line_event( EVENT_RETRACE, 0 );1.52 + if( pvr2_state.irq_hpos_mode == HPOS_PER_LINECOUNT ) {1.53 + pvr2_state.irq_hpos_line += pvr2_state.irq_hpos_line_count;1.54 + while( pvr2_state.irq_hpos_line > (pvr2_state.total_lines>>1) ) {1.55 + pvr2_state.irq_hpos_line -= (pvr2_state.total_lines>>1);1.56 + }1.57 + }1.58 + pvr2_schedule_scanline_event( eventid, pvr2_state.irq_hpos_line, 1,1.59 + pvr2_state.irq_hpos_time_ns );1.60 }1.62 /**1.63 @@ -105,9 +118,9 @@1.64 asic_event( eventid );1.65 pvr2_update_raster_posn(sh4r.slice_cycle);1.66 if( eventid == EVENT_SCANLINE1 ) {1.67 - pvr2_schedule_scanline_event( eventid, pvr2_state.irq_vpos1, 1 );1.68 + pvr2_schedule_scanline_event( eventid, pvr2_state.irq_vpos1, 1, 0 );1.69 } else {1.70 - pvr2_schedule_scanline_event( eventid, pvr2_state.irq_vpos2, 1 );1.71 + pvr2_schedule_scanline_event( eventid, pvr2_state.irq_vpos2, 1, 0 );1.72 }1.73 }1.75 @@ -116,7 +129,7 @@1.76 register_io_region( &mmio_region_PVR2 );1.77 register_io_region( &mmio_region_PVR2PAL );1.78 register_io_region( &mmio_region_PVR2TA );1.79 - register_event_callback( EVENT_RETRACE, pvr2_retrace_callback );1.80 + register_event_callback( EVENT_HPOS, pvr2_hpos_callback );1.81 register_event_callback( EVENT_SCANLINE1, pvr2_scanline_callback );1.82 register_event_callback( EVENT_SCANLINE2, pvr2_scanline_callback );1.83 video_base = mem_get_region_by_name( MEM_REGION_VIDEO );1.84 @@ -359,14 +372,36 @@1.85 break;1.86 case DISP_HPOSIRQ:1.87 MMIO_WRITE( PVR2, reg, val&0x03FF33FF );1.88 + pvr2_state.irq_hpos_line = val & 0x03FF;1.89 + pvr2_state.irq_hpos_time_ns = 2000000*((val>>16)&0x03FF)/pvr2_state.dot_clock;1.90 + pvr2_state.irq_hpos_mode = (val >> 12) & 0x03;1.91 + switch( pvr2_state.irq_hpos_mode ) {1.92 + case 3: /* Reserved - treat as 0 */1.93 + case 0: /* Once per frame at specified line */1.94 + pvr2_state.irq_hpos_mode = HPOS_PER_FRAME;1.95 + break;1.96 + case 2: /* Once per line - as per-line-count */1.97 + pvr2_state.irq_hpos_line = 1;1.98 + pvr2_state.irq_hpos_mode = 1;1.99 + case 1: /* Once per N lines */1.100 + pvr2_state.irq_hpos_line_count = pvr2_state.irq_hpos_line;1.101 + pvr2_state.irq_hpos_line = (pvr2_state.line_count >> 1) +1.102 + pvr2_state.irq_hpos_line_count;1.103 + while( pvr2_state.irq_hpos_line > (pvr2_state.total_lines>>1) ) {1.104 + pvr2_state.irq_hpos_line -= (pvr2_state.total_lines>>1);1.105 + }1.106 + pvr2_state.irq_hpos_mode = HPOS_PER_LINECOUNT;1.107 + }1.108 + pvr2_schedule_scanline_event( EVENT_HPOS, pvr2_state.irq_hpos_line, 0,1.109 + pvr2_state.irq_hpos_time_ns );1.110 break;1.111 case DISP_VPOSIRQ:1.112 val = val & 0x03FF03FF;1.113 pvr2_state.irq_vpos1 = (val >> 16);1.114 pvr2_state.irq_vpos2 = val & 0x03FF;1.115 pvr2_update_raster_posn(sh4r.slice_cycle);1.116 - pvr2_schedule_scanline_event( EVENT_SCANLINE1, pvr2_state.irq_vpos1, 0 );1.117 - pvr2_schedule_scanline_event( EVENT_SCANLINE2, pvr2_state.irq_vpos2, 0 );1.118 + pvr2_schedule_scanline_event( EVENT_SCANLINE1, pvr2_state.irq_vpos1, 0, 0 );1.119 + pvr2_schedule_scanline_event( EVENT_SCANLINE2, pvr2_state.irq_vpos2, 0, 0 );1.120 MMIO_WRITE( PVR2, reg, val );1.121 break;1.122 case RENDER_NEARCLIP:1.123 @@ -431,9 +466,10 @@1.124 pvr2_state.line_time_ns = 1000000 * pvr2_state.line_size / pvr2_state.dot_clock;1.125 pvr2_state.retrace_end_line = 0x2A;1.126 pvr2_state.retrace_start_line = pvr2_state.total_lines - 6;1.127 - pvr2_schedule_line_event( EVENT_RETRACE, 0 );1.128 - pvr2_schedule_scanline_event( EVENT_SCANLINE1, pvr2_state.irq_vpos1, 0 );1.129 - pvr2_schedule_scanline_event( EVENT_SCANLINE2, pvr2_state.irq_vpos2, 0 );1.130 + pvr2_schedule_scanline_event( EVENT_SCANLINE1, pvr2_state.irq_vpos1, 0, 0 );1.131 + pvr2_schedule_scanline_event( EVENT_SCANLINE2, pvr2_state.irq_vpos2, 0, 0 );1.132 + pvr2_schedule_scanline_event( EVENT_HPOS, pvr2_state.irq_hpos_line, 0,1.133 + pvr2_state.irq_hpos_time_ns );1.134 break;1.135 case DISP_SYNCCFG:1.136 MMIO_WRITE( PVR2, reg, val&0x000003FF );1.137 @@ -571,40 +607,25 @@1.138 }1.140 /**1.141 - * Schedule an event for the start of the given line. If the line is actually1.142 - * the current line, schedules it for the next field.1.143 - * The raster position should be updated before calling this method.1.144 - */1.145 -static void pvr2_schedule_line_event( int eventid, int line )1.146 -{1.147 - uint32_t time;1.148 - if( line <= pvr2_state.line_count ) {1.149 - time = (pvr2_state.total_lines - pvr2_state.line_count + line) * pvr2_state.line_time_ns1.150 - - pvr2_state.line_remainder;1.151 - } else {1.152 - time = (line - pvr2_state.line_count) * pvr2_state.line_time_ns - pvr2_state.line_remainder;1.153 - }1.154 -1.155 - if( line < pvr2_state.total_lines ) {1.156 - event_schedule( eventid, time );1.157 - } else {1.158 - event_cancel( eventid );1.159 - }1.160 -}1.161 -1.162 -/**1.163 * Schedule a "scanline" event. This actually goes off at1.164 * 2 * line in even fields and 2 * line + 1 in odd fields.1.165 * Otherwise this behaves as per pvr2_schedule_line_event().1.166 * The raster position should be updated before calling this1.167 * method.1.168 + * @param eventid Event to fire at the specified time1.169 + * @param line Line on which to fire the event (this is 2n/2n+1 for interlaced1.170 + * displays).1.171 + * @param hpos_ns Nanoseconds into the line at which to fire.1.172 */1.173 -static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines )1.174 +static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines, int hpos_ns )1.175 {1.176 uint32_t field = pvr2_state.odd_even_field;1.177 if( line <= pvr2_state.line_count && pvr2_state.interlaced ) {1.178 field = !field;1.179 }1.180 + if( hpos_ns > pvr2_state.line_time_ns ) {1.181 + hpos_ns = pvr2_state.line_time_ns;1.182 + }1.184 line <<= 1;1.185 if( field ) {1.186 @@ -622,7 +643,7 @@1.187 if( lines <= minimum_lines ) {1.188 lines += pvr2_state.total_lines;1.189 }1.190 - time = (lines * pvr2_state.line_time_ns) - pvr2_state.line_remainder;1.191 + time = (lines * pvr2_state.line_time_ns) - pvr2_state.line_remainder + hpos_ns;1.192 event_schedule( eventid, time );1.193 } else {1.194 event_cancel( eventid );
.