Commit e4faae21 by Jamie Madill Committed by Commit Bot

Rename state change notification messages.

This makes the style use CamelCase instead of ALL_CAPS. It also cleans up some of the naming. It also changes some uses of the messages in some of the objects to hopefully be more consistent. See the comments added to the enum SubjectMessage in Observer.h for more details. Bug: angleproject:3427 Change-Id: I6dff4f6d335ecf1a27e48df65743b1490bd3025a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1600411 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent fdbece20
......@@ -94,7 +94,7 @@ angle::Result Buffer::bufferData(Context *context,
mState.mSize = size;
// Notify when storage changes.
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
return angle::Result::Continue;
}
......@@ -111,7 +111,7 @@ angle::Result Buffer::bufferSubData(const Context *context,
static_cast<unsigned int>(size));
// Notify when data changes.
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
onStateChange(context, angle::SubjectMessage::ContentsChanged);
return angle::Result::Continue;
}
......@@ -129,7 +129,7 @@ angle::Result Buffer::copyBufferSubData(const Context *context,
static_cast<unsigned int>(size));
// Notify when data changes.
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
onStateChange(context, angle::SubjectMessage::ContentsChanged);
return angle::Result::Continue;
}
......@@ -151,7 +151,7 @@ angle::Result Buffer::map(const Context *context, GLenum access)
mIndexRangeCache.clear();
// Notify when state changes.
onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
onStateChange(context, angle::SubjectMessage::SubjectMapped);
return angle::Result::Continue;
}
......@@ -185,7 +185,7 @@ angle::Result Buffer::mapRange(const Context *context,
}
// Notify when state changes.
onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
onStateChange(context, angle::SubjectMessage::SubjectMapped);
return angle::Result::Continue;
}
......@@ -205,7 +205,7 @@ angle::Result Buffer::unmap(const Context *context, GLboolean *result)
mState.mAccessFlags = 0;
// Notify when data changes.
onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
onStateChange(context, angle::SubjectMessage::SubjectUnmapped);
return angle::Result::Continue;
}
......@@ -215,7 +215,7 @@ void Buffer::onTransformFeedback(const Context *context)
mIndexRangeCache.clear();
// Notify when data changes.
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
onStateChange(context, angle::SubjectMessage::ContentsChanged);
}
void Buffer::onPixelPack(const Context *context)
......@@ -223,7 +223,7 @@ void Buffer::onPixelPack(const Context *context)
mIndexRangeCache.clear();
// Notify when data changes.
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
onStateChange(context, angle::SubjectMessage::ContentsChanged);
}
angle::Result Buffer::getIndexRange(const gl::Context *context,
......@@ -266,7 +266,7 @@ void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed
ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0);
mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1;
onStateChange(context, angle::SubjectMessage::BINDING_CHANGED);
onStateChange(context, angle::SubjectMessage::BindingChanged);
}
else
{
......@@ -280,6 +280,7 @@ void Buffer::onSubjectStateChange(const gl::Context *context,
{
// Pass it along!
ASSERT(index == kImplementationSubjectIndex);
onStateChange(context, message);
ASSERT(message == angle::SubjectMessage::SubjectChanged);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
} // namespace gl
......@@ -8121,13 +8121,13 @@ void Context::onSubjectStateChange(const Context *context,
case kVertexArraySubjectIndex:
switch (message)
{
case angle::SubjectMessage::CONTENTS_CHANGED:
case angle::SubjectMessage::ContentsChanged:
mState.setObjectDirty(GL_VERTEX_ARRAY);
mStateCache.onVertexArrayBufferContentsChange(this);
break;
case angle::SubjectMessage::RESOURCE_MAPPED:
case angle::SubjectMessage::RESOURCE_UNMAPPED:
case angle::SubjectMessage::BINDING_CHANGED:
case angle::SubjectMessage::SubjectMapped:
case angle::SubjectMessage::SubjectUnmapped:
case angle::SubjectMessage::BindingChanged:
mStateCache.onVertexArrayBufferStateChange(this);
break;
default:
......@@ -8136,14 +8136,14 @@ void Context::onSubjectStateChange(const Context *context,
break;
case kReadFramebufferSubjectIndex:
if (message == angle::SubjectMessage::STORAGE_CHANGED)
if (message == angle::SubjectMessage::DirtyBitsFlagged)
{
mState.setObjectDirty(GL_READ_FRAMEBUFFER);
}
break;
case kDrawFramebufferSubjectIndex:
if (message == angle::SubjectMessage::STORAGE_CHANGED)
if (message == angle::SubjectMessage::DirtyBitsFlagged)
{
mState.setDrawFramebufferDirty();
}
......
......@@ -955,7 +955,7 @@ void Framebuffer::invalidateCompletenessCache(const Context *context)
if (mState.mId != 0)
{
mCachedStatus.reset();
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
}
......@@ -1853,16 +1853,16 @@ void Framebuffer::onSubjectStateChange(const Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message)
{
if (message != angle::SubjectMessage::STORAGE_CHANGED)
if (message != angle::SubjectMessage::SubjectChanged)
{
// This can be triggered by the GL back-end TextureGL class.
ASSERT(message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
return;
}
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
mDirtyBits.set(index);
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
invalidateCompletenessCache(context);
......
......@@ -31,14 +31,31 @@ bool IsInContainer(const HaystackT &haystack, const NeedleT &needle)
using SubjectIndex = size_t;
// Messages are used to distinguish different Subject events that get sent to a single Observer.
// It could be possible to improve the handling by using different callback functions instead
// of a single handler function. But in some cases we want to share a single binding between
// Observer and Subject and handle different types of events.
enum class SubjectMessage
{
CONTENTS_CHANGED,
STORAGE_CHANGED,
BINDING_CHANGED,
DEPENDENT_DIRTY_BITS,
RESOURCE_MAPPED,
RESOURCE_UNMAPPED,
// Used by the VertexArray class to notify a binding count change might need to update the
// validation cache.
BindingChanged,
// Only the contents (pixels, bytes, etc) changed in this Subject. Rather than the storage for
// the subject.
ContentsChanged,
// Used by Samplers, Textures and Framebuffers to indicate to the Observer (Context) that it
// will need to call syncState.
DirtyBitsFlagged,
// Generic state change message. Used in multiple places.
SubjectChanged,
// Special events passed from Buffers, through VertexArrays into the Context to indicate a bound
// Buffer is now mapped.
SubjectMapped,
SubjectUnmapped,
};
// The observing class inherits from this interface class.
......
......@@ -36,7 +36,7 @@ TEST(ObserverTest, BasicUsage)
binding.bind(&subject);
ASSERT_FALSE(observer.wasNotified);
subject.onStateChange(nullptr, SubjectMessage::STORAGE_CHANGED);
subject.onStateChange(nullptr, SubjectMessage::SubjectChanged);
ASSERT_TRUE(observer.wasNotified);
}
......
......@@ -102,7 +102,7 @@ angle::Result Renderbuffer::setStorage(const Context *context,
mState.update(static_cast<GLsizei>(width), static_cast<GLsizei>(height), Format(internalformat),
0, InitState::MayNeedInit);
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
return angle::Result::Continue;
}
......@@ -119,7 +119,7 @@ angle::Result Renderbuffer::setStorageMultisample(const Context *context,
mState.update(static_cast<GLsizei>(width), static_cast<GLsizei>(height), Format(internalformat),
static_cast<GLsizei>(samples), InitState::MayNeedInit);
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
return angle::Result::Continue;
}
......@@ -133,7 +133,7 @@ angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl
mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
Format(image->getFormat()), 0, image->sourceInitState());
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
return angle::Result::Continue;
}
......
......@@ -39,7 +39,7 @@ const std::string &Sampler::getLabel() const
void Sampler::setMinFilter(const Context *context, GLenum minFilter)
{
mState.setMinFilter(minFilter);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getMinFilter() const
......@@ -50,7 +50,7 @@ GLenum Sampler::getMinFilter() const
void Sampler::setMagFilter(const Context *context, GLenum magFilter)
{
mState.setMagFilter(magFilter);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getMagFilter() const
......@@ -61,7 +61,7 @@ GLenum Sampler::getMagFilter() const
void Sampler::setWrapS(const Context *context, GLenum wrapS)
{
mState.setWrapS(wrapS);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getWrapS() const
......@@ -72,7 +72,7 @@ GLenum Sampler::getWrapS() const
void Sampler::setWrapT(const Context *context, GLenum wrapT)
{
mState.setWrapT(wrapT);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getWrapT() const
......@@ -83,7 +83,7 @@ GLenum Sampler::getWrapT() const
void Sampler::setWrapR(const Context *context, GLenum wrapR)
{
mState.setWrapR(wrapR);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getWrapR() const
......@@ -94,7 +94,7 @@ GLenum Sampler::getWrapR() const
void Sampler::setMaxAnisotropy(const Context *context, float maxAnisotropy)
{
mState.setMaxAnisotropy(maxAnisotropy);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
float Sampler::getMaxAnisotropy() const
......@@ -105,7 +105,7 @@ float Sampler::getMaxAnisotropy() const
void Sampler::setMinLod(const Context *context, GLfloat minLod)
{
mState.setMinLod(minLod);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLfloat Sampler::getMinLod() const
......@@ -116,7 +116,7 @@ GLfloat Sampler::getMinLod() const
void Sampler::setMaxLod(const Context *context, GLfloat maxLod)
{
mState.setMaxLod(maxLod);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLfloat Sampler::getMaxLod() const
......@@ -127,7 +127,7 @@ GLfloat Sampler::getMaxLod() const
void Sampler::setCompareMode(const Context *context, GLenum compareMode)
{
mState.setCompareMode(compareMode);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getCompareMode() const
......@@ -138,7 +138,7 @@ GLenum Sampler::getCompareMode() const
void Sampler::setCompareFunc(const Context *context, GLenum compareFunc)
{
mState.setCompareFunc(compareFunc);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getCompareFunc() const
......@@ -149,7 +149,7 @@ GLenum Sampler::getCompareFunc() const
void Sampler::setSRGBDecode(const Context *context, GLenum sRGBDecode)
{
mState.setSRGBDecode(sRGBDecode);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Sampler::getSRGBDecode() const
......@@ -160,7 +160,7 @@ GLenum Sampler::getSRGBDecode() const
void Sampler::setBorderColor(const Context *context, const ColorGeneric &color)
{
mState.setBorderColor(color);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
const ColorGeneric &Sampler::getBorderColor() const
......
......@@ -136,7 +136,7 @@ void Surface::postSwap(const gl::Context *context)
if (mRobustResourceInitialization && mSwapBehavior != EGL_BUFFER_PRESERVED)
{
mInitState = gl::InitState::MayNeedInit;
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
}
......
......@@ -995,7 +995,7 @@ void Texture::signalDirtyStorage(const Context *context, InitState initState)
mState.mInitState = initState;
invalidateCompletenessCache();
mState.mCachedSamplerFormatValid = false;
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
void Texture::signalDirtyState(const Context *context, size_t dirtyBit)
......@@ -1003,7 +1003,7 @@ void Texture::signalDirtyState(const Context *context, size_t dirtyBit)
mDirtyBits.set(dirtyBit);
invalidateCompletenessCache();
mState.mCachedSamplerFormatValid = false;
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
angle::Result Texture::setImage(Context *context,
......@@ -1801,10 +1801,8 @@ void Texture::onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message)
{
if (message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS)
{
mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
signalDirtyState(context, DIRTY_BIT_IMPLEMENTATION);
}
ASSERT(message == angle::SubjectMessage::SubjectChanged);
mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
signalDirtyState(context, DIRTY_BIT_IMPLEMENTATION);
}
} // namespace gl
......@@ -172,7 +172,7 @@ const std::string &VertexArray::getLabel() const
bool VertexArray::detachBuffer(const Context *context, GLuint bufferName)
{
bool isBound = context->isCurrentVertexArray(this);
bool isBound = context->isCurrentVertexArray(this);
bool anyBufferDetached = false;
for (size_t bindingIndex = 0; bindingIndex < gl::MAX_VERTEX_ATTRIB_BINDINGS; ++bindingIndex)
{
......@@ -558,11 +558,11 @@ void VertexArray::onSubjectStateChange(const gl::Context *context,
{
switch (message)
{
case angle::SubjectMessage::CONTENTS_CHANGED:
case angle::SubjectMessage::ContentsChanged:
setDependentDirtyBit(context, true, index);
break;
case angle::SubjectMessage::STORAGE_CHANGED:
case angle::SubjectMessage::SubjectChanged:
if (!IsElementArrayBufferSubjectIndex(index))
{
updateCachedBufferBindingSize(context, &mState.mVertexBindings[index]);
......@@ -570,7 +570,7 @@ void VertexArray::onSubjectStateChange(const gl::Context *context,
setDependentDirtyBit(context, false, index);
break;
case angle::SubjectMessage::BINDING_CHANGED:
case angle::SubjectMessage::BindingChanged:
if (!IsElementArrayBufferSubjectIndex(index))
{
const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
......@@ -578,22 +578,22 @@ void VertexArray::onSubjectStateChange(const gl::Context *context,
}
break;
case angle::SubjectMessage::RESOURCE_MAPPED:
case angle::SubjectMessage::SubjectMapped:
if (!IsElementArrayBufferSubjectIndex(index))
{
updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
}
onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
onStateChange(context, angle::SubjectMessage::SubjectMapped);
break;
case angle::SubjectMessage::RESOURCE_UNMAPPED:
case angle::SubjectMessage::SubjectUnmapped:
setDependentDirtyBit(context, true, index);
if (!IsElementArrayBufferSubjectIndex(index))
{
updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
}
onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
onStateChange(context, angle::SubjectMessage::SubjectUnmapped);
break;
default:
......@@ -609,7 +609,7 @@ void VertexArray::setDependentDirtyBit(const gl::Context *context,
DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
mDirtyBits.set(dirtyBit);
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
onStateChange(context, angle::SubjectMessage::ContentsChanged);
}
bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
......
......@@ -494,7 +494,7 @@ void SetSamplerParameterBase(Context *context,
break;
}
sampler->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
sampler->onStateChange(context, angle::SubjectMessage::ContentsChanged);
}
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
......
......@@ -82,7 +82,7 @@ angle::Result EGLImageD3D::copyToLocalRendertarget(const gl::Context *context)
// Invalidate FBOs with this Image attached. Only currently applies to D3D11.
for (egl::ImageSibling *target : mState.targets)
{
target->onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
target->onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
return mRenderer->createRenderTargetCopy(context, curRenderTarget, &mRenderTarget);
......
......@@ -952,13 +952,13 @@ bool Buffer11::supportsDirectBinding() const
void Buffer11::initializeStaticData(const gl::Context *context)
{
BufferD3D::initializeStaticData(context);
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
void Buffer11::invalidateStaticData(const gl::Context *context)
{
BufferD3D::invalidateStaticData(context);
onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source)
......@@ -1151,7 +1151,7 @@ angle::Result Buffer11::NativeStorage::resize(const gl::Context *context,
// Notify that the storage has changed.
if (mOnStorageChanged)
{
mOnStorageChanged->onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
mOnStorageChanged->onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
return angle::Result::Continue;
......
......@@ -1306,7 +1306,7 @@ angle::Result TextureGL::setBaseLevel(const gl::Context *context, GLuint baseLev
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_BASE_LEVEL);
// Signal to the GL layer that the Impl has dirty bits.
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_BASE_LEVEL, baseLevel);
......@@ -1325,7 +1325,7 @@ void TextureGL::setMinFilter(const gl::Context *context, GLenum filter)
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MIN_FILTER);
// Signal to the GL layer that the Impl has dirty bits.
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MIN_FILTER, filter);
......@@ -1342,7 +1342,7 @@ void TextureGL::setMagFilter(const gl::Context *context, GLenum filter)
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAG_FILTER);
// Signal to the GL layer that the Impl has dirty bits.
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MAG_FILTER, filter);
......@@ -1366,7 +1366,7 @@ void TextureGL::setSwizzle(const gl::Context *context, GLint swizzle[4])
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
// Signal to the GL layer that the Impl has dirty bits.
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteriv(ToGLenum(getType()), GL_TEXTURE_SWIZZLE_RGBA, swizzle);
......@@ -1508,7 +1508,7 @@ void TextureGL::setLevelInfo(const gl::Context *context,
if (updateWorkarounds)
{
mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
}
......
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