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.17 by cebix, 2000-07-22T16:07:21Z vs.
Revision 1.24 by cebix, 2000-10-11T17:55:06Z

# Line 52 | Line 52
52   # include <sys/mman.h>
53   #endif
54  
55 + #ifdef ENABLE_VOSF
56 + # include <math.h> // log()
57 + # include <unistd.h>
58 + # include <signal.h>
59 + # include <fcntl.h>
60 + # include <sys/mman.h>
61 + #endif
62 +
63   #include "cpu_emulation.h"
64   #include "main.h"
65   #include "adb.h"
# Line 154 | Line 162 | static XF86VidModeModeInfo **x_video_mod
162   static int num_x_video_modes;
163   #endif
164  
165 + #ifdef ENABLE_VOSF
166 + static bool use_vosf = true;                                            // Flag: VOSF enabled
167 + #else
168 + static const bool use_vosf = false;                                     // Flag: VOSF enabled
169 + #endif
170 +
171 + #ifdef ENABLE_VOSF
172 + static uint8 * the_host_buffer;                                         // Host frame buffer in VOSF mode
173 + static uint32 the_buffer_size;                                          // Size of allocated the_buffer
174 + #endif
175 +
176 + #ifdef ENABLE_VOSF
177 + // Variables for Video on SEGV support (taken from the Win32 port)
178 + struct ScreenPageInfo {
179 +    int top, bottom;                    // Mapping between this virtual page and Mac scanlines
180 + };
181 +
182 + struct ScreenInfo {
183 +    uint32 memBase;                             // Real start address
184 +    uint32 memStart;                    // Start address aligned to page boundary
185 +    uint32 memEnd;                              // Address of one-past-the-end of the screen
186 +    uint32 memLength;                   // Length of the memory addressed by the screen pages
187 +    
188 +    uint32 pageSize;                    // Size of a page
189 +    int pageBits;                               // Shift count to get the page number
190 +    uint32 pageCount;                   // Number of pages allocated to the screen
191 +    
192 +    uint8 * dirtyPages;                 // Table of flags set if page was altered
193 +    ScreenPageInfo * pageInfo;  // Table of mappings page -> Mac scanlines
194 + };
195 +
196 + static ScreenInfo mainBuffer;
197 +
198 + #define PFLAG_SET(page)                 mainBuffer.dirtyPages[page] = 1
199 + #define PFLAG_CLEAR(page)               mainBuffer.dirtyPages[page] = 0
200 + #define PFLAG_ISSET(page)               mainBuffer.dirtyPages[page]
201 + #define PFLAG_ISCLEAR(page)             (mainBuffer.dirtyPages[page] == 0)
202 + #ifdef UNALIGNED_PROFITABLE
203 + # define PFLAG_ISCLEAR_4(page)  (*((uint32 *)(mainBuffer.dirtyPages + page)) == 0)
204 + #else
205 + # define PFLAG_ISCLEAR_4(page)  \
206 +                (mainBuffer.dirtyPages[page  ] == 0) \
207 +        &&      (mainBuffer.dirtyPages[page+1] == 0) \
208 +        &&      (mainBuffer.dirtyPages[page+2] == 0) \
209 +        &&      (mainBuffer.dirtyPages[page+3] == 0)
210 + #endif
211 + #define PFLAG_CLEAR_ALL                 memset(mainBuffer.dirtyPages, 0, mainBuffer.pageCount)
212 + #define PFLAG_SET_ALL                   memset(mainBuffer.dirtyPages, 1, mainBuffer.pageCount)
213 +
214 + static int zero_fd = -1;
215 + static bool Screen_fault_handler_init();
216 + static struct sigaction vosf_sa;
217 +
218 + #ifdef HAVE_PTHREADS
219 + static pthread_mutex_t Screen_draw_lock = PTHREAD_MUTEX_INITIALIZER;    // Mutex to protect frame buffer (dirtyPages in fact)
220 + #endif
221 +
222 + #endif
223 +
224 + // VideoRefresh function
225 + void VideoRefreshInit(void);
226 + static void (*video_refresh)(void);
227  
228   // Prototypes
229   static void *redraw_func(void *arg);
# Line 167 | Line 237 | extern Display *x_display;
237   // From sys_unix.cpp
238   extern void SysMountFirstFloppy(void);
239  
240 + #ifdef ENABLE_VOSF
241 + # include "video_vosf.h"
242 + #endif
243 +
244  
245   /*
246   *  Initialization
# Line 175 | Line 249 | extern void SysMountFirstFloppy(void);
249   // Set VideoMonitor according to video mode
250   void set_video_monitor(int width, int height, int bytes_per_row, bool native_byte_order)
251   {
252 < #if !REAL_ADDRESSING
252 > #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
253          int layout = FLAYOUT_DIRECT;
254          switch (depth) {
255                  case 1:
# Line 337 | Line 411 | static bool init_window(int width, int h
411                  img->bitmap_bit_order = MSBFirst;
412          }
413  
414 + #ifdef ENABLE_VOSF
415 +        // Allocate a page-aligned chunk of memory for frame buffer
416 +        the_buffer_size = align_on_page_boundary((aligned_height + 2) * img->bytes_per_line);
417 +        the_host_buffer = the_buffer_copy;
418 +        
419 +        the_buffer_copy = (uint8 *)allocate_framebuffer(the_buffer_size);
420 +        memset(the_buffer_copy, 0, the_buffer_size);
421 +        
422 +        the_buffer = (uint8 *)allocate_framebuffer(the_buffer_size);
423 +        memset(the_buffer, 0, the_buffer_size);
424 + #else
425          // Allocate memory for frame buffer
426          the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
427 + #endif
428  
429          // Create GC
430          the_gc = XCreateGC(x_display, the_win, 0, 0);
# Line 352 | Line 438 | static bool init_window(int width, int h
438          XDefineCursor(x_display, the_win, mac_cursor);
439  
440          // Set VideoMonitor
441 +        bool native_byte_order;
442   #ifdef WORDS_BIGENDIAN
443 <        set_video_monitor(width, height, img->bytes_per_line, img->bitmap_bit_order == MSBFirst);
443 >        native_byte_order = (img->bitmap_bit_order == MSBFirst);
444   #else
445 <        set_video_monitor(width, height, img->bytes_per_line, img->bitmap_bit_order == LSBFirst);
445 >        native_byte_order = (img->bitmap_bit_order == LSBFirst);
446 > #endif
447 > #ifdef ENABLE_VOSF
448 >        do_update_framebuffer = GET_FBCOPY_FUNC(depth, native_byte_order, DISPLAY_WINDOW);
449   #endif
450 +        set_video_monitor(width, height, img->bytes_per_line, native_byte_order);
451          
452 < #if REAL_ADDRESSING
453 <        VideoMonitor.mac_frame_base = (uint32)the_buffer;
452 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
453 >        VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer);
454   #else
455          VideoMonitor.mac_frame_base = MacFrameBaseMac;
456   #endif
# Line 492 | Line 583 | static bool init_fbdev_dga(char *in_fb_n
583                  }
584          }
585          
586 + #if ENABLE_VOSF
587 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
588 +        // If the blit function is null, i.e. just a copy of the buffer,
589 +        // we first try to avoid the allocation of a temporary frame buffer
590 +        use_vosf = true;
591 +        do_update_framebuffer = GET_FBCOPY_FUNC(depth, true, DISPLAY_DGA);
592 +        if (do_update_framebuffer == FBCOPY_FUNC(fbcopy_raw))
593 +                use_vosf = false;
594 +        
595 +        if (use_vosf) {
596 +                the_host_buffer = the_buffer;
597 +                the_buffer_size = align_on_page_boundary((height + 2) * bytes_per_row);
598 +                the_buffer_copy = (uint8 *)malloc(the_buffer_size);
599 +                memset(the_buffer_copy, 0, the_buffer_size);
600 +                the_buffer = (uint8 *)allocate_framebuffer(the_buffer_size);
601 +                memset(the_buffer, 0, the_buffer_size);
602 +        }
603 + #else
604 +        use_vosf = false;
605 + #endif
606 + #endif
607 +        
608          set_video_monitor(width, height, bytes_per_row, true);
609 < #if REAL_ADDRESSING
610 <        VideoMonitor.mac_frame_base = (uint32)the_buffer;
609 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
610 >        VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer);
611   #else
612          VideoMonitor.mac_frame_base = MacFrameBaseMac;
613   #endif
# Line 575 | Line 688 | static bool init_xf86_dga(int width, int
688                          bytes_per_row *= 4;
689                          break;
690          }
691 +        
692 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
693 +        // If the blit function is null, i.e. just a copy of the buffer,
694 +        // we first try to avoid the allocation of a temporary frame buffer
695 +        use_vosf = true;
696 +        do_update_framebuffer = GET_FBCOPY_FUNC(depth, true, DISPLAY_DGA);
697 +        if (do_update_framebuffer == FBCOPY_FUNC(fbcopy_raw))
698 +                use_vosf = false;
699 +        
700 +        if (use_vosf) {
701 +                the_host_buffer = the_buffer;
702 +                the_buffer_size = align_on_page_boundary((height + 2) * bytes_per_row);
703 +                the_buffer_copy = (uint8 *)malloc(the_buffer_size);
704 +                memset(the_buffer_copy, 0, the_buffer_size);
705 +                the_buffer = (uint8 *)allocate_framebuffer(the_buffer_size);
706 +                memset(the_buffer, 0, the_buffer_size);
707 +        }
708 + #elif defined(ENABLE_VOSF)
709 +        // The UAE memory handlers will already handle color conversion, if needed.
710 +        use_vosf = false;
711 + #endif
712 +        
713          set_video_monitor(width, height, bytes_per_row, true);
714 < #if REAL_ADDRESSING
715 <        VideoMonitor.mac_frame_base = (uint32)the_buffer;
716 <        MacFrameLayout = FLAYOUT_DIRECT;
714 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
715 >        VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer);
716 > //      MacFrameLayout = FLAYOUT_DIRECT;
717   #else
718          VideoMonitor.mac_frame_base = MacFrameBaseMac;
719   #endif
# Line 654 | Line 789 | static void keycode_init(void)
789          }
790   }
791  
792 + bool VideoInitBuffer()
793 + {
794 + #ifdef ENABLE_VOSF
795 +        if (use_vosf) {
796 +                const uint32 page_size  = getpagesize();
797 +                const uint32 page_mask  = page_size - 1;
798 +                
799 +                mainBuffer.memBase      = (uint32) the_buffer;
800 +                // Align the frame buffer on page boundary
801 +                mainBuffer.memStart             = (uint32)((((unsigned long) the_buffer) + page_mask) & ~page_mask);
802 +                mainBuffer.memLength    = the_buffer_size;
803 +                mainBuffer.memEnd       = mainBuffer.memStart + mainBuffer.memLength;
804 +
805 +                mainBuffer.pageSize     = page_size;
806 +                mainBuffer.pageCount    = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
807 +                mainBuffer.pageBits     = int( log(mainBuffer.pageSize) / log(2.0) );
808 +
809 +                if (mainBuffer.dirtyPages != 0)
810 +                        free(mainBuffer.dirtyPages);
811 +
812 +                mainBuffer.dirtyPages = (uint8 *) malloc(mainBuffer.pageCount);
813 +
814 +                if (mainBuffer.pageInfo != 0)
815 +                        free(mainBuffer.pageInfo);
816 +
817 +                mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
818 +
819 +                if ((mainBuffer.dirtyPages == 0) || (mainBuffer.pageInfo == 0))
820 +                        return false;
821 +
822 +                PFLAG_CLEAR_ALL;
823 +
824 +                uint32 a = 0;
825 +                for (int i = 0; i < mainBuffer.pageCount; i++) {
826 +                        int y1 = a / VideoMonitor.bytes_per_row;
827 +                        if (y1 >= VideoMonitor.y)
828 +                                y1 = VideoMonitor.y - 1;
829 +
830 +                        int y2 = (a + mainBuffer.pageSize) / VideoMonitor.bytes_per_row;
831 +                        if (y2 >= VideoMonitor.y)
832 +                                y2 = VideoMonitor.y - 1;
833 +
834 +                        mainBuffer.pageInfo[i].top = y1;
835 +                        mainBuffer.pageInfo[i].bottom = y2;
836 +
837 +                        a += mainBuffer.pageSize;
838 +                        if (a > mainBuffer.memLength)
839 +                                a = mainBuffer.memLength;
840 +                }
841 +                
842 +                // We can now write-protect the frame buffer
843 +                if (mprotect((caddr_t)mainBuffer.memStart, mainBuffer.memLength, PROT_READ) != 0)
844 +                        return false;
845 +        }
846 + #endif
847 +        return true;
848 + }
849 +
850   bool VideoInit(bool classic)
851   {
852 + #ifdef ENABLE_VOSF
853 +        // Open /dev/zero
854 +        zero_fd = open("/dev/zero", O_RDWR);
855 +        if (zero_fd < 0) {
856 +        char str[256];
857 +                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
858 +                ErrorAlert(str);
859 +        return false;
860 +        }
861 +        
862 +        // Zero the mainBuffer structure
863 +        mainBuffer.dirtyPages = 0;
864 +        mainBuffer.pageInfo = 0;
865 + #endif
866 +        
867          // Check if X server runs on local machine
868          local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0)
869                   || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0);
# Line 807 | Line 1015 | bool VideoInit(bool classic)
1015          pthread_mutex_lock(&frame_buffer_lock);
1016   #endif
1017  
1018 < #if !REAL_ADDRESSING
1018 > #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
1019          // Set variables for UAE memory mapping
1020          MacFrameBaseHost = the_buffer;
1021          MacFrameSize = VideoMonitor.bytes_per_row * VideoMonitor.y;
# Line 817 | Line 1025 | bool VideoInit(bool classic)
1025                  MacFrameLayout = FLAYOUT_NONE;
1026   #endif
1027  
1028 + #ifdef ENABLE_VOSF
1029 +        if (use_vosf) {
1030 +                // Initialize the mainBuffer structure
1031 +                if (!VideoInitBuffer()) {
1032 +                        // TODO: STR_VOSF_INIT_ERR ?
1033 +                        ErrorAlert("Could not initialize Video on SEGV signals");
1034 +                return false;
1035 +                }
1036 +
1037 +                // Initialize the handler for SIGSEGV
1038 +                if (!Screen_fault_handler_init()) {
1039 +                        // TODO: STR_VOSF_INIT_ERR ?
1040 +                        ErrorAlert("Could not initialize Video on SEGV signals");
1041 +                        return false;
1042 +                }
1043 +        }
1044 + #endif
1045 +        
1046 +        // Initialize VideoRefresh function
1047 +        VideoRefreshInit();
1048 +        
1049          XSync(x_display, false);
1050  
1051   #ifdef HAVE_PTHREADS
# Line 885 | Line 1114 | void VideoExit(void)
1114                          XFreeColormap(x_display, cmap[0]);
1115                          XFreeColormap(x_display, cmap[1]);
1116                  }
1117 +                
1118 +                if (!use_vosf) {
1119 +                        if (the_buffer) {
1120 +                                free(the_buffer);
1121 +                                the_buffer = NULL;
1122 +                        }
1123  
1124 <                if (the_buffer) {
1125 <                        free(the_buffer);
1126 <                        the_buffer = NULL;
1124 >                        if (!have_shm && the_buffer_copy) {
1125 >                                free(the_buffer_copy);
1126 >                                the_buffer_copy = NULL;
1127 >                        }
1128 >                }
1129 > #ifdef ENABLE_VOSF
1130 >                else {
1131 >                        if (the_buffer != (uint8 *)MAP_FAILED) {
1132 >                                munmap((caddr_t)the_buffer, the_buffer_size);
1133 >                                the_buffer = 0;
1134 >                        }
1135 >                        
1136 >                        if (the_buffer_copy != (uint8 *)MAP_FAILED) {
1137 >                                munmap((caddr_t)the_buffer_copy, the_buffer_size);
1138 >                                the_buffer_copy = 0;
1139 >                        }
1140 >                }
1141 > #endif
1142 >        }
1143 >        
1144 > #ifdef ENABLE_VOSF
1145 >        if (use_vosf) {
1146 >                // Clear mainBuffer data
1147 >                if (mainBuffer.pageInfo) {
1148 >                        free(mainBuffer.pageInfo);
1149 >                        mainBuffer.pageInfo = 0;
1150                  }
1151  
1152 <                if (!have_shm && the_buffer_copy) {
1153 <                        free(the_buffer_copy);
1154 <                        the_buffer_copy = NULL;
1152 >                if (mainBuffer.dirtyPages) {
1153 >                        free(mainBuffer.dirtyPages);
1154 >                        mainBuffer.dirtyPages = 0;
1155                  }
1156          }
1157 +
1158 +        // Close /dev/zero
1159 +        if (zero_fd > 0)
1160 +                close(zero_fd);
1161 + #endif
1162   }
1163  
1164  
# Line 1027 | Line 1290 | static void resume_emul(void)
1290          XF86DGASetViewPort(x_display, screen, 0, 0);
1291   #endif
1292          XSync(x_display, false);
1293 <
1293 >        
1294 >        // the_buffer already contains the data to restore. i.e. since a temporary
1295 >        // frame buffer is used when VOSF is actually used, fb_save is therefore
1296 >        // not necessary.
1297 > #ifdef ENABLE_VOSF
1298 >        if (use_vosf) {
1299 > #ifdef HAVE_PTHREADS
1300 >                pthread_mutex_lock(&Screen_draw_lock);
1301 > #endif
1302 >                PFLAG_SET_ALL;
1303 > #ifdef HAVE_PTHREADS
1304 >                pthread_mutex_unlock(&Screen_draw_lock);
1305 > #endif
1306 >                memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1307 >        }
1308 > #endif
1309 >        
1310          // Restore frame buffer
1311          if (fb_save) {
1312 + #ifdef ENABLE_VOSF
1313 +                // Don't copy fb_save to the temporary frame buffer in VOSF mode
1314 +                if (!use_vosf)
1315 + #endif
1316                  memcpy(the_buffer, fb_save, VideoMonitor.y * VideoMonitor.bytes_per_row);
1317                  free(fb_save);
1318                  fb_save = NULL;
# Line 1311 | Line 1594 | static void handle_events(void)
1594                          // Hidden parts exposed, force complete refresh of window
1595                          case Expose:
1596                                  if (display_type == DISPLAY_WINDOW) {
1597 + #ifdef ENABLE_VOSF
1598 +                                        if (use_vosf) {                 // VOSF refresh
1599 + #ifdef HAVE_PTHREADS
1600 +                                                pthread_mutex_lock(&Screen_draw_lock);
1601 + #endif
1602 +                                                PFLAG_SET_ALL;
1603 + #ifdef HAVE_PTHREADS
1604 +                                                pthread_mutex_unlock(&Screen_draw_lock);
1605 + #endif
1606 +                                                memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1607 +                                        }
1608 +                                        else
1609 + #endif
1610                                          if (frame_skip == 0) {  // Dynamic refresh
1611                                                  int x1, y1;
1612                                                  for (y1=0; y1<16; y1++)
1613                                                  for (x1=0; x1<16; x1++)
1614                                                          updt_box[x1][y1] = true;
1615                                                  nr_boxes = 16 * 16;
1616 <                                        } else
1616 >                                        } else                                  // Static refresh
1617                                                  memset(the_buffer_copy, 0, VideoMonitor.bytes_per_row * VideoMonitor.y);
1618                                  }
1619                                  break;
# Line 1449 | Line 1745 | static void update_display_static(void)
1745          // Check for first column from left and first column from right that have changed
1746          if (high) {
1747                  if (depth == 1) {
1748 <                        x1 = VideoMonitor.x;
1748 >                        x1 = VideoMonitor.x - 1;
1749                          for (j=y1; j<=y2; j++) {
1750                                  p = &the_buffer[j * bytes_per_row];
1751                                  p2 = &the_buffer_copy[j * bytes_per_row];
# Line 1458 | Line 1754 | static void update_display_static(void)
1754                                                  x1 = i << 3;
1755                                                  break;
1756                                          }
1757 <                                        p++;
1462 <                                        p2++;
1757 >                                        p++; p2++;
1758                                  }
1759                          }
1760                          x2 = x1;
# Line 1469 | Line 1764 | static void update_display_static(void)
1764                                  p += bytes_per_row;
1765                                  p2 += bytes_per_row;
1766                                  for (i=(VideoMonitor.x>>3); i>(x2>>3); i--) {
1767 <                                        p--;
1473 <                                        p2--;
1767 >                                        p--; p2--;
1768                                          if (*p != *p2) {
1769                                                  x2 = i << 3;
1770                                                  break;
# Line 1492 | Line 1786 | static void update_display_static(void)
1786                          for (j=y1; j<=y2; j++) {
1787                                  p = &the_buffer[j * bytes_per_row];
1788                                  p2 = &the_buffer_copy[j * bytes_per_row];
1789 <                                for (i=0; i<x1; i++) {
1790 <                                        if (memcmp(p, p2, bytes_per_pixel)) {
1791 <                                                x1 = i;
1789 >                                for (i=0; i<x1*bytes_per_pixel; i++) {
1790 >                                        if (*p != *p2) {
1791 >                                                x1 = i / bytes_per_pixel;
1792                                                  break;
1793                                          }
1794 <                                        p += bytes_per_pixel;
1501 <                                        p2 += bytes_per_pixel;
1794 >                                        p++; p2++;
1795                                  }
1796                          }
1797                          x2 = x1;
# Line 1507 | Line 1800 | static void update_display_static(void)
1800                                  p2 = &the_buffer_copy[j * bytes_per_row];
1801                                  p += bytes_per_row;
1802                                  p2 += bytes_per_row;
1803 <                                for (i=VideoMonitor.x; i>x2; i--) {
1804 <                                        p -= bytes_per_pixel;
1805 <                                        p2 -= bytes_per_pixel;
1806 <                                        if (memcmp(p, p2, bytes_per_pixel)) {
1807 <                                                x2 = i;
1803 >                                for (i=VideoMonitor.x*bytes_per_pixel; i>x2*bytes_per_pixel; i--) {
1804 >                                        p--;
1805 >                                        p2--;
1806 >                                        if (*p != *p2) {
1807 >                                                x2 = i / bytes_per_pixel;
1808                                                  break;
1809                                          }
1810                                  }
# Line 1539 | Line 1832 | static void update_display_static(void)
1832  
1833  
1834   /*
1835 + *      Screen refresh functions
1836 + */
1837 +
1838 + // The specialisations hereunder are meant to enable VOSF with DGA in direct
1839 + // addressing mode in case the address spaces (RAM, ROM, FrameBuffer) could
1840 + // not get mapped correctly with respect to the predetermined host frame
1841 + // buffer base address.
1842 + //
1843 + // Hmm, in other words, when in direct addressing mode and DGA is requested,
1844 + // we first try to "triple allocate" the address spaces according to the real
1845 + // host frame buffer address. Then, if it fails, we will use a temporary
1846 + // frame buffer thus making the real host frame buffer updated when pages
1847 + // of the temp frame buffer are altered.
1848 + //
1849 + // As a side effect, a little speed gain in screen updates could be noticed
1850 + // for other modes than DGA.
1851 + //
1852 + // The following two functions below are inline so that a clever compiler
1853 + // could specialise the code according to the current screen depth and
1854 + // display type. A more clever compiler would the job by itself though...
1855 + // (update_display_vosf is inlined as well)
1856 +
1857 + static inline void possibly_quit_dga_mode()
1858 + {
1859 + #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1860 +        // Quit DGA mode if requested
1861 +        if (quit_full_screen) {
1862 +                quit_full_screen = false;
1863 + #ifdef ENABLE_XF86_DGA
1864 +                XF86DGADirectVideo(x_display, screen, 0);
1865 + #endif
1866 +                XUngrabPointer(x_display, CurrentTime);
1867 +                XUngrabKeyboard(x_display, CurrentTime);
1868 +                XUnmapWindow(x_display, the_win);
1869 +                XSync(x_display, false);
1870 +        }
1871 + #endif
1872 + }
1873 +
1874 + static inline void handle_palette_changes(int depth, int display_type)
1875 + {
1876 + #ifdef HAVE_PTHREADS
1877 +        pthread_mutex_lock(&palette_lock);
1878 + #endif
1879 +        if (palette_changed) {
1880 +                palette_changed = false;
1881 +                if (depth == 8) {
1882 +                        XStoreColors(x_display, cmap[0], palette, 256);
1883 +                        XStoreColors(x_display, cmap[1], palette, 256);
1884 +                                
1885 + #ifdef ENABLE_XF86_DGA
1886 +                        if (display_type == DISPLAY_DGA) {
1887 +                                current_dga_cmap ^= 1;
1888 +                                XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1889 +                        }
1890 + #endif
1891 +                }
1892 +        }
1893 + #ifdef HAVE_PTHREADS
1894 +        pthread_mutex_unlock(&palette_lock);
1895 + #endif
1896 + }
1897 +
1898 + static void video_refresh_dga(void)
1899 + {
1900 +        // Quit DGA mode if requested
1901 +        possibly_quit_dga_mode();
1902 +        
1903 +        // Handle X events
1904 +        handle_events();
1905 +        
1906 +        // Handle palette changes
1907 +        handle_palette_changes(depth, DISPLAY_DGA);
1908 + }
1909 +
1910 + #ifdef ENABLE_VOSF
1911 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
1912 + static void video_refresh_dga_vosf(void)
1913 + {
1914 +        // Quit DGA mode if requested
1915 +        possibly_quit_dga_mode();
1916 +        
1917 +        // Handle X events
1918 +        handle_events();
1919 +        
1920 +        // Handle palette changes
1921 +        handle_palette_changes(depth, DISPLAY_DGA);
1922 +        
1923 +        // Update display (VOSF variant)
1924 +        static int tick_counter = 0;
1925 +        if (++tick_counter >= frame_skip) {
1926 +                tick_counter = 0;
1927 + #ifdef HAVE_PTHREADS
1928 +                pthread_mutex_lock(&Screen_draw_lock);
1929 + #endif
1930 +                update_display_dga_vosf();
1931 + #ifdef HAVE_PTHREADS
1932 +                pthread_mutex_unlock(&Screen_draw_lock);
1933 + #endif
1934 +        }
1935 + }
1936 + #endif
1937 +
1938 + static void video_refresh_window_vosf(void)
1939 + {
1940 +        // Quit DGA mode if requested
1941 +        possibly_quit_dga_mode();
1942 +        
1943 +        // Handle X events
1944 +        handle_events();
1945 +        
1946 +        // Handle palette changes
1947 +        handle_palette_changes(depth, DISPLAY_WINDOW);
1948 +        
1949 +        // Update display (VOSF variant)
1950 +        static int tick_counter = 0;
1951 +        if (++tick_counter >= frame_skip) {
1952 +                tick_counter = 0;
1953 + #ifdef HAVE_PTHREADS
1954 +                pthread_mutex_lock(&Screen_draw_lock);
1955 + #endif
1956 +                update_display_window_vosf();
1957 + #ifdef HAVE_PTHREADS
1958 +                pthread_mutex_unlock(&Screen_draw_lock);
1959 + #endif
1960 +        }
1961 + }
1962 + #endif // def ENABLE_VOSF
1963 +
1964 + static void video_refresh_window_static(void)
1965 + {
1966 +        // Handle X events
1967 +        handle_events();
1968 +        
1969 +        // Handle_palette changes
1970 +        handle_palette_changes(depth, DISPLAY_WINDOW);
1971 +        
1972 +        // Update display (static variant)
1973 +        static int tick_counter = 0;
1974 +        if (++tick_counter >= frame_skip) {
1975 +                tick_counter = 0;
1976 +                update_display_static();
1977 +        }
1978 + }
1979 +
1980 + static void video_refresh_window_dynamic(void)
1981 + {
1982 +        // Handle X events
1983 +        handle_events();
1984 +        
1985 +        // Handle_palette changes
1986 +        handle_palette_changes(depth, DISPLAY_WINDOW);
1987 +        
1988 +        // Update display (dynamic variant)
1989 +        static int tick_counter = 0;
1990 +        tick_counter++;
1991 +        update_display_dynamic(tick_counter);
1992 + }
1993 +
1994 +
1995 + /*
1996   *  Thread for screen refresh, input handling etc.
1997   */
1998  
1999 + void VideoRefreshInit(void)
2000 + {
2001 +        // TODO: set up specialised 8bpp VideoRefresh handlers ?
2002 +        if (display_type == DISPLAY_DGA) {
2003 + #if ENABLE_VOSF && (REAL_ADDRESSING || DIRECT_ADDRESSING)
2004 +                if (use_vosf)
2005 +                        video_refresh = video_refresh_dga_vosf;
2006 +                else
2007 + #endif
2008 +                        video_refresh = video_refresh_dga;
2009 +        }
2010 +        else {
2011 + #ifdef ENABLE_VOSF
2012 +                if (use_vosf)
2013 +                        video_refresh = video_refresh_window_vosf;
2014 +                else
2015 + #endif
2016 +                if (frame_skip == 0)
2017 +                        video_refresh = video_refresh_window_dynamic;
2018 +                else
2019 +                        video_refresh = video_refresh_window_static;
2020 +        }
2021 + }
2022 +
2023 + void VideoRefresh(void)
2024 + {
2025 +        // TODO: make main_unix/VideoRefresh call directly video_refresh() ?
2026 +        video_refresh();
2027 + }
2028 +
2029 + #if 0
2030   void VideoRefresh(void)
2031   {
2032   #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
# Line 1597 | Line 2082 | void VideoRefresh(void)
2082                  }
2083          }
2084   }
2085 + #endif
2086  
2087   #ifdef HAVE_PTHREADS
2088   static void *redraw_func(void *arg)
2089   {
2090 +        uint64 start = GetTicks_usec();
2091 +        int64 ticks = 0;
2092 +        uint64 next = GetTicks_usec();
2093          while (!redraw_thread_cancel) {
2094 < #ifdef HAVE_NANOSLEEP
2095 <                struct timespec req = {0, 16666667};
2096 <                nanosleep(&req, NULL);
2097 < #else
2098 <                usleep(16667);
2099 < #endif
2100 <                VideoRefresh();
2094 > //              VideoRefresh();
2095 >                video_refresh();
2096 >                next += 16667;
2097 >                int64 delay = next - GetTicks_usec();
2098 >                if (delay > 0)
2099 >                        Delay_usec(delay);
2100 >                else if (delay < -16667)
2101 >                        next = GetTicks_usec();
2102 >                ticks++;
2103          }
2104 +        uint64 end = GetTicks_usec();
2105 +        printf("%Ld ticks in %Ld usec = %Ld ticks/sec\n", ticks, end - start, (end - start) / ticks);
2106          return NULL;
2107   }
2108   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines