| Message ID | 20260805183517.228901-7-mzamazal@redhat.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
2026. 08. 05. 20:35 keltezéssel, Milan Zamazal írta: > From: Xander Pronk <xander.c.pronk@gmail.com> > > Add support for passing the LSC table from debayerParams to the shaders. > > We use 8-bit texture with the original UQ<2, 6> values to avoid trouble > with floats. 32-bit floats don't work in my environment and 16-bit > floats may not be supported in all OpenGL environments. > > When LSC is disabled by the runtime control, we provide a constant 1.0 > correction table, i.e. a no-op table. This is preferred to having a > runtime flag, to not disturb GPU computation with runtime switches, > assuming that disabling LSC in runtime is not a common use case. > > The LSC texture is created once and then updated. The texture creation > cannot be done in `configure', because of a different thread. > > Co-developed-by: Rick ten Wolde <rick_libcamera@wolde.info> > Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info> > Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com> > Signed-off-by: Milan Zamazal <mzamazal@redhat.com> > --- > include/libcamera/internal/egl.h | 8 +++- > .../internal/software_isp/debayer_params.h | 2 + > src/libcamera/egl.cpp | 14 +++++-- > src/libcamera/software_isp/debayer.cpp | 5 +++ > src/libcamera/software_isp/debayer_egl.cpp | 42 ++++++++++++++++++- > src/libcamera/software_isp/debayer_egl.h | 8 ++++ > 6 files changed, 71 insertions(+), 8 deletions(-) > > diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h > index 790ec4b22..b80d65877 100644 > --- a/include/libcamera/internal/egl.h > +++ b/include/libcamera/internal/egl.h > @@ -107,8 +107,12 @@ public: > > int createInputDMABufTexture2D(eGLImage &eglImage, int fd); > int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); > - void createTexture2D(eGLImage &eglImage, void *data, GLint filter); > - void updateTexture2D(eGLImage &eglImage, void *data); > + void createTexture2D(eGLImage &eglImage, > + GLint internalFormat, > + GLenum type, > + const void *data, > + GLint filter); > + void updateTexture2D(eGLImage &eglImage, const void *data); > void createOutputTexture2D(eGLImage &eglImage); > > int attachTextureToFBO(eGLImage &eglImage); > diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h > index 93dcf42e6..ae51c3271 100644 > --- a/include/libcamera/internal/software_isp/debayer_params.h > +++ b/include/libcamera/internal/software_isp/debayer_params.h > @@ -33,6 +33,8 @@ struct DebayerParams { > **/ > static constexpr unsigned int kLscGridSize = 17; > static constexpr unsigned int kLscValuesPerCell = 4; > + static constexpr unsigned int kLscBytesPerCell = > + kLscValuesPerCell * sizeof(uint8_t); > using LscLookupTable = > std::array<uint8_t, kLscGridSize * kLscGridSize * kLscValuesPerCell>; > LscLookupTable lscLut{}; > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index 32e7e0e9c..cbae3a664 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -277,6 +277,8 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) > /** > * \brief Create a 2D texture from a memory buffer > * \param[in,out] eglImage EGL image to associate with the texture > + * \param[in] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8) > + * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT) > * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture > * \param[in] filter GL texture filter setting > * > @@ -285,14 +287,18 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) > * is useful for uploading static data like lookup tables or uniform color > * matrices to the GPU. > */ > -void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter) > +void eGL::createTexture2D(eGLImage &eglImage, > + GLint internalFormat, > + GLenum type, > + const void *data, > + GLint filter) > { > ASSERT(tid_ == Thread::currentId()); > > activateBindTexture(eglImage); > > // Generate texture, bind, associate image to texture, configure, unbind > - glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); > + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, eglImage.width_, eglImage.height_, 0, eglImage.format_, type, data); > > // Nearest filtering > glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); > @@ -338,7 +344,7 @@ EGLDisplay eGL::probeDisplay() > * > * Updates a 2D texture in VRAM. > */ > -void eGL::updateTexture2D(eGLImage &eglImage, void *data) > +void eGL::updateTexture2D(eGLImage &eglImage, const void *data) I feel like it might be nice to separate the `eGL` class changes. > { > ASSERT(tid_ == Thread::currentId()); > > @@ -357,7 +363,7 @@ void eGL::updateTexture2D(eGLImage &eglImage, void *data) > */ > void eGL::createOutputTexture2D(eGLImage &eglImage) > { > - createTexture2D(eglImage, NULL, GL_NEAREST); > + createTexture2D(eglImage, eglImage.format_, GL_UNSIGNED_BYTE, NULL, GL_NEAREST); > attachTextureToFBO(eglImage); > } > > [...] > diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h > index a64dc925a..ac0de23a0 100644 > --- a/src/libcamera/software_isp/debayer_egl.h > +++ b/src/libcamera/software_isp/debayer_egl.h > @@ -83,7 +83,12 @@ private: > unsigned int inputBufferCount_; > unsigned int outputBufferCount_; > > + /* LSC lookup table */ > + std::unique_ptr<eGLImage> eglImageLscLookup_; > bool lscEnabled_; > + bool lscTextureCreated_ = false; I believe the unique_ptr/optional could be used instead of an extra bool if you move the construction into `setShaderVariableValues()`? > + uint64_t lscLutVersion_ = 0; Shouldn't this be reset in `start()` / `stop()`? And should it possibly be an `std::optional`? Especially given that `DebayerParams::lscLutVersion` does not seem to be reset anywhere? > + > /* Shader parameters */ > float firstRed_x_; > float firstRed_y_; > @@ -100,6 +105,9 @@ private: > /* Per-frame AWB gains */ > GLint awbUniformDataIn_; > > + /* Lens shading correction */ > + GLint textureUniformLsc_; > + > /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ > GLint ccmUniformDataIn_; >
Hi Barnabás, thank you for review. Barnabás Pőcze <barnabas.pocze@ideasonboard.com> writes: > 2026. 08. 05. 20:35 keltezéssel, Milan Zamazal írta: >> From: Xander Pronk <xander.c.pronk@gmail.com> >> Add support for passing the LSC table from debayerParams to the shaders. >> We use 8-bit texture with the original UQ<2, 6> values to avoid trouble >> with floats. 32-bit floats don't work in my environment and 16-bit >> floats may not be supported in all OpenGL environments. >> When LSC is disabled by the runtime control, we provide a constant 1.0 >> correction table, i.e. a no-op table. This is preferred to having a >> runtime flag, to not disturb GPU computation with runtime switches, >> assuming that disabling LSC in runtime is not a common use case. >> The LSC texture is created once and then updated. The texture creation >> cannot be done in `configure', because of a different thread. >> Co-developed-by: Rick ten Wolde <rick_libcamera@wolde.info> >> Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info> >> Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com> >> Signed-off-by: Milan Zamazal <mzamazal@redhat.com> >> --- >> include/libcamera/internal/egl.h | 8 +++- >> .../internal/software_isp/debayer_params.h | 2 + >> src/libcamera/egl.cpp | 14 +++++-- >> src/libcamera/software_isp/debayer.cpp | 5 +++ >> src/libcamera/software_isp/debayer_egl.cpp | 42 ++++++++++++++++++- >> src/libcamera/software_isp/debayer_egl.h | 8 ++++ >> 6 files changed, 71 insertions(+), 8 deletions(-) >> diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h >> index 790ec4b22..b80d65877 100644 >> --- a/include/libcamera/internal/egl.h >> +++ b/include/libcamera/internal/egl.h >> @@ -107,8 +107,12 @@ public: >> int createInputDMABufTexture2D(eGLImage &eglImage, int fd); >> int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); >> - void createTexture2D(eGLImage &eglImage, void *data, GLint filter); >> - void updateTexture2D(eGLImage &eglImage, void *data); >> + void createTexture2D(eGLImage &eglImage, >> + GLint internalFormat, >> + GLenum type, >> + const void *data, >> + GLint filter); >> + void updateTexture2D(eGLImage &eglImage, const void *data); >> void createOutputTexture2D(eGLImage &eglImage); >> int attachTextureToFBO(eGLImage &eglImage); >> diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h >> index 93dcf42e6..ae51c3271 100644 >> --- a/include/libcamera/internal/software_isp/debayer_params.h >> +++ b/include/libcamera/internal/software_isp/debayer_params.h >> @@ -33,6 +33,8 @@ struct DebayerParams { >> **/ >> static constexpr unsigned int kLscGridSize = 17; >> static constexpr unsigned int kLscValuesPerCell = 4; >> + static constexpr unsigned int kLscBytesPerCell = >> + kLscValuesPerCell * sizeof(uint8_t); >> using LscLookupTable = >> std::array<uint8_t, kLscGridSize * kLscGridSize * kLscValuesPerCell>; >> LscLookupTable lscLut{}; >> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp >> index 32e7e0e9c..cbae3a664 100644 >> --- a/src/libcamera/egl.cpp >> +++ b/src/libcamera/egl.cpp >> @@ -277,6 +277,8 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) >> /** >> * \brief Create a 2D texture from a memory buffer >> * \param[in,out] eglImage EGL image to associate with the texture >> + * \param[in] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8) >> + * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT) >> * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture >> * \param[in] filter GL texture filter setting >> * >> @@ -285,14 +287,18 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) >> * is useful for uploading static data like lookup tables or uniform color >> * matrices to the GPU. >> */ >> -void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter) >> +void eGL::createTexture2D(eGLImage &eglImage, >> + GLint internalFormat, >> + GLenum type, >> + const void *data, >> + GLint filter) >> { >> ASSERT(tid_ == Thread::currentId()); >> activateBindTexture(eglImage); >> // Generate texture, bind, associate image to texture, configure, unbind >> - glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); >> + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, eglImage.width_, eglImage.height_, 0, eglImage.format_, type, data); >> // Nearest filtering >> glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); >> @@ -338,7 +344,7 @@ EGLDisplay eGL::probeDisplay() >> * >> * Updates a 2D texture in VRAM. >> */ >> -void eGL::updateTexture2D(eGLImage &eglImage, void *data) >> +void eGL::updateTexture2D(eGLImage &eglImage, const void *data) > > I feel like it might be nice to separate the `eGL` class changes. I can put them to a separate commit if it helps. >> { >> ASSERT(tid_ == Thread::currentId()); >> @@ -357,7 +363,7 @@ void eGL::updateTexture2D(eGLImage &eglImage, void *data) >> */ >> void eGL::createOutputTexture2D(eGLImage &eglImage) >> { >> - createTexture2D(eglImage, NULL, GL_NEAREST); >> + createTexture2D(eglImage, eglImage.format_, GL_UNSIGNED_BYTE, NULL, GL_NEAREST); >> attachTextureToFBO(eglImage); >> } >> [...] >> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h >> index a64dc925a..ac0de23a0 100644 >> --- a/src/libcamera/software_isp/debayer_egl.h >> +++ b/src/libcamera/software_isp/debayer_egl.h >> @@ -83,7 +83,12 @@ private: >> unsigned int inputBufferCount_; >> unsigned int outputBufferCount_; >> + /* LSC lookup table */ >> + std::unique_ptr<eGLImage> eglImageLscLookup_; >> bool lscEnabled_; >> + bool lscTextureCreated_ = false; > > I believe the unique_ptr/optional could be used instead of an extra bool > if you move the construction into `setShaderVariableValues()`? OK. >> + uint64_t lscLutVersion_ = 0; > > Shouldn't this be reset in `start()` / `stop()`? And should it possibly be an `std::optional`? Good catch. It should be reset in stop() and using std::optional would be cleaner and safer. > Especially given that `DebayerParams::lscLutVersion` does not seem to be reset anywhere? It should be reset together with the other parameters, I'll add that. >> + >> /* Shader parameters */ >> float firstRed_x_; >> float firstRed_y_; >> @@ -100,6 +105,9 @@ private: >> /* Per-frame AWB gains */ >> GLint awbUniformDataIn_; >> + /* Lens shading correction */ >> + GLint textureUniformLsc_; >> + >> /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ >> GLint ccmUniformDataIn_; >>
diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 790ec4b22..b80d65877 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -107,8 +107,12 @@ public: int createInputDMABufTexture2D(eGLImage &eglImage, int fd); int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); - void createTexture2D(eGLImage &eglImage, void *data, GLint filter); - void updateTexture2D(eGLImage &eglImage, void *data); + void createTexture2D(eGLImage &eglImage, + GLint internalFormat, + GLenum type, + const void *data, + GLint filter); + void updateTexture2D(eGLImage &eglImage, const void *data); void createOutputTexture2D(eGLImage &eglImage); int attachTextureToFBO(eGLImage &eglImage); diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h index 93dcf42e6..ae51c3271 100644 --- a/include/libcamera/internal/software_isp/debayer_params.h +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -33,6 +33,8 @@ struct DebayerParams { **/ static constexpr unsigned int kLscGridSize = 17; static constexpr unsigned int kLscValuesPerCell = 4; + static constexpr unsigned int kLscBytesPerCell = + kLscValuesPerCell * sizeof(uint8_t); using LscLookupTable = std::array<uint8_t, kLscGridSize * kLscGridSize * kLscValuesPerCell>; LscLookupTable lscLut{}; diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 32e7e0e9c..cbae3a664 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -277,6 +277,8 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) /** * \brief Create a 2D texture from a memory buffer * \param[in,out] eglImage EGL image to associate with the texture + * \param[in] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8) + * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT) * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture * \param[in] filter GL texture filter setting * @@ -285,14 +287,18 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) * is useful for uploading static data like lookup tables or uniform color * matrices to the GPU. */ -void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter) +void eGL::createTexture2D(eGLImage &eglImage, + GLint internalFormat, + GLenum type, + const void *data, + GLint filter) { ASSERT(tid_ == Thread::currentId()); activateBindTexture(eglImage); // Generate texture, bind, associate image to texture, configure, unbind - glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, eglImage.width_, eglImage.height_, 0, eglImage.format_, type, data); // Nearest filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); @@ -338,7 +344,7 @@ EGLDisplay eGL::probeDisplay() * * Updates a 2D texture in VRAM. */ -void eGL::updateTexture2D(eGLImage &eglImage, void *data) +void eGL::updateTexture2D(eGLImage &eglImage, const void *data) { ASSERT(tid_ == Thread::currentId()); @@ -357,7 +363,7 @@ void eGL::updateTexture2D(eGLImage &eglImage, void *data) */ void eGL::createOutputTexture2D(eGLImage &eglImage) { - createTexture2D(eglImage, NULL, GL_NEAREST); + createTexture2D(eglImage, eglImage.format_, GL_UNSIGNED_BYTE, NULL, GL_NEAREST); attachTextureToFBO(eglImage); } diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 801c28fc9..44df03990 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -53,6 +53,11 @@ namespace libcamera { * \brief Number of pixel values per each of the lens shading grid areas */ +/** + * \var DebayerParams::kLscBytesPerCell + * \brief Number of bytes per each of the lens shading grid areas + */ + /** * \typedef DebayerParams::LscLookupTable * \brief Lookup table for lens shading correction diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index e03fef684..5562a7b76 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -115,6 +115,8 @@ int DebayerEGL::getShaderVariableLocations(void) textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + textureUniformLsc_ = glGetUniformLocation(programId_, "lsc_tex"); + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ << " awb " << awbUniformDataIn_ @@ -126,7 +128,8 @@ int DebayerEGL::getShaderVariableLocations(void) << " tex_size " << textureUniformSize_ << " stride_factor " << textureUniformStrideFactor_ << " tex_bayer_first_red " << textureUniformBayerFirstRed_ - << " proj_matrix " << textureUniformProjMatrix_; + << " proj_matrix " << textureUniformProjMatrix_ + << " tex_lsc " << textureUniformLsc_; return 0; } @@ -143,6 +146,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm /* Specify GL_OES_EGL_image_external */ egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); + if (lscEnabled_) + egl_.pushEnv(shaderEnv, "#define APPLY_LSC"); + /* * Tell shaders how to re-order output taking account of how the pixels * are actually stored by EGL. @@ -338,6 +344,18 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, inputBufferCount_ = inputCfg.bufferCount; outputBufferCount_ = outputCfg.bufferCount; + if (lscEnabled_) { + constexpr unsigned int gridSize = DebayerParams::kLscGridSize; + const unsigned int stride = gridSize * DebayerParams::kLscBytesPerCell; + eglImageLscLookup_ = + std::make_unique<eGLImage>(GL_RGBA, + gridSize, + gridSize, + stride, + GL_TEXTURE2, + 2); + } + return 0; } @@ -467,6 +485,21 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_TRUE, params.combinedMatrix.data().data()); LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; + if (lscEnabled_) { + glUniform1i(textureUniformLsc_, eglImageLscLookup_->texture_unit_uniform_id_); + if (params.lscLutVersion != lscLutVersion_) { + if (lscTextureCreated_) { + egl_.updateTexture2D(*eglImageLscLookup_, params.lscLut.data()); + } else { + egl_.createTexture2D(*eglImageLscLookup_, eglImageLscLookup_->format_, GL_UNSIGNED_BYTE, + params.lscLut.data(), GL_LINEAR); + lscTextureCreated_ = true; + } + + lscLutVersion_ = params.lscLutVersion; + } + } + /* * 0 = Red, 1 = Green, 2 = Blue */ @@ -536,7 +569,11 @@ eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optiona return nullptr; } if (cache_miss) - egl_.createTexture2D(*eglImageIn, inMapped->value().planes()[0].data(), GL_NEAREST); + egl_.createTexture2D(*eglImageIn, + eglImageIn->format_, + GL_UNSIGNED_BYTE, + inMapped->value().planes()[0].data(), + GL_NEAREST); else egl_.updateTexture2D(*eglImageIn, inMapped->value().planes()[0].data()); @@ -682,6 +719,7 @@ void DebayerEGL::stop() { eglImageOutCache_.clear(); eglImageInCache_.clear(); + lscTextureCreated_ = false; if (programId_) glDeleteProgram(programId_); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index a64dc925a..ac0de23a0 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -83,7 +83,12 @@ private: unsigned int inputBufferCount_; unsigned int outputBufferCount_; + /* LSC lookup table */ + std::unique_ptr<eGLImage> eglImageLscLookup_; bool lscEnabled_; + bool lscTextureCreated_ = false; + uint64_t lscLutVersion_ = 0; + /* Shader parameters */ float firstRed_x_; float firstRed_y_; @@ -100,6 +105,9 @@ private: /* Per-frame AWB gains */ GLint awbUniformDataIn_; + /* Lens shading correction */ + GLint textureUniformLsc_; + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_;