// Update the display to show anything that's changed since last time void Direct3D9Video::Update (CScreen* pScreen_, bool *pafDirty_) { HRESULT hr; if (!m_pd3dDevice) return; if (FAILED(hr = m_pd3dDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) { TRACE("D3DERR_DEVICELOST\n"); return; } if (hr == D3DERR_DEVICENOTRESET) { TRACE("D3DERR_DEVICENOTRESET\n"); Reset(); return; } else { TRACE("TestCooperativeLevel() failed (other)\n"); return; } } // Draw any changed lines to the back buffer if (!DrawChanges(pScreen_, pafDirty_)) return; hr = m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0L); hr = m_pd3dDevice->BeginScene(); bool fFilter = GUI::IsActive() ? GetOption(filtergui) : GetOption(filter); DWORD dwFilter = fFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT; DWORD dwCurrentFilter = 0; if (SUCCEEDED(m_pd3dDevice->GetSamplerState(0, D3DSAMP_MAGFILTER, &dwCurrentFilter)) && dwFilter != dwCurrentFilter) { hr = m_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, dwFilter); hr = m_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, dwFilter); } int nVertexOffset = GUI::IsActive() ? 0 : 4; hr = m_pd3dDevice->SetTexture(0, m_pTexture); hr = m_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); hr = m_pd3dDevice->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(CUSTOMVERTEX)); hr = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, nVertexOffset, 2); if (GetOption(scanlines) && !GUI::IsActive() && (int(m_d3dpp.BackBufferWidth) >= Frame::GetWidth())) { nVertexOffset = GetOption(scanhires) ? 8 : 0; hr = m_pd3dDevice->SetTexture(0, m_pScanlineTexture); hr = m_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); hr = m_pd3dDevice->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(CUSTOMVERTEX)); hr = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, nVertexOffset, 2); } hr = m_pd3dDevice->EndScene(); hr = m_pd3dDevice->Present(NULL, NULL, hwndCanvas, NULL); }
/* Overridable function, if necessary, for doing all of the drawing. Base class version checks whether a redraw is needed and does nothing if not. See Redraw() function. If a redraw is needed then there is an option to either redraw the whole screen or just redraw the moving objects. If redrawing the whole screen then: 1a) SetupBackgroundBuffer is called to draw the background to the background buffer. 1b) DrawScreen is called to copy the background buffer onto the screen, then draw the moving objects. 1c) SDL_UpdateRect() is called to actually redraw the whole screen. If only redrawing the moving objects then: 2a) DrawChangingObjects() is called to remove the objects from their old positions, and redraw them in their new positions. 2b) GetUpdateRectanglesForChangingObjects() is called to calculate where on the screen needs redrawing. 2c) SDL_UpdateRects() is called to redraw the parts of the screen which changed. */ void BaseEngine::GameRender(void) { if ( !m_bNeedsRedraw ) return; // Just drawn so no more redraw needed m_bNeedsRedraw = false; // Note: the redraw flags must only be set early in this method, not at the end, since the drawing/moving of the moving objects may // potentially flag a win/lose condition and a state change, which will set the redraw flag again to force a full draw after the // state changes. if ( m_bWholeScreenUpdate ) { // Drawn whole screen now, so no need to draw it again. See note above about the importance of not resetting this after DrawChangingObjects() m_bWholeScreenUpdate = false; // Lock surface if needed if (SDL_MUSTLOCK(m_pActualScreen)) { m_bInsideDraw = true; if (SDL_LockSurface(m_pActualScreen) < 0) return; } // Draw the screen as it should appear now. DrawScreen(); // Unlock if needed if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); m_bInsideDraw = false; SDL_UpdateRect(m_pActualScreen, 0, 0, m_iScreenWidth, m_iScreenHeight); } else { // Here we assume that the background buffer has already been set up // Lock surface if needed if (SDL_MUSTLOCK(m_pActualScreen)) { m_bInsideDraw = true; if (SDL_LockSurface(m_pActualScreen) < 0) return; } // Remove objects from their old positions // Draw the text for the user // Draw objects at their new positions DrawChanges(); // Unlock if needed if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); m_bInsideDraw = false; // Work out which parts of the screen need to be updated GetUpdateRectanglesForChangingObjects(); // Now actually perform the updates if ( m_iUpdateRectsInUse >= m_iMaxObjects ) { //printf( "Update whole window\n" ); //SDL_UpdateRect(m_pActualScreen, 0, 0, m_iScreenWidth, m_iScreenHeight); SDL_UpdateRect(m_pActualScreen, 0, 0, 0, 0); } else { //printf( "Update %d rectangles\n", m_iUpdateRectsInUse ); SDL_UpdateRects( m_pActualScreen, m_iUpdateRectsInUse, m_pUpdateRectangles ); } // DEBUG //printf( "%d update rectangles found\n", m_iUpdateRectsInUse ); //for ( int i = 0 ; i < m_iUpdateRectsInUse ; i++ ) // printf( "\tNumber %d : %d, %d, %d, %d\n", i, m_pUpdateRectangles[i].x, m_pUpdateRectangles[i].y, m_pUpdateRectangles[i].w, m_pUpdateRectangles[i].h ); // End of debug m_iUpdateRectsInUse = 0; } }