[WINED3D 6/8] Stateblock support for dmap and vtf samplers
Ivan Gyurdiev
ivg231 at gmail.com
Mon Oct 2 19:18:15 CDT 2006
Add displacement map and vertex texture (vtf) samplers to the stateblock.
Nothing is done with them yet... todo.
-------------- next part --------------
>From 30cf4451d4aaa69ef66c9d5969ec93b1953a2ba5 Mon Sep 17 00:00:00 2001
From: Ivan Gyurdiev <ivg2 at cornell.edu>
Date: Mon, 2 Oct 2006 19:48:06 -0400
Subject: [PATCH] Stateblock support for dmap and vtf samplers.
Add displacement map and vertex texture (vtf) samplers to the stateblock.
Nothing is done with them yet... todo.
---
dlls/wined3d/device.c | 91 +++++++++++++++++++++++++++++-----------
dlls/wined3d/directx.c | 5 ++
dlls/wined3d/stateblock.c | 64 +++++++++++++++++++++++++++-
dlls/wined3d/wined3d_private.h | 7 +++
include/wine/wined3d_gl.h | 1
5 files changed, 139 insertions(+), 29 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 6f79444..a99798f 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -8,6 +8,7 @@
* Copyright 2005 Oliver Stieber
* Copyright 2006 Stefan Dösinger for CodeWeavers
* Copyright 2006 Henri Verbeet
+ * Copyright 2006 Ivan Gyurdiev
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -2156,9 +2157,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl
This->cursorTexture = 0;
}
- for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
+ /* Set all textures to NULL */
+ IWineD3DDevice_SetTexture(iface, D3DDMAPSAMPLER, NULL);
+
+ for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler)
IWineD3DDevice_SetTexture(iface, sampler, NULL);
- }
+
+ for(sampler = 0; sampler < GL_LIMITS(vertex_samplers); ++sampler)
+ IWineD3DDevice_SetTexture(iface, D3DVERTEXTEXTURESAMPLER0 + sampler, NULL);
/* Release the buffers (with sanity checks)*/
TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
@@ -5738,20 +5744,23 @@ static HRESULT WINAPI IWineD3DDeviceImpl
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DBaseTexture *oldTexture;
-
- oldTexture = This->updateStateBlock->textures[Stage];
+ BOOL vertexTexture = FALSE;
+ BOOL dmapTexture = FALSE;
+
TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
-
-#if 0 /* TODO: check so vertex textures */
- if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
- This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
- return WINED3D_OK;
- }
-#endif
-
+
+ /* Check for displacement map sampler */
+ if (Stage == D3DDMAPSAMPLER)
+ dmapTexture = TRUE;
+
+ /* Check for vertex shader textures */
+ else if (Stage >= D3DVERTEXTEXTURESAMPLER0 && Stage <= D3DVERTEXTEXTURESAMPLER3)
+ vertexTexture = TRUE;
+
/* Reject invalid texture units */
- if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
- WARN("Attempt to access invalid texture rejected\n");
+ else if (Stage >= GL_LIMITS(sampler_stages)) {
+ WARN("Attempt to access invalid texture rejected, stage=%u, limit=%u\n",
+ Stage, GL_LIMITS(sampler_stages));
return WINED3DERR_INVALIDCALL;
}
@@ -5764,14 +5773,34 @@ #endif
}
}
- oldTexture = This->updateStateBlock->textures[Stage];
- TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
- TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
+ if (dmapTexture) {
+ oldTexture = This->updateStateBlock->dmapTexture;
+ TRACE("(%p) : Old Texture: (Stage=%u, %p)\n", This, Stage, oldTexture);
+ TRACE("(%p) : New Texture: (Stage=%u, %p)\n", This, Stage, pTexture);
+ This->updateStateBlock->set.dmapTexture = TRUE;
+ This->updateStateBlock->changed.dmapTexture = TRUE;
+ This->updateStateBlock->dmapTexture = pTexture;
- This->updateStateBlock->set.textures[Stage] = TRUE;
- This->updateStateBlock->changed.textures[Stage] = TRUE;
- TRACE("(%p) : setting new texture to %p\n", This, pTexture);
- This->updateStateBlock->textures[Stage] = pTexture;
+ } else if (vertexTexture) {
+ const int idx = Stage - D3DVERTEXTEXTURESAMPLER0;
+ oldTexture = This->updateStateBlock->vertexTextures[idx];
+ TRACE("(%p) : Old Texture: (Stage=%u, %p)\n", This, Stage, oldTexture);
+ TRACE("(%p) : New Texture: (Stage=%u, %p)\n", This, Stage, pTexture);
+
+ This->updateStateBlock->set.vertexTextures[idx] = TRUE;
+ This->updateStateBlock->changed.vertexTextures[idx] = TRUE;
+ This->updateStateBlock->vertexTextures[idx] = pTexture;
+
+ } else {
+ const int idx = Stage;
+ oldTexture = This->updateStateBlock->textures[idx];
+ TRACE("(%p) : Old Texture: (Stage=%u, %p)\n", This, Stage, oldTexture);
+ TRACE("(%p) : New Texture: (Stage=%u, %p)\n", This, Stage, pTexture);
+
+ This->updateStateBlock->set.textures[idx] = TRUE;
+ This->updateStateBlock->changed.textures[idx] = TRUE;
+ This->updateStateBlock->textures[idx] = pTexture;
+ }
/* Handle recording of state blocks */
if (This->isRecordingState) {
@@ -5783,8 +5812,8 @@ #endif
* and the the application nust set the texture back to null (or have a leaky application),
* This means we should pass the refcount up to the parent
*******************************/
- if (NULL != This->updateStateBlock->textures[Stage]) {
- IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
+ if (NULL != pTexture) {
+ IWineD3DBaseTexture_AddRef(pTexture);
}
if (NULL != oldTexture) {
@@ -5813,12 +5842,22 @@ static HRESULT WINAPI IWineD3DDeviceImpl
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
- /* Reject invalid texture units */
- if (Stage >= GL_LIMITS(sampler_stages)) {
+ /* Check for vertex shader textures */
+
+ if (Stage == D3DDMAPSAMPLER)
+ *ppTexture = This->updateStateBlock->dmapTexture;
+
+ else if (Stage >= D3DVERTEXTEXTURESAMPLER0 && Stage <= D3DVERTEXTEXTURESAMPLER3)
+ *ppTexture = This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER0];
+
+ else if (Stage < GL_LIMITS(sampler_stages))
+ *ppTexture = This->updateStateBlock->textures[Stage];
+
+ else {
TRACE("Attempt to access invalid texture rejected\n");
return WINED3DERR_INVALIDCALL;
}
- *ppTexture=This->updateStateBlock->textures[Stage];
+
if (*ppTexture)
IWineD3DBaseTexture_AddRef(*ppTexture);
else
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 0563918..2627d30 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -5,6 +5,7 @@
* Copyright 2003-2004 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
+ * Copyright 2006 Ivan Gyurdiev
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -464,6 +465,7 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *i
gl_info->max_textures = 1;
gl_info->max_texture_stages = 1;
gl_info->max_samplers = 1;
+ gl_info->max_vertex_samplers = 0;
gl_info->max_sampler_stages = 1;
gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
gl_info->ps_arb_max_temps = 0;
@@ -622,6 +624,9 @@ #undef USE_GL_FUNC
gl_max /= 4;
TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
gl_info->vs_glsl_constantsF = gl_max;
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
+ TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max vs samplers=%u\n", gl_max);
+ gl_info->max_vertex_samplers = min(MAX_VERTEX_SAMPLERS, gl_max);
} else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 98de692..d066f46 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -78,11 +78,13 @@ void stateblock_savedstates_copy(
dest->vertexDecl = source->vertexDecl;
dest->pixelShader = source->pixelShader;
dest->vertexShader = source->vertexShader;
+ dest->dmapTexture = source->dmapTexture;
/* Fixed size arrays */
memcpy(dest->streamSource, source->streamSource, bsize * MAX_STREAMS);
memcpy(dest->streamFreq, source->streamFreq, bsize * MAX_STREAMS);
memcpy(dest->textures, source->textures, bsize * MAX_SAMPLERS);
+ memcpy(dest->vertexTextures, source->vertexTextures, bsize * MAX_VERTEX_SAMPLERS);
memcpy(dest->transform, source->transform, bsize * (HIGHEST_TRANSFORMSTATE + 1));
memcpy(dest->renderState, source->renderState, bsize * (WINEHIGHEST_RENDER_STATE + 1));
memcpy(dest->textureState, source->textureState, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
@@ -115,11 +117,13 @@ void stateblock_savedstates_set(
states->vertexDecl = value;
states->pixelShader = value;
states->vertexShader = value;
+ states->dmapTexture = FALSE;
/* Fixed size arrays */
memset(states->streamSource, value, bsize * MAX_STREAMS);
memset(states->streamFreq, value, bsize * MAX_STREAMS);
memset(states->textures, value, bsize * MAX_SAMPLERS);
+ memset(states->vertexTextures, value, bsize * MAX_VERTEX_SAMPLERS);
memset(states->transform, value, bsize * (HIGHEST_TRANSFORMSTATE + 1));
memset(states->renderState, value, bsize * (WINEHIGHEST_RENDER_STATE + 1));
memset(states->textureState, value, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
@@ -170,6 +174,8 @@ void stateblock_copy(
Dest->vertex_blend = This->vertex_blend;
Dest->tween_factor = This->tween_factor;
Dest->glsl_program = This->glsl_program;
+ Dest->dmapTexture = This->dmapTexture;
+ Dest->dmapTextureDimensions = This->dmapTextureDimensions;
/* Fixed size arrays */
memcpy(Dest->vertexShaderConstantB, This->vertexShaderConstantB, sizeof(BOOL) * MAX_CONST_B);
@@ -187,6 +193,9 @@ void stateblock_copy(
memcpy(Dest->renderState, This->renderState, sizeof(DWORD) * (WINEHIGHEST_RENDER_STATE + 1));
memcpy(Dest->textures, This->textures, sizeof(IWineD3DBaseTexture*) * MAX_SAMPLERS);
memcpy(Dest->textureDimensions, This->textureDimensions, sizeof(int) * MAX_SAMPLERS);
+ memcpy(Dest->vertexTextures, This->vertexTextures, sizeof(IWineD3DBaseTexture*) * MAX_VERTEX_SAMPLERS);
+ memcpy(Dest->vertexTextureDimensions, This->vertexTextureDimensions, sizeof(int) * MAX_VERTEX_SAMPLERS);
+
memcpy(Dest->textureState, This->textureState, sizeof(DWORD) * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
memcpy(Dest->samplerState, This->samplerState, sizeof(DWORD) * MAX_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1));
@@ -261,15 +270,31 @@ static ULONG WINAPI IWineD3DStateBlockI
}
/* NOTE: according to MSDN: The application is responsible for making sure the texture references are cleared down */
+
+ if (This->dmapTexture) {
+ /* release our 'internal' hold on the texture */
+ if (0 != IWineD3DBaseTexture_Release(This->dmapTexture))
+ TRACE("Texture still referenced by stateblock, application has leaked "
+ "(Stage = %u, Texture = %p)\n", D3DDMAPSAMPLER, This->dmapTexture);
+ }
+
for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
if (This->textures[counter]) {
/* release our 'internal' hold on the texture */
- if(0 != IWineD3DBaseTexture_Release(This->textures[counter])) {
- TRACE("Texture still referenced by stateblock, applications has leaked Stage = %u Texture = %p\n", counter, This->textures[counter]);
- }
+ if(0 != IWineD3DBaseTexture_Release(This->textures[counter]))
+ TRACE("Texture still referenced by stateblock, application has leaked "
+ "(Stage = %u, Texture = %p)\n", counter, This->textures[counter]);
}
}
+ for (counter = 0; counter < GL_LIMITS(vertex_samplers); counter++) {
+ if (This->vertexTextures[counter]) {
+ /* release our 'internal' hold on the texture */
+ if (0 != IWineD3DBaseTexture_Release(This->vertexTextures[counter]))
+ TRACE("Texture still referenced by stateblock, application has leaked "
+ "(Stage = %u, Texture = %p)\n", D3DVERTEXTEXTURESAMPLER0 + counter, This->vertexTextures[counter]);
+ }
+ }
}
HeapFree(GetProcessHeap(), 0, This->vertexShaderConstantF);
@@ -586,6 +611,14 @@ static HRESULT WINAPI IWineD3DStateBloc
/* Samplers */
/* TODO: move over to using memcpy */
+
+ if (This->set.dmapTexture) {
+ TRACE("Updating texture %d to %p (was %p)\n",
+ D3DDMAPSAMPLER, targetStateBlock->dmapTexture, This->dmapTexture);
+ This->dmapTexture = targetStateBlock->dmapTexture;
+ }
+ /* FIXME: is sampler state allowed here? */
+
for (j = 0; j < GL_LIMITS(sampler_stages); j++) {
if (This->set.textures[j]) {
TRACE("Updating texture %d to %p (was %p)\n", j, targetStateBlock->textures[j], This->textures[j]);
@@ -600,6 +633,16 @@ static HRESULT WINAPI IWineD3DStateBloc
}
}
}
+
+ for (j = 0; j < GL_LIMITS(vertex_samplers); j++) {
+ if (This->set.vertexTextures[j]) {
+ TRACE("Updating texture %d to %p (was %p)\n",
+ D3DVERTEXTEXTURESAMPLER0 + j, targetStateBlock->vertexTextures[j], This->vertexTextures[j]);
+ This->vertexTextures[j] = targetStateBlock->vertexTextures[j];
+ }
+ /* FIXME: are sampler states allowed here? */
+ }
+
}
TRACE("(%p) : Updated state block %p ------------------^\n", targetStateBlock, This);
@@ -745,6 +788,12 @@ should really perform a delta so that on
/* Samplers */
/* TODO: move over to memcpy */
+
+ if (This->set.dmapTexture && This->changed.dmapTexture) {
+ IWineD3DDevice_SetTexture(pDevice, D3DDMAPSAMPLER, This->dmapTexture);
+ }
+ /* FIXME: are sampler states allowed here? */
+
for (j = 0 ; j < GL_LIMITS(sampler_stages); j++){
if (This->set.textures[j] && This->changed.textures[j]) {
IWineD3DDevice_SetTexture(pDevice, j, This->textures[j]);
@@ -756,9 +805,16 @@ should really perform a delta so that on
((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.samplerState[j][i] = TRUE;
}
}
+ }
+ for (j = 0 ; j < GL_LIMITS(vertex_samplers); j++){
+ if (This->set.vertexTextures[j] && This->changed.vertexTextures[j]) {
+ IWineD3DDevice_SetTexture(pDevice, D3DVERTEXTEXTURESAMPLER0 + j, This->vertexTextures[j]);
+ }
+ /* FIXME: are sampler states allowed here? */
}
+
} else if (This->blockType == WINED3DSBT_PIXELSTATE) {
for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
@@ -1023,6 +1079,8 @@ static HRESULT WINAPI IWineD3DStateBloc
This->samplerState[i][WINED3DSAMP_DMAPOFFSET ] = 256; /* TODO: Vertex offset in the presampled displacement map */
}
+ /* FIXME: does not account for vertex textures */
+
/* Under DirectX you can have texture stage operations even if no texture is
bound, whereas opengl will only do texture operations when a valid texture is
bound. We emulate this by creating dummy textures and binding them to each
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b859ade..6f1d984 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -48,6 +48,7 @@ #include "wine/list.h"
#define MAX_PALETTES 256
#define MAX_STREAMS 16
#define MAX_TEXTURES 8
+#define MAX_VERTEX_SAMPLERS 4
#define MAX_SAMPLERS 16
#define MAX_ACTIVE_LIGHTS 8
#define MAX_CLIPPLANES D3DMAXUSERCLIPPLANES
@@ -1036,7 +1037,9 @@ typedef struct SAVEDSTATES {
BOOL fvf;
BOOL streamSource[MAX_STREAMS];
BOOL streamFreq[MAX_STREAMS];
+ BOOL dmapTexture;
BOOL textures[MAX_SAMPLERS];
+ BOOL vertexTextures[MAX_VERTEX_SAMPLERS];
BOOL transform[HIGHEST_TRANSFORMSTATE + 1];
BOOL viewport;
BOOL renderState[WINEHIGHEST_RENDER_STATE + 1];
@@ -1132,8 +1135,12 @@ struct IWineD3DStateBlockImpl
DWORD renderState[WINEHIGHEST_RENDER_STATE + 1];
/* Texture */
+ IWineD3DBaseTexture *dmapTexture;
IWineD3DBaseTexture *textures[MAX_SAMPLERS];
+ IWineD3DBaseTexture *vertexTextures[MAX_VERTEX_SAMPLERS];
+ int dmapTextureDimensions;
int textureDimensions[MAX_SAMPLERS];
+ int vertexTextureDimensions[MAX_VERTEX_SAMPLERS];
/* Texture State Stage */
DWORD textureState[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 1cc6409..4b73984 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -1756,6 +1756,7 @@ typedef struct _WineD3D_GL_Info {
UINT max_textures;
UINT max_texture_stages;
UINT max_samplers;
+ UINT max_vertex_samplers;
UINT max_sampler_stages;
UINT max_clipplanes;
UINT max_texture_size;
--
1.4.2.1
More information about the wine-patches
mailing list