From f9530ea93cf61fe13820b7f09346b7063aeef66e Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 30 Nov 2025 19:19:58 +0200 Subject: [PATCH] Fast draw complete line (including hblank) if any overlay-like feature is enabled (lightpen etc) --- custom.cpp | 33 +++++++++----- drawing.cpp | 107 +++++++++++++++++++++++++++++++++++----------- include/drawing.h | 4 +- 3 files changed, 106 insertions(+), 38 deletions(-) diff --git a/custom.cpp b/custom.cpp index 0b218a16..fa943b1a 100644 --- a/custom.cpp +++ b/custom.cpp @@ -10771,6 +10771,18 @@ static int checkprevfieldlinestateequalbpl(struct linestate *l) return 0; } +// draw blanking line quickly (only if blanking can have overlay data, like lightpen crosshair) +static bool draw_blank_fast(struct linestate *l, int ldv) +{ + if (l->hbstrt_offset < 0 || l->hbstop_offset < 0) { + return false; + } + start_draw_denise(); + int dvp = calculate_linetype(ldv); + draw_denise_border_line_fast_queue(dvp, true, nextline_how, l); + return true; +} + // draw border line quickly (no copper, no sprites, no weird things, normal mode) static bool draw_border_fast(struct linestate *l, int ldv) { @@ -10782,7 +10794,7 @@ static bool draw_border_fast(struct linestate *l, int ldv) l->color0 = aga_mode ? agnus_colors.color_regs_aga[0] : agnus_colors.color_regs_ecs[0]; l->brdblank = brdblank; int dvp = calculate_linetype(ldv); - draw_denise_border_line_fast_queue(dvp, nextline_how, l); + draw_denise_border_line_fast_queue(dvp, false, nextline_how, l); return true; } @@ -10859,15 +10871,15 @@ static bool draw_line_fast(struct linestate *l, int ldv, uaecptr bplptp[8], bool return true; } -static bool draw_always(void) +static int draw_always(void) { if (nextline_how == nln_lower_black_always || nextline_how == nln_upper_black_always) { - return true; + return -1; } if (lineoptimizations_draw_always) { - return true; + return 1; } - return false; + return 0; } static void resetlinestate(void) @@ -10934,15 +10946,16 @@ static bool checkprevfieldlinestateequal(void) return false; } bool ret = false; - bool always = draw_always(); + int always = draw_always(); struct linestate *l = &lines[lvpos][lof_display]; int type = getlinetype(); if (type && type == l->type && displayresetcnt == l->cnt) { if (type == LINETYPE_BLANK) { - if (1) { - ret = true; + if (always > 0) { + draw_blank_fast(l, linear_display_vpos + 1); } + ret = true; } else if (type == LINETYPE_BORDER) { if (1) { bool brdblank = (bplcon0 & 1) && (bplcon3 & 0x20); @@ -11314,9 +11327,7 @@ static void start_sync_imm_handler(void) static void vsync_nosync(void) { - if (!nosignal_trigger) { - denise_clearbuffers(); - } + denise_clearbuffers(); nosignal_trigger = true; linear_vpos = 0; vsync_handler_post(); diff --git a/drawing.cpp b/drawing.cpp index 00a4f85f..1c4a2111 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -112,6 +112,7 @@ static struct denise_rga_queue rga_queue[DENISE_RGA_SLOT_CHUNKS]; static struct denise_rga_queue temp_line; static struct denise_rga_queue *this_line; static volatile bool thread_debug_lock; +static bool full_line_draw; static void denise_handle_quick_strobe(uae_u16 strobe, int offset, int vpos); static void draw_denise_vsync(int); @@ -166,7 +167,7 @@ static void read_denise_line_queue(void) } else if (q->type == 1) { draw_denise_bitplane_line_fast(q->gfx_ypos, q->how, q->ls); } else if (q->type == 2) { - draw_denise_border_line_fast(q->gfx_ypos, q->how, q->ls); + draw_denise_border_line_fast(q->gfx_ypos, q->blanked, q->how, q->ls); } else if (q->type == 3) { quick_denise_rga(q->linecnt, q->startpos, q->endpos); } else if (q->type == 4) { @@ -5254,6 +5255,8 @@ void set_drawbuffer(void) struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo; if (!drawing_can_lineoptimizations()) { + // full line is drawn because overlay graphics can be drawn on top of border and blanking + full_line_draw = true; vidinfo->inbuffer = &vidinfo->tempbuffer; struct vidbuffer *vb = &vidinfo->tempbuffer; if (!vb->outwidth || !vb->outheight) { @@ -5271,6 +5274,7 @@ void set_drawbuffer(void) vb->monitor_id = vb2->monitor_id; } } else { + full_line_draw = false; vidinfo->inbuffer = &vidinfo->drawbuffer; } } @@ -6863,6 +6867,39 @@ static int l_shift(int v, int shift) } } +static void draw_blank_start(int len) +{ + if (len > 0 && buf1 < (uae_u32*)xlinebuffer_start) { + int d = (uae_u32*)xlinebuffer_start - buf1; + buf1 += d; + len -= d; + } + if (buf1 + len > (uae_u32*)xlinebuffer_end) { + len = (uae_u32*)xlinebuffer_end - buf1; + } + if (len > 0) { + memset(buf1, 0, len * sizeof(uae_u32)); + if (buf2) { + memset(buf2, 0, len * sizeof(uae_u32)); + } + } +} +static void draw_blank_end(void) +{ + if (buf1 < (uae_u32*)xlinebuffer_start) { + buf1 = (uae_u32*)xlinebuffer_start; + } + if (buf1 < (uae_u32*)xlinebuffer_end) { + int len = (uae_u32*)xlinebuffer_end - buf1; + if (len > 0) { + memset(buf1, 0, len * sizeof(uae_u32)); + if (buf2) { + memset(buf2, 0, len * sizeof(uae_u32)); + } + } + } +} + static void fill_border(int total, uae_u32 bgcol) { if (buf2) { @@ -6912,7 +6949,7 @@ static void fill_border(int total, uae_u32 bgcol) } // draw border from hb to hb -void draw_denise_border_line_fast(int gfx_ypos, enum nln_how how, struct linestate *ls) +void draw_denise_border_line_fast(int gfx_ypos, bool blank, enum nln_how how, struct linestate *ls) { if (ls->strlong_seen) { set_strlong(); @@ -6920,7 +6957,7 @@ void draw_denise_border_line_fast(int gfx_ypos, enum nln_how how, struct linesta get_line(0, gfx_ypos, how, ls->lol_shift_prev); - if (!buf1 && !ls->blankedline && denise_planes > 0) { + if (!buf1 && !ls->blankedline && denise_planes > 0 && !blank) { resolution_count[denise_res]++; } lines_count++; @@ -6957,33 +6994,45 @@ void draw_denise_border_line_fast(int gfx_ypos, enum nln_how how, struct linesta buf1 = buf1p; buf2 = buf2p; - int start = draw_startoffset; - if (start < hbstop_offset) { - int diff = hbstop_offset - start; - buf1 += diff; + if (blank) { + memset(buf1, 0, xlinebuffer_end - (uae_u8*)buf1); if (buf2) { - buf2 += diff; + memset(buf2, 0, xlinebuffer_end - (uae_u8 *)buf1); } - if (gbufp) { - gbufp += diff; + } else { + if (full_line_draw) { + draw_blank_start(hbstop_offset); } - start = hbstop_offset; - } - int end = draw_end > hbstrt_offset ? hbstrt_offset : draw_end; - int total = end - start; + int start = draw_startoffset; + if (start < hbstop_offset) { + int diff = hbstop_offset - start; + buf1 += diff; + if (buf2) { + buf2 += diff; + } + if (gbufp) { + gbufp += diff; + } + start = hbstop_offset; + } + int end = draw_end > hbstrt_offset ? hbstrt_offset : draw_end; + int total = end - start; - fill_border(total, bgcol); + fill_border(total, bgcol); + if (full_line_draw) { + draw_blank_end(); + } - total = end - start; - if (need_genlock_data && gbuf && total) { - int max = addrdiff(xlinebuffer_genlock_end, gbufp); - total += GENLOCK_EXTRA_CLEAR; - if (total > max) { - total = max; + total = end - start; + if (need_genlock_data && gbuf && total) { + int max = addrdiff(xlinebuffer_genlock_end, gbufp); + total += GENLOCK_EXTRA_CLEAR; + if (total > max) { + total = max; + } + memset(gbufp, 0, total); } - memset(gbufp, 0, total); } - } static int ltsf_init(int draw_start, int draw_startoffset, int *draw_end, int hbstrt_offset, int hbstop_offset, int bpl1dat_trigger_offset, uae_u8 *buf_end, uae_u32 *buf1) @@ -7254,6 +7303,9 @@ void draw_denise_bitplane_line_fast(int gfx_ypos, enum nln_how how, struct lines buf1 = buf1p; buf2 = buf2p; } + if (full_line_draw) { + draw_blank_start(hbstop_offset); + } int cnt = ltsf_init(draw_start, draw_startoffset, &draw_end, hbstrt_offset, hbstop_offset, bpl1dat_trigger_offset, xlinebuffer_end, buf1); ltsf(cnt, draw_end, hbstrt_offset, hbstop_offset, hstrt_offset, hstop_offset, bpl1dat_trigger_offset, planecnt, bgcol, &cp, &cp2, 1 << cpadd, cpadds, 1 << bufadd, ls); @@ -7281,6 +7333,10 @@ void draw_denise_bitplane_line_fast(int gfx_ypos, enum nln_how how, struct lines } } + if (full_line_draw) { + draw_blank_end(); + } + // clear some more bytes to clear possible lightpen cursor graphics if (need_genlock_data && gbuf) { int max = addrdiff(xlinebuffer_genlock_end, gbuf); @@ -7495,7 +7551,7 @@ static void addtowritequeue(void) uae_sem_post(&write_sem); } -void draw_denise_border_line_fast_queue(int gfx_ypos, enum nln_how how, struct linestate *ls) +void draw_denise_border_line_fast_queue(int gfx_ypos, bool blank, enum nln_how how, struct linestate *ls) { if (MULTITHREADED_DENISE) { @@ -7505,6 +7561,7 @@ void draw_denise_border_line_fast_queue(int gfx_ypos, enum nln_how how, struct l struct denise_rga_queue *q = &rga_queue[rga_queue_write & DENISE_RGA_SLOT_CHUNKS_MASK]; q->gfx_ypos = gfx_ypos; + q->blanked = blank; q->how = how; q->ls = ls; q->type = 2; @@ -7516,7 +7573,7 @@ void draw_denise_border_line_fast_queue(int gfx_ypos, enum nln_how how, struct l } else { updatelinedata(); - draw_denise_border_line_fast(gfx_ypos, how, ls); + draw_denise_border_line_fast(gfx_ypos, blank, how, ls); } } diff --git a/include/drawing.h b/include/drawing.h index b368229c..cc3b939d 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -179,8 +179,8 @@ extern struct color_entry denise_colors; void draw_denise_line_queue(int gfx_ypos, nln_how how, uae_u32 linecnt, int startpos, int endpos, int startcycle, int endcycle, int skip, int skip2, int dtotal, int calib_start, int calib_len, bool lof, bool lol, int hdelay, bool blanked, bool finalseg, struct linestate *ls); void draw_denise_bitplane_line_fast(int gfx_ypos, enum nln_how how, struct linestate *ls); void draw_denise_bitplane_line_fast_queue(int gfx_ypos, enum nln_how how, struct linestate *ls); -void draw_denise_border_line_fast(int gfx_ypos, enum nln_how how, struct linestate *ls); -void draw_denise_border_line_fast_queue(int gfx_ypos, enum nln_how how, struct linestate *ls); +void draw_denise_border_line_fast(int gfx_ypos, bool blank, enum nln_how how, struct linestate *ls); +void draw_denise_border_line_fast_queue(int gfx_ypos, bool blank, enum nln_how how, struct linestate *ls); bool start_draw_denise(void); void end_draw_denise(void); void denise_reset(bool); -- 2.47.3