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.4 by gbeauche, 2000-10-02T17:52:42Z vs.
Revision 1.11 by gbeauche, 2001-01-11T16:39:08Z

# Line 130 | Line 130 | static void do_fbcopy_raw(uint8 * dest,
130   #define FB_FUNC_NAME do_fbcopy_16_nbo
131   #include "video_blit.h"
132  
133 < // opposite byte order (untested)
133 > // opposite byte order
134  
135   #define FB_BLIT_1(dst, src) \
136 <        (dst = ((((src) >> 6) & 0xff) | (((src) & 0x60) << 9)))
136 >        (dst = ((((src) >> 7) & 0xff) | (((src) << 9) & 0xc000) | (((src) << 8) & 0x1f00)))
137  
138   #define FB_BLIT_2(dst, src) \
139 <        (dst = ((((src) >> 6) & 0x00ff00ff) | (((src) & 0x00600060) << 9)))
139 >        (dst = ((((src) >> 7) & 0x00ff00ff) | (((src) << 9) & 0xc000c000) | (((src) << 8) & 0x1f001f00)))
140  
141   #define FB_DEPTH 16
142   #define FB_FUNC_NAME do_fbcopy_16_obo
# Line 206 | Line 206 | static fbcopy_func do_update_framebuffer
206   // fb_copy_funcs[depth_id][native_byte_order][dga_mode]
207   // NT  : not tested
208   // OK  : has been successfully tested
209 < // NBO : native byte order
210 < // OBO : opposite byte order
209 > // NBO : native byte order (X server vs. client)
210 > // OBO : opposite byte order (X server vs. client)
211   static fbcopy_func fbcopy_funcs[ID_DEPTH_COUNT][2][2] = {
212   #ifdef WORDS_BIGENDIAN
213                                  /*      opposite byte order             native byte order       */
214   /*  1 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_raw)          },      // NT
215   /*  8 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_raw)          },      // OK (NBO)
216 < /* 15 bpp */    {       WD(fbcopy_15_obo)       ,       WD(fbcopy_raw)          },      // NT
217 < /* 16 bpp */    {       WD(fbcopy_16_obo)       ,       WD(fbcopy_16_nbo)       },      // NT
218 < /* 24 bpp */    {       WD(fbcopy_24_obo)       ,       WD(fbcopy_raw)          }       // NT
216 > /* 15 bpp */    {       WD(fbcopy_15_obo)       ,       WD(fbcopy_raw)          },      // OK (OBO)
217 > /* 16 bpp */    {       WD(fbcopy_16_obo)       ,       WD(fbcopy_16_nbo)       },      // OK (OBO)
218 > /* 24 bpp */    {       WD(fbcopy_24_obo)       ,       WD(fbcopy_raw)          }       // OK (OBO)
219   #else
220                                  /*      opposite byte order             native byte order       */
221   /*  1 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_raw)          },      // NT
222   /*  8 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_raw)          },      // OK (NBO)
223   /* 15 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_15_nbo)       },      // OK (NBO)
224   /* 16 bpp */    {       WD(fbcopy_16_obo)       ,       WD(fbcopy_16_nbo)       },      // OK (NBO)
225 < /* 24 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_24_nbo)       }       // NT
225 > /* 24 bpp */    {       WD(fbcopy_raw)          ,       WD(fbcopy_24_nbo)       }       // OK (NBO)
226   #endif
227   };
228  
# Line 240 | Line 240 | static fbcopy_func fbcopy_funcs[ID_DEPTH
240   *      Screen fault handler
241   */
242  
243 < static inline void do_handle_screen_fault(uintptr addr)
243 > const uintptr INVALID_PC = (uintptr)-1;
244 >
245 > static inline void do_handle_screen_fault(uintptr addr, uintptr pc = INVALID_PC)
246   {
247 <        if ((addr < mainBuffer.memStart) || (addr >= mainBuffer.memEnd)) {
248 <                fprintf(stderr, "Segmentation fault at 0x%08X\n", addr);
249 <                abort();
247 >        /* Someone attempted to write to the frame buffer. Make it writeable
248 >         * now so that the data could actually be written. It will be made
249 >         * read-only back in one of the screen update_*() functions.
250 >         */
251 >        if ((addr >= mainBuffer.memStart) && (addr < mainBuffer.memEnd)) {
252 >                const int page  = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
253 >                caddr_t page_ad = (caddr_t)(addr & ~(mainBuffer.pageSize - 1));
254 >                LOCK_VOSF;
255 >                PFLAG_SET(page);
256 >                mprotect(page_ad, mainBuffer.pageSize, PROT_READ | PROT_WRITE);
257 >                UNLOCK_VOSF;
258 >                return;
259          }
260          
261 <        const int page  = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
262 <        caddr_t page_ad = (caddr_t)(addr & ~(mainBuffer.pageSize - 1));
263 < #ifdef HAVE_PTHREADS
264 <        pthread_mutex_lock(&Screen_draw_lock);
265 < #endif
266 <        PFLAG_SET(page);
267 <        mprotect(page_ad, mainBuffer.pageSize, PROT_READ | PROT_WRITE);
257 < #ifdef HAVE_PTHREADS
258 <        pthread_mutex_unlock(&Screen_draw_lock);
259 < #endif
261 >        /* Otherwise, we don't know how to handle the fault, let it crash */
262 >        fprintf(stderr, "do_handle_screen_fault: unhandled address 0x%08X", addr);
263 >        if (pc != INVALID_PC)
264 >                fprintf(stderr, " [IP=0x%08X]", pc);
265 >        fprintf(stderr, "\n");
266 >        
267 >        signal(SIGSEGV, SIG_DFL);
268   }
269  
270   #if defined(HAVE_SIGINFO_T)
271 +
272   static void Screen_fault_handler(int, siginfo_t * sip, void *)
273   {
274          D(bug("Screen_fault_handler: ADDR=0x%08X\n", sip->si_addr));
275          do_handle_screen_fault((uintptr)sip->si_addr);
276   }
277 +
278   #elif defined(HAVE_SIGCONTEXT_SUBTERFUGE)
279 +
280   # if defined(__i386__) && defined(__linux__)
281   static void Screen_fault_handler(int, struct sigcontext scs)
282   {
283          D(bug("Screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", scs.cr2, scs.eip));
284 <        do_handle_screen_fault((uintptr)scs.cr2);
284 >        do_handle_screen_fault((uintptr)scs.cr2, (uintptr)scs.eip);
285 > }
286 >
287 > # elif defined(__m68k__) && defined(__NetBSD__)
288 >
289 > # include <m68k/frame.h>
290 > static void Screen_fault_handler(int, int code, struct sigcontext *scp)
291 > {
292 >        D(bug("Screen_fault_handler: ADDR=0x%08X\n", code));
293 >        struct sigstate {
294 >                int ss_flags;
295 >                struct frame ss_frame;
296 >        };
297 >        struct sigstate *state = (struct sigstate *)scp->sc_ap;
298 >        uintptr fault_addr;
299 >        switch (state->ss_frame.f_format) {
300 >                case 7:         // 68040 access error
301 >                        // "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown
302 >                        fault_addr = state->ss_frame.f_fmt7.f_fa;
303 >                        break;
304 >                default:
305 >                        fault_addr = (uintptr)code;
306 >                        break;
307 >        }
308 >        do_handle_screen_fault(fault_addr);
309   }
310 +
311   # else
312   #  error "No suitable subterfuge for Video on SEGV signals"
313   # endif
# Line 290 | Line 326 | static bool Screen_fault_handler_init()
326          // Setup SIGSEGV handler to process writes to frame buffer
327          sigemptyset(&vosf_sa.sa_mask);
328          vosf_sa.sa_sigaction = Screen_fault_handler;
329 <        vosf_sa.sa_flags = 0;
329 >        vosf_sa.sa_flags = SA_SIGINFO;
330          return (sigaction(SIGSEGV, &vosf_sa, NULL) == 0);
331   }
332   #elif defined(HAVE_SIGCONTEXT_SUBTERFUGE)
# Line 299 | Line 335 | static bool Screen_fault_handler_init()
335          // Setup SIGSEGV handler to process writes to frame buffer
336          sigemptyset(&vosf_sa.sa_mask);
337          vosf_sa.sa_handler = (void (*)(int)) Screen_fault_handler;
338 + #if !EMULATED_68K && defined(__NetBSD__)
339 +        sigaddset(&vosf_sa.sa_mask, SIGALRM);
340 +        vosf_sa.sa_flags = SA_ONSTACK;
341 + #else
342          vosf_sa.sa_flags = 0;
343 + #endif
344          return (sigaction(SIGSEGV, &vosf_sa, NULL) == 0);
345   }
346   #endif
# Line 313 | Line 354 | static inline void update_display_window
354   {
355          int page = 0;
356          for (;;) {
357 <                while (PFLAG_ISCLEAR_4(page))
358 <                        page += 4;
318 <                
319 <                while (PFLAG_ISCLEAR(page))
320 <                        page++;
321 <                
322 <                if (page >= mainBuffer.pageCount)
357 >                const int first_page = find_next_page_set(page);
358 >                if (first_page >= mainBuffer.pageCount)
359                          break;
360 <                
361 <                const int first_page = page;
362 <                while ((page < mainBuffer.pageCount) && PFLAG_ISSET(page)) {
363 <                        PFLAG_CLEAR(page);
328 <                        ++page;
329 <                }
330 <                
360 >
361 >                page = find_next_page_clear(first_page);
362 >                PFLAG_CLEAR_RANGE(first_page, page);
363 >
364                  // Make the dirty pages read-only again
365                  const int32 offset  = first_page << mainBuffer.pageBits;
366                  const uint32 length = (page - first_page) << mainBuffer.pageBits;
# Line 344 | Line 377 | static inline void update_display_window
377                  
378                  // Check for first column from left and first column
379                  // from right that have changed
380 <                int x1 = VideoMonitor.x * bytes_per_pixel - 1;
381 <                for (j = y1; j <= y2; j++) {
382 <                        uint8 * const p1 = &the_buffer[j * bytes_per_row];
383 <                        uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
384 <                        for (i = 0; i < x1; i++) {
385 <                                if (p1[i] != p2[i]) {
386 <                                        x1 = i;
387 <                                        break;
380 >                int x1, x2, width;
381 >                if (depth == 1) {
382 >
383 >                        x1 = VideoMonitor.x - 1;
384 >                        for (j = y1; j <= y2; j++) {
385 >                                uint8 * const p1 = &the_buffer[j * bytes_per_row];
386 >                                uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
387 >                                for (i = 0; i < (x1>>3); i++) {
388 >                                        if (p1[i] != p2[i]) {
389 >                                                x1 = i << 3;
390 >                                                break;
391 >                                        }
392                                  }
393                          }
394 <                }
395 <                x1 /= bytes_per_pixel;
396 <                
397 <                int x2 = x1 * bytes_per_pixel;
398 <                for (j = y2; j >= y1; j--) {
399 <                        uint8 * const p1 = &the_buffer[j * bytes_per_row];
400 <                        uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
401 <                        for (i = VideoMonitor.x * bytes_per_pixel - 1; i > x2; i--) {
402 <                                if (p1[i] != p2[i]) {
403 <                                        x2 = i;
367 <                                        break;
394 >
395 >                        x2 = x1;
396 >                        for (j = y2; j >= y1; j--) {
397 >                                uint8 * const p1 = &the_buffer[j * bytes_per_row];
398 >                                uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
399 >                                for (i = (VideoMonitor.x>>3) - 1; i > (x2>>3); i--) {
400 >                                        if (p1[i] != p2[i]) {
401 >                                                x2 = (i << 3) + 7;
402 >                                                break;
403 >                                        }
404                                  }
405                          }
406 <                }
407 <                x2 /= bytes_per_pixel;
406 >                        width = x2 - x1 + 1;
407 >
408 >                        // Update the_host_buffer and copy of the_buffer
409 >                        i = y1 * bytes_per_row + (x1 >> 3);
410 >                        for (j = y1; j <= y2; j++) {
411 >                                do_update_framebuffer(the_host_buffer + i, the_buffer + i, width >> 3);
412 >                                memcpy(the_buffer_copy + i, the_buffer + i, width >> 3);
413 >                                i += bytes_per_row;
414 >                        }
415 >
416 >                } else {
417 >
418 >                        x1 = VideoMonitor.x * bytes_per_pixel - 1;
419 >                        for (j = y1; j <= y2; j++) {
420 >                                uint8 * const p1 = &the_buffer[j * bytes_per_row];
421 >                                uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
422 >                                for (i = 0; i < x1; i++) {
423 >                                        if (p1[i] != p2[i]) {
424 >                                                x1 = i;
425 >                                                break;
426 >                                        }
427 >                                }
428 >                        }
429 >                        x1 /= bytes_per_pixel;
430                  
431 <                // Update the_host_buffer and copy of the_buffer
432 <                // There is at least one pixel to copy
433 <                const int width = x2 - x1 + 1;
434 <                i = y1 * bytes_per_row + x1 * bytes_per_pixel;
435 <                for (j = y1; j <= y2; j++) {
436 <                        do_update_framebuffer(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width);
437 <                        memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width);
438 <                        i += bytes_per_row;
431 >                        x2 = x1 * bytes_per_pixel;
432 >                        for (j = y2; j >= y1; j--) {
433 >                                uint8 * const p1 = &the_buffer[j * bytes_per_row];
434 >                                uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
435 >                                for (i = VideoMonitor.x * bytes_per_pixel - 1; i > x2; i--) {
436 >                                        if (p1[i] != p2[i]) {
437 >                                                x2 = i;
438 >                                                break;
439 >                                        }
440 >                                }
441 >                        }
442 >                        x2 /= bytes_per_pixel;
443 >                        width = x2 - x1 + 1;
444 >
445 >                        // Update the_host_buffer and copy of the_buffer
446 >                        i = y1 * bytes_per_row + x1 * bytes_per_pixel;
447 >                        for (j = y1; j <= y2; j++) {
448 >                                do_update_framebuffer(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width);
449 >                                memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width);
450 >                                i += bytes_per_row;
451 >                        }
452                  }
453                  
454                  if (have_shm)
# Line 398 | Line 469 | static inline void update_display_dga_vo
469   {
470          int page = 0;
471          for (;;) {
472 <                while (PFLAG_ISCLEAR_4(page))
473 <                        page += 4;
403 <                
404 <                while (PFLAG_ISCLEAR(page))
405 <                        page++;
406 <                
407 <                if (page >= mainBuffer.pageCount)
472 >                const int first_page = find_next_page_set(page);
473 >                if (first_page >= mainBuffer.pageCount)
474                          break;
475 <                
476 <                const int first_page = page;
477 <                while ((page < mainBuffer.pageCount) && PFLAG_ISSET(page)) {
478 <                        PFLAG_CLEAR(page);
413 <                        ++page;
414 <                }
415 <                
475 >
476 >                page = find_next_page_clear(first_page);
477 >                PFLAG_CLEAR_RANGE(first_page, page);
478 >
479                  // Make the dirty pages read-only again
480                  const int32 offset  = first_page << mainBuffer.pageBits;
481                  const uint32 length = (page - first_page) << mainBuffer.pageBits;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines