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

Comparing BasiliskII/src/Unix/video_x.cpp (file contents):
Revision 1.31 by cebix, 2000-11-30T16:09:03Z vs.
Revision 1.38 by gbeauche, 2001-05-20T20:31:50Z

# Line 1 | Line 1
1   /*
2   *  video_x.cpp - Video/graphics emulation, X11 specific stuff
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2001 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 53 | Line 53
53   #endif
54  
55   #ifdef ENABLE_VOSF
56 # include <unistd.h>
57 # include <signal.h>
56   # include <fcntl.h>
57   # include <sys/mman.h>
58 + # include "sigsegv.h"
59   #endif
60  
61   #include "cpu_emulation.h"
# Line 197 | Line 196 | struct ScreenInfo {
196      int pageBits;                               // Shift count to get the page number
197      uint32 pageCount;                   // Number of pages allocated to the screen
198      
199 <    uint8 * dirtyPages;                 // Table of flags set if page was altered
199 >        bool dirty;                                     // Flag: set if the frame buffer was touched
200 >    char * dirtyPages;                  // Table of flags set if page was altered
201      ScreenPageInfo * pageInfo;  // Table of mappings page -> Mac scanlines
202   };
203  
204   static ScreenInfo mainBuffer;
205  
206 < #define PFLAG_SET(page)                 mainBuffer.dirtyPages[page] = 1
207 < #define PFLAG_CLEAR(page)               mainBuffer.dirtyPages[page] = 0
208 < #define PFLAG_ISSET(page)               mainBuffer.dirtyPages[page]
209 < #define PFLAG_ISCLEAR(page)             (mainBuffer.dirtyPages[page] == 0)
206 > #define PFLAG_SET_VALUE                 0x00
207 > #define PFLAG_CLEAR_VALUE               0x01
208 > #define PFLAG_SET_VALUE_4               0x00000000
209 > #define PFLAG_CLEAR_VALUE_4             0x01010101
210 > #define PFLAG_SET(page)                 mainBuffer.dirtyPages[page] = PFLAG_SET_VALUE
211 > #define PFLAG_CLEAR(page)               mainBuffer.dirtyPages[page] = PFLAG_CLEAR_VALUE
212 > #define PFLAG_ISSET(page)               (mainBuffer.dirtyPages[page] == PFLAG_SET_VALUE)
213 > #define PFLAG_ISCLEAR(page)             (mainBuffer.dirtyPages[page] != PFLAG_SET_VALUE)
214 >
215   #ifdef UNALIGNED_PROFITABLE
216 < # define PFLAG_ISCLEAR_4(page)  (*((uint32 *)(mainBuffer.dirtyPages + page)) == 0)
216 > # define PFLAG_ISSET_4(page)    (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_SET_VALUE_4)
217 > # define PFLAG_ISCLEAR_4(page)  (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_CLEAR_VALUE_4)
218 > #else
219 > # define PFLAG_ISSET_4(page) \
220 >                PFLAG_ISSET(page  ) && PFLAG_ISSET(page+1) \
221 >        &&      PFLAG_ISSET(page+2) && PFLAG_ISSET(page+3)
222 > # define PFLAG_ISCLEAR_4(page) \
223 >                PFLAG_ISCLEAR(page  ) && PFLAG_ISCLEAR(page+1) \
224 >        &&      PFLAG_ISCLEAR(page+2) && PFLAG_ISCLEAR(page+3)
225 > #endif
226 >
227 > // Set the selected page range [ first_page, last_page [ into the SET state
228 > #define PFLAG_SET_RANGE(first_page, last_page) \
229 >        memset(mainBuffer.dirtyPages + (first_page), PFLAG_SET_VALUE, \
230 >                (last_page) - (first_page))
231 >
232 > // Set the selected page range [ first_page, last_page [ into the CLEAR state
233 > #define PFLAG_CLEAR_RANGE(first_page, last_page) \
234 >        memset(mainBuffer.dirtyPages + (first_page), PFLAG_CLEAR_VALUE, \
235 >                (last_page) - (first_page))
236 >
237 > #define PFLAG_SET_ALL do { \
238 >        PFLAG_SET_RANGE(0, mainBuffer.pageCount); \
239 >        mainBuffer.dirty = true; \
240 > } while (0)
241 >
242 > #define PFLAG_CLEAR_ALL do { \
243 >        PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount); \
244 >        mainBuffer.dirty = false; \
245 > } while (0)
246 >
247 > // Set the following macro definition to 1 if your system
248 > // provides a really fast strchr() implementation
249 > //#define HAVE_FAST_STRCHR 0
250 >
251 > static inline int find_next_page_set(int page)
252 > {
253 > #if HAVE_FAST_STRCHR
254 >        char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_SET_VALUE);
255 >        return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount;
256   #else
257 < # define PFLAG_ISCLEAR_4(page)  \
258 <                (mainBuffer.dirtyPages[page  ] == 0) \
259 <        &&      (mainBuffer.dirtyPages[page+1] == 0) \
260 <        &&      (mainBuffer.dirtyPages[page+2] == 0) \
261 <        &&      (mainBuffer.dirtyPages[page+3] == 0)
257 >        while (PFLAG_ISCLEAR_4(page))
258 >                page += 4;
259 >        while (PFLAG_ISCLEAR(page))
260 >                page++;
261 >        return page;
262   #endif
263 < #define PFLAG_CLEAR_ALL                 memset(mainBuffer.dirtyPages, 0, mainBuffer.pageCount)
264 < #define PFLAG_SET_ALL                   memset(mainBuffer.dirtyPages, 1, mainBuffer.pageCount)
263 > }
264 >
265 > static inline int find_next_page_clear(int page)
266 > {
267 > #if HAVE_FAST_STRCHR
268 >        char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_CLEAR_VALUE);
269 >        return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount;
270 > #else
271 >        while (PFLAG_ISSET_4(page))
272 >                page += 4;
273 >        while (PFLAG_ISSET(page))
274 >                page++;
275 >        return page;
276 > #endif
277 > }
278  
279   static int zero_fd = -1;
223 static bool Screen_fault_handler_init();
224 static struct sigaction vosf_sa;
280  
281   #ifdef HAVE_PTHREADS
282   static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer (dirtyPages in fact)
# Line 242 | Line 297 | static int log_base_2(uint32 x)
297          }
298          return l;
299   }
300 <
246 < #endif
300 > #endif /* ENABLE_VOSF */
301  
302   // VideoRefresh function
303   void VideoRefreshInit(void);
# Line 334 | Line 388 | static void set_window_name(Window w, in
388                  hints->res_name = "BasiliskII";
389                  hints->res_class = "BasiliskII";
390                  XSetClassHint(x_display, w, hints);
391 <                XFree((char *)hints);
391 >                XFree(hints);
392          }
393   }
394  
# Line 347 | Line 401 | static void set_window_focus(Window w)
401                  hints->initial_state = NormalState;
402                  hints->flags = InputHint | StateHint;
403                  XSetWMHints(x_display, w, hints);
404 <                XFree((char *)hints);
404 >                XFree(hints);
405          }
406   }
407  
# Line 428 | Line 482 | static bool init_window(int width, int h
482                          hints->max_height = height;
483                          hints->flags = PMinSize | PMaxSize;
484                          XSetWMNormalHints(x_display, the_win, hints);
485 <                        XFree((char *)hints);
485 >                        XFree(hints);
486                  }
487          }
488          
# Line 523 | Line 577 | static bool init_window(int width, int h
577          native_byte_order = (XImageByteOrder(x_display) == LSBFirst);
578   #endif
579   #ifdef ENABLE_VOSF
580 <        do_update_framebuffer = GET_FBCOPY_FUNC(depth, native_byte_order, DISPLAY_WINDOW);
580 >        Screen_blitter_init(&visualInfo, native_byte_order);
581   #endif
582          set_video_monitor(width, height, img->bytes_per_line, native_byte_order);
583          
# Line 662 | Line 716 | static bool init_fbdev_dga(char *in_fb_n
716          
717   #if ENABLE_VOSF
718   #if REAL_ADDRESSING || DIRECT_ADDRESSING
719 <        // If the blit function is null, i.e. just a copy of the buffer,
720 <        // we first try to avoid the allocation of a temporary frame buffer
721 <        use_vosf = true;
668 <        do_update_framebuffer = GET_FBCOPY_FUNC(depth, true, DISPLAY_DGA);
669 <        if (do_update_framebuffer == FBCOPY_FUNC(fbcopy_raw))
670 <                use_vosf = false;
719 >        // Screen_blitter_init() returns TRUE if VOSF is mandatory
720 >        // i.e. the framebuffer update function is not Blit_Copy_Raw
721 >        use_vosf = Screen_blitter_init(&visualInfo, true);
722          
723          if (use_vosf) {
724                  the_host_buffer = the_buffer;
# Line 772 | Line 823 | static bool init_xf86_dga(int width, int
823          }
824          
825   #if REAL_ADDRESSING || DIRECT_ADDRESSING
826 <        // If the blit function is null, i.e. just a copy of the buffer,
827 <        // we first try to avoid the allocation of a temporary frame buffer
828 <        use_vosf = true;
778 <        do_update_framebuffer = GET_FBCOPY_FUNC(depth, true, DISPLAY_DGA);
779 <        if (do_update_framebuffer == FBCOPY_FUNC(fbcopy_raw))
780 <                use_vosf = false;
826 >        // Screen_blitter_init() returns TRUE if VOSF is mandatory
827 >        // i.e. the framebuffer update function is not Blit_Copy_Raw
828 >        use_vosf = Screen_blitter_init(&visualInfo, true);
829          
830          if (use_vosf) {
831                  the_host_buffer = the_buffer;
# Line 891 | Line 939 | bool VideoInitBuffer()
939                  if (mainBuffer.dirtyPages != 0)
940                          free(mainBuffer.dirtyPages);
941  
942 <                mainBuffer.dirtyPages = (uint8 *) malloc(mainBuffer.pageCount);
942 >                mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
943  
944                  if (mainBuffer.pageInfo != 0)
945                          free(mainBuffer.pageInfo);
# Line 900 | Line 948 | bool VideoInitBuffer()
948  
949                  if ((mainBuffer.dirtyPages == 0) || (mainBuffer.pageInfo == 0))
950                          return false;
951 +                
952 +                mainBuffer.dirty = false;
953  
954                  PFLAG_CLEAR_ALL;
955 +                // Safety net to insure the loops in the update routines will terminate
956 +                // See a discussion in <video_vosf.h> for further details
957 +                PFLAG_CLEAR(mainBuffer.pageCount);
958 +                PFLAG_SET(mainBuffer.pageCount+1);
959  
960                  uint32 a = 0;
961                  for (int i = 0; i < mainBuffer.pageCount; i++) {
# Line 954 | Line 1008 | bool VideoInit(bool classic)
1008          keycode_init();
1009  
1010          // Read prefs
1011 <        mouse_wheel_mode = PrefsFindInt16("mousewheelmode");
1012 <        mouse_wheel_lines = PrefsFindInt16("mousewheellines");
1011 >        mouse_wheel_mode = PrefsFindInt32("mousewheelmode");
1012 >        mouse_wheel_lines = PrefsFindInt32("mousewheellines");
1013  
1014          // Find screen and root window
1015          screen = XDefaultScreen(x_display);
# Line 1115 | Line 1169 | bool VideoInit(bool classic)
1169                  }
1170  
1171                  // Initialize the handler for SIGSEGV
1172 <                if (!Screen_fault_handler_init()) {
1172 >                if (!sigsegv_install_handler(screen_fault_handler)) {
1173                          // TODO: STR_VOSF_INIT_ERR ?
1174                          ErrorAlert("Could not initialize Video on SEGV signals");
1175                          return false;
# Line 1893 | Line 1947 | static void update_display_static(void)
1947   *      Screen refresh functions
1948   */
1949  
1950 < // The specialisations hereunder are meant to enable VOSF with DGA in direct
1951 < // addressing mode in case the address spaces (RAM, ROM, FrameBuffer) could
1952 < // not get mapped correctly with respect to the predetermined host frame
1953 < // buffer base address.
1954 < //
1901 < // Hmm, in other words, when in direct addressing mode and DGA is requested,
1902 < // we first try to "triple allocate" the address spaces according to the real
1903 < // host frame buffer address. Then, if it fails, we will use a temporary
1904 < // frame buffer thus making the real host frame buffer updated when pages
1905 < // of the temp frame buffer are altered.
1906 < //
1907 < // As a side effect, a little speed gain in screen updates could be noticed
1908 < // for other modes than DGA.
1909 < //
1910 < // The following two functions below are inline so that a clever compiler
1911 < // could specialise the code according to the current screen depth and
1912 < // display type. A more clever compiler would the job by itself though...
1913 < // (update_display_vosf is inlined as well)
1950 > // We suggest the compiler to inline the next two functions so that it
1951 > // may specialise the code according to the current screen depth and
1952 > // display type. A clever compiler would do that job by itself though...
1953 >
1954 > // NOTE: update_display_vosf is inlined too
1955  
1956   static inline void possibly_quit_dga_mode()
1957   {
# Line 1981 | Line 2022 | static void video_refresh_dga_vosf(void)
2022          static int tick_counter = 0;
2023          if (++tick_counter >= frame_skip) {
2024                  tick_counter = 0;
2025 <                LOCK_VOSF;
2026 <                update_display_dga_vosf();
2027 <                UNLOCK_VOSF;
2025 >                if (mainBuffer.dirty) {
2026 >                        LOCK_VOSF;
2027 >                        update_display_dga_vosf();
2028 >                        UNLOCK_VOSF;
2029 >                }
2030          }
2031   }
2032   #endif
# Line 2003 | Line 2046 | static void video_refresh_window_vosf(vo
2046          static int tick_counter = 0;
2047          if (++tick_counter >= frame_skip) {
2048                  tick_counter = 0;
2049 <                LOCK_VOSF;
2050 <                update_display_window_vosf();
2051 <                UNLOCK_VOSF;
2049 >                if (mainBuffer.dirty) {
2050 >                        LOCK_VOSF;
2051 >                        update_display_window_vosf();
2052 >                        UNLOCK_VOSF;
2053 >                        XSync(x_display, false); // Let the server catch up
2054 >                }
2055          }
2056   }
2057   #endif // def ENABLE_VOSF
# Line 2092 | Line 2138 | static void *redraw_func(void *arg)
2138                  ticks++;
2139          }
2140          uint64 end = GetTicks_usec();
2141 <        printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, (end - start) / ticks);
2141 >        // printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, ticks * 1000000 / (end - start));
2142          return NULL;
2143   }
2144   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines