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.50 by gbeauche, 2005-04-02T09:50:17Z vs.
Revision 1.59 by gbeauche, 2006-05-14T08:32:05Z

# Line 31 | Line 31
31   #endif
32  
33   // Glue for SDL and X11 support
34 + #ifdef TEST_VOSF_PERFORMANCE
35 + #define MONITOR_INIT                    /* nothing */
36 + #else
37   #ifdef USE_SDL_VIDEO
38   #define MONITOR_INIT                    SDL_monitor_desc &monitor
39 < #define VIDEO_DRV_INIT                  driver_window *drv
39 > #define VIDEO_DRV_WIN_INIT              driver_window *drv
40 > #define VIDEO_DRV_DGA_INIT              driver_fullscreen *drv
41 > #define VIDEO_DRV_LOCK_PIXELS   SDL_VIDEO_LOCK_SURFACE(drv->s)
42 > #define VIDEO_DRV_UNLOCK_PIXELS SDL_VIDEO_UNLOCK_SURFACE(drv->s)
43 > #define VIDEO_DRV_DEPTH                 drv->s->format->BitsPerPixel
44 > #define VIDEO_DRV_WIDTH                 drv->s->w
45 > #define VIDEO_DRV_HEIGHT                drv->s->h
46   #define VIDEO_DRV_ROW_BYTES             drv->s->pitch
38 #define VIDEO_DRV_LOCK_PIXELS   if (SDL_MUSTLOCK(drv->s)) SDL_LockSurface(drv->s)
39 #define VIDEO_DRV_UNLOCK_PIXELS if (SDL_MUSTLOCK(drv->s)) SDL_UnlockSurface(drv->s)
47   #else
48   #ifdef SHEEPSHAVER
49   #define MONITOR_INIT                    /* nothing */
50 < #define VIDEO_DRV_INIT                  /* nothing */
50 > #define VIDEO_DRV_WIN_INIT              /* nothing */
51 > #define VIDEO_DRV_DGA_INIT              /* nothing */
52   #define VIDEO_DRV_WINDOW                the_win
53   #define VIDEO_DRV_GC                    the_gc
54   #define VIDEO_DRV_IMAGE                 img
55   #define VIDEO_DRV_HAVE_SHM              have_shm
56   #else
57   #define MONITOR_INIT                    X11_monitor_desc &monitor
58 < #define VIDEO_DRV_INIT                  driver_window *drv
58 > #define VIDEO_DRV_WIN_INIT              driver_window *drv
59 > #define VIDEO_DRV_DGA_INIT              driver_dga *drv
60   #define VIDEO_DRV_WINDOW                drv->w
61   #define VIDEO_DRV_GC                    drv->gc
62   #define VIDEO_DRV_IMAGE                 drv->img
# Line 55 | Line 64
64   #endif
65   #define VIDEO_DRV_LOCK_PIXELS   /* nothing */
66   #define VIDEO_DRV_UNLOCK_PIXELS /* nothing */
67 + #define VIDEO_DRV_DEPTH                 VIDEO_DRV_IMAGE->depth
68 + #define VIDEO_DRV_WIDTH                 VIDEO_DRV_IMAGE->width
69 + #define VIDEO_DRV_HEIGHT                VIDEO_DRV_IMAGE->height
70   #define VIDEO_DRV_ROW_BYTES             VIDEO_DRV_IMAGE->bytes_per_line
71   #endif
72 + #endif
73 +
74 + // Prototypes
75 + static void vosf_do_set_dirty_area(uintptr first, uintptr last);
76 + static void vosf_set_dirty_area(int x, int y, int w, int h, int screen_width, int screen_height, int bytes_per_row);
77  
78   // Variables for Video on SEGV support
79   static uint8 *the_host_buffer;  // Host frame buffer in VOSF mode
63 static uint32 the_host_buffer_row_bytes; // Host frame buffer number of bytes per row
80  
81   struct ScreenPageInfo {
82      int top, bottom;                    // Mapping between this virtual page and Mac scanlines
# Line 160 | Line 176 | static inline int find_next_page_clear(i
176   #endif
177   }
178  
179 < #ifdef HAVE_SPINLOCKS
180 < static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED;                               // Mutex to protect frame buffer (dirtyPages in fact)
181 < #define LOCK_VOSF spin_lock(&vosf_lock)
182 < #define UNLOCK_VOSF spin_unlock(&vosf_lock)
179 > #if defined(HAVE_PTHREADS)
180 > static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer (dirtyPages in fact)
181 > #define LOCK_VOSF pthread_mutex_lock(&vosf_lock);
182 > #define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock);
183   #elif defined(_WIN32)
184   static mutex_t vosf_lock;                                                                               // Mutex to protect frame buffer (dirtyPages in fact)
185   #define LOCK_VOSF vosf_lock.lock();
186   #define UNLOCK_VOSF vosf_lock.unlock();
187 < #elif defined(HAVE_PTHREADS)
188 < static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer (dirtyPages in fact)
189 < #define LOCK_VOSF pthread_mutex_lock(&vosf_lock);
190 < #define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock);
187 > #elif defined(HAVE_SPINLOCKS)
188 > static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED;                               // Mutex to protect frame buffer (dirtyPages in fact)
189 > #define LOCK_VOSF spin_lock(&vosf_lock)
190 > #define UNLOCK_VOSF spin_unlock(&vosf_lock)
191   #else
192   #define LOCK_VOSF
193   #define UNLOCK_VOSF
# Line 209 | Line 225 | static bool video_vosf_profitable(void)
225          int64 durations[VOSF_PROFITABLE_TRIES];
226          int mean_duration = 0;
227  
228 + #ifdef SHEEPSHAVER
229 +        const bool accel = PrefsFindBool("gfxaccel");
230 + #else
231 +        const bool accel = false;
232 + #endif
233 +
234          for (int i = 0; i < VOSF_PROFITABLE_TRIES; i++) {
235                  uint64 start = GetTicks_usec();
236                  for (int p = 0; p < mainBuffer.pageCount; p++) {
237                          uint8 *addr = (uint8 *)(mainBuffer.memStart + (p * mainBuffer.pageSize));
238 <                        addr[0] = 0; // Trigger Screen_fault_handler()
238 >                        if (accel)
239 >                                vosf_do_set_dirty_area((uintptr)addr, (uintptr)addr + mainBuffer.pageSize - 1);
240 >                        else
241 >                                addr[0] = 0; // Trigger Screen_fault_handler()
242                  }
243                  int64 duration = GetTicks_usec() - start;
244                  mean_duration += duration;
# Line 314 | Line 339 | static void video_vosf_exit(void)
339  
340  
341   /*
342 + * Update VOSF state with specified dirty area
343 + */
344 +
345 + static void vosf_do_set_dirty_area(uintptr first, uintptr last)
346 + {
347 +        const int first_page = (first - mainBuffer.memStart) >> mainBuffer.pageBits;
348 +        const int last_page = (last - mainBuffer.memStart) >> mainBuffer.pageBits;
349 +        uint8 *addr = (uint8 *)(first & -mainBuffer.pageSize);
350 +        for (int i = first_page; i <= last_page; i++) {
351 +                if (PFLAG_ISCLEAR(i)) {
352 +                        PFLAG_SET(i);
353 +                        vm_protect(addr, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
354 +                }
355 +                addr += mainBuffer.pageSize;
356 +        }
357 + }
358 +
359 + static void vosf_set_dirty_area(int x, int y, int w, int h, int screen_width, int screen_height, int bytes_per_row)
360 + {
361 +        if (x < 0) {
362 +                w -= -x;
363 +                x = 0;
364 +        }
365 +        if (y < 0) {
366 +                h -= -y;
367 +                y = 0;
368 +        }
369 +        if (w <= 0 || h <= 0)
370 +                return;
371 +        if (x + w > screen_width)
372 +                w -= (x + w) - screen_width;
373 +        if (y + h > screen_height)
374 +                h -= (y + h) - screen_height;
375 +        LOCK_VOSF;
376 +        if (bytes_per_row >= screen_width) {
377 +                const int bytes_per_pixel = bytes_per_row / screen_width;
378 +                if (bytes_per_row <= mainBuffer.pageSize) {
379 +                        const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x * bytes_per_pixel;
380 +                        const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) * bytes_per_pixel;
381 +                        vosf_do_set_dirty_area(a0, a1);
382 +                } else {
383 +                        for (int j = y; j < y + h; j++) {
384 +                                const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x * bytes_per_pixel;
385 +                                const uintptr a1 = a0 + (w - 1) * bytes_per_pixel;
386 +                                vosf_do_set_dirty_area(a0, a1);
387 +                        }
388 +                }
389 +        } else {
390 +                const int pixels_per_byte = screen_width / bytes_per_row;
391 +                if (bytes_per_row <= mainBuffer.pageSize) {
392 +                        const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x / pixels_per_byte;
393 +                        const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) / pixels_per_byte;
394 +                        vosf_do_set_dirty_area(a0, a1);
395 +                } else {
396 +                        for (int j = y; j < y + h; j++) {
397 +                                const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x / pixels_per_byte;
398 +                                const uintptr a1 = mainBuffer.memStart + j * bytes_per_row + (x + w - 1) / pixels_per_byte;
399 +                                vosf_do_set_dirty_area(a0, a1);
400 +                        }
401 +                }
402 +        }
403 +        mainBuffer.dirty = true;
404 +        UNLOCK_VOSF;
405 + }
406 +
407 +
408 + /*
409   * Screen fault handler
410   */
411  
# Line 328 | Line 420 | bool Screen_fault_handler(sigsegv_addres
420          if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) {
421                  const int page  = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits;
422                  LOCK_VOSF;
423 <                PFLAG_SET(page);
424 <                vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
423 >                if (PFLAG_ISCLEAR(page)) {
424 >                        PFLAG_SET(page);
425 >                        vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
426 >                }
427                  mainBuffer.dirty = true;
428                  UNLOCK_VOSF;
429                  return true;
# Line 377 | Line 471 | There are two cases to check:
471          than pageCount.
472   */
473  
474 < static inline void update_display_window_vosf(VIDEO_DRV_INIT)
474 > #ifndef TEST_VOSF_PERFORMANCE
475 > static void update_display_window_vosf(VIDEO_DRV_WIN_INIT)
476   {
477          VIDEO_MODE_INIT;
478  
# Line 423 | Line 518 | static inline void update_display_window
518          }
519          mainBuffer.dirty = false;
520   }
521 + #endif
522  
523  
524   /*
# Line 430 | Line 526 | static inline void update_display_window
526   *      (only in Real or Direct Addressing mode)
527   */
528  
529 + #ifndef TEST_VOSF_PERFORMANCE
530   #if REAL_ADDRESSING || DIRECT_ADDRESSING
531 < static inline void update_display_dga_vosf(void)
531 > static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT)
532   {
533          VIDEO_MODE_INIT;
534  
535 +        // Compute number of bytes per row, take care to virtual screens
536 +        const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
537 +        const int dst_bytes_per_row = TrivialBytesPerRow(VIDEO_MODE_X, DepthModeForPixelDepth(VIDEO_DRV_DEPTH));
538 +        const int scr_bytes_per_row = VIDEO_DRV_ROW_BYTES;
539 +        assert(dst_bytes_per_row <= scr_bytes_per_row);
540 +        const int scr_bytes_left = scr_bytes_per_row - dst_bytes_per_row;
541 +
542 +        // Full screen update requested?
543          if (mainBuffer.very_dirty) {
544                  PFLAG_CLEAR_ALL;
545                  vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ);
441                VIDEO_DRV_LOCK_PIXELS;
546                  memcpy(the_buffer_copy, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
547 <                Screen_blit(the_host_buffer, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
547 >                VIDEO_DRV_LOCK_PIXELS;
548 >                int i1 = 0, i2 = 0;
549 >                for (int j = 0;  j < VIDEO_MODE_Y; j++) {
550 >                        Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row);
551 >                        i1 += src_bytes_per_row;
552 >                        i2 += scr_bytes_per_row;
553 >                }
554 > #ifdef USE_SDL_VIDEO
555 >                SDL_UpdateRect(drv->s, 0, 0, VIDEO_MODE_X, VIDEO_MODE_Y);
556 > #endif
557                  VIDEO_DRV_UNLOCK_PIXELS;
558                  return;
559          }
560  
561 <        int page = 0;
561 >        // Setup partial blitter (use 64-pixel wide chunks)
562 >        const int n_pixels = 64;
563 >        const int n_chunks = VIDEO_MODE_X / n_pixels;
564 >        const int n_pixels_left = VIDEO_MODE_X - (n_chunks * n_pixels);
565 >        const int src_chunk_size = src_bytes_per_row / n_chunks;
566 >        const int dst_chunk_size = dst_bytes_per_row / n_chunks;
567 >        const int src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size);
568 >        const int dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size);
569 >
570 >        int page = 0, last_scanline = -1;
571          for (;;) {
572                  const unsigned first_page = find_next_page_set(page);
573                  if (first_page >= mainBuffer.pageCount)
# Line 458 | Line 580 | static inline void update_display_dga_vo
580                  const int32 offset  = first_page << mainBuffer.pageBits;
581                  const uint32 length = (page - first_page) << mainBuffer.pageBits;
582                  vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ);
461                
462                // There is at least one line to update
463                const int y1 = mainBuffer.pageInfo[first_page].top;
464                const int y2 = mainBuffer.pageInfo[page - 1].bottom;
583  
584 < #ifndef USE_SDL_VIDEO
585 <                // Update the_host_buffer and copy of the_buffer (use 64 bytes chunks)
586 <                const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
587 <                const int dst_bytes_per_row = the_host_buffer_row_bytes;
588 <                const int n_pixels = 64;
589 <                const int n_chunks = VIDEO_MODE_X / n_pixels;
590 <                const int src_chunk_size = src_bytes_per_row / n_chunks;
591 <                const int dst_chunk_size = dst_bytes_per_row / n_chunks;
592 <                const int src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size);
593 <                const int dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size);
584 >                // Optimized for scanlines, don't process overlapping lines again
585 >                int y1 = mainBuffer.pageInfo[first_page].top;
586 >                int y2 = mainBuffer.pageInfo[page - 1].bottom;
587 >                if (y1 <= last_scanline && ++y1 >= VIDEO_MODE_Y)
588 >                        continue;
589 >                if (y2 <= last_scanline && ++y2 >= VIDEO_MODE_Y)
590 >                        continue;
591 >                last_scanline = y2;
592 >
593 >                // Update the_host_buffer and copy of the_buffer, one line at a time
594                  int i1 = y1 * src_bytes_per_row;
595 <                int i2 = y1 * dst_bytes_per_row;
595 >                int i2 = y1 * scr_bytes_per_row;
596 > #ifdef USE_SDL_VIDEO
597 >                int bbi = 0;
598 >                SDL_Rect bb[3] = {
599 >                        { VIDEO_MODE_X, y1, 0, 0 },
600 >                        { VIDEO_MODE_X, -1, 0, 0 },
601 >                        { VIDEO_MODE_X, -1, 0, 0 }
602 >                };
603 > #endif
604                  VIDEO_DRV_LOCK_PIXELS;
605                  for (int j = y1; j <= y2; j++) {
606                          for (int i = 0; i < n_chunks; i++) {
607                                  if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size) != 0) {
608                                          memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size);
609                                          Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size);
610 + #ifdef USE_SDL_VIDEO
611 +                                        const int x = i * n_pixels;
612 +                                        if (x < bb[bbi].x) {
613 +                                                if (bb[bbi].w)
614 +                                                        bb[bbi].w += bb[bbi].x - x;
615 +                                                else
616 +                                                        bb[bbi].w = n_pixels;
617 +                                                bb[bbi].x = x;
618 +                                        }
619 +                                        else if (x >= bb[bbi].x + bb[bbi].w)
620 +                                                bb[bbi].w = x + n_pixels - bb[bbi].x;
621 + #endif
622                                  }
623                                  i1 += src_chunk_size;
624                                  i2 += dst_chunk_size;
# Line 492 | Line 630 | static inline void update_display_dga_vo
630                                  }
631                                  i1 += src_chunk_size_left;
632                                  i2 += dst_chunk_size_left;
633 <                        }
634 <                }
635 <                VIDEO_DRV_UNLOCK_PIXELS;
636 < #else
637 <                // Check for first chunk from left and first chunk from right that have changed
638 <                typedef uint64 chunk_t;
639 <                const int chunk_size = sizeof(chunk_t);
640 <                const int bytes_per_row = VIDEO_MODE_ROW_BYTES;
503 <
504 <                int i, j;
505 <                int b1 = bytes_per_row / chunk_size;
506 <                int b2 = 0;
507 <                for (j = y1; j <= y2; j++) {
508 <                        chunk_t * const p1 = (chunk_t *)(the_buffer + (j * bytes_per_row));
509 <                        chunk_t * const p2 = (chunk_t *)(the_buffer_copy + (j * bytes_per_row));
510 <                        for (i = 0; i < b1; i++) {
511 <                                if (p1[i] != p2[i]) {
512 <                                        b1 = i;
513 <                                        break;
633 > #ifdef USE_SDL_VIDEO
634 >                                const int x = n_chunks * n_pixels;
635 >                                if (x < bb[bbi].x) {
636 >                                        if (bb[bbi].w)
637 >                                                bb[bbi].w += bb[bbi].x - x;
638 >                                        else
639 >                                                bb[bbi].w = n_pixels_left;
640 >                                        bb[bbi].x = x;
641                                  }
642 +                                else if (x >= bb[bbi].x + bb[bbi].w)
643 +                                        bb[bbi].w  = x + n_pixels_left - bb[bbi].x;
644 + #endif
645                          }
646 <                        if (b1 > b2)
647 <                                b2 = b1;
648 <                        for (i = (bytes_per_row / chunk_size) - 1; i > b2; i--) {
649 <                                if (p1[i] != p2[i]) {
650 <                                        b2 = i;
651 <                                        break;
652 <                                }
646 >                        i2 += scr_bytes_left;
647 > #ifdef USE_SDL_VIDEO
648 >                        bb[bbi].h++;
649 >                        if (bb[bbi].w && (j == y1 || j == y2 - 1 || j == y2)) {
650 >                                bbi++;
651 >                                assert(bbi <= 3);
652 >                                if (j != y2)
653 >                                        bb[bbi].y = j + 1;
654                          }
655 + #endif
656                  }
657 <                b2++;
658 <
527 <                // Convert to pixel information
528 <                int x1, x2;
529 <                switch (VIDEO_MODE_DEPTH) {
530 <                case VIDEO_DEPTH_1BIT:  x1 = (b1 * chunk_size) << 3; x2 = (b2 * chunk_size) << 3;       break;
531 <                case VIDEO_DEPTH_2BIT:  x1 = (b1 * chunk_size) << 2; x2 = (b2 * chunk_size) << 2;       break;
532 <                case VIDEO_DEPTH_4BIT:  x1 = (b1 * chunk_size) << 1; x2 = (b2 * chunk_size) << 1;       break;
533 <                case VIDEO_DEPTH_8BIT:  x1 = b1 * chunk_size; x2 = b2 * chunk_size;                                     break;
534 <                case VIDEO_DEPTH_16BIT: x1 = (b1 * chunk_size) >> 1; x2 = (b2 * chunk_size) >> 1;       break;
535 <                case VIDEO_DEPTH_32BIT: x1 = (b1 * chunk_size) >> 2; x2 = (b2 * chunk_size) >> 2;       break;
536 <                }
537 <                const int width = x2 - x1;
538 <
539 <                // Normalize bounds for for the next blit
540 <                const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
541 <                const int dst_bytes_per_row = the_host_buffer_row_bytes;
542 <                const int dst_bytes_per_pixel = dst_bytes_per_row / VIDEO_MODE_X;
543 <                int i2 = y1 * dst_bytes_per_row + x1 * dst_bytes_per_pixel;
544 <                int i1, n_bytes;
545 <                if ((int)VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) {
546 <                        const int src_pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row;
547 <                        i1 = y1 * src_bytes_per_row + x1 / src_pixels_per_byte;
548 <                        n_bytes = width / src_pixels_per_byte;
549 <                } else {
550 <                        const int src_bytes_per_pixel = src_bytes_per_row / VIDEO_MODE_X;
551 <                        i1 = y1 * src_bytes_per_row + x1 * src_bytes_per_pixel;
552 <                        n_bytes = width * src_bytes_per_pixel;
553 <                }
554 <
555 <                // Update the_host_buffer and copy of the_buffer
556 <                VIDEO_DRV_LOCK_PIXELS;
557 <                for (j = y1; j <= y2; j++) {
558 <                        Screen_blit(the_host_buffer + i2, the_buffer + i1, n_bytes);
559 <                        memcpy(the_buffer_copy + i1, the_buffer + i1, n_bytes);
560 <                        i1 += src_bytes_per_row;
561 <                        i2 += dst_bytes_per_row;
562 <                }
563 <                VIDEO_DRV_UNLOCK_PIXELS;
657 > #ifdef USE_SDL_VIDEO
658 >                SDL_UpdateRects(drv->s, bbi, bb);
659   #endif
660 +                VIDEO_DRV_UNLOCK_PIXELS;
661          }
662          mainBuffer.dirty = false;
663   }
664   #endif
665 + #endif
666  
667   #endif /* ENABLE_VOSF */
668  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines