//--------------------------------------------------------------------------------------------- void GLTexture::_createSurfaceList() { mSurfaceList.clear(); // For all faces and mipmaps, store surfaces as HardwarePixelBufferSharedPtr bool wantGeneratedMips = (mUsage & TU_AUTOMIPMAP)!=0; // Do mipmapping in software? (uses GLU) For some cards, this is still needed. Of course, // only when mipmap generation is desired. bool doSoftware = wantGeneratedMips && !mMipmapsHardwareGenerated && getNumMipmaps(); for(size_t face=0; face<getNumFaces(); face++) { for(size_t mip=0; mip<=getNumMipmaps(); mip++) { GLHardwarePixelBuffer *buf = new GLTextureBuffer(mName, getGLTextureTarget(), mTextureID, face, mip, static_cast<HardwareBuffer::Usage>(mUsage), doSoftware && mip==0, mHwGamma, mFSAA); mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf)); /// Check for error if(buf->getWidth()==0 || buf->getHeight()==0 || buf->getDepth()==0) { OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Zero sized texture surface on texture "+getName()+ " face "+StringConverter::toString(face)+ " mipmap "+StringConverter::toString(mip)+ ". Probably, the GL driver refused to create the texture.", "GLTexture::_createSurfaceList"); } } } }
PixelBox Image::getPixelBox(size_t face, size_t mipmap) const { // Image data is arranged as: // face 0, top level (mip 0) // face 0, mip 1 // face 0, mip 2 // face 1, top level (mip 0) // face 1, mip 1 // face 1, mip 2 // etc if(mipmap > getNumMipmaps()) OGRE_EXCEPT( Exception::ERR_NOT_IMPLEMENTED, "Mipmap index out of range", "Image::getPixelBox" ) ; if(face >= getNumFaces()) OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Face index out of range", "Image::getPixelBox"); // Calculate mipmap offset and size uint8 *offset = const_cast<uint8*>(getData()); // Base offset is number of full faces uint32 width = getWidth(), height=getHeight(), depth=getDepth(); size_t numMips = getNumMipmaps(); // Figure out the offsets size_t fullFaceSize = 0; size_t finalFaceSize = 0; uint32 finalWidth = 0, finalHeight = 0, finalDepth = 0; for(size_t mip=0; mip <= numMips; ++mip) { if (mip == mipmap) { finalFaceSize = fullFaceSize; finalWidth = width; finalHeight = height; finalDepth = depth; } fullFaceSize += PixelUtil::getMemorySize(width, height, depth, getFormat()); /// Half size in each dimension if(width!=1) width /= 2; if(height!=1) height /= 2; if(depth!=1) depth /= 2; } // Advance pointer by number of full faces, plus mip offset into offset += face * fullFaceSize; offset += finalFaceSize; // Return subface as pixelbox PixelBox src(finalWidth, finalHeight, finalDepth, getFormat(), offset); return src; }
void GLES2Texture::_createSurfaceList() { mSurfaceList.clear(); // For all faces and mipmaps, store surfaces as HardwarePixelBufferSharedPtr bool wantGeneratedMips = (mUsage & TU_AUTOMIPMAP)!=0; // Do mipmapping in software? (uses GLU) For some cards, this is still needed. Of course, // only when mipmap generation is desired. bool doSoftware = wantGeneratedMips && !mMipmapsHardwareGenerated && getNumMipmaps(); for (size_t face = 0; face < getNumFaces(); face++) { uint32 width = mWidth; uint32 height = mHeight; uint32 depth = mDepth; for (uint8 mip = 0; mip <= getNumMipmaps(); mip++) { GLES2HardwarePixelBuffer *buf = OGRE_NEW GLES2TextureBuffer(mName, getGLES2TextureTarget(), mTextureID, width, height, depth, GLES2PixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma), GLES2PixelUtil::getGLOriginDataType(mFormat), static_cast<GLint>(face), mip, static_cast<HardwareBuffer::Usage>(mUsage), doSoftware && mip == 0, mHwGamma, mFSAA); mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf)); // Check for error if (buf->getWidth() == 0 || buf->getHeight() == 0 || buf->getDepth() == 0) { OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Zero sized texture surface on texture " + getName() + " face " + StringConverter::toString(face) + " mipmap " + StringConverter::toString(mip) + ". The GL driver probably refused to create the texture.", "GLES2Texture::_createSurfaceList"); } } } }
PixelBox Image::getPixelBox(size_t face, size_t mipmap) const { if(mipmap > getNumMipmaps()) OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, "Mipmap index out of range", "Image::getPixelBox" ) ; if(face >= getNumFaces()) OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Face index out of range", "Image::getPixelBox"); // Calculate mipmap offset and size uint8 *offset = const_cast<uint8*>(getData()); size_t width = getWidth(), height=getHeight(), depth=getDepth(); size_t faceSize; // Size of one face of the image for(size_t mip=0; mip<mipmap; ++mip) { faceSize = PixelUtil::getMemorySize(width, height, depth, getFormat()); /// Skip all faces of this mipmap offset += faceSize*getNumFaces(); /// Half size in each dimension if(width!=1) width /= 2; if(height!=1) height /= 2; if(depth!=1) depth /= 2; } // We have advanced to the desired mipmap, offset to right face faceSize = PixelUtil::getMemorySize(width, height, depth, getFormat()); offset += faceSize*face; // Return subface as pixelbox PixelBox src(width, height, depth, getFormat(), offset); return src; }
void GL3PlusTexture::_createSurfaceList() { mSurfaceList.clear(); size_t depth = mDepth; for (uint8 face = 0; face < getNumFaces(); face++) { size_t width = mWidth; size_t height = mHeight; for (uint32 mip = 0; mip <= getNumMipmaps(); mip++) { GL3PlusHardwarePixelBuffer* buf = new GL3PlusTextureBuffer(this, face, mip, width, height, depth); mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf)); if (width > 1) width = width / 2; if (height > 1) height = height / 2; if (depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY) depth = depth / 2; } } }
void GL3PlusTexture::_createSurfaceList() { mSurfaceList.clear(); for (size_t face = 0; face < getNumFaces(); face++) { for (size_t mip = 0; mip <= getNumMipmaps(); mip++) { GL3PlusHardwarePixelBuffer *buf = new GL3PlusTextureBuffer(mName, getGL3PlusTextureTarget(), mTextureID, face, mip, static_cast<HardwareBuffer::Usage>(mUsage), mHwGamma, mFSAA); mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf)); // Check for error if (buf->getWidth() == 0 || buf->getHeight() == 0 || buf->getDepth() == 0) { OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Zero sized texture surface on texture "+getName()+ " face "+StringConverter::toString(face)+ " mipmap "+StringConverter::toString(mip)+ ". The GL driver probably refused to create the texture.", "GL3PlusTexture::_createSurfaceList"); } } } }
//--------------------------------------------------------------------------------------------- void GLTexture::_createSurfaceList() { mSurfaceList.clear(); uint32 depth = mDepth; // For all faces and mipmaps, store surfaces as HardwarePixelBufferSharedPtr for(GLint face=0; face<static_cast<GLint>(getNumFaces()); face++) { uint32 width = mWidth; uint32 height = mHeight; for(uint32 mip=0; mip<=getNumMipmaps(); mip++) { GLHardwarePixelBuffer* buf = new GLTextureBuffer(mRenderSystem, this, face, mip, width, height, depth); mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf)); if (width > 1) width = width / 2; if (height > 1) height = height / 2; if (depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY) depth = depth / 2; } } }
//----------------------------------------------------------------------------- void Texture::copyToTexture( TexturePtr& target ) { if(target->getNumFaces() != getNumFaces()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Texture types must match", "Texture::copyToTexture"); } size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps()); if((mUsage & TU_AUTOMIPMAP) || (target->getUsage()&TU_AUTOMIPMAP)) numMips = 0; for(unsigned int face=0; face<getNumFaces(); face++) { for(unsigned int mip=0; mip<=numMips; mip++) { target->getBuffer(face, mip)->blit(getBuffer(face, mip)); } } }
//--------------------------------------------------------------------- void Texture::convertToImage(Image& destImage, bool includeMipMaps) { size_t numMips = includeMipMaps? getNumMipmaps() + 1 : 1; size_t dataSize = Image::calculateSize(numMips, getNumFaces(), getWidth(), getHeight(), getDepth(), getFormat()); void* pixData = OGRE_MALLOC(dataSize, Ogre::MEMCATEGORY_GENERAL); // if there are multiple faces and mipmaps we must pack them into the data // faces, then mips void* currentPixData = pixData; for (size_t face = 0; face < getNumFaces(); ++face) { uint32 width = getWidth(); uint32 height = getHeight(); uint32 depth = getDepth(); for (size_t mip = 0; mip < numMips; ++mip) { size_t mipDataSize = PixelUtil::getMemorySize(width, height, depth, getFormat()); Ogre::PixelBox pixBox(width, height, depth, getFormat(), currentPixData); getBuffer(face, mip)->blitToMemory(pixBox); currentPixData = (void*)((char*)currentPixData + mipDataSize); if(width != 1) width /= 2; if(height != 1) height /= 2; if(depth != 1) depth /= 2; } } // load, and tell Image to delete the memory when it's done. destImage.loadDynamicImage((Ogre::uchar*)pixData, getWidth(), getHeight(), getDepth(), getFormat(), true, getNumFaces(), numMips - 1); }