gfx2 optimizations for horizontal lines, fix bug in disc drawing

This commit is contained in:
Irmen de Jong 2020-12-28 22:15:16 +01:00
parent 4b366358c4
commit 51f32677b7
3 changed files with 247 additions and 26 deletions

View File

@ -101,7 +101,7 @@ gfx2 {
} }
sub monochrome_stipple(ubyte enable) { sub monochrome_stipple(ubyte enable) {
monochrome_dont_stipple_flag = ~enable monochrome_dont_stipple_flag = not enable
} }
sub rect(uword x, uword y, uword width, uword height, ubyte color) { sub rect(uword x, uword y, uword width, uword height, ubyte color) {
@ -132,23 +132,95 @@ gfx2 {
when active_mode { when active_mode {
1 -> { 1 -> {
; 8bpp mode ; 8bpp mode
gfx2.plot(x, y, color) position(x, y)
repeat length-1 %asm {{
gfx2.next_pixel(color) lda color
phx
ldx length+1
beq +
ldy #0
- sta cx16.VERA_DATA0
iny
bne -
dex
bne -
+ ldy length ; remaining
beq +
- sta cx16.VERA_DATA0
dey
bne -
+ plx
}}
} }
0, 128 -> { 0, 128 -> {
; 1 bpp mode ; 1 bpp mode
; TODO optimize this to plot 8 pixels at once while possible, note: do mind the stipple setting and color 0 black ubyte separate_pixels = (8-lsb(x)) & 7
repeat length { if separate_pixels as uword > length
gfx2.plot(x, y, color) separate_pixels = lsb(length)
repeat separate_pixels {
; this could be optimized by setting this byte in 1 go but probably not worth it due to code size
plot(x, y, color)
x++ x++
} }
length -= separate_pixels
if length {
position(x, y)
separate_pixels = lsb(length) & 7
x += length & $fff8
%asm {{
lsr length+1
ror length
lsr length+1
ror length
lsr length+1
ror length
lda color
bne +
ldy #0 ; black
bra _loop
+ lda monochrome_dont_stipple_flag
beq _stipple
ldy #255 ; don't stipple
bra _loop
_stipple lda y
and #1 ; determine stipple pattern to use
bne +
ldy #%01010101
bra _loop
+ ldy #%10101010
_loop lda length
ora length+1
beq _done
sty cx16.VERA_DATA0
lda length
bne +
dec length+1
+ dec length
bra _loop
_done
}}
repeat separate_pixels {
; this could be optimized by setting this byte in 1 go but probably not worth it due to code size
plot(x, y, color)
x++
}
}
cx16.VERA_ADDR_H = (cx16.VERA_ADDR_H & %00000111) ; vera auto-increment off again
} }
} }
} }
sub vertical_line(uword x, uword y, uword height, ubyte color) { sub vertical_line(uword x, uword y, uword height, ubyte color) {
; TODO optimize this to use vera special increment mode, note: do mind the stipple setting and color 0 black if active_mode==1 {
; TODO for the 320x256 8bbp mode use vera auto increment
repeat lsb(height) {
plot(x, y, color)
y++
}
return
}
; note for the 1 bpp modes we can't use vera's auto increment mode because we have to 'or' the pixel data in place.
repeat height { repeat height {
plot(x, y, color) plot(x, y, color)
y++ y++
@ -297,8 +369,8 @@ gfx2 {
while radius>=yy { while radius>=yy {
horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, color) horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, color)
horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, color) horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, color)
horizontal_line(xcenter-yy, ycenter+radius, yy*2+1, color) horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, color)
horizontal_line(xcenter-yy, ycenter-radius, yy*2+1, color) horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, color)
yy++ yy++
if decisionOver2<=0 if decisionOver2<=0
decisionOver2 += (yy as word)*2+1 decisionOver2 += (yy as word)*2+1
@ -382,26 +454,42 @@ gfx2 {
inline asmsub next_pixel(ubyte color @A) { inline asmsub next_pixel(ubyte color @A) {
; -- sets the next pixel byte to the graphics chip. ; -- sets the next pixel byte to the graphics chip.
; for 8 bpp screens this will plot 1 pixel. for 1 bpp screens it will actually plot 8 pixels at once (bitmask). ; for 8 bpp screens this will plot 1 pixel.
; For super fast pixel plotting, don't call this subroutine but instead just use the assignment: cx16.VERA_DATA0 = color ; for 1 bpp screens it will plot 8 pixels at once (color = bit pattern).
%asm {{ %asm {{
sta cx16.VERA_DATA0 sta cx16.VERA_DATA0
}} }}
} }
sub next_pixels(uword pixels, uword amount) { asmsub next_pixels(uword pixels @AY, uword amount @R0) {
; -- sets the next bunch of pixels from a prepared array of bytes. ; -- sets the next bunch of pixels from a prepared array of bytes.
; for 8 bpp screens this will plot 1 pixel per byte, but for 1 bpp screens the bytes contain 8 pixels each. ; for 8 bpp screens this will plot 1 pixel per byte.
repeat msb(amount) { ; for 1 bpp screens it will plot 8 pixels at once (colors are the bit patterns per byte).
repeat 256 { %asm {{
cx16.VERA_DATA0 = @(pixels) phx
pixels++ sta P8ZP_SCRATCH_W1
} sty P8ZP_SCRATCH_W1+1
} ldx cx16.r0+1
repeat lsb(amount) { beq +
cx16.VERA_DATA0 = @(pixels) ldy #0
pixels++ - lda (P8ZP_SCRATCH_W1),y
} sta cx16.VERA_DATA0
iny
bne -
inc P8ZP_SCRATCH_W1+1 ; next page of 256 pixels
dex
bne -
+ ldx cx16.r0 ; remaining pixels
beq +
ldy #0
- lda (P8ZP_SCRATCH_W1),y
sta cx16.VERA_DATA0
iny
dex
bne -
+ plx
}}
} }
asmsub set_8_pixels_from_bits(ubyte bits @R0, ubyte oncolor @A, ubyte offcolor @Y) { asmsub set_8_pixels_from_bits(ubyte bits @R0, ubyte oncolor @A, ubyte offcolor @Y) {

View File

@ -1,11 +1,133 @@
%target cx16 %target cx16
%import gfx2 %import gfx2
%import textio %import textio
%zeropage basicsafe %import test_stack
%zeropage dontuse
main { main {
sub start () { sub start() {
gfx2.screen_mode(1)
uword pixels = memory("pixels", 320)
uword yy = 10
uword xx = gfx2.width/2
uword pp
uword cnt
pp=pixels
for xx in 10 to 300 {
gfx2.vertical_line(xx, 10, 220, 1)
}
gfx2.screen_mode(255)
txt.print("done!\n")
return
for cnt in 0 to 319 {
@(pp) = 255
pp++
}
gfx2.monochrome_stipple(false)
linesy()
linesx()
gfx2.monochrome_stipple(true)
linesy()
linesx()
sub linesx() {
repeat 8 {
gfx2.horizontal_line(10,yy,300,3)
yy++
}
yy+=4
repeat 8 {
gfx2.line(10,yy,309,yy,4)
yy++
}
yy+=4
repeat 8 {
for cnt in 10 to 309 {
gfx2.plot(cnt, yy, 1)
}
yy+=1
}
yy += 4
repeat 8 {
gfx2.horizontal_line(10,yy,100,3)
yy++
}
yy+=4
repeat 8 {
gfx2.line(10,yy,109,yy,4)
yy++
}
yy+=4
repeat 8 {
for cnt in 10 to 109 {
gfx2.plot(cnt, yy, 1)
}
yy++
}
yy+=4
}
sub linesy() {
repeat 8 {
gfx2.vertical_line(xx,10,300,3)
xx++
}
xx+=4
repeat 8 {
gfx2.line(xx,10, xx, 309, 4)
xx++
}
xx+=4
repeat 8 {
for cnt in 10 to 309 {
gfx2.plot(xx, cnt, 1)
}
xx+=1
}
xx += 4
repeat 8 {
gfx2.vertical_line(xx,10,100,3)
xx++
}
xx+=4
repeat 8 {
gfx2.line(xx,10,xx,109,4)
xx++
}
xx+=4
repeat 8 {
for cnt in 10 to 109 {
gfx2.plot(xx, cnt, 1)
}
xx++
}
xx+=4
}
; cx16.wait(3*60)
gfx2.screen_mode(255)
txt.print("done!\n")
test_stack.test()
}
sub start2 () {
gfx2.text_charset(3) gfx2.text_charset(3)
ubyte[] modes = [1, 0, 128] ubyte[] modes = [1, 0, 128]
@ -18,6 +140,7 @@ main {
gfx2.screen_mode(255) gfx2.screen_mode(255)
txt.print("done!\n") txt.print("done!\n")
test_stack.test()
} }
sub draw() { sub draw() {

View File

@ -9,6 +9,16 @@ main {
sub start () { sub start () {
; differences between:
; @(pp) = cnt as ubyte
; @(pp) = lsb(cnt)
; @(pp) = msb(cnt)
; repeat w as ubyte / repeat lsb(w)
; stack based evaluation for this function call even when it's inlined:
; gfx2.next_pixel((cnt as ubyte) + 30)
test_stack.test() test_stack.test()
} }