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) {
monochrome_dont_stipple_flag = ~enable
monochrome_dont_stipple_flag = not enable
}
sub rect(uword x, uword y, uword width, uword height, ubyte color) {
@ -132,23 +132,95 @@ gfx2 {
when active_mode {
1 -> {
; 8bpp mode
gfx2.plot(x, y, color)
repeat length-1
gfx2.next_pixel(color)
position(x, y)
%asm {{
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 -> {
; 1 bpp mode
; TODO optimize this to plot 8 pixels at once while possible, note: do mind the stipple setting and color 0 black
repeat length {
gfx2.plot(x, y, color)
ubyte separate_pixels = (8-lsb(x)) & 7
if separate_pixels as uword > length
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++
}
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) {
; 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 {
plot(x, y, color)
y++
@ -297,8 +369,8 @@ gfx2 {
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-yy, ycenter+radius, yy*2+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*$0002+1, color)
yy++
if decisionOver2<=0
decisionOver2 += (yy as word)*2+1
@ -382,26 +454,42 @@ gfx2 {
inline asmsub next_pixel(ubyte color @A) {
; -- 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 super fast pixel plotting, don't call this subroutine but instead just use the assignment: cx16.VERA_DATA0 = color
; for 8 bpp screens this will plot 1 pixel.
; for 1 bpp screens it will plot 8 pixels at once (color = bit pattern).
%asm {{
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.
; for 8 bpp screens this will plot 1 pixel per byte, but for 1 bpp screens the bytes contain 8 pixels each.
repeat msb(amount) {
repeat 256 {
cx16.VERA_DATA0 = @(pixels)
pixels++
}
}
repeat lsb(amount) {
cx16.VERA_DATA0 = @(pixels)
pixels++
}
; for 8 bpp screens this will plot 1 pixel per byte.
; for 1 bpp screens it will plot 8 pixels at once (colors are the bit patterns per byte).
%asm {{
phx
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldx cx16.r0+1
beq +
ldy #0
- 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) {

View File

@ -1,11 +1,133 @@
%target cx16
%import gfx2
%import textio
%zeropage basicsafe
%import test_stack
%zeropage dontuse
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)
ubyte[] modes = [1, 0, 128]
@ -18,6 +140,7 @@ main {
gfx2.screen_mode(255)
txt.print("done!\n")
test_stack.test()
}
sub draw() {

View File

@ -9,6 +9,16 @@ main {
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()
}