Commit 8b2c10bc authored by Jason Edmeades's avatar Jason Edmeades Committed by Alexandre Julliard

MaxActiveLights means number of concurrent lights, but any number can

be set up. Change support for lights into a linked list and only set up an equivalent gl light when the light is enabled.
parent ba69d050
......@@ -67,7 +67,6 @@ extern int num_lock;
/* Device caps */
#define MAX_PALETTES 256
#define MAX_STREAMS 16
#define MAX_ACTIVE_LIGHTS 8
#define MAX_CLIPPLANES D3DMAXUSERCLIPPLANES
#define MAX_LEVELS 256
......@@ -174,6 +173,27 @@ typedef struct PSHADEROUTPUTDATA8 {
D3DSHADERVECTOR oDepth;
} PSHADEROUTPUTDATA8;
/*
* Private definitions for internal use only
*/
typedef struct PLIGHTINFOEL PLIGHTINFOEL;
struct PLIGHTINFOEL {
D3DLIGHT8 OriginalParms;
DWORD OriginalIndex;
LONG glIndex;
BOOL lightEnabled;
BOOL changed;
BOOL enabledChanged;
/* Converted parms to speed up swapping lights */
float lightPosn[4];
float lightDirn[4];
float exponent;
float cutoff;
PLIGHTINFOEL *next;
PLIGHTINFOEL *prev;
};
/*
* Macros
......@@ -326,10 +346,6 @@ struct IDirect3DDevice8Impl
IDirect3DStateBlockImpl *StateBlock;
IDirect3DStateBlockImpl *UpdateStateBlock;
/* Other required values */
float lightPosn[MAX_ACTIVE_LIGHTS][4];
float lightDirn[MAX_ACTIVE_LIGHTS][4];
/* palettes texture management */
PALETTEENTRY palettes[MAX_PALETTES][256];
UINT currentPalette;
......@@ -354,6 +370,7 @@ struct IDirect3DDevice8Impl
Window win;
GLXContext render_ctx;
Drawable drawable;
GLint maxConcurrentLights;
/* OpenGL Extension related */
......@@ -1015,9 +1032,7 @@ extern HRESULT WINAPI IDirect3DVolumeTexture8Impl_AddDirtyBox(LPDIRECT3D
/* Note: Very long winded but I do not believe gl Lists will */
/* resolve everything we need, so doing it manually for now */
typedef struct SAVEDSTATES {
BOOL lightEnable[MAX_ACTIVE_LIGHTS];
BOOL Indices;
BOOL lights[MAX_ACTIVE_LIGHTS];
BOOL material;
BOOL stream_source[MAX_STREAMS];
BOOL textures[8];
......@@ -1059,9 +1074,6 @@ struct IDirect3DStateBlockImpl {
SAVEDSTATES Changed;
SAVEDSTATES Set;
/* Light Enable */
BOOL lightEnable[MAX_ACTIVE_LIGHTS];
/* ClipPlane */
double clipplane[MAX_CLIPPLANES][4];
......@@ -1081,7 +1093,7 @@ struct IDirect3DStateBlockImpl {
DWORD texture_state[8][HIGHEST_TEXTURE_STATE];
/* Lights */
D3DLIGHT8 lights[MAX_ACTIVE_LIGHTS];
PLIGHTINFOEL *lights; /* NOTE: active GL lights must be front of the chain */
/* Material */
D3DMATERIAL8 material;
......@@ -1321,4 +1333,13 @@ extern LONG primCounter;
#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
#define TRACE_STRIDED(sd,name) TRACE( #name "=(data:%p, stride:%ld, type:%ld)\n", sd->u.s.name.lpData, sd->u.s.name.dwStride, sd->u.s.name.dwType);
#define DUMP_LIGHT_CHAIN() \
{ \
PLIGHTINFOEL *el = This->StateBlock->lights;\
while (el) { \
TRACE("Light %p (glIndex %ld, d3dIndex %ld, enabled %d)\n", el, el->glIndex, el->OriginalIndex, el->lightEnabled);\
el = el->next; \
} \
}
#endif /* __WINE_D3DX8_PRIVATE_H */
......@@ -160,9 +160,9 @@ UINT WINAPI IDirect3D8Impl_GetAdapterModeCount (LPDIRECT3D8 iface,
int i = 0;
while (EnumDisplaySettingsExW(NULL, i, &DevModeW, 0)) {
TRACE("(%p}->(Adapter: %d) => %d\n", This, Adapter, i);
i++;
}
TRACE("(%p}->(Adapter: %d) => %d\n", This, Adapter, i);
return i;
} else {
FIXME("Adapter not primary display\n");
......@@ -190,8 +190,12 @@ HRESULT WINAPI IDirect3D8Impl_EnumAdapterModes (LPDIRECT3D8 iface,
{
pMode->Width = DevModeW.dmPelsWidth;
pMode->Height = DevModeW.dmPelsHeight;
bpp = DevModeW.dmBitsPerPel;
pMode->RefreshRate = D3DADAPTER_DEFAULT;
bpp = DevModeW.dmBitsPerPel;
if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
{
pMode->RefreshRate = DevModeW.dmDisplayFrequency;
}
}
else
{
......@@ -229,16 +233,18 @@ HRESULT WINAPI IDirect3D8Impl_GetAdapterDisplayMode (LPDIRECT3D8 iface,
}
if (Adapter == 0) { /* Display */
HDC hdc;
int bpp = 0;
DEVMODEW DevModeW;
pMode->Width = GetSystemMetrics(SM_CXSCREEN);
pMode->Height = GetSystemMetrics(SM_CYSCREEN);
pMode->RefreshRate = 85; /*FIXME: How to identify? */
hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
bpp = GetDeviceCaps(hdc, BITSPIXEL);
DeleteDC(hdc);
EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
pMode->Width = DevModeW.dmPelsWidth;
pMode->Height = DevModeW.dmPelsHeight;
bpp = DevModeW.dmBitsPerPel;
pMode->RefreshRate = D3DADAPTER_DEFAULT;
if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
{
pMode->RefreshRate = DevModeW.dmDisplayFrequency;
}
switch (bpp) {
case 8: pMode->Format = D3DFMT_R3G3B2; break;
......@@ -621,7 +627,7 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D
TRACE("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
pCaps->MaxActiveLights = min(MAX_ACTIVE_LIGHTS, gl_max);
pCaps->MaxActiveLights = gl_max;
TRACE("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
#if defined(GL_ARB_vertex_blend)
......@@ -716,7 +722,7 @@ static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) {
TRACE("ClipPlanes support - num Planes=%d\n", gl_max);
glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
This->gl_info.max_lights = min(MAX_ACTIVE_LIGHTS, gl_max);
This->gl_info.max_lights = gl_max;
TRACE("Lights support - max lights=%d\n", gl_max);
/* Parse the gl supported features, in theory enabling parts of our code appropriately */
......@@ -1151,7 +1157,7 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
object->proj_valid = 0;
object->view_ident = 1;
object->last_was_rhw = 0;
glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights);
TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
return D3D_OK;
}
......
......@@ -321,9 +321,31 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This,
object->Changed.texture_state[j][SavedVertexStates_T[i]] = TRUE;
}
}
for (i = 0; i < GL_LIMITS(lights); i++) {
object->Changed.lightEnable[i] = TRUE;
object->Changed.lights[i] = TRUE;
/* Duplicate light chain */
{
PLIGHTINFOEL *src = NULL;
PLIGHTINFOEL *dst = NULL;
PLIGHTINFOEL *newEl = NULL;
src = This->StateBlock->lights;
object->lights = NULL;
while (src) {
newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
memcpy(newEl, src, sizeof(PLIGHTINFOEL));
newEl->prev = dst;
newEl->changed = TRUE;
newEl->enabledChanged = TRUE;
if (dst == NULL) {
object->lights = newEl;
} else {
dst->next = newEl;
}
dst = newEl;
src = src->next;
}
}
} else {
......@@ -337,7 +359,16 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This,
/** yakkk temporary waiting for Release */
HRESULT WINAPI IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* pSB) {
PLIGHTINFOEL *tmp;
TRACE("(%p) : freeing StateBlock %p\n", This, pSB);
tmp = pSB->lights;
if (tmp) tmp = tmp->next;
while (tmp != NULL) {
HeapFree(GetProcessHeap(), 0, (void *)(tmp->prev));
tmp = tmp->next;
}
if (tmp) HeapFree(GetProcessHeap(), 0, (void *)tmp);
HeapFree(GetProcessHeap(), 0, (void *)pSB);
return D3D_OK;
}
......@@ -397,12 +428,13 @@ HRESULT WINAPI IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This,
if (pSB->blockType == D3DSBT_RECORDED || pSB->blockType == D3DSBT_ALL || pSB->blockType == D3DSBT_VERTEXSTATE) {
for (i = 0; i < GL_LIMITS(lights); i++) {
if (pSB->Set.lightEnable[i] && pSB->Changed.lightEnable[i])
IDirect3DDevice8Impl_LightEnable(iface, i, pSB->lightEnable[i]);
if (pSB->Set.lights[i] && pSB->Changed.lights[i])
IDirect3DDevice8Impl_SetLight(iface, i, &pSB->lights[i]);
PLIGHTINFOEL *toDo = pSB->lights;
while (toDo != NULL) {
if (toDo->changed)
IDirect3DDevice8Impl_SetLight(iface, toDo->OriginalIndex, &toDo->OriginalParms);
if (toDo->enabledChanged)
IDirect3DDevice8Impl_LightEnable(iface, toDo->OriginalIndex, toDo->lightEnabled);
toDo = toDo->next;
}
if (pSB->Set.vertexShader && pSB->Changed.vertexShader)
......@@ -514,6 +546,7 @@ HRESULT WINAPI IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This,
HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* updateBlock) {
LPDIRECT3DDEVICE8 iface = (LPDIRECT3DDEVICE8) This;
PLIGHTINFOEL *tmp;
TRACE("(%p) : Updating state block %p ------------------v \n", This, updateBlock);
......@@ -521,14 +554,18 @@ HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This,
if (updateBlock->blockType != D3DSBT_RECORDED) {
IDirect3DStateBlockImpl* tmpBlock;
IDirect3DDeviceImpl_CreateStateBlock(This, updateBlock->blockType, &tmpBlock);
/* Note just swap the light chains over so when deleting, the old one goes */
tmp = updateBlock->lights;
memcpy(updateBlock, tmpBlock, sizeof(IDirect3DStateBlockImpl));
IDirect3DDeviceImpl_DeleteStateBlock(This, tmpBlock);
tmpBlock->lights = tmp;
/* FIXME: This will record states of new lights! May need to have and save set_lights
across this action */
/* Delete the temporary one (which points to the old light chain though */
IDirect3DDeviceImpl_DeleteStateBlock(This, tmpBlock);
} else {
int i, j;
PLIGHTINFOEL *src;
/* Recorded => Only update 'changed' values */
if (updateBlock->Set.vertexShader && updateBlock->VertexShader != This->StateBlock->VertexShader) {
......@@ -538,23 +575,42 @@ HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This,
/* TODO: Vertex Shader Constants */
for (i = 0; i < GL_LIMITS(lights); i++) {
if (updateBlock->Set.lightEnable[i] && This->StateBlock->lightEnable[i] != updateBlock->lightEnable[i]) {
TRACE("Updating light enable for light %d to %d\n", i, This->StateBlock->lightEnable[i]);
updateBlock->lightEnable[i] = This->StateBlock->lightEnable[i];
}
if (updateBlock->Set.lights[i] && memcmp(&This->StateBlock->lights[i],
&updateBlock->lights[i],
sizeof(D3DLIGHT8)) != 0) {
TRACE("Updating lights for light %d\n", i);
memcpy(&updateBlock->lights[i], &This->StateBlock->lights[i], sizeof(D3DLIGHT8));
}
/* Lights... For a recorded state block, we just had a chain of actions to perform,
so we need to walk that chain and update any actions which differ */
src = updateBlock->lights;
while (src != NULL) {
PLIGHTINFOEL *realLight = NULL;
/* Locate the light in the live lights */
realLight = This->StateBlock->lights;
while (realLight != NULL && realLight->OriginalIndex != src->OriginalIndex) realLight = realLight->next;
if (realLight == NULL) {
FIXME("A captured light no longer exists...?\n");
} else {
/* If 'changed' then its a SetLight command. Rather than comparing to see
if the OriginalParms have changed and then copy them (twice through
memory) just do the copy */
if (src->changed) {
TRACE("Updating lights for light %ld\n", src->OriginalIndex);
memcpy(&src->OriginalParms, &realLight->OriginalParms, sizeof(PLIGHTINFOEL));
}
/* If 'enabledChanged' then its a LightEnable command */
if (src->enabledChanged) {
TRACE("Updating lightEnabled for light %ld\n", src->OriginalIndex);
src->lightEnabled = realLight->lightEnabled;
}
}
src = src->next;
}
if (updateBlock->Set.pixelShader && updateBlock->PixelShader != This->StateBlock->PixelShader) {
TRACE("Updating pixel shader to %ld\n", This->StateBlock->PixelShader);
updateBlock->lights[i] = This->StateBlock->lights[i];
IDirect3DDevice8Impl_SetVertexShader(iface, updateBlock->PixelShader);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment