//---------------------------------------------------------------------------- void PdrRenderTarget::Disable (Renderer* renderer) { IDirect3DDevice9* device = renderer->mData->mDevice; HRESULT hr; WM5_UNUSED(hr); // The viewport is automatically restored by this call. hr = device->SetRenderTarget(0, mSaveColorSurface); assertion(hr == D3D_OK, "Failed to set old rt 0 color surface: %s\n", DXGetErrorString(hr)); mSaveColorSurface->Release(); for (int i = 1; i < mNumTargets; ++i) { // The viewport is automatically restored by this call. hr = device->SetRenderTarget((DWORD)i, 0); assertion(hr == D3D_OK, "Failed to set old rt %d color surface: %s\n", i, DXGetErrorString(hr)); } if (mHasDepthStencil) { hr = device->SetDepthStencilSurface(mSaveDepthStencilSurface); assertion(hr == D3D_OK, "Failed to set old rt 0 depthstencil surface: %s\n", DXGetErrorString(hr)); mSaveDepthStencilSurface->Release(); } }
bool MythRenderD3D9::SetRenderTarget(IDirect3DTexture9 *texture) { D3D9Locker locker(this); IDirect3DDevice9* dev = locker.Acquire(); if (!dev) return false; bool ret = true; HRESULT hr; if (texture && m_textures.contains(texture)) { if (!m_default_surface) { hr = dev->GetRenderTarget(0, &m_default_surface); if (FAILED(hr)) { LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to get default surface."); return false; } } IDirect3DSurface9 *new_surface = NULL; hr = texture->GetSurfaceLevel(0, &new_surface); if (FAILED(hr)) LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to get surface level."); else { if (m_current_surface && m_current_surface != new_surface) m_current_surface->Release(); m_current_surface = new_surface; hr = dev->SetRenderTarget(0, m_current_surface); if (FAILED(hr)) LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to set render target."); } } else if (!texture) { if (m_default_surface) { hr = dev->SetRenderTarget(0, m_default_surface); if (FAILED(hr)) LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to set render target."); } else LOG(VB_GENERAL, LOG_ERR, D3DLOC + "No default surface for render target."); } else ret = false; return ret; }
void Blit::restoreState() { IDirect3DDevice9 *device = getDevice(); device->SetDepthStencilSurface(mSavedDepthStencil); if (mSavedDepthStencil != NULL) { mSavedDepthStencil->Release(); mSavedDepthStencil = NULL; } device->SetRenderTarget(0, mSavedRenderTarget); if (mSavedRenderTarget != NULL) { mSavedRenderTarget->Release(); mSavedRenderTarget = NULL; } ASSERT(mSavedStateBlock != NULL); if (mSavedStateBlock != NULL) { mSavedStateBlock->Apply(); } }
bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); if (!texture) { return false; } IDirect3DDevice9 *device = getDevice(); saveState(); device->SetTexture(0, texture); device->SetRenderTarget(0, dest); setViewport(sourceRect, xoffset, yoffset); setCommonBlitState(); if (setFormatConvertShaders(destFormat)) { render(); } texture->Release(); restoreState(); return true; }
bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); if (!texture) { return false; } IDirect3DDevice9 *device = getDevice(); saveState(); device->SetTexture(0, texture); device->SetRenderTarget(0, dest); setVertexShader(SHADER_VS_STANDARD); setPixelShader(SHADER_PS_PASSTHROUGH); setCommonBlitState(); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); setViewport(getSurfaceRect(dest), 0, 0); render(); texture->Release(); restoreState(); return true; }
gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { IDirect3DTexture9 *texture = NULL; gl::Error error = copySurfaceToTexture(source, sourceRect, &texture); if (error.isError()) { return error; } IDirect3DDevice9 *device = mRenderer->getDevice(); saveState(); device->SetTexture(0, texture); device->SetRenderTarget(0, dest); setViewport(sourceRect, xoffset, yoffset); setCommonBlitState(); error = setFormatConvertShaders(destFormat); if (!error.isError()) { render(); } SafeRelease(texture); restoreState(); return error; }
gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { IDirect3DTexture9 *texture = NULL; gl::Error error = copySurfaceToTexture(source, getSurfaceRect(source), &texture); if (error.isError()) { return error; } IDirect3DDevice9 *device = mRenderer->getDevice(); saveState(); device->SetTexture(0, texture); device->SetRenderTarget(0, dest); setVertexShader(SHADER_VS_STANDARD); setPixelShader(SHADER_PS_PASSTHROUGH); setCommonBlitState(); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); setViewport(getSurfaceRect(dest), 0, 0); render(); SafeRelease(texture); restoreState(); return gl::Error(GL_NO_ERROR); }
void GPUContextDX9::bindOutput( size_t inIndex, TextureHandle inTexture ) { DX9Texture* texture = (DX9Texture*)inTexture; _boundOutputs[inIndex] = texture; HRESULT result = _device->SetRenderTarget( inIndex, texture->getSurfaceHandle() ); GPUAssert( !FAILED(result), "SetRenderTarget failed" ); }
/////////////////////////////////////////////////////////////////////////////// // Draw the scene. // void RenderWindow::Draw() { IDirect3DDevice9* device = m_Render.GetD3DDevice(); if ( !device ) { return; } if ( m_IsDeviceLost ) { if ( device->TestCooperativeLevel() == D3DERR_DEVICENOTRESET ) { m_Render.Reset(); m_IsDeviceLost = device->TestCooperativeLevel() != D3D_OK; } } if ( m_IsDeviceLost ) { return; } // If we have a scene with a mesh, draw it if ( !RenderScene() ) { // No scene or no mesh, just clear the screen device->BeginScene(); device->SetRenderTarget( 0, m_Render.GetBackBuffer() ); device->SetDepthStencilSurface( m_Render.GetDepthBuffer() ); device->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0xFF, 0xB8, 0xB8, 0xB8), 1.0f, 0 ); device->EndScene(); } m_IsDeviceLost = ( m_Render.Display( GetHwnd() ) == D3DERR_DEVICELOST ); }
void Blit9::restoreState() { IDirect3DDevice9 *device = mRenderer->getDevice(); device->SetDepthStencilSurface(mSavedDepthStencil); SafeRelease(mSavedDepthStencil); device->SetRenderTarget(0, mSavedRenderTarget); SafeRelease(mSavedRenderTarget); ASSERT(mSavedStateBlock != NULL); if (mSavedStateBlock != NULL) { mSavedStateBlock->Apply(); } }
// parameters should be validated/clamped by caller EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } IDirect3DDevice9 *device = mRenderer->getDevice(); // Disable all pipeline operations device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); device->SetRenderState(D3DRS_STENCILENABLE, FALSE); device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetRenderTarget(0, mBackBuffer); device->SetDepthStencilSurface(NULL); device->SetTexture(0, mOffscreenTexture); device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) { device->SetStreamSourceFreq(streamIndex, 1); } D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; device->SetViewport(&viewport); float x1 = x - 0.5f; float y1 = (mHeight - y - height) - 0.5f; float x2 = (x + width) - 0.5f; float y2 = (mHeight - y) - 0.5f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, {x2, y1, 0.0f, 1.0f, u2, v2}, {x2, y2, 0.0f, 1.0f, u2, v1}, {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v mRenderer->startScene(); device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); mRenderer->endScene(); device->SetTexture(0, NULL); RECT rect = { x, mHeight - y - height, x + width, mHeight - y }; HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); mRenderer->markAllStateDirty(); if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) { return EGL_BAD_ALLOC; } // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The // device appears to be ok after emitting this error so simply return a failure to swap. if (result == 0x88760873) { return EGL_BAD_NATIVE_WINDOW; } // http://crbug.com/313210 // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific // device removed bug with lost contexts when reinstalling drivers. if (FAILED(result)) { mRenderer->notifyDeviceLost(); return EGL_CONTEXT_LOST; } return EGL_SUCCESS; }
RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) { mRenderer = Renderer9::makeRenderer9(renderer); mRenderTarget = NULL; D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat, mRenderer); int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples); if (supportedSamples == -1) { gl::error(GL_OUT_OF_MEMORY); return; } HRESULT result = D3DERR_INVALIDCALL; GLuint clientVersion = mRenderer->getCurrentClientVersion(); if (width > 0 && height > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); bool requiresInitialization = false; if (gl::GetDepthBits(internalFormat, clientVersion) > 0 || gl::GetStencilBits(internalFormat, clientVersion) > 0) { result = device->CreateDepthStencilSurface(width, height, renderFormat, gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &mRenderTarget, NULL); } else { requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat); result = device->CreateRenderTarget(width, height, renderFormat, gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &mRenderTarget, NULL); } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_INVALIDARG || result == E_OUTOFMEMORY) { gl::error(GL_OUT_OF_MEMORY); return; } ASSERT(SUCCEEDED(result)); if (requiresInitialization) { // This format requires that the data be initialized before the render target can be used // Unfortunately this requires a Get call on the d3d device but it is far better than having // to mark the render target as lockable and copy data to the gpu. IDirect3DSurface9 *prevRenderTarget = NULL; device->GetRenderTarget(0, &prevRenderTarget); device->SetRenderTarget(0, mRenderTarget); device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); device->SetRenderTarget(0, prevRenderTarget); } } mWidth = width; mHeight = height; mDepth = 1; mInternalFormat = internalFormat; mSamples = supportedSamples; mActualFormat = d3d9_gl::GetInternalFormat(renderFormat); }
// parameters should be validated/clamped by caller EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } IDirect3DDevice9 *device = mRenderer->getDevice(); // Disable all pipeline operations device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); device->SetRenderState(D3DRS_STENCILENABLE, FALSE); device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetRenderTarget(0, mBackBuffer); device->SetDepthStencilSurface(NULL); device->SetTexture(0, mOffscreenTexture); device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; device->SetViewport(&viewport); float x1 = x - 0.5f; float y1 = (mHeight - y - height) - 0.5f; float x2 = (x + width) - 0.5f; float y2 = (mHeight - y) - 0.5f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, {x2, y1, 0.0f, 1.0f, u2, v2}, {x2, y2, 0.0f, 1.0f, u2, v1}, {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v mRenderer->startScene(); device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); mRenderer->endScene(); device->SetTexture(0, NULL); RECT rect = { x, mHeight - y - height, x + width, mHeight - y }; HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); mRenderer->markAllStateDirty(); if (d3d9::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) { return EGL_BAD_ALLOC; } ASSERT(SUCCEEDED(result)); return EGL_SUCCESS; }
//---------------------------------------------------------------------------- void PdrRenderTarget::ReadColor (int i, Renderer* renderer, Texture2D*& texture) { if (i < 0 || i >= mNumTargets) { assertion(false, "Invalid target index.\n"); return; } IDirect3DDevice9* device = renderer->mData->mDevice; HRESULT hr; WM5_UNUSED(hr); // Enable the input render target surface. if (i == 0) { hr = device->GetRenderTarget(0, &mSaveColorSurface); assertion(hr == D3D_OK, "Failed to get old rt 0 color surface: %s\n", DXGetErrorString(hr)); } hr = device->SetRenderTarget((DWORD)i, mColorSurfaces[i]); assertion(hr == D3D_OK, "Failed to set new rt %d color surface: %s\n", i, DXGetErrorString(hr)); // Make a duplicate in system memory. IDirect3DTexture9* copyTexture = 0; hr = D3DXCreateTexture ( device, (UINT)mWidth, (UINT)mHeight, 0, 0, gDX9TextureFormat[mFormat], D3DPOOL_SYSTEMMEM, ©Texture ); assertion(hr == D3D_OK, "Failed to create copy texture: %s\n", DXGetErrorString(hr)); // Get the surface associated with the copy. IDirect3DSurface9* copySurface = 0; hr = copyTexture->GetSurfaceLevel(0, ©Surface); assertion(hr == D3D_OK, "Failed to get surface level for copy texture: %s\n", DXGetErrorString(hr)); // Copy the render target surface. hr = device->GetRenderTargetData(mColorSurfaces[i], copySurface); assertion(hr == D3D_OK, "Failed to copy the rt %d surface: %s\n", i, DXGetErrorString(hr)); // Get the data to write to disk. D3DLOCKED_RECT rect; hr = copySurface->LockRect(&rect, 0, 0); assertion(hr == D3D_OK, "Failed to lock copy surface: %s\n", DXGetErrorString(hr)); if (texture) { if (texture->GetFormat() != mFormat || texture->GetWidth() != (int)mWidth || texture->GetHeight() != (int)mHeight) { assertion(false, "Incompatible texture.\n"); delete0(texture); texture = new0 Texture2D(mFormat, mWidth, mHeight, 1); } } else { texture = new0 Texture2D(mFormat, mWidth, mHeight, 1); } memcpy(texture->GetData(0), rect.pBits, texture->GetNumLevelBytes(0)); hr = copySurface->UnlockRect(); assertion(hr == D3D_OK, "Failed to unlock copy surface: %s\n", DXGetErrorString(hr)); copySurface->Release(); copyTexture->Release(); // Restore the previous render target surface. if (i == 0) { hr = device->SetRenderTarget(0, mSaveColorSurface); assertion(hr == D3D_OK, "Failed to set old rt 0 color surface: %s\n", DXGetErrorString(hr)); mSaveColorSurface->Release(); } }
void GPUContextDX9::disableOutput( size_t inIndex ) { HRESULT result = _device->SetRenderTarget( inIndex, NULL ); GPUAssert( !FAILED(result), "SetRenderTarget failed" ); }