Commit 49725ba5 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Get rid of IWineD3DVertexShader.

parent c9ba0949
......@@ -169,7 +169,7 @@ struct d3d10_vertex_shader
const struct ID3D10VertexShaderVtbl *vtbl;
LONG refcount;
IWineD3DVertexShader *wined3d_shader;
IWineD3DBaseShader *wined3d_shader;
struct wined3d_shader_signature output_signature;
};
......
......@@ -162,9 +162,7 @@ static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *if
TRACE("%p increasing refcount to %u\n", This, refcount);
if (refcount == 1)
{
IWineD3DVertexShader_AddRef(This->wined3d_shader);
}
IWineD3DBaseShader_AddRef(This->wined3d_shader);
return refcount;
}
......@@ -177,9 +175,7 @@ static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *i
TRACE("%p decreasing refcount to %u\n", This, refcount);
if (!refcount)
{
IWineD3DVertexShader_Release(This->wined3d_shader);
}
IWineD3DBaseShader_Release(This->wined3d_shader);
return refcount;
}
......
......@@ -471,9 +471,8 @@ DECLARE_INTERFACE_(IDirect3DPixelShader8,IUnknown)
struct IDirect3DVertexShader8Impl {
IDirect3DVertexShader8 IDirect3DVertexShader8_iface;
LONG ref;
IDirect3DVertexDeclaration8 *vertex_declaration;
IWineD3DVertexShader *wineD3DVertexShader;
IDirect3DVertexDeclaration8 *vertex_declaration;
IWineD3DBaseShader *wined3d_shader;
};
HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Impl *device,
......@@ -497,7 +496,7 @@ HRESULT pixelshader_init(IDirect3DPixelShader8Impl *shader, IDirect3DDevice8Impl
D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) DECLSPEC_HIDDEN;
enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN;
void load_local_constants(const DWORD *d3d8_elements, IWineD3DVertexShader *wined3d_vertex_shader) DECLSPEC_HIDDEN;
void load_local_constants(const DWORD *d3d8_elements, IWineD3DBaseShader *wined3d_vertex_shader) DECLSPEC_HIDDEN;
size_t parse_token(const DWORD *pToken) DECLSPEC_HIDDEN;
#endif /* __WINE_D3DX8_PRIVATE_H */
......@@ -2076,7 +2076,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(IDirect3DDevice8 *ifa
hr = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice,
((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration);
if (SUCCEEDED(hr)) hr = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, shader->wineD3DVertexShader);
if (SUCCEEDED(hr))
hr = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, shader->wined3d_shader);
wined3d_mutex_unlock();
TRACE("Returning hr %#x\n", hr);
......@@ -2125,7 +2126,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(IDirect3DDevice8
{
IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
IDirect3DVertexShader8Impl *shader;
IWineD3DVertexShader *cur;
IWineD3DBaseShader *cur;
TRACE("iface %p, shader %#x.\n", iface, pShader);
......@@ -2142,8 +2143,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(IDirect3DDevice8
cur = IWineD3DDevice_GetVertexShader(This->WineD3DDevice);
if (cur)
{
if (cur == shader->wineD3DVertexShader) IDirect3DDevice8_SetVertexShader(iface, 0);
IWineD3DVertexShader_Release(cur);
if (cur == shader->wined3d_shader)
IDirect3DDevice8_SetVertexShader(iface, 0);
IWineD3DBaseShader_Release(cur);
}
wined3d_mutex_unlock();
......@@ -2259,14 +2261,14 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(IDirect3DDevi
return D3DERR_INVALIDCALL;
}
if (!shader->wineD3DVertexShader)
if (!shader->wined3d_shader)
{
wined3d_mutex_unlock();
*pSizeOfData = 0;
return D3D_OK;
}
hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData);
hr = IWineD3DBaseShader_GetFunction(shader->wined3d_shader, pData, pSizeOfData);
wined3d_mutex_unlock();
return hr;
......
......@@ -52,10 +52,10 @@ static ULONG WINAPI d3d8_vertexshader_AddRef(IDirect3DVertexShader8 *iface)
TRACE("%p increasing refcount to %u.\n", iface, refcount);
if (refcount == 1 && shader->wineD3DVertexShader)
if (refcount == 1 && shader->wined3d_shader)
{
wined3d_mutex_lock();
IWineD3DVertexShader_AddRef(shader->wineD3DVertexShader);
IWineD3DBaseShader_AddRef(shader->wined3d_shader);
wined3d_mutex_unlock();
}
......@@ -78,10 +78,10 @@ static ULONG WINAPI d3d8_vertexshader_Release(IDirect3DVertexShader8 *iface)
if (!refcount)
{
if (shader->wineD3DVertexShader)
if (shader->wined3d_shader)
{
wined3d_mutex_lock();
IWineD3DVertexShader_Release(shader->wineD3DVertexShader);
IWineD3DBaseShader_Release(shader->wined3d_shader);
wined3d_mutex_unlock();
}
else
......@@ -177,7 +177,7 @@ HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Im
wined3d_mutex_lock();
hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code, NULL /* output signature */,
shader, &d3d8_vertexshader_wined3d_parent_ops, &shader->wineD3DVertexShader);
shader, &d3d8_vertexshader_wined3d_parent_ops, &shader->wined3d_shader);
wined3d_mutex_unlock();
if (FAILED(hr))
{
......@@ -186,7 +186,7 @@ HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Im
return hr;
}
load_local_constants(declaration, shader->wineD3DVertexShader);
load_local_constants(declaration, shader->wined3d_shader);
}
return D3D_OK;
......
......@@ -199,7 +199,7 @@ size_t parse_token(const DWORD* pToken)
return tokenlen;
}
void load_local_constants(const DWORD *d3d8_elements, IWineD3DVertexShader *wined3d_vertex_shader)
void load_local_constants(const DWORD *d3d8_elements, IWineD3DBaseShader *wined3d_vertex_shader)
{
const DWORD *token = d3d8_elements;
......@@ -224,7 +224,8 @@ void load_local_constants(const DWORD *d3d8_elements, IWineD3DVertexShader *wine
*(const float *)(token + i * 4 + 4));
}
}
hr = IWineD3DVertexShader_SetLocalConstantsF(wined3d_vertex_shader, constant_idx, (const float *)token+1, count);
hr = IWineD3DBaseShader_SetLocalConstantsF(wined3d_vertex_shader,
constant_idx, (const float *)token + 1, count);
if (FAILED(hr)) ERR("Failed setting shader constants\n");
}
......
......@@ -431,13 +431,9 @@ HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration,
typedef struct IDirect3DVertexShader9Impl {
/* IUnknown fields */
const IDirect3DVertexShader9Vtbl *lpVtbl;
LONG ref;
/* IDirect3DVertexShader9 fields */
IWineD3DVertexShader *wineD3DVertexShader;
/* Parent reference */
LPDIRECT3DDEVICE9EX parentDevice;
LONG ref;
IWineD3DBaseShader *wined3d_shader;
IDirect3DDevice9Ex *parentDevice;
} IDirect3DVertexShader9Impl;
HRESULT vertexshader_init(IDirect3DVertexShader9Impl *shader,
......
......@@ -2233,7 +2233,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(IDirect3DDevice9Ex *i
wined3d_mutex_lock();
hr = IWineD3DDevice_SetVertexShader(((IDirect3DDevice9Impl *)iface)->WineD3DDevice,
shader ? ((IDirect3DVertexShader9Impl *)shader)->wineD3DVertexShader : NULL);
shader ? ((IDirect3DVertexShader9Impl *)shader)->wined3d_shader : NULL);
wined3d_mutex_unlock();
return hr;
......@@ -2242,7 +2242,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(IDirect3DDevice9Ex *i
static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(IDirect3DDevice9Ex *iface,
IDirect3DVertexShader9 **shader)
{
IWineD3DVertexShader *wined3d_shader;
IWineD3DBaseShader *wined3d_shader;
TRACE("iface %p, shader %p.\n", iface, shader);
......@@ -2250,9 +2250,9 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(IDirect3DDevice9Ex *i
wined3d_shader = IWineD3DDevice_GetVertexShader(((IDirect3DDevice9Impl *)iface)->WineD3DDevice);
if (wined3d_shader)
{
*shader = IWineD3DVertexShader_GetParent(wined3d_shader);
*shader = IWineD3DBaseShader_GetParent(wined3d_shader);
IDirect3DVertexShader9_AddRef(*shader);
IWineD3DVertexShader_Release(wined3d_shader);
IWineD3DBaseShader_Release(wined3d_shader);
}
else
{
......
......@@ -51,7 +51,7 @@ static ULONG WINAPI d3d9_vertexshader_AddRef(IDirect3DVertexShader9 *iface)
{
IDirect3DDevice9Ex_AddRef(shader->parentDevice);
wined3d_mutex_lock();
IWineD3DVertexShader_AddRef(shader->wineD3DVertexShader);
IWineD3DBaseShader_AddRef(shader->wined3d_shader);
wined3d_mutex_unlock();
}
......@@ -70,7 +70,7 @@ static ULONG WINAPI d3d9_vertexshader_Release(IDirect3DVertexShader9 *iface)
IDirect3DDevice9Ex *device = shader->parentDevice;
wined3d_mutex_lock();
IWineD3DVertexShader_Release(shader->wineD3DVertexShader);
IWineD3DBaseShader_Release(shader->wined3d_shader);
wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */
......@@ -100,7 +100,7 @@ static HRESULT WINAPI d3d9_vertexshader_GetFunction(IDirect3DVertexShader9 *ifac
TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
wined3d_mutex_lock();
hr = IWineD3DVertexShader_GetFunction(((IDirect3DVertexShader9Impl *)iface)->wineD3DVertexShader, data, data_size);
hr = IWineD3DBaseShader_GetFunction(((IDirect3DVertexShader9Impl *)iface)->wined3d_shader, data, data_size);
wined3d_mutex_unlock();
return hr;
......@@ -136,7 +136,7 @@ HRESULT vertexshader_init(IDirect3DVertexShader9Impl *shader, IDirect3DDevice9Im
wined3d_mutex_lock();
hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code, NULL,
shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wineD3DVertexShader);
shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader);
wined3d_mutex_unlock();
if (FAILED(hr))
{
......
......@@ -1513,7 +1513,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3D
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface,
const DWORD *pFunction, const struct wined3d_shader_signature *output_signature,
void *parent, const struct wined3d_parent_ops *parent_ops,
IWineD3DVertexShader **ppVertexShader)
IWineD3DBaseShader **shader)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexShaderImpl *object;
......@@ -1538,7 +1538,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac
}
TRACE("Created vertex shader %p.\n", object);
*ppVertexShader = (IWineD3DVertexShader *)object;
*shader = (IWineD3DBaseShader *)object;
return WINED3D_OK;
}
......@@ -3339,43 +3339,51 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice *if
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader *pShader)
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DBaseShader *shader)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexShader *oldShader = (IWineD3DVertexShader *)This->updateStateBlock->state.vertex_shader;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
IWineD3DBaseShader *prev = (IWineD3DBaseShader *)device->updateStateBlock->state.vertex_shader;
This->updateStateBlock->state.vertex_shader = (IWineD3DVertexShaderImpl *)pShader;
This->updateStateBlock->changed.vertexShader = TRUE;
device->updateStateBlock->state.vertex_shader = (IWineD3DVertexShaderImpl *)shader;
device->updateStateBlock->changed.vertexShader = TRUE;
if (This->isRecordingState) {
if(pShader) IWineD3DVertexShader_AddRef(pShader);
if(oldShader) IWineD3DVertexShader_Release(oldShader);
TRACE("Recording... not performing anything\n");
if (device->isRecordingState)
{
if (shader)
IWineD3DBaseShader_AddRef(shader);
if (prev)
IWineD3DBaseShader_Release(prev);
TRACE("Recording... not performing anything.\n");
return WINED3D_OK;
} else if(oldShader == pShader) {
}
else if(prev == shader)
{
/* Checked here to allow proper stateblock recording */
TRACE("App is setting the old shader over, nothing to do\n");
TRACE("App is setting the old shader over, nothing to do.\n");
return WINED3D_OK;
}
TRACE("(%p) : setting pShader(%p)\n", This, pShader);
if(pShader) IWineD3DVertexShader_AddRef(pShader);
if(oldShader) IWineD3DVertexShader_Release(oldShader);
TRACE("(%p) : setting shader(%p)\n", device, shader);
if (shader)
IWineD3DBaseShader_AddRef(shader);
if (prev)
IWineD3DBaseShader_Release(prev);
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
IWineD3DDeviceImpl_MarkStateDirty(device, STATE_VSHADER);
return WINED3D_OK;
}
static IWineD3DVertexShader * WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface)
static IWineD3DBaseShader * WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface)
{
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexShader *shader;
IWineD3DBaseShader *shader;
TRACE("iface %p.\n", iface);
shader = (IWineD3DVertexShader *)device->stateBlock->state.vertex_shader;
if (shader) IWineD3DVertexShader_AddRef(shader);
shader = (IWineD3DBaseShader *)device->stateBlock->state.vertex_shader;
if (shader)
IWineD3DBaseShader_AddRef(shader);
TRACE("Returning %p.\n", shader);
return shader;
......
......@@ -1644,12 +1644,11 @@ static HRESULT shader_set_function(IWineD3DBaseShaderImpl *shader, const DWORD *
return WINED3D_OK;
}
static HRESULT STDMETHODCALLTYPE vertexshader_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, void **object)
static HRESULT STDMETHODCALLTYPE vertexshader_QueryInterface(IWineD3DBaseShader *iface, REFIID riid, void **object)
{
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
if (IsEqualGUID(riid, &IID_IWineD3DVertexShader)
|| IsEqualGUID(riid, &IID_IWineD3DBaseShader)
if (IsEqualGUID(riid, &IID_IWineD3DBaseShader)
|| IsEqualGUID(riid, &IID_IWineD3DBase)
|| IsEqualGUID(riid, &IID_IUnknown))
{
......@@ -1664,7 +1663,7 @@ static HRESULT STDMETHODCALLTYPE vertexshader_QueryInterface(IWineD3DVertexShade
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE vertexshader_AddRef(IWineD3DVertexShader *iface)
static ULONG STDMETHODCALLTYPE vertexshader_AddRef(IWineD3DBaseShader *iface)
{
IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
ULONG refcount = InterlockedIncrement(&shader->baseShader.ref);
......@@ -1675,7 +1674,7 @@ static ULONG STDMETHODCALLTYPE vertexshader_AddRef(IWineD3DVertexShader *iface)
}
/* Do not call while under the GL lock. */
static ULONG STDMETHODCALLTYPE vertexshader_Release(IWineD3DVertexShader *iface)
static ULONG STDMETHODCALLTYPE vertexshader_Release(IWineD3DBaseShader *iface)
{
IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
ULONG refcount = InterlockedDecrement(&shader->baseShader.ref);
......@@ -1692,21 +1691,21 @@ static ULONG STDMETHODCALLTYPE vertexshader_Release(IWineD3DVertexShader *iface)
return refcount;
}
static void * STDMETHODCALLTYPE vertexshader_GetParent(IWineD3DVertexShader *iface)
static void * STDMETHODCALLTYPE vertexshader_GetParent(IWineD3DBaseShader *iface)
{
TRACE("iface %p.\n", iface);
return ((IWineD3DBaseShaderImpl *)iface)->baseShader.parent;
}
static HRESULT STDMETHODCALLTYPE vertexshader_GetFunction(IWineD3DVertexShader *iface, void *data, UINT *data_size)
static HRESULT STDMETHODCALLTYPE vertexshader_GetFunction(IWineD3DBaseShader *iface, void *data, UINT *data_size)
{
TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
}
static HRESULT STDMETHODCALLTYPE vertexshader_SetLocalConstantsF(IWineD3DVertexShader *iface,
static HRESULT STDMETHODCALLTYPE vertexshader_SetLocalConstantsF(IWineD3DBaseShader *iface,
UINT start_idx, const float *src_data, UINT count)
{
TRACE("iface %p, start_idx %u, src_data %p, count %u.\n", iface, start_idx, src_data, count);
......@@ -1715,7 +1714,7 @@ static HRESULT STDMETHODCALLTYPE vertexshader_SetLocalConstantsF(IWineD3DVertexS
start_idx, src_data, count);
}
static const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
static const IWineD3DBaseShaderVtbl IWineD3DVertexShader_Vtbl =
{
/* IUnknown methods */
vertexshader_QueryInterface,
......
......@@ -499,7 +499,7 @@ ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
if (stateblock->state.index_buffer)
wined3d_buffer_decref(stateblock->state.index_buffer);
if (stateblock->state.vertex_shader)
IWineD3DVertexShader_Release((IWineD3DVertexShader *)stateblock->state.vertex_shader);
IWineD3DBaseShader_Release((IWineD3DBaseShader *)stateblock->state.vertex_shader);
if (stateblock->state.pixel_shader)
IWineD3DPixelShader_Release((IWineD3DPixelShader *)stateblock->state.pixel_shader);
......@@ -599,9 +599,9 @@ HRESULT CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
stateblock->state.vertex_shader, src_state->vertex_shader);
if (src_state->vertex_shader)
IWineD3DVertexShader_AddRef((IWineD3DVertexShader *)src_state->vertex_shader);
IWineD3DBaseShader_AddRef((IWineD3DBaseShader *)src_state->vertex_shader);
if (stateblock->state.vertex_shader)
IWineD3DVertexShader_Release((IWineD3DVertexShader *)stateblock->state.vertex_shader);
IWineD3DBaseShader_Release((IWineD3DBaseShader *)stateblock->state.vertex_shader);
stateblock->state.vertex_shader = src_state->vertex_shader;
}
......@@ -901,7 +901,7 @@ HRESULT CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblo
TRACE("Blocktype: %#x.\n", stateblock->blockType);
if (stateblock->changed.vertexShader)
IWineD3DDevice_SetVertexShader(device, (IWineD3DVertexShader *)stateblock->state.vertex_shader);
IWineD3DDevice_SetVertexShader(device, (IWineD3DBaseShader *)stateblock->state.vertex_shader);
/* Vertex Shader Constants. */
for (i = 0; i < stateblock->num_contained_vs_consts_f; ++i)
......
......@@ -2815,11 +2815,9 @@ static inline BOOL shader_constant_is_local(IWineD3DBaseShaderImpl* This, DWORD
/*****************************************************************************
* IDirect3DVertexShader implementation structures
*/
typedef struct IWineD3DVertexShaderImpl {
/* IUnknown parts */
const IWineD3DVertexShaderVtbl *lpVtbl;
/* IWineD3DBaseShader */
typedef struct IWineD3DVertexShaderImpl
{
const IWineD3DBaseShaderVtbl *lpVtbl;
IWineD3DBaseShaderClass baseShader;
/* Vertex shader attributes. */
......
......@@ -2405,15 +2405,6 @@ interface IWineD3DBaseShader : IWineD3DBase
[
object,
local,
uuid(7f7a2b60-6f30-11d9-c687-00046142c14f)
]
interface IWineD3DVertexShader : IWineD3DBaseShader
{
}
[
object,
local,
uuid(8276c113-388b-49d1-ad8b-c9dd8bcbabcd)
]
interface IWineD3DGeometryShader : IWineD3DBaseShader
......@@ -2556,7 +2547,7 @@ interface IWineD3DDevice : IUnknown
[in] const struct wined3d_shader_signature *output_signature,
[in] void *parent,
[in] const struct wined3d_parent_ops *parent_ops,
[out] IWineD3DVertexShader **shader
[out] IWineD3DBaseShader **shader
);
HRESULT CreateGeometryShader(
[in] const DWORD *byte_code,
......@@ -2857,9 +2848,9 @@ interface IWineD3DDevice : IUnknown
[out] struct wined3d_vertex_declaration **declaration
);
HRESULT SetVertexShader(
[in] IWineD3DVertexShader *shader
[in] IWineD3DBaseShader *shader
);
IWineD3DVertexShader *GetVertexShader(
IWineD3DBaseShader *GetVertexShader(
);
HRESULT SetVertexShaderConstantB(
[in] UINT start_register,
......
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