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.20 by gbeauche, 2001-06-28T22:06:18Z vs.
Revision 1.31 by cebix, 2002-04-25T11:00:31Z

# Line 1 | Line 1
1   /*
2   *  video_vosf.h - Video/graphics emulation, video on SEGV signals support
3   *
4 < *  Basilisk II (C) 1997-2001 Christian Bauer
4 > *  Basilisk II (C) 1997-2002 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# 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)
168 < {
169 <        if (use_vosf) {
170 <                const uint32 page_size  = getpagesize();
171 <                const uint32 page_mask  = page_size - 1;
172 <                
173 <                mainBuffer.memBase      = (uintptr) the_buffer;
174 <                // Round up frame buffer base to page boundary
175 <                mainBuffer.memStart             = (uintptr)((((unsigned long) the_buffer) + page_mask) & ~page_mask);
176 <                mainBuffer.memLength    = the_buffer_size;
177 <                mainBuffer.memEnd       = mainBuffer.memStart + mainBuffer.memLength;
178 <
179 <                mainBuffer.pageSize     = page_size;
180 <                mainBuffer.pageCount    = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
181 <                mainBuffer.pageBits     = log_base_2(mainBuffer.pageSize);
182 <
183 <                if (mainBuffer.dirtyPages) {
184 <                        free(mainBuffer.dirtyPages);
185 <                        mainBuffer.dirtyPages = NULL;
186 <                }
164 > static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
165  
166 <                mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
166 > static bool video_vosf_init(X11_monitor_desc &monitor)
167 > {
168 >        const video_mode &mode = monitor.get_current_mode();
169  
170 <                if (mainBuffer.pageInfo) {
171 <                        free(mainBuffer.pageInfo);
172 <                        mainBuffer.pageInfo = NULL;
173 <                }
170 >        const uintptr page_size = getpagesize();
171 >        const uintptr page_mask = page_size - 1;
172 >        
173 >        // Round up frame buffer base to page boundary
174 >        mainBuffer.memStart = (((uintptr) the_buffer) + page_mask) & ~page_mask;
175 >        
176 >        // The frame buffer size shall already be aligned to page boundary (use page_extend)
177 >        mainBuffer.memLength = the_buffer_size;
178 >        
179 >        mainBuffer.pageSize = page_size;
180 >        mainBuffer.pageBits = log_base_2(mainBuffer.pageSize);
181 >        mainBuffer.pageCount =  (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
182 >        
183 >        // The "2" more bytes requested are a safety net to insure the
184 >        // loops in the update routines will terminate.
185 >        // See "How can we deal with array overrun conditions ?" hereunder for further details.
186 >        mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
187 >        if (mainBuffer.dirtyPages == NULL)
188 >                return false;
189 >                
190 >        PFLAG_CLEAR_ALL;
191 >        PFLAG_CLEAR(mainBuffer.pageCount);
192 >        PFLAG_SET(mainBuffer.pageCount+1);
193 >        
194 >        // Allocate and fill in pageInfo with start and end (inclusive) row in number of bytes
195 >        mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
196 >        if (mainBuffer.pageInfo == NULL)
197 >                return false;
198 >        
199 >        uint32 a = 0;
200 >        for (unsigned i = 0; i < mainBuffer.pageCount; i++) {
201 >                unsigned y1 = a / mode.bytes_per_row;
202 >                if (y1 >= mode.y)
203 >                        y1 = mode.y - 1;
204 >
205 >                unsigned y2 = (a + mainBuffer.pageSize) / mode.bytes_per_row;
206 >                if (y2 >= mode.y)
207 >                        y2 = mode.y - 1;
208 >
209 >                mainBuffer.pageInfo[i].top = y1;
210 >                mainBuffer.pageInfo[i].bottom = y2;
211 >
212 >                a += mainBuffer.pageSize;
213 >                if (a > mainBuffer.memLength)
214 >                        a = mainBuffer.memLength;
215 >        }
216 >        
217 >        // We can now write-protect the frame buffer
218 >        if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
219 >                return false;
220 >        
221 >        // Initialize the handler for SIGSEGV
222 >        if (!sigsegv_install_handler(screen_fault_handler))
223 >                return false;
224 >        
225 >        // The frame buffer is sane, i.e. there is no write to it yet
226 >        mainBuffer.dirty = false;
227 >        return true;
228 > }
229  
195                mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
230  
231 <                if ((mainBuffer.dirtyPages == 0) || (mainBuffer.pageInfo == 0))
232 <                        return false;
233 <                
200 <                mainBuffer.dirty = false;
231 > /*
232 > * Deinitialize VOSF system
233 > */
234  
235 <                PFLAG_CLEAR_ALL;
236 <                // Safety net to insure the loops in the update routines will terminate
237 <                // See "How can we deal with array overrun conditions ?" hereunder for further details
238 <                PFLAG_CLEAR(mainBuffer.pageCount);
239 <                PFLAG_SET(mainBuffer.pageCount+1);
240 <
241 <                uint32 a = 0;
242 <                for (int i = 0; i < mainBuffer.pageCount; i++) {
243 <                        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;
235 > static void video_vosf_exit(void)
236 > {
237 >        if (mainBuffer.pageInfo) {
238 >                free(mainBuffer.pageInfo);
239 >                mainBuffer.pageInfo = NULL;
240 >        }
241 >        if (mainBuffer.dirtyPages) {
242 >                free(mainBuffer.dirtyPages);
243 >                mainBuffer.dirtyPages = NULL;
244          }
230        return true;
245   }
246  
247  
# Line 237 | Line 251 | static bool video_init_buffer(void)
251  
252   static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
253   {
254 <        D(bug("screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", fault_address, fault_instruction));
254 > //      D(bug("screen_fault_handler: ADDR=%p from IP=%p\n", fault_address, fault_instruction));
255          const uintptr addr = (uintptr)fault_address;
256          
257          /* Someone attempted to write to the frame buffer. Make it writeable
258           * now so that the data could actually be written to. It will be made
259           * read-only back in one of the screen update_*() functions.
260           */
261 <        if ((addr >= mainBuffer.memStart) && (addr < mainBuffer.memEnd)) {
262 <                const int page  = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
249 <                caddr_t page_ad = (caddr_t)(addr & -mainBuffer.pageSize);
261 >        if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) {
262 >                const int page  = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits;
263                  LOCK_VOSF;
264                  PFLAG_SET(page);
265 <                vm_protect((char *)page_ad, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
265 >                vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
266                  mainBuffer.dirty = true;
267                  UNLOCK_VOSF;
268                  return true;
269          }
270          
271          /* Otherwise, we don't know how to handle the fault, let it crash */
272 <        fprintf(stderr, "do_handle_screen_fault: unhandled address 0x%08X", addr);
272 >        fprintf(stderr, "do_handle_screen_fault: unhandled address %p", fault_address);
273          if (fault_instruction != SIGSEGV_INVALID_PC)
274 <                fprintf(stderr, " [IP=0x%08X]", fault_instruction);
274 >                fprintf(stderr, " [IP=%p]", fault_instruction);
275          fprintf(stderr, "\n");
276   #if EMULATED_68K
277          uaecptr nextpc;
278          extern void m68k_dumpstate(uaecptr *nextpc);
279          m68k_dumpstate(&nextpc);
280   #endif
281 +        VideoQuitFullScreen();
282   #ifdef ENABLE_MON
283          char *arg[4] = {"mon", "-m", "-r", NULL};
284          mon(3, arg);
# Line 280 | Line 294 | static bool screen_fault_handler(sigsegv
294  
295   // From video_blit.cpp
296   extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length);
297 < extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order);
297 > extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth);
298 > extern uint32 ExpandMap[256];
299  
300   /*      How can we deal with array overrun conditions ?
301          
# Line 315 | Line 330 | There are two cases to check:
330          than pageCount.
331   */
332  
333 < static inline void update_display_window_vosf(void)
333 > static inline void update_display_window_vosf(driver_window *drv)
334   {
335 +        const video_mode &mode = drv->monitor.get_current_mode();
336 +
337          int page = 0;
338          for (;;) {
339 <                const int first_page = find_next_page_set(page);
339 >                const unsigned first_page = find_next_page_set(page);
340                  if (first_page >= mainBuffer.pageCount)
341                          break;
342  
# Line 336 | Line 353 | static inline void update_display_window
353                  const int y2 = mainBuffer.pageInfo[page - 1].bottom;
354                  const int height = y2 - y1 + 1;
355                  
356 <                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) {
356 >                if (mode.depth < VDEPTH_8BIT) {
357  
358                          // Update the_host_buffer and copy of the_buffer
359 +                        const int src_bytes_per_row = mode.bytes_per_row;
360 +                        const int dst_bytes_per_row = drv->img->bytes_per_line;
361 +                        const int pixels_per_byte = mode.x / src_bytes_per_row;
362 +                        int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
363                          for (j = y1; j <= y2; j++) {
364 <                                Screen_blit(the_host_buffer + i, the_buffer + i, VideoMonitor.mode.x >> 3);
365 <                                i += bytes_per_row;
364 >                                Screen_blit(the_host_buffer + i2, the_buffer + i1, mode.x / pixels_per_byte);
365 >                                i1 += src_bytes_per_row;
366 >                                i2 += dst_bytes_per_row;
367                          }
368  
369                  } else {
370  
371                          // Update the_host_buffer and copy of the_buffer
372 +                        const int src_bytes_per_row = mode.bytes_per_row;
373 +                        const int dst_bytes_per_row = drv->img->bytes_per_line;
374 +                        const int bytes_per_pixel = src_bytes_per_row / mode.x;
375 +                        int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
376                          for (j = y1; j <= y2; j++) {
377 <                                Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * VideoMonitor.mode.x);
378 <                                i += bytes_per_row;
377 >                                Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * mode.x);
378 >                                i1 += src_bytes_per_row;
379 >                                i2 += dst_bytes_per_row;
380                          }
381                  }
382  
383 <                if (have_shm)
384 <                        XShmPutImage(x_display, the_win, the_gc, img, 0, y1, 0, y1, VideoMonitor.mode.x, height, 0);
383 >                if (drv->have_shm)
384 >                        XShmPutImage(x_display, drv->w, drv->gc, drv->img, 0, y1, 0, y1, mode.x, height, 0);
385                  else
386 <                        XPutImage(x_display, the_win, the_gc, img, 0, y1, 0, y1, VideoMonitor.mode.x, height);
386 >                        XPutImage(x_display, drv->w, drv->gc, drv->img, 0, y1, 0, y1, mode.x, height);
387          }
388          mainBuffer.dirty = false;
389   }
# Line 374 | Line 397 | static inline void update_display_window
397   #if REAL_ADDRESSING || DIRECT_ADDRESSING
398   static inline void update_display_dga_vosf(void)
399   {
400 +        const video_mode &mode = drv->monitor.get_current_mode();
401 +
402          int page = 0;
403          for (;;) {
404 <                const int first_page = find_next_page_set(page);
404 >                const unsigned first_page = find_next_page_set(page);
405                  if (first_page >= mainBuffer.pageCount)
406                          break;
407  
# Line 392 | Line 417 | static inline void update_display_dga_vo
417                  const int y1 = mainBuffer.pageInfo[first_page].top;
418                  const int y2 = mainBuffer.pageInfo[page - 1].bottom;
419                  
420 <                const int bytes_per_row = VideoMonitor.mode.bytes_per_row;
421 <                const int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x;
420 >                const int bytes_per_row = mode.bytes_per_row;
421 >                const int bytes_per_pixel = mode.bytes_per_row / mode.x;
422                  int i, j;
423                  
424                  // Check for first column from left and first column
425                  // from right that have changed
426 <                int x1 = VideoMonitor.mode.x * bytes_per_pixel - 1;
426 >                int x1 = mode.x * bytes_per_pixel - 1;
427                  for (j = y1; j <= y2; j++) {
428                          uint8 * const p1 = &the_buffer[j * bytes_per_row];
429                          uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
# Line 415 | Line 440 | static inline void update_display_dga_vo
440                  for (j = y2; j >= y1; j--) {
441                          uint8 * const p1 = &the_buffer[j * bytes_per_row];
442                          uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
443 <                        for (i = VideoMonitor.mode.x * bytes_per_pixel - 1; i > x2; i--) {
443 >                        for (i = mode.x * bytes_per_pixel - 1; i > x2; i--) {
444                                  if (p1[i] != p2[i]) {
445                                          x2 = i;
446                                          break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines