Texture *DX10Render::loadTextureFromFile(const wchar_t *file) { DX10Texture *result = new DX10Texture(); HRESULT hr = D3DX10CreateShaderResourceViewFromFile(device, file, NULL, NULL, &result->resourceView, NULL); if (FAILED(hr)) { switch (hr) { case D3D10_ERROR_FILE_NOT_FOUND: { //log() << "Texture file \"" << file << "\" does not exists" << std::endl; break; } default: { //log() << "Failed to load texture \"" << file << "\" does not exists" << std::endl; break; } } delete result; return NULL; } // Now when we have pointer to shader resource interface we can get pointer to texture itself ID3D10Resource *resource = NULL; result->resourceView->GetResource(&resource); resource->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&result->texture); resource->Release(); return result; }
// Loads a texture from a file and creates the resource view Texture::Texture(std::wstring filename, bool srgb) { HRESULT hresult; ID3D10Device *d3d10_device = engine.GetDevice(); ID3D10Resource *resource; if ((hresult = DirectX::CreateDDSTextureFromFileEx(d3d10_device, filename.c_str(), 0, D3D10_USAGE_DEFAULT, D3D10_BIND_SHADER_RESOURCE, 0, 0, srgb, &resource, &resource_view)) != S_OK) throw Exception(L"DirectX::CreateDDSTextureFromFile failed: " + GetD3D10Error(hresult)); D3D10_RESOURCE_DIMENSION dim; resource->GetType(&dim); if (dim != D3D10_RESOURCE_DIMENSION_TEXTURE2D) throw Exception(L"Texture: Only 2D textures are supported currently"); if ((hresult = resource->QueryInterface(__uuidof(ID3D10Texture2D), (LPVOID*)&texture)) != S_OK) throw Exception(L"Texture: QueryInterface failed: " + GetD3D10Error(hresult)); D3D10_TEXTURE2D_DESC desc; texture->GetDesc(&desc); width = desc.Width; height = desc.Height; SafeRelease(resource); }
Texture3D* Texture3D::FromBuffer(Buffer& buf, Renderer* pRender) { ID3D10Resource* pResource = NULL; HRESULT hr = D3DX10CreateTextureFromMemory( pRender->GetDevice(), //[in] ID3D10Device *pDevice, buf.GetPtr(), //[in] LPCVOID pSrcData, buf.GetSize(), //[in] SIZE_T SrcDataSize, NULL, //[in] D3DX10_IMAGE_LOAD_INFO *pLoadInfo, NULL, //[in] ID3DX10ThreadPump *pPump, &pResource, //[out] ID3D10Resource **ppTexture, NULL //[out] HRESULT *pHResult ); if (SUCCEEDED(hr)) { ID3D10Texture3D* ptr = NULL; hr = pResource->QueryInterface(IID_ID3D10Texture3D, (LPVOID*)&ptr); pResource->Release(); if (SUCCEEDED(hr)) { Texture3D* pTexture3D = new Texture3D(ptr); return pTexture3D; } } return NULL; }
//----------------------------------------------------------------------------// void Direct3D10Texture::initialiseShaderResourceView() { if (!d_texture) return; D3D10_TEXTURE2D_DESC tex_desc; d_texture->GetDesc(&tex_desc); ID3D10Resource* resource = 0; d_texture->QueryInterface(__uuidof(ID3D10Resource), reinterpret_cast<LPVOID*>(&resource)); D3D10_SHADER_RESOURCE_VIEW_DESC srvd; srvd.Format = tex_desc.Format; srvd.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; srvd.Texture2D.MostDetailedMip = 0; srvd.Texture2D.MipLevels = tex_desc.MipLevels; d_device.CreateShaderResourceView(resource, &srvd, &d_resourceView); resource->Release(); }
TextureID Texture_Create( const char* filename ) { unsigned handle = 0; // Create from the free list if we can if( Texture_freelist_count > 0 ) { handle = Texture_freelist[ Texture_freelist_count - 1 ]; Texture_freelist_count--; } else // And only expand the range if free list is empty { assert( Texture_Count < MAX_TEXTURES ); handle = Texture_Count; Texture_Count++; } //load the texture Texture* Texture = &Textures[ handle ]; HRESULT load_texture = D3DX10CreateShaderResourceViewFromFile( dx_device, filename, NULL, NULL, &Texture->texture, NULL ); assert( SUCCEEDED( load_texture ) ); ID3D10Resource* res; Texture->texture->GetResource( &res ); D3D10_TEXTURE2D_DESC desc2D; ((ID3D10Texture2D*)res)->GetDesc(&desc2D); /*Texture->transform.position[0] = x / GAME_RESOLUTION_X; Texture->transform.position[1] = y / GAME_RESOLUTION_Y; Texture->transform.position[2] = 0; Texture->transform.scale[0] = (float)(desc2D.Width/(float)GAME_RESOLUTION_X); Texture->transform.scale[1] = (float)(desc2D.Height/(float)GAME_RESOLUTION_Y); Texture->transform.rotation = 180;*/ res->Release(); return handle; }
HRESULT CSurfaceQueueDeviceD3D10::CopySurface(IUnknown* pDst, IUnknown* pSrc, UINT width, UINT height) { HRESULT hr; D3D10_BOX UnitBox = {0, 0, 0, width, height, 1}; ID3D10Resource* pSrcRes = NULL; ID3D10Resource* pDstRes = NULL; if (FAILED(hr = pDst->QueryInterface(__uuidof(ID3D10Resource), (void**)&pDstRes))) { goto end; } if (FAILED(hr = pSrc->QueryInterface(__uuidof(ID3D10Resource), (void**)&pSrcRes))) { goto end; } m_pDevice->CopySubresourceRegion( pDstRes, 0, 0, 0, 0, //(x, y, z) pSrcRes, 0, &UnitBox); end: if (pSrcRes) { pSrcRes->Release(); } if (pDstRes) { pDstRes->Release(); } return hr; }
Texture1D* Texture1D::FromFile(LPCTSTR pFileName, Renderer* pRender) { ID3D10Resource* pResource = NULL; HRESULT hr = D3DX10CreateTextureFromFile( pRender->GetDevice(), //[in] ID3D10Device *pDevice, pFileName, //[in] LPCTSTR pSrcFile, NULL, //[in] D3DX10_IMAGE_LOAD_INFO *pLoadInfo, NULL, //[in] ID3DX10ThreadPump *pPump, &pResource, //[out] ID3D10Resource **ppTexture, NULL //[out] HRESULT *pHResult ); if (SUCCEEDED(hr)) { ID3D10Texture1D* ptr = NULL; hr = pResource->QueryInterface(IID_ID3D10Texture1D, (LPVOID*)&ptr); pResource->Release(); if (SUCCEEDED(hr)) { Texture1D* pTexture1D = new Texture1D(ptr); return pTexture1D; } } return NULL; }
// Detour function that replaces the IDXGISwapChain::Present() API DllExport HRESULT __stdcall hook_DXGISwapChainPresent( IDXGISwapChain * This, UINT SyncInterval, UINT Flags ) { static int frame_interval; static LARGE_INTEGER initialTv, captureTv, freq; static int capture_initialized = 0; // int i; struct pooldata *data; struct vsource_frame *frame; // DXGI_SWAP_CHAIN_DESC pDESC; HRESULT hr = pDXGISwapChainPresent(This, SyncInterval, Flags); if(resolution_retrieved == 0) { if(DXGI_get_resolution(This) >= 0) { resolution_retrieved = 1; } return hr; } if(vsource_initialized == 0) { ga_error("video source not initialized.\n"); return hr; } This->GetDesc(&pDESC); pDXGI_FORMAT = pDESC.BufferDesc.Format; // extract screen format for sws_scale if(pDESC.BufferDesc.Width != game_width || pDESC.BufferDesc.Height != game_height) { ga_error("game width/height mismatched (%dx%d) != (%dx%d)\n", pDESC.BufferDesc.Width, pDESC.BufferDesc.Height, game_width, game_height); return hr; } // if (enable_server_rate_control && ga_hook_video_rate_control() < 0) return hr; if (dx_version == dx_none) { //bool check_result = FALSE; if (check_dx_device_version(This, IID_ID3D10Device)) { dx_version = dx_10; ga_error("[DXGISwapChain] DirectX 10\n"); } else if (check_dx_device_version(This, IID_ID3D10Device1)) { dx_version = dx_10_1; ga_error("[DXGISwapChain] DirectX 10.1\n"); } else if (check_dx_device_version(This, IID_ID3D11Device)) { dx_version = dx_11; ga_error("[DXGISwapChain] DirectX 11\n"); } } if (capture_initialized == 0) { frame_interval = 1000000/video_fps; // in the unif of us frame_interval++; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&initialTv); capture_initialized = 1; } else { QueryPerformanceCounter(&captureTv); } hr = 0; // d3d10 / d3d10.1 if (dx_version == dx_10 || dx_version == dx_10_1) { void *ppDevice; ID3D10Device *pDevice; //IUnknown *pDevice; if (dx_version == dx_10) { This->GetDevice(IID_ID3D10Device, &ppDevice); pDevice = (ID3D10Device *)ppDevice; } else if (dx_version == dx_10_1) { This->GetDevice(IID_ID3D10Device1, &ppDevice); pDevice = (ID3D10Device1 *)ppDevice; } else { OutputDebugString("Invalid DirectX version in IDXGISwapChain::Present"); return hr; } ID3D10RenderTargetView *pRTV = NULL; ID3D10Resource *pSrcResource = NULL; pDevice->OMGetRenderTargets(1, &pRTV, NULL); pRTV->GetResource(&pSrcResource); ID3D10Texture2D* pSrcBuffer = (ID3D10Texture2D *)pSrcResource; ID3D10Texture2D* pDstBuffer = NULL; D3D10_TEXTURE2D_DESC desc; pSrcBuffer->GetDesc(&desc); desc.BindFlags = 0; desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; desc.Usage = D3D10_USAGE_STAGING; hr = pDevice->CreateTexture2D(&desc, NULL, &pDstBuffer); if (FAILED(hr)) { OutputDebugString("Failed to create texture2D"); //assert(exp_state == exp_none); } pDevice->CopyResource(pDstBuffer, pSrcBuffer); D3D10_MAPPED_TEXTURE2D mapped_screen; hr = pDstBuffer->Map(0, D3D10_MAP_READ, 0, &mapped_screen); if (FAILED(hr)) { OutputDebugString("Failed to map from DstBuffer"); //assert(exp_state == exp_none); } // copy image do { unsigned char *src, *dst; data = g_pipe[0]->allocate_data(); frame = (struct vsource_frame*) data->ptr; frame->pixelformat = PIX_FMT_BGRA; frame->realwidth = desc.Width; frame->realheight = desc.Height; frame->realstride = desc.Width<<2; frame->realsize = frame->realwidth * frame->realstride; frame->linesize[0] = frame->realstride;//frame->stride; // src = (unsigned char*) mapped_screen.pData; dst = (unsigned char*) frame->imgbuf; for (i = 0; i < encoder_height; i++) { CopyMemory(dst, src, frame->realstride/*frame->stride*/); src += mapped_screen.RowPitch; dst += frame->realstride;//frame->stride; } frame->imgpts = pcdiff_us(captureTv, initialTv, freq)/frame_interval; } while(0); // duplicate from channel 0 to other channels for(i = 1; i < SOURCES; i++) { int j; struct pooldata *dupdata; struct vsource_frame *dupframe; dupdata = g_pipe[i]->allocate_data(); dupframe = (struct vsource_frame*) dupdata->ptr; // vsource_dup_frame(frame, dupframe); // g_pipe[i]->store_data(dupdata); g_pipe[i]->notify_all(); } g_pipe[0]->store_data(data); g_pipe[0]->notify_all(); pDstBuffer->Unmap(0); pDevice->Release(); pSrcResource->Release(); pSrcBuffer->Release(); pRTV->Release(); pDstBuffer->Release(); // d11 } else if (dx_version == dx_11) { void *ppDevice; This->GetDevice(IID_ID3D11Device, &ppDevice); ID3D11Device *pDevice = (ID3D11Device*) ppDevice; This->GetDevice(IID_ID3D11DeviceContext, &ppDevice); ID3D11DeviceContext *pDeviceContext = (ID3D11DeviceContext *) ppDevice; ID3D11RenderTargetView *pRTV = NULL; ID3D11Resource *pSrcResource = NULL; pDeviceContext->OMGetRenderTargets(1, &pRTV, NULL); pRTV->GetResource(&pSrcResource); ID3D11Texture2D *pSrcBuffer = (ID3D11Texture2D *)pSrcResource; ID3D11Texture2D *pDstBuffer = NULL; D3D11_TEXTURE2D_DESC desc; pSrcBuffer->GetDesc(&desc); desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.Usage = D3D11_USAGE_STAGING; hr = pDevice->CreateTexture2D(&desc, NULL, &pDstBuffer); if (FAILED(hr)) { OutputDebugString("Failed to create buffer"); //assert(exp_state == exp_none); } pDeviceContext->CopyResource(pDstBuffer, pSrcBuffer); D3D11_MAPPED_SUBRESOURCE mapped_screen; hr = pDeviceContext->Map(pDstBuffer, 0, D3D11_MAP_READ, 0, &mapped_screen); if (FAILED(hr)) { OutputDebugString("Failed to map from DeviceContext"); //assert(exp_state == exp_none); } // copy image do { unsigned char *src, *dst; data = g_pipe[0]->allocate_data(); frame = (struct vsource_frame*) data->ptr; frame->pixelformat = PIX_FMT_BGRA; frame->realwidth = desc.Width; frame->realheight = desc.Height; frame->realstride = desc.Width<<2; frame->realsize = frame->realwidth * frame->realstride; frame->linesize[0] = frame->realstride;//frame->stride; // src = (unsigned char*) mapped_screen.pData; dst = (unsigned char*) frame->imgbuf; for (i = 0; i < encoder_height; i++) { CopyMemory(dst, src, frame->realstride/*frame->stride*/); src += mapped_screen.RowPitch; dst += frame->realstride;//frame->stride; } frame->imgpts = pcdiff_us(captureTv, initialTv, freq)/frame_interval; } while(0); // duplicate from channel 0 to other channels for(i = 1; i < SOURCES; i++) { int j; struct pooldata *dupdata; struct vsource_frame *dupframe; dupdata = g_pipe[i]->allocate_data(); dupframe = (struct vsource_frame*) dupdata->ptr; // vsource_dup_frame(frame, dupframe); // g_pipe[i]->store_data(dupdata); g_pipe[i]->notify_all(); } g_pipe[0]->store_data(data); g_pipe[0]->notify_all(); pDeviceContext->Unmap(pDstBuffer, 0); pDevice->Release(); pDeviceContext->Release(); pSrcResource->Release(); pSrcBuffer->Release(); pRTV->Release(); pDstBuffer->Release(); } return hr; }
BOOL DXMessD3D10Handler::UpdateTextures() { //call this each time the resolution changes (when the buffer changes) HRESULT hr; ID3D10Resource *test; ID3D10Texture2D *texturex; DXGI_SWAP_CHAIN_DESC desc; int i; int newTextureCount; WaitForSingleObject((HANDLE)(shared->TextureLock), INFINITE); if (shared->textureCount) { ZeroMemory(&desc, sizeof(desc)); hr=swapchain->GetDesc(&desc); if (FAILED(hr)) return hr; newTextureCount=shared->textureCount; if (shared->textureCount > TextureCount) { //update the textures if needed if (textures==NULL) //initial alloc textures=(TextureData10 *)malloc(sizeof(TextureData10)* shared->textureCount); else //realloc textures=(TextureData10 *)realloc(textures, sizeof(TextureData10)* shared->textureCount); //initialize the new entries to NULL for (i=TextureCount; i<shared->textureCount; i++) { textures[i].pTexture=NULL; textures[i].DefinedFontMap=NULL; } } for (i=0; i<newTextureCount; i++) { if (tea[i].AddressOfTexture) { if ((tea[i].hasBeenUpdated) || (textures[i].pTexture==NULL)) { if (textures[i].pTexture) { //already has a texture, so an update. Free the old one first textures[i].pTexture->Release(); textures[i].pTexture=NULL; //should always happen } if (textures[i].DefinedFontMap) { //already has a fontmap. Free the old one free(textures[i].DefinedFontMap); textures[i].DefinedFontMap=NULL; } hr=D3DX10CreateTextureFromMemory(dev, (void *)(tea[i].AddressOfTexture), tea[i].size, NULL, NULL, &test, NULL); if( FAILED( hr ) ) { OutputDebugStringA("Failure creating a texture"); return hr; } hr=test->QueryInterface(__uuidof(ID3D10Texture2D), (void **)(&texturex)); hr=dev->CreateShaderResourceView(test, NULL, &textures[i].pTexture); if( FAILED( hr ) ) return hr; test->Release(); texturex->Release(); if (tea[i].AddressOfFontmap) { int j; float currentOffset=0; textures[i].DefinedFontMap=(PFONTMAP)malloc(sizeof(FONTMAP)); //now parse the fontmap provided by ce and fill in the gaps WORD *cefontmap=(WORD *)(tea[i].AddressOfFontmap); textures[i].DefinedFontMap->charheight=(float)cefontmap[0]; for (j=0; j<96; j++) { textures[i].DefinedFontMap->charinfo[j].offset=currentOffset; textures[i].DefinedFontMap->charinfo[j].charwidth=(float)cefontmap[j+1]; currentOffset+=cefontmap[j+1]; } textures[i].DefinedFontMap->fullwidth=currentOffset; } tea[i].hasBeenUpdated=0; } } else { //It's NULL (cleanup) if (textures[i].pTexture) { textures[i].pTexture->Release(); textures[i].pTexture=NULL; } if (textures[i].DefinedFontMap) { free(textures[i].DefinedFontMap); textures[i].DefinedFontMap=NULL; } } } TextureCount=newTextureCount; } if (shared->texturelistHasUpdate) InterlockedExchange((volatile LONG *)&shared->texturelistHasUpdate,0); SetEvent((HANDLE)(shared->TextureLock)); return TRUE; }
Texture* D3D10Texture::CreateFromSharedHandle(unsigned int width, unsigned int height, HANDLE handle) { HRESULT err; if(!handle) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: NULL handle value.")); return NULL; } ID3D10Resource *tempResource; if(FAILED(err = GetD3D()->OpenSharedResource(handle, __uuidof(ID3D10Resource), (void**)&tempResource))) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: Failed to open shared handle, result = 0x%08lX"), err); return NULL; } ID3D10Texture2D *texVal; if(FAILED(err = tempResource->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&texVal))) { SafeRelease(tempResource); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: could not query interface, result = 0x%08lX"), err); return NULL; } tempResource->Release(); //------------------------------------------ D3D10_TEXTURE2D_DESC td; texVal->GetDesc(&td); //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = td.Format; //resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = 1; //resourceDesc.ViewDimension = D3D10_1_SRV_DIMENSION_TEXTURE2D; resourceDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; ID3D10ShaderResourceView *resource = NULL; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = GetGSFormatFromDXGIFormat(td.Format);; newTex->resource = resource; newTex->texture = texVal; newTex->bDynamic = false; newTex->width = width; newTex->height = height; return newTex; }
Texture* D3D10Texture::CreateFromFile(CTSTR lpFile, BOOL bBuildMipMaps) { HRESULT err; D3DX10_IMAGE_INFO ii; if(FAILED(D3DX10GetImageInfoFromFile(lpFile, NULL, &ii, NULL))) { AppWarning(TEXT("D3D10Texture::CreateFromFile: Could not get information about texture file '%s'"), lpFile); return NULL; } //------------------------------------------ if(bBuildMipMaps && (!IsPow2(ii.Width) || !IsPow2(ii.Height))) bBuildMipMaps = FALSE; D3DX10_IMAGE_LOAD_INFO ili; ili.Width = D3DX10_DEFAULT; ili.Height = D3DX10_DEFAULT; ili.Depth = D3DX10_DEFAULT; ili.FirstMipLevel = D3DX10_DEFAULT; ili.MipLevels = bBuildMipMaps ? 0 : 1; ili.Usage = (D3D10_USAGE)D3DX10_DEFAULT; ili.BindFlags = D3DX10_DEFAULT; ili.CpuAccessFlags = D3DX10_DEFAULT; ili.MiscFlags = D3DX10_DEFAULT; ili.Format = (DXGI_FORMAT)D3DX10_DEFAULT; ili.Filter = D3DX10_DEFAULT; ili.MipFilter = D3DX10_DEFAULT; ili.pSrcInfo = NULL; ID3D10Resource *texResource; if(FAILED(err = D3DX10CreateTextureFromFile(GetD3D(), lpFile, &ili, NULL, &texResource, NULL))) { AppWarning(TEXT("D3D10Texture::CreateFromFile: failed to load '%s'"), lpFile); return NULL; } //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = ii.Format; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = bBuildMipMaps ? -1 : 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texResource, &resourceDesc, &resource))) { SafeRelease(texResource); AppWarning(TEXT("D3D10Texture::CreateFromFile: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ ID3D10Texture2D *tex2D; err = texResource->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&tex2D); if(FAILED(err)) { SafeRelease(texResource); SafeRelease(resource); AppWarning(TEXT("D3D10Texture::CreateFromFile: could not query texture interface")); return NULL; } texResource->Release(); //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->resource = resource; newTex->texture = tex2D; newTex->width = ii.Width; newTex->height = ii.Height; switch(ii.Format) { case DXGI_FORMAT_R8_UNORM: newTex->format = GS_ALPHA; break; case DXGI_FORMAT_A8_UNORM: newTex->format = GS_GRAYSCALE; break; case DXGI_FORMAT_B8G8R8X8_UNORM: newTex->format = GS_BGR; break; case DXGI_FORMAT_B8G8R8A8_UNORM: newTex->format = GS_BGRA; break; case DXGI_FORMAT_R8G8B8A8_UNORM: newTex->format = GS_RGBA; break; case DXGI_FORMAT_R16G16B16A16_FLOAT: newTex->format = GS_RGBA16F; break; case DXGI_FORMAT_R32G32B32A32_FLOAT: newTex->format = GS_RGBA32F; break; case DXGI_FORMAT_BC1_UNORM: newTex->format = GS_DXT1; break; case DXGI_FORMAT_BC2_UNORM: newTex->format = GS_DXT3; break; case DXGI_FORMAT_BC3_UNORM: newTex->format = GS_DXT5; break; default: newTex->format = GS_UNKNOWNFORMAT; } return newTex; }
Texture* D3D10Texture::CreateFromSharedHandle(unsigned int width, unsigned int height, GSColorFormat colorFormat, HANDLE handle) { HRESULT err; if(colorFormat >= GS_DXT1) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: tried to a blank DXT shared texture.")); return NULL; } if(!handle) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: NULL handle value.")); return NULL; } ID3D10Resource *tempResource; if(FAILED(err = GetD3D()->OpenSharedResource(handle, __uuidof(ID3D10Resource), (void**)&tempResource))) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: Failed to open shared handle, result = 0x%08lX"), err); return NULL; } ID3D10Texture2D *texVal; if(FAILED(err = tempResource->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&texVal))) { SafeRelease(tempResource); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: could not query interface, result = 0x%08lX"), err); return NULL; } tempResource->Release(); //------------------------------------------ IDXGIKeyedMutex *km; if(FAILED(err = texVal->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&km))) { //SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: could not query keyed mutex interface, result = 0x%08lX"), err); //return NULL; } //------------------------------------------ DXGI_FORMAT format = convertFormat[(UINT)colorFormat]; D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = format; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = colorFormat; newTex->resource = resource; newTex->texture = texVal; newTex->keyedMutex = km; newTex->bDynamic = false; newTex->width = width; newTex->height = height; return newTex; }
void DoD3D10Capture(IDXGISwapChain *swap) { ID3D10Device *device = NULL; if(SUCCEEDED(swap->GetDevice(__uuidof(ID3D10Device), (void**)&device))) { if(!lpCurrentDevice) { lpCurrentDevice = device; /*FARPROC oldRelease = GetVTable(device, (8/4)); if(oldRelease != newD3D10Release) { oldD3D10Release = oldRelease; newD3D10Release = ConvertClassProcToFarproc((CLASSPROC)&D3D10Override::DeviceReleaseHook); SetVTable(device, (8/4), newD3D10Release); }*/ } if(bCapturing && bStopRequested) { ClearD3D10Data(); bCapturing = false; bStopRequested = false; } if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0) { hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL); if(hwndOBS) bCapturing = true; } if(!bHasTextures && bCapturing) { if(dxgiFormat && hwndOBS) { BOOL bSuccess = DoD3D10Hook(device); if(bSuccess) { d3d10CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData); if(!d3d10CaptureInfo.mapID) bSuccess = false; } if(bSuccess) { bHasTextures = true; d3d10CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX; d3d10CaptureInfo.bFlip = FALSE; texData->texHandle = (DWORD)sharedHandle; memcpy(infoMem, &d3d10CaptureInfo, sizeof(CaptureInfo)); SetEvent(hSignalReady); logOutput << "DoD3D10Hook: success" << endl; } else { ClearD3D10Data(); } } } if(bHasTextures) { LONGLONG timeVal = OSGetTimeMicroseconds(); //check keep alive state, dumb but effective if(bCapturing) { if((timeVal-keepAliveTime) > 3000000) { HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str()); if (hKeepAlive) { CloseHandle(hKeepAlive); } else { ClearD3D10Data(); bCapturing = false; } keepAliveTime = timeVal; } } LONGLONG frameTime; if(bCapturing) { if(texData) { if(frameTime = texData->frameTime) { LONGLONG timeElapsed = timeVal-lastTime; if(timeElapsed >= frameTime) { if(!IsWindow(hwndOBS)) { hwndOBS = NULL; bStopRequested = true; } if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0) bStopRequested = true; lastTime += frameTime; if(timeElapsed > frameTime*2) lastTime = timeVal; DWORD nextCapture = curCapture == 0 ? 1 : 0; ID3D10Resource *backBuffer = NULL; if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D10Resource, (void**)&backBuffer))) { if(bIsMultisampled) device->ResolveSubresource(copyD3D10TextureGame, 0, backBuffer, 0, dxgiFormat); else device->CopyResource(copyD3D10TextureGame, backBuffer); backBuffer->Release(); } curCapture = nextCapture; } } } } else ClearD3D10Data(); } } device->Release(); }
void IDXGISwapChainNew::preUpdateBB(UINT *width, UINT *height) { dbg("dxgi_sc: preUpdateBB"); int rrx = config.main.renderResolution.x; int rry = config.main.renderResolution.y; if(*width == rrx && *height == rry) { dbg("dxgi_sc: Multihead swapchain mode detected"); HEAD *h = config.getPrimaryHead(); *width = h->screenMode.x; *height = h->screenMode.y; // Set mouse hook on application focus window ihGlobal.setHWND(win); SoftTHActive++; h->hwnd = win; // Create new backbuffer dbg("dxgi_sc: Creating new backbuffer"); // TODO: format #if defined(SOFTTHMAIN) || defined(D3D11) if(dev11) { // Create the full backbuffer render texture dbg("dxgi_sc: Creating FULL backbuffer for D3D11 Device"); //CD3D10_TEXTURE2D_DESC d(DXGI_FORMAT_R8G8B8A8_UNORM, rrx, rry, 1, 1, D3D10_BIND_RENDER_TARGET, D3D10_USAGE_DEFAULT, NULL); CD3D11_TEXTURE2D_DESC d(DXGI_FORMAT_R8G8B8A8_UNORM, rrx, rry, 1, 1, D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, NULL); newbbDesc11 = d; if(dev11->CreateTexture2D(&newbbDesc11, NULL, &newbb11) != S_OK) dbg("dxgi_sc: CreateTexture2D failed :("), exit(0); // Initialize outputs numDevs = config.getNumAdditionalHeads(); dbg("dxgi_sc: Initializing %d outputs", numDevs); int logoStopTime = GetTickCount() + 4000; bool fpuPreserve = true; // TODO: does this exist in d3d10? outDevs11 = new OUTDEVICE11[numDevs]; stagingOuts11 = new STAGINGOUT11[numDevs]; for(int i=0;i<numDevs;i++) { OUTDEVICE11 *o = &outDevs11[i]; STAGINGOUT11 *so = &stagingOuts11[i]; so->headID = i+1; so->devID = h->devID; so->stagingSurf = NULL; // Create the output device HEAD *h = config.getHead(i); dbg("dxgi_sc: Initializing Head %d (DevID: %d)",i+1,h->devID); o->output = new outDirect3D11(h->devID, h->screenMode.x, h->screenMode.y, h->transportRes.x, h->transportRes.y, win); o->cfg = h; bool local = h->transportMethod==OUTMETHOD_LOCAL; if (!local) has_nonlocal = true; dbg("dxgi_sc: Head %d is %s", i+1, local?"local":"non-local"); // Create a main staging buffer sized for this head if non-local if (!local) { dbg("dxgi_sc: Creating a main non-local staging buffer for Head %d (DevID %d)", i + 1, h->devID); CD3D11_TEXTURE2D_DESC dss(DXGI_FORMAT_R8G8B8A8_UNORM, h->transportRes.x, h->transportRes.y, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, 1, 0, 0); /*DWORD32 *fillbuf = new DWORD32[h->transportRes.x*h->transportRes.y]; for (int ii = 0; ii < h->transportRes.y; ii++) for (int jj = 0; jj < h->transportRes.x; jj++) { if ((ii&32)==(jj&32)) fillbuf[ii*h->transportRes.x + jj] = (DWORD32) 0x0000ff00; else fillbuf[ii*h->transportRes.x + jj] = (DWORD32) 0xffffffff; } D3D11_SUBRESOURCE_DATA fillsr; ZeroMemory(&fillsr, sizeof(fillsr)); fillsr.pSysMem = (void *)fillbuf; fillsr.SysMemPitch = h->transportRes.x * 4; fillsr.SysMemSlicePitch = h->transportRes.x * h->transportRes.y * 4; if (dev11->CreateTexture2D(&dss, &fillsr, &so->stagingSurf) != S_OK) {*/ if (dev11->CreateTexture2D(&dss, NULL, &so->stagingSurf) != S_OK) { dbg("dxgi_sc: CreateTexture2D staged for Head %d (DevID %d) failed :(",i+1,h->devID), exit(0); } } // Create shared surfaces HANDLE sha = o->output->GetShareHandle(); if(sha) { o->localSurf = NULL; { // Open surfA share handle ID3D11Resource *tr; if (o->cfg->transportMethod == OUTMETHOD_LOCAL) { // Local output if (dev11->OpenSharedResource(sha, __uuidof(ID3D11Resource), (void**)(&tr)) != S_OK) dbg("dxgi_sc: Local OpenSharedResource A failed!"), exit(0); } else { // Non-local output if (o->output->dev->OpenSharedResource(sha, __uuidof(ID3D11Resource), (void**)(&tr)) != S_OK) dbg("dxgi_sc: Non-local OpenSharedResource A failed!"), exit(0); } if(tr->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&o->localSurf)) != S_OK) dbg("dxgi_sc: Shared surface QueryInterface failed!"), exit(0); tr->Release(); } dbg("dxgi_sc: Opened share handles"); } else dbg("dxgi_sc: ERROR: Head %d: No share handle!", i+1), exit(0); } // Create the full backbuffer staged texture if we have non-local head /*if (has_nonlocal) { CD3D11_TEXTURE2D_DESC ds(DXGI_FORMAT_R8G8B8A8_UNORM, rrx, rry, 1, 1, NULL, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ, 1, 0, D3D11_RESOURCE_MISC_SHARED); newbbDesc11staged = ds; if(dev11->CreateTexture2D(&newbbDesc11staged, NULL, &newbb11staged) != S_OK) dbg("dxgi_sc: CreateTexture2D staged failed :("), exit(0); }*/ } #endif #ifdef SOFTTHMAIN else #endif #if defined(SOFTTHMAIN) || defined(D3D10_1) if(dev10_1) { dbg("dxgi_sc: Creating backbuffer for D3D10.1 Device"); CD3D10_TEXTURE2D_DESC d(DXGI_FORMAT_R8G8B8A8_UNORM, rrx, rry, 1, 1, D3D10_BIND_RENDER_TARGET, D3D10_USAGE_DEFAULT, NULL); newbbDesc10 = d; if(dev10_1->CreateTexture2D(&newbbDesc10, NULL, &newbb10) != S_OK) dbg("dxgi_sc: CreateTexture2D failed :("), exit(0); // Initialize outputs numDevs = config.getNumAdditionalHeads(); dbg("dxgi_sc: Initializing %d outputs", numDevs); int logoStopTime = GetTickCount() + 4000; bool fpuPreserve = true; // TODO: does this exist in d3d10? outDevs10 = new OUTDEVICE10[numDevs]; for(int i=0;i<numDevs;i++) { OUTDEVICE10 *o = &outDevs10[i]; // Create the output device HEAD *h = config.getHead(i); bool local = h->transportMethod==OUTMETHOD_LOCAL; dbg("dxgi_sc: Initializing head %d (DevID: %d, %s)...", i+1, h->devID, local?"local":"non-local"); o->output = new outDirect3D10(h->devID, h->screenMode.x, h->screenMode.y, h->transportRes.x, h->transportRes.y, win); o->cfg = h; // Create shared surfaces HANDLE sha = o->output->GetShareHandle(); if(sha) { o->localSurf = NULL; { // Open surfA share handle ID3D10Resource *tr; if(dev10_1->OpenSharedResource(sha, __uuidof(ID3D10Resource), (void**)(&tr)) != S_OK) dbg("dxgi_sc: OpenSharedResource A failed!"), exit(0); if(tr->QueryInterface(__uuidof(ID3D10Texture2D), (void**)(&o->localSurf)) != S_OK) dbg("dxgi_sc: Shared surface QueryInterface failed!"), exit(0); tr->Release(); } dbg("dxgi_sc: Opened share handles"); } else dbg("dxgi_sc: ERROR: Head %d: No share handle!", i+1), exit(0); } } #endif #ifdef SOFTTHMAIN else #endif #if defined(SOFTTHMAIN) || defined(D3D10) if(dev10) { dbg("dxgi_sc: Creating backbuffer for D3D10 Device"); CD3D10_TEXTURE2D_DESC d(DXGI_FORMAT_R8G8B8A8_UNORM, rrx, rry, 1, 1, D3D10_BIND_RENDER_TARGET, D3D10_USAGE_DEFAULT, NULL); newbbDesc10 = d; if(dev10->CreateTexture2D(&newbbDesc10, NULL, &newbb10) != S_OK) dbg("dxgi_sc: CreateTexture2D failed :("), exit(0); // Initialize outputs numDevs = config.getNumAdditionalHeads(); dbg("dxgi_sc: Initializing %d outputs", numDevs); int logoStopTime = GetTickCount() + 4000; bool fpuPreserve = true; // TODO: does this exist in d3d10? outDevs10 = new OUTDEVICE10[numDevs]; for(int i=0;i<numDevs;i++) { OUTDEVICE10 *o = &outDevs10[i]; // Create the output device HEAD *h = config.getHead(i); bool local = h->transportMethod==OUTMETHOD_LOCAL; dbg("dxgi_sc: Initializing head %d (DevID: %d, %s)...", i+1, h->devID, local?"local":"non-local"); o->output = new outDirect3D10(h->devID, h->screenMode.x, h->screenMode.y, h->transportRes.x, h->transportRes.y, win); o->cfg = h; // Create shared surfaces HANDLE sha = o->output->GetShareHandle(); if(sha) { o->localSurf = NULL; { // Open surfA share handle ID3D10Resource *tr; if(dev10->OpenSharedResource(sha, __uuidof(ID3D10Resource), (void**)(&tr)) != S_OK) dbg("dxgi_sc: OpenSharedResource A failed!"), exit(0); if(tr->QueryInterface(__uuidof(ID3D10Texture2D), (void**)(&o->localSurf)) != S_OK) dbg("dxgi_sc: Shared surface QueryInterface failed!"), exit(0); tr->Release(); } dbg("dxgi_sc: Opened share handles"); } else dbg("dxgi_sc: ERROR: Head %d: No share handle!", i+1), exit(0); } } #endif } else { dbg("dxgi_sc: Singlehead swapchain mode"); SoftTHActive--; if(dev11) { if(newbb11) SAFE_RELEASE_LAST(newbb11); newbb11 = NULL; } else if(dev10 || dev10_1) { if(newbb10) SAFE_RELEASE_LAST(newbb10); newbb10 = NULL; } } }
void D3D9Hook::gdiCreateSceneObjects() { if(m_sceneObjectsCreated) return; // Already created if(!isCapturable()) return; // Not capturable // Is the back buffer format compatible with DXGI? if(d3d9ToGdiCompatible(m_bbD3D9Format) == DXGI_FORMAT_UNKNOWN) { HookLog2(InterprocessLog::Warning, "Back buffer not compatible with DXGI, falling back to CPU capture"); m_useCpuCopy = true; return; } // Create a dummy DirectX 10 or 10.1 device depending on the system ID3D10Device *m_dx10Device = HookMain::s_instance->refDummyDX10Device(); if(m_dx10Device == NULL) { HookLog2(InterprocessLog::Warning, "Failed to create DirectX 10 device, falling back to CPU capture"); m_useCpuCopy = true; return; } HookLog(stringf("Creating D3D9 scene objects for window of size %d x %d", m_width, m_height)); // Create D3D9 render target surface HRESULT res = m_device->CreateRenderTarget( m_width, m_height, m_bbD3D9Format, D3DMULTISAMPLE_NONE, 0, TRUE, &m_rtSurface, NULL); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared D3D9 render target. Reason = %s", getD3D9ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } // Create shared DX10 textures D3D10_TEXTURE2D_DESC desc; desc.Width = m_width; desc.Height = m_height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = d3d9ToGdiCompatible(m_bbD3D9Format); desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED | D3D10_RESOURCE_MISC_GDI_COMPATIBLE; for(int i = 0; i < NUM_SHARED_TEXTURES; i++) { res = m_dx10Device->CreateTexture2D(&desc, NULL, &m_dx10Texs[i]); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared DX10 target. Reason = %s", getDX10ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } } m_nextDx10Tex = 0; // Get DXGI shared handles from the textures for(int i = 0; i < NUM_SHARED_TEXTURES; i++) { IDXGIResource *dxgiRes = NULL; res = m_dx10Texs[i]->QueryInterface( __uuidof(IDXGIResource), (void **)&dxgiRes); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI resource. Reason = %s", getDX10ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } m_dx10TexHandles[i] = NULL; res = dxgiRes->GetSharedHandle(&m_dx10TexHandles[i]); dxgiRes->Release(); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI shared handle. Reason = %s", getDX10ErrorCode(res).data())); goto gdiCreateSceneObjectsFailed1; } } #if 0 // Create D3D9 render target surface HRESULT res = m_device->CreateRenderTarget( m_width, m_height, m_bbD3D9Format, D3DMULTISAMPLE_NONE, 0, FALSE, &m_rtSurface, NULL); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared D3D9 render target. Reason = %s", getD3D9ErrorCode(res).data())); return; // TODO: Not safe to return here } // Create shared D3D9 texture HANDLE sharedHandle = NULL; res = m_device->CreateTexture( m_width, m_height, 1, D3DUSAGE_RENDERTARGET, m_bbD3D9Format, D3DPOOL_DEFAULT, &m_dx9Tex, &sharedHandle); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create D3D9 texture. Reason = %s", getD3D9ErrorCode(res).data())); return; // TODO: Not safe to return here } // Open shared surface as a DX10 texture ID3D10Resource *resource = NULL; res = m_dx10Device->OpenSharedResource( sharedHandle, __uuidof(ID3D10Resource), (void **)(&resource)); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to open D3D9 surface as a DX10 resource. Reason = %s", getDX10ErrorCode(res).data())); return; // TODO: Not safe to return here } res = resource->QueryInterface( __uuidof(ID3D10Texture2D), (void **)(&m_dx10Tex)); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to query DX10 texture interface. Reason = %s", getDX10ErrorCode(res).data())); return; // TODO: Not safe to return here } resource->Release(); #endif // 0 #if 0 // Create shared DX10 texture D3D10_TEXTURE2D_DESC desc; desc.Width = m_width; desc.Height = m_height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = d3d9ToDxgiFormat(m_bbD3D9Format); desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED; HRESULT res = m_dx10Device->CreateTexture2D(&desc, NULL, &m_dx10Tex); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create DX10 target. Reason = %s", getDX10ErrorCode(res).data())); // TODO: Don't continue } // Get DXGI shared handle from the texture IDXGIResource *dxgiRes = NULL; res = m_dx10Tex->QueryInterface( __uuidof(IDXGIResource), (void **)&dxgiRes); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI resource. Reason = %s", getDX10ErrorCode(res).data())); // TODO: Don't continue } HANDLE sharedHandle = NULL; res = dxgiRes->GetSharedHandle(&sharedHandle); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to get DXGI shared handle. Reason = %s", getDX10ErrorCode(res).data())); // TODO: Don't continue } dxgiRes->Release(); // Create D3D9 render target surface from the shared handle res = m_device->CreateRenderTarget( m_width, m_height, m_bbD3D9Format, D3DMULTISAMPLE_NONE, 0, TRUE, &m_rtSurface, &sharedHandle); if(FAILED(res)) { HookLog2(InterprocessLog::Warning, stringf( "Failed to create shared D3D9 render target. Reason = %s", getD3D9ErrorCode(res).data())); // TODO: Don't continue } #endif // 0 m_sceneObjectsCreated = true; return; // Error handling gdiCreateSceneObjectsFailed1: // Return everything to the same state as when we started if(m_rtSurface != NULL) m_rtSurface->Release(); for(int i = 0; i < NUM_SHARED_TEXTURES; i++) { m_dx10TexHandles[i] = NULL; if(m_dx10Texs[i] != NULL) { m_dx10Texs[i]->Release(); m_dx10Texs[i] = NULL; } } }