win-capture: Remove game capture scaling

The performance save is not worth accidental usage support.

Also remove unnecessary copies from the shmem paths.
master
jpark37 2020-06-22 15:07:07 -07:00
parent 0f27cf4983
commit 6393399758
16 changed files with 201 additions and 1329 deletions

View File

@ -210,7 +210,7 @@ void cursor_capture(struct cursor_data *data)
}
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 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_matrix_push();
gs_matrix_scale3f(x_scale, y_scale, 1.0f);
obs_source_draw(data->texture, x_draw, y_draw, 0, 0, false);
gs_matrix_pop();

View File

@ -24,5 +24,5 @@ struct cursor_data {
extern void cursor_capture(struct cursor_data *data);
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);

View File

@ -205,7 +205,7 @@ static uint32_t duplicator_capture_height(void *data)
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->height : capture->width);
}

View File

@ -32,8 +32,6 @@
#define SETTING_ACTIVE_WINDOW "active_window"
#define SETTING_WINDOW_PRIORITY "priority"
#define SETTING_COMPATIBILITY "sli_compatibility"
#define SETTING_FORCE_SCALING "force_scaling"
#define SETTING_SCALE_RES "scale_res"
#define SETTING_CURSOR "capture_cursor"
#define SETTING_TRANSPARENCY "allow_transparency"
#define SETTING_LIMIT_FRAMERATE "limit_framerate"
@ -56,8 +54,6 @@
#define TEXT_ANY_FULLSCREEN obs_module_text("GameCapture.AnyFullscreen")
#define TEXT_SLI_COMPATIBILITY obs_module_text("SLIFix")
#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_MATCH_PRIORITY obs_module_text("WindowCapture.Priority")
#define TEXT_MATCH_TITLE obs_module_text("WindowCapture.Priority.Title")
@ -104,11 +100,8 @@ struct game_capture_config {
char *executable;
enum window_priority priority;
enum capture_mode mode;
uint32_t scale_cx;
uint32_t scale_cy;
bool cursor;
bool force_shmem;
bool force_scaling;
bool allow_transparency;
bool limit_framerate;
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,
obs_data_t *settings, const char *window)
{
int ret;
const char *scale_str;
const char *mode_str = NULL;
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->allow_transparency =
obs_data_get_bool(settings, SETTING_TRANSPARENCY);
cfg->force_scaling = obs_data_get_bool(settings, SETTING_FORCE_SCALING);
cfg->limit_framerate =
obs_data_get_bool(settings, SETTING_LIMIT_FRAMERATE);
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);
cfg->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)
@ -465,13 +441,6 @@ static inline bool capture_needs_reset(struct game_capture_config *cfg1,
cfg1->priority != cfg2->priority)) {
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) {
return true;
@ -525,12 +494,7 @@ static void game_capture_update(void *data, obs_data_t *settings)
get_config(&cfg, settings, window);
reset_capture = capture_needs_reset(&cfg, &gc->config);
if (cfg.force_scaling && (cfg.scale_cx == 0 || cfg.scale_cy == 0)) {
gc->error_acquiring = true;
warn("error acquiring, scale is bad");
} else {
gc->error_acquiring = false;
}
gc->error_acquiring = false;
if (cfg.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;
gc->global_hook_info->capture_overlay = gc->config.capture_overlays;
gc->global_hook_info->force_shmem = gc->config.force_shmem;
gc->global_hook_info->use_scale = gc->config.force_scaling;
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;
gc->global_hook_info->UNUSED_use_scale = false;
reset_frame_interval(gc);
obs_enter_graphics();
@ -1817,7 +1777,7 @@ static inline void game_capture_render_cursor(struct game_capture *gc)
POINT p = {0};
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;
window = !!gc->global_hook_info->window
@ -1826,14 +1786,8 @@ static inline void game_capture_render_cursor(struct game_capture *gc)
ClientToScreen(window, &p);
float x_scale = (float)gc->global_hook_info->cx /
(float)gc->global_hook_info->base_cx;
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);
cursor_draw(&gc->cursor_data, -p.x, -p.y, gc->global_hook_info->cx,
gc->global_hook_info->cy);
}
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,
(int)WINDOW_PRIORITY_EXE);
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_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_CAPTURE_OVERLAYS, false);
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;
}
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)
{
char *class = NULL;
@ -1992,11 +1934,6 @@ static bool window_changed_callback(obs_properties_t *ppts, obs_property_t *p,
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,
LPARAM data)
{
@ -2082,29 +2019,6 @@ static obs_properties_t *game_capture_properties(void *data)
obs_properties_add_bool(ppts, SETTING_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,
TEXT_ALLOW_TRANSPARENCY);

View File

@ -90,8 +90,8 @@ struct hook_info {
uint32_t format;
uint32_t cx;
uint32_t cy;
uint32_t base_cx;
uint32_t base_cy;
uint32_t UNUSED_base_cx;
uint32_t UNUSED_base_cy;
uint32_t pitch;
uint32_t map_id;
uint32_t map_size;
@ -99,7 +99,7 @@ struct hook_info {
/* additional options */
uint64_t frame_interval;
bool use_scale;
bool UNUSED_use_scale;
bool force_shmem;
bool capture_overlay;

View File

@ -7,13 +7,10 @@
struct d3d10_data {
ID3D10Device *device; /* do not release */
uint32_t base_cx;
uint32_t base_cy;
uint32_t cx;
uint32_t cy;
DXGI_FORMAT format;
bool using_shtex;
bool using_scale;
bool multisampled;
ID3D10Texture2D *scale_tex;
@ -42,8 +39,6 @@ struct d3d10_data {
struct {
struct shmem_data *shmem_info;
ID3D10Texture2D *copy_surfaces[NUM_BUFFERS];
ID3D10Texture2D *textures[NUM_BUFFERS];
ID3D10RenderTargetView *render_targets[NUM_BUFFERS];
bool texture_ready[NUM_BUFFERS];
bool texture_mapped[NUM_BUFFERS];
uint32_t pitch;
@ -92,10 +87,6 @@ void d3d10_free(void)
data.copy_surfaces[i]->Unmap(0);
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.multisampled = desc.SampleDesc.Count > 1;
window = desc.OutputWindow;
data.base_cx = desc.BufferDesc.Width;
data.base_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;
}
data.cx = desc.BufferDesc.Width;
data.cy = desc.BufferDesc.Height;
return true;
}
@ -467,13 +248,6 @@ static bool d3d10_shmem_init_buffers(size_t idx)
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;
}
@ -486,9 +260,8 @@ static bool d3d10_shmem_init(HWND window)
return false;
}
}
if (!capture_init_shmem(&data.shmem_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.pitch,
data.format, false)) {
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
data.pitch, data.format, false)) {
return false;
}
@ -512,9 +285,8 @@ static bool d3d10_shtex_init(HWND window)
hlog("d3d10_shtex_init: failed to create texture");
return false;
}
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.format,
false, (uintptr_t)data.handle)) {
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
data.format, false, (uintptr_t)data.handle)) {
return false;
}
@ -524,12 +296,9 @@ static bool d3d10_shtex_init(HWND window)
static void d3d10_init(IDXGISwapChain *swap)
{
bool success = true;
HWND window;
HRESULT hr;
data.using_scale = global_hook_info->use_scale;
hr = swap->GetDevice(__uuidof(ID3D10Device), (void **)&data.device);
if (FAILED(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)) {
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)
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)
{
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)
{
if (data.using_scale) {
d3d10_copy_texture(data.scale_tex, backbuffer);
d3d10_scale_texture(data.render_target, data.scale_resource);
} else {
d3d10_copy_texture(data.texture, backbuffer);
}
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;
HRESULT hr;
D3D10_MAPPED_TEXTURE2D map;
HRESULT hr;
if (data.texture_ready[i]) {
data.texture_ready[i] = false;
if (data.texture_ready[i]) {
data.texture_ready[i] = false;
hr = data.copy_surfaces[i]->Map(0, D3D10_MAP_READ, 0,
&map);
if (SUCCEEDED(hr)) {
data.texture_mapped[i] = true;
shmem_copy_data(i, map.pData);
}
break;
hr = data.copy_surfaces[i]->Map(0, D3D10_MAP_READ, 0, &map);
if (SUCCEEDED(hr)) {
data.texture_mapped[i] = true;
shmem_copy_data(i, map.pData);
}
}
}
@ -748,32 +353,21 @@ static inline void d3d10_shmem_capture(ID3D10Resource *backbuffer)
{
int next_tex;
d3d10_shmem_queue_copy();
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);
}
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
d3d10_shmem_capture_copy(next_tex);
if (data.copy_wait < NUM_BUFFERS - 1) {
data.copy_wait++;
} else {
ID3D10Texture2D *src = data.textures[next_tex];
ID3D10Texture2D *dst = data.copy_surfaces[next_tex];
if (shmem_texture_data_lock(next_tex)) {
dst->Unmap(0);
data.texture_mapped[next_tex] = false;
shmem_texture_data_unlock(next_tex);
if (shmem_texture_data_lock(data.cur_tex)) {
data.copy_surfaces[data.cur_tex]->Unmap(0);
data.texture_mapped[data.cur_tex] = false;
shmem_texture_data_unlock(data.cur_tex);
}
d3d10_copy_texture(dst, src);
data.texture_ready[next_tex] = true;
d3d10_copy_texture(data.copy_surfaces[data.cur_tex],
backbuffer);
data.texture_ready[data.cur_tex] = true;
}
data.cur_tex = next_tex;

View File

@ -8,13 +8,10 @@
struct d3d11_data {
ID3D11Device *device; /* do not release */
ID3D11DeviceContext *context; /* do not release */
uint32_t base_cx;
uint32_t base_cy;
uint32_t cx;
uint32_t cy;
DXGI_FORMAT format;
bool using_shtex;
bool using_scale;
bool multisampled;
ID3D11Texture2D *scale_tex;
@ -42,8 +39,6 @@ struct d3d11_data {
/* shared memory */
struct {
ID3D11Texture2D *copy_surfaces[NUM_BUFFERS];
ID3D11Texture2D *textures[NUM_BUFFERS];
ID3D11RenderTargetView *render_targets[NUM_BUFFERS];
bool texture_ready[NUM_BUFFERS];
bool texture_mapped[NUM_BUFFERS];
uint32_t pitch;
@ -94,10 +89,6 @@ void d3d11_free(void)
data.copy_surfaces[i], 0);
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.multisampled = desc.SampleDesc.Count > 1;
window = desc.OutputWindow;
data.base_cx = desc.BufferDesc.Width;
data.base_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;
}
data.cx = desc.BufferDesc.Width;
data.cy = desc.BufferDesc.Height;
return true;
}
@ -472,13 +251,6 @@ static bool d3d11_shmem_init_buffers(size_t idx)
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;
}
@ -491,9 +263,8 @@ static bool d3d11_shmem_init(HWND window)
return false;
}
}
if (!capture_init_shmem(&data.shmem_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.pitch,
data.format, false)) {
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
data.pitch, data.format, false)) {
return false;
}
@ -517,9 +288,8 @@ static bool d3d11_shtex_init(HWND window)
hlog("d3d11_shtex_init: failed to create texture");
return false;
}
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.format,
false, (uintptr_t)data.handle)) {
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
data.format, false, (uintptr_t)data.handle)) {
return false;
}
@ -529,12 +299,9 @@ static bool d3d11_shtex_init(HWND window)
static void d3d11_init(IDXGISwapChain *swap)
{
bool success = true;
HWND window;
HRESULT hr;
data.using_scale = global_hook_info->use_scale;
hr = swap->GetDevice(__uuidof(ID3D11Device), (void **)&data.device);
if (FAILED(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)) {
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)
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)
{
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)
{
if (data.using_scale) {
d3d11_copy_texture(data.scale_tex, backbuffer);
d3d11_scale_texture(data.render_target, data.scale_resource);
} else {
d3d11_copy_texture(data.texture, backbuffer);
}
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;
HRESULT hr;
D3D11_MAPPED_SUBRESOURCE map;
HRESULT hr;
if (data.texture_ready[i]) {
data.texture_ready[i] = false;
if (data.texture_ready[i]) {
data.texture_ready[i] = false;
hr = data.context->Map(data.copy_surfaces[i], 0,
D3D11_MAP_READ, 0, &map);
if (SUCCEEDED(hr)) {
data.texture_mapped[i] = true;
shmem_copy_data(i, map.pData);
}
break;
hr = data.context->Map(data.copy_surfaces[i], 0, D3D11_MAP_READ,
0, &map);
if (SUCCEEDED(hr)) {
data.texture_mapped[i] = true;
shmem_copy_data(i, map.pData);
}
}
}
@ -787,32 +359,22 @@ static inline void d3d11_shmem_capture(ID3D11Resource *backbuffer)
{
int next_tex;
d3d11_shmem_queue_copy();
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);
}
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
d3d11_shmem_capture_copy(next_tex);
if (data.copy_wait < NUM_BUFFERS - 1) {
data.copy_wait++;
} else {
ID3D11Texture2D *src = data.textures[next_tex];
ID3D11Texture2D *dst = data.copy_surfaces[next_tex];
if (shmem_texture_data_lock(next_tex)) {
data.context->Unmap(dst, 0);
data.texture_mapped[next_tex] = false;
shmem_texture_data_unlock(next_tex);
if (shmem_texture_data_lock(data.cur_tex)) {
data.context->Unmap(data.copy_surfaces[data.cur_tex],
0);
data.texture_mapped[data.cur_tex] = false;
shmem_texture_data_unlock(data.cur_tex);
}
d3d11_copy_texture(dst, src);
data.texture_ready[next_tex] = true;
d3d11_copy_texture(data.copy_surfaces[data.cur_tex],
backbuffer);
data.texture_ready[data.cur_tex] = true;
}
data.cur_tex = next_tex;

View File

@ -14,13 +14,10 @@
struct d3d12_data {
ID3D12Device *device; /* do not release */
uint32_t base_cx;
uint32_t base_cy;
uint32_t cx;
uint32_t cy;
DXGI_FORMAT format;
bool using_shtex;
bool using_scale;
bool multisampled;
bool dxgi_1_4;
@ -197,9 +194,8 @@ static bool d3d12_shtex_init(HWND window, bb_info &bb)
if (!create_d3d12_tex(bb)) {
return false;
}
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.format,
false, (uintptr_t)data.handle)) {
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
data.format, false, (uintptr_t)data.handle)) {
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.multisampled = desc.SampleDesc.Count > 1;
window = desc.OutputWindow;
data.base_cx = desc.BufferDesc.Width;
data.base_cy = desc.BufferDesc.Height;
data.cx = desc.BufferDesc.Width;
data.cy = desc.BufferDesc.Height;
hr = swap->QueryInterface(__uuidof(IDXGISwapChain3), (void **)&swap3);
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;
}
static void d3d12_init(IDXGISwapChain *swap)
{
bool success = true;
bb_info bb = {};
HWND window;
HRESULT hr;
data.using_scale = global_hook_info->use_scale;
hr = swap->GetDevice(__uuidof(ID3D12Device), (void **)&data.device);
if (FAILED(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)) {
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();
}

View File

@ -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); \
}";

View File

@ -24,6 +24,7 @@ struct d3d8_data {
HWND window;
uint32_t pitch;
IDirect3DSurface8 *copy_surfaces[NUM_BUFFERS];
bool texture_ready[NUM_BUFFERS];
bool surface_locked[NUM_BUFFERS];
int cur_surface;
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,
data.cx, data.cy, data.pitch, data.dxgi_format,
false)) {
data.pitch, data.dxgi_format, false)) {
return false;
}
@ -184,45 +184,50 @@ static void d3d8_init(IDirect3DDevice8 *device)
static void d3d8_shmem_capture_copy(int idx)
{
IDirect3DSurface8 *target = data.copy_surfaces[idx];
D3DLOCKED_RECT rect;
HRESULT hr;
if (data.surface_locked[idx])
return;
if (data.texture_ready[idx]) {
data.texture_ready[idx] = false;
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
if (SUCCEEDED(hr)) {
shmem_copy_data(idx, rect.pBits);
IDirect3DSurface8 *target = data.copy_surfaces[idx];
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
if (SUCCEEDED(hr)) {
data.surface_locked[idx] = true;
shmem_copy_data(idx, rect.pBits);
}
}
}
static void d3d8_shmem_capture(IDirect3DDevice8 *device,
IDirect3DSurface8 *backbuffer)
{
int cur_surface;
int next_surface;
HRESULT hr;
cur_surface = data.cur_surface;
next_surface = (cur_surface == NUM_BUFFERS - 1) ? 0 : cur_surface + 1;
next_surface = (data.cur_surface + 1) % NUM_BUFFERS;
d3d8_shmem_capture_copy(next_surface);
if (data.copy_wait < NUM_BUFFERS - 1) {
data.copy_wait++;
} else {
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();
data.surface_locked[next_surface] = false;
shmem_texture_data_unlock(next_surface);
data.surface_locked[data.cur_surface] = false;
shmem_texture_data_unlock(data.cur_surface);
}
hr = device->CopyRects(src, nullptr, 0, dst, nullptr);
if (SUCCEEDED(hr)) {
d3d8_shmem_capture_copy(cur_surface);
if (FAILED(hr)) {
hlog_hr("d3d8_shmem_capture: CopyRects "
"failed",
hr);
}
data.texture_ready[data.cur_surface] = true;
}
data.cur_surface = next_surface;

View File

@ -38,7 +38,6 @@ struct d3d9_data {
D3DFORMAT d3d9_format;
DXGI_FORMAT dxgi_format;
bool using_shtex;
bool using_scale;
/* shared texture */
IDirect3DSurface9 *d3d9_copytex;
@ -51,7 +50,6 @@ struct d3d9_data {
/* shared memory */
IDirect3DSurface9 *copy_surfaces[NUM_BUFFERS];
IDirect3DSurface9 *render_targets[NUM_BUFFERS];
IDirect3DQuery9 *queries[NUM_BUFFERS];
struct shmem_data *shmem_info;
bool texture_mapped[NUM_BUFFERS];
@ -83,8 +81,6 @@ static void d3d9_free()
data.copy_surfaces[i]->UnlockRect();
data.copy_surfaces[i]->Release();
}
if (data.render_targets[i])
data.render_targets[i]->Release();
if (data.queries[i])
data.queries[i]->Release();
}
@ -289,7 +285,7 @@ static inline bool d3d9_shtex_init_copytex()
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;
@ -302,8 +298,8 @@ static bool d3d9_shtex_init(uint32_t cx, uint32_t cy, HWND window)
if (!d3d9_shtex_init_copytex()) {
return false;
}
if (!capture_init_shtex(&data.shtex_info, window, cx, cy, data.cx,
data.cy, data.dxgi_format, false,
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
data.dxgi_format, false,
(uintptr_t)data.handle)) {
return false;
}
@ -340,17 +336,6 @@ static bool d3d9_shmem_init_buffers(size_t buffer)
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,
&data.queries[buffer]);
if (FAILED(hr)) {
@ -361,7 +346,7 @@ static bool d3d9_shmem_init_buffers(size_t buffer)
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;
@ -370,8 +355,8 @@ static bool d3d9_shmem_init(uint32_t cx, uint32_t cy, HWND window)
return false;
}
}
if (!capture_init_shmem(&data.shmem_info, window, cx, cy, data.cx,
data.cy, data.pitch, data.dxgi_format, false)) {
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
data.pitch, data.dxgi_format, false)) {
return false;
}
@ -403,8 +388,7 @@ static bool d3d9_get_swap_desc(D3DPRESENT_PARAMETERS &pp)
return true;
}
static bool d3d9_init_format_backbuffer(uint32_t &cx, uint32_t &cy,
HWND &window)
static bool d3d9_init_format_backbuffer(HWND &window)
{
IDirect3DSurface9 *back_buffer = nullptr;
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.dxgi_format = d3d9_to_dxgi_format(desc.Format);
data.using_scale = global_hook_info->use_scale;
window = pp.hDeviceWindow;
cx = desc.Width;
cy = desc.Height;
if (data.using_scale) {
data.cx = global_hook_info->cx;
data.cy = global_hook_info->cy;
} else {
data.cx = desc.Width;
data.cy = desc.Height;
}
data.cx = desc.Width;
data.cy = desc.Height;
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;
@ -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.d3d9_format = pp.BackBufferFormat;
data.using_scale = global_hook_info->use_scale;
window = pp.hDeviceWindow;
cx = pp.BackBufferWidth;
cy = pp.BackBufferHeight;
if (data.using_scale) {
data.cx = global_hook_info->cx;
data.cy = global_hook_info->cy;
} else {
data.cx = pp.BackBufferWidth;
data.cy = pp.BackBufferHeight;
}
data.cx = pp.BackBufferWidth;
data.cy = pp.BackBufferHeight;
return true;
}
@ -481,8 +449,6 @@ static void d3d9_init(IDirect3DDevice9 *device)
global_hook_info->offsets.d3d9.d3d9_clsoff &&
global_hook_info->offsets.d3d9.is_d3d9ex_clsoff;
bool success;
uint32_t cx = 0;
uint32_t cy = 0;
HWND window = nullptr;
HRESULT hr;
@ -500,17 +466,17 @@ static void d3d9_init(IDirect3DDevice9 *device)
data.patch = -1;
}
if (!d3d9_init_format_backbuffer(cx, cy, window)) {
if (!d3d9_init_format_swapchain(cx, cy, window)) {
if (!d3d9_init_format_backbuffer(window)) {
if (!d3d9_init_format_swapchain(window)) {
return;
}
}
if (global_hook_info->force_shmem ||
(!d3d9ex && data.patch == -1 && !has_d3d9ex_bool_offset)) {
success = d3d9_shmem_init(cx, cy, window);
success = d3d9_shmem_init(window);
} else {
success = d3d9_shtex_init(cx, cy, window);
success = d3d9_shtex_init(window);
}
if (!success)
@ -539,73 +505,54 @@ static inline HRESULT get_backbuffer(IDirect3DDevice9 *device,
static inline void d3d9_shtex_capture(IDirect3DSurface9 *backbuffer)
{
D3DTEXTUREFILTERTYPE filter;
HRESULT hr;
filter = data.using_scale ? D3DTEXF_LINEAR : D3DTEXF_NONE;
hr = data.device->StretchRect(backbuffer, nullptr, data.d3d9_copytex,
nullptr, filter);
nullptr, D3DTEXF_NONE);
if (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];
D3DLOCKED_RECT rect;
HRESULT hr;
IDirect3DSurface9 *target = data.copy_surfaces[i];
D3DLOCKED_RECT rect;
HRESULT hr;
if (!data.issued_queries[i]) {
continue;
}
if (data.queries[i]->GetData(0, 0, 0) != S_OK) {
continue;
}
if (!data.issued_queries[i]) {
return;
}
if (data.queries[i]->GetData(0, 0, 0) != S_OK) {
return;
}
data.issued_queries[i] = false;
data.issued_queries[i] = false;
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
if (SUCCEEDED(hr)) {
data.texture_mapped[i] = true;
shmem_copy_data(i, rect.pBits);
}
break;
hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY);
if (SUCCEEDED(hr)) {
data.texture_mapped[i] = true;
shmem_copy_data(i, rect.pBits);
}
}
static inline void d3d9_shmem_capture(IDirect3DSurface9 *backbuffer)
{
D3DTEXTUREFILTERTYPE filter;
IDirect3DSurface9 *copy;
int next_tex;
HRESULT hr;
d3d9_shmem_capture_queue_copy();
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;
}
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
d3d9_shmem_capture_copy(next_tex);
if (data.copy_wait < NUM_BUFFERS - 1) {
data.copy_wait++;
} else {
IDirect3DSurface9 *src = data.render_targets[next_tex];
IDirect3DSurface9 *dst = data.copy_surfaces[next_tex];
IDirect3DSurface9 *src = backbuffer;
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();
data.texture_mapped[next_tex] = false;
shmem_texture_data_unlock(next_tex);
data.texture_mapped[data.cur_tex] = false;
shmem_texture_data_unlock(data.cur_tex);
}
hr = data.device->GetRenderTargetData(src, dst);
@ -615,8 +562,8 @@ static inline void d3d9_shmem_capture(IDirect3DSurface9 *backbuffer)
hr);
}
data.queries[next_tex]->Issue(D3DISSUE_END);
data.issued_queries[next_tex] = true;
data.queries[data.cur_tex]->Issue(D3DISSUE_END);
data.issued_queries[data.cur_tex] = true;
}
data.cur_tex = next_tex;

View File

@ -3,7 +3,6 @@
#include <dxgi1_2.h>
#include <d3dcompiler.h>
#include "d3d1x_shaders.hpp"
#include "graphics-hook.h"
#include "../funchook.h"
@ -218,41 +217,9 @@ hook_present1(IDXGISwapChain1 *swap, UINT sync_interval, UINT flags,
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)
{
pD3DCompile compile;
ID3D10Blob *blob;
HMODULE dxgi_module = get_system_module("dxgi.dll");
HRESULT hr;
void *present_addr;
void *resize_addr;
void *present1_addr = nullptr;
@ -261,42 +228,6 @@ bool hook_dxgi(void)
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,
@ -323,15 +254,3 @@ bool hook_dxgi(void)
hlog("Hooked DXGI");
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;
}

View File

@ -34,14 +34,11 @@ static bool functions_initialized = false;
struct gl_data {
HDC hdc;
uint32_t base_cx;
uint32_t base_cy;
uint32_t cx;
uint32_t cy;
DXGI_FORMAT format;
GLuint fbo;
bool using_shtex;
bool using_scale;
bool shmem_fallback;
union {
@ -434,9 +431,8 @@ static bool gl_shtex_init(HWND window)
if (!gl_init_fbo()) {
return false;
}
if (!capture_init_shtex(&data.shtex_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.format,
true, (uintptr_t)data.handle)) {
if (!capture_init_shtex(&data.shtex_info, window, data.cx, data.cy,
data.format, true, (uintptr_t)data.handle)) {
return false;
}
@ -516,9 +512,8 @@ static bool gl_shmem_init(HWND window)
if (!gl_init_fbo()) {
return false;
}
if (!capture_init_shmem(&data.shmem_info, window, data.base_cx,
data.base_cy, data.cx, data.cy, data.cx * 4,
data.format, true)) {
if (!capture_init_shmem(&data.shmem_info, window, data.cx, data.cy,
data.cx * 4, data.format, true)) {
return false;
}
@ -538,29 +533,20 @@ static int gl_init(HDC hdc)
RECT rc = {0};
if (darkest_dungeon_fix) {
data.base_cx = 1920;
data.base_cy = 1080;
data.cx = 1920;
data.cy = 1080;
} else {
GetClientRect(window, &rc);
data.base_cx = rc.right;
data.base_cy = rc.bottom;
data.cx = rc.right;
data.cy = rc.bottom;
}
data.hdc = hdc;
data.format = DXGI_FORMAT_B8G8R8A8_UNORM;
data.using_scale = global_hook_info->use_scale;
data.using_shtex = nv_capture_available &&
!global_hook_info->force_shmem &&
!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) {
success = gl_shtex_init(window);
if (!success)
@ -606,8 +592,8 @@ static void gl_copy_backbuffer(GLuint dst)
return;
}
glBlitFramebuffer(0, 0, data.base_cx, data.base_cy, 0, 0, data.cx,
data.cy, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBlitFramebuffer(0, 0, data.cx, data.cy, 0, 0, data.cx, data.cy,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
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);
}
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]) {
GLvoid *buffer;
if (data.texture_ready[i]) {
GLvoid *buffer;
data.texture_ready[i] = false;
data.texture_ready[i] = false;
glBindBuffer(GL_PIXEL_PACK_BUFFER, data.pbos[i]);
if (gl_error("gl_shmem_capture_queue_copy",
"failed to bind pbo")) {
return;
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, data.pbos[i]);
if (gl_error("gl_shmem_capture_queue_copy",
"failed to bind pbo")) {
return;
}
buffer =
glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (buffer) {
data.texture_mapped[i] = true;
shmem_copy_data(i, buffer);
}
break;
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (buffer) {
data.texture_mapped[i] = true;
shmem_copy_data(i, buffer);
}
}
}
@ -686,6 +668,7 @@ static void gl_shmem_capture(void)
int next_tex;
GLint last_fbo;
GLint last_tex;
GLint last_pbo;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fbo);
if (gl_error("gl_shmem_capture", "failed to get last fbo")) {
@ -697,30 +680,36 @@ static void gl_shmem_capture(void)
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;
gl_copy_backbuffer(data.textures[next_tex]);
next_tex = (data.cur_tex + 1) % NUM_BUFFERS;
gl_shmem_capture_copy(next_tex);
if (data.copy_wait < NUM_BUFFERS - 1) {
data.copy_wait++;
} else {
GLuint src = data.textures[next_tex];
GLuint dst = data.pbos[next_tex];
if (shmem_texture_data_lock(next_tex)) {
if (shmem_texture_data_lock(data.cur_tex)) {
glBindBuffer(GL_PIXEL_PACK_BUFFER,
data.pbos[data.cur_tex]);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
data.texture_mapped[next_tex] = false;
shmem_texture_data_unlock(next_tex);
data.texture_mapped[data.cur_tex] = false;
shmem_texture_data_unlock(data.cur_tex);
}
gl_shmem_capture_stage(dst, src);
data.texture_ready[next_tex] = true;
gl_copy_backbuffer(data.textures[data.cur_tex]);
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);
glBindBuffer(GL_PIXEL_PACK_BUFFER, last_pbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, last_fbo);
data.cur_tex = next_tex;
}
static void gl_capture(HDC hdc)
@ -757,7 +746,7 @@ static void gl_capture(HDC hdc)
/* reset capture if resized */
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)
gl_free();
return;

View File

@ -531,9 +531,9 @@ static inline bool init_shared_info(size_t size, HWND window)
return true;
}
bool capture_init_shtex(struct shtex_data **data, HWND window, uint32_t base_cx,
uint32_t base_cy, uint32_t cx, uint32_t cy,
uint32_t format, bool flip, uintptr_t handle)
bool capture_init_shtex(struct shtex_data **data, HWND window, uint32_t cx,
uint32_t cy, uint32_t format, bool flip,
uintptr_t handle)
{
if (!init_shared_info(sizeof(struct shtex_data), window)) {
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->cx = cx;
global_hook_info->cy = cy;
global_hook_info->base_cx = base_cx;
global_hook_info->base_cy = base_cy;
global_hook_info->UNUSED_base_cx = cx;
global_hook_info->UNUSED_base_cy = cy;
if (!SetEvent(signal_ready)) {
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))
#endif
bool capture_init_shmem(struct shmem_data **data, HWND window, uint32_t base_cx,
uint32_t base_cy, uint32_t cx, uint32_t cy,
uint32_t pitch, uint32_t format, bool flip)
bool capture_init_shmem(struct shmem_data **data, HWND window, uint32_t cx,
uint32_t cy, uint32_t pitch, uint32_t format, bool flip)
{
uint32_t tex_size = cy * pitch;
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->cx = cx;
global_hook_info->cy = cy;
global_hook_info->base_cx = base_cx;
global_hook_info->base_cy = base_cy;
global_hook_info->UNUSED_base_cx = cx;
global_hook_info->UNUSED_base_cy = cy;
if (!init_shmem_thread(pitch, cy)) {
return false;

View File

@ -59,19 +59,14 @@ extern void d3d12_capture(void *swap, void *backbuffer, bool capture_overlay);
extern void d3d12_free(void);
#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 capture_init_shtex(struct shtex_data **data, HWND window,
uint32_t base_cx, uint32_t base_cy, uint32_t cx,
uint32_t cy, uint32_t format, bool flip,
uintptr_t handle);
uint32_t cx, uint32_t cy, uint32_t format,
bool flip, uintptr_t handle);
extern bool capture_init_shmem(struct shmem_data **data, HWND window,
uint32_t base_cx, uint32_t base_cy, uint32_t cx,
uint32_t cy, uint32_t pitch, uint32_t format,
bool flip);
uint32_t cx, uint32_t cy, uint32_t pitch,
uint32_t format, bool flip);
extern void capture_free(void);
extern struct hook_info *global_hook_info;

View File

@ -705,11 +705,11 @@ static bool vk_shtex_init(struct vk_data *data, HWND window,
data->cur_swap = swap;
swap->captured = capture_init_shtex(
&swap->shtex_info, window, swap->image_extent.width,
swap->image_extent.height, swap->image_extent.width,
swap->image_extent.height, (uint32_t)swap->format, false,
(uintptr_t)swap->handle);
swap->captured = capture_init_shtex(&swap->shtex_info, window,
swap->image_extent.width,
swap->image_extent.height,
(uint32_t)swap->format, false,
(uintptr_t)swap->handle);
if (swap->captured) {
if (global_hook_info->force_shmem) {