ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_vosf.h
(Generate patch)

Comparing BasiliskII/src/Unix/video_vosf.h (file contents):
Revision 1.22 by cebix, 2001-07-01T14:38:03Z vs.
Revision 1.29 by gbeauche, 2001-07-14T18:41:01Z

# Line 35 | Line 35
35  
36   // Variables for Video on SEGV support
37   static uint8 *the_host_buffer;  // Host frame buffer in VOSF mode
38 static uint32 the_buffer_size;  // Size of allocated the_buffer
38  
39   struct ScreenPageInfo {
40      int top, bottom;                    // Mapping between this virtual page and Mac scanlines
41   };
42  
43   struct ScreenInfo {
45    uintptr memBase;                    // Real start address
44      uintptr memStart;                   // Start address aligned to page boundary
47    uintptr memEnd;                             // Address of one-past-the-end of the screen
45      uint32 memLength;                   // Length of the memory addressed by the screen pages
46      
47 <    uint32 pageSize;                    // Size of a page
47 >    uintptr pageSize;                   // Size of a page
48      int pageBits;                               // Shift count to get the page number
49      uint32 pageCount;                   // Number of pages allocated to the screen
50      
# Line 161 | Line 158 | static uint32 page_extend(uint32 size)
158  
159  
160   /*
161 < *  Initialize mainBuffer structure
161 > *  Initialize the VOSF system (mainBuffer structure, SIGSEGV handler)
162   */
163  
164 < static bool video_init_buffer(void)
164 > static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
165 >
166 > static bool video_vosf_init(void)
167   {
168 <        if (use_vosf) {
169 <                const uint32 page_size  = getpagesize();
170 <                const uint32 page_mask  = page_size - 1;
168 >        const uintptr page_size = getpagesize();
169 >        const uintptr page_mask = page_size - 1;
170 >        
171 >        // Round up frame buffer base to page boundary
172 >        mainBuffer.memStart = (((uintptr) the_buffer) + page_mask) & ~page_mask;
173 >        
174 >        // The frame buffer size shall already be aligned to page boundary (use page_extend)
175 >        mainBuffer.memLength = the_buffer_size;
176 >        
177 >        mainBuffer.pageSize = page_size;
178 >        mainBuffer.pageBits = log_base_2(mainBuffer.pageSize);
179 >        mainBuffer.pageCount =  (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
180 >        
181 >        // The "2" more bytes requested are a safety net to insure the
182 >        // loops in the update routines will terminate.
183 >        // See "How can we deal with array overrun conditions ?" hereunder for further details.
184 >        mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
185 >        if (mainBuffer.dirtyPages == NULL)
186 >                return false;
187                  
188 <                mainBuffer.memBase      = (uintptr) the_buffer;
189 <                // Round up frame buffer base to page boundary
190 <                mainBuffer.memStart             = (uintptr)((((unsigned long) the_buffer) + page_mask) & ~page_mask);
191 <                mainBuffer.memLength    = the_buffer_size;
192 <                mainBuffer.memEnd       = mainBuffer.memStart + mainBuffer.memLength;
193 <
194 <                mainBuffer.pageSize     = page_size;
195 <                mainBuffer.pageCount    = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
196 <                mainBuffer.pageBits     = log_base_2(mainBuffer.pageSize);
197 <
198 <                if (mainBuffer.dirtyPages) {
199 <                        free(mainBuffer.dirtyPages);
200 <                        mainBuffer.dirtyPages = NULL;
201 <                }
202 <
203 <                mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
204 <
205 <                if (mainBuffer.pageInfo) {
206 <                        free(mainBuffer.pageInfo);
207 <                        mainBuffer.pageInfo = NULL;
208 <                }
188 >        PFLAG_CLEAR_ALL;
189 >        PFLAG_CLEAR(mainBuffer.pageCount);
190 >        PFLAG_SET(mainBuffer.pageCount+1);
191 >        
192 >        // Allocate and fill in pageInfo with start and end (inclusive) row in number of bytes
193 >        mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
194 >        if (mainBuffer.pageInfo == NULL)
195 >                return false;
196 >        
197 >        uint32 a = 0;
198 >        for (unsigned i = 0; i < mainBuffer.pageCount; i++) {
199 >                unsigned y1 = a / VideoMonitor.mode.bytes_per_row;
200 >                if (y1 >= VideoMonitor.mode.y)
201 >                        y1 = VideoMonitor.mode.y - 1;
202 >
203 >                unsigned y2 = (a + mainBuffer.pageSize) / VideoMonitor.mode.bytes_per_row;
204 >                if (y2 >= VideoMonitor.mode.y)
205 >                        y2 = VideoMonitor.mode.y - 1;
206 >
207 >                mainBuffer.pageInfo[i].top = y1;
208 >                mainBuffer.pageInfo[i].bottom = y2;
209 >
210 >                a += mainBuffer.pageSize;
211 >                if (a > mainBuffer.memLength)
212 >                        a = mainBuffer.memLength;
213 >        }
214 >        
215 >        // We can now write-protect the frame buffer
216 >        if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
217 >                return false;
218 >        
219 >        // Initialize the handler for SIGSEGV
220 >        if (!sigsegv_install_handler(screen_fault_handler))
221 >                return false;
222 >        
223 >        // The frame buffer is sane, i.e. there is no write to it yet
224 >        mainBuffer.dirty = false;
225 >        return true;
226 > }
227  
195                mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
228  
229 <                if ((mainBuffer.dirtyPages == NULL) || (mainBuffer.pageInfo == NULL))
230 <                        return false;
231 <                
200 <                mainBuffer.dirty = false;
229 > /*
230 > * Deinitialize VOSF system
231 > */
232  
233 <                PFLAG_CLEAR_ALL;
234 <                // Safety net to insure the loops in the update routines will terminate
235 <                // See "How can we deal with array overrun conditions ?" hereunder for further details
236 <                PFLAG_CLEAR(mainBuffer.pageCount);
237 <                PFLAG_SET(mainBuffer.pageCount+1);
238 <
239 <                uint32 a = 0;
240 <                for (int i = 0; i < mainBuffer.pageCount; i++) {
241 <                        int y1 = a / VideoMonitor.mode.bytes_per_row;
211 <                        if (y1 >= VideoMonitor.mode.y)
212 <                                y1 = VideoMonitor.mode.y - 1;
213 <
214 <                        int y2 = (a + mainBuffer.pageSize) / VideoMonitor.mode.bytes_per_row;
215 <                        if (y2 >= VideoMonitor.mode.y)
216 <                                y2 = VideoMonitor.mode.y - 1;
217 <
218 <                        mainBuffer.pageInfo[i].top = y1;
219 <                        mainBuffer.pageInfo[i].bottom = y2;
220 <
221 <                        a += mainBuffer.pageSize;
222 <                        if (a > mainBuffer.memLength)
223 <                                a = mainBuffer.memLength;
224 <                }
225 <                
226 <                // We can now write-protect the frame buffer
227 <                if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
228 <                        return false;
233 > static void video_vosf_exit(void)
234 > {
235 >        if (mainBuffer.pageInfo) {
236 >                free(mainBuffer.pageInfo);
237 >                mainBuffer.pageInfo = NULL;
238 >        }
239 >        if (mainBuffer.dirtyPages) {
240 >                free(mainBuffer.dirtyPages);
241 >                mainBuffer.dirtyPages = NULL;
242          }
230        return true;
243   }
244  
245  
# Line 237 | Line 249 | static bool video_init_buffer(void)
249  
250   static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
251   {
252 <        D(bug("screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", fault_address, fault_instruction));
252 > //      D(bug("screen_fault_handler: ADDR=%p from IP=%p\n", fault_address, fault_instruction));
253          const uintptr addr = (uintptr)fault_address;
254          
255          /* Someone attempted to write to the frame buffer. Make it writeable
256           * now so that the data could actually be written to. It will be made
257           * read-only back in one of the screen update_*() functions.
258           */
259 <        if ((addr >= mainBuffer.memStart) && (addr < mainBuffer.memEnd)) {
260 <                const int page  = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
249 <                caddr_t page_ad = (caddr_t)(addr & -mainBuffer.pageSize);
259 >        if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) {
260 >                const int page  = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits;
261                  LOCK_VOSF;
262                  PFLAG_SET(page);
263 <                vm_protect((char *)page_ad, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
263 >                vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
264                  mainBuffer.dirty = true;
265                  UNLOCK_VOSF;
266                  return true;
267          }
268          
269          /* Otherwise, we don't know how to handle the fault, let it crash */
270 <        fprintf(stderr, "do_handle_screen_fault: unhandled address 0x%08X", addr);
270 >        fprintf(stderr, "do_handle_screen_fault: unhandled address %p", fault_address);
271          if (fault_instruction != SIGSEGV_INVALID_PC)
272 <                fprintf(stderr, " [IP=0x%08X]", fault_instruction);
272 >                fprintf(stderr, " [IP=%p]", fault_instruction);
273          fprintf(stderr, "\n");
274   #if EMULATED_68K
275          uaecptr nextpc;
276          extern void m68k_dumpstate(uaecptr *nextpc);
277          m68k_dumpstate(&nextpc);
278   #endif
279 +        VideoQuitFullScreen();
280   #ifdef ENABLE_MON
281          char *arg[4] = {"mon", "-m", "-r", NULL};
282          mon(3, arg);
# Line 281 | Line 293 | static bool screen_fault_handler(sigsegv
293   // From video_blit.cpp
294   extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length);
295   extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth);
296 + extern uint32 ExpandMap[256];
297  
298   /*      How can we deal with array overrun conditions ?
299          
# Line 319 | Line 332 | static inline void update_display_window
332   {
333          int page = 0;
334          for (;;) {
335 <                const int first_page = find_next_page_set(page);
335 >                const unsigned first_page = find_next_page_set(page);
336                  if (first_page >= mainBuffer.pageCount)
337                          break;
338  
# Line 336 | Line 349 | static inline void update_display_window
349                  const int y2 = mainBuffer.pageInfo[page - 1].bottom;
350                  const int height = y2 - y1 + 1;
351                  
352 <                const int bytes_per_row = VideoMonitor.mode.bytes_per_row;
340 <                const int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x;
341 <                int i = y1 * bytes_per_row, j;
342 <                
343 <                if (VideoMonitor.mode.depth == VDEPTH_1BIT) {
352 >                if (VideoMonitor.mode.depth < VDEPTH_8BIT) {
353  
354                          // Update the_host_buffer and copy of the_buffer
355 +                        const int src_bytes_per_row = VideoMonitor.mode.bytes_per_row;
356 +                        const int dst_bytes_per_row = drv->img->bytes_per_line;
357 +                        const int pixels_per_byte = VideoMonitor.mode.x / src_bytes_per_row;
358 +                        int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
359                          for (j = y1; j <= y2; j++) {
360 <                                Screen_blit(the_host_buffer + i, the_buffer + i, VideoMonitor.mode.x >> 3);
361 <                                i += bytes_per_row;
360 >                                Screen_blit(the_host_buffer + i2, the_buffer + i1, VideoMonitor.mode.x / pixels_per_byte);
361 >                                i1 += src_bytes_per_row;
362 >                                i2 += dst_bytes_per_row;
363                          }
364  
365                  } else {
366  
367                          // Update the_host_buffer and copy of the_buffer
368 +                        const int src_bytes_per_row = VideoMonitor.mode.bytes_per_row;
369 +                        const int dst_bytes_per_row = drv->img->bytes_per_line;
370 +                        const int bytes_per_pixel = src_bytes_per_row / VideoMonitor.mode.x;
371 +                        int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
372                          for (j = y1; j <= y2; j++) {
373 <                                Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * VideoMonitor.mode.x);
374 <                                i += bytes_per_row;
373 >                                Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * VideoMonitor.mode.x);
374 >                                i1 += src_bytes_per_row;
375 >                                i2 += dst_bytes_per_row;
376                          }
377                  }
378  
# Line 376 | Line 395 | static inline void update_display_dga_vo
395   {
396          int page = 0;
397          for (;;) {
398 <                const int first_page = find_next_page_set(page);
398 >                const unsigned first_page = find_next_page_set(page);
399                  if (first_page >= mainBuffer.pageCount)
400                          break;
401  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines