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 bytes_per_row); |
77 |
+ |
|
78 |
|
// Variables for Video on SEGV support |
79 |
|
static uint8 *the_host_buffer; // Host frame buffer in VOSF mode |
80 |
|
|
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; |
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; |
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 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 |
+ |
LOCK_VOSF; |
372 |
+ |
if (bytes_per_row >= screen_width) { |
373 |
+ |
const int bytes_per_pixel = bytes_per_row / screen_width; |
374 |
+ |
if (bytes_per_row <= mainBuffer.pageSize) { |
375 |
+ |
const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x * bytes_per_pixel; |
376 |
+ |
const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) * bytes_per_pixel; |
377 |
+ |
vosf_do_set_dirty_area(a0, a1); |
378 |
+ |
} else { |
379 |
+ |
for (int j = y; j < y + h; j++) { |
380 |
+ |
const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x * bytes_per_pixel; |
381 |
+ |
const uintptr a1 = a0 + (w - 1) * bytes_per_pixel; |
382 |
+ |
vosf_do_set_dirty_area(a0, a1); |
383 |
+ |
} |
384 |
+ |
} |
385 |
+ |
} else { |
386 |
+ |
const int pixels_per_byte = screen_width / bytes_per_row; |
387 |
+ |
if (bytes_per_row <= mainBuffer.pageSize) { |
388 |
+ |
const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x / pixels_per_byte; |
389 |
+ |
const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) / pixels_per_byte; |
390 |
+ |
vosf_do_set_dirty_area(a0, a1); |
391 |
+ |
} else { |
392 |
+ |
for (int j = y; j < y + h; j++) { |
393 |
+ |
const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x / pixels_per_byte; |
394 |
+ |
const uintptr a1 = mainBuffer.memStart + j * bytes_per_row + (x + w - 1) / pixels_per_byte; |
395 |
+ |
vosf_do_set_dirty_area(a0, a1); |
396 |
+ |
} |
397 |
+ |
} |
398 |
+ |
} |
399 |
+ |
mainBuffer.dirty = true; |
400 |
+ |
UNLOCK_VOSF; |
401 |
+ |
} |
402 |
+ |
|
403 |
+ |
|
404 |
+ |
/* |
405 |
|
* Screen fault handler |
406 |
|
*/ |
407 |
|
|
416 |
|
if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) { |
417 |
|
const int page = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits; |
418 |
|
LOCK_VOSF; |
419 |
< |
PFLAG_SET(page); |
420 |
< |
vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE); |
419 |
> |
if (PFLAG_ISCLEAR(page)) { |
420 |
> |
PFLAG_SET(page); |
421 |
> |
vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE); |
422 |
> |
} |
423 |
|
mainBuffer.dirty = true; |
424 |
|
UNLOCK_VOSF; |
425 |
|
return true; |