Commit 79145e21 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Add support for shadow samplers.

parent 29b13f75
...@@ -299,6 +299,7 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac ...@@ -299,6 +299,7 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac
gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0; gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1; gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = 0; gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = 0;
gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
IWineD3DBaseTexture_SetDirty(iface, TRUE); IWineD3DBaseTexture_SetDirty(iface, TRUE);
isNewTexture = TRUE; isNewTexture = TRUE;
...@@ -516,4 +517,22 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface, ...@@ -516,4 +517,22 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface,
} }
gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso; gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso;
} }
if (!(This->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW)
!= !gl_tex->states[WINED3DTEXSTA_SHADOW])
{
if (This->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW)
{
glTexParameteri(textureDimensions, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB)");
gl_tex->states[WINED3DTEXSTA_SHADOW] = TRUE;
}
else
{
glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE)");
gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
}
}
} }
...@@ -3956,6 +3956,11 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt ...@@ -3956,6 +3956,11 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n"); TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
return WINED3DERR_NOTAVAILABLE; return WINED3DERR_NOTAVAILABLE;
} }
if ((format_desc->Flags & WINED3DFMT_FLAG_SHADOW) && !gl_info->supported[ARB_SHADOW])
{
TRACE_(d3d_caps)("[FAILED] - No shadow sampler support.\n");
return WINED3DERR_NOTAVAILABLE;
}
UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
} }
break; break;
......
...@@ -2024,6 +2024,9 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, ...@@ -2024,6 +2024,9 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader,
} }
args->color_fixup[i] = texture->resource.format_desc->color_fixup; args->color_fixup[i] = texture->resource.format_desc->color_fixup;
if (texture->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW)
args->shadow |= 1 << i;
/* Flag samplers that need NP2 texcoord fixup. */ /* Flag samplers that need NP2 texcoord fixup. */
if (!texture->baseTexture.pow2Matrix_identity) if (!texture->baseTexture.pow2Matrix_identity)
{ {
......
...@@ -4070,6 +4070,7 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl ...@@ -4070,6 +4070,7 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl
GLuint texture, GLsizei w, GLsizei h, GLenum target) GLuint texture, GLsizei w, GLsizei h, GLenum target)
{ {
IWineD3DDeviceImpl *device = This->resource.device; IWineD3DDeviceImpl *device = This->resource.device;
GLint compare_mode = GL_NONE;
struct blt_info info; struct blt_info info;
GLint old_binding = 0; GLint old_binding = 0;
...@@ -4090,6 +4091,11 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl ...@@ -4090,6 +4091,11 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
glGetIntegerv(info.binding, &old_binding); glGetIntegerv(info.binding, &old_binding);
glBindTexture(info.bind_target, texture); glBindTexture(info.bind_target, texture);
if (gl_info->supported[ARB_SHADOW])
{
glGetTexParameteriv(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, &compare_mode);
if (compare_mode != GL_NONE) glTexParameteri(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
}
device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device, device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device,
info.tex_type, &This->ds_current_size); info.tex_type, &This->ds_current_size);
...@@ -4105,6 +4111,7 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl ...@@ -4105,6 +4111,7 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl
glVertex2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
glEnd(); glEnd();
if (compare_mode != GL_NONE) glTexParameteri(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, compare_mode);
glBindTexture(info.bind_target, old_binding); glBindTexture(info.bind_target, old_binding);
glPopAttrib(); glPopAttrib();
......
...@@ -775,55 +775,60 @@ static const struct wined3d_format_texture_info format_texture_info[] = ...@@ -775,55 +775,60 @@ static const struct wined3d_format_texture_info format_texture_info[] =
/* Depth stencil formats */ /* Depth stencil formats */
{WINED3DFMT_D16_LOCKABLE, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, {WINED3DFMT_D16_LOCKABLE, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0,
WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_D32_UNORM, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT32_ARB, 0, {WINED3DFMT_D32_UNORM, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT32_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0,
WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4,
WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
EXT_PACKED_DEPTH_STENCIL, &convert_s1_uint_d15_unorm}, EXT_PACKED_DEPTH_STENCIL, &convert_s1_uint_d15_unorm},
{WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4,
WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
ARB_FRAMEBUFFER_OBJECT, &convert_s1_uint_d15_unorm}, ARB_FRAMEBUFFER_OBJECT, &convert_s1_uint_d15_unorm},
{WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
| WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0,
WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
| WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
EXT_PACKED_DEPTH_STENCIL, NULL}, EXT_PACKED_DEPTH_STENCIL, NULL},
{WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0,
WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
| WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
ARB_FRAMEBUFFER_OBJECT, NULL}, ARB_FRAMEBUFFER_OBJECT, NULL},
{WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, {WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
| WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4,
WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
EXT_PACKED_DEPTH_STENCIL, &convert_s4x4_uint_d24_unorm}, EXT_PACKED_DEPTH_STENCIL, &convert_s4x4_uint_d24_unorm},
{WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4,
WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
ARB_FRAMEBUFFER_OBJECT, &convert_s4x4_uint_d24_unorm}, ARB_FRAMEBUFFER_OBJECT, &convert_s4x4_uint_d24_unorm},
{WINED3DFMT_D16_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, {WINED3DFMT_D16_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0,
WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
| WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_TEXTURE, NULL}, ARB_DEPTH_TEXTURE, NULL},
{WINED3DFMT_L16_UNORM, GL_LUMINANCE16, GL_LUMINANCE16, 0, {WINED3DFMT_L16_UNORM, GL_LUMINANCE16, GL_LUMINANCE16, 0,
GL_LUMINANCE, GL_UNSIGNED_SHORT, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, 0,
...@@ -831,11 +836,11 @@ static const struct wined3d_format_texture_info format_texture_info[] = ...@@ -831,11 +836,11 @@ static const struct wined3d_format_texture_info format_texture_info[] =
WINED3D_GL_EXT_NONE, NULL}, WINED3D_GL_EXT_NONE, NULL},
{WINED3DFMT_D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, 0, {WINED3DFMT_D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0,
WINED3DFMT_FLAG_DEPTH, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_BUFFER_FLOAT, NULL}, ARB_DEPTH_BUFFER_FLOAT, NULL},
{WINED3DFMT_S8_UINT_D24_FLOAT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, 0, {WINED3DFMT_S8_UINT_D24_FLOAT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, 0,
GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8,
WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
ARB_DEPTH_BUFFER_FLOAT, &convert_s8_uint_d24_float}, ARB_DEPTH_BUFFER_FLOAT, &convert_s8_uint_d24_float},
/* Vendor-specific formats */ /* Vendor-specific formats */
{WINED3DFMT_ATI2N, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0, {WINED3DFMT_ATI2N, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0,
......
...@@ -687,6 +687,7 @@ struct ps_compile_args { ...@@ -687,6 +687,7 @@ struct ps_compile_args {
/* Bitmap for NP2 texcoord fixups (16 samplers max currently). /* Bitmap for NP2 texcoord fixups (16 samplers max currently).
D3D9 has a limit of 16 samplers and the fixup is superfluous D3D9 has a limit of 16 samplers and the fixup is superfluous
in D3D10 (unconditional NP2 support mandatory). */ in D3D10 (unconditional NP2 support mandatory). */
WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */
}; };
enum fog_src_type { enum fog_src_type {
...@@ -1821,7 +1822,8 @@ typedef enum winetexturestates { ...@@ -1821,7 +1822,8 @@ typedef enum winetexturestates {
WINED3DTEXSTA_MAXMIPLEVEL = 7, WINED3DTEXSTA_MAXMIPLEVEL = 7,
WINED3DTEXSTA_MAXANISOTROPY = 8, WINED3DTEXSTA_MAXANISOTROPY = 8,
WINED3DTEXSTA_SRGBTEXTURE = 9, WINED3DTEXSTA_SRGBTEXTURE = 9,
MAX_WINETEXTURESTATES = 10, WINED3DTEXSTA_SHADOW = 10,
MAX_WINETEXTURESTATES = 11,
} winetexturestates; } winetexturestates;
enum WINED3DSRGB enum WINED3DSRGB
...@@ -2979,6 +2981,7 @@ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN; ...@@ -2979,6 +2981,7 @@ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN;
#define WINED3DFMT_FLAG_SRGB_READ 0x00000800 #define WINED3DFMT_FLAG_SRGB_READ 0x00000800
#define WINED3DFMT_FLAG_SRGB_WRITE 0x00001000 #define WINED3DFMT_FLAG_SRGB_WRITE 0x00001000
#define WINED3DFMT_FLAG_VTF 0x00002000 #define WINED3DFMT_FLAG_VTF 0x00002000
#define WINED3DFMT_FLAG_SHADOW 0x00004000
struct wined3d_format_desc struct wined3d_format_desc
{ {
......
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