comparison vdp.c @ 1891:179a2ac29f27

Wait to reacquire framebuffer so that switching to UI does not require pushing a new frame if it happens in between bottom and top of display
author Michael Pavone <pavone@retrodev.com>
date Wed, 09 Oct 2019 23:06:02 -0700
parents bd60e74fd173
children 55d034719345
comparison
equal deleted inserted replaced
1890:7bb4081e9e52 1891:179a2ac29f27
2048 vdp_update_per_frame_debug(context); 2048 vdp_update_per_frame_debug(context);
2049 } 2049 }
2050 2050
2051 static void advance_output_line(vdp_context *context) 2051 static void advance_output_line(vdp_context *context)
2052 { 2052 {
2053 //This function is kind of gross because of the need to deal with vertical border busting via mode changes
2053 uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; 2054 uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top;
2054
2055 if (context->output_lines == lines_max) {
2056 if (!headless) {
2057 render_framebuffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER));
2058 context->cur_buffer = context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD;
2059 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch);
2060 }
2061 vdp_update_per_frame_debug(context);
2062 context->h40_lines = 0;
2063 context->frame++;
2064 context->output_lines = 0;
2065 } else if (context->output_lines && context->vcounter < context->inactive_start && context->vcounter > context->output_lines) {
2066 context->output_lines = context->vcounter;
2067 }
2068 uint32_t output_line = context->vcounter; 2055 uint32_t output_line = context->vcounter;
2069 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) { 2056 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
2070 //vcounter increment occurs much later in Mode 4 2057 //vcounter increment occurs much later in Mode 4
2071 output_line++; 2058 output_line++;
2072 } 2059 }
2073 if (output_line < context->inactive_start + context->border_bot && context->output_lines > 0) { 2060
2074 output_line = context->output_lines++;//context->border_top + context->vcounter; 2061 if (context->output_lines == lines_max || (!context->pushed_frame && output_line == context->inactive_start + context->border_top)) {
2075 } else if (output_line >= 0x200 - context->border_top || (!context->border_top && !output_line)) { 2062 //we've either filled up a full frame or we're at the bottom of screen in the current defined mode + border crop
2076 if (output_line == 0x200 - context->border_top || (!context->border_top && !output_line)) { 2063 if (!headless) {
2064 render_framebuffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER));
2065 uint8_t is_even = context->flags2 & FLAG2_EVEN_FIELD;
2066 if (context->vcounter <= context->inactive_start && (context->regs[REG_MODE_4] & BIT_INTERLACE)) {
2067 is_even = !is_even;
2068 }
2069 context->cur_buffer = is_even ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD;
2070 context->pushed_frame = 1;
2071 context->fb = NULL;
2072 }
2073 vdp_update_per_frame_debug(context);
2074 context->h40_lines = 0;
2075 context->frame++;
2076 context->output_lines = 0;
2077 }
2078
2079 if (output_line < context->inactive_start + context->border_bot) {
2080 if (context->output_lines) {
2081 output_line = context->output_lines++;//context->border_top + context->vcounter;
2082 } else if (!output_line && !context->border_top) {
2083 //top border is completely cropped so we won't hit the case below
2084 output_line = 0;
2085 context->output_lines = 1;
2086 context->pushed_frame = 0;
2087 } else {
2088 context->output_lines = output_line + 1;
2089 }
2090 } else if (output_line >= 0x200 - context->border_top) {
2091 if (output_line == 0x200 - context->border_top) {
2077 //We're at the top of the display, force context->output_lines to be zero to avoid 2092 //We're at the top of the display, force context->output_lines to be zero to avoid
2078 //potential screen rolling if the mode is changed at an inopportune time 2093 //potential screen rolling if the mode is changed at an inopportune time
2079 context->output_lines = 0; 2094 context->output_lines = 0;
2095 context->pushed_frame = 0;
2080 } 2096 }
2081 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top); 2097 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top);
2082 } else { 2098 } else {
2083 context->output = NULL; 2099 context->output = NULL;
2084 return; 2100 return;
2101 }
2102 if (!context->fb) {
2103 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch);
2085 } 2104 }
2086 output_line += context->top_offset; 2105 output_line += context->top_offset;
2087 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); 2106 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line);
2088 #ifdef DEBUG_FB_FILL 2107 #ifdef DEBUG_FB_FILL
2089 for (int i = 0; i < LINEBUF_SIZE; i++) 2108 for (int i = 0; i < LINEBUF_SIZE; i++)
2096 } 2115 }
2097 } 2116 }
2098 2117
2099 void vdp_release_framebuffer(vdp_context *context) 2118 void vdp_release_framebuffer(vdp_context *context)
2100 { 2119 {
2101 render_framebuffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER)); 2120 if (context->fb) {
2102 context->output = context->fb = NULL; 2121 render_framebuffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER));
2122 context->output = context->fb = NULL;
2123 }
2103 } 2124 }
2104 2125
2105 void vdp_reacquire_framebuffer(vdp_context *context) 2126 void vdp_reacquire_framebuffer(vdp_context *context)
2106 { 2127 {
2107 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch);
2108 uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; 2128 uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top;
2109 if (context->output_lines <= lines_max && context->output_lines > 0) { 2129 if (context->output_lines <= lines_max && context->output_lines > 0) {
2130 context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch);
2110 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1 + context->top_offset)); 2131 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1 + context->top_offset));
2111 } else { 2132 } else {
2112 context->output = NULL; 2133 context->output = NULL;
2113 } 2134 }
2114 } 2135 }