win-capture: Remove game capture scaling
The performance save is not worth accidental usage support. Also remove unnecessary copies from the shmem paths.master
parent
0f27cf4983
commit
6393399758
|
@ -210,7 +210,7 @@ void cursor_capture(struct cursor_data *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
void cursor_draw(struct cursor_data *data, long x_offset, long y_offset,
|
void cursor_draw(struct cursor_data *data, long x_offset, long y_offset,
|
||||||
float x_scale, float y_scale, long width, long height)
|
long width, long height)
|
||||||
{
|
{
|
||||||
long x = data->cursor_pos.x + x_offset;
|
long x = data->cursor_pos.x + x_offset;
|
||||||
long y = data->cursor_pos.y + y_offset;
|
long y = data->cursor_pos.y + y_offset;
|
||||||
|
@ -226,7 +226,6 @@ void cursor_draw(struct cursor_data *data, long x_offset, long y_offset,
|
||||||
gs_enable_color(true, true, true, false);
|
gs_enable_color(true, true, true, false);
|
||||||
|
|
||||||
gs_matrix_push();
|
gs_matrix_push();
|
||||||
gs_matrix_scale3f(x_scale, y_scale, 1.0f);
|
|
||||||
obs_source_draw(data->texture, x_draw, y_draw, 0, 0, false);
|
obs_source_draw(data->texture, x_draw, y_draw, 0, 0, false);
|
||||||
gs_matrix_pop();
|
gs_matrix_pop();
|
||||||
|
|
||||||
|
|
|
@ -24,5 +24,5 @@ struct cursor_data {
|
||||||
|
|
||||||
extern void cursor_capture(struct cursor_data *data);
|
extern void cursor_capture(struct cursor_data *data);
|
||||||
extern void cursor_draw(struct cursor_data *data, long x_offset, long y_offset,
|
extern void cursor_draw(struct cursor_data *data, long x_offset, long y_offset,
|
||||||
float x_scale, float y_scale, long width, long height);
|
long width, long height);
|
||||||
extern void cursor_data_free(struct cursor_data *data);
|
extern void cursor_data_free(struct cursor_data *data);
|
||||||
|
|
|
@ -205,7 +205,7 @@ static uint32_t duplicator_capture_height(void *data)
|
||||||
|
|
||||||
static void draw_cursor(struct duplicator_capture *capture)
|
static void draw_cursor(struct duplicator_capture *capture)
|
||||||
{
|
{
|
||||||
cursor_draw(&capture->cursor_data, -capture->x, -capture->y, 1.0f, 1.0f,
|
cursor_draw(&capture->cursor_data, -capture->x, -capture->y,
|
||||||
capture->rot % 180 == 0 ? capture->width : capture->height,
|
capture->rot % 180 == 0 ? capture->width : capture->height,
|
||||||
capture->rot % 180 == 0 ? capture->height : capture->width);
|
capture->rot % 180 == 0 ? capture->height : capture->width);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#define SETTING_ACTIVE_WINDOW "active_window"
|
#define SETTING_ACTIVE_WINDOW "active_window"
|
||||||
#define SETTING_WINDOW_PRIORITY "priority"
|
#define SETTING_WINDOW_PRIORITY "priority"
|
||||||
#define SETTING_COMPATIBILITY "sli_compatibility"
|
#define SETTING_COMPATIBILITY "sli_compatibility"
|
||||||
#define SETTING_FORCE_SCALING "force_scaling"
|
|
||||||
#define SETTING_SCALE_RES "scale_res"
|
|
||||||
#define SETTING_CURSOR "capture_cursor"
|
#define SETTING_CURSOR "capture_cursor"
|
||||||
#define SETTING_TRANSPARENCY "allow_transparency"
|
#define SETTING_TRANSPARENCY "allow_transparency"
|
||||||
#define SETTING_LIMIT_FRAMERATE "limit_framerate"
|
#define SETTING_LIMIT_FRAMERATE "limit_framerate"
|
||||||
|
@ -56,8 +54,6 @@
|
||||||
#define TEXT_ANY_FULLSCREEN obs_module_text("GameCapture.AnyFullscreen")
|
#define TEXT_ANY_FULLSCREEN obs_module_text("GameCapture.AnyFullscreen")
|
||||||
#define TEXT_SLI_COMPATIBILITY obs_module_text("SLIFix")
|
#define TEXT_SLI_COMPATIBILITY obs_module_text("SLIFix")
|
||||||
#define TEXT_ALLOW_TRANSPARENCY obs_module_text("AllowTransparency")
|
#define TEXT_ALLOW_TRANSPARENCY obs_module_text("AllowTransparency")
|
||||||
#define TEXT_FORCE_SCALING obs_module_text("GameCapture.ForceScaling")
|
|
||||||
#define TEXT_SCALE_RES obs_module_text("GameCapture.ScaleRes")
|
|
||||||
#define TEXT_WINDOW obs_module_text("WindowCapture.Window")
|
#define TEXT_WINDOW obs_module_text("WindowCapture.Window")
|
||||||
#define TEXT_MATCH_PRIORITY obs_module_text("WindowCapture.Priority")
|
#define TEXT_MATCH_PRIORITY obs_module_text("WindowCapture.Priority")
|
||||||
#define TEXT_MATCH_TITLE obs_module_text("WindowCapture.Priority.Title")
|
#define TEXT_MATCH_TITLE obs_module_text("WindowCapture.Priority.Title")
|
||||||
|
@ -104,11 +100,8 @@ struct game_capture_config {
|
||||||
char *executable;
|
char *executable;
|
||||||
enum window_priority priority;
|
enum window_priority priority;
|
||||||
enum capture_mode mode;
|
enum capture_mode mode;
|
||||||
uint32_t scale_cx;
|
|
||||||
uint32_t scale_cy;
|
|
||||||
bool cursor;
|
bool cursor;
|
||||||
bool force_shmem;
|
bool force_shmem;
|
||||||
bool force_scaling;
|
|
||||||
bool allow_transparency;
|
bool allow_transparency;
|
||||||
bool limit_framerate;
|
bool limit_framerate;
|
||||||
bool capture_overlays;
|
bool capture_overlays;
|
||||||
|
@ -392,8 +385,6 @@ static inline bool using_older_non_mode_format(obs_data_t *settings)
|
||||||
static inline void get_config(struct game_capture_config *cfg,
|
static inline void get_config(struct game_capture_config *cfg,
|
||||||
obs_data_t *settings, const char *window)
|
obs_data_t *settings, const char *window)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
const char *scale_str;
|
|
||||||
const char *mode_str = NULL;
|
const char *mode_str = NULL;
|
||||||
|
|
||||||
build_window_strings(window, &cfg->class, &cfg->title,
|
build_window_strings(window, &cfg->class, &cfg->title,
|
||||||
|
@ -419,7 +410,6 @@ static inline void get_config(struct game_capture_config *cfg,
|
||||||
cfg->cursor = obs_data_get_bool(settings, SETTING_CURSOR);
|
cfg->cursor = obs_data_get_bool(settings, SETTING_CURSOR);
|
||||||
cfg->allow_transparency =
|
cfg->allow_transparency =
|
||||||
obs_data_get_bool(settings, SETTING_TRANSPARENCY);
|
obs_data_get_bool(settings, SETTING_TRANSPARENCY);
|
||||||
cfg->force_scaling = obs_data_get_bool(settings, SETTING_FORCE_SCALING);
|
|
||||||
cfg->limit_framerate =
|
cfg->limit_framerate =
|
||||||
obs_data_get_bool(settings, SETTING_LIMIT_FRAMERATE);
|
obs_data_get_bool(settings, SETTING_LIMIT_FRAMERATE);
|
||||||
cfg->capture_overlays =
|
cfg->capture_overlays =
|
||||||
|
@ -428,20 +418,6 @@ static inline void get_config(struct game_capture_config *cfg,
|
||||||
obs_data_get_bool(settings, SETTING_ANTI_CHEAT_HOOK);
|
obs_data_get_bool(settings, SETTING_ANTI_CHEAT_HOOK);
|
||||||
cfg->hook_rate =
|
cfg->hook_rate =
|
||||||
(enum hook_rate)obs_data_get_int(settings, SETTING_HOOK_RATE);
|
(enum hook_rate)obs_data_get_int(settings, SETTING_HOOK_RATE);
|
||||||
|
|
||||||
scale_str = obs_data_get_string(settings, SETTING_SCALE_RES);
|
|
||||||
ret = sscanf(scale_str, "%" PRIu32 "x%" PRIu32, &cfg->scale_cx,
|
|
||||||
&cfg->scale_cy);
|
|
||||||
|
|
||||||
cfg->scale_cx &= ~2;
|
|
||||||
cfg->scale_cy &= ~2;
|
|
||||||
|
|
||||||
if (cfg->force_scaling) {
|
|
||||||
if (ret != 2 || cfg->scale_cx == 0 || cfg->scale_cy == 0) {
|
|
||||||
cfg->scale_cx = 0;
|
|
||||||
cfg->scale_cy = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int s_cmp(const char *str1, const char *str2)
|
static inline int s_cmp(const char *str1, const char *str2)
|
||||||
|
@ -465,13 +441,6 @@ static inline bool capture_needs_reset(struct game_capture_config *cfg1,
|
||||||
cfg1->priority != cfg2->priority)) {
|
cfg1->priority != cfg2->priority)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else if (cfg1->force_scaling != cfg2->force_scaling) {
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (cfg1->force_scaling && (cfg1->scale_cx != cfg2->scale_cx ||
|
|
||||||
cfg1->scale_cy != cfg2->scale_cy)) {
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (cfg1->force_shmem != cfg2->force_shmem) {
|
} else if (cfg1->force_shmem != cfg2->force_shmem) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -525,12 +494,7 @@ static void game_capture_update(void *data, obs_data_t *settings)
|
||||||
get_config(&cfg, settings, window);
|
get_config(&cfg, settings, window);
|
||||||
reset_capture = capture_needs_reset(&cfg, &gc->config);
|
reset_capture = capture_needs_reset(&cfg, &gc->config);
|
||||||
|
|
||||||
if (cfg.force_scaling && (cfg.scale_cx == 0 || cfg.scale_cy == 0)) {
|
gc->error_acquiring = false;
|
||||||
gc->error_acquiring = true;
|
|
||||||
warn("error acquiring, scale is bad");
|
|
||||||
} else {
|
|
||||||
gc->error_acquiring = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cfg.mode == CAPTURE_MODE_HOTKEY &&
|
if (cfg.mode == CAPTURE_MODE_HOTKEY &&
|
||||||
gc->config.mode != CAPTURE_MODE_HOTKEY) {
|
gc->config.mode != CAPTURE_MODE_HOTKEY) {
|
||||||
|
@ -771,11 +735,7 @@ static inline bool init_hook_info(struct game_capture *gc)
|
||||||
: offsets32;
|
: offsets32;
|
||||||
gc->global_hook_info->capture_overlay = gc->config.capture_overlays;
|
gc->global_hook_info->capture_overlay = gc->config.capture_overlays;
|
||||||
gc->global_hook_info->force_shmem = gc->config.force_shmem;
|
gc->global_hook_info->force_shmem = gc->config.force_shmem;
|
||||||
gc->global_hook_info->use_scale = gc->config.force_scaling;
|
gc->global_hook_info->UNUSED_use_scale = false;
|
||||||
if (gc->config.scale_cx)
|
|
||||||
gc->global_hook_info->cx = gc->config.scale_cx;
|
|
||||||
if (gc->config.scale_cy)
|
|
||||||
gc->global_hook_info->cy = gc->config.scale_cy;
|
|
||||||
reset_frame_interval(gc);
|
reset_frame_interval(gc);
|
||||||
|
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
|
@ -1817,7 +1777,7 @@ static inline void game_capture_render_cursor(struct game_capture *gc)
|
||||||
POINT p = {0};
|
POINT p = {0};
|
||||||
HWND window;
|
HWND window;
|
||||||
|
|
||||||
if (!gc->global_hook_info->base_cx || !gc->global_hook_info->base_cy)
|
if (!gc->global_hook_info->cx || !gc->global_hook_info->cy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window = !!gc->global_hook_info->window
|
window = !!gc->global_hook_info->window
|
||||||
|
@ -1826,14 +1786,8 @@ static inline void game_capture_render_cursor(struct game_capture *gc)
|
||||||
|
|
||||||
ClientToScreen(window, &p);
|
ClientToScreen(window, &p);
|
||||||
|
|
||||||
float x_scale = (float)gc->global_hook_info->cx /
|
cursor_draw(&gc->cursor_data, -p.x, -p.y, gc->global_hook_info->cx,
|
||||||
(float)gc->global_hook_info->base_cx;
|
gc->global_hook_info->cy);
|
||||||
float y_scale = (float)gc->global_hook_info->cy /
|
|
||||||
(float)gc->global_hook_info->base_cy;
|
|
||||||
|
|
||||||
cursor_draw(&gc->cursor_data, -p.x, -p.y, x_scale, y_scale,
|
|
||||||
gc->global_hook_info->base_cx,
|
|
||||||
gc->global_hook_info->base_cy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_capture_render(void *data, gs_effect_t *effect)
|
static void game_capture_render(void *data, gs_effect_t *effect)
|
||||||
|
@ -1890,10 +1844,8 @@ static void game_capture_defaults(obs_data_t *settings)
|
||||||
obs_data_set_default_int(settings, SETTING_WINDOW_PRIORITY,
|
obs_data_set_default_int(settings, SETTING_WINDOW_PRIORITY,
|
||||||
(int)WINDOW_PRIORITY_EXE);
|
(int)WINDOW_PRIORITY_EXE);
|
||||||
obs_data_set_default_bool(settings, SETTING_COMPATIBILITY, false);
|
obs_data_set_default_bool(settings, SETTING_COMPATIBILITY, false);
|
||||||
obs_data_set_default_bool(settings, SETTING_FORCE_SCALING, false);
|
|
||||||
obs_data_set_default_bool(settings, SETTING_CURSOR, true);
|
obs_data_set_default_bool(settings, SETTING_CURSOR, true);
|
||||||
obs_data_set_default_bool(settings, SETTING_TRANSPARENCY, false);
|
obs_data_set_default_bool(settings, SETTING_TRANSPARENCY, false);
|
||||||
obs_data_set_default_string(settings, SETTING_SCALE_RES, "0x0");
|
|
||||||
obs_data_set_default_bool(settings, SETTING_LIMIT_FRAMERATE, false);
|
obs_data_set_default_bool(settings, SETTING_LIMIT_FRAMERATE, false);
|
||||||
obs_data_set_default_bool(settings, SETTING_CAPTURE_OVERLAYS, false);
|
obs_data_set_default_bool(settings, SETTING_CAPTURE_OVERLAYS, false);
|
||||||
obs_data_set_default_bool(settings, SETTING_ANTI_CHEAT_HOOK, true);
|
obs_data_set_default_bool(settings, SETTING_ANTI_CHEAT_HOOK, true);
|
||||||
|
@ -1923,16 +1875,6 @@ static bool mode_callback(obs_properties_t *ppts, obs_property_t *p,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool use_scaling_callback(obs_properties_t *ppts, obs_property_t *p,
|
|
||||||
obs_data_t *settings)
|
|
||||||
{
|
|
||||||
bool use_scale = obs_data_get_bool(settings, SETTING_FORCE_SCALING);
|
|
||||||
|
|
||||||
p = obs_properties_get(ppts, SETTING_SCALE_RES);
|
|
||||||
obs_property_set_enabled(p, use_scale);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void insert_preserved_val(obs_property_t *p, const char *val, size_t idx)
|
static void insert_preserved_val(obs_property_t *p, const char *val, size_t idx)
|
||||||
{
|
{
|
||||||
char *class = NULL;
|
char *class = NULL;
|
||||||
|
@ -1992,11 +1934,6 @@ static bool window_changed_callback(obs_properties_t *ppts, obs_property_t *p,
|
||||||
SETTING_CAPTURE_WINDOW, 1);
|
SETTING_CAPTURE_WINDOW, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const double default_scale_vals[] = {1.25, 1.5, 2.0, 2.5, 3.0};
|
|
||||||
|
|
||||||
#define NUM_DEFAULT_SCALE_VALS \
|
|
||||||
(sizeof(default_scale_vals) / sizeof(default_scale_vals[0]))
|
|
||||||
|
|
||||||
static BOOL CALLBACK EnumFirstMonitor(HMONITOR monitor, HDC hdc, LPRECT rc,
|
static BOOL CALLBACK EnumFirstMonitor(HMONITOR monitor, HDC hdc, LPRECT rc,
|
||||||
LPARAM data)
|
LPARAM data)
|
||||||
{
|
{
|
||||||
|
@ -2082,29 +2019,6 @@ static obs_properties_t *game_capture_properties(void *data)
|
||||||
obs_properties_add_bool(ppts, SETTING_COMPATIBILITY,
|
obs_properties_add_bool(ppts, SETTING_COMPATIBILITY,
|
||||||
TEXT_SLI_COMPATIBILITY);
|
TEXT_SLI_COMPATIBILITY);
|
||||||
|
|
||||||
p = obs_properties_add_bool(ppts, SETTING_FORCE_SCALING,
|
|
||||||
TEXT_FORCE_SCALING);
|
|
||||||
|
|
||||||
obs_property_set_modified_callback(p, use_scaling_callback);
|
|
||||||
|
|
||||||
p = obs_properties_add_list(ppts, SETTING_SCALE_RES, TEXT_SCALE_RES,
|
|
||||||
OBS_COMBO_TYPE_EDITABLE,
|
|
||||||
OBS_COMBO_FORMAT_STRING);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < NUM_DEFAULT_SCALE_VALS; i++) {
|
|
||||||
char scale_str[64];
|
|
||||||
uint32_t new_cx =
|
|
||||||
(uint32_t)((double)cx / default_scale_vals[i]) & ~2;
|
|
||||||
uint32_t new_cy =
|
|
||||||
(uint32_t)((double)cy / default_scale_vals[i]) & ~2;
|
|
||||||
|
|
||||||
sprintf(scale_str, "%" PRIu32 "x%" PRIu32, new_cx, new_cy);
|
|
||||||
|
|
||||||
obs_property_list_add_string(p, scale_str, scale_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_property_set_enabled(p, false);
|
|
||||||
|
|
||||||
obs_properties_add_bool(ppts, SETTING_TRANSPARENCY,
|
obs_properties_add_bool(ppts, SETTING_TRANSPARENCY,
|
||||||
TEXT_ALLOW_TRANSPARENCY);
|
TEXT_ALLOW_TRANSPARENCY);
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,8 @@ struct hook_info {
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
uint32_t cx;
|
uint32_t cx;
|
||||||
uint32_t cy;
|
uint32_t cy;
|
||||||
uint32_t base_cx;
|
uint32_t UNUSED_base_cx;
|
||||||
uint32_t base_cy;
|
uint32_t UNUSED_base_cy;
|
||||||
uint32_t pitch;
|
uint32_t pitch;
|
||||||
uint32_t map_id;
|
uint32_t map_id;
|
||||||
uint32_t map_size;
|
uint32_t map_size;
|
||||||
|
@ -99,7 +99,7 @@ struct hook_info {
|
||||||
|
|
||||||
/* additional options */
|
/* additional options */
|
||||||
uint64_t frame_interval;
|
uint64_t frame_interval;
|
||||||
bool use_scale;
|
bool UNUSED_use_scale;
|
||||||
bool force_shmem;
|
bool force_shmem;
|
||||||
bool capture_overlay;
|
bool capture_overlay;
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,10 @@
|
||||||
|
|
||||||
struct d3d10_data {
|
struct d3d10_data {
|
||||||
ID3D10Device *device; /* do not release */
|
ID3D10Device *device; /* do not release */
|
||||||
uint32_t base_cx;
|
|
||||||
uint32_t base_cy;
|
|
||||||
uint32_t cx;
|
uint32_t cx;
|
||||||
uint32_t cy;
|
uint32_t cy;
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
bool using_shtex;
|
bool using_shtex;
|
||||||
bool using_scale;
|
|
||||||
bool multisampled;
|
bool multisampled;
|
||||||
|
|
||||||
ID3D10Texture2D *scale_tex;
|
ID3D10Texture2D *scale_tex;
|
||||||
|
@ -42,8 +39,6 @@ struct d3d10_data {
|
||||||
struct {
|
struct {
|
||||||
struct shmem_data *shmem_info;
|
struct shmem_data *shmem_info;
|
||||||
ID3D10Texture2D *copy_surfaces[NUM_BUFFERS];
|
ID3D10Texture2D *copy_surfaces[NUM_BUFFERS];
|
||||||
ID3D10Texture2D *textures[NUM_BUFFERS];
|
|
||||||
ID3D10RenderTargetView *render_targets[NUM_BUFFERS];
|
|
||||||
bool texture_ready[NUM_BUFFERS];
|
bool texture_ready[NUM_BUFFERS];
|
||||||
bool texture_mapped[NUM_BUFFERS];
|
bool texture_mapped[NUM_BUFFERS];
|
||||||
uint32_t pitch;
|
uint32_t pitch;
|
||||||
|
@ -92,10 +87,6 @@ void d3d10_free(void)
|
||||||
data.copy_surfaces[i]->Unmap(0);
|
data.copy_surfaces[i]->Unmap(0);
|
||||||
data.copy_surfaces[i]->Release();
|
data.copy_surfaces[i]->Release();
|
||||||
}
|
}
|
||||||
if (data.textures[i])
|
|
||||||
data.textures[i]->Release();
|
|
||||||
if (data.render_targets[i])
|
|
||||||
data.render_targets[i]->Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,218 +216,8 @@ static inline bool d3d10_init_format(IDXGISwapChain *swap, HWND &window)
|
||||||
data.format = fix_dxgi_format(desc.BufferDesc.Format);
|
data.format = fix_dxgi_format(desc.BufferDesc.Format);
|
||||||
data.multisampled = desc.SampleDesc.Count > 1;
|
data.multisampled = desc.SampleDesc.Count > 1;
|
||||||
window = desc.OutputWindow;
|
window = desc.OutputWindow;
|
||||||
data.base_cx = desc.BufferDesc.Width;
|
data.cx = desc.BufferDesc.Width;
|
||||||
data.base_cy = desc.BufferDesc.Height;
|
data.cy = desc.BufferDesc.Height;
|
||||||
|
|
||||||
if (data.using_scale) {
|
|
||||||
data.cx = global_hook_info->cx;
|
|
||||||
data.cy = global_hook_info->cy;
|
|
||||||
} else {
|
|
||||||
data.cx = desc.BufferDesc.Width;
|
|
||||||
data.cy = desc.BufferDesc.Height;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d10_init_vertex_shader(void)
|
|
||||||
{
|
|
||||||
D3D10_INPUT_ELEMENT_DESC desc[2];
|
|
||||||
uint8_t *vs_data;
|
|
||||||
size_t size;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
vs_data = get_d3d1x_vertex_shader(&size);
|
|
||||||
|
|
||||||
hr = data.device->CreateVertexShader(vs_data, size,
|
|
||||||
&data.vertex_shader);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_vertex_shader: failed to create shader",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc[0].SemanticName = "SV_Position";
|
|
||||||
desc[0].SemanticIndex = 0;
|
|
||||||
desc[0].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
|
||||||
desc[0].InputSlot = 0;
|
|
||||||
desc[0].AlignedByteOffset = 0;
|
|
||||||
desc[0].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
|
|
||||||
desc[0].InstanceDataStepRate = 0;
|
|
||||||
|
|
||||||
desc[1].SemanticName = "TEXCOORD";
|
|
||||||
desc[1].SemanticIndex = 0;
|
|
||||||
desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
|
|
||||||
desc[1].InputSlot = 0;
|
|
||||||
desc[1].AlignedByteOffset = D3D10_APPEND_ALIGNED_ELEMENT;
|
|
||||||
desc[1].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
|
|
||||||
desc[1].InstanceDataStepRate = 0;
|
|
||||||
|
|
||||||
hr = data.device->CreateInputLayout(desc, 2, vs_data, size,
|
|
||||||
&data.vertex_layout);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_vertex_shader: failed to create layout",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d10_init_pixel_shader(void)
|
|
||||||
{
|
|
||||||
uint8_t *ps_data;
|
|
||||||
size_t size;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
ps_data = get_d3d1x_pixel_shader(&size);
|
|
||||||
|
|
||||||
hr = data.device->CreatePixelShader(ps_data, size, &data.pixel_shader);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_pixel_shader: failed to create shader", hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d10_init_sampler_state(void)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
D3D10_SAMPLER_DESC desc = {};
|
|
||||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
|
|
||||||
desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
|
|
||||||
desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
|
|
||||||
|
|
||||||
hr = data.device->CreateSamplerState(&desc, &data.sampler_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_sampler_state: failed to create sampler "
|
|
||||||
"state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d10_init_blend_state(void)
|
|
||||||
{
|
|
||||||
D3D10_BLEND_DESC desc = {};
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; i++)
|
|
||||||
desc.RenderTargetWriteMask[i] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
|
||||||
|
|
||||||
hr = data.device->CreateBlendState(&desc, &data.blend_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_blend_state: failed to create blend state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d10_init_zstencil_state(void)
|
|
||||||
{
|
|
||||||
D3D10_DEPTH_STENCIL_DESC desc = {}; /* defaults all to off */
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
hr = data.device->CreateDepthStencilState(&desc, &data.zstencil_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_zstencil_state: failed to create "
|
|
||||||
"zstencil state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d10_init_raster_state(void)
|
|
||||||
{
|
|
||||||
D3D10_RASTERIZER_DESC desc = {};
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
desc.FillMode = D3D10_FILL_SOLID;
|
|
||||||
desc.CullMode = D3D10_CULL_NONE;
|
|
||||||
|
|
||||||
hr = data.device->CreateRasterizerState(&desc, &data.raster_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_raster_state: failed to create raster "
|
|
||||||
"state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUM_VERTS 4
|
|
||||||
|
|
||||||
static inline bool d3d10_init_vertex_buffer(void)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
const vertex verts[NUM_VERTS] = {
|
|
||||||
{{-1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
|
|
||||||
{{-1.0f, -1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
|
|
||||||
{{1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
|
|
||||||
{{1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}};
|
|
||||||
|
|
||||||
D3D10_BUFFER_DESC desc;
|
|
||||||
desc.ByteWidth = sizeof(vertex) * NUM_VERTS;
|
|
||||||
desc.Usage = D3D10_USAGE_DEFAULT;
|
|
||||||
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
|
||||||
desc.CPUAccessFlags = 0;
|
|
||||||
desc.MiscFlags = 0;
|
|
||||||
|
|
||||||
D3D10_SUBRESOURCE_DATA srd = {};
|
|
||||||
srd.pSysMem = (const void *)verts;
|
|
||||||
|
|
||||||
hr = data.device->CreateBuffer(&desc, &srd, &data.vertex_buffer);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d10_init_vertex_buffer: failed to create vertex "
|
|
||||||
"buffer",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool d3d10_init_scaling(void)
|
|
||||||
{
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
success = create_d3d10_tex(data.base_cx, data.base_cy, &data.scale_tex,
|
|
||||||
&data.scale_resource, nullptr, nullptr);
|
|
||||||
if (!success) {
|
|
||||||
hlog("d3d10_init_scaling: failed to create scale texture");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!d3d10_init_vertex_shader()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d10_init_pixel_shader()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d10_init_sampler_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d10_init_blend_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d10_init_zstencil_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d10_init_raster_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d10_init_vertex_buffer()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -467,13 +248,6 @@ static bool d3d10_shmem_init_buffers(size_t idx)
|
||||||
data.copy_surfaces[idx]->Unmap(0);
|
data.copy_surfaces[idx]->Unmap(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = create_d3d10_tex(data.cx, data.cy, &data.textures[idx],
|
|
||||||
nullptr, &data.render_targets[idx], nullptr);
|
|
||||||
if (!success) {
|
|
||||||
hlog("d3d10_shmem_init_buffers: failed to create texture");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,9 +260,8 @@ static bool d3d10_shmem_init(HWND window)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!capture_init_shmem(&data.shmem_info, window, data.base_cx,
|
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.pitch,
|
data.pitch, data.format, false)) {
|
||||||
data.format, false)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,9 +285,8 @@ static bool d3d10_shtex_init(HWND window)
|
||||||
hlog("d3d10_shtex_init: failed to create texture");
|
hlog("d3d10_shtex_init: failed to create texture");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
|
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.format,
|
data.format, false, (uintptr_t)data.handle)) {
|
||||||
false, (uintptr_t)data.handle)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,12 +296,9 @@ static bool d3d10_shtex_init(HWND window)
|
||||||
|
|
||||||
static void d3d10_init(IDXGISwapChain *swap)
|
static void d3d10_init(IDXGISwapChain *swap)
|
||||||
{
|
{
|
||||||
bool success = true;
|
|
||||||
HWND window;
|
HWND window;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
data.using_scale = global_hook_info->use_scale;
|
|
||||||
|
|
||||||
hr = swap->GetDevice(__uuidof(ID3D10Device), (void **)&data.device);
|
hr = swap->GetDevice(__uuidof(ID3D10Device), (void **)&data.device);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
hlog_hr("d3d10_init: failed to get device from swap", hr);
|
hlog_hr("d3d10_init: failed to get device from swap", hr);
|
||||||
|
@ -542,169 +311,14 @@ static void d3d10_init(IDXGISwapChain *swap)
|
||||||
if (!d3d10_init_format(swap, window)) {
|
if (!d3d10_init_format(swap, window)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.using_scale && !d3d10_init_scaling()) {
|
|
||||||
hlog("d3d10_init: failed to initialize scaling");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
if (global_hook_info->force_shmem) {
|
|
||||||
success = d3d10_shmem_init(window);
|
|
||||||
} else {
|
|
||||||
success = d3d10_shtex_init(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const bool success = global_hook_info->force_shmem
|
||||||
|
? d3d10_shmem_init(window)
|
||||||
|
: d3d10_shtex_init(window);
|
||||||
if (!success)
|
if (!success)
|
||||||
d3d10_free();
|
d3d10_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_RENDER_TARGETS D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT
|
|
||||||
#define MAX_SO_TARGETS 4
|
|
||||||
|
|
||||||
struct d3d10_state {
|
|
||||||
ID3D10GeometryShader *geom_shader;
|
|
||||||
ID3D10InputLayout *vertex_layout;
|
|
||||||
D3D10_PRIMITIVE_TOPOLOGY topology;
|
|
||||||
ID3D10Buffer *vertex_buffer;
|
|
||||||
UINT vb_stride;
|
|
||||||
UINT vb_offset;
|
|
||||||
ID3D10BlendState *blend_state;
|
|
||||||
float blend_factor[4];
|
|
||||||
UINT sample_mask;
|
|
||||||
ID3D10DepthStencilState *zstencil_state;
|
|
||||||
UINT zstencil_ref;
|
|
||||||
ID3D10RenderTargetView *render_targets[MAX_RENDER_TARGETS];
|
|
||||||
ID3D10DepthStencilView *zstencil_view;
|
|
||||||
ID3D10SamplerState *sampler_state;
|
|
||||||
ID3D10PixelShader *pixel_shader;
|
|
||||||
ID3D10ShaderResourceView *resource;
|
|
||||||
ID3D10RasterizerState *raster_state;
|
|
||||||
UINT num_viewports;
|
|
||||||
D3D10_VIEWPORT *viewports;
|
|
||||||
ID3D10Buffer *stream_output_targets[MAX_SO_TARGETS];
|
|
||||||
UINT so_offsets[MAX_SO_TARGETS];
|
|
||||||
ID3D10VertexShader *vertex_shader;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void d3d10_save_state(struct d3d10_state *state)
|
|
||||||
{
|
|
||||||
data.device->GSGetShader(&state->geom_shader);
|
|
||||||
data.device->IAGetInputLayout(&state->vertex_layout);
|
|
||||||
data.device->IAGetPrimitiveTopology(&state->topology);
|
|
||||||
data.device->IAGetVertexBuffers(0, 1, &state->vertex_buffer,
|
|
||||||
&state->vb_stride, &state->vb_offset);
|
|
||||||
data.device->OMGetBlendState(&state->blend_state, state->blend_factor,
|
|
||||||
&state->sample_mask);
|
|
||||||
data.device->OMGetDepthStencilState(&state->zstencil_state,
|
|
||||||
&state->zstencil_ref);
|
|
||||||
data.device->OMGetRenderTargets(MAX_RENDER_TARGETS,
|
|
||||||
state->render_targets,
|
|
||||||
&state->zstencil_view);
|
|
||||||
data.device->PSGetSamplers(0, 1, &state->sampler_state);
|
|
||||||
data.device->PSGetShader(&state->pixel_shader);
|
|
||||||
data.device->PSGetShaderResources(0, 1, &state->resource);
|
|
||||||
data.device->RSGetState(&state->raster_state);
|
|
||||||
data.device->RSGetViewports(&state->num_viewports, nullptr);
|
|
||||||
if (state->num_viewports) {
|
|
||||||
state->viewports = (D3D10_VIEWPORT *)malloc(
|
|
||||||
sizeof(D3D10_VIEWPORT) * state->num_viewports);
|
|
||||||
data.device->RSGetViewports(&state->num_viewports,
|
|
||||||
state->viewports);
|
|
||||||
}
|
|
||||||
data.device->SOGetTargets(MAX_SO_TARGETS, state->stream_output_targets,
|
|
||||||
state->so_offsets);
|
|
||||||
data.device->VSGetShader(&state->vertex_shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void safe_release(IUnknown *p)
|
|
||||||
{
|
|
||||||
if (p)
|
|
||||||
p->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d10_restore_state(struct d3d10_state *state)
|
|
||||||
{
|
|
||||||
data.device->GSSetShader(state->geom_shader);
|
|
||||||
data.device->IASetInputLayout(state->vertex_layout);
|
|
||||||
data.device->IASetPrimitiveTopology(state->topology);
|
|
||||||
data.device->IASetVertexBuffers(0, 1, &state->vertex_buffer,
|
|
||||||
&state->vb_stride, &state->vb_offset);
|
|
||||||
data.device->OMSetBlendState(state->blend_state, state->blend_factor,
|
|
||||||
state->sample_mask);
|
|
||||||
data.device->OMSetDepthStencilState(state->zstencil_state,
|
|
||||||
state->zstencil_ref);
|
|
||||||
data.device->OMSetRenderTargets(MAX_RENDER_TARGETS,
|
|
||||||
state->render_targets,
|
|
||||||
state->zstencil_view);
|
|
||||||
data.device->PSSetSamplers(0, 1, &state->sampler_state);
|
|
||||||
data.device->PSSetShader(state->pixel_shader);
|
|
||||||
data.device->PSSetShaderResources(0, 1, &state->resource);
|
|
||||||
data.device->RSSetState(state->raster_state);
|
|
||||||
data.device->RSSetViewports(state->num_viewports, state->viewports);
|
|
||||||
data.device->SOSetTargets(MAX_SO_TARGETS, state->stream_output_targets,
|
|
||||||
state->so_offsets);
|
|
||||||
data.device->VSSetShader(state->vertex_shader);
|
|
||||||
safe_release(state->geom_shader);
|
|
||||||
safe_release(state->vertex_layout);
|
|
||||||
safe_release(state->vertex_buffer);
|
|
||||||
safe_release(state->blend_state);
|
|
||||||
safe_release(state->zstencil_state);
|
|
||||||
for (size_t i = 0; i < MAX_RENDER_TARGETS; i++)
|
|
||||||
safe_release(state->render_targets[i]);
|
|
||||||
safe_release(state->zstencil_view);
|
|
||||||
safe_release(state->sampler_state);
|
|
||||||
safe_release(state->pixel_shader);
|
|
||||||
safe_release(state->resource);
|
|
||||||
safe_release(state->raster_state);
|
|
||||||
for (size_t i = 0; i < MAX_SO_TARGETS; i++)
|
|
||||||
safe_release(state->stream_output_targets[i]);
|
|
||||||
safe_release(state->vertex_shader);
|
|
||||||
free(state->viewports);
|
|
||||||
memset(state, 0, sizeof(*state));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d10_setup_pipeline(ID3D10RenderTargetView *target,
|
|
||||||
ID3D10ShaderResourceView *resource)
|
|
||||||
{
|
|
||||||
D3D10_VIEWPORT viewport = {0};
|
|
||||||
const float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
||||||
void *emptyptr = nullptr;
|
|
||||||
UINT stride = sizeof(vertex);
|
|
||||||
UINT zero = 0;
|
|
||||||
|
|
||||||
viewport.Width = data.cx;
|
|
||||||
viewport.Height = data.cy;
|
|
||||||
viewport.MaxDepth = 1.0f;
|
|
||||||
|
|
||||||
data.device->GSSetShader(nullptr);
|
|
||||||
data.device->IASetInputLayout(data.vertex_layout);
|
|
||||||
data.device->IASetPrimitiveTopology(
|
|
||||||
D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
||||||
data.device->IASetVertexBuffers(0, 1, &data.vertex_buffer, &stride,
|
|
||||||
&zero);
|
|
||||||
data.device->OMSetBlendState(data.blend_state, factor, 0xFFFFFFFF);
|
|
||||||
data.device->OMSetDepthStencilState(data.zstencil_state, 0);
|
|
||||||
data.device->OMSetRenderTargets(1, &target, nullptr);
|
|
||||||
data.device->PSSetSamplers(0, 1, &data.sampler_state);
|
|
||||||
data.device->PSSetShader(data.pixel_shader);
|
|
||||||
data.device->PSSetShaderResources(0, 1, &resource);
|
|
||||||
data.device->RSSetState(data.raster_state);
|
|
||||||
data.device->RSSetViewports(1, &viewport);
|
|
||||||
data.device->SOSetTargets(1, (ID3D10Buffer **)&emptyptr, &zero);
|
|
||||||
data.device->VSSetShader(data.vertex_shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d10_scale_texture(ID3D10RenderTargetView *target,
|
|
||||||
ID3D10ShaderResourceView *resource)
|
|
||||||
{
|
|
||||||
struct d3d10_state old_state = {};
|
|
||||||
|
|
||||||
d3d10_save_state(&old_state);
|
|
||||||
d3d10_setup_pipeline(target, resource);
|
|
||||||
data.device->Draw(4, 0);
|
|
||||||
d3d10_restore_state(&old_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d10_copy_texture(ID3D10Resource *dst, ID3D10Resource *src)
|
static inline void d3d10_copy_texture(ID3D10Resource *dst, ID3D10Resource *src)
|
||||||
{
|
{
|
||||||
if (data.multisampled) {
|
if (data.multisampled) {
|
||||||
|
@ -716,30 +330,21 @@ static inline void d3d10_copy_texture(ID3D10Resource *dst, ID3D10Resource *src)
|
||||||
|
|
||||||
static inline void d3d10_shtex_capture(ID3D10Resource *backbuffer)
|
static inline void d3d10_shtex_capture(ID3D10Resource *backbuffer)
|
||||||
{
|
{
|
||||||
if (data.using_scale) {
|
d3d10_copy_texture(data.texture, backbuffer);
|
||||||
d3d10_copy_texture(data.scale_tex, backbuffer);
|
|
||||||
d3d10_scale_texture(data.render_target, data.scale_resource);
|
|
||||||
} else {
|
|
||||||
d3d10_copy_texture(data.texture, backbuffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void d3d10_shmem_queue_copy()
|
static void d3d10_shmem_capture_copy(int i)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < NUM_BUFFERS; i++) {
|
D3D10_MAPPED_TEXTURE2D map;
|
||||||
D3D10_MAPPED_TEXTURE2D map;
|
HRESULT hr;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (data.texture_ready[i]) {
|
if (data.texture_ready[i]) {
|
||||||
data.texture_ready[i] = false;
|
data.texture_ready[i] = false;
|
||||||
|
|
||||||
hr = data.copy_surfaces[i]->Map(0, D3D10_MAP_READ, 0,
|
hr = data.copy_surfaces[i]->Map(0, D3D10_MAP_READ, 0, &map);
|
||||||
&map);
|
if (SUCCEEDED(hr)) {
|
||||||
if (SUCCEEDED(hr)) {
|
data.texture_mapped[i] = true;
|
||||||
data.texture_mapped[i] = true;
|
shmem_copy_data(i, map.pData);
|
||||||
shmem_copy_data(i, map.pData);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,32 +353,21 @@ static inline void d3d10_shmem_capture(ID3D10Resource *backbuffer)
|
||||||
{
|
{
|
||||||
int next_tex;
|
int next_tex;
|
||||||
|
|
||||||
d3d10_shmem_queue_copy();
|
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
|
||||||
|
d3d10_shmem_capture_copy(next_tex);
|
||||||
next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
|
|
||||||
|
|
||||||
if (data.using_scale) {
|
|
||||||
d3d10_copy_texture(data.scale_tex, backbuffer);
|
|
||||||
d3d10_scale_texture(data.render_targets[data.cur_tex],
|
|
||||||
data.scale_resource);
|
|
||||||
} else {
|
|
||||||
d3d10_copy_texture(data.textures[data.cur_tex], backbuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.copy_wait < NUM_BUFFERS - 1) {
|
if (data.copy_wait < NUM_BUFFERS - 1) {
|
||||||
data.copy_wait++;
|
data.copy_wait++;
|
||||||
} else {
|
} else {
|
||||||
ID3D10Texture2D *src = data.textures[next_tex];
|
if (shmem_texture_data_lock(data.cur_tex)) {
|
||||||
ID3D10Texture2D *dst = data.copy_surfaces[next_tex];
|
data.copy_surfaces[data.cur_tex]->Unmap(0);
|
||||||
|
data.texture_mapped[data.cur_tex] = false;
|
||||||
if (shmem_texture_data_lock(next_tex)) {
|
shmem_texture_data_unlock(data.cur_tex);
|
||||||
dst->Unmap(0);
|
|
||||||
data.texture_mapped[next_tex] = false;
|
|
||||||
shmem_texture_data_unlock(next_tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d3d10_copy_texture(dst, src);
|
d3d10_copy_texture(data.copy_surfaces[data.cur_tex],
|
||||||
data.texture_ready[next_tex] = true;
|
backbuffer);
|
||||||
|
data.texture_ready[data.cur_tex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.cur_tex = next_tex;
|
data.cur_tex = next_tex;
|
||||||
|
|
|
@ -8,13 +8,10 @@
|
||||||
struct d3d11_data {
|
struct d3d11_data {
|
||||||
ID3D11Device *device; /* do not release */
|
ID3D11Device *device; /* do not release */
|
||||||
ID3D11DeviceContext *context; /* do not release */
|
ID3D11DeviceContext *context; /* do not release */
|
||||||
uint32_t base_cx;
|
|
||||||
uint32_t base_cy;
|
|
||||||
uint32_t cx;
|
uint32_t cx;
|
||||||
uint32_t cy;
|
uint32_t cy;
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
bool using_shtex;
|
bool using_shtex;
|
||||||
bool using_scale;
|
|
||||||
bool multisampled;
|
bool multisampled;
|
||||||
|
|
||||||
ID3D11Texture2D *scale_tex;
|
ID3D11Texture2D *scale_tex;
|
||||||
|
@ -42,8 +39,6 @@ struct d3d11_data {
|
||||||
/* shared memory */
|
/* shared memory */
|
||||||
struct {
|
struct {
|
||||||
ID3D11Texture2D *copy_surfaces[NUM_BUFFERS];
|
ID3D11Texture2D *copy_surfaces[NUM_BUFFERS];
|
||||||
ID3D11Texture2D *textures[NUM_BUFFERS];
|
|
||||||
ID3D11RenderTargetView *render_targets[NUM_BUFFERS];
|
|
||||||
bool texture_ready[NUM_BUFFERS];
|
bool texture_ready[NUM_BUFFERS];
|
||||||
bool texture_mapped[NUM_BUFFERS];
|
bool texture_mapped[NUM_BUFFERS];
|
||||||
uint32_t pitch;
|
uint32_t pitch;
|
||||||
|
@ -94,10 +89,6 @@ void d3d11_free(void)
|
||||||
data.copy_surfaces[i], 0);
|
data.copy_surfaces[i], 0);
|
||||||
data.copy_surfaces[i]->Release();
|
data.copy_surfaces[i]->Release();
|
||||||
}
|
}
|
||||||
if (data.textures[i])
|
|
||||||
data.textures[i]->Release();
|
|
||||||
if (data.render_targets[i])
|
|
||||||
data.render_targets[i]->Release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,220 +218,8 @@ static inline bool d3d11_init_format(IDXGISwapChain *swap, HWND &window)
|
||||||
data.format = fix_dxgi_format(desc.BufferDesc.Format);
|
data.format = fix_dxgi_format(desc.BufferDesc.Format);
|
||||||
data.multisampled = desc.SampleDesc.Count > 1;
|
data.multisampled = desc.SampleDesc.Count > 1;
|
||||||
window = desc.OutputWindow;
|
window = desc.OutputWindow;
|
||||||
data.base_cx = desc.BufferDesc.Width;
|
data.cx = desc.BufferDesc.Width;
|
||||||
data.base_cy = desc.BufferDesc.Height;
|
data.cy = desc.BufferDesc.Height;
|
||||||
|
|
||||||
if (data.using_scale) {
|
|
||||||
data.cx = global_hook_info->cx;
|
|
||||||
data.cy = global_hook_info->cy;
|
|
||||||
} else {
|
|
||||||
data.cx = desc.BufferDesc.Width;
|
|
||||||
data.cy = desc.BufferDesc.Height;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d11_init_vertex_shader(void)
|
|
||||||
{
|
|
||||||
D3D11_INPUT_ELEMENT_DESC desc[2];
|
|
||||||
uint8_t *vs_data;
|
|
||||||
size_t size;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
vs_data = get_d3d1x_vertex_shader(&size);
|
|
||||||
|
|
||||||
hr = data.device->CreateVertexShader(vs_data, size, nullptr,
|
|
||||||
&data.vertex_shader);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_vertex_shader: failed to create shader",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc[0].SemanticName = "SV_Position";
|
|
||||||
desc[0].SemanticIndex = 0;
|
|
||||||
desc[0].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
|
||||||
desc[0].InputSlot = 0;
|
|
||||||
desc[0].AlignedByteOffset = 0;
|
|
||||||
desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
|
||||||
desc[0].InstanceDataStepRate = 0;
|
|
||||||
|
|
||||||
desc[1].SemanticName = "TEXCOORD";
|
|
||||||
desc[1].SemanticIndex = 0;
|
|
||||||
desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
|
|
||||||
desc[1].InputSlot = 0;
|
|
||||||
desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
|
|
||||||
desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
|
||||||
desc[1].InstanceDataStepRate = 0;
|
|
||||||
|
|
||||||
hr = data.device->CreateInputLayout(desc, 2, vs_data, size,
|
|
||||||
&data.vertex_layout);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_vertex_shader: failed to create layout",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d11_init_pixel_shader(void)
|
|
||||||
{
|
|
||||||
uint8_t *ps_data;
|
|
||||||
size_t size;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
ps_data = get_d3d1x_pixel_shader(&size);
|
|
||||||
|
|
||||||
hr = data.device->CreatePixelShader(ps_data, size, nullptr,
|
|
||||||
&data.pixel_shader);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_pixel_shader: failed to create shader", hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d11_init_sampler_state(void)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
D3D11_SAMPLER_DESC desc = {};
|
|
||||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
||||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
||||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
||||||
|
|
||||||
hr = data.device->CreateSamplerState(&desc, &data.sampler_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_sampler_state: failed to create sampler "
|
|
||||||
"state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d11_init_blend_state(void)
|
|
||||||
{
|
|
||||||
D3D11_BLEND_DESC desc = {};
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; i++)
|
|
||||||
desc.RenderTarget[i].RenderTargetWriteMask =
|
|
||||||
D3D11_COLOR_WRITE_ENABLE_ALL;
|
|
||||||
|
|
||||||
hr = data.device->CreateBlendState(&desc, &data.blend_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_blend_state: failed to create blend state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d11_init_zstencil_state(void)
|
|
||||||
{
|
|
||||||
D3D11_DEPTH_STENCIL_DESC desc = {}; /* defaults all to off */
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
hr = data.device->CreateDepthStencilState(&desc, &data.zstencil_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_zstencil_state: failed to create "
|
|
||||||
"zstencil state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool d3d11_init_raster_state(void)
|
|
||||||
{
|
|
||||||
D3D11_RASTERIZER_DESC desc = {};
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
desc.FillMode = D3D11_FILL_SOLID;
|
|
||||||
desc.CullMode = D3D11_CULL_NONE;
|
|
||||||
|
|
||||||
hr = data.device->CreateRasterizerState(&desc, &data.raster_state);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_raster_state: failed to create raster "
|
|
||||||
"state",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUM_VERTS 4
|
|
||||||
|
|
||||||
static inline bool d3d11_init_vertex_buffer(void)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
const vertex verts[NUM_VERTS] = {
|
|
||||||
{{-1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
|
|
||||||
{{-1.0f, -1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
|
|
||||||
{{1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
|
|
||||||
{{1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}};
|
|
||||||
|
|
||||||
D3D11_BUFFER_DESC desc;
|
|
||||||
desc.ByteWidth = sizeof(vertex) * NUM_VERTS;
|
|
||||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
|
||||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
|
||||||
desc.CPUAccessFlags = 0;
|
|
||||||
desc.MiscFlags = 0;
|
|
||||||
|
|
||||||
D3D11_SUBRESOURCE_DATA srd = {};
|
|
||||||
srd.pSysMem = (const void *)verts;
|
|
||||||
|
|
||||||
hr = data.device->CreateBuffer(&desc, &srd, &data.vertex_buffer);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d11_init_vertex_buffer: failed to create vertex "
|
|
||||||
"buffer",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool d3d11_init_scaling(void)
|
|
||||||
{
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
success = create_d3d11_tex(data.base_cx, data.base_cy, &data.scale_tex,
|
|
||||||
&data.scale_resource, nullptr, nullptr);
|
|
||||||
if (!success) {
|
|
||||||
hlog("d3d11_init_scaling: failed to create scale texture");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!d3d11_init_vertex_shader()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d11_init_pixel_shader()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d11_init_sampler_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d11_init_blend_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d11_init_zstencil_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d11_init_raster_state()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!d3d11_init_vertex_buffer()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -472,13 +251,6 @@ static bool d3d11_shmem_init_buffers(size_t idx)
|
||||||
data.context->Unmap(data.copy_surfaces[idx], 0);
|
data.context->Unmap(data.copy_surfaces[idx], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = create_d3d11_tex(data.cx, data.cy, &data.textures[idx],
|
|
||||||
nullptr, &data.render_targets[idx], nullptr);
|
|
||||||
if (!success) {
|
|
||||||
hlog("d3d11_shmem_init_buffers: failed to create texture");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,9 +263,8 @@ static bool d3d11_shmem_init(HWND window)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!capture_init_shmem(&data.shmem_info, window, data.base_cx,
|
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.pitch,
|
data.pitch, data.format, false)) {
|
||||||
data.format, false)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,9 +288,8 @@ static bool d3d11_shtex_init(HWND window)
|
||||||
hlog("d3d11_shtex_init: failed to create texture");
|
hlog("d3d11_shtex_init: failed to create texture");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
|
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.format,
|
data.format, false, (uintptr_t)data.handle)) {
|
||||||
false, (uintptr_t)data.handle)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,12 +299,9 @@ static bool d3d11_shtex_init(HWND window)
|
||||||
|
|
||||||
static void d3d11_init(IDXGISwapChain *swap)
|
static void d3d11_init(IDXGISwapChain *swap)
|
||||||
{
|
{
|
||||||
bool success = true;
|
|
||||||
HWND window;
|
HWND window;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
data.using_scale = global_hook_info->use_scale;
|
|
||||||
|
|
||||||
hr = swap->GetDevice(__uuidof(ID3D11Device), (void **)&data.device);
|
hr = swap->GetDevice(__uuidof(ID3D11Device), (void **)&data.device);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
hlog_hr("d3d11_init: failed to get device from swap", hr);
|
hlog_hr("d3d11_init: failed to get device from swap", hr);
|
||||||
|
@ -549,201 +316,14 @@ static void d3d11_init(IDXGISwapChain *swap)
|
||||||
if (!d3d11_init_format(swap, window)) {
|
if (!d3d11_init_format(swap, window)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.using_scale && !d3d11_init_scaling()) {
|
|
||||||
hlog("d3d11_init: failed to initialize scaling");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
if (global_hook_info->force_shmem) {
|
|
||||||
success = d3d11_shmem_init(window);
|
|
||||||
} else {
|
|
||||||
success = d3d11_shtex_init(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const bool success = global_hook_info->force_shmem
|
||||||
|
? d3d11_shmem_init(window)
|
||||||
|
: d3d11_shtex_init(window);
|
||||||
if (!success)
|
if (!success)
|
||||||
d3d11_free();
|
d3d11_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_RENDER_TARGETS D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT
|
|
||||||
#define MAX_SO_TARGETS 4
|
|
||||||
#define MAX_CLASS_INSTS 256
|
|
||||||
|
|
||||||
struct d3d11_state {
|
|
||||||
ID3D11GeometryShader *geom_shader;
|
|
||||||
ID3D11InputLayout *vertex_layout;
|
|
||||||
D3D11_PRIMITIVE_TOPOLOGY topology;
|
|
||||||
ID3D11Buffer *vertex_buffer;
|
|
||||||
UINT vb_stride;
|
|
||||||
UINT vb_offset;
|
|
||||||
ID3D11BlendState *blend_state;
|
|
||||||
float blend_factor[4];
|
|
||||||
UINT sample_mask;
|
|
||||||
ID3D11DepthStencilState *zstencil_state;
|
|
||||||
UINT zstencil_ref;
|
|
||||||
ID3D11RenderTargetView *render_targets[MAX_RENDER_TARGETS];
|
|
||||||
ID3D11DepthStencilView *zstencil_view;
|
|
||||||
ID3D11SamplerState *sampler_state;
|
|
||||||
ID3D11PixelShader *pixel_shader;
|
|
||||||
ID3D11ShaderResourceView *resource;
|
|
||||||
ID3D11RasterizerState *raster_state;
|
|
||||||
UINT num_viewports;
|
|
||||||
D3D11_VIEWPORT *viewports;
|
|
||||||
ID3D11Buffer *stream_output_targets[MAX_SO_TARGETS];
|
|
||||||
ID3D11VertexShader *vertex_shader;
|
|
||||||
ID3D11ClassInstance *gs_class_instances[MAX_CLASS_INSTS];
|
|
||||||
ID3D11ClassInstance *ps_class_instances[MAX_CLASS_INSTS];
|
|
||||||
ID3D11ClassInstance *vs_class_instances[MAX_CLASS_INSTS];
|
|
||||||
UINT gs_class_inst_count;
|
|
||||||
UINT ps_class_inst_count;
|
|
||||||
UINT vs_class_inst_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void d3d11_save_state(struct d3d11_state *state)
|
|
||||||
{
|
|
||||||
state->gs_class_inst_count = MAX_CLASS_INSTS;
|
|
||||||
state->ps_class_inst_count = MAX_CLASS_INSTS;
|
|
||||||
state->vs_class_inst_count = MAX_CLASS_INSTS;
|
|
||||||
|
|
||||||
data.context->GSGetShader(&state->geom_shader,
|
|
||||||
state->gs_class_instances,
|
|
||||||
&state->gs_class_inst_count);
|
|
||||||
data.context->IAGetInputLayout(&state->vertex_layout);
|
|
||||||
data.context->IAGetPrimitiveTopology(&state->topology);
|
|
||||||
data.context->IAGetVertexBuffers(0, 1, &state->vertex_buffer,
|
|
||||||
&state->vb_stride, &state->vb_offset);
|
|
||||||
data.context->OMGetBlendState(&state->blend_state, state->blend_factor,
|
|
||||||
&state->sample_mask);
|
|
||||||
data.context->OMGetDepthStencilState(&state->zstencil_state,
|
|
||||||
&state->zstencil_ref);
|
|
||||||
data.context->OMGetRenderTargets(MAX_RENDER_TARGETS,
|
|
||||||
state->render_targets,
|
|
||||||
&state->zstencil_view);
|
|
||||||
data.context->PSGetSamplers(0, 1, &state->sampler_state);
|
|
||||||
data.context->PSGetShader(&state->pixel_shader,
|
|
||||||
state->ps_class_instances,
|
|
||||||
&state->ps_class_inst_count);
|
|
||||||
data.context->PSGetShaderResources(0, 1, &state->resource);
|
|
||||||
data.context->RSGetState(&state->raster_state);
|
|
||||||
data.context->RSGetViewports(&state->num_viewports, nullptr);
|
|
||||||
if (state->num_viewports) {
|
|
||||||
state->viewports = (D3D11_VIEWPORT *)malloc(
|
|
||||||
sizeof(D3D11_VIEWPORT) * state->num_viewports);
|
|
||||||
data.context->RSGetViewports(&state->num_viewports,
|
|
||||||
state->viewports);
|
|
||||||
}
|
|
||||||
data.context->SOGetTargets(MAX_SO_TARGETS,
|
|
||||||
state->stream_output_targets);
|
|
||||||
data.context->VSGetShader(&state->vertex_shader,
|
|
||||||
state->vs_class_instances,
|
|
||||||
&state->vs_class_inst_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void safe_release(IUnknown *p)
|
|
||||||
{
|
|
||||||
if (p)
|
|
||||||
p->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SO_APPEND ((UINT)-1)
|
|
||||||
|
|
||||||
static inline void d3d11_restore_state(struct d3d11_state *state)
|
|
||||||
{
|
|
||||||
UINT so_offsets[MAX_SO_TARGETS] = {SO_APPEND, SO_APPEND, SO_APPEND,
|
|
||||||
SO_APPEND};
|
|
||||||
|
|
||||||
data.context->GSSetShader(state->geom_shader, state->gs_class_instances,
|
|
||||||
state->gs_class_inst_count);
|
|
||||||
data.context->IASetInputLayout(state->vertex_layout);
|
|
||||||
data.context->IASetPrimitiveTopology(state->topology);
|
|
||||||
data.context->IASetVertexBuffers(0, 1, &state->vertex_buffer,
|
|
||||||
&state->vb_stride, &state->vb_offset);
|
|
||||||
data.context->OMSetBlendState(state->blend_state, state->blend_factor,
|
|
||||||
state->sample_mask);
|
|
||||||
data.context->OMSetDepthStencilState(state->zstencil_state,
|
|
||||||
state->zstencil_ref);
|
|
||||||
data.context->OMSetRenderTargets(MAX_RENDER_TARGETS,
|
|
||||||
state->render_targets,
|
|
||||||
state->zstencil_view);
|
|
||||||
data.context->PSSetSamplers(0, 1, &state->sampler_state);
|
|
||||||
data.context->PSSetShader(state->pixel_shader,
|
|
||||||
state->ps_class_instances,
|
|
||||||
state->ps_class_inst_count);
|
|
||||||
data.context->PSSetShaderResources(0, 1, &state->resource);
|
|
||||||
data.context->RSSetState(state->raster_state);
|
|
||||||
data.context->RSSetViewports(state->num_viewports, state->viewports);
|
|
||||||
data.context->SOSetTargets(MAX_SO_TARGETS, state->stream_output_targets,
|
|
||||||
so_offsets);
|
|
||||||
data.context->VSSetShader(state->vertex_shader,
|
|
||||||
state->vs_class_instances,
|
|
||||||
state->vs_class_inst_count);
|
|
||||||
safe_release(state->geom_shader);
|
|
||||||
safe_release(state->vertex_layout);
|
|
||||||
safe_release(state->vertex_buffer);
|
|
||||||
safe_release(state->blend_state);
|
|
||||||
safe_release(state->zstencil_state);
|
|
||||||
for (size_t i = 0; i < MAX_RENDER_TARGETS; i++)
|
|
||||||
safe_release(state->render_targets[i]);
|
|
||||||
safe_release(state->zstencil_view);
|
|
||||||
safe_release(state->sampler_state);
|
|
||||||
safe_release(state->pixel_shader);
|
|
||||||
safe_release(state->resource);
|
|
||||||
safe_release(state->raster_state);
|
|
||||||
for (size_t i = 0; i < MAX_SO_TARGETS; i++)
|
|
||||||
safe_release(state->stream_output_targets[i]);
|
|
||||||
safe_release(state->vertex_shader);
|
|
||||||
for (size_t i = 0; i < state->gs_class_inst_count; i++)
|
|
||||||
state->gs_class_instances[i]->Release();
|
|
||||||
for (size_t i = 0; i < state->ps_class_inst_count; i++)
|
|
||||||
state->ps_class_instances[i]->Release();
|
|
||||||
for (size_t i = 0; i < state->vs_class_inst_count; i++)
|
|
||||||
state->vs_class_instances[i]->Release();
|
|
||||||
free(state->viewports);
|
|
||||||
memset(state, 0, sizeof(*state));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d11_setup_pipeline(ID3D11RenderTargetView *target,
|
|
||||||
ID3D11ShaderResourceView *resource)
|
|
||||||
{
|
|
||||||
const float factor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
||||||
D3D11_VIEWPORT viewport = {0};
|
|
||||||
UINT stride = sizeof(vertex);
|
|
||||||
void *emptyptr = nullptr;
|
|
||||||
UINT zero = 0;
|
|
||||||
|
|
||||||
viewport.Width = (float)data.cx;
|
|
||||||
viewport.Height = (float)data.cy;
|
|
||||||
viewport.MaxDepth = 1.0f;
|
|
||||||
|
|
||||||
data.context->GSSetShader(nullptr, nullptr, 0);
|
|
||||||
data.context->IASetInputLayout(data.vertex_layout);
|
|
||||||
data.context->IASetPrimitiveTopology(
|
|
||||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
||||||
data.context->IASetVertexBuffers(0, 1, &data.vertex_buffer, &stride,
|
|
||||||
&zero);
|
|
||||||
data.context->OMSetBlendState(data.blend_state, factor, 0xFFFFFFFF);
|
|
||||||
data.context->OMSetDepthStencilState(data.zstencil_state, 0);
|
|
||||||
data.context->OMSetRenderTargets(1, &target, nullptr);
|
|
||||||
data.context->PSSetSamplers(0, 1, &data.sampler_state);
|
|
||||||
data.context->PSSetShader(data.pixel_shader, nullptr, 0);
|
|
||||||
data.context->PSSetShaderResources(0, 1, &resource);
|
|
||||||
data.context->RSSetState(data.raster_state);
|
|
||||||
data.context->RSSetViewports(1, &viewport);
|
|
||||||
data.context->SOSetTargets(1, (ID3D11Buffer **)&emptyptr, &zero);
|
|
||||||
data.context->VSSetShader(data.vertex_shader, nullptr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d11_scale_texture(ID3D11RenderTargetView *target,
|
|
||||||
ID3D11ShaderResourceView *resource)
|
|
||||||
{
|
|
||||||
static struct d3d11_state old_state = {0};
|
|
||||||
|
|
||||||
d3d11_save_state(&old_state);
|
|
||||||
d3d11_setup_pipeline(target, resource);
|
|
||||||
data.context->Draw(4, 0);
|
|
||||||
d3d11_restore_state(&old_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void d3d11_copy_texture(ID3D11Resource *dst, ID3D11Resource *src)
|
static inline void d3d11_copy_texture(ID3D11Resource *dst, ID3D11Resource *src)
|
||||||
{
|
{
|
||||||
if (data.multisampled) {
|
if (data.multisampled) {
|
||||||
|
@ -755,30 +335,22 @@ static inline void d3d11_copy_texture(ID3D11Resource *dst, ID3D11Resource *src)
|
||||||
|
|
||||||
static inline void d3d11_shtex_capture(ID3D11Resource *backbuffer)
|
static inline void d3d11_shtex_capture(ID3D11Resource *backbuffer)
|
||||||
{
|
{
|
||||||
if (data.using_scale) {
|
d3d11_copy_texture(data.texture, backbuffer);
|
||||||
d3d11_copy_texture(data.scale_tex, backbuffer);
|
|
||||||
d3d11_scale_texture(data.render_target, data.scale_resource);
|
|
||||||
} else {
|
|
||||||
d3d11_copy_texture(data.texture, backbuffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void d3d11_shmem_queue_copy()
|
static void d3d11_shmem_capture_copy(int i)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < NUM_BUFFERS; i++) {
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
D3D11_MAPPED_SUBRESOURCE map;
|
HRESULT hr;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (data.texture_ready[i]) {
|
if (data.texture_ready[i]) {
|
||||||
data.texture_ready[i] = false;
|
data.texture_ready[i] = false;
|
||||||
|
|
||||||
hr = data.context->Map(data.copy_surfaces[i], 0,
|
hr = data.context->Map(data.copy_surfaces[i], 0, D3D11_MAP_READ,
|
||||||
D3D11_MAP_READ, 0, &map);
|
0, &map);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
data.texture_mapped[i] = true;
|
data.texture_mapped[i] = true;
|
||||||
shmem_copy_data(i, map.pData);
|
shmem_copy_data(i, map.pData);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -787,32 +359,22 @@ static inline void d3d11_shmem_capture(ID3D11Resource *backbuffer)
|
||||||
{
|
{
|
||||||
int next_tex;
|
int next_tex;
|
||||||
|
|
||||||
d3d11_shmem_queue_copy();
|
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
|
||||||
|
d3d11_shmem_capture_copy(next_tex);
|
||||||
next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
|
|
||||||
|
|
||||||
if (data.using_scale) {
|
|
||||||
d3d11_copy_texture(data.scale_tex, backbuffer);
|
|
||||||
d3d11_scale_texture(data.render_targets[data.cur_tex],
|
|
||||||
data.scale_resource);
|
|
||||||
} else {
|
|
||||||
d3d11_copy_texture(data.textures[data.cur_tex], backbuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.copy_wait < NUM_BUFFERS - 1) {
|
if (data.copy_wait < NUM_BUFFERS - 1) {
|
||||||
data.copy_wait++;
|
data.copy_wait++;
|
||||||
} else {
|
} else {
|
||||||
ID3D11Texture2D *src = data.textures[next_tex];
|
if (shmem_texture_data_lock(data.cur_tex)) {
|
||||||
ID3D11Texture2D *dst = data.copy_surfaces[next_tex];
|
data.context->Unmap(data.copy_surfaces[data.cur_tex],
|
||||||
|
0);
|
||||||
if (shmem_texture_data_lock(next_tex)) {
|
data.texture_mapped[data.cur_tex] = false;
|
||||||
data.context->Unmap(dst, 0);
|
shmem_texture_data_unlock(data.cur_tex);
|
||||||
data.texture_mapped[next_tex] = false;
|
|
||||||
shmem_texture_data_unlock(next_tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d3d11_copy_texture(dst, src);
|
d3d11_copy_texture(data.copy_surfaces[data.cur_tex],
|
||||||
data.texture_ready[next_tex] = true;
|
backbuffer);
|
||||||
|
data.texture_ready[data.cur_tex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.cur_tex = next_tex;
|
data.cur_tex = next_tex;
|
||||||
|
|
|
@ -14,13 +14,10 @@
|
||||||
|
|
||||||
struct d3d12_data {
|
struct d3d12_data {
|
||||||
ID3D12Device *device; /* do not release */
|
ID3D12Device *device; /* do not release */
|
||||||
uint32_t base_cx;
|
|
||||||
uint32_t base_cy;
|
|
||||||
uint32_t cx;
|
uint32_t cx;
|
||||||
uint32_t cy;
|
uint32_t cy;
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
bool using_shtex;
|
bool using_shtex;
|
||||||
bool using_scale;
|
|
||||||
bool multisampled;
|
bool multisampled;
|
||||||
bool dxgi_1_4;
|
bool dxgi_1_4;
|
||||||
|
|
||||||
|
@ -197,9 +194,8 @@ static bool d3d12_shtex_init(HWND window, bb_info &bb)
|
||||||
if (!create_d3d12_tex(bb)) {
|
if (!create_d3d12_tex(bb)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
|
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.format,
|
data.format, false, (uintptr_t)data.handle)) {
|
||||||
false, (uintptr_t)data.handle)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +219,8 @@ static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window,
|
||||||
data.format = fix_dxgi_format(desc.BufferDesc.Format);
|
data.format = fix_dxgi_format(desc.BufferDesc.Format);
|
||||||
data.multisampled = desc.SampleDesc.Count > 1;
|
data.multisampled = desc.SampleDesc.Count > 1;
|
||||||
window = desc.OutputWindow;
|
window = desc.OutputWindow;
|
||||||
data.base_cx = desc.BufferDesc.Width;
|
data.cx = desc.BufferDesc.Width;
|
||||||
data.base_cy = desc.BufferDesc.Height;
|
data.cy = desc.BufferDesc.Height;
|
||||||
|
|
||||||
hr = swap->QueryInterface(__uuidof(IDXGISwapChain3), (void **)&swap3);
|
hr = swap->QueryInterface(__uuidof(IDXGISwapChain3), (void **)&swap3);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
|
@ -260,25 +256,15 @@ static inline bool d3d12_init_format(IDXGISwapChain *swap, HWND &window,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.using_scale) {
|
|
||||||
data.cx = global_hook_info->cx;
|
|
||||||
data.cy = global_hook_info->cy;
|
|
||||||
} else {
|
|
||||||
data.cx = desc.BufferDesc.Width;
|
|
||||||
data.cy = desc.BufferDesc.Height;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d3d12_init(IDXGISwapChain *swap)
|
static void d3d12_init(IDXGISwapChain *swap)
|
||||||
{
|
{
|
||||||
bool success = true;
|
|
||||||
bb_info bb = {};
|
bb_info bb = {};
|
||||||
HWND window;
|
HWND window;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
data.using_scale = global_hook_info->use_scale;
|
|
||||||
|
|
||||||
hr = swap->GetDevice(__uuidof(ID3D12Device), (void **)&data.device);
|
hr = swap->GetDevice(__uuidof(ID3D12Device), (void **)&data.device);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
hlog_hr("d3d12_init: failed to get device from swap", hr);
|
hlog_hr("d3d12_init: failed to get device from swap", hr);
|
||||||
|
@ -290,19 +276,13 @@ static void d3d12_init(IDXGISwapChain *swap)
|
||||||
if (!d3d12_init_format(swap, window, bb)) {
|
if (!d3d12_init_format(swap, window, bb)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.using_scale) {
|
|
||||||
hlog("d3d12_init: scaling currently unsupported; ignoring");
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
if (global_hook_info->force_shmem) {
|
|
||||||
hlog("d3d12_init: shared memory capture currently "
|
|
||||||
"unsupported; ignoring");
|
|
||||||
}
|
|
||||||
|
|
||||||
success = d3d12_shtex_init(window, bb);
|
if (global_hook_info->force_shmem) {
|
||||||
|
hlog("d3d12_init: shared memory capture currently "
|
||||||
|
"unsupported; ignoring");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!d3d12_shtex_init(window, bb))
|
||||||
d3d12_free();
|
d3d12_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
static const char vertex_shader_string[] = "struct VertData \
|
|
||||||
{ \
|
|
||||||
float4 pos : SV_Position; \
|
|
||||||
float2 texCoord : TexCoord0; \
|
|
||||||
}; \
|
|
||||||
VertData main(VertData input) \
|
|
||||||
{ \
|
|
||||||
VertData output; \
|
|
||||||
output.pos = input.pos; \
|
|
||||||
output.texCoord = input.texCoord; \
|
|
||||||
return output; \
|
|
||||||
}";
|
|
||||||
|
|
||||||
static const char pixel_shader_string[] = "uniform Texture2D diffuseTexture; \
|
|
||||||
SamplerState textureSampler \
|
|
||||||
{ \
|
|
||||||
AddressU = Clamp; \
|
|
||||||
AddressV = Clamp; \
|
|
||||||
Filter = Linear; \
|
|
||||||
}; \
|
|
||||||
struct VertData \
|
|
||||||
{ \
|
|
||||||
float4 pos : SV_Position; \
|
|
||||||
float2 texCoord : TexCoord0; \
|
|
||||||
}; \
|
|
||||||
float4 main(VertData input) : SV_Target \
|
|
||||||
{ \
|
|
||||||
return diffuseTexture.Sample(textureSampler, input.texCoord); \
|
|
||||||
}";
|
|
|
@ -24,6 +24,7 @@ struct d3d8_data {
|
||||||
HWND window;
|
HWND window;
|
||||||
uint32_t pitch;
|
uint32_t pitch;
|
||||||
IDirect3DSurface8 *copy_surfaces[NUM_BUFFERS];
|
IDirect3DSurface8 *copy_surfaces[NUM_BUFFERS];
|
||||||
|
bool texture_ready[NUM_BUFFERS];
|
||||||
bool surface_locked[NUM_BUFFERS];
|
bool surface_locked[NUM_BUFFERS];
|
||||||
int cur_surface;
|
int cur_surface;
|
||||||
int copy_wait;
|
int copy_wait;
|
||||||
|
@ -145,8 +146,7 @@ static bool d3d8_shmem_init(IDirect3DDevice8 *device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!capture_init_shmem(&data.shmem_info, data.window, data.cx, data.cy,
|
if (!capture_init_shmem(&data.shmem_info, data.window, data.cx, data.cy,
|
||||||
data.cx, data.cy, data.pitch, data.dxgi_format,
|
data.pitch, data.dxgi_format, false)) {
|
||||||
false)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,45 +184,50 @@ static void d3d8_init(IDirect3DDevice8 *device)
|
||||||
|
|
||||||
static void d3d8_shmem_capture_copy(int idx)
|
static void d3d8_shmem_capture_copy(int idx)
|
||||||
{
|
{
|
||||||
IDirect3DSurface8 *target = data.copy_surfaces[idx];
|
|
||||||
D3DLOCKED_RECT rect;
|
D3DLOCKED_RECT rect;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (data.surface_locked[idx])
|
if (data.texture_ready[idx]) {
|
||||||
return;
|
data.texture_ready[idx] = false;
|
||||||
|
|
||||||
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
|
IDirect3DSurface8 *target = data.copy_surfaces[idx];
|
||||||
if (SUCCEEDED(hr)) {
|
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
|
||||||
shmem_copy_data(idx, rect.pBits);
|
if (SUCCEEDED(hr)) {
|
||||||
|
data.surface_locked[idx] = true;
|
||||||
|
shmem_copy_data(idx, rect.pBits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d3d8_shmem_capture(IDirect3DDevice8 *device,
|
static void d3d8_shmem_capture(IDirect3DDevice8 *device,
|
||||||
IDirect3DSurface8 *backbuffer)
|
IDirect3DSurface8 *backbuffer)
|
||||||
{
|
{
|
||||||
int cur_surface;
|
|
||||||
int next_surface;
|
int next_surface;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
cur_surface = data.cur_surface;
|
next_surface = (data.cur_surface + 1) % NUM_BUFFERS;
|
||||||
next_surface = (cur_surface == NUM_BUFFERS - 1) ? 0 : cur_surface + 1;
|
d3d8_shmem_capture_copy(next_surface);
|
||||||
|
|
||||||
if (data.copy_wait < NUM_BUFFERS - 1) {
|
if (data.copy_wait < NUM_BUFFERS - 1) {
|
||||||
data.copy_wait++;
|
data.copy_wait++;
|
||||||
} else {
|
} else {
|
||||||
IDirect3DSurface8 *src = backbuffer;
|
IDirect3DSurface8 *src = backbuffer;
|
||||||
IDirect3DSurface8 *dst = data.copy_surfaces[cur_surface];
|
IDirect3DSurface8 *dst = data.copy_surfaces[data.cur_surface];
|
||||||
|
|
||||||
if (shmem_texture_data_lock(next_surface)) {
|
if (shmem_texture_data_lock(data.cur_surface)) {
|
||||||
dst->UnlockRect();
|
dst->UnlockRect();
|
||||||
data.surface_locked[next_surface] = false;
|
data.surface_locked[data.cur_surface] = false;
|
||||||
shmem_texture_data_unlock(next_surface);
|
shmem_texture_data_unlock(data.cur_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = device->CopyRects(src, nullptr, 0, dst, nullptr);
|
hr = device->CopyRects(src, nullptr, 0, dst, nullptr);
|
||||||
if (SUCCEEDED(hr)) {
|
if (FAILED(hr)) {
|
||||||
d3d8_shmem_capture_copy(cur_surface);
|
hlog_hr("d3d8_shmem_capture: CopyRects "
|
||||||
|
"failed",
|
||||||
|
hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.texture_ready[data.cur_surface] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.cur_surface = next_surface;
|
data.cur_surface = next_surface;
|
||||||
|
|
|
@ -38,7 +38,6 @@ struct d3d9_data {
|
||||||
D3DFORMAT d3d9_format;
|
D3DFORMAT d3d9_format;
|
||||||
DXGI_FORMAT dxgi_format;
|
DXGI_FORMAT dxgi_format;
|
||||||
bool using_shtex;
|
bool using_shtex;
|
||||||
bool using_scale;
|
|
||||||
|
|
||||||
/* shared texture */
|
/* shared texture */
|
||||||
IDirect3DSurface9 *d3d9_copytex;
|
IDirect3DSurface9 *d3d9_copytex;
|
||||||
|
@ -51,7 +50,6 @@ struct d3d9_data {
|
||||||
|
|
||||||
/* shared memory */
|
/* shared memory */
|
||||||
IDirect3DSurface9 *copy_surfaces[NUM_BUFFERS];
|
IDirect3DSurface9 *copy_surfaces[NUM_BUFFERS];
|
||||||
IDirect3DSurface9 *render_targets[NUM_BUFFERS];
|
|
||||||
IDirect3DQuery9 *queries[NUM_BUFFERS];
|
IDirect3DQuery9 *queries[NUM_BUFFERS];
|
||||||
struct shmem_data *shmem_info;
|
struct shmem_data *shmem_info;
|
||||||
bool texture_mapped[NUM_BUFFERS];
|
bool texture_mapped[NUM_BUFFERS];
|
||||||
|
@ -83,8 +81,6 @@ static void d3d9_free()
|
||||||
data.copy_surfaces[i]->UnlockRect();
|
data.copy_surfaces[i]->UnlockRect();
|
||||||
data.copy_surfaces[i]->Release();
|
data.copy_surfaces[i]->Release();
|
||||||
}
|
}
|
||||||
if (data.render_targets[i])
|
|
||||||
data.render_targets[i]->Release();
|
|
||||||
if (data.queries[i])
|
if (data.queries[i])
|
||||||
data.queries[i]->Release();
|
data.queries[i]->Release();
|
||||||
}
|
}
|
||||||
|
@ -289,7 +285,7 @@ static inline bool d3d9_shtex_init_copytex()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d3d9_shtex_init(uint32_t cx, uint32_t cy, HWND window)
|
static bool d3d9_shtex_init(HWND window)
|
||||||
{
|
{
|
||||||
data.using_shtex = true;
|
data.using_shtex = true;
|
||||||
|
|
||||||
|
@ -302,8 +298,8 @@ static bool d3d9_shtex_init(uint32_t cx, uint32_t cy, HWND window)
|
||||||
if (!d3d9_shtex_init_copytex()) {
|
if (!d3d9_shtex_init_copytex()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!capture_init_shtex(&data.shtex_info, window, cx, cy, data.cx,
|
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
|
||||||
data.cy, data.dxgi_format, false,
|
data.dxgi_format, false,
|
||||||
(uintptr_t)data.handle)) {
|
(uintptr_t)data.handle)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -340,17 +336,6 @@ static bool d3d9_shmem_init_buffers(size_t buffer)
|
||||||
data.copy_surfaces[buffer]->UnlockRect();
|
data.copy_surfaces[buffer]->UnlockRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = data.device->CreateRenderTarget(data.cx, data.cy, data.d3d9_format,
|
|
||||||
D3DMULTISAMPLE_NONE, 0, false,
|
|
||||||
&data.render_targets[buffer],
|
|
||||||
nullptr);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d9_shmem_init_buffers: Failed to create render "
|
|
||||||
"target",
|
|
||||||
hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = data.device->CreateQuery(D3DQUERYTYPE_EVENT,
|
hr = data.device->CreateQuery(D3DQUERYTYPE_EVENT,
|
||||||
&data.queries[buffer]);
|
&data.queries[buffer]);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -361,7 +346,7 @@ static bool d3d9_shmem_init_buffers(size_t buffer)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d3d9_shmem_init(uint32_t cx, uint32_t cy, HWND window)
|
static bool d3d9_shmem_init(HWND window)
|
||||||
{
|
{
|
||||||
data.using_shtex = false;
|
data.using_shtex = false;
|
||||||
|
|
||||||
|
@ -370,8 +355,8 @@ static bool d3d9_shmem_init(uint32_t cx, uint32_t cy, HWND window)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!capture_init_shmem(&data.shmem_info, window, cx, cy, data.cx,
|
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
|
||||||
data.cy, data.pitch, data.dxgi_format, false)) {
|
data.pitch, data.dxgi_format, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,8 +388,7 @@ static bool d3d9_get_swap_desc(D3DPRESENT_PARAMETERS &pp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d3d9_init_format_backbuffer(uint32_t &cx, uint32_t &cy,
|
static bool d3d9_init_format_backbuffer(HWND &window)
|
||||||
HWND &window)
|
|
||||||
{
|
{
|
||||||
IDirect3DSurface9 *back_buffer = nullptr;
|
IDirect3DSurface9 *back_buffer = nullptr;
|
||||||
D3DPRESENT_PARAMETERS pp;
|
D3DPRESENT_PARAMETERS pp;
|
||||||
|
@ -432,23 +416,15 @@ static bool d3d9_init_format_backbuffer(uint32_t &cx, uint32_t &cy,
|
||||||
|
|
||||||
data.d3d9_format = desc.Format;
|
data.d3d9_format = desc.Format;
|
||||||
data.dxgi_format = d3d9_to_dxgi_format(desc.Format);
|
data.dxgi_format = d3d9_to_dxgi_format(desc.Format);
|
||||||
data.using_scale = global_hook_info->use_scale;
|
|
||||||
window = pp.hDeviceWindow;
|
window = pp.hDeviceWindow;
|
||||||
cx = desc.Width;
|
|
||||||
cy = desc.Height;
|
|
||||||
|
|
||||||
if (data.using_scale) {
|
data.cx = desc.Width;
|
||||||
data.cx = global_hook_info->cx;
|
data.cy = desc.Height;
|
||||||
data.cy = global_hook_info->cy;
|
|
||||||
} else {
|
|
||||||
data.cx = desc.Width;
|
|
||||||
data.cy = desc.Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool d3d9_init_format_swapchain(uint32_t &cx, uint32_t &cy, HWND &window)
|
static bool d3d9_init_format_swapchain(HWND &window)
|
||||||
{
|
{
|
||||||
D3DPRESENT_PARAMETERS pp;
|
D3DPRESENT_PARAMETERS pp;
|
||||||
|
|
||||||
|
@ -458,18 +434,10 @@ static bool d3d9_init_format_swapchain(uint32_t &cx, uint32_t &cy, HWND &window)
|
||||||
|
|
||||||
data.dxgi_format = d3d9_to_dxgi_format(pp.BackBufferFormat);
|
data.dxgi_format = d3d9_to_dxgi_format(pp.BackBufferFormat);
|
||||||
data.d3d9_format = pp.BackBufferFormat;
|
data.d3d9_format = pp.BackBufferFormat;
|
||||||
data.using_scale = global_hook_info->use_scale;
|
|
||||||
window = pp.hDeviceWindow;
|
window = pp.hDeviceWindow;
|
||||||
cx = pp.BackBufferWidth;
|
|
||||||
cy = pp.BackBufferHeight;
|
|
||||||
|
|
||||||
if (data.using_scale) {
|
data.cx = pp.BackBufferWidth;
|
||||||
data.cx = global_hook_info->cx;
|
data.cy = pp.BackBufferHeight;
|
||||||
data.cy = global_hook_info->cy;
|
|
||||||
} else {
|
|
||||||
data.cx = pp.BackBufferWidth;
|
|
||||||
data.cy = pp.BackBufferHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -481,8 +449,6 @@ static void d3d9_init(IDirect3DDevice9 *device)
|
||||||
global_hook_info->offsets.d3d9.d3d9_clsoff &&
|
global_hook_info->offsets.d3d9.d3d9_clsoff &&
|
||||||
global_hook_info->offsets.d3d9.is_d3d9ex_clsoff;
|
global_hook_info->offsets.d3d9.is_d3d9ex_clsoff;
|
||||||
bool success;
|
bool success;
|
||||||
uint32_t cx = 0;
|
|
||||||
uint32_t cy = 0;
|
|
||||||
HWND window = nullptr;
|
HWND window = nullptr;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -500,17 +466,17 @@ static void d3d9_init(IDirect3DDevice9 *device)
|
||||||
data.patch = -1;
|
data.patch = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d3d9_init_format_backbuffer(cx, cy, window)) {
|
if (!d3d9_init_format_backbuffer(window)) {
|
||||||
if (!d3d9_init_format_swapchain(cx, cy, window)) {
|
if (!d3d9_init_format_swapchain(window)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global_hook_info->force_shmem ||
|
if (global_hook_info->force_shmem ||
|
||||||
(!d3d9ex && data.patch == -1 && !has_d3d9ex_bool_offset)) {
|
(!d3d9ex && data.patch == -1 && !has_d3d9ex_bool_offset)) {
|
||||||
success = d3d9_shmem_init(cx, cy, window);
|
success = d3d9_shmem_init(window);
|
||||||
} else {
|
} else {
|
||||||
success = d3d9_shtex_init(cx, cy, window);
|
success = d3d9_shtex_init(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
|
@ -539,73 +505,54 @@ static inline HRESULT get_backbuffer(IDirect3DDevice9 *device,
|
||||||
|
|
||||||
static inline void d3d9_shtex_capture(IDirect3DSurface9 *backbuffer)
|
static inline void d3d9_shtex_capture(IDirect3DSurface9 *backbuffer)
|
||||||
{
|
{
|
||||||
D3DTEXTUREFILTERTYPE filter;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
filter = data.using_scale ? D3DTEXF_LINEAR : D3DTEXF_NONE;
|
|
||||||
|
|
||||||
hr = data.device->StretchRect(backbuffer, nullptr, data.d3d9_copytex,
|
hr = data.device->StretchRect(backbuffer, nullptr, data.d3d9_copytex,
|
||||||
nullptr, filter);
|
nullptr, D3DTEXF_NONE);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
hlog_hr("d3d9_shtex_capture: StretchRect failed", hr);
|
hlog_hr("d3d9_shtex_capture: StretchRect failed", hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void d3d9_shmem_capture_queue_copy()
|
static void d3d9_shmem_capture_copy(int i)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NUM_BUFFERS; i++) {
|
IDirect3DSurface9 *target = data.copy_surfaces[i];
|
||||||
IDirect3DSurface9 *target = data.copy_surfaces[i];
|
D3DLOCKED_RECT rect;
|
||||||
D3DLOCKED_RECT rect;
|
HRESULT hr;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (!data.issued_queries[i]) {
|
if (!data.issued_queries[i]) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
if (data.queries[i]->GetData(0, 0, 0) != S_OK) {
|
if (data.queries[i]->GetData(0, 0, 0) != S_OK) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.issued_queries[i] = false;
|
data.issued_queries[i] = false;
|
||||||
|
|
||||||
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
|
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
data.texture_mapped[i] = true;
|
data.texture_mapped[i] = true;
|
||||||
shmem_copy_data(i, rect.pBits);
|
shmem_copy_data(i, rect.pBits);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void d3d9_shmem_capture(IDirect3DSurface9 *backbuffer)
|
static inline void d3d9_shmem_capture(IDirect3DSurface9 *backbuffer)
|
||||||
{
|
{
|
||||||
D3DTEXTUREFILTERTYPE filter;
|
|
||||||
IDirect3DSurface9 *copy;
|
|
||||||
int next_tex;
|
int next_tex;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
d3d9_shmem_capture_queue_copy();
|
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
|
||||||
|
d3d9_shmem_capture_copy(next_tex);
|
||||||
next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
|
|
||||||
filter = data.using_scale ? D3DTEXF_LINEAR : D3DTEXF_NONE;
|
|
||||||
copy = data.render_targets[data.cur_tex];
|
|
||||||
|
|
||||||
hr = data.device->StretchRect(backbuffer, nullptr, copy, nullptr,
|
|
||||||
filter);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("d3d9_shmem_capture: StretchRect failed", hr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.copy_wait < NUM_BUFFERS - 1) {
|
if (data.copy_wait < NUM_BUFFERS - 1) {
|
||||||
data.copy_wait++;
|
data.copy_wait++;
|
||||||
} else {
|
} else {
|
||||||
IDirect3DSurface9 *src = data.render_targets[next_tex];
|
IDirect3DSurface9 *src = backbuffer;
|
||||||
IDirect3DSurface9 *dst = data.copy_surfaces[next_tex];
|
IDirect3DSurface9 *dst = data.copy_surfaces[data.cur_tex];
|
||||||
|
|
||||||
if (shmem_texture_data_lock(next_tex)) {
|
if (shmem_texture_data_lock(data.cur_tex)) {
|
||||||
dst->UnlockRect();
|
dst->UnlockRect();
|
||||||
data.texture_mapped[next_tex] = false;
|
data.texture_mapped[data.cur_tex] = false;
|
||||||
shmem_texture_data_unlock(next_tex);
|
shmem_texture_data_unlock(data.cur_tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = data.device->GetRenderTargetData(src, dst);
|
hr = data.device->GetRenderTargetData(src, dst);
|
||||||
|
@ -615,8 +562,8 @@ static inline void d3d9_shmem_capture(IDirect3DSurface9 *backbuffer)
|
||||||
hr);
|
hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.queries[next_tex]->Issue(D3DISSUE_END);
|
data.queries[data.cur_tex]->Issue(D3DISSUE_END);
|
||||||
data.issued_queries[next_tex] = true;
|
data.issued_queries[data.cur_tex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.cur_tex = next_tex;
|
data.cur_tex = next_tex;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <dxgi1_2.h>
|
#include <dxgi1_2.h>
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
|
|
||||||
#include "d3d1x_shaders.hpp"
|
|
||||||
#include "graphics-hook.h"
|
#include "graphics-hook.h"
|
||||||
#include "../funchook.h"
|
#include "../funchook.h"
|
||||||
|
|
||||||
|
@ -218,41 +217,9 @@ hook_present1(IDXGISwapChain1 *swap, UINT sync_interval, UINT flags,
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pD3DCompile get_compiler(void)
|
|
||||||
{
|
|
||||||
pD3DCompile compile = nullptr;
|
|
||||||
char d3dcompiler[40] = {};
|
|
||||||
int ver = 49;
|
|
||||||
|
|
||||||
while (ver > 30) {
|
|
||||||
sprintf_s(d3dcompiler, 40, "D3DCompiler_%02d.dll", ver);
|
|
||||||
|
|
||||||
HMODULE module = LoadLibraryA(d3dcompiler);
|
|
||||||
if (module) {
|
|
||||||
compile = (pD3DCompile)GetProcAddress(module,
|
|
||||||
"D3DCompile");
|
|
||||||
if (compile) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ver--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return compile;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t vertex_shader_data[1024];
|
|
||||||
static uint8_t pixel_shader_data[1024];
|
|
||||||
static size_t vertex_shader_size = 0;
|
|
||||||
static size_t pixel_shader_size = 0;
|
|
||||||
|
|
||||||
bool hook_dxgi(void)
|
bool hook_dxgi(void)
|
||||||
{
|
{
|
||||||
pD3DCompile compile;
|
|
||||||
ID3D10Blob *blob;
|
|
||||||
HMODULE dxgi_module = get_system_module("dxgi.dll");
|
HMODULE dxgi_module = get_system_module("dxgi.dll");
|
||||||
HRESULT hr;
|
|
||||||
void *present_addr;
|
void *present_addr;
|
||||||
void *resize_addr;
|
void *resize_addr;
|
||||||
void *present1_addr = nullptr;
|
void *present1_addr = nullptr;
|
||||||
|
@ -261,42 +228,6 @@ bool hook_dxgi(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
compile = get_compiler();
|
|
||||||
if (!compile) {
|
|
||||||
hlog("hook_dxgi: failed to find d3d compiler library");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------- */
|
|
||||||
|
|
||||||
hr = compile(vertex_shader_string, sizeof(vertex_shader_string),
|
|
||||||
"vertex_shader_string", nullptr, nullptr, "main", "vs_4_0",
|
|
||||||
D3D10_SHADER_OPTIMIZATION_LEVEL1, 0, &blob, nullptr);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("hook_dxgi: failed to compile vertex shader", hr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex_shader_size = (size_t)blob->GetBufferSize();
|
|
||||||
memcpy(vertex_shader_data, blob->GetBufferPointer(),
|
|
||||||
blob->GetBufferSize());
|
|
||||||
blob->Release();
|
|
||||||
|
|
||||||
/* ---------------------- */
|
|
||||||
|
|
||||||
hr = compile(pixel_shader_string, sizeof(pixel_shader_string),
|
|
||||||
"pixel_shader_string", nullptr, nullptr, "main", "ps_4_0",
|
|
||||||
D3D10_SHADER_OPTIMIZATION_LEVEL1, 0, &blob, nullptr);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
hlog_hr("hook_dxgi: failed to compile pixel shader", hr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixel_shader_size = (size_t)blob->GetBufferSize();
|
|
||||||
memcpy(pixel_shader_data, blob->GetBufferPointer(),
|
|
||||||
blob->GetBufferSize());
|
|
||||||
blob->Release();
|
|
||||||
|
|
||||||
/* ---------------------- */
|
/* ---------------------- */
|
||||||
|
|
||||||
present_addr = get_offset_addr(dxgi_module,
|
present_addr = get_offset_addr(dxgi_module,
|
||||||
|
@ -323,15 +254,3 @@ bool hook_dxgi(void)
|
||||||
hlog("Hooked DXGI");
|
hlog("Hooked DXGI");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *get_d3d1x_vertex_shader(size_t *size)
|
|
||||||
{
|
|
||||||
*size = vertex_shader_size;
|
|
||||||
return vertex_shader_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *get_d3d1x_pixel_shader(size_t *size)
|
|
||||||
{
|
|
||||||
*size = pixel_shader_size;
|
|
||||||
return pixel_shader_data;
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,14 +34,11 @@ static bool functions_initialized = false;
|
||||||
|
|
||||||
struct gl_data {
|
struct gl_data {
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
uint32_t base_cx;
|
|
||||||
uint32_t base_cy;
|
|
||||||
uint32_t cx;
|
uint32_t cx;
|
||||||
uint32_t cy;
|
uint32_t cy;
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
bool using_shtex;
|
bool using_shtex;
|
||||||
bool using_scale;
|
|
||||||
bool shmem_fallback;
|
bool shmem_fallback;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
@ -434,9 +431,8 @@ static bool gl_shtex_init(HWND window)
|
||||||
if (!gl_init_fbo()) {
|
if (!gl_init_fbo()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
|
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.format,
|
data.format, true, (uintptr_t)data.handle)) {
|
||||||
true, (uintptr_t)data.handle)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,9 +512,8 @@ static bool gl_shmem_init(HWND window)
|
||||||
if (!gl_init_fbo()) {
|
if (!gl_init_fbo()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!capture_init_shmem(&data.shmem_info, window, data.base_cx,
|
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
|
||||||
data.base_cy, data.cx, data.cy, data.cx * 4,
|
data.cx * 4, data.format, true)) {
|
||||||
data.format, true)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,29 +533,20 @@ static int gl_init(HDC hdc)
|
||||||
RECT rc = {0};
|
RECT rc = {0};
|
||||||
|
|
||||||
if (darkest_dungeon_fix) {
|
if (darkest_dungeon_fix) {
|
||||||
data.base_cx = 1920;
|
data.cx = 1920;
|
||||||
data.base_cy = 1080;
|
data.cy = 1080;
|
||||||
} else {
|
} else {
|
||||||
GetClientRect(window, &rc);
|
GetClientRect(window, &rc);
|
||||||
data.base_cx = rc.right;
|
data.cx = rc.right;
|
||||||
data.base_cy = rc.bottom;
|
data.cy = rc.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.hdc = hdc;
|
data.hdc = hdc;
|
||||||
data.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
data.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
data.using_scale = global_hook_info->use_scale;
|
|
||||||
data.using_shtex = nv_capture_available &&
|
data.using_shtex = nv_capture_available &&
|
||||||
!global_hook_info->force_shmem &&
|
!global_hook_info->force_shmem &&
|
||||||
!data.shmem_fallback;
|
!data.shmem_fallback;
|
||||||
|
|
||||||
if (data.using_scale) {
|
|
||||||
data.cx = global_hook_info->cx;
|
|
||||||
data.cy = global_hook_info->cy;
|
|
||||||
} else {
|
|
||||||
data.cx = data.base_cx;
|
|
||||||
data.cy = data.base_cy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.using_shtex) {
|
if (data.using_shtex) {
|
||||||
success = gl_shtex_init(window);
|
success = gl_shtex_init(window);
|
||||||
if (!success)
|
if (!success)
|
||||||
|
@ -606,8 +592,8 @@ static void gl_copy_backbuffer(GLuint dst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBlitFramebuffer(0, 0, data.base_cx, data.base_cy, 0, 0, data.cx,
|
glBlitFramebuffer(0, 0, data.cx, data.cy, 0, 0, data.cx, data.cy,
|
||||||
data.cy, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
gl_error("gl_copy_backbuffer", "failed to blit");
|
gl_error("gl_copy_backbuffer", "failed to blit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,27 +624,23 @@ static void gl_shtex_capture(void)
|
||||||
IDXGISwapChain_Present(data.dxgi_swap, 0, 0);
|
IDXGISwapChain_Present(data.dxgi_swap, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gl_shmem_capture_queue_copy(void)
|
static void gl_shmem_capture_copy(int i)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NUM_BUFFERS; i++) {
|
if (data.texture_ready[i]) {
|
||||||
if (data.texture_ready[i]) {
|
GLvoid *buffer;
|
||||||
GLvoid *buffer;
|
|
||||||
|
|
||||||
data.texture_ready[i] = false;
|
data.texture_ready[i] = false;
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, data.pbos[i]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, data.pbos[i]);
|
||||||
if (gl_error("gl_shmem_capture_queue_copy",
|
if (gl_error("gl_shmem_capture_queue_copy",
|
||||||
"failed to bind pbo")) {
|
"failed to bind pbo")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer =
|
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||||
glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
if (buffer) {
|
||||||
if (buffer) {
|
data.texture_mapped[i] = true;
|
||||||
data.texture_mapped[i] = true;
|
shmem_copy_data(i, buffer);
|
||||||
shmem_copy_data(i, buffer);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,6 +668,7 @@ static void gl_shmem_capture(void)
|
||||||
int next_tex;
|
int next_tex;
|
||||||
GLint last_fbo;
|
GLint last_fbo;
|
||||||
GLint last_tex;
|
GLint last_tex;
|
||||||
|
GLint last_pbo;
|
||||||
|
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fbo);
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fbo);
|
||||||
if (gl_error("gl_shmem_capture", "failed to get last fbo")) {
|
if (gl_error("gl_shmem_capture", "failed to get last fbo")) {
|
||||||
|
@ -697,30 +680,36 @@ static void gl_shmem_capture(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_shmem_capture_queue_copy();
|
glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &last_pbo);
|
||||||
|
if (gl_error("gl_shmem_capture", "failed to get last pbo")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
next_tex = (data.cur_tex == NUM_BUFFERS - 1) ? 0 : data.cur_tex + 1;
|
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
|
||||||
|
gl_shmem_capture_copy(next_tex);
|
||||||
gl_copy_backbuffer(data.textures[next_tex]);
|
|
||||||
|
|
||||||
if (data.copy_wait < NUM_BUFFERS - 1) {
|
if (data.copy_wait < NUM_BUFFERS - 1) {
|
||||||
data.copy_wait++;
|
data.copy_wait++;
|
||||||
} else {
|
} else {
|
||||||
GLuint src = data.textures[next_tex];
|
if (shmem_texture_data_lock(data.cur_tex)) {
|
||||||
GLuint dst = data.pbos[next_tex];
|
glBindBuffer(GL_PIXEL_PACK_BUFFER,
|
||||||
|
data.pbos[data.cur_tex]);
|
||||||
if (shmem_texture_data_lock(next_tex)) {
|
|
||||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||||
data.texture_mapped[next_tex] = false;
|
data.texture_mapped[data.cur_tex] = false;
|
||||||
shmem_texture_data_unlock(next_tex);
|
shmem_texture_data_unlock(data.cur_tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_shmem_capture_stage(dst, src);
|
gl_copy_backbuffer(data.textures[data.cur_tex]);
|
||||||
data.texture_ready[next_tex] = true;
|
gl_shmem_capture_stage(data.pbos[data.cur_tex],
|
||||||
|
data.textures[data.cur_tex]);
|
||||||
|
data.texture_ready[data.cur_tex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_tex);
|
glBindTexture(GL_TEXTURE_2D, last_tex);
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, last_pbo);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, last_fbo);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, last_fbo);
|
||||||
|
|
||||||
|
data.cur_tex = next_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gl_capture(HDC hdc)
|
static void gl_capture(HDC hdc)
|
||||||
|
@ -757,7 +746,7 @@ static void gl_capture(HDC hdc)
|
||||||
|
|
||||||
/* reset capture if resized */
|
/* reset capture if resized */
|
||||||
get_window_size(hdc, &new_cx, &new_cy);
|
get_window_size(hdc, &new_cx, &new_cy);
|
||||||
if (new_cx != data.base_cx || new_cy != data.base_cy) {
|
if (new_cx != data.cx || new_cy != data.cy) {
|
||||||
if (new_cx != 0 && new_cy != 0)
|
if (new_cx != 0 && new_cy != 0)
|
||||||
gl_free();
|
gl_free();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -531,9 +531,9 @@ static inline bool init_shared_info(size_t size, HWND window)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool capture_init_shtex(struct shtex_data **data, HWND window, uint32_t base_cx,
|
bool capture_init_shtex(struct shtex_data **data, HWND window, uint32_t cx,
|
||||||
uint32_t base_cy, uint32_t cx, uint32_t cy,
|
uint32_t cy, uint32_t format, bool flip,
|
||||||
uint32_t format, bool flip, uintptr_t handle)
|
uintptr_t handle)
|
||||||
{
|
{
|
||||||
if (!init_shared_info(sizeof(struct shtex_data), window)) {
|
if (!init_shared_info(sizeof(struct shtex_data), window)) {
|
||||||
hlog("capture_init_shtex: Failed to initialize memory");
|
hlog("capture_init_shtex: Failed to initialize memory");
|
||||||
|
@ -553,8 +553,8 @@ bool capture_init_shtex(struct shtex_data **data, HWND window, uint32_t base_cx,
|
||||||
global_hook_info->map_size = sizeof(struct shtex_data);
|
global_hook_info->map_size = sizeof(struct shtex_data);
|
||||||
global_hook_info->cx = cx;
|
global_hook_info->cx = cx;
|
||||||
global_hook_info->cy = cy;
|
global_hook_info->cy = cy;
|
||||||
global_hook_info->base_cx = base_cx;
|
global_hook_info->UNUSED_base_cx = cx;
|
||||||
global_hook_info->base_cy = base_cy;
|
global_hook_info->UNUSED_base_cy = cy;
|
||||||
|
|
||||||
if (!SetEvent(signal_ready)) {
|
if (!SetEvent(signal_ready)) {
|
||||||
hlog("capture_init_shtex: Failed to signal ready: %d",
|
hlog("capture_init_shtex: Failed to signal ready: %d",
|
||||||
|
@ -708,9 +708,8 @@ static inline bool init_shmem_thread(uint32_t pitch, uint32_t cy)
|
||||||
#define ALIGN(bytes, align) (((bytes) + ((align)-1)) & ~((align)-1))
|
#define ALIGN(bytes, align) (((bytes) + ((align)-1)) & ~((align)-1))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool capture_init_shmem(struct shmem_data **data, HWND window, uint32_t base_cx,
|
bool capture_init_shmem(struct shmem_data **data, HWND window, uint32_t cx,
|
||||||
uint32_t base_cy, uint32_t cx, uint32_t cy,
|
uint32_t cy, uint32_t pitch, uint32_t format, bool flip)
|
||||||
uint32_t pitch, uint32_t format, bool flip)
|
|
||||||
{
|
{
|
||||||
uint32_t tex_size = cy * pitch;
|
uint32_t tex_size = cy * pitch;
|
||||||
uint32_t aligned_header = ALIGN(sizeof(struct shmem_data), 32);
|
uint32_t aligned_header = ALIGN(sizeof(struct shmem_data), 32);
|
||||||
|
@ -749,8 +748,8 @@ bool capture_init_shmem(struct shmem_data **data, HWND window, uint32_t base_cx,
|
||||||
global_hook_info->pitch = pitch;
|
global_hook_info->pitch = pitch;
|
||||||
global_hook_info->cx = cx;
|
global_hook_info->cx = cx;
|
||||||
global_hook_info->cy = cy;
|
global_hook_info->cy = cy;
|
||||||
global_hook_info->base_cx = base_cx;
|
global_hook_info->UNUSED_base_cx = cx;
|
||||||
global_hook_info->base_cy = base_cy;
|
global_hook_info->UNUSED_base_cy = cy;
|
||||||
|
|
||||||
if (!init_shmem_thread(pitch, cy)) {
|
if (!init_shmem_thread(pitch, cy)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -59,19 +59,14 @@ extern void d3d12_capture(void *swap, void *backbuffer, bool capture_overlay);
|
||||||
extern void d3d12_free(void);
|
extern void d3d12_free(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern uint8_t *get_d3d1x_vertex_shader(size_t *size);
|
|
||||||
extern uint8_t *get_d3d1x_pixel_shader(size_t *size);
|
|
||||||
|
|
||||||
extern bool rehook_gl(void);
|
extern bool rehook_gl(void);
|
||||||
|
|
||||||
extern bool capture_init_shtex(struct shtex_data **data, HWND window,
|
extern bool capture_init_shtex(struct shtex_data **data, HWND window,
|
||||||
uint32_t base_cx, uint32_t base_cy, uint32_t cx,
|
uint32_t cx, uint32_t cy, uint32_t format,
|
||||||
uint32_t cy, uint32_t format, bool flip,
|
bool flip, uintptr_t handle);
|
||||||
uintptr_t handle);
|
|
||||||
extern bool capture_init_shmem(struct shmem_data **data, HWND window,
|
extern bool capture_init_shmem(struct shmem_data **data, HWND window,
|
||||||
uint32_t base_cx, uint32_t base_cy, uint32_t cx,
|
uint32_t cx, uint32_t cy, uint32_t pitch,
|
||||||
uint32_t cy, uint32_t pitch, uint32_t format,
|
uint32_t format, bool flip);
|
||||||
bool flip);
|
|
||||||
extern void capture_free(void);
|
extern void capture_free(void);
|
||||||
|
|
||||||
extern struct hook_info *global_hook_info;
|
extern struct hook_info *global_hook_info;
|
||||||
|
|
|
@ -705,11 +705,11 @@ static bool vk_shtex_init(struct vk_data *data, HWND window,
|
||||||
|
|
||||||
data->cur_swap = swap;
|
data->cur_swap = swap;
|
||||||
|
|
||||||
swap->captured = capture_init_shtex(
|
swap->captured = capture_init_shtex(&swap->shtex_info, window,
|
||||||
&swap->shtex_info, window, swap->image_extent.width,
|
swap->image_extent.width,
|
||||||
swap->image_extent.height, swap->image_extent.width,
|
swap->image_extent.height,
|
||||||
swap->image_extent.height, (uint32_t)swap->format, false,
|
(uint32_t)swap->format, false,
|
||||||
(uintptr_t)swap->handle);
|
(uintptr_t)swap->handle);
|
||||||
|
|
||||||
if (swap->captured) {
|
if (swap->captured) {
|
||||||
if (global_hook_info->force_shmem) {
|
if (global_hook_info->force_shmem) {
|
||||||
|
|
Loading…
Reference in New Issue