Shinya Kitaoka e5734a
#include <memory></memory>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/meshtexturizer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Shinya Kitaoka 120a6e
#include "tgl.h"  // OpenGL includes
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qreadwritelock></qreadwritelock>
Toshihiro Shimizu 890ddd
#include <qreadlocker></qreadlocker>
Toshihiro Shimizu 890ddd
#include <qwritelocker></qwritelocker>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_macros.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_list.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_misc.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define COPIED_BORDER 1  // Amount of tile border from the original image
Shinya Kitaoka 120a6e
#define TRANSP_BORDER 1  // Amount of transparent tile border
Shinya Kitaoka 120a6e
#define NONPREM_BORDER                                                         \
Shinya Kitaoka 120a6e
  1  // Amount of nonpremultiplied copied transparent border
Shinya Kitaoka 120a6e
#define TOTAL_BORDER                                                           \
Shinya Kitaoka 120a6e
  (COPIED_BORDER + TRANSP_BORDER)  // Overall border to texture tiles above
Shinya Kitaoka 120a6e
#define TOTAL_BORDER_2 (2 * TOTAL_BORDER)  // Twice the above
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCG_STATIC_ASSERT(COPIED_BORDER >
Shinya Kitaoka 120a6e
                  0);  // Due to GL_LINEAR alpha blending on tile seams
Shinya Kitaoka 120a6e
TCG_STATIC_ASSERT(TRANSP_BORDER > 0);  // Due to GL_CLAMP beyond tile limits
Shinya Kitaoka 120a6e
TCG_STATIC_ASSERT(NONPREM_BORDER <=
Shinya Kitaoka 120a6e
                  TRANSP_BORDER);  // The nonpremultiplied border is transparent
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    MeshTexturizer::Imp  definition
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class MeshTexturizer::Imp {
Shinya Kitaoka 120a6e
  typedef MeshTexturizer::TextureData TextureData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  QReadWriteLock m_lock;  //!< Lock for synchronized access
Shinya Kitaoka 120a6e
  tcg::list<std::shared_ptr<texturedata>></std::shared_ptr<texturedata>
Shinya Kitaoka 120a6e
      m_textureDatas;  //!< Pool of texture datas
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp() : m_lock(QReadWriteLock::Recursive) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool testTextureAlloc(int lx, int ly);
Shinya Kitaoka 120a6e
  GLuint textureAlloc(const TRaster32P &ras, const TRaster32P &aux, int x,
Shinya Kitaoka 120a6e
                      int y, int textureLx, int textureLy, bool premultiplied);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void allocateTextures(int groupIdx, const TRaster32P &ras,
Shinya Kitaoka 120a6e
                        const TRaster32P &aux, int x, int y, int textureLx,
Shinya Kitaoka 120a6e
                        int textureLy, bool premultiplied);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TextureData *getTextureData(int groupIdx);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool MeshTexturizer::Imp::testTextureAlloc(int lx, int ly) {
Shinya Kitaoka 120a6e
  lx += TOTAL_BORDER_2, ly += TOTAL_BORDER_2;  // Add border
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glTexImage2D(GL_PROXY_TEXTURE_2D,
Shinya Kitaoka 120a6e
               0,                 // one level only
Shinya Kitaoka 120a6e
               GL_RGBA,           // number of pixel channels
Shinya Kitaoka 120a6e
               lx,                // width
Shinya Kitaoka 120a6e
               ly,                // height
Shinya Kitaoka 120a6e
               0,                 // border size
Shinya Kitaoka 120a6e
               TGL_FMT,           // pixel format
Shinya Kitaoka 120a6e
               GL_UNSIGNED_BYTE,  // pixel data type
Shinya Kitaoka 120a6e
               0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int outLx;
Shinya Kitaoka 120a6e
  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &outLx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (lx == outLx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
GLuint MeshTexturizer::Imp::textureAlloc(const TRaster32P &ras,
Shinya Kitaoka 120a6e
                                         const TRaster32P &aux, int x, int y,
Shinya Kitaoka 120a6e
                                         int textureLx, int textureLy,
Shinya Kitaoka 120a6e
                                         bool premultiplied) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static void clearMatte(const TRaster32P &ras, int xBegin, int yBegin,
Shinya Kitaoka 120a6e
                           int xEnd, int yEnd) {
Shinya Kitaoka 120a6e
      for (int y = yBegin; y != yEnd; ++y) {
Shinya Kitaoka 120a6e
        TPixel32 *line = ras->pixels(y), *pixEnd = line + xEnd;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        for (TPixel32 *pix = line + xBegin; pix != pixEnd; ++pix) pix->m = 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    static void clearMatte_border(const TRaster32P &ras, int border0,
Shinya Kitaoka 120a6e
                                  int border1) {
Shinya Kitaoka 120a6e
      assert(border0 < border1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Horizontal
Shinya Kitaoka 120a6e
      clearMatte(ras, border0, border0, ras->getLx() - border0, border1);
Shinya Kitaoka 120a6e
      clearMatte(ras, border0, ras->getLy() - border1, ras->getLx() - border0,
Shinya Kitaoka 120a6e
                 ras->getLy() - border0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Vertical
Shinya Kitaoka 120a6e
      clearMatte(ras, border0, border1, border1, ras->getLy() - border1);
Shinya Kitaoka 120a6e
      clearMatte(ras, ras->getLx() - border1, border1, ras->getLx() - border0,
Shinya Kitaoka 120a6e
                 ras->getLy() - border1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Prepare the texture tile
Shinya Kitaoka 120a6e
  assert(aux->getLx() >= textureLx + TOTAL_BORDER_2 &&
Shinya Kitaoka 120a6e
         aux->getLy() >= textureLy + TOTAL_BORDER_2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect rasRect(x, y, x + textureLx - 1, y + textureLy - 1);
Shinya Kitaoka 120a6e
  rasRect = rasRect.enlarge(premultiplied ? COPIED_BORDER
Shinya Kitaoka 120a6e
                                          : COPIED_BORDER + NONPREM_BORDER);
Shinya Kitaoka 120a6e
  rasRect = rasRect * ras->getBounds();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect auxRect(rasRect - TPoint(x - TOTAL_BORDER, y - TOTAL_BORDER));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // An auxiliary raster must be used to supply the transparent border
Shinya Kitaoka 120a6e
  TRaster32P tex(aux->extract(0, 0, textureLx + TOTAL_BORDER_2 - 1,
Shinya Kitaoka 120a6e
                              textureLy + TOTAL_BORDER_2 - 1));
Shinya Kitaoka 120a6e
  tex->clear();
Shinya Kitaoka 120a6e
  aux->extract(auxRect)->copy(ras->extract(rasRect));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!premultiplied && NONPREM_BORDER > 0)
Shinya Kitaoka 120a6e
    locals::clearMatte_border(aux, TRANSP_BORDER - NONPREM_BORDER,
Shinya Kitaoka 120a6e
                              TRANSP_BORDER);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Pass the raster into VRAM
Shinya Kitaoka 120a6e
  GLuint texId;
Shinya Kitaoka 120a6e
  glGenTextures(1, &texId);
Shinya Kitaoka 120a6e
  glBindTexture(GL_TEXTURE_2D, texId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
Shinya Kitaoka 120a6e
                  GL_CLAMP);  // These must be used on a bound texture,
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
Shinya Kitaoka 120a6e
                  GL_CLAMP);  // and are remembered in the OpenGL context.
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
Shinya Kitaoka 120a6e
                  GL_LINEAR);  // They can be set here, no need for
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
Shinya Kitaoka 120a6e
                  GL_LINEAR);  // the user to do it.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->getWrap());
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glTexImage2D(GL_TEXTURE_2D,
Shinya Kitaoka 120a6e
               0,                 // one level only
Shinya Kitaoka 120a6e
               GL_RGBA,           // pixel channels count
Shinya Kitaoka 120a6e
               tex->getLx(),      // width
Shinya Kitaoka 120a6e
               tex->getLy(),      // height
Shinya Kitaoka 120a6e
               0,                 // border size
Shinya Kitaoka 120a6e
               TGL_FMT,           // pixel format
Shinya Kitaoka 120a6e
               GL_UNSIGNED_BYTE,  // pixel data type
Shinya Kitaoka 120a6e
               (GLvoid *)tex->getRawData());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return texId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MeshTexturizer::Imp::allocateTextures(int groupIdx, const TRaster32P &ras,
Shinya Kitaoka 120a6e
                                           const TRaster32P &aux, int x, int y,
Shinya Kitaoka 120a6e
                                           int textureLx, int textureLy,
Shinya Kitaoka 120a6e
                                           bool premultiplied) {
Shinya Kitaoka 120a6e
  TextureData *data = m_textureDatas[groupIdx].get();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Test the specified texture allocation
Shinya Kitaoka 120a6e
  if (testTextureAlloc(textureLx, textureLy)) {
Shinya Kitaoka 120a6e
    TPointD scale(data->m_geom.getLx() / (double)ras->getLx(),
Shinya Kitaoka 120a6e
                  data->m_geom.getLy() / (double)ras->getLy());
Shinya Kitaoka 120a6e
    TRectD tileGeom(TRectD(scale.x * (x - TOTAL_BORDER),
Shinya Kitaoka 120a6e
                           scale.y * (y - TOTAL_BORDER),
Shinya Kitaoka 120a6e
                           scale.x * (x + textureLx + TOTAL_BORDER),
Shinya Kitaoka 120a6e
                           scale.y * (y + textureLy + TOTAL_BORDER)) +
Shinya Kitaoka 120a6e
                    data->m_geom.getP00());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    GLuint texId =
Shinya Kitaoka 120a6e
        textureAlloc(ras, aux, x, y, textureLx, textureLy, premultiplied);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TextureData::TileData td = {texId, tileGeom};
Shinya Kitaoka 120a6e
    data->m_tileDatas.push_back(td);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (textureLx <= 1 && textureLy <= 1) return;  // No texture can be allocated
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // The texture could not be allocated. Then, bisecate and branch.
Shinya Kitaoka 120a6e
  if (textureLx > textureLy) {
Shinya Kitaoka 120a6e
    int textureLx_2 = textureLx >> 1;
Shinya Kitaoka 120a6e
    allocateTextures(groupIdx, ras, aux, x, y, textureLx_2, textureLy,
Shinya Kitaoka 120a6e
                     premultiplied);
Shinya Kitaoka 120a6e
    allocateTextures(groupIdx, ras, aux, x + textureLx_2, y, textureLx_2,
Shinya Kitaoka 120a6e
                     textureLy, premultiplied);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    int textureLy_2 = textureLy >> 1;
Shinya Kitaoka 120a6e
    allocateTextures(groupIdx, ras, aux, x, y, textureLx, textureLy_2,
Shinya Kitaoka 120a6e
                     premultiplied);
Shinya Kitaoka 120a6e
    allocateTextures(groupIdx, ras, aux, x, y + textureLy_2, textureLx,
Shinya Kitaoka 120a6e
                     textureLy_2, premultiplied);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
MeshTexturizer::TextureData *MeshTexturizer::Imp::getTextureData(int groupIdx) {
Shinya Kitaoka 120a6e
  typedef MeshTexturizer::TextureData TextureData;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Copy tile datas container
Shinya Kitaoka 120a6e
  return m_textureDatas[groupIdx].get();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    MeshTexturizer  implementation
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
MeshTexturizer::MeshTexturizer() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
MeshTexturizer::~MeshTexturizer() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int MeshTexturizer::bindTexture(const TRaster32P &ras, const TRectD &geom,
Shinya Kitaoka 120a6e
                                PremultMode premultiplyMode) {
Shinya Kitaoka 120a6e
  QWriteLocker locker(&m_imp->m_lock);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Backup the state of some specific OpenGL variables that will be changed
Shinya Kitaoka 120a6e
  // throughout the code
Shinya Kitaoka 120a6e
  int row_length, alignment;
Shinya Kitaoka 120a6e
  glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
Shinya Kitaoka 120a6e
  glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Initialize a new texture data
Shinya Kitaoka 120a6e
  int dataIdx =
Shinya Kitaoka 120a6e
      m_imp->m_textureDatas.push_back(std::make_shared<texturedata>(geom));</texturedata>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Textures must have 2-power sizes. So, let's start with the smallest 2 power
Shinya Kitaoka 120a6e
  // >= ras's sizes.
Shinya Kitaoka 120a6e
  int textureLx =
Shinya Kitaoka 120a6e
      tcg::numeric_ops::GE_2Power((unsigned int)ras->getLx() + TOTAL_BORDER_2);
Shinya Kitaoka 120a6e
  int textureLy =
Shinya Kitaoka 120a6e
      tcg::numeric_ops::GE_2Power((unsigned int)ras->getLy() + TOTAL_BORDER_2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // We'll assume a strict granularity max of 512 x 512 textures
Shinya Kitaoka 120a6e
  textureLx = std::min(textureLx, 1 << 9);
Shinya Kitaoka 120a6e
  textureLy = std::min(textureLy, 1 << 9);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Allocate a suitable texture raster. The texture will include a transparent
Shinya Kitaoka 120a6e
  // 1-pix border
Shinya Kitaoka 120a6e
  // that is needed to perform texture mapping with GL_CLAMP transparent
Shinya Kitaoka 120a6e
  // wrapping
Shinya Kitaoka 120a6e
  TRaster32P tex(textureLx, textureLy);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, let's tile the specified raster. We'll start from the lower-left
Shinya Kitaoka 120a6e
  // corner in case
Shinya Kitaoka 120a6e
  // the raster can be completely included in just one tile
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lx = ras->getLx(), ly = ras->getLy();
Shinya Kitaoka 120a6e
  int tileLx = textureLx - TOTAL_BORDER_2,
Shinya Kitaoka 120a6e
      tileLy = textureLy - TOTAL_BORDER_2;  // Texture size without border
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int xEntireCells = (lx - 1) / tileLx,
Shinya Kitaoka 120a6e
      yEntireCells =
Shinya Kitaoka 120a6e
          (ly - 1) /
Shinya Kitaoka 120a6e
          tileLy;  // +1 so in case l == tileL, we get the remainder case
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lastTexLx = tcg::numeric_ops::GE_2Power(
Shinya Kitaoka 120a6e
      (unsigned int)(lx - xEntireCells * tileLx + TOTAL_BORDER_2));
Shinya Kitaoka 120a6e
  int lastTexLy = tcg::numeric_ops::GE_2Power(
Shinya Kitaoka 120a6e
      (unsigned int)(ly - yEntireCells * tileLy + TOTAL_BORDER_2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lastTileLx = lastTexLx - TOTAL_BORDER_2,
Shinya Kitaoka 120a6e
      lastTileLy = lastTexLy - TOTAL_BORDER_2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool premultiplied = (premultiplyMode == PREMULTIPLIED);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
  for (i = 0; i < yEntireCells; ++i) {
Shinya Kitaoka 120a6e
    for (j = 0; j < xEntireCells; ++j)
Shinya Kitaoka 120a6e
      // Perform a (possibly subdividing) allocation of the specified tile
Shinya Kitaoka 120a6e
      m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, tileLx,
Shinya Kitaoka 120a6e
                              tileLy, premultiplied);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy,
Shinya Kitaoka 120a6e
                            lastTileLx, tileLy, premultiplied);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (j = 0; j < xEntireCells; ++j)
Shinya Kitaoka 120a6e
    m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, tileLx,
Shinya Kitaoka 120a6e
                            lastTileLy, premultiplied);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, lastTileLx,
Shinya Kitaoka 120a6e
                          lastTileLy, premultiplied);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Restore OpenGL variables
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return dataIdx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MeshTexturizer::rebindTexture(int texId, const TRaster32P &ras,
Shinya Kitaoka 120a6e
                                   const TRectD &geom,
Shinya Kitaoka 120a6e
                                   PremultMode premultiplyMode) {
Shinya Kitaoka 120a6e
  QWriteLocker locker(&m_imp->m_lock);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  unbindTexture(texId);
Shinya Kitaoka 120a6e
  int newTexId = bindTexture(ras, geom, premultiplyMode);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(texId == newTexId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void MeshTexturizer::unbindTexture(int texId) {
Shinya Kitaoka 120a6e
  QWriteLocker locker(&m_imp->m_lock);
Shinya Kitaoka 120a6e
  m_imp->m_textureDatas.erase(texId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
MeshTexturizer::TextureData *MeshTexturizer::getTextureData(int textureId) {
Shinya Kitaoka 120a6e
  QReadLocker locker(&m_imp->m_lock);
Shinya Kitaoka 120a6e
  return m_imp->getTextureData(textureId);
Toshihiro Shimizu 890ddd
}