- Direct3DBlitter and DirectDrawBlitter: Force blocking updates when sync to vblank is enabled.
Some updates only block if there's a prior unfinished update in progress. This screws up frame time estimation in turn screwing up vsync. To fix this we do a double update (and extra blit) if close to a frame time period has passed since the last update when sync to vblank is enabled. I really should have noticed this earlier as it pretty much breaks vsync adaption completely. - Direct3DBlitter: Use the D3DCREATE_FPU_PRESERVE flag when creating device. Omitting this flag can screw up floating point calculations in other parts of the code. For instance WASAPI cursor timestamps get utterly screwed up here. - Direct3DBlitter: It appears that managed textures are updated before they are unlocked, which screws up redraws, making things appear choppy in some situations. Use a default memory texture and a system memory texture and the UpdateTexure method instead. git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@214 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
parent
e3f1d0ecb1
commit
d9edc2e78d
@ -68,7 +68,9 @@ Direct3DBlitter::Direct3DBlitter(PixelBufferSetter setPixelBuffer, QWidget *pare
|
||||
d3d(NULL),
|
||||
device(NULL),
|
||||
vertexBuffer(NULL),
|
||||
texture(NULL),
|
||||
stexture(NULL),
|
||||
vtexture(NULL),
|
||||
lastblank(0),
|
||||
inWidth(1),
|
||||
inHeight(1),
|
||||
textRes(1),
|
||||
@ -200,8 +202,8 @@ void Direct3DBlitter::lockTexture() {
|
||||
D3DLOCKED_RECT lockedrect;
|
||||
lockedrect.pBits = NULL;
|
||||
|
||||
if (texture)
|
||||
texture->LockRect(0, &lockedrect, &rect, D3DLOCK_NOSYSLOCK);
|
||||
if (stexture)
|
||||
stexture->LockRect(0, &lockedrect, &rect, D3DLOCK_NOSYSLOCK);
|
||||
|
||||
setPixelBuffer(lockedrect.pBits, MediaSource::RGB32, lockedrect.Pitch >> 2);
|
||||
}
|
||||
@ -271,15 +273,20 @@ void Direct3DBlitter::resetDevice() {
|
||||
if (device && device->TestCooperativeLevel() != D3DERR_DEVICELOST) {
|
||||
device->SetTexture(0, NULL);
|
||||
|
||||
if (vtexture) {
|
||||
vtexture->Release();
|
||||
vtexture = NULL;
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS presentParams;
|
||||
|
||||
getPresentParams(&presentParams);
|
||||
|
||||
if (FAILED(device->Reset(&presentParams)) && FAILED(device->Reset(&presentParams))) {
|
||||
if (texture) {
|
||||
if (stexture) {
|
||||
setPixelBuffer(NULL, MediaSource::RGB32, 0);
|
||||
texture->Release();
|
||||
texture = NULL;
|
||||
stexture->Release();
|
||||
stexture = NULL;
|
||||
}
|
||||
|
||||
if (vertexBuffer) {
|
||||
@ -297,7 +304,7 @@ void Direct3DBlitter::resetDevice() {
|
||||
windowed = presentParams.Windowed;
|
||||
clear = presentParams.BackBufferCount + 1;
|
||||
setDeviceState();
|
||||
device->SetTexture(0, texture);
|
||||
setVideoTexture();
|
||||
setVertexBuffer();
|
||||
}
|
||||
}
|
||||
@ -351,15 +358,32 @@ void Direct3DBlitter::present() {
|
||||
resetDevice();
|
||||
|
||||
if (device) {
|
||||
IDirect3DSwapChain9 *swapChain = NULL;
|
||||
if (swapInterval) {
|
||||
const unsigned long estft = ftEst.est();
|
||||
const usec_t swaplimit = getusecs() - lastblank > estft - estft / 32 ? estft * 2 - 500000 / hz : 0;
|
||||
|
||||
device->GetSwapChain(0, &swapChain);
|
||||
|
||||
if (swapChain) {
|
||||
swapChain->Present(NULL, NULL, 0, NULL, vblankblit && !swapInterval ? 1 : 0);
|
||||
swapChain->Release();
|
||||
} else
|
||||
device->Present(NULL, NULL, 0, NULL);
|
||||
|
||||
usec_t now = getusecs();
|
||||
|
||||
if (now - lastblank < swaplimit) {
|
||||
drawn = false;
|
||||
draw();
|
||||
device->Present(NULL, NULL, 0, NULL);
|
||||
now = getusecs();
|
||||
}
|
||||
|
||||
lastblank = now;
|
||||
} else {
|
||||
IDirect3DSwapChain9 *swapChain = NULL;
|
||||
device->GetSwapChain(0, &swapChain);
|
||||
|
||||
if (swapChain) {
|
||||
swapChain->Present(NULL, NULL, 0, NULL, vblankblit ? 1 : 0);
|
||||
swapChain->Release();
|
||||
} else
|
||||
device->Present(NULL, NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
drawn = false;
|
||||
@ -371,9 +395,10 @@ void Direct3DBlitter::init() {
|
||||
|
||||
getPresentParams(&presentParams);
|
||||
|
||||
// Omitting the D3DCREATE_FPU_PRESERVE will cause problems with floating point code elsewhere. For instance WASAPI screws up cursor time stamps.
|
||||
for (unsigned n = 2; n--;) {
|
||||
if (!FAILED(d3d->CreateDevice(adapterIndex, D3DDEVTYPE_HAL,
|
||||
parentWidget()->parentWidget()->winId(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &device))) {
|
||||
parentWidget()->parentWidget()->winId(), D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &device))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -401,10 +426,15 @@ void Direct3DBlitter::uninit() {
|
||||
device->SetTexture(0, NULL);
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
texture->UnlockRect(0);
|
||||
texture->Release();
|
||||
texture = NULL;
|
||||
if (stexture) {
|
||||
stexture->UnlockRect(0);
|
||||
stexture->Release();
|
||||
stexture = NULL;
|
||||
}
|
||||
|
||||
if (vtexture) {
|
||||
vtexture->Release();
|
||||
vtexture = NULL;
|
||||
}
|
||||
|
||||
if (vertexBuffer) {
|
||||
@ -418,17 +448,31 @@ void Direct3DBlitter::uninit() {
|
||||
}
|
||||
}
|
||||
|
||||
void Direct3DBlitter::setVideoTexture() {
|
||||
if (device) {
|
||||
device->SetTexture(0, NULL);
|
||||
|
||||
if (vtexture) {
|
||||
vtexture->Release();
|
||||
vtexture = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(device->CreateTexture(textRes, textRes, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &vtexture, NULL)))
|
||||
std::cout << "device->CreateTexture failed" << std::endl;
|
||||
|
||||
device->SetTexture(0, vtexture);
|
||||
}
|
||||
}
|
||||
|
||||
void Direct3DBlitter::setBufferDimensions(unsigned w, unsigned h) {
|
||||
inWidth = w;
|
||||
inHeight = h;
|
||||
|
||||
if (device) {
|
||||
device->SetTexture(0, NULL);
|
||||
|
||||
if (texture) {
|
||||
texture->UnlockRect(0);
|
||||
texture->Release();
|
||||
texture = NULL;
|
||||
if (stexture) {
|
||||
stexture->UnlockRect(0);
|
||||
stexture->Release();
|
||||
stexture = NULL;
|
||||
}
|
||||
|
||||
textRes = std::max(w, h);
|
||||
@ -440,20 +484,20 @@ void Direct3DBlitter::setBufferDimensions(unsigned w, unsigned h) {
|
||||
textRes |= textRes >> 8;
|
||||
++textRes;
|
||||
|
||||
if (FAILED(device->CreateTexture(textRes, textRes, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL)))
|
||||
if (FAILED(device->CreateTexture(textRes, textRes, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &stexture, NULL)))
|
||||
std::cout << "device->CreateTexture failed" << std::endl;
|
||||
|
||||
device->SetTexture(0, texture);
|
||||
}
|
||||
|
||||
lockTexture();
|
||||
setVideoTexture();
|
||||
setVertexBuffer();
|
||||
}
|
||||
|
||||
void Direct3DBlitter::blit() {
|
||||
if (texture) {
|
||||
texture->UnlockRect(0);
|
||||
if (device && stexture && vtexture) {
|
||||
stexture->UnlockRect(0);
|
||||
|
||||
device->UpdateTexture(stexture, vtexture);
|
||||
draw();
|
||||
drawn = true;
|
||||
|
||||
|
@ -42,7 +42,9 @@ class Direct3DBlitter : public BlitterWidget {
|
||||
IDirect3D9 *d3d;
|
||||
IDirect3DDevice9* device;
|
||||
IDirect3DVertexBuffer9* vertexBuffer;
|
||||
IDirect3DTexture9 *texture;
|
||||
IDirect3DTexture9 *stexture;
|
||||
IDirect3DTexture9 *vtexture;
|
||||
usec_t lastblank;
|
||||
unsigned inWidth;
|
||||
unsigned inHeight;
|
||||
unsigned textRes;
|
||||
@ -64,6 +66,7 @@ class Direct3DBlitter : public BlitterWidget {
|
||||
void getPresentParams(D3DPRESENT_PARAMETERS *presentParams) const;
|
||||
void lockTexture();
|
||||
void setVertexBuffer();
|
||||
void setVideoTexture();
|
||||
void setFilter();
|
||||
void setDeviceState();
|
||||
void resetDevice();
|
||||
|
@ -571,15 +571,40 @@ long DirectDrawBlitter::sync(const long ft) {
|
||||
HRESULT ddrval = DD_OK;
|
||||
|
||||
if (exclusive & flipping) {
|
||||
const bool wf = swapInterval || !vblankflip;
|
||||
if (swapInterval) {
|
||||
const unsigned long estft = ftEst.est();
|
||||
const usec_t swaplimit = getusecs() - lastblank > estft - estft / 32 ? estft * 2 - 500000 / hz : 0;
|
||||
|
||||
if (!blitted)
|
||||
finalBlit(wf ? DDBLT_WAIT : DDBLT_DONOTWAIT);
|
||||
if (!blitted)
|
||||
finalBlit(DDBLT_WAIT);
|
||||
|
||||
if (lpDDSPrimary && blitted)
|
||||
ddrval = lpDDSPrimary->Flip(NULL,
|
||||
(wf ? DDFLIP_WAIT : DDFLIP_DONOTWAIT) |
|
||||
((vblankflip | swapInterval) ? (swapInterval == 2 ? DDFLIP_INTERVAL2 : 0) : DDFLIP_NOVSYNC));
|
||||
const DWORD flipflags = DDFLIP_WAIT | (swapInterval == 2 ? DDFLIP_INTERVAL2 : 0);
|
||||
|
||||
if (lpDDSPrimary)
|
||||
ddrval = lpDDSPrimary->Flip(NULL, flipflags);
|
||||
|
||||
usec_t now = getusecs();
|
||||
|
||||
if (now - lastblank < swaplimit) {
|
||||
blitted = false;
|
||||
finalBlit(DDBLT_WAIT);
|
||||
|
||||
if (lpDDSPrimary)
|
||||
ddrval = lpDDSPrimary->Flip(NULL, flipflags);
|
||||
|
||||
now = getusecs();
|
||||
}
|
||||
|
||||
lastblank = now;
|
||||
} else {
|
||||
if (!blitted)
|
||||
finalBlit(vblankflip ? DDBLT_DONOTWAIT : DDBLT_WAIT);
|
||||
|
||||
if (lpDDSPrimary && blitted)
|
||||
ddrval = lpDDSPrimary->Flip(NULL,
|
||||
(vblankflip ? DDFLIP_DONOTWAIT : DDFLIP_WAIT) |
|
||||
(vblankflip ? 0 : DDFLIP_NOVSYNC));
|
||||
}
|
||||
} else {
|
||||
if (swapInterval) {
|
||||
const usec_t refreshPeriod = 1000000 / hz;
|
||||
@ -595,7 +620,7 @@ long DirectDrawBlitter::sync(const long ft) {
|
||||
}
|
||||
|
||||
if (swapInterval)
|
||||
ftEst.update(getusecs());
|
||||
ftEst.update(lastblank);
|
||||
|
||||
blitted = false;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user