ddraw: D3DOP_BRANCHFORWARD includes the current instruction size.

Native D3DRM puts a branchforward with offset 0 at the beginning of each
execute buffer. With the old code this used to get stuck in an endless
loop. This patch adds a test that shows that such a branchforward
terminates properly.
This commit is contained in:
Stefan Dösinger 2007-07-01 13:53:29 +02:00 committed by Alexandre Julliard
parent c58b2f2283
commit 5fa4de27bc
3 changed files with 112 additions and 3 deletions

View File

@ -519,13 +519,11 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This,
if (!ci->bNegate) { if (!ci->bNegate) {
TRACE(" Branch to %d\n", ci->dwOffset); TRACE(" Branch to %d\n", ci->dwOffset);
instr = (char*)current + ci->dwOffset; instr = (char*)current + ci->dwOffset;
break;
} }
} else { } else {
if (ci->bNegate) { if (ci->bNegate) {
TRACE(" Branch to %d\n", ci->dwOffset); TRACE(" Branch to %d\n", ci->dwOffset);
instr = (char*)current + ci->dwOffset; instr = (char*)current + ci->dwOffset;
break;
} }
} }

View File

@ -110,7 +110,8 @@ IDirectDrawSurfaceImpl_QueryInterface(IDirectDrawSurface7 *iface,
return S_OK; return S_OK;
} }
else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) || else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
IsEqualGUID(riid, &IID_IDirect3DHALDevice) ) IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
{ {
IDirect3DDevice7 *d3d; IDirect3DDevice7 *d3d;

View File

@ -818,6 +818,115 @@ static void CapsTest(void)
IDirectDraw_Release(dd1); IDirectDraw_Release(dd1);
} }
static void ExecutebufferTest(void)
{
IDirect3DDevice *dev1 = NULL;
IDirectDraw *dd;
IDirect3D *d3d;
IDirectDrawSurface *dds;
IDirect3DExecuteBuffer *exebuf;
IDirect3DViewport *vp;
HRESULT hr;
DDSURFACEDESC ddsd;
D3DEXECUTEBUFFERDESC desc;
D3DVIEWPORT vp_data;
D3DINSTRUCTION *instr;
D3DBRANCH *branch;
unsigned int idx = 0;
/* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
hr = DirectDrawCreate(NULL, &dd, NULL);
ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
if (!dd) {
trace("DirectDrawCreate() failed with an error %x\n", hr);
return;
}
hr = IDirectDraw_SetCooperativeLevel(dd, NULL, DDSCL_NORMAL);
ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
hr = IDirectDraw_QueryInterface(dd, &IID_IDirect3D, (void**) &d3d);
ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
ddsd.dwWidth = 256;
ddsd.dwHeight = 256;
hr = IDirectDraw_CreateSurface(dd, &ddsd, &dds, NULL);
ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
dev1 = NULL;
hr = IDirectDrawSurface_QueryInterface(dds, &IID_IDirect3DRGBDevice, (void **) &dev1);
ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
if(!dev1) return;
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
desc.dwBufferSize = 128;
desc.lpData = NULL;
hr = IDirect3DDevice_CreateExecuteBuffer(dev1, &desc, &exebuf, NULL);
ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
hr = IDirect3DExecuteBuffer_Lock(exebuf, &desc);
ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
instr = desc.lpData;
instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
instr[idx].bSize = sizeof(*branch);
instr[idx].wCount = 1;
idx++;
branch = (D3DBRANCH *) &instr[idx];
branch->dwMask = 0x0;
branch->dwValue = 1;
branch->bNegate = TRUE;
branch->dwOffset = 0;
idx += (sizeof(*branch) / sizeof(*instr));
instr[idx].bOpcode = D3DOP_EXIT;
instr[idx].bSize = 0;
instr[idx].bSize = 0;
hr = IDirect3DExecuteBuffer_Unlock(exebuf);
ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
hr = IDirect3D_CreateViewport(d3d, &vp, NULL);
ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
hr = IDirect3DViewport_Initialize(vp, d3d);
ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
hr = IDirect3DDevice_AddViewport(dev1, vp);
ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
vp_data.dwSize = sizeof(vp_data);
vp_data.dwX = 0;
vp_data.dwY = 0;
vp_data.dwWidth = 256;
vp_data.dwHeight = 256;
vp_data.dvScaleX = 1;
vp_data.dvScaleY = 1;
vp_data.dvMaxX = 256;
vp_data.dvMaxY = 256;
vp_data.dvMinZ = 0;
vp_data.dvMaxZ = 1;
hr = IDirect3DViewport_SetViewport(vp, &vp_data);
ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
hr = IDirect3DDevice_Execute(dev1, exebuf, vp, D3DEXECUTE_CLIPPED);
ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
hr = IDirect3DDevice_DeleteViewport(dev1, vp);
ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
IDirect3DViewport_Release(vp);
IDirect3DExecuteBuffer_Release(exebuf);
IDirect3DDevice_Release(dev1);
IDirectDrawSurface_Release(dds);
IDirect3D_Release(d3d);
IDirectDraw_Release(dd);
return;
}
START_TEST(d3d) START_TEST(d3d)
{ {
init_function_pointers(); init_function_pointers();
@ -837,4 +946,5 @@ START_TEST(d3d)
LimitTest(); LimitTest();
CapsTest(); CapsTest();
ReleaseDirect3D(); ReleaseDirect3D();
ExecutebufferTest();
} }