diff --git a/src/osd/windows/d3dcomm.h b/src/osd/windows/d3dcomm.h index f000c56866c..2b1e2c9defd 100644 --- a/src/osd/windows/d3dcomm.h +++ b/src/osd/windows/d3dcomm.h @@ -70,6 +70,7 @@ struct _d3d_texture_info int xprescale; // what is our X prescale factor? int yprescale; // what is our Y prescale factor? int cur_frame; // what is our current frame? + int prev_frame; // what was our last frame? (used to determine pause state) d3d_texture * d3dtex; // Direct3D texture pointer d3d_surface * d3dsurface; // Direct3D offscreen plain surface pointer d3d_texture * d3dfinaltex; // Direct3D final (post-scaled) texture diff --git a/src/osd/windows/d3dhlsl.c b/src/osd/windows/d3dhlsl.c index 00ffa233b49..eecf54b51e9 100644 --- a/src/osd/windows/d3dhlsl.c +++ b/src/osd/windows/d3dhlsl.c @@ -66,6 +66,7 @@ #include "emuopts.h" #include "aviio.h" #include "png.h" +#include "screen.h" // MAMEOS headers #include "d3dintf.h" @@ -198,7 +199,10 @@ hlsl_info::hlsl_info() shadow_bitmap = NULL; shadow_texture = NULL; registered_targets = 0; + cyclic_target_idx = 0; options = NULL; + paused = true; + lastidx = -1; } @@ -599,6 +603,23 @@ void hlsl_info::set_texture(d3d_texture_info *texture) d3d_info *d3d = (d3d_info *)window->drawdata; + if(texture != NULL) + { + if(texture->prev_frame == texture->cur_frame) + { + //printf("Paused\n"); + paused = true; + } + else + { + //printf("Not paused\n"); + paused = false; + } + + texture->prev_frame = texture->cur_frame; + //printf("%08x cur_frame is %d\n", (UINT32)(UINT64)texture, texture->cur_frame); + } + (*d3dintf->effect.set_texture)(effect, "Diffuse", (texture == NULL) ? d3d->default_texture->d3dfinaltex : texture->d3dfinaltex); if (options->yiq_enable) (*d3dintf->effect.set_texture)(yiq_encode_effect, "Diffuse", (texture == NULL) ? d3d->default_texture->d3dfinaltex : texture->d3dfinaltex); @@ -1229,7 +1250,12 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) if(PRIMFLAG_GET_SCREENTEX(d3d->last_texture_flags) && poly->texture != NULL) { - int targetidx = poly->texture->target_index; + int rawidx = poly->texture->target_index; + int targetidx = rawidx % 9; + int minidx = cyclic_target_idx - (num_screens * 2); + int wrappedidx = (minidx + ((rawidx - minidx) % num_screens) + num_screens) % 9; + //printf("rendering %d %d %d %d %d %d %d %d %d %f %f\n", poly->texture->target_index, rawidx, targetidx, minidx, wrappedidx, poly->texture->rawwidth, poly->texture->rawheight, d3d->width, d3d->height, (float)(poly->texture->ustop - poly->texture->ustart), (float)(poly->texture->vstop - poly->texture->vstart)); + screen_encountered[targetidx] = true; target_in_use[targetidx] = poly->texture; @@ -1504,8 +1530,8 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) // Simulate phosphorescence. This should happen after the shadow/scanline pass, but since // the phosphors are a direct result of the incoming texture, might as well just change the // input texture. - int num_screens = registered_targets / 2; curr_effect = phosphor_effect; + //printf("num_screens %d\n", num_screens); if(options->params_dirty) { @@ -1522,7 +1548,7 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) (*d3dintf->effect.set_float)(curr_effect, "Passthrough", 0.0f); (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", focus_enable ? texture1[targetidx] : texture2[targetidx]); - (*d3dintf->effect.set_texture)(curr_effect, "LastPass", last_texture[num_screens > 0 ? (targetidx % num_screens) : targetidx]); // Avoid changing targets due to page flipping + (*d3dintf->effect.set_texture)(curr_effect, "LastPass", last_texture[wrappedidx]); // Avoid changing targets due to page flipping result = (*d3dintf->device.set_render_target)(d3d->device, 0, target0[targetidx]); if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); @@ -1549,7 +1575,7 @@ void hlsl_info::render_quad(d3d_poly_info *poly, int vertnum) (*d3dintf->effect.set_texture)(curr_effect, "LastPass", texture0[targetidx]); (*d3dintf->effect.set_float)(curr_effect, "Passthrough", 1.0f); - result = (*d3dintf->device.set_render_target)(d3d->device, 0, last_target[num_screens > 0 ? (targetidx % num_screens) : targetidx]); // Avoid changing targets due to page flipping + result = (*d3dintf->device.set_render_target)(d3d->device, 0, last_target[wrappedidx]); // Avoid changing targets due to page flipping if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 5\n", (int)result); result = (*d3dintf->device.clear)(d3d->device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); @@ -1683,9 +1709,17 @@ void hlsl_info::end() (*d3dintf->surface.release)(backbuffer); + //printf("registered_targets %d\n", registered_targets); + + // Don't check de-registration if we're paused. + if(paused) + { + return; + } + // Unregister any registered targets we didn't traverse in the past frame. A resolution change must // have occurred. - for(int index = 0; index < 9 && master_enable && d3dintf->post_fx_available; index++) + for(int index = 0; index < 9; index++) { if(!screen_encountered[index] && smalltarget0[index] != NULL) { @@ -1695,6 +1729,7 @@ void hlsl_info::end() } else { + //printf("deregging %d\n", index); // free all textures if(target_in_use[index] != NULL) { @@ -1810,6 +1845,7 @@ void hlsl_info::end() last_target[index] = NULL; } target_use_count[index] = 0; + registered_targets--; } } } @@ -1827,7 +1863,9 @@ int hlsl_info::register_prescaled_texture(d3d_texture_info *texture, int scwidth d3d_info *d3d = (d3d_info *)window->drawdata; - int idx = registered_targets; + //printf("registering prescaled texture, seqid %d\n", texture->texinfo.seqid); + + int idx = cyclic_target_idx % 9; // Find the nearest prescale factor that is over our screen size int hlsl_prescale_x = prescale_force_x ? prescale_force_x : 1; @@ -1884,17 +1922,37 @@ int hlsl_info::register_prescaled_texture(d3d_texture_info *texture, int scwidth return 1; (*d3dintf->texture.get_surface_level)(last_texture[idx], 0, &last_target[idx]); - texture->target_index = registered_targets; + texture->target_index = cyclic_target_idx; target_width[idx] = scwidth * hlsl_prescale_x; target_height[idx] = scheight * hlsl_prescale_y; - target_use_count[texture->target_index] = 60; - target_in_use[texture->target_index] = texture; + target_use_count[idx] = 60; + target_in_use[idx] = texture; + raw_target_idx[idx] = cyclic_target_idx; registered_targets++; - registered_targets %= 9; + cyclic_target_idx++; + + options->params_dirty = true; + + enumerate_screens(); return 0; } +//============================================================ +// hlsl_info::enumerate_screens +//============================================================ +void hlsl_info::enumerate_screens() +{ + screen_device *screen = window->machine().first_screen(); + num_screens = 0; + while(screen != NULL) + { + num_screens++; + screen = screen->next_screen(); + //printf("Encountered %d screens\n", num_screens); + } +} + //============================================================ // hlsl_info::register_texture //============================================================ @@ -1906,7 +1964,9 @@ int hlsl_info::register_texture(d3d_texture_info *texture) d3d_info *d3d = (d3d_info *)window->drawdata; - int idx = registered_targets; + //printf("registering unscaled texture, seqid %d\n", texture->texinfo.seqid); + + int idx = cyclic_target_idx % 9; // Find the nearest prescale factor that is over our screen size int hlsl_prescale_x = prescale_force_x ? prescale_force_x : 1; @@ -1963,13 +2023,18 @@ int hlsl_info::register_texture(d3d_texture_info *texture) return 1; (*d3dintf->texture.get_surface_level)(last_texture[idx], 0, &last_target[idx]); - texture->target_index = registered_targets; + texture->target_index = cyclic_target_idx; target_width[idx] = texture->rawwidth * hlsl_prescale_x; target_height[idx] = texture->rawheight * hlsl_prescale_y; - target_use_count[texture->target_index] = 60; - target_in_use[texture->target_index] = texture; + target_use_count[idx] = 60; + target_in_use[idx] = texture; + raw_target_idx[idx] = cyclic_target_idx; registered_targets++; - registered_targets %= 9; + cyclic_target_idx++; + + options->params_dirty = true; + + enumerate_screens(); return 0; } diff --git a/src/osd/windows/d3dhlsl.h b/src/osd/windows/d3dhlsl.h index e604bb3e620..0ef0d45e48b 100644 --- a/src/osd/windows/d3dhlsl.h +++ b/src/osd/windows/d3dhlsl.h @@ -137,6 +137,8 @@ public: slider_state *init_slider_list(); private: + void enumerate_screens(); + void end_avi_recording(); void begin_avi_recording(const char *name); @@ -146,6 +148,9 @@ private: win_window_info * window; // D3D window info bool master_enable; // overall enable flag + bool paused; // whether or not rendering is currently paused + int num_screens; // number of emulated physical screens + int lastidx; // index of the last-encountered target bool write_ini; // enable external ini saving bool read_ini; // enable external ini loading int prescale_force_x; // prescale force x @@ -156,6 +161,7 @@ private: bitmap_t * shadow_bitmap; // shadow mask bitmap for post-processing shader d3d_texture_info * shadow_texture; // shadow mask texture for post-processing shader int registered_targets; // number of registered HLSL targets (i.e., screens) + int cyclic_target_idx; // cyclic index of next HLSL target slot hlsl_options * options; // current uniform state avi_file * avi_output_file; // AVI file bitmap_t * avi_snap; // AVI snapshot @@ -191,6 +197,7 @@ private: d3d_vertex * fsfx_vertices; // pointer to our full-screen-quad object // render targets + int raw_target_idx[9]; // Number of targets currently in use int target_use_count[9]; // Whether or not a target has been used yet d3d_texture_info * target_in_use[9]; // Target texture that is currently in use int target_width[9]; // Render target width