I'm interested in learning more about the virtual framebuffer (although I don't know much about graphics theory).
In the frame buffer structure, there are some fields relating to virtual width, virtual height, x and y offset.
I've read in a few places (including some replies to an old post of mine http://www.raspberrypi.org/phpBB3/viewt ... 6&p=264141) that to improve performace, the virtual framebuffer can be set to twice the size of the physical framebuffer (eg, if the physical screen is 800x600, set the virtual to 800*1200), which creates a physcial and a virtual screen.
I think the offset can then be used to 'flip' between these screens, so the background buffer can be updated, then 'flipped' over onto the physical screen.
Is this correct? If so, other than setting the virtual height in the framebuffer structure, how is this implemented? What 'flips' these buffers, and is it really faster than writing directly to the framebuffer?
If there's already some good information or tutorials out there, please let me know (I've had a look, but I can't find much).
Thankyou for your help
Re: Virtual Frame Buffer
Hi
I use this
With the following macro-
Now I use in my kernel.asm
which returns the graphic area to be written in R12 the use FlipScreen to display the backbuffer!
I use this
Code: Select all
InitVSync: stmfd sp!, {r0-r1, lr}
move r0, 0x2000B214
move r1, 0x00010000
str r1, [r0]
move r0, 0x20600000
mov r1, 0
str r1, [r0]
.Exit: ldmfd sp!, {r0-r1, pc}
FlipScreen: ;;; Enter with:-
;;; Nothing
;;; Leave with:-
;;; r12=Pointer to screen buffer to write to.
stmfd sp!, {r0-r5, lr}
move r0, FrameBufferStructure
ldr r1, [r0, 28]
cmp r1, 0
beq .SetDisplayHigherHalf
.SetDisplayLowerHalf: mov r1, 0
b .Continue
.SetDisplayHigherHalf: ldr r1, [r0, 4]
.Continue: str r1, [r0, 28]
b SetScreen.ByPassEntry
SetScreen: stmfd sp!, {r0-r5, lr}
.ByPassEntry: move r0, 0x2000B208
.LoopVSync: ldr r1, [r0]
tst r1, 0x00010000
beq .LoopVSync
;;; Tell GPU about FrameBuffer structure
.MailWriteLoop: move r1, PERIPHERAL_BASE + MAIL_BASE + MAIL_STATUS
ldr r0, [r1]
and r0, r0, MAIL_FULL
cmp r0, MAIL_FULL
beq .MailWriteLoop
;bl SmallDelay
move r0, FrameBufferStructure+BUS_ADDRESSES_l2CACHE_ENABLED
orr r0, r0, 1
move r1, PERIPHERAL_BASE + MAIL_BASE + MAIL_WRITE + MAIL_FB
str r0, [r1]
;bl SmallDelay
;;; See if GPU knows about required frame buffer structure
.MailReadLoop: move r1, PERIPHERAL_BASE + MAIL_BASE + MAIL_STATUS
ldr r0, [r1]
and r0, r0, MAIL_EMPTY
cmp r0, MAIL_EMPTY
beq .MailReadLoop
;bl SmallDelay
move r1, PERIPHERAL_BASE + MAIL_BASE + MAIL_READ
ldr r0, [r1]
mov r3, 0
and r0, r0, 0xf
cmp r0, MAIL_FB
bne .MailReadLoop
and r3, r3, 0xFFFFFFF0
cmp r3, 0
bne .MailWriteLoop
move r0, FrameBufferStructure.ScreenPointer ;FRAME_BUFFER_ADDRESS+0x20;0xa00020
ldr r0, [r0]
cmp r0, 0
beq .MailWriteLoop
move r0, FrameBufferStructure
ldr r1, [r0, 28]
ldr r12, [r0, 32]
cmp r1, 0
beq .SetPointerHighHalf
.SetPointerLowHalf: b .Exit
.SetPointerHighHalf: move r1, (SCREEN_WIDTH*SCREEN_HEIGHT*4)
add r12, r1
.Exit: ldmfd sp!, {r0-r5, pc}
align 16
FrameBufferStructure:
.PhysicalWidth: dw SCREEN_WIDTH ;;; 0
.PhysicalHeight: dw SCREEN_HEIGHT ;;; 4
.VirtualWidth: dw SCREEN_WIDTH ;;; 8
.VirtualHeight: dw SCREEN_HEIGHT*2 ;;; 12
.Pitch: dw 0 ;;; 16
.BitDepth: dw SCREEN_BIT_DEPTH ;;; 20
.DisplayXOffset: dw 0 ;;; 24
.DisplayYOffset: dw 0 ;;; 28
.ScreenPointer: dw 0 ;;; 32
.ScreenFrameSize: dw 0 ;;; 36Code: Select all
macro move reg,immediate {
mov reg,(immediate) and $FF
orr reg,(immediate) and $FF00
orr reg,(immediate) and $FF0000
orr reg,(immediate) and $FF000000
}Code: Select all
bl InitVSync
bl SetScreenRe: Virtual Frame Buffer
I'm not great with ARM assembly yet, but it looks like you're trying to do this:
1. Set the virtual framebuffer to twice the size of the physical screen (vertically) in the structure
2. Call 'vsync' - I don't understand this yet
3. Use 'setscreen' to setup the framebuffer (using the mailbox)
4. Check if the Y offset is upper or lower half of the framebuffer. Update the pointer offset accordingly (to write to either the top or bottom half of the virtual framebuffer)
Then it looks like you have 'flipscreen' to alternate between the top and bottom half.
Is this right so far?
Is one of the buffer's 'active', meaning it's contents are displayed on the screen, while the other is the one I should write to? Then, when I've finished writing to the 'passive' buffer, I can 'flip' it, and it becomes what is seen on the screen?
Thanks again for your help.
1. Set the virtual framebuffer to twice the size of the physical screen (vertically) in the structure
2. Call 'vsync' - I don't understand this yet
3. Use 'setscreen' to setup the framebuffer (using the mailbox)
4. Check if the Y offset is upper or lower half of the framebuffer. Update the pointer offset accordingly (to write to either the top or bottom half of the virtual framebuffer)
Then it looks like you have 'flipscreen' to alternate between the top and bottom half.
Is this right so far?
Is one of the buffer's 'active', meaning it's contents are displayed on the screen, while the other is the one I should write to? Then, when I've finished writing to the 'passive' buffer, I can 'flip' it, and it becomes what is seen on the screen?
Thanks again for your help.
Re: Virtual Frame Buffer
One more thought...
I've read that I can output to screen faster by using DMA. How does this work?
Is it because DMA makes copying between the physical and virtual framebuffer faster?
Are there any tutorials out there on implementing DMA on baremetal?
I've read that I can output to screen faster by using DMA. How does this work?
Is it because DMA makes copying between the physical and virtual framebuffer faster?
Are there any tutorials out there on implementing DMA on baremetal?
Re: Virtual Frame Buffer
Hi
Sorry for not responding quickly, sometimes life gets in the way! DMA moves memory around independent of the CPU. It's that simple. Have a look at this (under 'helloworld') https://github.com/PeterLemon/RaspberryPi
Now in your config.txt you need the following entry for the vsync to work
Hopes this helps 
Sorry for not responding quickly, sometimes life gets in the way! DMA moves memory around independent of the CPU. It's that simple. Have a look at this (under 'helloworld') https://github.com/PeterLemon/RaspberryPi
Now in your config.txt you need the following entry for the vsync to work
Code: Select all
fake_vsync_isr=1Re: Virtual Frame Buffer
Thanks, I'll have a look and see what I can do 