EXPORT bool gs_duplicator_update_frame(gs_duplicator_t *d) { DXGI_OUTDUPL_FRAME_INFO info; ComPtr<ID3D11Texture2D> tex; ComPtr<IDXGIResource> res; HRESULT hr; hr = d->duplicator->AcquireNextFrame(0, &info, res.Assign()); if (hr == DXGI_ERROR_ACCESS_LOST) { return false; } else if (hr == DXGI_ERROR_WAIT_TIMEOUT) { return true; } else if (FAILED(hr)) { blog(LOG_ERROR, "gs_duplicator_update_frame: Failed to update " "frame (%08lX)", hr); return true; } hr = res->QueryInterface(__uuidof(ID3D11Texture2D), (void**)tex.Assign()); if (FAILED(hr)) { blog(LOG_ERROR, "gs_duplicator_update_frame: Failed to query " "ID3D11Texture2D (%08lX)", hr); d->duplicator->ReleaseFrame(); return true; } copy_texture(d, tex); d->duplicator->ReleaseFrame(); return true; }
static inline void EnumD3DAdapters( bool (*callback)(void*, const char*, uint32_t), void *param) { ComPtr<IDXGIFactory1> factory; ComPtr<IDXGIAdapter1> adapter; HRESULT hr; UINT i = 0; IID factoryIID = (GetWinVer() >= 0x602) ? dxgiFactory2 : __uuidof(IDXGIFactory1); hr = CreateDXGIFactory1(factoryIID, (void**)factory.Assign()); if (FAILED(hr)) throw HRError("Failed to create DXGIFactory", hr); while (factory->EnumAdapters1(i++, adapter.Assign()) == S_OK) { DXGI_ADAPTER_DESC desc; char name[512] = ""; hr = adapter->GetDesc(&desc); if (FAILED(hr)) continue; /* ignore microsoft's 'basic' renderer' */ if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c) continue; os_wcs_to_utf8(desc.Description, 0, name, sizeof(name)); if (!callback(param, name, i - 1)) break; } }
gs_device::gs_device(gs_init_data *data) : curRenderTarget (NULL), curZStencilBuffer (NULL), curRenderSide (0), curIndexBuffer (NULL), curVertexBuffer (NULL), curVertexShader (NULL), curPixelShader (NULL), curSwapChain (&defaultSwap), zstencilStateChanged (true), rasterStateChanged (true), blendStateChanged (true), curDepthStencilState (NULL), curRasterState (NULL), curBlendState (NULL), curToplogy (D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) { ComPtr<IDXGIAdapter1> adapter; matrix4_identity(&curProjMatrix); matrix4_identity(&curViewMatrix); matrix4_identity(&curViewProjMatrix); memset(&viewport, 0, sizeof(viewport)); for (size_t i = 0; i < GS_MAX_TEXTURES; i++) { curTextures[i] = NULL; curSamplers[i] = NULL; } InitFactory(data->adapter, adapter.Assign()); InitDevice(data, adapter); device_set_render_target(this, NULL, NULL); }
void WASAPISource::InitClient() { CoTaskMemPtr<WAVEFORMATEX> wfex; HRESULT res; DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK; res = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)client.Assign()); if (FAILED(res)) throw HRError("Failed to activate client context", res); res = client->GetMixFormat(&wfex); if (FAILED(res)) throw HRError("Failed to get mix format", res); InitFormat(wfex); if (!isInputDevice) flags |= AUDCLNT_STREAMFLAGS_LOOPBACK; res = client->Initialize( AUDCLNT_SHAREMODE_SHARED, flags, BUFFER_TIME_100NS, 0, wfex, nullptr); if (FAILED(res)) throw HRError("Failed to get initialize audio client", res); }
void WASAPISource::InitRender() { CoTaskMemPtr<WAVEFORMATEX> wfex; HRESULT res; LPBYTE buffer; UINT32 frames; ComPtr<IAudioClient> client; res = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)client.Assign()); if (FAILED(res)) throw HRError("Failed to activate client context", res); res = client->GetMixFormat(&wfex); if (FAILED(res)) throw HRError("Failed to get mix format", res); res = client->Initialize( AUDCLNT_SHAREMODE_SHARED, 0, BUFFER_TIME_100NS, 0, wfex, nullptr); if (FAILED(res)) throw HRError("Failed to get initialize audio client", res); /* Silent loopback fix. Prevents audio stream from stopping and */ /* messing up timestamps and other weird glitches during silence */ /* by playing a silent sample all over again. */ res = client->GetBufferSize(&frames); if (FAILED(res)) throw HRError("Failed to get buffer size", res); res = client->GetService(__uuidof(IAudioRenderClient), (void**)render.Assign()); if (FAILED(res)) throw HRError("Failed to get render client", res); res = render->GetBuffer(frames, &buffer); if (FAILED(res)) throw HRError("Failed to get buffer", res); memset(buffer, 0, frames*wfex->nBlockAlign); render->ReleaseBuffer(frames, 0); }
bool WASAPISource::InitDevice(IMMDeviceEnumerator *enumerator) { HRESULT res; if (isDefaultDevice) { res = enumerator->GetDefaultAudioEndpoint( isInputDevice ? eCapture : eRender, isInputDevice ? eCommunications : eConsole, device.Assign()); } else { wchar_t *w_id; os_utf8_to_wcs_ptr(device_id.c_str(), device_id.size(), &w_id); res = enumerator->GetDevice(w_id, device.Assign()); bfree(w_id); } return SUCCEEDED(res); }
EXPORT bool device_get_duplicator_monitor_info(gs_device_t *device, int monitor_idx, struct gs_monitor_info *info) { DXGI_OUTPUT_DESC desc; HRESULT hr; try { ComPtr<IDXGIOutput> output; if (!get_monitor(device, monitor_idx, output.Assign())) return false; hr = output->GetDesc(&desc); if (FAILED(hr)) throw HRError("GetDesc failed", hr); } catch (HRError error) { blog(LOG_ERROR, "device_get_duplicator_monitor_info: " "%s (%08lX)", error.str, error.hr); return false; } switch (desc.Rotation) { case DXGI_MODE_ROTATION_UNSPECIFIED: case DXGI_MODE_ROTATION_IDENTITY: info->rotation_degrees = 0; break; case DXGI_MODE_ROTATION_ROTATE90: info->rotation_degrees = 90; break; case DXGI_MODE_ROTATION_ROTATE180: info->rotation_degrees = 180; break; case DXGI_MODE_ROTATION_ROTATE270: info->rotation_degrees = 270; break; } info->x = desc.DesktopCoordinates.left; info->y = desc.DesktopCoordinates.top; info->cx = desc.DesktopCoordinates.right - info->x; info->cy = desc.DesktopCoordinates.bottom - info->y; return true; }
Shader* D3D10VertexShader::CreateVertexShaderFromBlob(ShaderBlob const &blob, CTSTR lpShader, CTSTR lpFileName) { ShaderProcessor shaderProcessor; if (!shaderProcessor.ProcessShader(lpShader, lpFileName)) AppWarning(TEXT("Unable to process vertex shader '%s'"), lpFileName); //don't exit, leave it to the actual shader compiler to tell the errors //----------------------------------------------- if (!blob.size()) return nullptr; ComPtr<ID3D11VertexShader> vShader; ID3D11InputLayout *vShaderLayout; HRESULT err = GetD3D()->CreateVertexShader(&blob.front(), blob.size(), NULL, vShader.Assign()); if (FAILED(err)) { CrashError(TEXT("Unable to create vertex shader '%s', result = %08lX"), lpFileName, err); return NULL; } err = GetD3D()->CreateInputLayout(shaderProcessor.generatedLayout.Array(), shaderProcessor.generatedLayout.Num(), &blob.front(), blob.size(), &vShaderLayout); if (FAILED(err)) { CrashError(TEXT("Unable to create vertex layout for vertex shader '%s', result = %08lX"), lpFileName, err); return NULL; } //----------------------------------------------- D3D10VertexShader *shader = new D3D10VertexShader; shader->vertexShader = vShader.Detach(); shader->inputLayout = vShaderLayout; if (!shader->ProcessData(shaderProcessor, lpFileName)) { delete shader; return NULL; } shader->bHasNormals = shaderProcessor.bHasNormals; shader->bHasColors = shaderProcessor.bHasColors; shader->bHasTangents = shaderProcessor.bHasTangents; shader->nTextureCoords = shaderProcessor.numTextureCoords; shader->hViewProj = shader->GetParameterByName(TEXT("ViewProj")); return shader; }
gs_vertex_buffer::gs_vertex_buffer(gs_device_t device, struct gs_vb_data *data, uint32_t flags) : device (device), vbd (data), numVerts (data->num), dynamic ((flags & GS_DYNAMIC) != 0) { if (!data->num) throw "Cannot initialize vertex buffer with 0 vertices"; if (!data->points) throw "No points specified for vertex buffer"; InitBuffer(sizeof(vec3), data->num, data->points, vertexBuffer.Assign()); if (data->normals) InitBuffer(sizeof(vec3), data->num, data->normals, normalBuffer.Assign()); if (data->tangents) InitBuffer(sizeof(vec3), data->num, data->tangents, tangentBuffer.Assign()); if (data->colors) InitBuffer(sizeof(uint32_t), data->num, data->colors, colorBuffer.Assign()); for (size_t i = 0; i < data->num_tex; i++) { struct gs_tvertarray *tverts = data->tvarray+i; if (tverts->width != 2 && tverts->width != 4) throw "Invalid texture vertex size specified"; if (!tverts->array) throw "No texture vertices specified"; ComPtr<ID3D11Buffer> buffer; InitBuffer(tverts->width * sizeof(float), data->num, tverts->array, buffer.Assign()); uvBuffers.push_back(buffer); uvSizes.push_back(tverts->width * sizeof(float)); } if (!dynamic) vbd.Clear(); }
void gs_duplicator::Start() { ComPtr<IDXGIOutput1> output1; ComPtr<IDXGIOutput> output; HRESULT hr; if (!get_monitor(device, idx, output.Assign())) throw "Invalid monitor index"; hr = output->QueryInterface(__uuidof(IDXGIOutput1), (void**)output1.Assign()); if (FAILED(hr)) throw HRError("Failed to query IDXGIOutput1", hr); hr = output1->DuplicateOutput(device->device, duplicator.Assign()); if (FAILED(hr)) throw HRError("Failed to duplicate output", hr); }
void gs_shader::Compile(const char *shaderString, const char *file, const char *target, ID3D10Blob **shader) { ComPtr<ID3D10Blob> errorsBlob; HRESULT hr; if (!shaderString) throw "No shader string specified"; hr = device->d3dCompile(shaderString, strlen(shaderString), file, NULL, NULL, "main", target, D3D10_SHADER_OPTIMIZATION_LEVEL1, 0, shader, errorsBlob.Assign()); if (FAILED(hr)) { if (errorsBlob != NULL && errorsBlob->GetBufferSize()) throw ShaderError(errorsBlob, hr); else throw HRError("Failed to compile shader", hr); } }
void WASAPISource::Initialize() { ComPtr<IMMDeviceEnumerator> enumerator; HRESULT res; res = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)enumerator.Assign()); if (FAILED(res)) throw HRError("Failed to create enumerator", res); if (!InitDevice(enumerator)) return; device_name = GetDeviceName(device); InitClient(); InitCapture(); }
gs_pixel_shader::gs_pixel_shader(gs_device_t *device, const char *file, const char *shaderString) : gs_shader(device, GS_SHADER_PIXEL) { ShaderProcessor processor(device); ComPtr<ID3D10Blob> shaderBlob; string outputString; HRESULT hr; processor.Process(shaderString, file); processor.BuildString(outputString); processor.BuildParams(params); processor.BuildSamplers(samplers); BuildConstantBuffer(); Compile(outputString.c_str(), file, "ps_4_0", shaderBlob.Assign()); hr = device->device->CreatePixelShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL, shader.Assign()); if (FAILED(hr)) throw HRError("Failed to create vertex shader", hr); }
void WASAPISource::InitCapture() { HRESULT res = client->GetService(__uuidof(IAudioCaptureClient), (void**)capture.Assign()); if (FAILED(res)) throw HRError("Failed to create capture context", res); res = client->SetEventHandle(receiveSignal); if (FAILED(res)) throw HRError("Failed to set event handle", res); captureThread = CreateThread(nullptr, 0, WASAPISource::CaptureThread, this, 0, nullptr); if (!captureThread.Valid()) throw "Failed to create capture thread"; client->Start(); active = true; blog(LOG_INFO, "WASAPI: Device '%s' initialized", device_name.c_str()); }
gs_device::gs_device(const gs_init_data *data) : curSwapChain (&defaultSwap), curToplogy (D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) { ComPtr<IDXGIAdapter1> adapter; matrix4_identity(&curProjMatrix); matrix4_identity(&curViewMatrix); matrix4_identity(&curViewProjMatrix); memset(&viewport, 0, sizeof(viewport)); for (size_t i = 0; i < GS_MAX_TEXTURES; i++) { curTextures[i] = NULL; curSamplers[i] = NULL; } InitCompiler(); InitFactory(data->adapter, adapter.Assign()); InitDevice(data, adapter); device_set_render_target(this, NULL, NULL); }
gs_vertex_shader::gs_vertex_shader(gs_device_t *device, const char *file, const char *shaderString) : gs_shader (device, GS_SHADER_VERTEX), hasNormals (false), hasColors (false), hasTangents (false), nTexUnits (0) { vector<D3D11_INPUT_ELEMENT_DESC> inputs; ShaderProcessor processor(device); ComPtr<ID3D10Blob> shaderBlob; string outputString; HRESULT hr; processor.Process(shaderString, file); processor.BuildString(outputString); processor.BuildParams(params); processor.BuildInputLayout(inputs); GetBuffersExpected(inputs); BuildConstantBuffer(); Compile(outputString.c_str(), file, "vs_4_0", shaderBlob.Assign()); hr = device->device->CreateVertexShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL, shader.Assign()); if (FAILED(hr)) throw HRError("Failed to create vertex shader", hr); hr = device->device->CreateInputLayout(inputs.data(), (UINT)inputs.size(), shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), layout.Assign()); if (FAILED(hr)) throw HRError("Failed to create input layout", hr); viewProj = gs_shader_get_param_by_name(this, "ViewProj"); world = gs_shader_get_param_by_name(this, "World"); }