diff --git a/.gitattributes b/.gitattributes index a118f9bbbc6..96b39a3a28b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8388,6 +8388,8 @@ src/osd/sdl/window.c svneol=native#text/plain src/osd/sdl/window.h svneol=native#text/plain src/osd/windows/d3d9intf.c svneol=native#text/plain src/osd/windows/d3dcomm.h svneol=native#text/plain +src/osd/windows/d3dhlsl.c svneol=native#text/plain +src/osd/windows/d3dhlsl.h svneol=native#text/plain src/osd/windows/d3dintf.h svneol=native#text/plain src/osd/windows/debugwin.c svneol=native#text/plain src/osd/windows/debugwin.h svneol=native#text/plain diff --git a/src/osd/windows/d3d9intf.c b/src/osd/windows/d3d9intf.c index a6a49be0442..0c0a60bccb0 100644 --- a/src/osd/windows/d3d9intf.c +++ b/src/osd/windows/d3d9intf.c @@ -102,12 +102,13 @@ INLINE void convert_present_params(const present_parameters *params, D3DPRESENT_ // drawd3d9_init //============================================================ -base *drawd3d9_init() +base *drawd3d9_init(void) { direct3dcreate9_ptr direct3dcreate9; HINSTANCE dllhandle; IDirect3D9 *d3d9; base *d3dptr; + bool post_available = true; // dynamically grab the create function from d3d9.dll dllhandle = LoadLibrary(TEXT("d3d9.dll")); @@ -138,13 +139,39 @@ base *drawd3d9_init() } // dynamically grab the shader load function from d3dx9.dll - g_load_effect = NULL; + HINSTANCE fxhandle = LoadLibrary(TEXT("d3dx9_43.dll")); + if (fxhandle == NULL) + { + post_available = false; + mame_printf_verbose("Direct3D: Warning - Unable to access d3dx9_43.dll; disabling post-effect rendering\n"); + } + + // import the create function + if(post_available) + { + g_load_effect = (direct3dx9_loadeffect_ptr)GetProcAddress(fxhandle, "D3DXCreateEffectFromFileW"); + if (g_load_effect == NULL) + { + printf("Direct3D: Unable to find D3DXCreateEffectFromFileW\n"); + FreeLibrary(dllhandle); + fxhandle = NULL; + dllhandle = NULL; + return NULL; + } + } + else + { + g_load_effect = NULL; + post_available = false; + mame_printf_verbose("Direct3D: Warning - Unable to get a handle to D3DXCreateEffectFromFileW; disabling post-effect rendering\n"); + } // allocate an object to hold our data d3dptr = global_alloc(base); d3dptr->version = 9; d3dptr->d3dobj = d3d9; d3dptr->dllhandle = dllhandle; + d3dptr->post_fx_available = post_available; set_interfaces(d3dptr); mame_printf_verbose("Direct3D: Using Direct3D 9\n"); diff --git a/src/osd/windows/d3dhlsl.c b/src/osd/windows/d3dhlsl.c new file mode 100644 index 00000000000..90d60bff071 --- /dev/null +++ b/src/osd/windows/d3dhlsl.c @@ -0,0 +1,3544 @@ +//============================================================ +// +// d3dhlsl.c - Win32 Direct3D HLSL implementation +// +//============================================================ +// +// Copyright Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the +// above copyright notice, this list of conditions and +// the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// * Neither the name 'MAME' nor the names of its +// contributors may be used to endorse or promote +// products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================ + +// Useful info: +// Windows XP/2003 shipped with DirectX 8.1 +// Windows 2000 shipped with DirectX 7a +// Windows 98SE shipped with DirectX 6.1a +// Windows 98 shipped with DirectX 5 +// Windows NT shipped with DirectX 3.0a +// Windows 95 shipped with DirectX 2 + +// standard windows headers +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#undef interface + +// MAME headers +#include "emu.h" +#include "render.h" +#include "ui.h" +#include "rendutil.h" +#include "options.h" +#include "emuopts.h" +#include "aviio.h" +#include "png.h" +#include "screen.h" + +// MAMEOS headers +#include "d3dintf.h" +#include "winmain.h" +#include "window.h" +#include "config.h" +#include "strconv.h" +#include "d3dcomm.h" +#include "drawd3d.h" + + + +//============================================================ +// GLOBALS +//============================================================ + +static slider_state *g_slider_list; +static file_error open_next(d3d::renderer *d3d, emu_file &file, const char *templ, const char *extension, int idx); + +namespace d3d +{ + +hlsl_options shaders::s_hlsl_presets[4] = +{ + { // 25% Shadow mask, 50% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation + true, + 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, + 0.03f, 0.03f, + 0.5f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.9f, 0.9f, 0.9f }, + { 0.05f,0.05f,0.05f}, + { 0.25f,0.25f,0.25f}, + 1.2f, + false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, + 0.9f, 4.0f, + 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f + }, + { // 25% Shadow mask, 0% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation + true, + 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, + 0.03f, 0.03f, + 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.9f, 0.9f, 0.9f }, + { 0.05f,0.05f,0.05f}, + { 0.25f,0.25f,0.25f}, + 1.2f, + false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, + 0.9f, 4.0f, + 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f + }, + { // 25% Shadow mask, 0% Scanlines, 0% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation + true, + 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, + 0.0f, 0.0f, + 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.9f, 0.9f, 0.9f }, + { 0.05f,0.05f,0.05f}, + { 0.25f,0.25f,0.25f}, + 1.2f, + false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, + 0.9f, 4.0f, + 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f + }, + { // 25% Shadow mask, 100% Scanlines, 15% Pincushion, 3 defocus, 24-degree Tint Out, 1.5 Exponent, 5% Floor, 70% Phosphor Return, 80% Saturation, Bad Convergence + true, + 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, + 0.15f, 0.15f, + 1.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f, + { 3.0f, 3.0f, 3.0f, 3.0f }, + { 0.5f,-0.33f,0.7f }, + { 0.0f,-1.0f, 0.5f }, + { 0.0f, 0.2f, 0.3f }, + { 0.0f, 0.2f, 0.0f }, + { 0.8f, 0.2f, 0.0f }, + { 0.0f, 0.8f, 0.2f}, + { 0.2f, 0.0f, 0.8f}, + { 0.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f }, + { 1.5f, 1.5f, 1.5f }, + { 0.05f,0.05f,0.05f}, + { 0.7f, 0.7f, 0.7f}, + 0.8f, + false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, + 0.9f, 4.0f, + 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f + }, +}; + +//============================================================ +// PROTOTYPES +//============================================================ + +static void get_vector(const char *data, int count, float *out, int report_error); + + + +//============================================================ +// shader manager constructor +//============================================================ + +shaders::shaders() +{ + master_enable = false; + vector_enable = true; + prescale_size_x = 1; + prescale_size_y = 1; + prescale_force_x = 0; + prescale_force_y = 0; + preset = -1; + shadow_texture = NULL; + options = NULL; + paused = true; + lastidx = -1; + targethead = NULL; + cachehead = NULL; + initialized = false; +} + + + +//============================================================ +// shaders destructor +//============================================================ + +shaders::~shaders() +{ + global_free(options); + cache_target *currcache = cachehead; + while(cachehead != NULL) + { + cachehead = currcache->next; + global_free(currcache); + currcache = cachehead; + } + + render_target *currtarget = targethead; + while(targethead != NULL) + { + targethead = currtarget->next; + global_free(currtarget); + currtarget = targethead; + } +} + + + +//============================================================ +// shaders::window_save +//============================================================ + +void shaders::window_save() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), snap_width, snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &snap_copy_texture); + if (result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to init system-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result); + return; + } + (*d3dintf->texture.get_surface_level)(snap_copy_texture, 0, &snap_copy_target); + + result = (*d3dintf->device.create_texture)(d3d->get_device(), snap_width, snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &snap_texture); + if (result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to init video-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result); + return; + } + (*d3dintf->texture.get_surface_level)(snap_texture, 0, &snap_target); + + render_snap = true; + snap_rendered = false; +} + + + +//============================================================ +// shaders::window_record +//============================================================ + +void shaders::window_record() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + windows_options &options = downcast(window->machine().options()); + const char *filename = options.d3d_hlsl_write(); + + if (avi_output_file != NULL) + end_avi_recording(); + else if (filename[0] != 0) + begin_avi_recording(filename); +} + + +//============================================================ +// shaders::avi_update_snap +//============================================================ + +void shaders::avi_update_snap(surface *surface) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + D3DLOCKED_RECT rect; + + // if we don't have a bitmap, or if it's not the right size, allocate a new one + if (!avi_snap.valid() || (int)snap_width != avi_snap.width() || (int)snap_height != avi_snap.height()) + { + avi_snap.allocate((int)snap_width, (int)snap_height); + } + + // copy the texture + HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->get_device(), surface, avi_copy_surface); + if (result != D3D_OK) + { + return; + } + + // lock the texture + result = (*d3dintf->surface.lock_rect)(avi_copy_surface, &rect, NULL, D3DLOCK_DISCARD); + if (result != D3D_OK) + { + return; + } + + // loop over Y + for (int srcy = 0; srcy < (int)snap_height; srcy++) + { + DWORD *src = (DWORD *)((BYTE *)rect.pBits + srcy * rect.Pitch); + UINT32 *dst = &avi_snap.pix32(srcy); + + for(int x = 0; x < snap_width; x++) + *dst++ = *src++; + } + + // unlock + result = (*d3dintf->surface.unlock_rect)(avi_copy_surface); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); +} + + + +//============================================================ +// hlsl_render_snapshot +//============================================================ + +void shaders::render_snapshot(surface *surface) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + D3DLOCKED_RECT rect; + + render_snap = false; + + // if we don't have a bitmap, or if it's not the right size, allocate a new one + if (!avi_snap.valid() || snap_width != (avi_snap.width() / 2) || snap_height != (avi_snap.height() / 2)) + { + avi_snap.allocate(snap_width / 2, snap_height / 2); + } + + // copy the texture + HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->get_device(), surface, snap_copy_target); + if (result != D3D_OK) + { + return; + } + + // lock the texture + result = (*d3dintf->surface.lock_rect)(snap_copy_target, &rect, NULL, D3DLOCK_DISCARD); + if (result != D3D_OK) + { + return; + } + + for(int cy = 0; cy < 2; cy++) + { + for(int cx = 0; cx < 2; cx++) + { + // loop over Y + for (int srcy = 0; srcy < snap_height / 2; srcy++) + { + int toty = (srcy + cy * (snap_height / 2)); + int totx = cx * (snap_width / 2); + DWORD *src = (DWORD *)((BYTE *)rect.pBits + toty * rect.Pitch + totx * 4); + UINT32 *dst = &avi_snap.pix32(srcy); + + for(int x = 0; x < snap_width / 2; x++) + *dst++ = *src++; + } + + int idx = cy * 2 + cx; + + emu_file file(window->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + file_error filerr = open_next(d3d, file, NULL, "png", idx); + if (filerr != FILERR_NONE) + return; + + // add two text entries describing the image + astring text1(emulator_info::get_appname(), " ", build_version); + astring text2(window->machine().system().manufacturer, " ", window->machine().system().description); + png_info pnginfo = { 0 }; + png_add_text(&pnginfo, "Software", text1); + png_add_text(&pnginfo, "System", text2); + + // now do the actual work + png_error error = png_write_bitmap(file, &pnginfo, avi_snap, 1 << 24, NULL); + if (error != PNGERR_NONE) + mame_printf_error("Error generating PNG for HLSL snapshot: png_error = %d\n", error); + + // free any data allocated + png_free(&pnginfo); + } + } + + // unlock + result = (*d3dintf->surface.unlock_rect)(snap_copy_target); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); + + if(snap_texture != NULL) + { + (*d3dintf->texture.release)(snap_texture); + snap_texture = NULL; + } + + if(snap_target != NULL) + { + (*d3dintf->surface.release)(snap_target); + snap_target = NULL; + } + + if(snap_copy_texture != NULL) + { + (*d3dintf->texture.release)(snap_copy_texture); + snap_copy_texture = NULL; + } + + if(snap_copy_target != NULL) + { + (*d3dintf->surface.release)(snap_copy_target); + snap_copy_target = NULL; + } +} + + +//============================================================ +// shaders::record_texture +//============================================================ + +void shaders::record_texture() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + surface *surface = avi_final_target; + + // ignore if nothing to do + if (avi_output_file == NULL || surface == NULL) + return; + + // get the current time + attotime curtime = window->machine().time(); + + avi_update_snap(surface); + + // loop until we hit the right time + while (avi_next_frame_time <= curtime) + { + // handle an AVI recording + // write the next frame + avi_error avierr = avi_append_video_frame(avi_output_file, avi_snap); + if (avierr != AVIERR_NONE) + { + end_avi_recording(); + return; + } + + // advance time + avi_next_frame_time += avi_frame_period; + avi_frame++; + } +} + + +//============================================================ +// shaders::end_hlsl_avi_recording +//============================================================ + +void shaders::end_avi_recording() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + if (avi_output_file != NULL) + avi_close(avi_output_file); + + avi_output_file = NULL; + avi_frame = 0; +} + + +//============================================================ +// shaders::set_texture +//============================================================ + +void shaders::toggle() +{ + if (master_enable) + { + if (initialized) + { + delete_resources(false); + } + master_enable = !master_enable; + } + else + { + if (!initialized) + { + master_enable = !master_enable; + bool failed = create_resources(false); + if (failed) + { + master_enable = false; + } + } + else + { + master_enable = !master_enable; + } + } +} + +//============================================================ +// shaders::begin_avi_recording +//============================================================ + +void shaders::begin_avi_recording(const char *name) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + // stop any existing recording + end_avi_recording(); + + // reset the state + avi_frame = 0; + avi_next_frame_time = window->machine().time(); + + // build up information about this new movie + avi_movie_info info; + info.video_format = 0; + info.video_timescale = 1000 * ((window->machine().primary_screen != NULL) ? ATTOSECONDS_TO_HZ(window->machine().primary_screen->frame_period().attoseconds) : screen_device::DEFAULT_FRAME_RATE); + info.video_sampletime = 1000; + info.video_numsamples = 0; + info.video_width = snap_width; + info.video_height = snap_height; + info.video_depth = 24; + + info.audio_format = 0; + info.audio_timescale = window->machine().sample_rate(); + info.audio_sampletime = 1; + info.audio_numsamples = 0; + info.audio_channels = 2; + info.audio_samplebits = 16; + info.audio_samplerate = window->machine().sample_rate(); + + // create a new temporary movie file + file_error filerr; + astring fullpath; + { + emu_file tempfile(window->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + if (name != NULL) + { + filerr = tempfile.open(name); + } + else + { + filerr = open_next(d3d, tempfile, NULL, "avi", 0); + } + + // compute the frame time + { + avi_frame_period = attotime::from_seconds(1000) / info.video_timescale; + } + + // if we succeeded, make a copy of the name and create the real file over top + if (filerr == FILERR_NONE) + { + fullpath = tempfile.fullpath(); + } + } + + if (filerr == FILERR_NONE) + { + // create the file and free the string + avi_error avierr = avi_create(fullpath, &info, &avi_output_file); + if (avierr != AVIERR_NONE) + { + mame_printf_error("Error creating AVI: %s\n", avi_error_string(avierr)); + } + } +} + + +//============================================================ +// remove_cache_target - remove an active cache target when +// refcount hits zero +//============================================================ + +void shaders::remove_cache_target(cache_target *cache) +{ + if (cache != NULL) + { + if (cache == cachehead) + { + cachehead = cachehead->next; + } + + if (cache->prev != NULL) + { + cache->prev->next = cache->next; + } + + if (cache->next != NULL) + { + cache->next->prev = cache->prev; + } + + global_free(cache); + } +} + + +//============================================================ +// remove_render_target - remove an active target +//============================================================ + +void shaders::remove_render_target(texture_info *texture) +{ + remove_render_target(find_render_target(texture)); +} + +void shaders::remove_render_target(int width, int height, UINT32 screen_index, UINT32 page_index) +{ + render_target *target = find_render_target(width, height, screen_index, page_index); + if (target != NULL) + { + remove_render_target(target); + } +} + +void shaders::remove_render_target(render_target *rt) +{ + if (rt != NULL) + { + if (rt == targethead) + { + targethead = targethead->next; + } + + if (rt->prev != NULL) + { + rt->prev->next = rt->next; + } + + if (rt->next != NULL) + { + rt->next->prev = rt->prev; + } + + cache_target *cache = find_cache_target(rt->screen_index, rt->width, rt->height); + if (cache != NULL) + { + remove_cache_target(cache); + } + + int screen_index = rt->screen_index; + int other_page = 1 - rt->page_index; + int width = rt->width; + int height = rt->height; + + global_free(rt); + + // Remove other double-buffered page (if it exists) + remove_render_target(width, height, screen_index, other_page); + } +} + + +//============================================================ +// shaders::set_texture +//============================================================ + +void shaders::set_texture(texture_info *texture) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + if(texture != NULL) + { + paused = texture->paused(); + texture->advance_frame(); + } + + texture_info *default_texture = d3d->get_default_texture(); + (*d3dintf->effect.set_texture)(default_effect, "Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); + if (options->yiq_enable) + (*d3dintf->effect.set_texture)(yiq_encode_effect, "Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); + else + (*d3dintf->effect.set_texture)(color_effect, "Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); + (*d3dintf->effect.set_texture)(pincushion_effect, "Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); +} + + +//============================================================ +// shaders::init +//============================================================ + +void shaders::init(base *d3dintf, win_window_info *window) +{ + if (!d3dintf->post_fx_available) + return; + + this->d3dintf = d3dintf; + this->window = window; + + master_enable = downcast(window->machine().options()).d3d_hlsl_enable(); + prescale_size_x = 1; + prescale_size_y = 1; + preset = downcast(window->machine().options()).d3d_hlsl_preset(); + if (preset < -1 || preset > 3) + { + preset = -1; + } + + snap_width = downcast(window->machine().options()).d3d_snap_width(); + snap_height = downcast(window->machine().options()).d3d_snap_height(); + prescale_force_x = 0; + prescale_force_y = 0; + + windows_options &winoptions = downcast(window->machine().options()); + + options = (hlsl_options*)global_alloc_clear(hlsl_options); + + options->params_dirty = true; + strcpy(options->shadow_mask_texture, downcast(window->machine().options()).screen_shadow_mask_texture()); // unsafe + + write_ini = downcast(window->machine().options()).hlsl_write_ini(); + read_ini = downcast(window->machine().options()).hlsl_read_ini(); + + if(read_ini) + { + emu_file ini_file(downcast(window->machine().options()).screen_post_fx_dir(), OPEN_FLAG_READ | OPEN_FLAG_CREATE_PATHS); + file_error filerr = open_next((renderer*)window->drawdata, ini_file, downcast(window->machine().options()).hlsl_ini_name(), "ini", 0); + + read_ini = false; + if (filerr == FILERR_NONE) + { + ini_file.seek(0, SEEK_END); + if (ini_file.tell() >= 1000) + { + read_ini = true; + ini_file.seek(0, SEEK_SET); + + int en = 0; + char buf[1024]; + ini_file.gets(buf, 1024); + sscanf(buf, "hlsl_enable %d\n", &en); + master_enable = en == 1; + + ini_file.gets(buf, 1024); + sscanf(buf, "hlsl_prescale_x %d\n", &prescale_force_x); + + ini_file.gets(buf, 1024); + sscanf(buf, "hlsl_prescale_y %d\n", &prescale_force_y); + + ini_file.gets(buf, 1024); + sscanf(buf, "hlsl_preset %d\n", &preset); + + ini_file.gets(buf, 1024); + sscanf(buf, "hlsl_snap_width %d\n", &snap_width); + + ini_file.gets(buf, 1024); + sscanf(buf, "hlsl_snap_height %d\n", &snap_height); + + ini_file.gets(buf, 1024); + sscanf(buf, "shadow_mask_alpha %f\n", &options->shadow_mask_alpha); + + ini_file.gets(buf, 1024); + sscanf(buf, "shadow_mask_texture %s\n", options->shadow_mask_texture); + + ini_file.gets(buf, 1024); + sscanf(buf, "shadow_mask_x_count %d\n", &options->shadow_mask_count_x); + + ini_file.gets(buf, 1024); + sscanf(buf, "shadow_mask_y_count %d\n", &options->shadow_mask_count_y); + + ini_file.gets(buf, 1024); + sscanf(buf, "shadow_mask_usize %f\n", &options->shadow_mask_u_size); + + ini_file.gets(buf, 1024); + sscanf(buf, "shadow_mask_vsize %f\n", &options->shadow_mask_v_size); + + ini_file.gets(buf, 1024); + sscanf(buf, "curvature %f\n", &options->curvature); + + ini_file.gets(buf, 1024); + sscanf(buf, "pincushion %f\n", &options->pincushion); + + ini_file.gets(buf, 1024); + sscanf(buf, "scanline_alpha %f\n", &options->scanline_alpha); + + ini_file.gets(buf, 1024); + sscanf(buf, "scanline_size %f\n", &options->scanline_scale); + + ini_file.gets(buf, 1024); + sscanf(buf, "scanline_height %f\n", &options->scanline_height); + + ini_file.gets(buf, 1024); + sscanf(buf, "scanline_bright_scale %f\n", &options->scanline_bright_scale); + + ini_file.gets(buf, 1024); + sscanf(buf, "scanline_bright_offset %f\n", &options->scanline_bright_offset); + + ini_file.gets(buf, 1024); + sscanf(buf, "scanline_jitter %f\n", &options->scanline_offset); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "defocus %f %f\n", &options->defocus[0], &options->defocus[1]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "converge_x %f %f %f\n", &options->converge_x[0], &options->converge_x[1], &options->converge_x[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "converge_y %f %f %f\n", &options->converge_y[0], &options->converge_y[1], &options->converge_y[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "radial_converge_x %f %f %f\n", &options->radial_converge_x[0], &options->radial_converge_x[1], &options->radial_converge_x[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "radial_converge_y %f %f %f\n", &options->radial_converge_y[0], &options->radial_converge_y[1], &options->radial_converge_y[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "red_ratio %f %f %f\n", &options->red_ratio[0], &options->red_ratio[1], &options->red_ratio[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "grn_ratio %f %f %f\n", &options->grn_ratio[0], &options->grn_ratio[1], &options->grn_ratio[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "blu_ratio %f %f %f\n", &options->blu_ratio[0], &options->blu_ratio[1], &options->blu_ratio[2]); + + ini_file.gets(buf, 1024); + sscanf(buf, "saturation %f\n", &options->saturation); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "offset %f %f %f\n", &options->offset[0], &options->offset[1], &options->offset[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "scale %f %f %f\n", &options->scale[0], &options->scale[1], &options->scale[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "power %f %f %f\n", &options->power[0], &options->power[1], &options->power[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "floor %f %f %f\n", &options->floor[0], &options->floor[1], &options->floor[2]); + + ini_file.gets(buf, 1024); + for(int idx = 0; idx < strlen(buf); idx++) if(buf[idx] == ',') buf[idx] = ' '; + sscanf(buf, "phosphor_life %f %f %f\n", &options->phosphor[0], &options->phosphor[1], &options->phosphor[2]); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_enable %d\n", &en); + options->yiq_enable = en == 1; + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_cc %f\n", &options->yiq_cc); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_a %f\n", &options->yiq_a); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_b %f\n", &options->yiq_b); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_o %f\n", &options->yiq_o); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_p %f\n", &options->yiq_p); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_n %f\n", &options->yiq_n); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_y %f\n", &options->yiq_y); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_i %f\n", &options->yiq_i); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_q %f\n", &options->yiq_q); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_scan_time %f\n", &options->yiq_scan_time); + + ini_file.gets(buf, 1024); + sscanf(buf, "yiq_phase_count %d\n", &options->yiq_phase_count); + + ini_file.gets(buf, 1024); + sscanf(buf, "vector_length_scale %f\n", &options->vector_length_scale); + + ini_file.gets(buf, 1024); + sscanf(buf, "vector_length_ratio %f\n", &options->vector_length_ratio); + } + } + } + else + { + prescale_force_x = winoptions.d3d_hlsl_prescale_x(); + prescale_force_y = winoptions.d3d_hlsl_prescale_y(); + if(preset == -1) + { + options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha(); + options->shadow_mask_count_x = winoptions.screen_shadow_mask_count_x(); + options->shadow_mask_count_y = winoptions.screen_shadow_mask_count_y(); + options->shadow_mask_u_size = winoptions.screen_shadow_mask_u_size(); + options->shadow_mask_v_size = winoptions.screen_shadow_mask_v_size(); + options->curvature = winoptions.screen_curvature(); + options->pincushion = winoptions.screen_pincushion(); + options->scanline_alpha = winoptions.screen_scanline_amount(); + options->scanline_scale = winoptions.screen_scanline_scale(); + options->scanline_height = winoptions.screen_scanline_height(); + options->scanline_bright_scale = winoptions.screen_scanline_bright_scale(); + options->scanline_bright_offset = winoptions.screen_scanline_bright_offset(); + options->scanline_offset = winoptions.screen_scanline_offset(); + get_vector(winoptions.screen_defocus(), 2, options->defocus, TRUE); + get_vector(winoptions.screen_converge_x(), 3, options->converge_x, TRUE); + get_vector(winoptions.screen_converge_y(), 3, options->converge_y, TRUE); + get_vector(winoptions.screen_radial_converge_x(), 3, options->radial_converge_x, TRUE); + get_vector(winoptions.screen_radial_converge_y(), 3, options->radial_converge_y, TRUE); + get_vector(winoptions.screen_red_ratio(), 3, options->red_ratio, TRUE); + get_vector(winoptions.screen_grn_ratio(), 3, options->grn_ratio, TRUE); + get_vector(winoptions.screen_blu_ratio(), 3, options->blu_ratio, TRUE); + get_vector(winoptions.screen_offset(), 3, options->offset, TRUE); + get_vector(winoptions.screen_scale(), 3, options->scale, TRUE); + get_vector(winoptions.screen_power(), 3, options->power, TRUE); + get_vector(winoptions.screen_floor(), 3, options->floor, TRUE); + get_vector(winoptions.screen_phosphor(), 3, options->phosphor, TRUE); + options->saturation = winoptions.screen_saturation(); + } + else + { + options = &s_hlsl_presets[preset]; + } + + options->yiq_enable = winoptions.screen_yiq_enable(); + options->yiq_cc = winoptions.screen_yiq_cc(); + options->yiq_a = winoptions.screen_yiq_a(); + options->yiq_b = winoptions.screen_yiq_b(); + options->yiq_o = winoptions.screen_yiq_o(); + options->yiq_p = winoptions.screen_yiq_p(); + options->yiq_n = winoptions.screen_yiq_n(); + options->yiq_y = winoptions.screen_yiq_y(); + options->yiq_i = winoptions.screen_yiq_i(); + options->yiq_q = winoptions.screen_yiq_q(); + options->yiq_scan_time = winoptions.screen_yiq_scan_time(); + options->yiq_phase_count = winoptions.screen_yiq_phase_count(); + options->vector_length_scale = winoptions.screen_vector_length_scale(); + options->vector_length_ratio = winoptions.screen_vector_length_ratio(); + options->vector_bloom_scale = winoptions.screen_vector_bloom_scale(); + options->raster_bloom_scale = winoptions.screen_raster_bloom_scale(); + options->bloom_level0_weight = winoptions.screen_bloom_lvl0_weight(); + options->bloom_level1_weight = winoptions.screen_bloom_lvl1_weight(); + options->bloom_level2_weight = winoptions.screen_bloom_lvl2_weight(); + options->bloom_level3_weight = winoptions.screen_bloom_lvl3_weight(); + options->bloom_level4_weight = winoptions.screen_bloom_lvl4_weight(); + options->bloom_level5_weight = winoptions.screen_bloom_lvl5_weight(); + options->bloom_level6_weight = winoptions.screen_bloom_lvl6_weight(); + options->bloom_level7_weight = winoptions.screen_bloom_lvl7_weight(); + options->bloom_level8_weight = winoptions.screen_bloom_lvl8_weight(); + options->bloom_level9_weight = winoptions.screen_bloom_lvl9_weight(); + options->bloom_level10_weight = winoptions.screen_bloom_lvl10_weight(); + } + + options->params_dirty = true; + // experimental: load a PNG to use for vector rendering; it is treated + // as a brightness map + emu_file file(window->machine().options().art_path(), OPEN_FLAG_READ); + + render_load_png(shadow_bitmap, file, NULL, options->shadow_mask_texture); + + g_slider_list = init_slider_list(); +} + + + +//============================================================ +// shaders::init_fsfx_quad +//============================================================ + +void shaders::init_fsfx_quad(void *vertbuf) +{ + // Called at the start of each frame by the D3D code in order to reserve two triangles + // that are guaranteed to be at a fixed position so as to simply use D3DPT_TRIANGLELIST, 0, 2 + // instead of having to do bookkeeping about a specific screen quad + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + // get a pointer to the vertex buffer + fsfx_vertices = (vertex *)vertbuf; + if (fsfx_vertices == NULL) + return; + + // fill in the vertexes clockwise + fsfx_vertices[0].x = 0.0f; + fsfx_vertices[0].y = 0.0f; + fsfx_vertices[1].x = d3d->get_width(); + fsfx_vertices[1].y = 0.0f; + fsfx_vertices[2].x = 0.0f; + fsfx_vertices[2].y = d3d->get_height(); + fsfx_vertices[3].x = d3d->get_width(); + fsfx_vertices[3].y = 0.0f; + fsfx_vertices[4].x = 0.0f; + fsfx_vertices[4].y = d3d->get_height(); + fsfx_vertices[5].x = d3d->get_width(); + fsfx_vertices[5].y = d3d->get_height(); + + fsfx_vertices[0].u0 = 0.0f; + fsfx_vertices[0].v0 = 0.0f; + + fsfx_vertices[1].u0 = 1.0f; + fsfx_vertices[1].v0 = 0.0f; + + fsfx_vertices[2].u0 = 0.0f; + fsfx_vertices[2].v0 = 1.0f; + + fsfx_vertices[3].u0 = 1.0f; + fsfx_vertices[3].v0 = 0.0f; + + fsfx_vertices[4].u0 = 0.0f; + fsfx_vertices[4].v0 = 1.0f; + + fsfx_vertices[5].u0 = 1.0f; + fsfx_vertices[5].v0 = 1.0f; + + fsfx_vertices[0].u1 = 0.0f; + fsfx_vertices[0].v1 = 0.0f; + fsfx_vertices[1].u1 = 0.0f; + fsfx_vertices[1].v1 = 0.0f; + fsfx_vertices[2].u1 = 0.0f; + fsfx_vertices[2].v1 = 0.0f; + fsfx_vertices[3].u1 = 0.0f; + fsfx_vertices[3].v1 = 0.0f; + fsfx_vertices[4].u1 = 0.0f; + fsfx_vertices[4].v1 = 0.0f; + fsfx_vertices[5].u1 = 0.0f; + fsfx_vertices[5].v1 = 0.0f; + + // set the color, Z parameters to standard values + for (int i = 0; i < 6; i++) + { + fsfx_vertices[i].z = 0.0f; + fsfx_vertices[i].rhw = 1.0f; + fsfx_vertices[i].color = D3DCOLOR_ARGB(255, 255, 255, 255); + } +} + + + +//============================================================ +// shaders::create_resources +//============================================================ + +int shaders::create_resources(bool reset) +{ + if (!master_enable || !d3dintf->post_fx_available) + return 0; + + renderer *d3d = (renderer *)window->drawdata; + + HRESULT result = (*d3dintf->device.get_render_target)(d3d->get_device(), 0, &backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); + + result = (*d3dintf->device.create_texture)(d3d->get_device(), 4, 4, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &black_texture); + if (result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to init video-memory target for black texture (%08x)\n", (UINT32)result); + return 1; + } + (*d3dintf->texture.get_surface_level)(black_texture, 0, &black_surface); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, black_surface); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)snap_width, (int)snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &avi_copy_texture); + if (result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to init system-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result); + return 1; + } + (*d3dintf->texture.get_surface_level)(avi_copy_texture, 0, &avi_copy_surface); + + result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)snap_width, (int)snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &avi_final_texture); + if (result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to init video-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result); + return 1; + } + (*d3dintf->texture.get_surface_level)(avi_final_texture, 0, &avi_final_target); + + // experimental: if we have a shadow bitmap, create a texture for it + if (shadow_bitmap.valid()) + { + render_texinfo texture; + + // fake in the basic data so it looks like it came from render.c + texture.base = shadow_bitmap.raw_pixptr(0); + texture.rowpixels = shadow_bitmap.rowpixels(); + texture.width = shadow_bitmap.width(); + texture.height = shadow_bitmap.height(); + texture.palette = NULL; + texture.seqid = 0; + + // now create it + shadow_texture = new texture_info(d3d->get_texture_manager(), &texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); + } + + const char *fx_dir = downcast(window->machine().options()).screen_post_fx_dir(); + + // Replace all this garbage with a proper data-driven system + char primary_name_cstr[1024]; + sprintf(primary_name_cstr, "%s\\primary.fx", fx_dir); + TCHAR *primary_name = tstring_from_utf8(primary_name_cstr); + + char post_name_cstr[1024]; + sprintf(post_name_cstr, "%s\\post.fx", fx_dir); + TCHAR *post_name = tstring_from_utf8(post_name_cstr); + + char prescale_name_cstr[1024]; + sprintf(prescale_name_cstr, "%s\\prescale.fx", fx_dir); + TCHAR *prescale_name = tstring_from_utf8(prescale_name_cstr); + + char pincushion_name_cstr[1024]; + sprintf(pincushion_name_cstr, "%s\\pincushion.fx", fx_dir); + TCHAR *pincushion_name = tstring_from_utf8(pincushion_name_cstr); + + char phosphor_name_cstr[1024]; + sprintf(phosphor_name_cstr, "%s\\phosphor.fx", fx_dir); + TCHAR *phosphor_name = tstring_from_utf8(phosphor_name_cstr); + + char focus_name_cstr[1024]; + sprintf(focus_name_cstr, "%s\\focus.fx", fx_dir); + TCHAR *focus_name = tstring_from_utf8(focus_name_cstr); + + char deconverge_name_cstr[1024]; + sprintf(deconverge_name_cstr, "%s\\deconverge.fx", fx_dir); + TCHAR *deconverge_name = tstring_from_utf8(deconverge_name_cstr); + + char color_name_cstr[1024]; + sprintf(color_name_cstr, "%s\\color.fx", fx_dir); + TCHAR *color_name = tstring_from_utf8(color_name_cstr); + + char yiq_encode_name_cstr[1024]; + sprintf(yiq_encode_name_cstr, "%s\\yiq_encode.fx", fx_dir); + TCHAR *yiq_encode_name = tstring_from_utf8(yiq_encode_name_cstr); + + char yiq_decode_name_cstr[1024]; + sprintf(yiq_decode_name_cstr, "%s\\yiq_decode.fx", fx_dir); + TCHAR *yiq_decode_name = tstring_from_utf8(yiq_decode_name_cstr); + + // create the regular shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), primary_name, &default_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load primary.fx\n"); + return 1; + } + + // create the post-processing shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), post_name, &post_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load post.fx\n"); + return 1; + } + + // create the prescaling shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), prescale_name, &prescale_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load prescale.fx\n"); + return 1; + } + + // create the pincushion shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), pincushion_name, &pincushion_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load pincushion.fx\n"); + return 1; + } + + // create the phosphor shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), phosphor_name, &phosphor_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load phosphor.fx\n"); + return 1; + } + + // create the focus shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), focus_name, &focus_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load focus.fx\n"); + return 1; + } + + // create the deconvergence shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), deconverge_name, &deconverge_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load deconverge.fx\n"); + return 1; + } + + // create the color convolution shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), color_name, &color_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load color.fx\n"); + return 1; + } + + // create the YIQ modulation shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), yiq_encode_name, &yiq_encode_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load yiq_encode.fx\n"); + return 1; + } + + // create the YIQ demodulation shader + result = (*d3dintf->device.create_effect)(d3d->get_device(), yiq_decode_name, &yiq_decode_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load yiq_decode.fx\n"); + return 1; + } + +#if HLSL_VECTOR || CRT_BLOOM + char bloom_cstr[1024]; + sprintf(bloom_cstr, "%s\\bloom.fx", fx_dir); + TCHAR *bloom_name = tstring_from_utf8(bloom_cstr); + + result = (*d3dintf->device.create_effect)(d3d->get_device(), bloom_name, &bloom_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load bloom.fx\n"); + return 1; + } + if (bloom_name) + osd_free(bloom_name); + + char downsample_cstr[1024]; + sprintf(downsample_cstr, "%s\\downsample.fx", fx_dir); + TCHAR *downsample_name = tstring_from_utf8(downsample_cstr); + + result = (*d3dintf->device.create_effect)(d3d->get_device(), downsample_name, &downsample_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load downsample.fx\n"); + return 1; + } + if (downsample_name) + osd_free(downsample_name); +#endif +#if HLSL_VECTOR + // create the vector shader + char vector_cstr[1024]; + sprintf(vector_cstr, "%s\\vector.fx", fx_dir); + TCHAR *vector_name = tstring_from_utf8(vector_cstr); + + result = (*d3dintf->device.create_effect)(d3d->get_device(), vector_name, &vector_effect); + if(result != D3D_OK) + { + mame_printf_verbose("Direct3D: Unable to load vector.fx\n"); + return 1; + } + if (vector_name) + osd_free(vector_name); +#endif + + if (primary_name) + osd_free(primary_name); + if (post_name) + osd_free(post_name); + if (prescale_name) + osd_free(prescale_name); + if (pincushion_name) + osd_free(pincushion_name); + if (phosphor_name) + osd_free(phosphor_name); + if (focus_name) + osd_free(focus_name); + if (deconverge_name) + osd_free(deconverge_name); + if (color_name) + osd_free(color_name); + if (yiq_encode_name) + osd_free(yiq_encode_name); + if (yiq_decode_name) + osd_free(yiq_decode_name); + + initialized = true; + + return 0; +} + + +//============================================================ +// shaders::begin_draw +//============================================================ + +void shaders::begin_draw() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + + curr_effect = default_effect; + + (*d3dintf->effect.set_technique)(default_effect, "TestTechnique"); + (*d3dintf->effect.set_technique)(post_effect, "ScanMaskTechnique"); + (*d3dintf->effect.set_technique)(pincushion_effect, "TestTechnique"); + (*d3dintf->effect.set_technique)(phosphor_effect, "TestTechnique"); + (*d3dintf->effect.set_technique)(focus_effect, "TestTechnique"); + (*d3dintf->effect.set_technique)(deconverge_effect, "DeconvergeTechnique"); + (*d3dintf->effect.set_technique)(color_effect, "ColorTechnique"); + (*d3dintf->effect.set_technique)(yiq_encode_effect, "EncodeTechnique"); + (*d3dintf->effect.set_technique)(yiq_decode_effect, "DecodeTechnique"); + + HRESULT result = (*d3dintf->device.get_render_target)(d3d->get_device(), 0, &backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); +} + + +//============================================================ +// shaders::begin_frame +//============================================================ + +void shaders::begin_frame() +{ + record_texture(); +} + + +//============================================================ +// shaders::blit +//============================================================ + +void shaders::blit(surface *dst, texture *src, surface *new_dst, D3DPRIMITIVETYPE prim_type, + UINT32 prim_index, UINT32 prim_count, int dstw, int dsth) +{ + renderer *d3d = (renderer *)window->drawdata; + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, dst); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + curr_effect = default_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", src); + + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)dstw); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)dsth); + (*d3dintf->effect.set_float)(curr_effect, "PostPass", 1.0f); + (*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion); + (*d3dintf->effect.set_float)(curr_effect, "Brighten", 0.0f); + + unsigned int num_passes = 0; + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + if (new_dst) + { + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, new_dst); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + } +} + + + +//============================================================ +// shaders::blit +//============================================================ + +void shaders::blit(surface *dst, texture *src, surface *new_dst, D3DPRIMITIVETYPE prim_type, + UINT32 prim_index, UINT32 prim_count) +{ + renderer *d3d = (renderer *)window->drawdata; + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, dst); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); + + curr_effect = default_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", src); + + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "ScreenWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "ScreenHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "PostPass", 1.0f); + (*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion); + (*d3dintf->effect.set_float)(curr_effect, "Brighten", 1.0f); + + unsigned int num_passes = 0; + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + (*d3dintf->effect.set_float)(curr_effect, "Brighten", 0.0f); + + if (new_dst) + { + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, new_dst); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + } +} + +//============================================================ +// shaders::end_frame +//============================================================ + +void shaders::end_frame() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + if(render_snap && snap_rendered) + { + render_snapshot(snap_target); + } + + if (!lines_pending) + return; + + lines_pending = false; + + /*render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); + if (rt == NULL) + { + return; + } + + blit(backbuffer, rt->render_texture[1], NULL, vecbuf_type, vecbuf_index, vecbuf_count); + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);*/ +} + + +//============================================================ +// shaders::init_effect_info +//============================================================ + +void shaders::init_effect_info(poly_info *poly) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + renderer *d3d = (renderer *)window->drawdata; + texture_info *texture = poly->get_texture(); + + vec2f shadow_dims; + + if (shadow_texture) + { + shadow_dims = shadow_texture->get_rawdims(); + } + else + { + shadow_dims.c.x = 1.0f; + shadow_dims.c.y = 1.0f; + } + + if(PRIMFLAG_GET_TEXSHADE(d3d->get_last_texture_flags())) + { + curr_effect = pincushion_effect; + } + else if(PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && texture != NULL) + { + // Plug in all of the shader settings we're going to need + // This is extremely slow, but we're not rendering models here, + // just post-processing. + curr_effect = post_effect; + + (*d3dintf->effect.set_float)(curr_effect, "ScanlineOffset", (texture->get_cur_frame() == 0) ? 0.0f : options->scanline_offset); + + if(options->params_dirty) + { + vec2f delta = texture->get_uvstop() - texture->get_uvstart(); + (*d3dintf->effect.set_vector)(curr_effect, "RawDims", 2, &texture->get_rawdims().c.x); + (*d3dintf->effect.set_vector)(curr_effect, "SizeRatio", 2, &delta.c.x); + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "Floor", 3, options->floor); + (*d3dintf->effect.set_float)(curr_effect, "SnapX", snap_width); + (*d3dintf->effect.set_float)(curr_effect, "SnapY", snap_height); + (*d3dintf->effect.set_float)(curr_effect, "PincushionAmount", options->pincushion); + (*d3dintf->effect.set_float)(curr_effect, "CurvatureAmount", options->curvature); + (*d3dintf->effect.set_float)(curr_effect, "UseShadow", shadow_texture == NULL ? 0.0f : 1.0f); + (*d3dintf->effect.set_texture)(curr_effect, "Shadow", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex()); + (*d3dintf->effect.set_float)(curr_effect, "ShadowBrightness", options->shadow_mask_alpha); + (*d3dintf->effect.set_float)(curr_effect, "ShadowMaskSizeX", (float)options->shadow_mask_count_x); + (*d3dintf->effect.set_float)(curr_effect, "ShadowMaskSizeY", (float)options->shadow_mask_count_y); + (*d3dintf->effect.set_float)(curr_effect, "ShadowU", options->shadow_mask_u_size); + (*d3dintf->effect.set_float)(curr_effect, "ShadowV", options->shadow_mask_v_size); + + (*d3dintf->effect.set_vector)(curr_effect, "ShadowDims", 2, &shadow_dims.c.x); + (*d3dintf->effect.set_float)(curr_effect, "ScanlineAmount", options->scanline_alpha); + (*d3dintf->effect.set_float)(curr_effect, "ScanlineScale", options->scanline_scale); + (*d3dintf->effect.set_float)(curr_effect, "ScanlineHeight", options->scanline_height); + (*d3dintf->effect.set_float)(curr_effect, "ScanlineBrightScale", options->scanline_bright_scale); + (*d3dintf->effect.set_float)(curr_effect, "ScanlineBrightOffset", options->scanline_bright_offset); + //(*d3dintf->effect.set_float)(curr_effect, "ScanlineOffset", (texture->get_cur_frame() == 0) ? 0.0f : options->scanline_offset); + (*d3dintf->effect.set_vector)(curr_effect, "Power", 3, options->power); + } + } + else + { + curr_effect = default_effect; + + (*d3dintf->effect.set_float)(curr_effect, "FixedAlpha", 1.0f); + } +} + + +//============================================================ +// shaders::find_render_target +//============================================================ + +render_target* shaders::find_render_target(texture_info *info) +{ + render_target *curr = targethead; + UINT32 screen_index_data = (UINT32)info->get_texinfo().osddata; + UINT32 screen_index = screen_index_data >> 1; + UINT32 page_index = screen_index_data & 1; + + while (curr != NULL && (curr->screen_index != screen_index || curr->page_index != page_index || + curr->width != info->get_texinfo().width || curr->height != info->get_texinfo().height)) + { + curr = curr->next; + } + + return curr; +} + + +//============================================================ +// shaders::find_render_target +//============================================================ + +render_target* shaders::find_render_target(int width, int height, UINT32 screen_index, UINT32 page_index) +{ + render_target *curr = targethead; + + while (curr != NULL && (curr->width != width || curr->height != height || curr->screen_index != screen_index || curr->page_index != page_index)) + { + curr = curr->next; + } + + return curr; +} + + +//============================================================ +// shaders::find_cache_target +//============================================================ + +cache_target* shaders::find_cache_target(UINT32 screen_index, int width, int height) +{ + cache_target *curr = cachehead; + + while (curr != NULL && (curr->screen_index != screen_index || curr->width != width || curr->height != height)) + { + curr = curr->next; + } + + return curr; +} + + +//============================================================ +// shaders::render_quad +//============================================================ + +void shaders::render_quad(poly_info *poly, int vertnum) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + UINT num_passes = 0; + renderer *d3d = (renderer *)window->drawdata; + texture_info *texture = poly->get_texture(); + + if(PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && texture != NULL) + { + render_target *rt = find_render_target(texture); + if (rt == NULL) + { + return; + } + cache_target *ct = find_cache_target(rt->screen_index, texture->get_texinfo().width, texture->get_texinfo().height); + + vec2f& rawdims = texture->get_rawdims(); + vec2f delta = texture->get_uvstop() - texture->get_uvstart(); + + if(options->yiq_enable) + { + // Convert our signal into YIQ + curr_effect = yiq_encode_effect; + + if(options->params_dirty) + { + (*d3dintf->effect.set_vector)(curr_effect, "RawDims", 2, &rawdims.c.x); + (*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / delta.c.x); + (*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / delta.c.y); + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "CCValue", options->yiq_cc); + (*d3dintf->effect.set_float)(curr_effect, "AValue", options->yiq_a); + (*d3dintf->effect.set_float)(curr_effect, "BValue", (texture->get_cur_frame() == 2) ? 0.0f : ((float)texture->get_cur_frame() * options->yiq_b)); + (*d3dintf->effect.set_float)(curr_effect, "PValue", options->yiq_p); + (*d3dintf->effect.set_float)(curr_effect, "NotchHalfWidth", options->yiq_n); + (*d3dintf->effect.set_float)(curr_effect, "YFreqResponse", options->yiq_y); + (*d3dintf->effect.set_float)(curr_effect, "IFreqResponse", options->yiq_i); + (*d3dintf->effect.set_float)(curr_effect, "QFreqResponse", options->yiq_q); + (*d3dintf->effect.set_float)(curr_effect, "ScanTime", options->yiq_scan_time); + } + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[4]); + + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + // Convert our signal from YIQ + curr_effect = yiq_decode_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Composite", rt->render_texture[4]); + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", texture->get_finaltex()); + if(true)//options->params_dirty) + { + (*d3dintf->effect.set_float)(curr_effect, "RawWidth", rawdims.c.x); + (*d3dintf->effect.set_float)(curr_effect, "RawHeight", rawdims.c.y); + (*d3dintf->effect.set_float)(curr_effect, "WidthRatio", 1.0f / delta.c.x); + (*d3dintf->effect.set_float)(curr_effect, "HeightRatio", 1.0f / delta.c.y); + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "CCValue", options->yiq_cc); + (*d3dintf->effect.set_float)(curr_effect, "AValue", options->yiq_a); + (*d3dintf->effect.set_float)(curr_effect, "BValue", (texture->get_cur_frame() == 2) ? 0.0f : ((float)texture->get_cur_frame() * options->yiq_b)); + (*d3dintf->effect.set_float)(curr_effect, "OValue", options->yiq_o); + (*d3dintf->effect.set_float)(curr_effect, "PValue", options->yiq_p); + (*d3dintf->effect.set_float)(curr_effect, "NotchHalfWidth", options->yiq_n); + (*d3dintf->effect.set_float)(curr_effect, "YFreqResponse", options->yiq_y); + (*d3dintf->effect.set_float)(curr_effect, "IFreqResponse", options->yiq_i); + (*d3dintf->effect.set_float)(curr_effect, "QFreqResponse", options->yiq_q); + (*d3dintf->effect.set_float)(curr_effect, "ScanTime", options->yiq_scan_time); + } + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[3]); + + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + curr_effect = color_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[3]); + } + + curr_effect = color_effect; + + // Render the initial color-convolution pass + if(options->params_dirty) + { + (*d3dintf->effect.set_vector)(curr_effect, "RawDims", 2, &rawdims.c.x); + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "YIQEnable", options->yiq_enable ? 1.0f : 0.0f); + (*d3dintf->effect.set_vector)(curr_effect, "RedRatios", 3, options->red_ratio); + (*d3dintf->effect.set_vector)(curr_effect, "GrnRatios", 3, options->grn_ratio); + (*d3dintf->effect.set_vector)(curr_effect, "BluRatios", 3, options->blu_ratio); + (*d3dintf->effect.set_vector)(curr_effect, "Offset", 3, options->offset); + (*d3dintf->effect.set_vector)(curr_effect, "Scale", 3, options->scale); + (*d3dintf->effect.set_float)(curr_effect, "Saturation", options->saturation); + } + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->smalltarget); + + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + // Pre-scaling pass + curr_effect = prescale_effect; + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->smalltexture); + + if(options->params_dirty) + { + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "RawDims", 2, &rawdims.c.x); + } + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->prescaletarget); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + // Deconverge pass + curr_effect = deconverge_effect; + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->prescaletexture); + + if(options->params_dirty) + { + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "RawDims", 2, &rawdims.c.x); + (*d3dintf->effect.set_vector)(curr_effect, "SizeRatio", 2, &delta.c.x); + (*d3dintf->effect.set_vector)(curr_effect, "ConvergeX", 3, options->converge_x); + (*d3dintf->effect.set_vector)(curr_effect, "ConvergeY", 3, options->converge_y); + (*d3dintf->effect.set_vector)(curr_effect, "RadialConvergeX", 3, options->radial_converge_x); + (*d3dintf->effect.set_vector)(curr_effect, "RadialConvergeY", 3, options->radial_converge_y); + } + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[2]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + float defocus_x = options->defocus[0]; + float defocus_y = options->defocus[1]; + bool focus_enable = defocus_x != 0.0f || defocus_y != 0.0f; + if(focus_enable) + { + // Defocus pass 1 + curr_effect = focus_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[2]); + + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "Defocus", 2, &options->defocus[0]); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + // Defocus pass 2 + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[0]); + + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "Defocus", 2, &options->defocus[1]); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 7\n", (int)result); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + } + + // 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. + curr_effect = phosphor_effect; + + if(options->params_dirty) + { + //(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)rt->target_width); + //(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)rt->target_height); + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "Phosphor", 3, options->phosphor); + } + (*d3dintf->effect.set_float)(curr_effect, "TextureWidth", (float)rt->target_width); + (*d3dintf->effect.set_float)(curr_effect, "TextureHeight", (float)rt->target_height); + (*d3dintf->effect.set_float)(curr_effect, "Passthrough", 0.0f); + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", focus_enable ? rt->render_texture[1] : rt->render_texture[2]); + (*d3dintf->effect.set_texture)(curr_effect, "LastPass", ct->last_texture); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + // Pass along our phosphor'd screen + curr_effect = phosphor_effect; + + //(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + //(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + //(*d3dintf->effect.set_float)(curr_effect, "TextureWidth", (float)d3d->get_width()); + //(*d3dintf->effect.set_float)(curr_effect, "TextureHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[0]); + (*d3dintf->effect.set_texture)(curr_effect, "LastPass", rt->render_texture[0]); + (*d3dintf->effect.set_float)(curr_effect, "Passthrough", 1.0f); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, ct->last_target); // Avoid changing targets due to page flipping + //result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); // 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->get_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); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + curr_effect = post_effect; + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + + // Scanlines and shadow mask, at high res for AVI logging + if(avi_output_file != NULL) + { + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[0]); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, avi_final_target); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + } + + if(render_snap) + { + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[0]); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, snap_target); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + snap_rendered = true; + } + + // Scanlines and shadow mask + curr_effect = post_effect; + + //float raw_dims[2] = { d3d->get_width(), d3d->get_height() }; + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[0]); + (*d3dintf->effect.set_vector)(curr_effect, "RawDims", 2, &rawdims.c.x); + (*d3dintf->effect.set_vector)(curr_effect, "SizeRatio", 2, &delta.c.x); + + d3d->set_wrap(D3DTADDRESS_MIRROR); + +#if CRT_BLOOM + //(*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)rt->target_width); + //(*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)rt->target_height); + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[2]); + + d3d->set_wrap(D3DTADDRESS_MIRROR); + result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); +#else + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); +#endif + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(poly->get_texture()->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); + +#if CRT_BLOOM + // Bloom + curr_effect = downsample_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[2]); + (*d3dintf->effect.set_float)(curr_effect, "BloomRescale", options->raster_bloom_scale); + + float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); + int bloom_index = 0; + float bloom_width = rt->target_width; + float bloom_height = rt->target_height; + float prim_width = poly->get_prim_width(); + float prim_height = poly->get_prim_height(); + float prim_ratio[2] = { prim_width / bloom_width, prim_height / bloom_height }; + float screen_size[2] = { d3d->get_width(), d3d->get_height() }; + //float target_size[2] = { bloom_width * 0.5f, bloom_height * 0.5f }; + (*d3dintf->effect.set_vector)(curr_effect, "ScreenSize", 2, screen_size); + for(; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) + { + float target_size[2] = { bloom_width, bloom_height }; + float source_size[2] = { bloom_width * 0.5f, bloom_height * 0.5f }; + (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size); + (*d3dintf->effect.set_vector)(curr_effect, "SourceSize", 2, source_size); + (*d3dintf->effect.set_vector)(curr_effect, "PrimRatio", 2, prim_ratio); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", (bloom_index == 0) ? rt->render_texture[2] : rt->bloom_texture[bloom_index - 1]); + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->bloom_target[bloom_index]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); + //result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + //result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + bloom_index++; + bloom_width *= 0.5f; + bloom_height *= 0.5f; + } + + // Bloom composite pass + curr_effect = bloom_effect; + + float target_size[2] = { d3d->get_width(), d3d->get_height() }; + (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size); + float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, + options->bloom_level2_weight, options->bloom_level3_weight }; + float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, + options->bloom_level6_weight, options->bloom_level7_weight }; + float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, + options->bloom_level10_weight }; + (*d3dintf->effect.set_vector)(curr_effect, "Level0123Weight", 4, weight0123); + (*d3dintf->effect.set_vector)(curr_effect, "Level4567Weight", 4, weight4567); + (*d3dintf->effect.set_vector)(curr_effect, "Level89AWeight", 3, weight89A); + (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size); + + (*d3dintf->effect.set_texture)(curr_effect, "DiffuseA", rt->render_texture[2]); + (*d3dintf->effect.set_float)(curr_effect, "DiffuseScaleA", 1.0f); + + char name[9] = "Diffuse*"; + char scale[14] = "DiffuseScale*"; + for(int index = 1; index < bloom_index; index++) + { + name[7] = 'A' + index; + scale[12] = 'A' + index; + (*d3dintf->effect.set_texture)(curr_effect, name, rt->bloom_texture[index - 1]); + (*d3dintf->effect.set_float)(curr_effect, scale, 1.0f); + } + for(int index = bloom_index; index < 11; index++) + { + name[7] = 'A' + index; + scale[12] = 'A' + index; + (*d3dintf->effect.set_texture)(curr_effect, name, black_texture); + (*d3dintf->effect.set_float)(curr_effect, scale, 0.0f); + } + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + //HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); + //result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + //result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); +#endif + texture->increment_frame_count(); + texture->mask_frame_count(options->yiq_phase_count); + + options->params_dirty = false; + + } +#if HLSL_VECTOR + else if(PRIMFLAG_GET_VECTOR(poly->get_flags()) && vector_enable) + { + render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); + if (rt == NULL) + { + return; + } + + lines_pending = true; + + curr_effect = vector_effect; + + if(options->params_dirty) + { + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + } + + float time_params[2] = { 0.0f, 0.0f }; + float length_params[3] = { poly->get_line_length(), options->vector_length_scale, options->vector_length_ratio }; + (*d3dintf->effect.set_vector)(curr_effect, "TimeParams", 2, time_params); + (*d3dintf->effect.set_vector)(curr_effect, "LengthParams", 3, length_params); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + curr_effect = default_effect; + + (*d3dintf->effect.set_float)(curr_effect, "FixedAlpha", 1.0f); + } + else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable) + { + //if (!lines_pending) + //return; + //lines_pending = false; + + renderer *d3d = (renderer *)window->drawdata; + + render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); + if (rt == NULL) + { + return; + } + + /* Bloom */ + curr_effect = downsample_effect; + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[0]); + (*d3dintf->effect.set_float)(curr_effect, "BloomRescale", options->vector_bloom_scale); + + float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); + int bloom_index = 0; + float bloom_width = rt->target_width; + float bloom_height = rt->target_height; + float prim_width = poly->get_prim_width(); + float prim_height = poly->get_prim_height(); + float prim_ratio[2] = { prim_width / bloom_width, prim_height / bloom_height }; + float screen_size[2] = { d3d->get_width(), d3d->get_height() }; + //float target_size[2] = { bloom_width * 0.5f, bloom_height * 0.5f }; + (*d3dintf->effect.set_vector)(curr_effect, "ScreenSize", 2, screen_size); + for(; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) + { + float target_size[2] = { bloom_width, bloom_height }; + float source_size[2] = { bloom_width * 0.5f, bloom_height * 0.5f }; + (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size); + (*d3dintf->effect.set_vector)(curr_effect, "SourceSize", 2, source_size); + (*d3dintf->effect.set_vector)(curr_effect, "PrimRatio", 2, prim_ratio); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", (bloom_index == 0) ? rt->render_texture[0] : rt->bloom_texture[bloom_index - 1]); + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->bloom_target[bloom_index]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); + //result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + bloom_index++; + bloom_width *= 0.5f; + bloom_height *= 0.5f; + } + + // Bloom composite pass + curr_effect = bloom_effect; + + float target_size[2] = { d3d->get_width(), d3d->get_height() }; + (*d3dintf->effect.set_vector)(curr_effect, "TargetSize", 2, target_size); + float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, + options->bloom_level2_weight, options->bloom_level3_weight }; + float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, + options->bloom_level6_weight, options->bloom_level7_weight }; + float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, + options->bloom_level10_weight }; + (*d3dintf->effect.set_vector)(curr_effect, "Level0123Weight", 4, weight0123); + (*d3dintf->effect.set_vector)(curr_effect, "Level4567Weight", 4, weight4567); + (*d3dintf->effect.set_vector)(curr_effect, "Level89AWeight", 3, weight89A); + + (*d3dintf->effect.set_texture)(curr_effect, "DiffuseA", rt->render_texture[0]); + (*d3dintf->effect.set_float)(curr_effect, "DiffuseScaleA", 1.0f); + + char name[9] = "Diffuse*"; + char scale[14] = "DiffuseScale*"; + for(int index = 1; index < bloom_index; index++) + { + name[7] = 'A' + index; + scale[12] = 'A' + index; + (*d3dintf->effect.set_texture)(curr_effect, name, rt->bloom_texture[index - 1]); + (*d3dintf->effect.set_float)(curr_effect, scale, 1.0f); + } + for(int index = bloom_index; index < 11; index++) + { + name[7] = 'A' + index; + scale[12] = 'A' + index; + (*d3dintf->effect.set_texture)(curr_effect, name, black_texture); + (*d3dintf->effect.set_float)(curr_effect, scale, 0.0f); + } + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + /* Phosphor */ + curr_effect = phosphor_effect; + + if(options->params_dirty) + { + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_vector)(curr_effect, "Phosphor", 3, options->phosphor); + } + (*d3dintf->effect.set_float)(curr_effect, "TextureWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TextureHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "Passthrough", 0.0f); + + (*d3dintf->effect.set_texture)(curr_effect, "Diffuse", rt->render_texture[1]); + (*d3dintf->effect.set_texture)(curr_effect, "LastPass", rt->render_texture[2]); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[3]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + + blit(rt->target[2], rt->render_texture[3], NULL, poly->get_type(), vertnum, poly->get_count()); + blit(backbuffer, rt->render_texture[3], backbuffer, poly->get_type(), vertnum, poly->get_count()); + + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + lines_pending = false; + } +#else + else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable) + { + // Do nothing + } +#endif + else + { + curr_effect = default_effect; + + (*d3dintf->effect.set_float)(curr_effect, "TargetWidth", (float)d3d->get_width()); + (*d3dintf->effect.set_float)(curr_effect, "TargetHeight", (float)d3d->get_height()); + (*d3dintf->effect.set_float)(curr_effect, "PostPass", 0.0f); + + (*d3dintf->effect.begin)(curr_effect, &num_passes, 0); + + for (UINT pass = 0; pass < num_passes; pass++) + { + (*d3dintf->effect.begin_pass)(curr_effect, pass); + // add the primitives + HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + (*d3dintf->effect.end_pass)(curr_effect); + } + + (*d3dintf->effect.end)(curr_effect); + } +} + + + +//============================================================ +// shaders::end_draw +//============================================================ + +void shaders::end_draw() +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + (*d3dintf->surface.release)(backbuffer); +} + + +//============================================================ +// shaders::register_prescaled_texture +//============================================================ + +bool shaders::register_prescaled_texture(texture_info *texture) +{ + return register_texture(texture); +} + + +//============================================================ +// shaders::add_cache_target - register a cache target +//============================================================ +bool shaders::add_cache_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index) +{ + cache_target* target = (cache_target*)global_alloc_clear(cache_target); + + if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) + { + global_free(target); + return false; + } + + if (info != NULL) + { + target->width = info->get_texinfo().width; + target->height = info->get_texinfo().height; + } + else + { + target->width = d3d->get_width(); + target->height = d3d->get_height(); + } + + target->next = cachehead; + target->prev = NULL; + + target->screen_index = screen_index; + + if (cachehead != NULL) + { + cachehead->prev = target; + } + cachehead = target; + + return true; +} + +render_target* shaders::get_vector_target() +{ +#if HLSL_VECTOR + if (!vector_enable) + { + return NULL; + } + + renderer *d3d = (renderer *)window->drawdata; + + return find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); +#else + return NULL; +#endif +} + +void shaders::create_vector_target(render_primitive *prim) +{ +#if HLSL_VECTOR + renderer *d3d = (renderer *)window->drawdata; + if (!add_render_target(d3d, NULL, d3d->get_width(), d3d->get_height(), 1, 1)) + { + vector_enable = false; + } +#endif +} + +//============================================================ +// shaders::add_render_target - register a render target +//============================================================ + +bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale) +{ + UINT32 screen_index = 0; + UINT32 page_index = 0; + if (info != NULL) + { + render_target *existing_target = find_render_target(info); + if (existing_target != NULL) + { + remove_render_target(existing_target); + } + + UINT32 screen_index_data = (UINT32)info->get_texinfo().osddata; + screen_index = screen_index_data >> 1; + page_index = screen_index_data & 1; + } + else + { + render_target *existing_target = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); + if (existing_target != NULL) + { + remove_render_target(existing_target); + } + } + + render_target* target = (render_target*)global_alloc_clear(render_target); + + if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) + { + global_free(target); + return false; + } + + if (info != NULL) + { + target->width = info->get_texinfo().width; + target->height = info->get_texinfo().height; + } + else + { + target->width = d3d->get_width(); + target->height = d3d->get_height(); + } + + HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, target->target[0]); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + result = (*d3dintf->device.clear)(d3d->get_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); + result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); + + target->screen_index = screen_index; + target->page_index = page_index; + + cache_target* cache = find_cache_target(target->screen_index, target->width, target->height); + if (cache == NULL) + { + if (!add_cache_target(d3d, info, width, height, xprescale, yprescale, target->screen_index)) + { + global_free(target); + return false; + } + } + + target->next = targethead; + target->prev = NULL; + + if (targethead != NULL) + { + targethead->prev = target; + } + targethead = target; + + return true; +} + +//============================================================ +// shaders::enumerate_screens +//============================================================ +void shaders::enumerate_screens() +{ + screen_device_iterator iter(window->machine().root_device()); + num_screens = iter.count(); +} + + +//============================================================ +// shaders::register_texture(texture::info) +//============================================================ + +bool shaders::register_texture(texture_info *texture) +{ + int width = texture->get_width(); + int height = texture->get_height(); + int xscale = texture->get_xscale(); + int yscale = texture->get_yscale(); + + if (!master_enable || !d3dintf->post_fx_available) + { + return false; + } + + enumerate_screens(); + + renderer *d3d = (renderer *)window->drawdata; + + int hlsl_prescale_x = prescale_force_x; + int hlsl_prescale_y = prescale_force_y; + + // Find the nearest prescale factor that is over our screen size + if (hlsl_prescale_x == 0) + { + hlsl_prescale_x = 1; + while (width * xscale * hlsl_prescale_x <= d3d->get_width()) + { + hlsl_prescale_x++; + } + hlsl_prescale_x--; + } + + if (hlsl_prescale_y == 0) + { + hlsl_prescale_y = 1; + while (height * yscale * hlsl_prescale_y <= d3d->get_height()) + { + hlsl_prescale_y++; + } + hlsl_prescale_y--; + } + + hlsl_prescale_x = ((hlsl_prescale_x == 0) ? 1 : hlsl_prescale_x); + hlsl_prescale_y = ((hlsl_prescale_y == 0) ? 1 : hlsl_prescale_y); + + if (!add_render_target(d3d, texture, width, height, xscale * hlsl_prescale_x, yscale * hlsl_prescale_y)) + return false; + + options->params_dirty = true; + + return true; +} + +//============================================================ +// shaders::delete_resources +//============================================================ + +void shaders::delete_resources(bool reset) +{ + if (!master_enable || !d3dintf->post_fx_available) + return; + + initialized = false; + + if(write_ini && !reset) + { + emu_file file(downcast(window->machine().options()).screen_post_fx_dir(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + file_error filerr = open_next((renderer*)window->drawdata, file, downcast(window->machine().options()).hlsl_ini_name(), "ini", 0); + + if (filerr != FILERR_NONE) + return; + + file.printf("hlsl_enable %d\n", master_enable ? 1 : 0); + file.printf("hlsl_prescale_x %d\n", prescale_force_x); + file.printf("hlsl_prescale_y %d\n", prescale_force_y); + file.printf("hlsl_preset %d\n", preset); + file.printf("hlsl_snap_width %d\n", snap_width); + file.printf("hlsl_snap_height %d\n", snap_height); + file.printf("shadow_mask_alpha %f\n", options->shadow_mask_alpha); + file.printf("shadow_mask_texture %s\n", options->shadow_mask_texture); + file.printf("shadow_mask_x_count %d\n", options->shadow_mask_count_x); + file.printf("shadow_mask_y_count %d\n", options->shadow_mask_count_y); + file.printf("shadow_mask_usize %f\n", options->shadow_mask_u_size); + file.printf("shadow_mask_vsize %f\n", options->shadow_mask_v_size); + file.printf("curvature %f\n", options->curvature); + file.printf("pincushion %f\n", options->pincushion); + file.printf("scanline_alpha %f\n", options->scanline_alpha); + file.printf("scanline_size %f\n", options->scanline_scale); + file.printf("scanline_height %f\n", options->scanline_height); + file.printf("scanline_bright_scale %f\n", options->scanline_bright_scale); + file.printf("scanline_bright_offset %f\n", options->scanline_bright_offset); + file.printf("scanline_jitter %f\n", options->scanline_offset); + file.printf("defocus %f,%f\n", options->defocus[0], options->defocus[1]); + file.printf("converge_x %f,%f,%f\n", options->converge_x[0], options->converge_x[1], options->converge_x[2]); + file.printf("converge_y %f,%f,%f\n", options->converge_y[0], options->converge_y[1], options->converge_y[2]); + file.printf("radial_converge_x %f,%f,%f\n", options->radial_converge_x[0], options->radial_converge_x[1], options->radial_converge_x[2]); + file.printf("radial_converge_y %f,%f,%f\n", options->radial_converge_y[0], options->radial_converge_y[1], options->radial_converge_y[2]); + file.printf("red_ratio %f,%f,%f\n", options->red_ratio[0], options->red_ratio[1], options->red_ratio[2]); + file.printf("grn_ratio %f,%f,%f\n", options->grn_ratio[0], options->grn_ratio[1], options->grn_ratio[2]); + file.printf("blu_ratio %f,%f,%f\n", options->blu_ratio[0], options->blu_ratio[1], options->blu_ratio[2]); + file.printf("saturation %f\n", options->saturation); + file.printf("offset %f,%f,%f\n", options->offset[0], options->offset[1], options->offset[2]); + file.printf("scale %f,%f,%f\n", options->scale[0], options->scale[1], options->scale[2]); + file.printf("power %f,%f,%f\n", options->power[0], options->power[1], options->power[2]); + file.printf("floor %f,%f,%f\n", options->floor[0], options->floor[1], options->floor[2]); + file.printf("phosphor_life %f,%f,%f\n", options->phosphor[0], options->phosphor[1], options->phosphor[2]); + file.printf("yiq_enable %d\n", options->yiq_enable ? 1 : 0); + file.printf("yiq_cc %f\n", options->yiq_cc); + file.printf("yiq_a %f\n", options->yiq_a); + file.printf("yiq_b %f\n", options->yiq_b); + file.printf("yiq_o %f\n", options->yiq_o); + file.printf("yiq_p %f\n", options->yiq_p); + file.printf("yiq_n %f\n", options->yiq_n); + file.printf("yiq_y %f\n", options->yiq_y); + file.printf("yiq_i %f\n", options->yiq_i); + file.printf("yiq_q %f\n", options->yiq_q); + file.printf("yiq_scan_time %f\n", options->yiq_scan_time); + file.printf("yiq_phase_count %d\n", options->yiq_phase_count); + file.printf("vector_length_scale %f\n", options->vector_length_scale); + file.printf("vector_length_ratio %f\n", options->vector_length_ratio); + } + + while (targethead != NULL) + { + remove_render_target(targethead); + } + +#if (HLSL_VECTOR || CRT_BLOOM) + if (downsample_effect != NULL) + { + (*d3dintf->effect.release)(downsample_effect); + downsample_effect = NULL; + } + if (bloom_effect != NULL) + { + (*d3dintf->effect.release)(bloom_effect); + bloom_effect = NULL; + } +#endif + if (default_effect != NULL) + { + (*d3dintf->effect.release)(default_effect); + default_effect = NULL; + } + if (post_effect != NULL) + { + (*d3dintf->effect.release)(post_effect); + post_effect = NULL; + } + if (prescale_effect != NULL) + { + (*d3dintf->effect.release)(prescale_effect); + prescale_effect = NULL; + } + if (pincushion_effect != NULL) + { + (*d3dintf->effect.release)(pincushion_effect); + pincushion_effect = NULL; + } + if (phosphor_effect != NULL) + { + (*d3dintf->effect.release)(phosphor_effect); + phosphor_effect = NULL; + } + if (focus_effect != NULL) + { + (*d3dintf->effect.release)(focus_effect); + focus_effect = NULL; + } + if (deconverge_effect != NULL) + { + (*d3dintf->effect.release)(deconverge_effect); + deconverge_effect = NULL; + } + if (color_effect != NULL) + { + (*d3dintf->effect.release)(color_effect); + color_effect = NULL; + } + if (yiq_encode_effect != NULL) + { + (*d3dintf->effect.release)(yiq_encode_effect); + yiq_encode_effect = NULL; + } + if (yiq_decode_effect != NULL) + { + (*d3dintf->effect.release)(yiq_decode_effect); + yiq_decode_effect = NULL; + } + + if (black_texture != NULL) + { + (*d3dintf->texture.release)(black_texture); + black_texture = NULL; + } + + if (avi_copy_texture != NULL) + { + (*d3dintf->texture.release)(avi_copy_texture); + avi_copy_texture = NULL; + } + + if (avi_copy_surface != NULL) + { + (*d3dintf->surface.release)(avi_copy_surface); + avi_copy_surface = NULL; + } + + if (avi_final_texture != NULL) + { + (*d3dintf->texture.release)(avi_final_texture); + avi_final_texture = NULL; + } + + if (avi_final_target != NULL) + { + (*d3dintf->surface.release)(avi_final_target); + avi_final_target = NULL; + } + + shadow_bitmap.reset(); +} + + +//============================================================ +// get_vector +//============================================================ + +static void get_vector(const char *data, int count, float *out, int report_error) +{ + if (count > 3) + { + if (sscanf(data, "%f,%f,%f,%f", &out[0], &out[1], &out[2], &out[3]) < 4 && report_error) + mame_printf_error("Illegal quad vector value = %s\n", data); + } + else if(count > 2) + { + if (sscanf(data, "%f,%f,%f", &out[0], &out[1], &out[2]) < 3 && report_error) + mame_printf_error("Illegal triple vector value = %s\n", data); + } + else if(count > 1) + { + if (sscanf(data, "%f,%f", &out[0], &out[1]) < 2 && report_error) + mame_printf_error("Illegal double vector value = %s\n", data); + } + else if(count > 0) + { + if (sscanf(data, "%f", &out[0]) < 1 && report_error) + mame_printf_error("Illegal single vector value = %s\n", data); + } +} + + +/*------------------------------------------------- + slider_alloc - allocate a new slider entry + currently duplicated from ui.c, this could + be done in a more ideal way. +-------------------------------------------------*/ + +static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg) +{ + int size = sizeof(slider_state) + strlen(title); + slider_state *state = (slider_state *)auto_alloc_array_clear(machine, UINT8, size); + + state->minval = minval; + state->defval = defval; + state->maxval = maxval; + state->incval = incval; + state->update = update; + state->arg = arg; + strcpy(state->description, title); + + return state; +} + + +//============================================================ +// assorted global slider accessors +//============================================================ + +static INT32 slider_set(float *option, float scale, const char *fmt, astring *string, INT32 newval) +{ + if (option != NULL && newval != SLIDER_NOCHANGE) *option = (float)newval * scale; + if (string != NULL) string->printf(fmt, *option); + return floor(*option / scale + 0.5f); +} + +static INT32 slider_shadow_mask_alpha(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + return slider_set(&(((hlsl_options*)arg)->shadow_mask_alpha), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_shadow_mask_x_count(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + hlsl_options *options = (hlsl_options*)arg; + if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_x = newval; + if (string != NULL) string->printf("%d", options->shadow_mask_count_x); + options->params_dirty = true; + return options->shadow_mask_count_x; +} + +static INT32 slider_shadow_mask_y_count(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + hlsl_options *options = (hlsl_options*)arg; + if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_y = newval; + if (string != NULL) string->printf("%d", options->shadow_mask_count_y); + options->params_dirty = true; + return options->shadow_mask_count_y; +} + +static INT32 slider_shadow_mask_usize(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->shadow_mask_u_size), 1.0f / 32.0f, "%2.5f", string, newval); +} + +static INT32 slider_shadow_mask_vsize(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->shadow_mask_v_size), 1.0f / 32.0f, "%2.5f", string, newval); +} + +static INT32 slider_curvature(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->curvature), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_pincushion(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->pincushion), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_scanline_alpha(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scanline_alpha), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_scanline_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scanline_scale), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_scanline_height(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scanline_height), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_scanline_bright_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scanline_bright_scale), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_scanline_bright_offset(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scanline_bright_offset), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_scanline_offset(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scanline_offset), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_defocus_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->defocus[0]), 0.5f, "%2.1f", string, newval); +} + +static INT32 slider_defocus_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->defocus[1]), 0.5f, "%2.1f", string, newval); +} + +static INT32 slider_red_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->converge_x[0]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_red_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->converge_y[0]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_green_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->converge_x[1]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_green_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->converge_y[1]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_blue_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->converge_x[2]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_blue_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->converge_y[2]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_red_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->radial_converge_x[0]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_red_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->radial_converge_y[0]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_green_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->radial_converge_x[1]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_green_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->radial_converge_y[1]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_blue_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->radial_converge_x[2]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_blue_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->radial_converge_y[2]), 0.1f, "%3.1f", string, newval); +} + +static INT32 slider_red_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->red_ratio[0]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_red_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->red_ratio[1]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_red_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->red_ratio[2]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_green_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->grn_ratio[0]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_green_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->grn_ratio[1]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_green_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->grn_ratio[2]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_blue_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->blu_ratio[0]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_blue_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->blu_ratio[1]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_blue_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->blu_ratio[2]), 0.005f, "%2.3f", string, newval); +} + +static INT32 slider_red_offset(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->offset[0]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_green_offset(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->offset[1]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_blue_offset(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->offset[2]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_red_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scale[0]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_green_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scale[1]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_blue_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->scale[2]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_red_power(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->power[0]), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_green_power(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->power[1]), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_blue_power(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->power[2]), 0.05f, "%2.2f", string, newval); +} + +static INT32 slider_red_floor(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->floor[0]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_green_floor(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->floor[1]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_blue_floor(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->floor[2]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_red_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->phosphor[0]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_green_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->phosphor[1]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_blue_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->phosphor[2]), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_saturation(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->saturation), 0.01f, "%2.2f", string, newval); +} + +static INT32 slider_vector_attenuation(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->vector_length_scale), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_vector_length_max(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->vector_length_ratio), 1.0f, "%4f", string, newval); +} + +static INT32 slider_vector_bloom_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->vector_bloom_scale), 0.001f, "%1.3f", string, newval); +} + +static INT32 slider_raster_bloom_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->raster_bloom_scale), 0.001f, "%1.3f", string, newval); +} + +static INT32 slider_bloom_lvl0_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level0_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl1_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level1_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl2_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level2_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl3_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level3_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl4_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level4_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl5_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level5_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl6_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level6_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl7_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level7_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl8_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level8_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl9_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level9_weight), 0.01f, "%1.2f", string, newval); +} + +static INT32 slider_bloom_lvl10_scale(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + ((hlsl_options*)arg)->params_dirty = true; + return slider_set(&(((hlsl_options*)arg)->bloom_level10_weight), 0.01f, "%1.2f", string, newval); +} + +//============================================================ +// init_slider_list +//============================================================ + +shaders::slider_desc shaders::s_sliders[] = +{ + { "Shadow Mask Darkness", 0, 0, 100, 1, slider_shadow_mask_alpha }, + { "Shadow Mask X Count", 1, 320, 1024, 1, slider_shadow_mask_x_count }, + { "Shadow Mask Y Count", 1, 240, 1024, 1, slider_shadow_mask_y_count }, + { "Shadow Mask Pixel Count X", 1, 6, 64, 1, slider_shadow_mask_usize }, + { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, + { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, + { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, + { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, + { "Screen Curvature", 0, 3, 100, 1, slider_curvature }, + { "Image Pincushion", 0, 3, 100, 1, slider_pincushion }, + { "Scanline Darkness", 0, 100, 100, 1, slider_scanline_alpha }, + { "Scanline Screen Height", 1, 20, 80, 1, slider_scanline_scale }, + { "Scanline Indiv. Height", 1, 20, 80, 1, slider_scanline_height }, + { "Scanline Brightness", 0, 20, 40, 1, slider_scanline_bright_scale }, + { "Scanline Brightness Overdrive", 0, 0, 20, 1, slider_scanline_bright_offset }, + { "Scanline Jitter", 0, 0, 40, 1, slider_scanline_offset }, + { "Defocus X", 0, 0, 64, 1, slider_defocus_x }, + { "Defocus Y", 0, 0, 64, 1, slider_defocus_y }, + { "Red Position Offset X", -1500, 3, 1500, 1, slider_red_converge_x }, + { "Red Position Offset Y", -1500, 0, 1500, 1, slider_red_converge_y }, + { "Green Position Offset X", -1500, 0, 1500, 1, slider_green_converge_x }, + { "Green Position Offset Y", -1500, 3, 1500, 1, slider_green_converge_y }, + { "Blue Position Offset X", -1500, 3, 1500, 1, slider_blue_converge_x }, + { "Blue Position Offset Y", -1500, 3, 1500, 1, slider_blue_converge_y }, + { "Red Convergence X", -1500, 0, 1500, 1, slider_red_radial_converge_x }, + { "Red Convergence Y", -1500, 0, 1500, 1, slider_red_radial_converge_y }, + { "Green Convergence X", -1500, 0, 1500, 1, slider_green_radial_converge_x }, + { "Green Convergence Y", -1500, 0, 1500, 1, slider_green_radial_converge_y }, + { "Blue Convergence X", -1500, 0, 1500, 1, slider_blue_radial_converge_x }, + { "Blue Convergence Y", -1500, 0, 1500, 1, slider_blue_radial_converge_y }, + { "Red Output from Red Input", -400, 0, 400, 5, slider_red_from_r }, + { "Red Output from Green Input", -400, 0, 400, 5, slider_red_from_g }, + { "Red Output from Blue Input", -400, 0, 400, 5, slider_red_from_b }, + { "Green Output from Red Input", -400, 0, 400, 5, slider_green_from_r }, + { "Green Output from Green Input", -400, 0, 400, 5, slider_green_from_g }, + { "Green Output from Blue Input", -400, 0, 400, 5, slider_green_from_b }, + { "Blue Output from Red Input", -400, 0, 400, 5, slider_blue_from_r }, + { "Blue Output from Green Input", -400, 0, 400, 5, slider_blue_from_g }, + { "Blue Output from Blue Input", -400, 0, 400, 5, slider_blue_from_b }, + { "Saturation", 0, 140, 400, 1, slider_saturation }, + { "Red DC Offset", -100, 0, 100, 1, slider_red_offset }, + { "Green DC Offset", -100, 0, 100, 1, slider_green_offset }, + { "Blue DC Offset", -100, 0, 100, 1, slider_blue_offset }, + { "Red Scale", -200, 95, 200, 1, slider_red_scale }, + { "Green Scale", -200, 95, 200, 1, slider_green_scale }, + { "Blue Scale", -200, 95, 200, 1, slider_blue_scale }, + { "Red Gamma", -80, 16, 80, 1, slider_red_power }, + { "Green Gamma", -80, 16, 80, 1, slider_green_power }, + { "Blue Gamma", -80, 16, 80, 1, slider_blue_power }, + { "Red Floor", 0, 5, 100, 1, slider_red_floor }, + { "Green Floor", 0, 5, 100, 1, slider_green_floor }, + { "Blue Floor", 0, 5, 100, 1, slider_blue_floor }, + { "Red Phosphor Life", 0, 40, 100, 1, slider_red_phosphor_life }, + { "Green Phosphor Life", 0, 40, 100, 1, slider_green_phosphor_life }, + { "Blue Phosphor Life", 0, 40, 100, 1, slider_blue_phosphor_life }, + { "Vector Length Attenuation", 0, 80, 100, 1, slider_vector_attenuation }, + { "Vector Attenuation Length Limit", 1, 500, 1000, 1, slider_vector_length_max }, + { "Vector Bloom Scale", 0, 300, 1000, 5, slider_vector_bloom_scale }, + { "Raster Bloom Scale", 0, 225, 1000, 5, slider_raster_bloom_scale }, + { "Bloom Level 0 Scale", 0, 100, 100, 1, slider_bloom_lvl0_scale }, + { "Bloom Level 1 Scale", 0, 21, 100, 1, slider_bloom_lvl1_scale }, + { "Bloom Level 2 Scale", 0, 19, 100, 1, slider_bloom_lvl2_scale }, + { "Bloom Level 3 Scale", 0, 17, 100, 1, slider_bloom_lvl3_scale }, + { "Bloom Level 4 Scale", 0, 15, 100, 1, slider_bloom_lvl4_scale }, + { "Bloom Level 5 Scale", 0, 14, 100, 1, slider_bloom_lvl5_scale }, + { "Bloom Level 6 Scale", 0, 13, 100, 1, slider_bloom_lvl6_scale }, + { "Bloom Level 7 Scale", 0, 12, 100, 1, slider_bloom_lvl7_scale }, + { "Bloom Level 8 Scale", 0, 11, 100, 1, slider_bloom_lvl8_scale }, + { "Bloom Level 9 Scale", 0, 10, 100, 1, slider_bloom_lvl9_scale }, + { "Bloom Level 10 Scale", 0, 9, 100, 1, slider_bloom_lvl10_scale }, + { NULL, 0, 0, 0, 0, NULL }, +}; + +slider_state *shaders::init_slider_list() +{ + if (!master_enable || !d3dintf->post_fx_available) + { + g_slider_list = NULL; + return NULL; + } + + slider_state *listhead = NULL; + slider_state **tailptr = &listhead; + + for (int index = 0; s_sliders[index].name != NULL; index++) + { + slider_desc *slider = &s_sliders[index]; + *tailptr = slider_alloc(window->machine(), slider->name, slider->minval, slider->defval, slider->maxval, slider->step, slider->adjustor, (void*)options); + tailptr = &(*tailptr)->next; + } + + return listhead; +} + +}; + +//============================================================ +// get_slider_list +//============================================================ + +void *windows_osd_interface::get_slider_list() +{ + return (void*)g_slider_list; +} + + + +// NOTE: The function below is taken directly from src/emu/video.c and should likely be moved into a global helper function. +//------------------------------------------------- +// open_next - open the next non-existing file of +// type filetype according to our numbering +// scheme +//------------------------------------------------- + +static file_error open_next(d3d::renderer *d3d, emu_file &file, const char *templ, const char *extension, int idx) +{ + UINT32 origflags = file.openflags(); + + // handle defaults + const char *snapname = templ ? templ : d3d->get_window()->machine().options().snap_name(); + + if (snapname == NULL || snapname[0] == 0) + snapname = "%g/%i"; + astring snapstr(snapname); + + // strip any extension in the provided name + int index = snapstr.rchr(0, '.'); + if (index != -1) + snapstr.substr(0, index); + + // handle %d in the template (for image devices) + astring snapdev("%d_"); + int pos = snapstr.find(0, snapdev); + + if (pos != -1) + { + // if more %d are found, revert to default and ignore them all + if (snapstr.find(pos + 3, snapdev) != -1) + snapstr.cpy("%g/%i"); + // else if there is a single %d, try to create the correct snapname + else + { + int name_found = 0; + + // find length of the device name + int end1 = snapstr.find(pos + 3, "/"); + int end2 = snapstr.find(pos + 3, "%"); + int end = -1; + + if ((end1 != -1) && (end2 != -1)) + end = MIN(end1, end2); + else if (end1 != -1) + end = end1; + else if (end2 != -1) + end = end2; + else + end = snapstr.len(); + + if (end - pos < 3) + fatalerror("Something very wrong is going on!!!\n"); + + // copy the device name to an astring + astring snapdevname; + snapdevname.cpysubstr(snapstr, pos + 3, end - pos - 3); + + // verify that there is such a device for this system + image_interface_iterator iter(d3d->get_window()->machine().root_device()); + for (device_image_interface *image = iter.first(); image != NULL; iter.next()) + { + // get the device name + astring tempdevname(image->brief_instance_name()); + + if (snapdevname.cmp(tempdevname) == 0) + { + // verify that such a device has an image mounted + if (image->basename() != NULL) + { + astring filename(image->basename()); + + // strip extension + filename.substr(0, filename.rchr(0, '.')); + + // setup snapname and remove the %d_ + snapstr.replace(0, snapdevname, filename); + snapstr.del(pos, 3); + + name_found = 1; + } + } + } + + // or fallback to default + if (name_found == 0) + snapstr.cpy("%g/%i"); + } + } + + // add our own index + // add our own extension + snapstr.cat(".").cat(extension); + + // substitute path and gamename up front + snapstr.replace(0, "/", PATH_SEPARATOR); + snapstr.replace(0, "%g", d3d->get_window()->machine().basename()); + + // determine if the template has an index; if not, we always use the same name + astring fname; + if (snapstr.find(0, "%i") == -1) + fname.cpy(snapstr); + + // otherwise, we scan for the next available filename + else + { + // try until we succeed + astring seqtext; + file.set_openflags(OPEN_FLAG_READ); + for (int seq = 0; ; seq++) + { + // build up the filename + fname.cpy(snapstr).replace(0, "%i", seqtext.format("%04d_%d", seq, idx).cstr()); + + // try to open the file; stop when we fail + file_error filerr = file.open(fname); + if (filerr != FILERR_NONE) + break; + } + } + + // create the final file + file.set_openflags(origflags); + return file.open(fname); +} diff --git a/src/osd/windows/d3dhlsl.h b/src/osd/windows/d3dhlsl.h new file mode 100644 index 00000000000..e712d0e00a7 --- /dev/null +++ b/src/osd/windows/d3dhlsl.h @@ -0,0 +1,291 @@ +//============================================================ +// +// drawd3d.c - Win32 Direct3D HLSL-specific header +// +//============================================================ +// +// Copyright Aaron Giles +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the +// above copyright notice, this list of conditions and +// the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// * Neither the name 'MAME' nor the names of its +// contributors may be used to endorse or promote +// products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================ + +#ifndef __WIN_D3DHLSL__ +#define __WIN_D3DHLSL__ + +#include "aviio.h" + +//============================================================ +// CONSTANTS +//============================================================ + +#define HLSL_VECTOR (1) +#define CRT_BLOOM (1) + +//============================================================ +// TYPE DEFINITIONS +//============================================================ + +namespace d3d +{ +class render_target; +class cache_target; +class renderer; + +/* hlsl_options is the information about runtime-mutable Direct3D HLSL options */ +/* in the future this will be moved into an OSD/emu shared buffer */ +struct hlsl_options +{ + bool params_dirty; + float shadow_mask_alpha; + char shadow_mask_texture[1024]; + int shadow_mask_count_x; + int shadow_mask_count_y; + float shadow_mask_u_size; + float shadow_mask_v_size; + float curvature; + float pincushion; + float scanline_alpha; + float scanline_scale; + float scanline_height; + float scanline_bright_scale; + float scanline_bright_offset; + float scanline_offset; + float defocus[4]; + float converge_x[3]; + float converge_y[3]; + float radial_converge_x[3]; + float radial_converge_y[3]; + float red_ratio[3]; + float grn_ratio[3]; + float blu_ratio[3]; + float offset[3]; + float scale[3]; + float power[3]; + float floor[3]; + float phosphor[3]; + float saturation; + + // NTSC + bool yiq_enable; + float yiq_cc; + float yiq_a; + float yiq_b; + float yiq_o; + float yiq_p; + float yiq_n; + float yiq_y; + float yiq_i; + float yiq_q; + float yiq_scan_time; + int yiq_phase_count; + + // Vectors + float vector_length_scale; + float vector_length_ratio; + + // Bloom + float vector_bloom_scale; + float raster_bloom_scale; + float bloom_level0_weight; + float bloom_level1_weight; + float bloom_level2_weight; + float bloom_level3_weight; + float bloom_level4_weight; + float bloom_level5_weight; + float bloom_level6_weight; + float bloom_level7_weight; + float bloom_level8_weight; + float bloom_level9_weight; + float bloom_level10_weight; +}; + +class shaders +{ +public: + // construction/destruction + shaders(); + ~shaders(); + + void init(base *d3dintf, win_window_info *window); + + bool enabled() { return master_enable; } + void toggle(); + + bool vector_enabled() { return master_enable && vector_enable && (bool)HLSL_VECTOR; } + render_target* get_vector_target(); + void create_vector_target(render_primitive *prim); + + void begin_frame(); + void end_frame(); + + void begin_draw(); + void end_draw(); + + void init_effect_info(poly_info *poly); + void render_quad(poly_info *poly, int vertnum); + + bool register_texture(texture_info *texture); + bool register_prescaled_texture(texture_info *texture); + bool add_render_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale); + bool add_cache_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index); + + void window_save(); + void window_record(); + bool recording() { return avi_output_file != NULL; } + + void avi_update_snap(surface *surface); + void render_snapshot(surface *surface); + void record_texture(); + void init_fsfx_quad(void *vertbuf); + + void set_texture(texture_info *texture); + render_target * find_render_target(texture_info *info); + void remove_render_target(texture_info *texture); + void remove_render_target(int width, int height, UINT32 screen_index, UINT32 page_index); + void remove_render_target(render_target *rt); + + int create_resources(bool reset); + void delete_resources(bool reset); + + // slider-related functions + slider_state *init_slider_list(); + + struct slider_desc + { + const char * name; + int minval; + int defval; + int maxval; + int step; + INT32 (*adjustor)(running_machine &, void *, astring *, INT32); + }; + +private: + void blit(surface *dst, texture *src, surface *new_dst, + D3DPRIMITIVETYPE prim_type, UINT32 prim_index, UINT32 prim_count, + int dstw, int dsth); + void blit(surface *dst, texture *src, surface *new_dst, + D3DPRIMITIVETYPE prim_type, UINT32 prim_index, UINT32 prim_count); + void enumerate_screens(); + + void end_avi_recording(); + void begin_avi_recording(const char *name); + + bool register_texture(texture_info *texture, int width, int height, int xscale, int yscale); + + render_target* find_render_target(int width, int height, UINT32 screen_index, UINT32 page_index); + cache_target * find_cache_target(UINT32 screen_index, int width, int height); + void remove_cache_target(cache_target *cache); + + base * d3dintf; // D3D interface + win_window_info * window; // D3D window info + + bool master_enable; // overall enable flag + bool vector_enable; // vector post-processing enable flag + bool paused; // whether or not rendering is currently paused + int num_screens; // number of emulated physical screens + int curr_screen; // current screen for render target operations + int curr_frame; // current frame (0/1) of a screen for render target operations + 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 + int prescale_force_y; // prescale force y + int prescale_size_x; // prescale size x + int prescale_size_y; // prescale size y + int preset; // preset, if relevant + bitmap_argb32 shadow_bitmap; // shadow mask bitmap for post-processing shader + texture_info * shadow_texture; // shadow mask texture for post-processing shader + hlsl_options * options; // current uniform state + D3DPRIMITIVETYPE vecbuf_type; + UINT32 vecbuf_index; + UINT32 vecbuf_count; + + avi_file * avi_output_file; // AVI file + bitmap_rgb32 avi_snap; // AVI snapshot + int avi_frame; // AVI frame + attotime avi_frame_period; // AVI frame period + attotime avi_next_frame_time; // AVI next frame time + surface * avi_copy_surface; // AVI destination surface in system memory + texture * avi_copy_texture; // AVI destination texture in system memory + surface * avi_final_target; // AVI upscaled surface + texture * avi_final_texture; // AVI upscaled texture + + surface * black_surface; // black dummy surface + texture * black_texture; // black dummy texture + + bool render_snap; // whether or not to take HLSL post-render snapshot + bool snap_rendered; // whether we just rendered our HLSL post-render shot or not + surface * snap_copy_target; // snapshot destination surface in system memory + texture * snap_copy_texture; // snapshot destination surface in system memory + surface * snap_target; // snapshot upscaled surface + texture * snap_texture; // snapshot upscaled texture + int snap_width; // snapshot width + int snap_height; // snapshot height + bool lines_pending; // whether or not we have lines to flush on the next quad + + bool initialized; // whether or not we're initialize + + // HLSL effects + surface * backbuffer; // pointer to our device's backbuffer + effect * curr_effect; // pointer to the currently active effect object + effect * default_effect; // pointer to the primary-effect object + effect * prescale_effect; // pointer to the prescale-effect object + effect * post_effect; // pointer to the post-effect object + effect * pincushion_effect; // pointer to the pincushion-effect object + effect * focus_effect; // pointer to the focus-effect object + effect * phosphor_effect; // pointer to the phosphor-effect object + effect * deconverge_effect; // pointer to the deconvergence-effect object + effect * color_effect; // pointer to the color-effect object + effect * yiq_encode_effect; // pointer to the YIQ encoder effect object + effect * yiq_decode_effect; // pointer to the YIQ decoder effect object +#if (HLSL_VECTOR || CRT_BLOOM) + effect * bloom_effect; // pointer to the bloom composite effect + effect * downsample_effect; // pointer to the bloom downsample effect +#endif +#if (HLSL_VECTOR) + effect * vector_effect; // pointer to the vector-effect object +#endif + vertex * fsfx_vertices; // pointer to our full-screen-quad object + +public: + render_target * targethead; + cache_target * cachehead; + + static slider_desc s_sliders[]; + static hlsl_options s_hlsl_presets[4]; +}; + +}; + +#endif diff --git a/src/osd/windows/d3dintf.h b/src/osd/windows/d3dintf.h index 06e610f942d..8b72732d025 100644 --- a/src/osd/windows/d3dintf.h +++ b/src/osd/windows/d3dintf.h @@ -42,7 +42,6 @@ #ifndef __WIN_D3DINTF__ #define __WIN_D3DINTF__ -//#include "winmain.h" //============================================================ // CONSTANTS @@ -267,6 +266,7 @@ struct base int version; void * d3dobj; HINSTANCE dllhandle; + bool post_fx_available; // interface pointers interface d3d; @@ -282,7 +282,7 @@ struct base // PROTOTYPES //============================================================ -base *drawd3d9_init(); +base *drawd3d9_init(void); }; diff --git a/src/osd/windows/drawd3d.c b/src/osd/windows/drawd3d.c index 54331a8435d..fc0d418e18e 100644 --- a/src/osd/windows/drawd3d.c +++ b/src/osd/windows/drawd3d.c @@ -217,6 +217,7 @@ static void drawd3d_window_destroy(win_window_info *window); static render_primitive_list *drawd3d_window_get_primitives(win_window_info *window); static void drawd3d_window_save(win_window_info *window); static void drawd3d_window_record(win_window_info *window); +static void drawd3d_window_toggle_fsfx(win_window_info *window); static int drawd3d_window_draw(win_window_info *window, HDC dc, int update); @@ -250,12 +251,22 @@ static void drawd3d_exit(void) (*d3dintf->d3d.release)(d3dintf); } +static void drawd3d_window_toggle_fsfx(win_window_info *window) +{ + d3d::renderer *d3d = (d3d::renderer *)window->drawdata; + d3d->set_restarting(true); +} + static void drawd3d_window_record(win_window_info *window) { + d3d::renderer *d3d = (d3d::renderer *)window->drawdata; + d3d->get_shaders()->window_record(); } static void drawd3d_window_save(win_window_info *window) { + d3d::renderer *d3d = (d3d::renderer *)window->drawdata; + d3d->get_shaders()->window_save(); } @@ -272,6 +283,9 @@ static void drawd3d_window_destroy(win_window_info *window) if (d3d == NULL) return; + if (d3d->get_shaders()->recording()) + d3d->get_shaders()->window_record(); + // free the memory in the window global_free(d3d); window->drawdata = NULL; @@ -318,6 +332,7 @@ int drawd3d_init(running_machine &machine, win_draw_callbacks *callbacks) callbacks->window_draw = drawd3d_window_draw; callbacks->window_save = drawd3d_window_save; callbacks->window_record = drawd3d_window_record; + callbacks->window_toggle_fsfx = drawd3d_window_toggle_fsfx; callbacks->window_destroy = drawd3d_window_destroy; return 0; } @@ -354,6 +369,7 @@ void renderer::set_texture(texture_info *texture) m_last_texture = texture; m_last_texture_flags = (texture == NULL ? 0 : texture->get_flags()); HRESULT result = (*d3dintf->device.set_texture)(m_device, 0, (texture == NULL) ? get_default_texture()->get_finaltex() : texture->get_finaltex()); + m_shaders->set_texture(texture); if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result); } } @@ -615,7 +631,111 @@ texture_info *texture_manager::find_texinfo(const render_texinfo *texinfo, UINT3 texture->get_texinfo().height == texinfo->height && ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) { - return texture; + // Reject a texture if it belongs to an out-of-date render target, so as to cause the HLSL system to re-cache + if (m_renderer->get_shaders()->enabled() && texinfo->width != 0 && texinfo->height != 0 && (flags & PRIMFLAG_SCREENTEX_MASK) != 0) + { + if (m_renderer->get_shaders()->find_render_target(texture) != NULL) + { + return texture; + } + } + else + { + return texture; + } + } + } + + // Nothing found + /*int checkidx = 0; + for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next()) + { + printf("Checking texture index %d\n", checkidx); + UINT32 test_screen = (UINT32)texture->get_texinfo().osddata >> 1; + UINT32 test_page = (UINT32)texture->get_texinfo().osddata & 1; + UINT32 prim_screen = (UINT32)texinfo->osddata >> 1; + UINT32 prim_page = (UINT32)texinfo->osddata & 1; + if (test_screen != prim_screen || test_page != prim_page) + { + printf("No screen/page match: %d vs. %d, %d vs. %d\n", test_screen, prim_screen, test_page, prim_page); + continue; + } + + if (texture->get_hash() == hash && + texture->get_texinfo().base == texinfo->base && + texture->get_texinfo().width == texinfo->width && + texture->get_texinfo().height == texinfo->height && + ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) + { + // Reject a texture if it belongs to an out-of-date render target, so as to cause the HLSL system to re-cache + if (m_renderer->get_shaders()->enabled() && texinfo->width != 0 && texinfo->height != 0 && (flags & PRIMFLAG_SCREENTEX_MASK) != 0) + { + if (m_renderer->get_shaders()->find_render_target(texture) != NULL) + { + return texture; + } + } + else + { + return texture; + } + } + + if (texture->get_hash() != hash) + { + printf("No hash match: %d vs. %d\n", texture->get_hash(), hash); + } + if (texture->get_texinfo().base != texinfo->base) + { + printf("No base match\n"); + } + if (texture->get_texinfo().width != texinfo->width) + { + printf("No width match: %d vs. %d\n", texture->get_texinfo().width, texinfo->width); + } + if (texture->get_texinfo().height != texinfo->height) + { + printf("No height match: %d vs. %d\n", texture->get_texinfo().height, texinfo->height); + } + if (((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) != 0) + { + printf("No flag match: %08x & %08x = %08x\n", texture->get_flags(), flags, ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK))); + } + printf("\n"); + checkidx++; + } + + printf("\n\n\n\n");*/ + + // Nothing found, check if we need to unregister something with HLSL + if (m_renderer->get_shaders()->enabled()) + { + if (texinfo->width == 0 || texinfo->height == 0) + { + return NULL; + } + + UINT32 prim_screen = texinfo->osddata >> 1; + UINT32 prim_page = texinfo->osddata & 1; + + for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next()) + { + UINT32 test_screen = texture->get_texinfo().osddata >> 1; + UINT32 test_page = texture->get_texinfo().osddata & 1; + if (test_screen != prim_screen || test_page != prim_page) + { + continue; + } + + // Clear out our old texture reference + if (texture->get_hash() == hash && + texture->get_texinfo().base == texinfo->base && + ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0 && + (texture->get_texinfo().width != texinfo->width || + texture->get_texinfo().height != texinfo->height)) + { + m_renderer->get_shaders()->remove_render_target(texture); + } } } @@ -627,12 +747,14 @@ renderer::renderer(win_window_info *window) m_device = NULL; m_restarting = false; m_window = window; + m_shaders = NULL; m_numverts = 0; m_numpolys = 0; m_vertexbuf = NULL; m_lockedbuf = NULL; m_vectorbatch = NULL; m_last_texture = NULL; + m_hlsl_buf = NULL; m_texture_manager = NULL; } @@ -658,6 +780,8 @@ int renderer::pre_window_draw_check() // if we're restarting the renderer, leave things alone if (m_restarting) { + m_shaders->toggle(); + // free all existing resources and re-create device_delete_resources(); device_create_resources(); @@ -711,6 +835,13 @@ void texture_manager::update_textures() } } } + else if(m_renderer->get_shaders()->vector_enabled() && PRIMFLAG_GET_VECTORBUF(prim->flags)) + { + if (!m_renderer->get_shaders()->get_vector_target()) + { + m_renderer->get_shaders()->create_vector_target(prim); + } + } } } @@ -719,6 +850,8 @@ void renderer::begin_frame() HRESULT result = (*d3dintf->device.clear)(m_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); + m_shaders->begin_frame(); + m_window->primlist->acquire_lock(); // first update any textures @@ -731,6 +864,12 @@ mtlog_add("drawd3d_window_draw: begin_scene"); m_lockedbuf = NULL; + if(m_shaders->enabled()) + { + m_hlsl_buf = (void*)mesh_alloc(6); + m_shaders->init_fsfx_quad(m_hlsl_buf); + } + m_line_count = 0; // loop over primitives for (render_primitive *prim = m_window->primlist->first(); prim != NULL; prim = prim->next()) @@ -740,6 +879,11 @@ mtlog_add("drawd3d_window_draw: begin_scene"); void renderer::process_primitives() { + if (m_line_count && m_shaders->enabled() && d3dintf->post_fx_available) + { + batch_vectors(); + } + // Rotating index for vector time offsets for (render_primitive *prim = m_window->primlist->first(); prim != NULL; prim = prim->next()) { @@ -764,6 +908,11 @@ void renderer::process_primitives() throw emu_fatalerror("Unexpected render_primitive type"); } } + + if (m_line_count && !(m_shaders->enabled() && d3dintf->post_fx_available)) + { + batch_vectors(); + } } void renderer::end_frame() @@ -773,6 +922,8 @@ void renderer::end_frame() // flush any pending polygons primitive_flush_pending(); + m_shaders->end_frame(); + // finish the scene HRESULT result = (*d3dintf->device.end_scene)(m_device); if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result); @@ -902,6 +1053,10 @@ try_again: } } + int ret = m_shaders->create_resources(false); + if (ret != 0) + return ret; + return device_create_resources(); } @@ -917,7 +1072,7 @@ int renderer::device_create_resources() HRESULT result = (*d3dintf->device.create_vertex_buffer)(m_device, sizeof(vertex) * VERTEX_BUFFER_SIZE, D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, - VERTEX_BASE_FORMAT | D3DFVF_XYZRHW, + VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW), D3DPOOL_DEFAULT, &m_vertexbuf); if (result != D3D_OK) { @@ -926,7 +1081,8 @@ int renderer::device_create_resources() } // set the vertex format - result = (*d3dintf->device.set_vertex_format)(m_device, (D3DFORMAT)(VERTEX_BASE_FORMAT | D3DFVF_XYZRHW)); + result = (*d3dintf->device.set_vertex_format)(m_device, (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() && + d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW))); if (result != D3D_OK) { mame_printf_error("Error setting vertex format (%08X)", (UINT32)result); @@ -983,6 +1139,12 @@ renderer::~renderer() void renderer::device_delete() { + // free our effects + m_shaders->delete_resources(false); + + // delete the HLSL interface + global_free(m_shaders); + // free our base resources device_delete_resources(); @@ -1024,10 +1186,20 @@ int renderer::device_verify_caps() { int retval = 0; + m_shaders = global_alloc_clear(shaders); + m_shaders->init(d3dintf, m_window); + DWORD tempcaps; + HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_MAX_PS30_INSN_SLOTS, &tempcaps); + if (result != D3D_OK) mame_printf_verbose("Direct3D Error %08X during get_caps_dword call\n", (int)result); + if(tempcaps < 512) + { + mame_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n"); + d3dintf->post_fx_available = false; + } // verify presentation capabilities - HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_PRESENTATION_INTERVALS, &tempcaps); + result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_PRESENTATION_INTERVALS, &tempcaps); if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); if (!(tempcaps & D3DPRESENT_INTERVAL_IMMEDIATE)) { @@ -1094,6 +1266,7 @@ int renderer::device_test_cooperative() // free all existing resources and call reset on the device device_delete_resources(); + m_shaders->delete_resources(true); result = (*d3dintf->device.reset)(m_device, &m_presentation); // if it didn't work, punt to GDI @@ -1110,6 +1283,13 @@ int renderer::device_test_cooperative() device_delete(); return 1; } + + if (m_shaders->create_resources(true)) + { + mame_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n"); + device_delete(); + return 1; + } } return 0; } @@ -1364,9 +1544,9 @@ void renderer::batch_vectors() m_vectorbatch = mesh_alloc(m_line_count * vector_size); m_batchindex = 0; - //static int start_index = 0; - //int line_index = 0; - //float period = options.screen_vector_time_period(); + static int start_index = 0; + int line_index = 0; + float period = options.screen_vector_time_period(); UINT32 cached_flags = 0; for (render_primitive *prim = m_window->primlist->first(); prim != NULL; prim = prim->next()) { @@ -1375,14 +1555,14 @@ void renderer::batch_vectors() case render_primitive::LINE: if (PRIMFLAG_GET_VECTOR(prim->flags)) { - /*if (period == 0.0f || m_line_count == 0) + if (period == 0.0f || m_line_count == 0) { batch_vector(prim, 1.0f); } - else*/ + else { - batch_vector(prim, 1.0f);//(float)(start_index + line_index) / ((float)m_line_count * period)); - //line_index++; + batch_vector(prim, (float)(start_index + line_index) / ((float)m_line_count * period)); + line_index++; } cached_flags = prim->flags; } @@ -1399,11 +1579,11 @@ void renderer::batch_vectors() m_texture_manager->get_vector_texture(), D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f); m_numpolys++; - //start_index += (int)((float)line_index * period); - //if (m_line_count > 0) - //{ - // start_index %= m_line_count; - //} + start_index += (int)((float)line_index * period); + if (m_line_count > 0) + { + start_index %= m_line_count; + } } void renderer::batch_vector(const render_primitive *prim, float line_time) @@ -1699,7 +1879,14 @@ vertex *renderer::mesh_alloc(int numverts) // if we're going to overflow, flush if (m_lockedbuf != NULL && m_numverts + numverts >= VERTEX_BUFFER_SIZE) { + printf("request for %d verts\n", numverts); primitive_flush_pending(); + + if(m_shaders->enabled()) + { + m_hlsl_buf = (void*)mesh_alloc(6); + m_shaders->init_fsfx_quad(m_hlsl_buf); + } } // if we don't have a lock, grab it now @@ -1743,7 +1930,13 @@ void renderer::primitive_flush_pending() result = (*d3dintf->device.set_stream_source)(m_device, 0, m_vertexbuf, sizeof(vertex)); if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result); + m_shaders->begin_draw(); + int vertnum = 0; + if (m_shaders->enabled()) + { + vertnum = 6; + } // now do the polys for (int polynum = 0; polynum < m_numpolys; polynum++) @@ -1764,6 +1957,8 @@ void renderer::primitive_flush_pending() set_filter(newfilter); set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); set_modmode(m_poly[polynum].get_modmode()); + + m_shaders->init_effect_info(&m_poly[polynum]); } // set the blendmode if different @@ -1777,14 +1972,23 @@ void renderer::primitive_flush_pending() assert(vertnum + m_poly[polynum].get_vertcount() <= m_numverts); - // add the primitives - result = (*d3dintf->device.draw_primitive)(m_device, m_poly[polynum].get_type(), vertnum, - m_poly[polynum].get_count()); - if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + if(m_shaders->enabled() && d3dintf->post_fx_available) + { + m_shaders->render_quad(&m_poly[polynum], vertnum); + } + else + { + // add the primitives + result = (*d3dintf->device.draw_primitive)(m_device, m_poly[polynum].get_type(), vertnum, + m_poly[polynum].get_count()); + if (result != D3D_OK) mame_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); + } vertnum += m_poly[polynum].get_vertcount(); } + m_shaders->end_draw(); + // reset the vertex count m_numverts = 0; m_numpolys = 0; @@ -1913,6 +2117,12 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso { m_d3dfinaltex = m_d3dtex; m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; + + if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this)) + { + goto error; + } + break; } } @@ -1952,6 +2162,10 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex); if (result == D3D_OK) { + if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_prescaled_texture(this)) + { + goto error; + } break; } (*d3dintf->texture.release)(m_d3dtex); @@ -1973,6 +2187,7 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso return; error: + d3dintf->post_fx_available = false; printf("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n"); if (m_d3dsurface != NULL) (*d3dintf->surface.release)(m_d3dsurface); diff --git a/src/osd/windows/drawd3d.h b/src/osd/windows/drawd3d.h index 19c4366230d..7fc10b3d740 100644 --- a/src/osd/windows/drawd3d.h +++ b/src/osd/windows/drawd3d.h @@ -43,6 +43,9 @@ #define __WIN_DRAWD3D__ +#include "d3dhlsl.h" + + //============================================================ // CONSTANTS //============================================================ @@ -198,6 +201,8 @@ public: texture_info * get_default_texture() { return m_texture_manager->get_default_texture(); } texture_info * get_vector_texture() { return m_texture_manager->get_vector_texture(); } + shaders * get_shaders() { return m_shaders; } + private: int m_adapter; // ordinal adapter number int m_width; // current width @@ -239,6 +244,9 @@ private: D3DTEXTUREADDRESS m_last_wrap; // previous wrap state DWORD m_last_modmode; // previous texture modulation + void * m_hlsl_buf; // HLSL vertex data + shaders * m_shaders; // HLSL interface + texture_manager * m_texture_manager; // texture manager int m_line_count; diff --git a/src/osd/windows/drawdd.c b/src/osd/windows/drawdd.c index 896255004cf..5157fe271d5 100644 --- a/src/osd/windows/drawdd.c +++ b/src/osd/windows/drawdd.c @@ -223,6 +223,7 @@ int drawdd_init(running_machine &machine, win_draw_callbacks *callbacks) callbacks->window_draw = drawdd_window_draw; callbacks->window_save = NULL; callbacks->window_record = NULL; + callbacks->window_toggle_fsfx = NULL; callbacks->window_destroy = drawdd_window_destroy; mame_printf_verbose("DirectDraw: Using DirectDraw 7\n"); diff --git a/src/osd/windows/drawgdi.c b/src/osd/windows/drawgdi.c index 52d3b629f81..0a8d3c54fd5 100644 --- a/src/osd/windows/drawgdi.c +++ b/src/osd/windows/drawgdi.c @@ -93,6 +93,7 @@ int drawgdi_init(running_machine &machine, win_draw_callbacks *callbacks) callbacks->window_draw = drawgdi_window_draw; callbacks->window_save = NULL; callbacks->window_record = NULL; + callbacks->window_toggle_fsfx = NULL; callbacks->window_destroy = drawgdi_window_destroy; return 0; } diff --git a/src/osd/windows/drawnone.c b/src/osd/windows/drawnone.c index c82740f84ac..a87ef14f823 100644 --- a/src/osd/windows/drawnone.c +++ b/src/osd/windows/drawnone.c @@ -77,6 +77,7 @@ int drawnone_init(running_machine &machine, win_draw_callbacks *callbacks) callbacks->window_draw = drawnone_window_draw; callbacks->window_save = NULL; callbacks->window_record = NULL; + callbacks->window_toggle_fsfx = NULL; callbacks->window_destroy = drawnone_window_destroy; return 0; } diff --git a/src/osd/windows/input.c b/src/osd/windows/input.c index 17afb7727ce..2f556082123 100644 --- a/src/osd/windows/input.c +++ b/src/osd/windows/input.c @@ -776,6 +776,24 @@ void windows_osd_interface::customize_input_type_list(simple_listdefseq(SEQ_TYPE_STANDARD).set(KEYCODE_LALT, KEYCODE_ENTER); break; + // alt-F12 for fullscreen snap + case IPT_OSD_2: + entry->configure_osd("RENDER_SNAP", "Take Rendered Snapshot"); + entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_LALT, KEYCODE_F12, input_seq::not_code, KEYCODE_LCONTROL); + break; + + // alt-F11 for fullscreen video + case IPT_OSD_3: + entry->configure_osd("RENDER_AVI", "Record Rendered Video"); + entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_LALT, KEYCODE_F11); + break; + + // ctrl-alt-F12 to toggle post-processing + case IPT_OSD_4: + entry->configure_osd("POST_PROCESS", "Toggle Post-Processing"); + entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_LALT, KEYCODE_LCONTROL, KEYCODE_F5); + break; + // leave everything else alone default: break; diff --git a/src/osd/windows/video.c b/src/osd/windows/video.c index c8d5d1e4a7c..e7eaffa9372 100644 --- a/src/osd/windows/video.c +++ b/src/osd/windows/video.c @@ -366,6 +366,18 @@ static void check_osd_inputs(running_machine &machine) // check for toggling fullscreen mode if (ui_input_pressed(machine, IPT_OSD_1)) winwindow_toggle_full_screen(); + + // check for taking fullscreen snap + if (ui_input_pressed(machine, IPT_OSD_2)) + winwindow_take_snap(); + + // check for taking fullscreen video + if (ui_input_pressed(machine, IPT_OSD_3)) + winwindow_take_video(); + + // check for taking fullscreen video + if (ui_input_pressed(machine, IPT_OSD_4)) + winwindow_toggle_fsfx(); } diff --git a/src/osd/windows/windows.mak b/src/osd/windows/windows.mak index 6e341145645..59a057ac428 100644 --- a/src/osd/windows/windows.mak +++ b/src/osd/windows/windows.mak @@ -306,6 +306,7 @@ OSDCOREOBJS = \ OSDOBJS = \ $(WINOBJ)/d3d9intf.o \ $(WINOBJ)/drawd3d.o \ + $(WINOBJ)/d3dhlsl.o \ $(WINOBJ)/drawdd.o \ $(WINOBJ)/drawgdi.o \ $(WINOBJ)/drawnone.o \ diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index 14d15f99739..6fb390890b0 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -331,6 +331,85 @@ const options_entry windows_options::s_option_entries[] = { NULL, NULL, OPTION_HEADER, "DIRECT3D-SPECIFIC OPTIONS" }, { WINOPTION_FILTER ";d3dfilter;flt", "1", OPTION_BOOLEAN, "enable bilinear filtering on screen output" }, + // post-processing options + { NULL, NULL, OPTION_HEADER, "DIRECT3D POST-PROCESSING OPTIONS" }, + { WINOPTION_HLSL_ENABLE";hlsl", "0", OPTION_BOOLEAN, "enable HLSL post-processing (PS3.0 required)" }, + { WINOPTION_HLSLPATH, "hlsl", OPTION_STRING, "path to hlsl files" }, + { WINOPTION_HLSL_INI_READ, "0", OPTION_BOOLEAN, "enable HLSL INI reading" }, + { WINOPTION_HLSL_INI_WRITE, "0", OPTION_BOOLEAN, "enable HLSL INI writing" }, + { WINOPTION_HLSL_INI_NAME, "%g", OPTION_STRING, "HLSL INI file name for this game" }, + { WINOPTION_HLSL_PRESCALE_X, "0", OPTION_INTEGER, "HLSL pre-scale override factor for X (0 for auto)" }, + { WINOPTION_HLSL_PRESCALE_Y, "0", OPTION_INTEGER, "HLSL pre-scale override factor for Y (0 for auto)" }, + { WINOPTION_HLSL_PRESET";(-1-3)", "-1", OPTION_INTEGER, "HLSL preset to use (0-3)" }, + { WINOPTION_HLSL_WRITE, NULL, OPTION_STRING, "enable HLSL AVI writing (huge disk bandwidth suggested)" }, + { WINOPTION_HLSL_SNAP_WIDTH, "2048", OPTION_STRING, "HLSL upscaled-snapshot width" }, + { WINOPTION_HLSL_SNAP_HEIGHT, "1536", OPTION_STRING, "HLSL upscaled-snapshot height" }, + { WINOPTION_SHADOW_MASK_ALPHA";fs_shadwa(0.0-1.0)", "0.0", OPTION_FLOAT, "shadow mask alpha-blend value (1.0 is fully blended, 0.0 is no mask)" }, + { WINOPTION_SHADOW_MASK_TEXTURE";fs_shadwt(0.0-1.0)", "aperture.png", OPTION_STRING, "shadow mask texture name" }, + { WINOPTION_SHADOW_MASK_COUNT_X";fs_shadww", "320", OPTION_INTEGER, "shadow mask width, in phosphor dots" }, + { WINOPTION_SHADOW_MASK_COUNT_Y";fs_shadwh", "240", OPTION_INTEGER, "shadow mask height, in phosphor dots" }, + { WINOPTION_SHADOW_MASK_USIZE";fs_shadwu(0.0-1.0)", "0.09375", OPTION_FLOAT, "shadow mask texture size in U direction" }, + { WINOPTION_SHADOW_MASK_VSIZE";fs_shadwv(0.0-1.0)", "0.109375", OPTION_FLOAT, "shadow mask texture size in V direction" }, + { WINOPTION_CURVATURE";fs_curv(0.0-4.0)", "0.03", OPTION_FLOAT, "screen curvature amount" }, + /* Beam-related values below this line*/ + { WINOPTION_PINCUSHION";fs_pin(0.0-4.0)", "0.03", OPTION_FLOAT, "pincushion amount" }, + { WINOPTION_SCANLINE_AMOUNT";fs_scanam(0.0-4.0)", "1.0", OPTION_FLOAT, "overall alpha scaling value for scanlines" }, + { WINOPTION_SCANLINE_SCALE";fs_scansc(0.0-4.0)", "1.0", OPTION_FLOAT, "overall height scaling value for scanlines" }, + { WINOPTION_SCANLINE_HEIGHT";fs_scanh(0.0-4.0)", "1.0", OPTION_FLOAT, "individual height scaling value for scanlines" }, + { WINOPTION_SCANLINE_BRIGHT_SCALE";fs_scanbs(0.0-2.0)", "1.0", OPTION_FLOAT, "overall brightness scaling value for scanlines (multiplicative)" }, + { WINOPTION_SCANLINE_BRIGHT_OFFSET";fs_scanbo(0.0-1.0)", "0.0", OPTION_FLOAT, "overall brightness offset value for scanlines (additive)" }, + { WINOPTION_SCANLINE_OFFSET";fs_scanjt(0.0-4.0)", "0.0", OPTION_FLOAT, "overall interlace jitter scaling value for scanlines" }, + { WINOPTION_DEFOCUS";fs_focus", "0.0,0.0", OPTION_STRING, "overall defocus value in screen-relative coords" }, + { WINOPTION_CONVERGE_X";fs_convx", "0.3,0.0,-0.3",OPTION_STRING, "convergence in screen-relative X direction" }, + { WINOPTION_CONVERGE_Y";fs_convy", "0.0,0.3,-0.3",OPTION_STRING, "convergence in screen-relative Y direction" }, + { WINOPTION_RADIAL_CONVERGE_X";fs_rconvx", "0.0,0.0,0.0",OPTION_STRING, "radial convergence in screen-relative X direction" }, + { WINOPTION_RADIAL_CONVERGE_Y";fs_rconvy", "0.0,0.0,0.0",OPTION_STRING, "radial convergence in screen-relative Y direction" }, + /* RGB colorspace convolution below this line */ + { WINOPTION_RED_RATIO";fs_redratio", "1.0,0.0,0.0",OPTION_STRING, "red output signal generated by input signal" }, + { WINOPTION_GRN_RATIO";fs_grnratio", "0.0,1.0,0.0",OPTION_STRING, "green output signal generated by input signal" }, + { WINOPTION_BLU_RATIO";fs_bluratio", "0.0,0.0,1.0",OPTION_STRING, "blue output signal generated by input signal" }, + { WINOPTION_SATURATION";fs_sat(0.0-4.0)", "1.4", OPTION_FLOAT, "saturation scaling value" }, + { WINOPTION_OFFSET";fs_offset", "0.0,0.0,0.0",OPTION_STRING, "signal offset value (additive)" }, + { WINOPTION_SCALE";fs_scale", "0.95,0.95,0.95",OPTION_STRING, "signal scaling value (multiplicative)" }, + { WINOPTION_POWER";fs_power", "0.8,0.8,0.8",OPTION_STRING, "signal power value (exponential)" }, + { WINOPTION_FLOOR";fs_floor", "0.05,0.05,0.05",OPTION_STRING, "signal floor level" }, + { WINOPTION_PHOSPHOR";fs_phosphor", "0.4,0.4,0.4",OPTION_STRING, "phosphorescence decay rate (0.0 is instant, 1.0 is forever)" }, + /* NTSC simulation below this line */ + { NULL, NULL, OPTION_HEADER, "NTSC POST-PROCESSING OPTIONS" }, + { WINOPTION_YIQ_ENABLE";yiq", "0", OPTION_BOOLEAN, "enable YIQ-space HLSL post-processing" }, + { WINOPTION_YIQ_CCVALUE";yiqcc", "3.59754545",OPTION_FLOAT, "Color Carrier frequency for NTSC signal processing" }, + { WINOPTION_YIQ_AVALUE";yiqa", "0.5", OPTION_FLOAT, "A value for NTSC signal processing" }, + { WINOPTION_YIQ_BVALUE";yiqb", "0.5", OPTION_FLOAT, "B value for NTSC signal processing" }, + { WINOPTION_YIQ_OVALUE";yiqo", "0.0", OPTION_FLOAT, "Outgoing Color Carrier phase offset for NTSC signal processing" }, + { WINOPTION_YIQ_PVALUE";yiqp", "1.0", OPTION_FLOAT, "Incoming Pixel Clock scaling value for NTSC signal processing" }, + { WINOPTION_YIQ_NVALUE";yiqn", "1.0", OPTION_FLOAT, "Y filter notch width for NTSC signal processing" }, + { WINOPTION_YIQ_YVALUE";yiqy", "6.0", OPTION_FLOAT, "Y filter cutoff frequency for NTSC signal processing" }, + { WINOPTION_YIQ_IVALUE";yiqi", "1.2", OPTION_FLOAT, "I filter cutoff frequency for NTSC signal processing" }, + { WINOPTION_YIQ_QVALUE";yiqq", "0.6", OPTION_FLOAT, "Q filter cutoff frequency for NTSC signal processing" }, + { WINOPTION_YIQ_SCAN_TIME";yiqsc", "52.6", OPTION_FLOAT, "Horizontal scanline duration for NTSC signal processing (in usec)" }, + { WINOPTION_YIQ_PHASE_COUNT";yiqp", "2", OPTION_INTEGER, "Phase Count value for NTSC signal processing" }, + { WINOPTION_YIQ_SCAN_TIME";yiqsc", "52.6", OPTION_FLOAT, "Horizontal scanline duration for NTSC signal processing (in usec)" }, + { WINOPTION_YIQ_PHASE_COUNT";yiqp", "2", OPTION_INTEGER, "Phase Count value for NTSC signal processing" }, + /* Vector simulation below this line */ + { NULL, NULL, OPTION_HEADER, "VECTOR POST-PROCESSING OPTIONS" }, + { WINOPTION_VECTOR_LENGTH_SCALE";veclength", "0.8", OPTION_FLOAT, "How much length affects vector fade" }, + { WINOPTION_VECTOR_LENGTH_RATIO";vecsize", "500.0", OPTION_FLOAT, "Vector fade length (4.0 - vectors fade the most at and above 4 pixels, etc.)" }, + /* Bloom below this line */ + { NULL, NULL, OPTION_HEADER, "BLOOM POST-PROCESSING OPTIONS" }, + { WINOPTION_VECTOR_BLOOM_SCALE, "0.3", OPTION_FLOAT, "Intensity factor for vector bloom" }, + { WINOPTION_RASTER_BLOOM_SCALE, "0.225", OPTION_FLOAT, "Intensity factor for raster bloom" }, + { WINOPTION_BLOOM_LEVEL0_WEIGHT, "1.0", OPTION_FLOAT, "Bloom level 0 (full-size target) weight" }, + { WINOPTION_BLOOM_LEVEL1_WEIGHT, "0.21", OPTION_FLOAT, "Bloom level 1 (half-size target) weight" }, + { WINOPTION_BLOOM_LEVEL2_WEIGHT, "0.19", OPTION_FLOAT, "Bloom level 2 (quarter-size target) weight" }, + { WINOPTION_BLOOM_LEVEL3_WEIGHT, "0.17", OPTION_FLOAT, "Bloom level 3 (.) weight" }, + { WINOPTION_BLOOM_LEVEL4_WEIGHT, "0.15", OPTION_FLOAT, "Bloom level 4 (.) weight" }, + { WINOPTION_BLOOM_LEVEL5_WEIGHT, "0.14", OPTION_FLOAT, "Bloom level 5 (.) weight" }, + { WINOPTION_BLOOM_LEVEL6_WEIGHT, "0.13", OPTION_FLOAT, "Bloom level 6 (.) weight" }, + { WINOPTION_BLOOM_LEVEL7_WEIGHT, "0.12", OPTION_FLOAT, "Bloom level 7 (.) weight" }, + { WINOPTION_BLOOM_LEVEL8_WEIGHT, "0.11", OPTION_FLOAT, "Bloom level 8 (.) weight" }, + { WINOPTION_BLOOM_LEVEL9_WEIGHT, "0.10", OPTION_FLOAT, "Bloom level 9 (.) weight" }, + { WINOPTION_BLOOM_LEVEL10_WEIGHT, "0.09", OPTION_FLOAT, "Bloom level 10 (1x1 target) weight" }, + // per-window options { NULL, NULL, OPTION_HEADER, "PER-WINDOW VIDEO OPTIONS" }, { WINOPTION_SCREEN, "auto", OPTION_STRING, "explicit name of all screens; 'auto' here will try to make a best guess" }, diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 656a568a915..b591529b702 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -77,6 +77,74 @@ // Direct3D-specific options #define WINOPTION_FILTER "filter" +// core post-processing options +#define WINOPTION_HLSL_ENABLE "hlsl_enable" +#define WINOPTION_HLSLPATH "hlslpath" +#define WINOPTION_HLSL_INI_NAME "hlslini" +#define WINOPTION_HLSL_INI_WRITE "hlsl_ini_write" +#define WINOPTION_HLSL_INI_READ "hlsl_ini_read" +#define WINOPTION_HLSL_PRESCALE_X "hlsl_prescale_x" +#define WINOPTION_HLSL_PRESCALE_Y "hlsl_prescale_y" +#define WINOPTION_HLSL_PRESET "hlsl_preset" +#define WINOPTION_HLSL_WRITE "hlsl_write" +#define WINOPTION_HLSL_SNAP_WIDTH "hlsl_snap_width" +#define WINOPTION_HLSL_SNAP_HEIGHT "hlsl_snap_height" +#define WINOPTION_SHADOW_MASK_ALPHA "shadow_mask_alpha" +#define WINOPTION_SHADOW_MASK_TEXTURE "shadow_mask_texture" +#define WINOPTION_SHADOW_MASK_COUNT_X "shadow_mask_x_count" +#define WINOPTION_SHADOW_MASK_COUNT_Y "shadow_mask_y_count" +#define WINOPTION_SHADOW_MASK_USIZE "shadow_mask_usize" +#define WINOPTION_SHADOW_MASK_VSIZE "shadow_mask_vsize" +#define WINOPTION_PINCUSHION "pincushion" +#define WINOPTION_CURVATURE "curvature" +#define WINOPTION_SCANLINE_AMOUNT "scanline_alpha" +#define WINOPTION_SCANLINE_SCALE "scanline_size" +#define WINOPTION_SCANLINE_HEIGHT "scanline_height" +#define WINOPTION_SCANLINE_BRIGHT_SCALE "scanline_bright_scale" +#define WINOPTION_SCANLINE_BRIGHT_OFFSET "scanline_bright_offset" +#define WINOPTION_SCANLINE_OFFSET "scanline_jitter" +#define WINOPTION_DEFOCUS "defocus" +#define WINOPTION_CONVERGE_X "converge_x" +#define WINOPTION_CONVERGE_Y "converge_y" +#define WINOPTION_RADIAL_CONVERGE_X "radial_converge_x" +#define WINOPTION_RADIAL_CONVERGE_Y "radial_converge_y" +#define WINOPTION_RED_RATIO "red_ratio" +#define WINOPTION_GRN_RATIO "grn_ratio" +#define WINOPTION_BLU_RATIO "blu_ratio" +#define WINOPTION_OFFSET "offset" +#define WINOPTION_SCALE "scale" +#define WINOPTION_POWER "power" +#define WINOPTION_FLOOR "floor" +#define WINOPTION_PHOSPHOR "phosphor_life" +#define WINOPTION_SATURATION "saturation" +#define WINOPTION_YIQ_ENABLE "yiq_enable" +#define WINOPTION_YIQ_CCVALUE "yiq_cc" +#define WINOPTION_YIQ_AVALUE "yiq_a" +#define WINOPTION_YIQ_BVALUE "yiq_b" +#define WINOPTION_YIQ_OVALUE "yiq_o" +#define WINOPTION_YIQ_PVALUE "yiq_p" +#define WINOPTION_YIQ_NVALUE "yiq_n" +#define WINOPTION_YIQ_YVALUE "yiq_y" +#define WINOPTION_YIQ_IVALUE "yiq_i" +#define WINOPTION_YIQ_QVALUE "yiq_q" +#define WINOPTION_YIQ_SCAN_TIME "yiq_scan_time" +#define WINOPTION_YIQ_PHASE_COUNT "yiq_phase_count" +#define WINOPTION_VECTOR_LENGTH_SCALE "vector_length_scale" +#define WINOPTION_VECTOR_LENGTH_RATIO "vector_length_ratio" +#define WINOPTION_VECTOR_BLOOM_SCALE "vector_bloom_scale" +#define WINOPTION_RASTER_BLOOM_SCALE "raster_bloom_scale" +#define WINOPTION_BLOOM_LEVEL0_WEIGHT "bloom_lvl0_weight" +#define WINOPTION_BLOOM_LEVEL1_WEIGHT "bloom_lvl1_weight" +#define WINOPTION_BLOOM_LEVEL2_WEIGHT "bloom_lvl2_weight" +#define WINOPTION_BLOOM_LEVEL3_WEIGHT "bloom_lvl3_weight" +#define WINOPTION_BLOOM_LEVEL4_WEIGHT "bloom_lvl4_weight" +#define WINOPTION_BLOOM_LEVEL5_WEIGHT "bloom_lvl5_weight" +#define WINOPTION_BLOOM_LEVEL6_WEIGHT "bloom_lvl6_weight" +#define WINOPTION_BLOOM_LEVEL7_WEIGHT "bloom_lvl7_weight" +#define WINOPTION_BLOOM_LEVEL8_WEIGHT "bloom_lvl8_weight" +#define WINOPTION_BLOOM_LEVEL9_WEIGHT "bloom_lvl9_weight" +#define WINOPTION_BLOOM_LEVEL10_WEIGHT "bloom_lvl10_weight" + // per-window options #define WINOPTION_SCREEN "screen" #define WINOPTION_ASPECT "aspect" @@ -138,6 +206,74 @@ public: // Direct3D-specific options bool filter() const { return bool_value(WINOPTION_FILTER); } + // core post-processing options + const char *screen_post_fx_dir() const { return value(WINOPTION_HLSLPATH); } + const char *hlsl_ini_name() const { return value(WINOPTION_HLSL_INI_NAME); } + bool d3d_hlsl_enable() const { return bool_value(WINOPTION_HLSL_ENABLE); } + bool hlsl_write_ini() const { return bool_value(WINOPTION_HLSL_INI_WRITE); } + bool hlsl_read_ini() const { return bool_value(WINOPTION_HLSL_INI_READ); } + const char *d3d_hlsl_write() const { return value(WINOPTION_HLSL_WRITE); } + int d3d_hlsl_prescale_x() const { return int_value(WINOPTION_HLSL_PRESCALE_X); } + int d3d_hlsl_prescale_y() const { return int_value(WINOPTION_HLSL_PRESCALE_Y); } + int d3d_hlsl_preset() const { return int_value(WINOPTION_HLSL_PRESET); } + int d3d_snap_width() const { return int_value(WINOPTION_HLSL_SNAP_WIDTH); } + int d3d_snap_height() const { return int_value(WINOPTION_HLSL_SNAP_HEIGHT); } + float screen_shadow_mask_alpha() const { return float_value(WINOPTION_SHADOW_MASK_ALPHA); } + const char *screen_shadow_mask_texture() const { return value(WINOPTION_SHADOW_MASK_TEXTURE); } + int screen_shadow_mask_count_x() const { return int_value(WINOPTION_SHADOW_MASK_COUNT_X); } + int screen_shadow_mask_count_y() const { return int_value(WINOPTION_SHADOW_MASK_COUNT_Y); } + float screen_shadow_mask_u_size() const { return float_value(WINOPTION_SHADOW_MASK_USIZE); } + float screen_shadow_mask_v_size() const { return float_value(WINOPTION_SHADOW_MASK_VSIZE); } + float screen_scanline_amount() const { return float_value(WINOPTION_SCANLINE_AMOUNT); } + float screen_scanline_scale() const { return float_value(WINOPTION_SCANLINE_SCALE); } + float screen_scanline_height() const { return float_value(WINOPTION_SCANLINE_HEIGHT); } + float screen_scanline_bright_scale() const { return float_value(WINOPTION_SCANLINE_BRIGHT_SCALE); } + float screen_scanline_bright_offset() const { return float_value(WINOPTION_SCANLINE_BRIGHT_OFFSET); } + float screen_scanline_offset() const { return float_value(WINOPTION_SCANLINE_OFFSET); } + float screen_pincushion() const { return float_value(WINOPTION_PINCUSHION); } + float screen_curvature() const { return float_value(WINOPTION_CURVATURE); } + const char *screen_defocus() const { return value(WINOPTION_DEFOCUS); } + const char *screen_converge_x() const { return value(WINOPTION_CONVERGE_X); } + const char *screen_converge_y() const { return value(WINOPTION_CONVERGE_Y); } + const char *screen_radial_converge_x() const { return value(WINOPTION_RADIAL_CONVERGE_X); } + const char *screen_radial_converge_y() const { return value(WINOPTION_RADIAL_CONVERGE_Y); } + const char *screen_red_ratio() const { return value(WINOPTION_RED_RATIO); } + const char *screen_grn_ratio() const { return value(WINOPTION_GRN_RATIO); } + const char *screen_blu_ratio() const { return value(WINOPTION_BLU_RATIO); } + bool screen_yiq_enable() const { return bool_value(WINOPTION_YIQ_ENABLE); } + float screen_yiq_cc() const { return float_value(WINOPTION_YIQ_CCVALUE); } + float screen_yiq_a() const { return float_value(WINOPTION_YIQ_AVALUE); } + float screen_yiq_b() const { return float_value(WINOPTION_YIQ_BVALUE); } + float screen_yiq_o() const { return float_value(WINOPTION_YIQ_OVALUE); } + float screen_yiq_p() const { return float_value(WINOPTION_YIQ_PVALUE); } + float screen_yiq_n() const { return float_value(WINOPTION_YIQ_NVALUE); } + float screen_yiq_y() const { return float_value(WINOPTION_YIQ_YVALUE); } + float screen_yiq_i() const { return float_value(WINOPTION_YIQ_IVALUE); } + float screen_yiq_q() const { return float_value(WINOPTION_YIQ_QVALUE); } + float screen_yiq_scan_time() const { return float_value(WINOPTION_YIQ_SCAN_TIME); } + int screen_yiq_phase_count() const { return int_value(WINOPTION_YIQ_PHASE_COUNT); } + float screen_vector_length_scale() const { return float_value(WINOPTION_VECTOR_LENGTH_SCALE); } + float screen_vector_length_ratio() const { return float_value(WINOPTION_VECTOR_LENGTH_RATIO); } + float screen_vector_bloom_scale() const { return float_value(WINOPTION_VECTOR_BLOOM_SCALE); } + float screen_raster_bloom_scale() const { return float_value(WINOPTION_RASTER_BLOOM_SCALE); } + float screen_bloom_lvl0_weight() const { return float_value(WINOPTION_BLOOM_LEVEL0_WEIGHT); } + float screen_bloom_lvl1_weight() const { return float_value(WINOPTION_BLOOM_LEVEL1_WEIGHT); } + float screen_bloom_lvl2_weight() const { return float_value(WINOPTION_BLOOM_LEVEL2_WEIGHT); } + float screen_bloom_lvl3_weight() const { return float_value(WINOPTION_BLOOM_LEVEL3_WEIGHT); } + float screen_bloom_lvl4_weight() const { return float_value(WINOPTION_BLOOM_LEVEL4_WEIGHT); } + float screen_bloom_lvl5_weight() const { return float_value(WINOPTION_BLOOM_LEVEL5_WEIGHT); } + float screen_bloom_lvl6_weight() const { return float_value(WINOPTION_BLOOM_LEVEL6_WEIGHT); } + float screen_bloom_lvl7_weight() const { return float_value(WINOPTION_BLOOM_LEVEL7_WEIGHT); } + float screen_bloom_lvl8_weight() const { return float_value(WINOPTION_BLOOM_LEVEL8_WEIGHT); } + float screen_bloom_lvl9_weight() const { return float_value(WINOPTION_BLOOM_LEVEL9_WEIGHT); } + float screen_bloom_lvl10_weight() const { return float_value(WINOPTION_BLOOM_LEVEL10_WEIGHT); } + const char *screen_offset() const { return value(WINOPTION_OFFSET); } + const char *screen_scale() const { return value(WINOPTION_SCALE); } + const char *screen_power() const { return value(WINOPTION_POWER); } + const char *screen_floor() const { return value(WINOPTION_FLOOR); } + const char *screen_phosphor() const { return value(WINOPTION_PHOSPHOR); } + float screen_saturation() const { return float_value(WINOPTION_SATURATION); } + // per-window options const char *screen() const { return value(WINOPTION_SCREEN); } const char *aspect() const { return value(WINOPTION_ASPECT); } @@ -202,6 +338,9 @@ public: virtual void update_audio_stream(const INT16 *buffer, int samples_this_frame); virtual void set_mastervolume(int attenuation); + // video overridables + virtual void *get_slider_list(); + // input overridables virtual void customize_input_type_list(simple_list &typelist); @@ -210,12 +349,7 @@ public: virtual void font_close(osd_font font); virtual bool font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs); - virtual void set_shader_system(void *shader_system) { m_shader_system = shader_system; } - virtual void *shader_system() { return m_shader_system; } - private: - void * m_shader_system; - static void osd_exit(running_machine &machine); static const int DEFAULT_FONT_HEIGHT = 200;