diff --git a/Makefile.common b/Makefile.common index 4474c5fa0c..c3bbf0ebbb 100644 --- a/Makefile.common +++ b/Makefile.common @@ -465,8 +465,9 @@ ifeq ($(HAVE_OPENGL), 1) ifeq ($(OSX), 1) LIBS += -framework OpenGL else ifneq ($(findstring Win32,$(OS)),) - LIBS += -lopengl32 -lgdi32 -lcomdlg32 + LIBS += -lopengl32 -lgdi32 -lcomdlg32 -lcomctl32 OBJ += gfx/drivers_context/wgl_ctx.o + OBJ += gfx/drivers_context/wgl_shader_dlg.o else LIBS += -lGL endif diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index c380714786..6071b094e5 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -54,6 +54,7 @@ #if defined(_WIN32) && !defined(_XBOX) #include "../drivers_context/win32_dwm_common.h" +#include "../drivers_context/wgl_shader_dlg.h" #endif #include "../video_shader_driver.h" @@ -2651,6 +2652,9 @@ static bool gl_set_shader(void *data, gl_set_shader_viewport(gl, 0); gl_set_shader_viewport(gl, 1); context_bind_hw_render(gl, true); +#if defined(_WIN32) && !defined(_XBOX) + shader_dlg_params_reload(); +#endif return true; #else return false; diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index 32ca4c2c76..eb946be718 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -27,6 +27,7 @@ #include "../gl_common.h" #include "../video_monitor.h" #include "win32_common.h" +#include "wgl_shader_dlg.h" #include #include #include @@ -316,7 +317,7 @@ static void gfx_ctx_wgl_check_window(void *data, bool *quit, (void)data; (void)frame_count; - while (PeekMessage(&msg, g_hwnd, 0, 0, PM_REMOVE)) + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -418,6 +419,9 @@ static bool gfx_ctx_wgl_init(void *data) if (!RegisterClassEx(&wndclass)) return false; + if (!wgl_shader_dlg_init()) + RARCH_ERR("[WGL]: wgl_shader_dlg_init() failed.\n"); + return true; } diff --git a/gfx/drivers_context/wgl_shader_dlg.c b/gfx/drivers_context/wgl_shader_dlg.c new file mode 100644 index 0000000000..96118ef4cf --- /dev/null +++ b/gfx/drivers_context/wgl_shader_dlg.c @@ -0,0 +1,391 @@ +#ifdef _MSC_VER +#pragma comment( lib, "comctl32" ) +#endif + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 //_WIN32_WINNT_WIN2K +#endif + +#define _WIN32_IE 0x0300 + +#include "../../driver.h" +#include "../../runloop.h" +#include "../video_context_driver.h" +#include "../gl_common.h" +#include "../video_monitor.h" +#include "win32_common.h" +#include "wgl_shader_dlg.h" +#include +#include +#include +#include + + +#define IDI_ICON 1 + +#define SHADER_DLG_WIDTH 220 +#define SHADER_DLG_MIN_HEIGHT 200 +#define SHADER_DLG_MAX_HEIGHT 800 +#define SHADER_DLG_CTRL_MARGIN 8 +#define SHADER_DLG_CTRL_X 10 +#define SHADER_DLG_CHECKBOX_HEIGHT 15 +#define SHADER_DLG_SEPARATOR_HEIGHT 10 +#define SHADER_DLG_LABEL_HEIGHT 14 +#define SHADER_DLG_TRACKBAR_HEIGHT 22 +#define SHADER_DLG_TRACKBAR_LABEL_WIDTH 30 + +#define SHADER_DLG_CTRL_WIDTH (SHADER_DLG_WIDTH - 2 * SHADER_DLG_CTRL_X) +#define SHADER_DLG_TRACKBAR_WIDTH (SHADER_DLG_CTRL_WIDTH - SHADER_DLG_TRACKBAR_LABEL_WIDTH) + +enum shader_param_ctrl_type +{ + SHADER_PARAM_CTRL_NONE = 0, + SHADER_PARAM_CTRL_CHECKBOX, + SHADER_PARAM_CTRL_TRACKBAR +}; + +enum +{ + SHADER_DLG_CHECKBOX_ONTOP_ID = GFX_MAX_PARAMETERS, + SHADER_DLG_CHECKBOX_BUTTON1_ID, + SHADER_DLG_CHECKBOX_BUTTON2_ID +}; + +typedef struct +{ + enum shader_param_ctrl_type type; + union + { + struct + { + HWND hwnd; + } checkbox; + struct + { + HWND hwnd; + HWND label_title; + HWND label_val; + } trackbar; + }; +} shader_param_ctrl_t; + +typedef struct +{ + HWND hwnd; + HWND on_top_checkbox; + HWND separator; + shader_param_ctrl_t controls[GFX_MAX_PARAMETERS]; + int parameters_start_y; +} shader_dlg_t; + +static shader_dlg_t g_shader_dlg = {0}; + +static inline void shader_dlg_refresh_trackbar_label(int index) +{ + char val_buffer[32]; + struct video_shader* shader = video_shader_driver_get_current_shader(); + + if (floorf(shader->parameters[index].current) == shader->parameters[index].current) + snprintf(val_buffer, sizeof(val_buffer), "%.0f", shader->parameters[index].current); + else + snprintf(val_buffer, sizeof(val_buffer), "%.2f", shader->parameters[index].current); + + SendMessage(g_shader_dlg.controls[index].trackbar.label_val, WM_SETTEXT, 0, (LPARAM)val_buffer); + +} + +static void shader_dlg_params_refresh(void) +{ + int i; + struct video_shader* shader = video_shader_driver_get_current_shader(); + + for (i = 0; i < GFX_MAX_PARAMETERS; i++) + { + if (g_shader_dlg.controls[i].type == SHADER_PARAM_CTRL_NONE) + break; + else if (g_shader_dlg.controls[i].type == SHADER_PARAM_CTRL_CHECKBOX) + { + bool checked = (shader->parameters[i].current == shader->parameters[i].maximum); + SendMessage(g_shader_dlg.controls[i].checkbox.hwnd, BM_SETCHECK, checked, 0); + + } + else if (g_shader_dlg.controls[i].type == SHADER_PARAM_CTRL_TRACKBAR) + { + shader_dlg_refresh_trackbar_label(i); + + SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)0); + SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, + (LPARAM)((shader->parameters[i].maximum - shader->parameters[i].minimum) / shader->parameters[i].step)); + SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_SETPOS, (WPARAM)TRUE, + (LPARAM)((shader->parameters[i].current - shader->parameters[i].minimum) / shader->parameters[i].step)); + + } + } +} + +static void shader_dlg_params_clear(void) +{ + int i; + + for (i = 0; i < GFX_MAX_PARAMETERS; i++) + { + if (g_shader_dlg.controls[i].type == SHADER_PARAM_CTRL_NONE) + break; + else if (g_shader_dlg.controls[i].type == SHADER_PARAM_CTRL_CHECKBOX) + DestroyWindow(g_shader_dlg.controls[i].checkbox.hwnd); + else if (g_shader_dlg.controls[i].type == SHADER_PARAM_CTRL_TRACKBAR) + { + DestroyWindow(g_shader_dlg.controls[i].trackbar.label_title); + DestroyWindow(g_shader_dlg.controls[i].trackbar.label_val); + DestroyWindow(g_shader_dlg.controls[i].trackbar.hwnd); + } + + g_shader_dlg.controls[i].type = SHADER_PARAM_CTRL_NONE; + } +} + +void shader_dlg_params_reload(void) +{ + int i, pos_x, pos_y; + struct video_shader* shader = video_shader_driver_get_current_shader(); + shader_dlg_params_clear(); + + if (!shader) + return; + + if (shader->num_parameters > GFX_MAX_PARAMETERS) + return; + + HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + + pos_y = g_shader_dlg.parameters_start_y; + pos_x = SHADER_DLG_CTRL_X; + + for (i = 0; i < shader->num_parameters; i++) + { + if ((shader->parameters[i].minimum == 0.0) + && (shader->parameters[i].maximum == (shader->parameters[i].minimum + shader->parameters[i].step))) + { + if ((pos_y + SHADER_DLG_CHECKBOX_HEIGHT + SHADER_DLG_CTRL_MARGIN + 20) > SHADER_DLG_MAX_HEIGHT) + { + pos_y = g_shader_dlg.parameters_start_y; + pos_x += SHADER_DLG_WIDTH; + } + + g_shader_dlg.controls[i].type = SHADER_PARAM_CTRL_CHECKBOX; + g_shader_dlg.controls[i].checkbox.hwnd = CreateWindowEx(0, "BUTTON", shader->parameters[i].desc, + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, pos_x, pos_y, SHADER_DLG_CTRL_WIDTH, SHADER_DLG_CHECKBOX_HEIGHT, + g_shader_dlg.hwnd, (HMENU)i, NULL, NULL); + SendMessage(g_shader_dlg.controls[i].checkbox.hwnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); + pos_y += SHADER_DLG_CHECKBOX_HEIGHT + SHADER_DLG_CTRL_MARGIN; + } + else + { + if ((pos_y + SHADER_DLG_LABEL_HEIGHT + SHADER_DLG_TRACKBAR_HEIGHT + + SHADER_DLG_CTRL_MARGIN + 20) > SHADER_DLG_MAX_HEIGHT) + { + pos_y = g_shader_dlg.parameters_start_y; + pos_x += SHADER_DLG_WIDTH; + } + + g_shader_dlg.controls[i].type = SHADER_PARAM_CTRL_TRACKBAR; + g_shader_dlg.controls[i].trackbar.label_title = CreateWindowEx(0, "STATIC", shader->parameters[i].desc, + WS_CHILD | WS_VISIBLE | SS_LEFT, pos_x, pos_y, SHADER_DLG_CTRL_WIDTH, SHADER_DLG_LABEL_HEIGHT, g_shader_dlg.hwnd, + (HMENU)i, NULL, NULL); + SendMessage(g_shader_dlg.controls[i].trackbar.label_title, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); + + pos_y += SHADER_DLG_LABEL_HEIGHT; + g_shader_dlg.controls[i].trackbar.hwnd = CreateWindowEx(0, TRACKBAR_CLASS, "", + WS_CHILD | WS_VISIBLE | TBS_HORZ | TBS_NOTICKS, pos_x + SHADER_DLG_TRACKBAR_LABEL_WIDTH, pos_y, + SHADER_DLG_TRACKBAR_WIDTH, SHADER_DLG_TRACKBAR_HEIGHT, g_shader_dlg.hwnd, (HMENU)i, NULL, NULL); + + g_shader_dlg.controls[i].trackbar.label_val = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE | SS_LEFT, pos_x, + pos_y, SHADER_DLG_TRACKBAR_LABEL_WIDTH, SHADER_DLG_LABEL_HEIGHT, g_shader_dlg.hwnd, (HMENU)i, NULL, NULL); + SendMessage(g_shader_dlg.controls[i].trackbar.label_val, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); + + SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_SETBUDDY, (WPARAM)TRUE, + (LPARAM)g_shader_dlg.controls[i].trackbar.label_val); + + pos_y += SHADER_DLG_TRACKBAR_HEIGHT + SHADER_DLG_CTRL_MARGIN; + + } + + } + + if (g_shader_dlg.separator) + DestroyWindow(g_shader_dlg.separator); + + g_shader_dlg.separator = CreateWindowEx(0, "STATIC", "", SS_ETCHEDHORZ | WS_VISIBLE | WS_CHILD, SHADER_DLG_CTRL_X, + g_shader_dlg.parameters_start_y - SHADER_DLG_CTRL_MARGIN - SHADER_DLG_SEPARATOR_HEIGHT / 2, + (pos_x - SHADER_DLG_CTRL_X) + SHADER_DLG_CTRL_WIDTH, SHADER_DLG_SEPARATOR_HEIGHT / 2, g_shader_dlg.hwnd, NULL, NULL, + NULL); + + shader_dlg_params_refresh(); + + RECT parent_rect; + GetWindowRect(g_shader_dlg.hwnd, &parent_rect); + SetWindowPos(g_shader_dlg.hwnd, NULL, 0, 0, + (pos_x - SHADER_DLG_CTRL_X) + SHADER_DLG_WIDTH, + (pos_x == SHADER_DLG_CTRL_X) ? pos_y + 30 : SHADER_DLG_MAX_HEIGHT, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + +} + +static void shader_dlg_update_on_top_state(void) +{ + bool on_top = SendMessage(g_shader_dlg.on_top_checkbox, BM_GETCHECK, 0, 0) == BST_CHECKED; + SetWindowPos(g_shader_dlg.hwnd, on_top ? HWND_TOPMOST : HWND_NOTOPMOST , 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); +} + +void shader_dlg_show(HWND parent_hwnd) +{ + const video_driver_t* vid_drv; + video_driver_resolve(&vid_drv); + if(vid_drv != &video_gl) + return; + + + if (!IsWindowVisible(g_shader_dlg.hwnd)) + { + if (parent_hwnd) + { + RECT parent_rect; + GetWindowRect(parent_hwnd, &parent_rect); + SetWindowPos(g_shader_dlg.hwnd, HWND_TOP, parent_rect.right, parent_rect.top, + 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + } + else + ShowWindow(g_shader_dlg.hwnd, SW_SHOW); + + shader_dlg_update_on_top_state(); + + shader_dlg_params_reload(); + + } + + SetFocus(g_shader_dlg.hwnd); + +} +static LRESULT CALLBACK ShaderDlgWndProc(HWND hwnd, UINT message, + WPARAM wparam, LPARAM lparam) +{ + int i, pos; + struct video_shader* shader = video_shader_driver_get_current_shader(); + + switch (message) + { + case WM_CREATE: + break; + + case WM_CLOSE: + case WM_DESTROY: + case WM_QUIT: + ShowWindow(g_shader_dlg.hwnd, 0); + return 0; + + case WM_COMMAND: + i = LOWORD(wparam); + + if (i == SHADER_DLG_CHECKBOX_ONTOP_ID) + { + shader_dlg_update_on_top_state(); + break; + } + + if (i >= GFX_MAX_PARAMETERS) + break; + + if (g_shader_dlg.controls[i].type != SHADER_PARAM_CTRL_CHECKBOX) + break; + + if (SendMessage(g_shader_dlg.controls[i].checkbox.hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED) + shader->parameters[i].current = shader->parameters[i].maximum; + else + shader->parameters[i].current = shader->parameters[i].minimum; + + break; + + case WM_HSCROLL: + i = GetWindowLong((HWND)lparam, GWL_ID); + + if (i >= GFX_MAX_PARAMETERS) + break; + + if (g_shader_dlg.controls[i].type != SHADER_PARAM_CTRL_TRACKBAR) + break; + + pos = (int)SendMessage(g_shader_dlg.controls[i].trackbar.hwnd, TBM_GETPOS, 0, 0); + shader->parameters[i].current = shader->parameters[i].minimum + pos * shader->parameters[i].step; + + shader_dlg_refresh_trackbar_label(i); + break; + + } + + return DefWindowProc(hwnd, message, wparam, lparam); +} + + + +bool wgl_shader_dlg_init(void) +{ + + static bool inited = false; + + const video_driver_t* vid_drv; + video_driver_resolve(&vid_drv); + if(vid_drv != &video_gl) + return false; + + if (g_shader_dlg.hwnd) + return true; + + if (!inited) + { + WNDCLASSEX wc_shader_dlg = {0}; + INITCOMMONCONTROLSEX comm_ctrl_init = {0}; + + comm_ctrl_init.dwSize = sizeof(comm_ctrl_init); + comm_ctrl_init.dwICC = ICC_BAR_CLASSES; + + + if (!InitCommonControlsEx(&comm_ctrl_init)) + return false; + + wc_shader_dlg.cbSize = sizeof(wc_shader_dlg); + wc_shader_dlg.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_OWNDC; + wc_shader_dlg.lpfnWndProc = ShaderDlgWndProc; + wc_shader_dlg.hInstance = GetModuleHandle(NULL); + wc_shader_dlg.hCursor = LoadCursor(NULL, IDC_ARROW); + wc_shader_dlg.lpszClassName = "Shader Dialog"; + wc_shader_dlg.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON)); + wc_shader_dlg.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0); + wc_shader_dlg.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + + if (!RegisterClassEx(&wc_shader_dlg)) + return false; + + inited = true; + } + + int pos_y; + HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + + g_shader_dlg.hwnd = CreateWindowEx(0, "Shader Dialog", "Shader Parameters", WS_POPUPWINDOW | WS_CAPTION, 100, 100, + SHADER_DLG_WIDTH, SHADER_DLG_MIN_HEIGHT, NULL, NULL, NULL, NULL); + + pos_y = SHADER_DLG_CTRL_MARGIN; + g_shader_dlg.on_top_checkbox = CreateWindowEx(0, "BUTTON", "Always on Top", BS_AUTOCHECKBOX | WS_VISIBLE | WS_CHILD, + SHADER_DLG_CTRL_X, pos_y, SHADER_DLG_CTRL_WIDTH, SHADER_DLG_CHECKBOX_HEIGHT, g_shader_dlg.hwnd, + (HMENU)SHADER_DLG_CHECKBOX_ONTOP_ID, NULL, NULL); + pos_y += SHADER_DLG_CHECKBOX_HEIGHT + SHADER_DLG_CTRL_MARGIN; + + SendMessage(g_shader_dlg.on_top_checkbox, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); + + pos_y += SHADER_DLG_SEPARATOR_HEIGHT + SHADER_DLG_CTRL_MARGIN; + + g_shader_dlg.parameters_start_y = pos_y; + + return true; +} diff --git a/gfx/drivers_context/wgl_shader_dlg.h b/gfx/drivers_context/wgl_shader_dlg.h new file mode 100644 index 0000000000..94cdfad2fc --- /dev/null +++ b/gfx/drivers_context/wgl_shader_dlg.h @@ -0,0 +1,23 @@ +#ifndef WGL_SHADER_DLG_H +#define WGL_SHADER_DLG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _XBOX +#define WIN32_LEAN_AND_MEAN +#include + + +bool wgl_shader_dlg_init(void); +void shader_dlg_show(HWND parent_hwnd); +void shader_dlg_params_reload(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // WGL_SHADER_DLG_H diff --git a/gfx/drivers_context/win32_common.c b/gfx/drivers_context/win32_common.c index 98f32062a7..a5cb5b6d07 100644 --- a/gfx/drivers_context/win32_common.c +++ b/gfx/drivers_context/win32_common.c @@ -27,6 +27,10 @@ #if !defined(_XBOX) && defined(_WIN32) #include "../../retroarch.h" +#ifdef HAVE_OPENGL +#include "wgl_shader_dlg.h" +#endif + static bool win32_browser(HWND owner, char *filename, const char *extensions, const char *title, const char *initial_dir) { @@ -130,6 +134,11 @@ LRESULT win32_menu_loop(HWND owner, WPARAM wparam) case ID_M_FULL_SCREEN: cmd = RARCH_CMD_FULLSCREEN_TOGGLE; break; +#ifdef HAVE_OPENGL + case ID_M_SHADER_PARAMETERS: + shader_dlg_show(owner); + break; +#endif case ID_M_MOUSE_GRAB: cmd = RARCH_CMD_GRAB_MOUSE_TOGGLE; break; diff --git a/griffin/griffin.c b/griffin/griffin.c index 5896ed4c82..1978254cbb 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -129,6 +129,7 @@ VIDEO CONTEXT #if defined(_WIN32) && !defined(_XBOX) #include "../gfx/drivers_context/wgl_ctx.c" +#include "../gfx/drivers_context/wgl_shader_dlg.c" #endif #endif diff --git a/media/rarch.rc b/media/rarch.rc index e412314377..71165a2c72 100644 --- a/media/rarch.rc +++ b/media/rarch.rc @@ -64,5 +64,6 @@ BEGIN MENUITEM "10x", ID_M_WINDOW_SCALE_10X END MENUITEM "Toggle Exclusive Full Screen", ID_M_FULL_SCREEN + MENUITEM "Shader Parameters", ID_M_SHADER_PARAMETERS END END diff --git a/win32/resource.h b/win32/resource.h index 6a11d51081..1415f7fc00 100644 --- a/win32/resource.h +++ b/win32/resource.h @@ -27,3 +27,4 @@ #define ID_M_STATE_INDEX_AUTO 40024 #define ID_M_TAKE_SCREENSHOT 40025 #define ID_M_MUTE_TOGGLE 40026 +#define ID_M_SHADER_PARAMETERS 40027