Pi Firmware: Multi-buffering now working

Change-Id: Ifeb39ed9a4178e2dc82eec72705b5e6829567bc6
soft_delitch
David Banks 2018-07-23 12:39:54 +01:00
rodzic b1fb1a0fd8
commit 4aee47b3bb
4 zmienionych plików z 42 dodań i 47 usunięć

Wyświetl plik

@ -12,8 +12,11 @@
// #define USE_PROPERTY_INTERFACE_FOR_FB
// Enable double buffering and vsync based page flipping
#define DOUBLE_BUFFER
// Enable multiple buffering and vsync based page flipping
#define MULTI_BUFFER
// The number of buffers used by multi-buffering
#define NBUFFERS 3
#define VSYNCINT 16
@ -35,12 +38,10 @@
#define BIT_CLEAR 0x100
#define BIT_SPARE 0x200
#define OFFSET_LAST_BUFFER 10
#define OFFSET_DISP_BUFFER 12
#define OFFSET_LAST_BUFFER 12
#define OFFSET_CURR_BUFFER 14
#define MASK_LAST_BUFFER (3 << OFFSET_LAST_BUFFER)
#define MASK_DISP_BUFFER (3 << OFFSET_DISP_BUFFER)
#define MASK_CURR_BUFFER (3 << OFFSET_CURR_BUFFER)
// R0 return value bits

Wyświetl plik

@ -189,9 +189,6 @@ void osd_clear() {
if (active) {
memset(buffer, 0, sizeof(buffer));
osd_update((uint32_t *)fb, pitch);
#ifdef DOUBLE_BUFFER
osd_update((uint32_t *)(fb + SCREEN_HEIGHT * pitch), pitch);
#endif
active = 0;
RPI_SetGpioValue(LED1_PIN, active);
update_palette();
@ -212,9 +209,6 @@ void osd_set(int line, int attr, char *text) {
}
strncpy(buffer + line * LINELEN, text, len);
osd_update((uint32_t *)fb, pitch);
#ifdef DOUBLE_BUFFER
osd_update((uint32_t *)(fb + SCREEN_HEIGHT * pitch), pitch);
#endif
}

Wyświetl plik

@ -22,7 +22,7 @@
ldr r0, [r0]
tst r0, #(1<<VSYNCINT)
beq novsync\@
#ifndef DOUBLE_BUFFER
#ifndef MULTI_BUFFER
ldr r0, =SMICTRL
mov r10, #0
str r10, [r0]
@ -33,8 +33,8 @@ novsync\@:
.endm
.macro POLL_VSYNC
#ifdef DOUBLE_BUFFER
// Skip the double buffering in mode 7 and probe mode
#ifdef MULTI_BUFFER
// Skip the multi buffering in mode 7 and probe mode
tst r3, #(BIT_MODE7 | BIT_PROBE)
bne novsync\@
// Poll for the VSYNC interrupt
@ -46,13 +46,10 @@ novsync\@:
ldr r0, =SMICTRL
mov r10, #0
str r10, [r0]
// Copy the last completed draw buffer number to the display buffer
// Flip to the last completed draw buffer
push {r0-r3}
mov r0, r3, lsr #OFFSET_LAST_BUFFER
and r0, r0, #3
bic r3, r3, #MASK_DISP_BUFFER
orr r3, r3, r0, lsl #OFFSET_DISP_BUFFER
// And then flip the display to it
push {r0-r3}
bl swapBuffer
pop {r0-r3}
novsync\@:
@ -196,13 +193,15 @@ rgb_to_fb:
// Save the parameters so the registers can be reused
str r0, param_framebuffer0
#ifdef DOUBLE_BUFFER
#ifdef MULTI_BUFFER
ldr r10, =SCREEN_HEIGHT
mul r10, r10, r2
add r0, r10
str r0, param_framebuffer1
add r0, r10
str r0, param_framebuffer2
add r0, r10
str r0, param_framebuffer3
// Default to displaying buffer 0 in Mode 7 (or on probe)
tst r3, #(BIT_MODE7 | BIT_PROBE)
beq skip_swap
@ -229,8 +228,8 @@ skip_swap:
orr r3, r8
// In Mode 7 (or on probe) write to buffer 0, display buffer 0
bic r3, r3, #(MASK_LAST_BUFFER | MASK_DISP_BUFFER | MASK_CURR_BUFFER)
#ifdef DOUBLE_BUFFER
bic r3, r3, #(MASK_LAST_BUFFER | MASK_CURR_BUFFER)
#ifdef MULTI_BUFFER
tst r3, #(BIT_MODE7 | BIT_PROBE)
// In modes 0..6, restore the previous buffer state
ldreq r10, buffer_state
@ -261,28 +260,26 @@ frame:
// r12 = pointer into frame buffer (moves within line)
// Pick the next draw buffer
// In Mode 7, or if DOUBLE_BUFFER disabled, than draw to 0
// In Mode 7, or if MULTI_BUFFER disabled, than draw to 0
// else draw to the "spare" buffer
mov r0, #0
ldr r11, param_framebuffer0
#ifdef DOUBLE_BUFFER
#ifdef MULTI_BUFFER
tst r3, #(BIT_MODE7 | BIT_PROBE)
bne buffer_chosen
// Draw to the buffers cyclically
// r8 is the last completed buffer
mov r8, r3, lsr #OFFSET_LAST_BUFFER
and r8, r8, #3
// r9 is the current display buffer
mov r9, r3, lsr #OFFSET_DISP_BUFFER
and r9, r9, #3
// find the buffer that is neither of these
cmp r0, r8
cmpne r0, r9
bne buffer_chosen
// Last buffer 2: Current buffer 0
cmp r8, #2
beq buffer_chosen
mov r0, #1
ldr r11, param_framebuffer1
cmp r0, r8
cmpne r0, r9
bne buffer_chosen
// Last buffer 0: Current buffer 1
cmp r8, #0
beq buffer_chosen
// Last buffer 1: Current buffer 2
mov r0, #2
ldr r11, param_framebuffer2
buffer_chosen:
@ -459,7 +456,7 @@ next_line:
pop {r0-r12, lr}
skip_osd_update:
#ifdef DOUBLE_BUFFER
#ifdef MULTI_BUFFER
// Update the last drawn buffer
mov r0, r3, lsr #OFFSET_CURR_BUFFER
and r0, #3
@ -479,9 +476,9 @@ skip_osd_update:
// Return
exit:
#ifdef DOUBLE_BUFFER
#ifdef MULTI_BUFFER
// Save the old buffer state before exiting
and r3, r3, #(MASK_LAST_BUFFER | MASK_DISP_BUFFER)
and r3, r3, #MASK_LAST_BUFFER
str r3, buffer_state
// Return the current buffer state
orr r0, r0, r3
@ -592,10 +589,10 @@ measure_vsync:
clear_screen:
ldr r11, param_framebuffer0
ldr r8, =0x88888888
#ifdef DOUBLE_BUFFER
ldr r5, =SCREEN_HEIGHT * 3 // double the number of active lines
#ifdef MULTI_BUFFER
ldr r5, =SCREEN_HEIGHT * NBUFFERS
#else
ldr r5, =SCREEN_HEIGHT // double the number of active lines
ldr r5, =SCREEN_HEIGHT
#endif
clear_loop1:
mov r6, r2 // r2 is bytes per line
@ -613,13 +610,16 @@ clear_loop2:
param_framebuffer0:
.word 0
#ifdef DOUBLE_BUFFER
#ifdef MULTI_BUFFER
param_framebuffer1:
.word 0
param_framebuffer2:
.word 0
param_framebuffer3:
.word 0
buffer_state:
.word 0

Wyświetl plik

@ -151,8 +151,8 @@ static void init_framebuffer(int mode7) {
RPI_PropertyInit();
RPI_PropertyAddTag( TAG_ALLOCATE_BUFFER );
RPI_PropertyAddTag( TAG_SET_PHYSICAL_SIZE, w, SCREEN_HEIGHT );
#ifdef DOUBLE_BUFFER
RPI_PropertyAddTag( TAG_SET_VIRTUAL_SIZE, w, SCREEN_HEIGHT * 3 );
#ifdef MULTI_BUFFER
RPI_PropertyAddTag( TAG_SET_VIRTUAL_SIZE, w, SCREEN_HEIGHT * NBUFFERS );
#else
RPI_PropertyAddTag( TAG_SET_VIRTUAL_SIZE, w, SCREEN_HEIGHT );
#endif
@ -210,8 +210,8 @@ static void init_framebuffer(int mode7) {
fbp->width = w;
fbp->height = SCREEN_HEIGHT;
fbp->virtual_width = w;
#ifdef DOUBLE_BUFFER
fbp->virtual_height = SCREEN_HEIGHT * 3;
#ifdef MULTI_BUFFER
fbp->virtual_height = SCREEN_HEIGHT * NBUFFERS;
#else
fbp->virtual_height = SCREEN_HEIGHT;
#endif
@ -335,7 +335,7 @@ static int calibrate_clock() {
// Correct for non-interlaced mode
if (!(frame_time & INTERLACED_FLAG)) {
//f2 *= 625.0 / 624.0;
f2 *= 626.0 / 624.0;
}
// Dump the target PLL frequency
@ -738,7 +738,7 @@ int total_N_frames(int n, int mode7, int elk, int chars_per_line) {
}
#endif
#ifdef DOUBLE_BUFFER
#ifdef MULTI_BUFFER
void swapBuffer(int buffer) {
// Flush the previous response from the GPU->ARM mailbox
// Doing it like this avoids stalling for the response