- 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),
|
d3d(NULL),
|
||||||
device(NULL),
|
device(NULL),
|
||||||
vertexBuffer(NULL),
|
vertexBuffer(NULL),
|
||||||
texture(NULL),
|
stexture(NULL),
|
||||||
|
vtexture(NULL),
|
||||||
|
lastblank(0),
|
||||||
inWidth(1),
|
inWidth(1),
|
||||||
inHeight(1),
|
inHeight(1),
|
||||||
textRes(1),
|
textRes(1),
|
||||||
@ -200,8 +202,8 @@ void Direct3DBlitter::lockTexture() {
|
|||||||
D3DLOCKED_RECT lockedrect;
|
D3DLOCKED_RECT lockedrect;
|
||||||
lockedrect.pBits = NULL;
|
lockedrect.pBits = NULL;
|
||||||
|
|
||||||
if (texture)
|
if (stexture)
|
||||||
texture->LockRect(0, &lockedrect, &rect, D3DLOCK_NOSYSLOCK);
|
stexture->LockRect(0, &lockedrect, &rect, D3DLOCK_NOSYSLOCK);
|
||||||
|
|
||||||
setPixelBuffer(lockedrect.pBits, MediaSource::RGB32, lockedrect.Pitch >> 2);
|
setPixelBuffer(lockedrect.pBits, MediaSource::RGB32, lockedrect.Pitch >> 2);
|
||||||
}
|
}
|
||||||
@ -271,15 +273,20 @@ void Direct3DBlitter::resetDevice() {
|
|||||||
if (device && device->TestCooperativeLevel() != D3DERR_DEVICELOST) {
|
if (device && device->TestCooperativeLevel() != D3DERR_DEVICELOST) {
|
||||||
device->SetTexture(0, NULL);
|
device->SetTexture(0, NULL);
|
||||||
|
|
||||||
|
if (vtexture) {
|
||||||
|
vtexture->Release();
|
||||||
|
vtexture = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
D3DPRESENT_PARAMETERS presentParams;
|
D3DPRESENT_PARAMETERS presentParams;
|
||||||
|
|
||||||
getPresentParams(&presentParams);
|
getPresentParams(&presentParams);
|
||||||
|
|
||||||
if (FAILED(device->Reset(&presentParams)) && FAILED(device->Reset(&presentParams))) {
|
if (FAILED(device->Reset(&presentParams)) && FAILED(device->Reset(&presentParams))) {
|
||||||
if (texture) {
|
if (stexture) {
|
||||||
setPixelBuffer(NULL, MediaSource::RGB32, 0);
|
setPixelBuffer(NULL, MediaSource::RGB32, 0);
|
||||||
texture->Release();
|
stexture->Release();
|
||||||
texture = NULL;
|
stexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vertexBuffer) {
|
if (vertexBuffer) {
|
||||||
@ -297,7 +304,7 @@ void Direct3DBlitter::resetDevice() {
|
|||||||
windowed = presentParams.Windowed;
|
windowed = presentParams.Windowed;
|
||||||
clear = presentParams.BackBufferCount + 1;
|
clear = presentParams.BackBufferCount + 1;
|
||||||
setDeviceState();
|
setDeviceState();
|
||||||
device->SetTexture(0, texture);
|
setVideoTexture();
|
||||||
setVertexBuffer();
|
setVertexBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,15 +358,32 @@ void Direct3DBlitter::present() {
|
|||||||
resetDevice();
|
resetDevice();
|
||||||
|
|
||||||
if (device) {
|
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);
|
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;
|
drawn = false;
|
||||||
@ -371,9 +395,10 @@ void Direct3DBlitter::init() {
|
|||||||
|
|
||||||
getPresentParams(&presentParams);
|
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--;) {
|
for (unsigned n = 2; n--;) {
|
||||||
if (!FAILED(d3d->CreateDevice(adapterIndex, D3DDEVTYPE_HAL,
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,10 +426,15 @@ void Direct3DBlitter::uninit() {
|
|||||||
device->SetTexture(0, NULL);
|
device->SetTexture(0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture) {
|
if (stexture) {
|
||||||
texture->UnlockRect(0);
|
stexture->UnlockRect(0);
|
||||||
texture->Release();
|
stexture->Release();
|
||||||
texture = NULL;
|
stexture = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vtexture) {
|
||||||
|
vtexture->Release();
|
||||||
|
vtexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vertexBuffer) {
|
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) {
|
void Direct3DBlitter::setBufferDimensions(unsigned w, unsigned h) {
|
||||||
inWidth = w;
|
inWidth = w;
|
||||||
inHeight = h;
|
inHeight = h;
|
||||||
|
|
||||||
if (device) {
|
if (device) {
|
||||||
device->SetTexture(0, NULL);
|
if (stexture) {
|
||||||
|
stexture->UnlockRect(0);
|
||||||
if (texture) {
|
stexture->Release();
|
||||||
texture->UnlockRect(0);
|
stexture = NULL;
|
||||||
texture->Release();
|
|
||||||
texture = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textRes = std::max(w, h);
|
textRes = std::max(w, h);
|
||||||
@ -440,20 +484,20 @@ void Direct3DBlitter::setBufferDimensions(unsigned w, unsigned h) {
|
|||||||
textRes |= textRes >> 8;
|
textRes |= textRes >> 8;
|
||||||
++textRes;
|
++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;
|
std::cout << "device->CreateTexture failed" << std::endl;
|
||||||
|
|
||||||
device->SetTexture(0, texture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lockTexture();
|
lockTexture();
|
||||||
|
setVideoTexture();
|
||||||
setVertexBuffer();
|
setVertexBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Direct3DBlitter::blit() {
|
void Direct3DBlitter::blit() {
|
||||||
if (texture) {
|
if (device && stexture && vtexture) {
|
||||||
texture->UnlockRect(0);
|
stexture->UnlockRect(0);
|
||||||
|
|
||||||
|
device->UpdateTexture(stexture, vtexture);
|
||||||
draw();
|
draw();
|
||||||
drawn = true;
|
drawn = true;
|
||||||
|
|
||||||
|
@ -42,7 +42,9 @@ class Direct3DBlitter : public BlitterWidget {
|
|||||||
IDirect3D9 *d3d;
|
IDirect3D9 *d3d;
|
||||||
IDirect3DDevice9* device;
|
IDirect3DDevice9* device;
|
||||||
IDirect3DVertexBuffer9* vertexBuffer;
|
IDirect3DVertexBuffer9* vertexBuffer;
|
||||||
IDirect3DTexture9 *texture;
|
IDirect3DTexture9 *stexture;
|
||||||
|
IDirect3DTexture9 *vtexture;
|
||||||
|
usec_t lastblank;
|
||||||
unsigned inWidth;
|
unsigned inWidth;
|
||||||
unsigned inHeight;
|
unsigned inHeight;
|
||||||
unsigned textRes;
|
unsigned textRes;
|
||||||
@ -64,6 +66,7 @@ class Direct3DBlitter : public BlitterWidget {
|
|||||||
void getPresentParams(D3DPRESENT_PARAMETERS *presentParams) const;
|
void getPresentParams(D3DPRESENT_PARAMETERS *presentParams) const;
|
||||||
void lockTexture();
|
void lockTexture();
|
||||||
void setVertexBuffer();
|
void setVertexBuffer();
|
||||||
|
void setVideoTexture();
|
||||||
void setFilter();
|
void setFilter();
|
||||||
void setDeviceState();
|
void setDeviceState();
|
||||||
void resetDevice();
|
void resetDevice();
|
||||||
|
@ -571,15 +571,40 @@ long DirectDrawBlitter::sync(const long ft) {
|
|||||||
HRESULT ddrval = DD_OK;
|
HRESULT ddrval = DD_OK;
|
||||||
|
|
||||||
if (exclusive & flipping) {
|
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)
|
if (!blitted)
|
||||||
finalBlit(wf ? DDBLT_WAIT : DDBLT_DONOTWAIT);
|
finalBlit(DDBLT_WAIT);
|
||||||
|
|
||||||
if (lpDDSPrimary && blitted)
|
const DWORD flipflags = DDFLIP_WAIT | (swapInterval == 2 ? DDFLIP_INTERVAL2 : 0);
|
||||||
ddrval = lpDDSPrimary->Flip(NULL,
|
|
||||||
(wf ? DDFLIP_WAIT : DDFLIP_DONOTWAIT) |
|
if (lpDDSPrimary)
|
||||||
((vblankflip | swapInterval) ? (swapInterval == 2 ? DDFLIP_INTERVAL2 : 0) : DDFLIP_NOVSYNC));
|
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 {
|
} else {
|
||||||
if (swapInterval) {
|
if (swapInterval) {
|
||||||
const usec_t refreshPeriod = 1000000 / hz;
|
const usec_t refreshPeriod = 1000000 / hz;
|
||||||
@ -595,7 +620,7 @@ long DirectDrawBlitter::sync(const long ft) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (swapInterval)
|
if (swapInterval)
|
||||||
ftEst.update(getusecs());
|
ftEst.update(lastblank);
|
||||||
|
|
||||||
blitted = false;
|
blitted = false;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user