~ubuntu-branches/ubuntu/feisty/basilisk2/feisty

« back to all changes in this revision

Viewing changes to src/Unix/video_vosf.h

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2005-07-30 20:42:20 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050730204220-1nl1cg2jkjvy63ry
Tags: 0.9.20050730-1
* New upstream CVS snapshot.
* Build-depend on virtual libsdl-dev (not libsdl1.2-dev).
* Invoke init rules also on clean (to separate better from official
  builds).
* Update URL of upstream source in debian/copyright.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  video_vosf.h - Video/graphics emulation, video on SEGV signals support
3
3
 *
4
 
 *  Basilisk II (C) 1997-2002 Christian Bauer
 
4
 *  Basilisk II (C) 1997-2005 Christian Bauer
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
21
21
#ifndef VIDEO_VOSF_H
22
22
#define VIDEO_VOSF_H
23
23
 
24
 
// Note: this file is #include'd in video_x.cpp
 
24
// Note: this file must be #include'd only in video_x.cpp
25
25
#ifdef ENABLE_VOSF
26
26
 
27
 
#include <fcntl.h>
28
 
#include <sys/mman.h>
29
27
#include "sigsegv.h"
30
28
#include "vm_alloc.h"
 
29
#ifdef _WIN32
 
30
#include "util_windows.h"
 
31
#endif
31
32
 
32
 
// Glue for SheepShaver and BasiliskII
33
 
#if POWERPC_ROM
34
 
#define X11_MONITOR_INIT                /* nothing */
35
 
#define VIDEO_DRV_INIT                  /* nothing */
 
33
// Glue for SDL and X11 support
 
34
#ifdef USE_SDL_VIDEO
 
35
#define MONITOR_INIT                    SDL_monitor_desc &monitor
 
36
#define VIDEO_DRV_WIN_INIT              driver_window *drv
 
37
#define VIDEO_DRV_DGA_INIT              driver_fullscreen *drv
 
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)
 
40
#define VIDEO_DRV_DEPTH                 drv->s->format->BitsPerPixel
 
41
#define VIDEO_DRV_WIDTH                 drv->s->w
 
42
#define VIDEO_DRV_HEIGHT                drv->s->h
 
43
#define VIDEO_DRV_ROW_BYTES             drv->s->pitch
 
44
#else
 
45
#ifdef SHEEPSHAVER
 
46
#define MONITOR_INIT                    /* nothing */
 
47
#define VIDEO_DRV_WIN_INIT              /* nothing */
 
48
#define VIDEO_DRV_DGA_INIT              /* nothing */
36
49
#define VIDEO_DRV_WINDOW                the_win
37
50
#define VIDEO_DRV_GC                    the_gc
38
51
#define VIDEO_DRV_IMAGE                 img
39
52
#define VIDEO_DRV_HAVE_SHM              have_shm
40
 
#define VIDEO_MODE_INIT                 VideoInfo const & mode = VModes[cur_mode]
41
 
#define VIDEO_MODE_ROW_BYTES    mode.viRowBytes
42
 
#define VIDEO_MODE_X                    mode.viXsize
43
 
#define VIDEO_MODE_Y                    mode.viYsize
44
 
#define VIDEO_MODE_DEPTH                mode.viAppleMode
45
 
enum {
46
 
  VIDEO_DEPTH_1BIT = APPLE_1_BIT,
47
 
  VIDEO_DEPTH_2BIT = APPLE_2_BIT,
48
 
  VIDEO_DEPTH_4BIT = APPLE_4_BIT,
49
 
  VIDEO_DEPTH_8BIT = APPLE_8_BIT,
50
 
  VIDEO_DEPTH_16BIT = APPLE_16_BIT,
51
 
  VIDEO_DEPTH_32BIT = APPLE_32_BIT
52
 
};
53
53
#else
54
 
#define X11_MONITOR_INIT                X11_monitor_desc &monitor
55
 
#define VIDEO_DRV_INIT                  driver_window *drv
 
54
#define MONITOR_INIT                    X11_monitor_desc &monitor
 
55
#define VIDEO_DRV_WIN_INIT              driver_window *drv
 
56
#define VIDEO_DRV_DGA_INIT              driver_dga *drv
56
57
#define VIDEO_DRV_WINDOW                drv->w
57
58
#define VIDEO_DRV_GC                    drv->gc
58
59
#define VIDEO_DRV_IMAGE                 drv->img
59
60
#define VIDEO_DRV_HAVE_SHM              drv->have_shm
60
 
#define VIDEO_MODE_INIT                 video_mode const & mode = drv->monitor.get_current_mode();
61
 
#define VIDEO_MODE_ROW_BYTES    mode.bytes_per_row
62
 
#define VIDEO_MODE_X                    mode.x
63
 
#define VIDEO_MODE_Y                    mode.y
64
 
#define VIDEO_MODE_DEPTH                (int)mode.depth
65
 
enum {
66
 
  VIDEO_DEPTH_1BIT = VDEPTH_1BIT,
67
 
  VIDEO_DEPTH_2BIT = VDEPTH_2BIT,
68
 
  VIDEO_DEPTH_4BIT = VDEPTH_4BIT,
69
 
  VIDEO_DEPTH_8BIT = VDEPTH_8BIT,
70
 
  VIDEO_DEPTH_16BIT = VDEPTH_16BIT,
71
 
  VIDEO_DEPTH_32BIT = VDEPTH_32BIT
72
 
};
 
61
#endif
 
62
#define VIDEO_DRV_LOCK_PIXELS   /* nothing */
 
63
#define VIDEO_DRV_UNLOCK_PIXELS /* nothing */
 
64
#define VIDEO_DRV_DEPTH                 VIDEO_DRV_IMAGE->depth
 
65
#define VIDEO_DRV_WIDTH                 VIDEO_DRV_IMAGE->width
 
66
#define VIDEO_DRV_HEIGHT                VIDEO_DRV_IMAGE->height
 
67
#define VIDEO_DRV_ROW_BYTES             VIDEO_DRV_IMAGE->bytes_per_line
73
68
#endif
74
69
 
75
70
// Variables for Video on SEGV support
88
83
    uint32 pageCount;                   // Number of pages allocated to the screen
89
84
    
90
85
        bool dirty;                                     // Flag: set if the frame buffer was touched
 
86
        bool very_dirty;                        // Flag: set if the frame buffer was completely modified (e.g. colormap changes)
91
87
    char * dirtyPages;                  // Table of flags set if page was altered
92
88
    ScreenPageInfo * pageInfo;  // Table of mappings page -> Mac scanlines
93
89
};
133
129
#define PFLAG_CLEAR_ALL do { \
134
130
        PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount); \
135
131
        mainBuffer.dirty = false; \
 
132
        mainBuffer.very_dirty = false; \
 
133
} while (0)
 
134
 
 
135
#define PFLAG_SET_VERY_DIRTY do { \
 
136
        mainBuffer.very_dirty = true; \
136
137
} while (0)
137
138
 
138
139
// Set the following macro definition to 1 if your system
167
168
#endif
168
169
}
169
170
 
170
 
#ifdef HAVE_PTHREADS
 
171
#if defined(HAVE_PTHREADS)
171
172
static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER;   // Mutex to protect frame buffer (dirtyPages in fact)
172
173
#define LOCK_VOSF pthread_mutex_lock(&vosf_lock);
173
174
#define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock);
 
175
#elif defined(_WIN32)
 
176
static mutex_t vosf_lock;                                                                               // Mutex to protect frame buffer (dirtyPages in fact)
 
177
#define LOCK_VOSF vosf_lock.lock();
 
178
#define UNLOCK_VOSF vosf_lock.unlock();
 
179
#elif defined(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)
174
183
#else
175
184
#define LOCK_VOSF
176
185
#define UNLOCK_VOSF
190
199
// Extend size to page boundary
191
200
static uint32 page_extend(uint32 size)
192
201
{
193
 
        const uint32 page_size = getpagesize();
 
202
        const uint32 page_size = vm_get_page_size();
194
203
        const uint32 page_mask = page_size - 1;
195
204
        return (size + page_mask) & ~page_mask;
196
205
}
197
206
 
198
207
 
199
208
/*
 
209
 *  Check if VOSF acceleration is profitable on this platform
 
210
 */
 
211
 
 
212
const int VOSF_PROFITABLE_TRIES = 3;                    // Make 3 attempts for full screen update
 
213
const int VOSF_PROFITABLE_THRESHOLD = 16667;    // 60 Hz
 
214
 
 
215
static bool video_vosf_profitable(void)
 
216
{
 
217
        int64 durations[VOSF_PROFITABLE_TRIES];
 
218
        int mean_duration = 0;
 
219
 
 
220
        for (int i = 0; i < VOSF_PROFITABLE_TRIES; i++) {
 
221
                uint64 start = GetTicks_usec();
 
222
                for (int p = 0; p < mainBuffer.pageCount; p++) {
 
223
                        uint8 *addr = (uint8 *)(mainBuffer.memStart + (p * mainBuffer.pageSize));
 
224
                        addr[0] = 0; // Trigger Screen_fault_handler()
 
225
                }
 
226
                int64 duration = GetTicks_usec() - start;
 
227
                mean_duration += duration;
 
228
                durations[i] = duration;
 
229
 
 
230
                PFLAG_CLEAR_ALL;
 
231
                mainBuffer.dirty = false;
 
232
                if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
 
233
                        return false;
 
234
        }
 
235
 
 
236
        mean_duration /= VOSF_PROFITABLE_TRIES;
 
237
        D(bug("Triggered %d screen faults in %ld usec on average\n", mainBuffer.pageCount, mean_duration));
 
238
        return (mean_duration < (VOSF_PROFITABLE_THRESHOLD * (frame_skip ? frame_skip : 1)));
 
239
}
 
240
 
 
241
 
 
242
/*
200
243
 *  Initialize the VOSF system (mainBuffer structure, SIGSEGV handler)
201
244
 */
202
245
 
203
 
#if !EMULATED_PPC && !POWERPC_ROM
204
 
static
205
 
#endif
206
 
bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
207
 
 
208
 
static bool video_vosf_init(X11_MONITOR_INIT)
 
246
static bool video_vosf_init(MONITOR_INIT)
209
247
{
210
 
        VIDEO_MODE_INIT;
 
248
        VIDEO_MODE_INIT_MONITOR;
211
249
 
212
 
        const uintptr page_size = getpagesize();
 
250
        const uintptr page_size = vm_get_page_size();
213
251
        const uintptr page_mask = page_size - 1;
214
252
        
215
253
        // Round up frame buffer base to page boundary
260
298
        if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
261
299
                return false;
262
300
        
263
 
#if !EMULATED_PPC && !POWERPC_ROM
264
 
        // Initialize the handler for SIGSEGV
265
 
        if (!sigsegv_install_handler(Screen_fault_handler))
266
 
                return false;
267
 
#endif
268
 
        
269
301
        // The frame buffer is sane, i.e. there is no write to it yet
270
302
        mainBuffer.dirty = false;
271
303
        return true;
320
352
 *      Update display for Windowed mode and VOSF
321
353
 */
322
354
 
323
 
// From video_blit.cpp
324
 
extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length);
325
 
extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, int mac_depth);
326
 
extern uint32 ExpandMap[256];
327
 
 
328
355
/*      How can we deal with array overrun conditions ?
329
356
        
330
357
        The state of the framebuffer pages that have been touched are maintained
358
385
        than pageCount.
359
386
*/
360
387
 
361
 
static inline void update_display_window_vosf(VIDEO_DRV_INIT)
 
388
static void update_display_window_vosf(VIDEO_DRV_WIN_INIT)
362
389
{
363
390
        VIDEO_MODE_INIT;
364
391
 
380
407
                const int y1 = mainBuffer.pageInfo[first_page].top;
381
408
                const int y2 = mainBuffer.pageInfo[page - 1].bottom;
382
409
                const int height = y2 - y1 + 1;
383
 
                
384
 
                if (VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) {
385
 
 
386
 
                        // Update the_host_buffer and copy of the_buffer
387
 
                        const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
388
 
                        const int dst_bytes_per_row = VIDEO_DRV_IMAGE->bytes_per_line;
389
 
                        const int pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row;
390
 
                        int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
391
 
                        for (j = y1; j <= y2; j++) {
392
 
                                Screen_blit(the_host_buffer + i2, the_buffer + i1, VIDEO_MODE_X / pixels_per_byte);
393
 
                                i1 += src_bytes_per_row;
394
 
                                i2 += dst_bytes_per_row;
395
 
                        }
396
 
 
397
 
                } else {
398
 
 
399
 
                        // Update the_host_buffer and copy of the_buffer
400
 
                        const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
401
 
                        const int dst_bytes_per_row = VIDEO_DRV_IMAGE->bytes_per_line;
402
 
                        const int bytes_per_pixel = src_bytes_per_row / VIDEO_MODE_X;
403
 
                        int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
404
 
                        for (j = y1; j <= y2; j++) {
405
 
                                Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * VIDEO_MODE_X);
406
 
                                i1 += src_bytes_per_row;
407
 
                                i2 += dst_bytes_per_row;
408
 
                        }
 
410
 
 
411
                // Update the_host_buffer
 
412
                VIDEO_DRV_LOCK_PIXELS;
 
413
                const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
 
414
                const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES;
 
415
                int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
 
416
                for (j = y1; j <= y2; j++) {
 
417
                        Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row);
 
418
                        i1 += src_bytes_per_row;
 
419
                        i2 += dst_bytes_per_row;
409
420
                }
 
421
                VIDEO_DRV_UNLOCK_PIXELS;
410
422
 
 
423
#ifdef USE_SDL_VIDEO
 
424
                SDL_UpdateRect(drv->s, 0, y1, VIDEO_MODE_X, height);
 
425
#else
411
426
                if (VIDEO_DRV_HAVE_SHM)
412
427
                        XShmPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height, 0);
413
428
                else
414
429
                        XPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height);
 
430
#endif
415
431
        }
416
432
        mainBuffer.dirty = false;
417
433
}
423
439
 */
424
440
 
425
441
#if REAL_ADDRESSING || DIRECT_ADDRESSING
426
 
static inline void update_display_dga_vosf(void)
 
442
static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT)
427
443
{
428
444
        VIDEO_MODE_INIT;
429
445
 
430
 
        int page = 0;
 
446
        // Compute number of bytes per row, take care to virtual screens
 
447
        const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
 
448
        const int dst_bytes_per_row = TrivialBytesPerRow(VIDEO_MODE_X, DepthModeForPixelDepth(VIDEO_DRV_DEPTH));
 
449
        const int scr_bytes_per_row = VIDEO_DRV_ROW_BYTES;
 
450
        assert(dst_bytes_per_row <= scr_bytes_per_row);
 
451
        const int scr_bytes_left = scr_bytes_per_row - dst_bytes_per_row;
 
452
 
 
453
        // Full screen update requested?
 
454
        if (mainBuffer.very_dirty) {
 
455
                PFLAG_CLEAR_ALL;
 
456
                vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ);
 
457
                memcpy(the_buffer_copy, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
 
458
                VIDEO_DRV_LOCK_PIXELS;
 
459
                int i1 = 0, i2 = 0;
 
460
                for (int j = 0;  j < VIDEO_MODE_Y; j++) {
 
461
                        Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row);
 
462
                        i1 += src_bytes_per_row;
 
463
                        i2 += scr_bytes_per_row;
 
464
                }
 
465
#ifdef USE_SDL_VIDEO
 
466
                SDL_UpdateRect(drv->s, 0, 0, VIDEO_MODE_X, VIDEO_MODE_Y);
 
467
#endif
 
468
                VIDEO_DRV_UNLOCK_PIXELS;
 
469
                return;
 
470
        }
 
471
 
 
472
        // Setup partial blitter (use 64-pixel wide chunks)
 
473
        const int n_pixels = 64;
 
474
        const int n_chunks = VIDEO_MODE_X / n_pixels;
 
475
        const int n_pixels_left = VIDEO_MODE_X - (n_chunks * n_pixels);
 
476
        const int src_chunk_size = src_bytes_per_row / n_chunks;
 
477
        const int dst_chunk_size = dst_bytes_per_row / n_chunks;
 
478
        const int src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size);
 
479
        const int dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size);
 
480
 
 
481
        int page = 0, last_scanline = -1;
431
482
        for (;;) {
432
483
                const unsigned first_page = find_next_page_set(page);
433
484
                if (first_page >= mainBuffer.pageCount)
440
491
                const int32 offset  = first_page << mainBuffer.pageBits;
441
492
                const uint32 length = (page - first_page) << mainBuffer.pageBits;
442
493
                vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ);
443
 
                
444
 
                // I am sure that y2 >= y1 and depth != 1
445
 
                const int y1 = mainBuffer.pageInfo[first_page].top;
446
 
                const int y2 = mainBuffer.pageInfo[page - 1].bottom;
447
 
                
448
 
                const int bytes_per_row = VIDEO_MODE_ROW_BYTES;
449
 
                const int bytes_per_pixel = VIDEO_MODE_ROW_BYTES / VIDEO_MODE_X;
450
 
                int i, j;
451
 
                
452
 
                // Check for first column from left and first column
453
 
                // from right that have changed
454
 
                int x1 = VIDEO_MODE_X * bytes_per_pixel - 1;
455
 
                for (j = y1; j <= y2; j++) {
456
 
                        uint8 * const p1 = &the_buffer[j * bytes_per_row];
457
 
                        uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
458
 
                        for (i = 0; i < x1; i++) {
459
 
                                if (p1[i] != p2[i]) {
460
 
                                        x1 = i;
461
 
                                        break;
462
 
                                }
463
 
                        }
464
 
                }
465
 
                x1 /= bytes_per_pixel;
466
 
                
467
 
                int x2 = x1 * bytes_per_pixel;
468
 
                for (j = y2; j >= y1; j--) {
469
 
                        uint8 * const p1 = &the_buffer[j * bytes_per_row];
470
 
                        uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
471
 
                        for (i = VIDEO_MODE_X * bytes_per_pixel - 1; i > x2; i--) {
472
 
                                if (p1[i] != p2[i]) {
473
 
                                        x2 = i;
474
 
                                        break;
475
 
                                }
476
 
                        }
477
 
                }
478
 
                x2 /= bytes_per_pixel;
479
 
                
480
 
                // Update the_host_buffer and copy of the_buffer
481
 
                // There should be at least one pixel to copy
482
 
                const int width = x2 - x1 + 1;
483
 
                i = y1 * bytes_per_row + x1 * bytes_per_pixel;
484
 
                for (j = y1; j <= y2; j++) {
485
 
                        Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width);
486
 
                        memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width);
487
 
                        i += bytes_per_row;
488
 
                }
 
494
 
 
495
                // Optimized for scanlines, don't process overlapping lines again
 
496
                int y1 = mainBuffer.pageInfo[first_page].top;
 
497
                int y2 = mainBuffer.pageInfo[page - 1].bottom;
 
498
                if (y1 <= last_scanline && ++y1 >= VIDEO_MODE_Y)
 
499
                        continue;
 
500
                if (y2 <= last_scanline && ++y2 >= VIDEO_MODE_Y)
 
501
                        continue;
 
502
                last_scanline = y2;
 
503
 
 
504
                // Update the_host_buffer and copy of the_buffer, one line at a time
 
505
                int i1 = y1 * src_bytes_per_row;
 
506
                int i2 = y1 * scr_bytes_per_row;
 
507
#ifdef USE_SDL_VIDEO
 
508
                int bbi = 0;
 
509
                SDL_Rect bb[3] = {
 
510
                        { VIDEO_MODE_X, y1, 0, 0 },
 
511
                        { VIDEO_MODE_X, -1, 0, 0 },
 
512
                        { VIDEO_MODE_X, -1, 0, 0 }
 
513
                };
 
514
#endif
 
515
                VIDEO_DRV_LOCK_PIXELS;
 
516
                for (int j = y1; j <= y2; j++) {
 
517
                        for (int i = 0; i < n_chunks; i++) {
 
518
                                if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size) != 0) {
 
519
                                        memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size);
 
520
                                        Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size);
 
521
#ifdef USE_SDL_VIDEO
 
522
                                        const int x = i * n_pixels;
 
523
                                        if (x < bb[bbi].x) {
 
524
                                                if (bb[bbi].w)
 
525
                                                        bb[bbi].w += bb[bbi].x - x;
 
526
                                                else
 
527
                                                        bb[bbi].w = n_pixels;
 
528
                                                bb[bbi].x = x;
 
529
                                        }
 
530
                                        else if (x >= bb[bbi].x + bb[bbi].w)
 
531
                                                bb[bbi].w = x + n_pixels - bb[bbi].x;
 
532
#endif
 
533
                                }
 
534
                                i1 += src_chunk_size;
 
535
                                i2 += dst_chunk_size;
 
536
                        }
 
537
                        if (src_chunk_size_left && dst_chunk_size_left) {
 
538
                                if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left) != 0) {
 
539
                                        memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left);
 
540
                                        Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size_left);
 
541
                                }
 
542
                                i1 += src_chunk_size_left;
 
543
                                i2 += dst_chunk_size_left;
 
544
#ifdef USE_SDL_VIDEO
 
545
                                const int x = n_chunks * n_pixels;
 
546
                                if (x < bb[bbi].x) {
 
547
                                        if (bb[bbi].w)
 
548
                                                bb[bbi].w += bb[bbi].x - x;
 
549
                                        else
 
550
                                                bb[bbi].w = n_pixels_left;
 
551
                                        bb[bbi].x = x;
 
552
                                }
 
553
                                else if (x >= bb[bbi].x + bb[bbi].w)
 
554
                                        bb[bbi].w  = x + n_pixels_left - bb[bbi].x;
 
555
#endif
 
556
                        }
 
557
                        i2 += scr_bytes_left;
 
558
#ifdef USE_SDL_VIDEO
 
559
                        bb[bbi].h++;
 
560
                        if (bb[bbi].w && (j == y1 || j == y2 - 1 || j == y2)) {
 
561
                                bbi++;
 
562
                                assert(bbi <= 3);
 
563
                                if (j != y2)
 
564
                                        bb[bbi].y = j + 1;
 
565
                        }
 
566
#endif
 
567
                }
 
568
#ifdef USE_SDL_VIDEO
 
569
                SDL_UpdateRects(drv->s, bbi, bb);
 
570
#endif
 
571
                VIDEO_DRV_UNLOCK_PIXELS;
489
572
        }
490
573
        mainBuffer.dirty = false;
491
574
}