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; ...@@ -67,7 +67,6 @@ extern int num_lock;
/* Device caps */ /* Device caps */
#define MAX_PALETTES 256 #define MAX_PALETTES 256
#define MAX_STREAMS 16 #define MAX_STREAMS 16
#define MAX_ACTIVE_LIGHTS 8
#define MAX_CLIPPLANES D3DMAXUSERCLIPPLANES #define MAX_CLIPPLANES D3DMAXUSERCLIPPLANES
#define MAX_LEVELS 256 #define MAX_LEVELS 256
...@@ -174,6 +173,27 @@ typedef struct PSHADEROUTPUTDATA8 { ...@@ -174,6 +173,27 @@ typedef struct PSHADEROUTPUTDATA8 {
D3DSHADERVECTOR oDepth; D3DSHADERVECTOR oDepth;
} PSHADEROUTPUTDATA8; } 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 * Macros
...@@ -326,10 +346,6 @@ struct IDirect3DDevice8Impl ...@@ -326,10 +346,6 @@ struct IDirect3DDevice8Impl
IDirect3DStateBlockImpl *StateBlock; IDirect3DStateBlockImpl *StateBlock;
IDirect3DStateBlockImpl *UpdateStateBlock; IDirect3DStateBlockImpl *UpdateStateBlock;
/* Other required values */
float lightPosn[MAX_ACTIVE_LIGHTS][4];
float lightDirn[MAX_ACTIVE_LIGHTS][4];
/* palettes texture management */ /* palettes texture management */
PALETTEENTRY palettes[MAX_PALETTES][256]; PALETTEENTRY palettes[MAX_PALETTES][256];
UINT currentPalette; UINT currentPalette;
...@@ -354,6 +370,7 @@ struct IDirect3DDevice8Impl ...@@ -354,6 +370,7 @@ struct IDirect3DDevice8Impl
Window win; Window win;
GLXContext render_ctx; GLXContext render_ctx;
Drawable drawable; Drawable drawable;
GLint maxConcurrentLights;
/* OpenGL Extension related */ /* OpenGL Extension related */
...@@ -1015,9 +1032,7 @@ extern HRESULT WINAPI IDirect3DVolumeTexture8Impl_AddDirtyBox(LPDIRECT3D ...@@ -1015,9 +1032,7 @@ extern HRESULT WINAPI IDirect3DVolumeTexture8Impl_AddDirtyBox(LPDIRECT3D
/* Note: Very long winded but I do not believe gl Lists will */ /* Note: Very long winded but I do not believe gl Lists will */
/* resolve everything we need, so doing it manually for now */ /* resolve everything we need, so doing it manually for now */
typedef struct SAVEDSTATES { typedef struct SAVEDSTATES {
BOOL lightEnable[MAX_ACTIVE_LIGHTS];
BOOL Indices; BOOL Indices;
BOOL lights[MAX_ACTIVE_LIGHTS];
BOOL material; BOOL material;
BOOL stream_source[MAX_STREAMS]; BOOL stream_source[MAX_STREAMS];
BOOL textures[8]; BOOL textures[8];
...@@ -1059,9 +1074,6 @@ struct IDirect3DStateBlockImpl { ...@@ -1059,9 +1074,6 @@ struct IDirect3DStateBlockImpl {
SAVEDSTATES Changed; SAVEDSTATES Changed;
SAVEDSTATES Set; SAVEDSTATES Set;
/* Light Enable */
BOOL lightEnable[MAX_ACTIVE_LIGHTS];
/* ClipPlane */ /* ClipPlane */
double clipplane[MAX_CLIPPLANES][4]; double clipplane[MAX_CLIPPLANES][4];
...@@ -1081,7 +1093,7 @@ struct IDirect3DStateBlockImpl { ...@@ -1081,7 +1093,7 @@ struct IDirect3DStateBlockImpl {
DWORD texture_state[8][HIGHEST_TEXTURE_STATE]; DWORD texture_state[8][HIGHEST_TEXTURE_STATE];
/* Lights */ /* Lights */
D3DLIGHT8 lights[MAX_ACTIVE_LIGHTS]; PLIGHTINFOEL *lights; /* NOTE: active GL lights must be front of the chain */
/* Material */ /* Material */
D3DMATERIAL8 material; D3DMATERIAL8 material;
...@@ -1321,4 +1333,13 @@ extern LONG primCounter; ...@@ -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_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 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 */ #endif /* __WINE_D3DX8_PRIVATE_H */
...@@ -160,9 +160,9 @@ UINT WINAPI IDirect3D8Impl_GetAdapterModeCount (LPDIRECT3D8 iface, ...@@ -160,9 +160,9 @@ UINT WINAPI IDirect3D8Impl_GetAdapterModeCount (LPDIRECT3D8 iface,
int i = 0; int i = 0;
while (EnumDisplaySettingsExW(NULL, i, &DevModeW, 0)) { while (EnumDisplaySettingsExW(NULL, i, &DevModeW, 0)) {
TRACE("(%p}->(Adapter: %d) => %d\n", This, Adapter, i);
i++; i++;
} }
TRACE("(%p}->(Adapter: %d) => %d\n", This, Adapter, i);
return i; return i;
} else { } else {
FIXME("Adapter not primary display\n"); FIXME("Adapter not primary display\n");
...@@ -190,8 +190,12 @@ HRESULT WINAPI IDirect3D8Impl_EnumAdapterModes (LPDIRECT3D8 iface, ...@@ -190,8 +190,12 @@ HRESULT WINAPI IDirect3D8Impl_EnumAdapterModes (LPDIRECT3D8 iface,
{ {
pMode->Width = DevModeW.dmPelsWidth; pMode->Width = DevModeW.dmPelsWidth;
pMode->Height = DevModeW.dmPelsHeight; pMode->Height = DevModeW.dmPelsHeight;
bpp = DevModeW.dmBitsPerPel;
pMode->RefreshRate = D3DADAPTER_DEFAULT; pMode->RefreshRate = D3DADAPTER_DEFAULT;
bpp = DevModeW.dmBitsPerPel; if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
{
pMode->RefreshRate = DevModeW.dmDisplayFrequency;
}
} }
else else
{ {
...@@ -229,16 +233,18 @@ HRESULT WINAPI IDirect3D8Impl_GetAdapterDisplayMode (LPDIRECT3D8 iface, ...@@ -229,16 +233,18 @@ HRESULT WINAPI IDirect3D8Impl_GetAdapterDisplayMode (LPDIRECT3D8 iface,
} }
if (Adapter == 0) { /* Display */ if (Adapter == 0) { /* Display */
HDC hdc;
int bpp = 0; int bpp = 0;
DEVMODEW DevModeW;
pMode->Width = GetSystemMetrics(SM_CXSCREEN); EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
pMode->Height = GetSystemMetrics(SM_CYSCREEN); pMode->Width = DevModeW.dmPelsWidth;
pMode->RefreshRate = 85; /*FIXME: How to identify? */ pMode->Height = DevModeW.dmPelsHeight;
bpp = DevModeW.dmBitsPerPel;
hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); pMode->RefreshRate = D3DADAPTER_DEFAULT;
bpp = GetDeviceCaps(hdc, BITSPIXEL); if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
DeleteDC(hdc); {
pMode->RefreshRate = DevModeW.dmDisplayFrequency;
}
switch (bpp) { switch (bpp) {
case 8: pMode->Format = D3DFMT_R3G3B2; break; case 8: pMode->Format = D3DFMT_R3G3B2; break;
...@@ -621,7 +627,7 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D ...@@ -621,7 +627,7 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D
TRACE("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes); TRACE("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
glGetIntegerv(GL_MAX_LIGHTS, &gl_max); 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); TRACE("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
#if defined(GL_ARB_vertex_blend) #if defined(GL_ARB_vertex_blend)
...@@ -716,7 +722,7 @@ static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) { ...@@ -716,7 +722,7 @@ static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) {
TRACE("ClipPlanes support - num Planes=%d\n", gl_max); TRACE("ClipPlanes support - num Planes=%d\n", gl_max);
glGetIntegerv(GL_MAX_LIGHTS, &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); TRACE("Lights support - max lights=%d\n", gl_max);
/* Parse the gl supported features, in theory enabling parts of our code appropriately */ /* Parse the gl supported features, in theory enabling parts of our code appropriately */
...@@ -1151,7 +1157,7 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, ...@@ -1151,7 +1157,7 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
object->proj_valid = 0; object->proj_valid = 0;
object->view_ident = 1; object->view_ident = 1;
object->last_was_rhw = 0; 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); TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
return D3D_OK; return D3D_OK;
} }
......
...@@ -321,9 +321,31 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This, ...@@ -321,9 +321,31 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This,
object->Changed.texture_state[j][SavedVertexStates_T[i]] = TRUE; object->Changed.texture_state[j][SavedVertexStates_T[i]] = TRUE;
} }
} }
for (i = 0; i < GL_LIMITS(lights); i++) {
object->Changed.lightEnable[i] = TRUE; /* Duplicate light chain */
object->Changed.lights[i] = TRUE; {
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 { } else {
...@@ -337,7 +359,16 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This, ...@@ -337,7 +359,16 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This,
/** yakkk temporary waiting for Release */ /** yakkk temporary waiting for Release */
HRESULT WINAPI IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* pSB) { HRESULT WINAPI IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* pSB) {
PLIGHTINFOEL *tmp;
TRACE("(%p) : freeing StateBlock %p\n", This, pSB); 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); HeapFree(GetProcessHeap(), 0, (void *)pSB);
return D3D_OK; return D3D_OK;
} }
...@@ -397,12 +428,13 @@ HRESULT WINAPI IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This, ...@@ -397,12 +428,13 @@ HRESULT WINAPI IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This,
if (pSB->blockType == D3DSBT_RECORDED || pSB->blockType == D3DSBT_ALL || pSB->blockType == D3DSBT_VERTEXSTATE) { if (pSB->blockType == D3DSBT_RECORDED || pSB->blockType == D3DSBT_ALL || pSB->blockType == D3DSBT_VERTEXSTATE) {
for (i = 0; i < GL_LIMITS(lights); i++) { PLIGHTINFOEL *toDo = pSB->lights;
while (toDo != NULL) {
if (pSB->Set.lightEnable[i] && pSB->Changed.lightEnable[i]) if (toDo->changed)
IDirect3DDevice8Impl_LightEnable(iface, i, pSB->lightEnable[i]); IDirect3DDevice8Impl_SetLight(iface, toDo->OriginalIndex, &toDo->OriginalParms);
if (pSB->Set.lights[i] && pSB->Changed.lights[i]) if (toDo->enabledChanged)
IDirect3DDevice8Impl_SetLight(iface, i, &pSB->lights[i]); IDirect3DDevice8Impl_LightEnable(iface, toDo->OriginalIndex, toDo->lightEnabled);
toDo = toDo->next;
} }
if (pSB->Set.vertexShader && pSB->Changed.vertexShader) if (pSB->Set.vertexShader && pSB->Changed.vertexShader)
...@@ -514,6 +546,7 @@ HRESULT WINAPI IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This, ...@@ -514,6 +546,7 @@ HRESULT WINAPI IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This,
HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* updateBlock) { HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* updateBlock) {
LPDIRECT3DDEVICE8 iface = (LPDIRECT3DDEVICE8) This; LPDIRECT3DDEVICE8 iface = (LPDIRECT3DDEVICE8) This;
PLIGHTINFOEL *tmp;
TRACE("(%p) : Updating state block %p ------------------v \n", This, updateBlock); TRACE("(%p) : Updating state block %p ------------------v \n", This, updateBlock);
...@@ -521,14 +554,18 @@ HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This, ...@@ -521,14 +554,18 @@ HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This,
if (updateBlock->blockType != D3DSBT_RECORDED) { if (updateBlock->blockType != D3DSBT_RECORDED) {
IDirect3DStateBlockImpl* tmpBlock; IDirect3DStateBlockImpl* tmpBlock;
IDirect3DDeviceImpl_CreateStateBlock(This, updateBlock->blockType, &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)); 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 /* Delete the temporary one (which points to the old light chain though */
across this action */ IDirect3DDeviceImpl_DeleteStateBlock(This, tmpBlock);
} else { } else {
int i, j; int i, j;
PLIGHTINFOEL *src;
/* Recorded => Only update 'changed' values */ /* Recorded => Only update 'changed' values */
if (updateBlock->Set.vertexShader && updateBlock->VertexShader != This->StateBlock->VertexShader) { if (updateBlock->Set.vertexShader && updateBlock->VertexShader != This->StateBlock->VertexShader) {
...@@ -538,23 +575,42 @@ HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This, ...@@ -538,23 +575,42 @@ HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This,
/* TODO: Vertex Shader Constants */ /* TODO: Vertex Shader Constants */
for (i = 0; i < GL_LIMITS(lights); i++) { /* Lights... For a recorded state block, we just had a chain of actions to perform,
if (updateBlock->Set.lightEnable[i] && This->StateBlock->lightEnable[i] != updateBlock->lightEnable[i]) { so we need to walk that chain and update any actions which differ */
TRACE("Updating light enable for light %d to %d\n", i, This->StateBlock->lightEnable[i]); src = updateBlock->lights;
updateBlock->lightEnable[i] = This->StateBlock->lightEnable[i]; while (src != NULL) {
} PLIGHTINFOEL *realLight = NULL;
if (updateBlock->Set.lights[i] && memcmp(&This->StateBlock->lights[i], /* Locate the light in the live lights */
&updateBlock->lights[i], realLight = This->StateBlock->lights;
sizeof(D3DLIGHT8)) != 0) { while (realLight != NULL && realLight->OriginalIndex != src->OriginalIndex) realLight = realLight->next;
TRACE("Updating lights for light %d\n", i);
memcpy(&updateBlock->lights[i], &This->StateBlock->lights[i], sizeof(D3DLIGHT8)); 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) { if (updateBlock->Set.pixelShader && updateBlock->PixelShader != This->StateBlock->PixelShader) {
TRACE("Updating pixel shader to %ld\n", 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); 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