Esempio n. 1
0
static bool d3d8_shmem_init_buffer(IDirect3DDevice8 *device, int idx)
{
	HRESULT hr;

	hr = device->CreateImageSurface(data.cx, data.cy,
			data.d3d8_format, &data.copy_surfaces[idx]);
	if (FAILED(hr)) {
		hlog_hr("d3d8_shmem_init_buffer: Failed to create surface", hr);
		return false;
	}

	if (idx == 0) {
		D3DLOCKED_RECT rect;
		hr = data.copy_surfaces[0]->LockRect(&rect, nullptr,
				D3DLOCK_READONLY);
		if (FAILED(hr)) {
			hlog_hr("d3d8_shmem_init_buffer: Failed to lock buffer", hr);
			return false;
		}

		data.pitch = rect.Pitch;
		data.copy_surfaces[0]->UnlockRect();
	}

	return true;
}
Esempio n. 2
0
static bool d3d8_init_format_backbuffer(IDirect3DDevice8 *device)
{
	IDirect3DSurface8 *backbuffer;
	D3DSURFACE_DESC desc;
	HRESULT hr;

	if (!d3d8_get_window_handle(device))
		return false;

	backbuffer = d3d8_get_backbuffer(device);
	if (!backbuffer)
		return false;

	hr = backbuffer->GetDesc(&desc);
	backbuffer->Release();
	if (FAILED(hr)) {
		hlog_hr("d3d8_init_format_backbuffer: Failed to get "
				"backbuffer descriptor", hr);
		return false;
	}

	data.d3d8_format = desc.Format;
	data.dxgi_format = d3d8_to_dxgi_format(desc.Format);
	data.cx = desc.Width;
	data.cy = desc.Height;

	return true;
}
Esempio n. 3
0
static bool d3d9_shmem_init_buffers(size_t buffer)
{
	HRESULT hr;

	hr = data.device->CreateOffscreenPlainSurface(data.cx, data.cy,
			data.d3d9_format, D3DPOOL_SYSTEMMEM,
			&data.copy_surfaces[buffer], nullptr);
	if (FAILED(hr)) {
		hlog_hr("d3d9_shmem_init_buffers: Failed to create surface",
				hr);
		return false;
	}

	if (buffer == 0) {
		D3DLOCKED_RECT rect;
		hr = data.copy_surfaces[buffer]->LockRect(&rect, nullptr,
				D3DLOCK_READONLY);
		if (FAILED(hr)) {
			hlog_hr("d3d9_shmem_init_buffers: Failed to lock "
			        "buffer", hr);
			return false;
		}

		data.pitch = rect.Pitch;
		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)) {
		hlog_hr("d3d9_shmem_init_buffers: Failed to create query", hr);
		return false;
	}

	return true;
}
Esempio n. 4
0
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;
	}

	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];

		if (shmem_texture_data_lock(next_tex)) {
			dst->UnlockRect();
			data.texture_mapped[next_tex] = false;
			shmem_texture_data_unlock(next_tex);
		}

		hr = data.device->GetRenderTargetData(src, dst);
		if (FAILED(hr)) {
			hlog_hr("d3d9_shmem_capture: GetRenderTargetData "
			        "failed", hr);
		}

		data.queries[next_tex]->Issue(D3DISSUE_END);
		data.issued_queries[next_tex] = true;
	}

	data.cur_tex = next_tex;
}
Esempio n. 5
0
static inline bool d3d9_shtex_init_shtex()
{
	IDXGIResource *res;
	HRESULT hr;

	D3D11_TEXTURE2D_DESC desc = {};
	desc.Width                = data.cx;
	desc.Height               = data.cy;
	desc.Format               = data.dxgi_format;
	desc.MipLevels            = 1;
	desc.ArraySize            = 1;
	desc.SampleDesc.Count     = 1;
	desc.Usage                = D3D11_USAGE_DEFAULT;
	desc.MiscFlags            = D3D11_RESOURCE_MISC_SHARED;
	desc.BindFlags            = D3D11_BIND_RENDER_TARGET |
	                            D3D11_BIND_SHADER_RESOURCE;

	hr = data.d3d11_device->CreateTexture2D(&desc, nullptr,
			(ID3D11Texture2D**)&data.d3d11_tex);
	if (FAILED(hr)) {
		hlog_hr("d3d9_shtex_init_shtex: Failed to create D3D11 texture",
				hr);
		return false;
	}

	hr = data.d3d11_tex->QueryInterface(__uuidof(IDXGIResource),
			(void**)&res);
	if (FAILED(hr)) {
		hlog_hr("d3d9_shtex_init_shtex: Failed to query IDXGIResource",
				hr);
		return false;
	}

	hr = res->GetSharedHandle(&data.handle);
	res->Release();

	if (FAILED(hr)) {
		hlog_hr("d3d9_shtex_init_shtex: Failed to get shared handle",
				hr);
		return false;
	}

	return true;
}
Esempio n. 6
0
static inline bool gl_shtex_init_d3d11_tex(void)
{
	IDXGIResource *dxgi_res;
	HRESULT hr;

	D3D11_TEXTURE2D_DESC desc      = {0};
	desc.Width                     = data.cx;
	desc.Height                    = data.cy;
	desc.MipLevels                 = 1;
	desc.ArraySize                 = 1;
	desc.Format                    = DXGI_FORMAT_B8G8R8A8_UNORM;
	desc.SampleDesc.Count          = 1;
	desc.Usage                     = D3D11_USAGE_DEFAULT;
	desc.MiscFlags                 = D3D11_RESOURCE_MISC_SHARED;
	desc.BindFlags                 = D3D11_BIND_RENDER_TARGET |
	                                 D3D11_BIND_SHADER_RESOURCE;

	hr = ID3D11Device_CreateTexture2D(data.d3d11_device, &desc, NULL,
			&data.d3d11_tex);
	if (FAILED(hr)) {
		hlog_hr("gl_shtex_init_d3d11_tex: failed to create texture",
				hr);
		return false;
	}

	hr = ID3D11Device_QueryInterface(data.d3d11_tex,
			&GUID_IDXGIResource, (void**)&dxgi_res);
	if (FAILED(hr)) {
		hlog_hr("gl_shtex_init_d3d11_tex: failed to get IDXGIResource",
				hr);
		return false;
	}

	hr = IDXGIResource_GetSharedHandle(dxgi_res, &data.handle);
	IDXGIResource_Release(dxgi_res);

	if (FAILED(hr)) {
		hlog_hr("gl_shtex_init_d3d11_tex: failed to get shared handle",
				hr);
		return false;
	}

	return true;
}
Esempio n. 7
0
static inline bool d3d9_shtex_init_copytex()
{
	uint8_t *patch_addr = get_d3d9_patch_addr(data.d3d9, data.patch);
	uint8_t saved_data[MAX_PATCH_SIZE];
	size_t patch_size = 0;
	IDirect3DTexture9 *tex;
	DWORD protect_val;
	HRESULT hr;

	if (patch_addr) {
		patch_size = patch[data.patch].size;
		VirtualProtect(patch_addr, patch_size, PAGE_EXECUTE_READWRITE,
				&protect_val);
		memcpy(saved_data, patch_addr, patch_size);
		memcpy(patch_addr, patch[data.patch].data, patch_size);
	}

	hr = data.device->CreateTexture(data.cx, data.cy, 1,
			D3DUSAGE_RENDERTARGET, data.d3d9_format,
			D3DPOOL_DEFAULT, &tex, &data.handle);

	if (patch_addr && patch_size) {
		memcpy(patch_addr, saved_data, patch_size);
		VirtualProtect(patch_addr, patch_size, protect_val,
				&protect_val);
	}

	if (FAILED(hr)) {
		hlog_hr("d3d9_shtex_init_copytex: Failed to create shared texture",
				hr);
		return false;
	}

	hr = tex->GetSurfaceLevel(0, &data.d3d9_copytex);
	tex->Release();

	if (FAILED(hr)) {
		hlog_hr("d3d9_shtex_init_copytex: Failed to get surface level", hr);
		return false;
	}

	return true;
}
Esempio n. 8
0
static inline IUnknown *get_dxgi_backbuffer(IDXGISwapChain *swap)
{
    IDXGIResource *res = nullptr;
    HRESULT hr;

    hr = swap->GetBuffer(0, __uuidof(IUnknown), (void**)&res);
    if (FAILED(hr))
        hlog_hr("get_dxgi_backbuffer: GetBuffer failed", hr);

    return res;
}
Esempio n. 9
0
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);
	if (FAILED(hr))
		hlog_hr("d3d9_shtex_capture: StretchRect failed", hr);
}
Esempio n. 10
0
static bool d3d9_get_swap_desc(D3DPRESENT_PARAMETERS &pp)
{
	IDirect3DSwapChain9 *swap = nullptr;
	HRESULT hr;

	hr = data.device->GetSwapChain(0, &swap);
	if (FAILED(hr)) {
		hlog_hr("d3d9_get_swap_desc: Failed to get swap chain", hr);
		return false;
	}

	hr = swap->GetPresentParameters(&pp);
	swap->Release();

	if (FAILED(hr)) {
		hlog_hr("d3d9_get_swap_desc: Failed to get "
		        "presentation parameters", hr);
		return false;
	}

	return true;
}
Esempio n. 11
0
static IDirect3DSurface8 *d3d8_get_backbuffer(IDirect3DDevice8 *device)
{
	IDirect3DSurface8 *backbuffer;
	HRESULT hr;

	hr = device->GetRenderTarget(&backbuffer);
	if (FAILED(hr)) {
		hlog_hr("d3d8_get_backbuffer: Failed to get backbuffer", hr);
		backbuffer = nullptr;
	}

	return backbuffer;
}
Esempio n. 12
0
static bool d3d8_get_window_handle(IDirect3DDevice8 *device)
{
	D3DDEVICE_CREATION_PARAMETERS parameters;
	HRESULT hr;
	hr = device->GetCreationParameters(&parameters);
	if (FAILED(hr)) {
		hlog_hr("d3d8_get_window_handle: Failed to get "
				"device creation parameters", hr);
		return false;
	}

	data.window = parameters.hFocusWindow;

	return true;
}
Esempio n. 13
0
static bool d3d9_init_format_backbuffer(uint32_t &cx, uint32_t &cy,
		HWND &window)
{
	IDirect3DSurface9 *back_buffer = nullptr;
	D3DPRESENT_PARAMETERS pp;
	D3DSURFACE_DESC desc;
	HRESULT hr;

	if (!d3d9_get_swap_desc(pp)) {
		return false;
	}

	hr = data.device->GetRenderTarget(0, &back_buffer);
	if (FAILED(hr)) {
		return false;
	}

	hr = back_buffer->GetDesc(&desc);
	back_buffer->Release();

	if (FAILED(hr)) {
		hlog_hr("d3d9_init_format_backbuffer: Failed to get "
		        "backbuffer descriptor", hr);
		return false;
	}

	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;
	}

	return true;
}
Esempio n. 14
0
static inline void present_begin(IDirect3DDevice9 *device,
		IDirect3DSurface9 *&backbuffer)
{
	HRESULT hr;

	if (!present_recurse) {
		hr = get_backbuffer(device, &backbuffer);
		if (FAILED(hr)) {
			hlog_hr("d3d9_shmem_capture: Failed to get "
				"backbuffer", hr);
		}

		if (!global_hook_info->capture_overlay) {
			d3d9_capture(device, backbuffer);
		}
	}

	present_recurse++;
}
Esempio n. 15
0
static inline bool shex_init_d3d11()
{
	PFN_D3D11_CREATE_DEVICE create_device;
	createfactory1_t create_factory;
	D3D_FEATURE_LEVEL level_used;
	IDXGIFactory *factory;
	IDXGIAdapter *adapter;
	HMODULE d3d11;
	HMODULE dxgi;
	HRESULT hr;

	d3d11 = load_system_library("d3d11.dll");
	if (!d3d11) {
		hlog("d3d9_init: Failed to load D3D11");
		return false;
	}

	dxgi = load_system_library("dxgi.dll");
	if (!dxgi) {
		hlog("d3d9_init: Failed to load DXGI");
		return false;
	}

	create_factory = (createfactory1_t)GetProcAddress(dxgi,
			"CreateDXGIFactory1");
	if (!create_factory) {
		hlog("d3d9_init: Failed to get CreateDXGIFactory1 address");
		return false;
	}

	create_device = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d11,
			"D3D11CreateDevice");
	if (!create_device) {
		hlog("d3d9_init: Failed to get D3D11CreateDevice address");
		return false;
	}

	hr = create_factory(__uuidof(IDXGIFactory1), (void**)&factory);
	if (FAILED(hr)) {
		hlog_hr("d3d9_init: Failed to create factory object", hr);
		return false;
	}

	hr = factory->EnumAdapters(0, &adapter);
	factory->Release();

	if (FAILED(hr)) {
		hlog_hr("d3d9_init: Failed to get adapter", hr);
		return false;
	}

	hr = create_device(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
			0, feature_levels,
			sizeof(feature_levels) / sizeof(D3D_FEATURE_LEVEL),
			D3D11_SDK_VERSION, &data.d3d11_device, &level_used,
			&data.d3d11_context);
	adapter->Release();

	if (FAILED(hr)) {
		hlog_hr("d3d9_init: Failed to create D3D11 device", hr);
		return false;
	}

	return true;
}
Esempio n. 16
0
static inline bool gl_shtex_init_d3d11(void)
{
	D3D_FEATURE_LEVEL level_used;
	IDXGIFactory1 *factory;
	IDXGIAdapter *adapter;
	HRESULT hr;

	HMODULE d3d11 = load_system_library("d3d11.dll");
	if (!d3d11) {
		hlog("gl_shtex_init_d3d11: failed to load D3D11.dll: %d",
				GetLastError());
		return false;
	}

	HMODULE dxgi = load_system_library("dxgi.dll");
	if (!dxgi) {
		hlog("gl_shtex_init_d3d11: failed to load DXGI.dll: %d",
				GetLastError());
		return false;
	}

	DXGI_SWAP_CHAIN_DESC desc      = {0};
	desc.BufferCount               = 2;
	desc.BufferDesc.Format         = DXGI_FORMAT_B8G8R8A8_UNORM;
	desc.BufferDesc.Width          = 2;
	desc.BufferDesc.Height         = 2;
	desc.BufferUsage               = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	desc.SampleDesc.Count          = 1;
	desc.Windowed                  = true;
	desc.OutputWindow              = data.hwnd;

	create_dxgi_factory1_t create_factory = (void*)GetProcAddress(dxgi,
			"CreateDXGIFactory1");
	if (!create_factory) {
		hlog("gl_shtex_init_d3d11: failed to load CreateDXGIFactory1 "
		     "procedure: %d", GetLastError());
		return false;
	}

	PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN create = (void*)GetProcAddress(
			d3d11, "D3D11CreateDeviceAndSwapChain");
	if (!create) {
		hlog("gl_shtex_init_d3d11: failed to load "
		     "D3D11CreateDeviceAndSwapChain procedure: %d",
		     GetLastError());
		return false;
	}

	hr = create_factory(&GUID_IDXGIFactory1, (void**)&factory);
	if (FAILED(hr)) {
		hlog_hr("gl_shtex_init_d3d11: failed to create factory", hr);
		return false;
	}

	hr = IDXGIFactory1_EnumAdapters1(factory, 0, (IDXGIAdapter1**)&adapter);
	IDXGIFactory1_Release(factory);

	if (FAILED(hr)) {
		hlog_hr("gl_shtex_init_d3d11: failed to create adapter", hr);
		return false;
	}

	hr = create(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, feature_levels,
			sizeof(feature_levels) / sizeof(D3D_FEATURE_LEVEL),
			D3D11_SDK_VERSION, &desc, &data.dxgi_swap,
			&data.d3d11_device, &level_used, &data.d3d11_context);
	IDXGIAdapter_Release(adapter);

	if (FAILED(hr)) {
		hlog_hr("gl_shtex_init_d3d11: failed to create device", hr);
		return false;
	}

	return true;
}
Esempio n. 17
0
static DWORD CALLBACK copy_thread(LPVOID unused)
{
	uint32_t pitch = thread_data.pitch;
	uint32_t cy = thread_data.cy;
	HANDLE events[2] = {NULL, NULL};
	int shmem_id = 0;

	if (!duplicate_handle(&events[0], thread_data.copy_event)) {
		hlog_hr("copy_thread: Failed to duplicate copy event: %d",
				GetLastError());
		return 0;
	}

	if (!duplicate_handle(&events[1], thread_data.stop_event)) {
		hlog_hr("copy_thread: Failed to duplicate stop event: %d",
				GetLastError());
		goto finish;
	}

	for (;;) {
		int copy_tex;
		void *cur_data;

		DWORD ret = WaitForMultipleObjects(2, events, false, INFINITE);
		if (ret != WAIT_OBJECT_0) {
			break;
		}

		EnterCriticalSection(&thread_data.data_mutex);
		copy_tex = thread_data.cur_tex;
		cur_data = thread_data.cur_data;
		LeaveCriticalSection(&thread_data.data_mutex);

		if (copy_tex < NUM_BUFFERS && !!cur_data) {
			EnterCriticalSection(&thread_data.mutexes[copy_tex]);

			int lock_id = try_lock_shmem_tex(shmem_id);
			if (lock_id != -1) {
				memcpy(thread_data.shmem_textures[lock_id],
						cur_data, pitch * cy);

				unlock_shmem_tex(lock_id);
				((struct shmem_data*)shmem_info)->last_tex =
					lock_id;

				shmem_id = lock_id == 0 ? 1 : 0;
			}

			LeaveCriticalSection(&thread_data.mutexes[copy_tex]);
		}
	}

finish:
	for (size_t i = 0; i < 2; i++) {
		if (events[i]) {
			CloseHandle(events[i]);
		}
	}

	(void)unused;
	return 0;
}
Esempio n. 18
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;

    if (!dxgi_module) {
        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,
                                   global_hook_info->offsets.dxgi.present);
    resize_addr = get_offset_addr(dxgi_module,
                                  global_hook_info->offsets.dxgi.resize);

    hook_init(&present, present_addr, (void*)hook_present,
              "IDXGISwapChain::Present");
    hook_init(&resize_buffers, resize_addr, (void*)hook_resize_buffers,
              "IDXGISwapChain::ResizeBuffers");

    rehook(&resize_buffers);
    rehook(&present);

    hlog("Hooked DXGI");
    return true;
}