Пример #1
0
    void GLES2Texture::loadImpl()
    {
        if (mUsage & TU_RENDERTARGET)
        {
            createRenderTexture();
            return;
        }

        // Now the only copy is on the stack and will be cleaned in case of
        // exceptions being thrown from _loadImages
        LoadedImages loadedImages = mLoadedImages;
        mLoadedImages.setNull();

        // Call internal _loadImages, not loadImage since that's external and 
        // will determine load status etc again
        ConstImagePtrList imagePtrs;

        for (size_t i = 0; i < loadedImages->size(); ++i)
        {
            imagePtrs.push_back(&(*loadedImages)[i]);
        }

        _loadImages(imagePtrs);

        if((mUsage & TU_AUTOMIPMAP) &&
           mNumRequestedMipmaps && mMipmapsHardwareGenerated)
        {
            OGRE_CHECK_GL_ERROR(glGenerateMipmap(getGLES2TextureTarget()));
        }
    }
Пример #2
0
    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");
                }
            }
        }
    }
Пример #3
0
    void GLES2Texture::_createGLTexResource()
    {
        if(!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_NON_POWER_OF_2_TEXTURES) ||
           (Root::getSingleton().getRenderSystem()->getCapabilities()->getNonPOW2TexturesLimited() && mNumRequestedMipmaps > 0))
        {
            // Convert to nearest power-of-two size if required
            mWidth = GLES2PixelUtil::optionalPO2(mWidth);
            mHeight = GLES2PixelUtil::optionalPO2(mHeight);
            mDepth = GLES2PixelUtil::optionalPO2(mDepth);
        }

        // Adjust format if required
        mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage);
        GLenum texTarget = getGLES2TextureTarget();

        // Check requested number of mipmaps
        size_t maxMips = GLES2PixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);
        
        if(PixelUtil::isCompressed(mFormat) && (mNumMipmaps == 0))
            mNumRequestedMipmaps = 0;
        
        mNumMipmaps = mNumRequestedMipmaps;
        if (mNumMipmaps > maxMips)
            mNumMipmaps = maxMips;

        // Generate texture name
        OGRE_CHECK_GL_ERROR(glGenTextures(1, &mTextureID));
           
        // Set texture type
        mGLSupport.getStateCacheManager()->bindGLTexture(texTarget, mTextureID);
        
        // If we can do automip generation and the user desires this, do so
        mMipmapsHardwareGenerated =
            Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP) && !PixelUtil::isCompressed(mFormat);

        if(!Bitwise::isPO2(mWidth) || !Bitwise::isPO2(mHeight))
            mMipmapsHardwareGenerated = false;

        // glGenerateMipmap require all mip levels to be prepared. So override how many this texture has.
        if((mUsage & TU_AUTOMIPMAP) && mMipmapsHardwareGenerated && mNumRequestedMipmaps)
            mNumMipmaps = maxMips;

        if(getGLES2SupportRef()->checkExtension("GL_APPLE_texture_max_level") || gleswIsSupported(3, 0))
            mGLSupport.getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MAX_LEVEL_APPLE, mNumRequestedMipmaps ? mNumMipmaps + 1 : 0);

        // Set some misc default parameters, these can of course be changed later
        mGLSupport.getStateCacheManager()->setTexParameteri(texTarget,
                                                            GL_TEXTURE_MIN_FILTER, ((mUsage & TU_AUTOMIPMAP) && mNumRequestedMipmaps) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
        mGLSupport.getStateCacheManager()->setTexParameteri(texTarget,
                                                            GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        mGLSupport.getStateCacheManager()->setTexParameteri(texTarget,
                                                            GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        mGLSupport.getStateCacheManager()->setTexParameteri(texTarget,
                                                            GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // Set up texture swizzling
#if OGRE_NO_GLES3_SUPPORT == 0
        if(gleswIsSupported(3, 0))
        {
            OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED));
            OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_GREEN));
            OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_BLUE));
            OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ALPHA));

            if(mFormat == PF_L8 || mFormat == PF_L16)
            {
                OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED));
                OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED));
                OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED));
                OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_RED));
            }
        }
#endif

        // Allocate internal buffer so that glTexSubImageXD can be used
        // Internal format
        GLenum format = GLES2PixelUtil::getGLOriginFormat(mFormat);
        GLenum internalformat = GLES2PixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma);
        uint32 width = mWidth;
        uint32 height = mHeight;
        uint32 depth = mDepth;
        
        if (PixelUtil::isCompressed(mFormat))
        {
            // Compressed formats
            GLsizei size = static_cast<GLsizei>(PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat));
            
            // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not
            // accept a 0 pointer like normal glTexImageXD
            // Run through this process for every mipmap to pregenerate mipmap pyramid
            
            uint8* tmpdata = new uint8[size];
            memset(tmpdata, 0, size);
            for (GLint mip = 0; mip <= mNumMipmaps; mip++)
            {
#if OGRE_DEBUG_MODE
                LogManager::getSingleton().logMessage("GLES2Texture::create - Mip: " + StringConverter::toString(mip) +
                                                      " Width: " + StringConverter::toString(width) +
                                                      " Height: " + StringConverter::toString(height) +
                                                      " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex) +
                                                      " Format: " + StringConverter::toString(format, 0, ' ', std::ios::hex)
                                                      );
#endif
                size = static_cast<GLsizei>(PixelUtil::getMemorySize(width, height, depth, mFormat));
                
                switch(mTextureType)
                {
                    case TEX_TYPE_1D:
                    case TEX_TYPE_2D:
                        OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_2D,
                                               mip,
                                               internalformat,
                                               width, height,
                                               0,
                                               size,
                                               tmpdata));
                        break;
                    case TEX_TYPE_CUBE_MAP:
                        for(int face = 0; face < 6; face++) {
                            OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat,
                                width, height, 0, 
                                size, tmpdata));
                        }
                        break;
#if OGRE_NO_GLES3_SUPPORT == 0
                    case TEX_TYPE_2D_ARRAY:
                    case TEX_TYPE_3D:
                        glCompressedTexImage3D(getGLES2TextureTarget(), mip, format,
                            width, height, depth, 0, 
                            size, tmpdata);
                        break;
#endif
                    default:
                        break;
                };
                
                if(width > 1)
                {
                    width = width / 2;
                }
                if(height > 1)
                {
                    height = height / 2;
                }
                if(depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY)
                {
                    depth = depth / 2;
                }
            }
            delete [] tmpdata;
        }
        else
        {
#if OGRE_NO_GLES3_SUPPORT == 0
#if OGRE_DEBUG_MODE
            LogManager::getSingleton().logMessage("GLES2Texture::create - Name: " + mName +
                                                      " ID: " + StringConverter::toString(mTextureID) +
                                                      " Width: " + StringConverter::toString(width) +
                                                      " Height: " + StringConverter::toString(height) +
                                                      " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex));
#endif
            switch(mTextureType)
            {
                case TEX_TYPE_1D:
                case TEX_TYPE_2D:
                case TEX_TYPE_2D_RECT:
                    OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_2D, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height)));
                    break;
                case TEX_TYPE_CUBE_MAP:
                    OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_CUBE_MAP, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height)));
                    break;
                case TEX_TYPE_2D_ARRAY:
                    OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_2D_ARRAY, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height), GLsizei(depth)));
                    break;
                case TEX_TYPE_3D:
                    OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_3D, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height), GLsizei(depth)));
                    break;
            }
#else
            GLenum datatype = GLES2PixelUtil::getGLOriginDataType(mFormat);

            // Run through this process to pregenerate mipmap pyramid
            for(GLint mip = 0; mip <= mNumMipmaps; mip++)
            {
#if OGRE_DEBUG_MODE
                LogManager::getSingleton().logMessage("GLES2Texture::create - Mip: " + StringConverter::toString(mip) +
                                                      " Name: " + mName +
                                                      " ID: " + StringConverter::toString(mTextureID) +
                                                      " Width: " + StringConverter::toString(width) +
                                                      " Height: " + StringConverter::toString(height) +
                                                      " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex) +
                                                      " Format: " + StringConverter::toString(format, 0, ' ', std::ios::hex) +
                                                      " Datatype: " + StringConverter::toString(datatype, 0, ' ', std::ios::hex)
                                                      );
#endif
                // Normal formats
                switch(mTextureType)
                {
                    case TEX_TYPE_1D:
                    case TEX_TYPE_2D:
#if OGRE_PLATFORM == OGRE_PLATFORM_NACL
                        if(internalformat != format)
                        {
                            LogManager::getSingleton().logMessage("glTexImage2D: format != internalFormat, "
                                "format=" + StringConverter::toString(format) + 
                                ", internalFormat=" + StringConverter::toString(internalformat));
                        }
#endif
                        OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_2D,
                                     mip,
                                     internalformat,
                                     width, height,
                                     0,
                                     format,
                                     datatype, 0));
                        break;
                    case TEX_TYPE_CUBE_MAP:
                        for(int face = 0; face < 6; face++) {
                            OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat,
                                width, height, 0, 
                                format, datatype, 0));
                        }
                        break;
                    default:
                        break;
                };
                
                if (width > 1)
                {
                    width = Bitwise::firstPO2From(width / 2);
                }
                if (height > 1)
                {
                    height = Bitwise::firstPO2From(height / 2);
                }
            }
#endif
        }
    }
Пример #4
0
    // Creation / loading methods
    void GLES2Texture::createInternalResourcesImpl(void)
    {
		// Convert to nearest power-of-two size if required
        mWidth = GLES2PixelUtil::optionalPO2(mWidth);
        mHeight = GLES2PixelUtil::optionalPO2(mHeight);
        mDepth = GLES2PixelUtil::optionalPO2(mDepth);

		// Adjust format if required
        mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage);

		// Check requested number of mipmaps
        size_t maxMips = GLES2PixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);

        if(PixelUtil::isCompressed(mFormat) && (mNumMipmaps == 0))
            mNumRequestedMipmaps = 0;

        mNumMipmaps = mNumRequestedMipmaps;
        if (mNumMipmaps > maxMips)
            mNumMipmaps = maxMips;

		// Generate texture name
        glGenTextures(1, &mTextureID);
        GL_CHECK_ERROR;

		// Set texture type
        glBindTexture(getGLES2TextureTarget(), mTextureID);
        GL_CHECK_ERROR;

        // If we can do automip generation and the user desires this, do so
        mMipmapsHardwareGenerated =
            Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP) && !PixelUtil::isCompressed(mFormat);

#if GL_APPLE_texture_max_level && OGRE_PLATFORM != OGRE_PLATFORM_NACL
        glTexParameteri( getGLES2TextureTarget(), GL_TEXTURE_MAX_LEVEL_APPLE, (mMipmapsHardwareGenerated && (mUsage & TU_AUTOMIPMAP)) ? maxMips : mNumMipmaps );
#endif

        // Set some misc default parameters, these can of course be changed later
        glTexParameteri(getGLES2TextureTarget(),
                        GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        GL_CHECK_ERROR;
        glTexParameteri(getGLES2TextureTarget(),
                        GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        GL_CHECK_ERROR;
        glTexParameteri(getGLES2TextureTarget(),
                        GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_ERROR;
        glTexParameteri(getGLES2TextureTarget(),
                        GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_ERROR;

        // Allocate internal buffer so that glTexSubImageXD can be used
        // Internal format
        GLenum format = GLES2PixelUtil::getGLOriginFormat(mFormat);
        GLenum internalformat = GLES2PixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma);
        GLenum datatype = GLES2PixelUtil::getGLOriginDataType(mFormat);
        size_t width = mWidth;
        size_t height = mHeight;
        size_t depth = mDepth;

        if (PixelUtil::isCompressed(mFormat))
        {
            // Compressed formats
            size_t size = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);

            // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not
            // accept a 0 pointer like normal glTexImageXD
            // Run through this process for every mipmap to pregenerate mipmap pyramid

            uint8* tmpdata = new uint8[size];
            memset(tmpdata, 0, size);
            for (size_t mip = 0; mip <= mNumMipmaps; mip++)
            {
//                LogManager::getSingleton().logMessage("GLES2Texture::create - Mip: " + StringConverter::toString(mip) +
//                                                      " Width: " + StringConverter::toString(width) +
//                                                      " Height: " + StringConverter::toString(height) +
//                                                      " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex) +
//                                                      " Format: " + StringConverter::toString(format, 0, ' ', std::ios::hex) +
//                                                      " Datatype: " + StringConverter::toString(datatype, 0, ' ', std::ios::hex)
//                                                      );

                size = PixelUtil::getMemorySize(width, height, depth, mFormat);

				switch(mTextureType)
				{
					case TEX_TYPE_1D:
					case TEX_TYPE_2D:
                        glCompressedTexImage2D(GL_TEXTURE_2D,
                                               mip,
                                               internalformat,
                                               width, height,
                                               0,
                                               size,
                                               tmpdata);
                        GL_CHECK_ERROR;
                        break;
					case TEX_TYPE_CUBE_MAP:
						for(int face = 0; face < 6; face++) {
							glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat,
								width, height, 0, 
								size, tmpdata);
                            GL_CHECK_ERROR;
						}
						break;
					case TEX_TYPE_3D:
                    default:
                        break;
                };

                if(width > 1)
                {
                    width = width / 2;
                }
                if(height > 1)
                {
                    height = height / 2;
                }
                if(depth > 1)
                {
                    depth = depth / 2;
                }
            }
            delete [] tmpdata;
        }
        else
        {
            // Run through this process to pregenerate mipmap pyramid
            for(size_t mip = 0; mip <= mNumMipmaps; mip++)
            {
//                LogManager::getSingleton().logMessage("GLES2Texture::create - Mip: " + StringConverter::toString(mip) +
//                                                      " Name: " + mName +
//                                                      " ID: " + StringConverter::toString(mTextureID) +
//                                                      " Width: " + StringConverter::toString(width) +
//                                                      " Height: " + StringConverter::toString(height) +
//                                                      " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex) +
//                                                      " Format: " + StringConverter::toString(format, 0, ' ', std::ios::hex) +
//                                                      " Datatype: " + StringConverter::toString(datatype, 0, ' ', std::ios::hex)
//                                                      );

				// Normal formats
				switch(mTextureType)
				{
					case TEX_TYPE_1D:
					case TEX_TYPE_2D:
#if OGRE_PLATFORM == OGRE_PLATFORM_NACL
                        if(internalformat != format)
                        {
                            LogManager::getSingleton().logMessage("glTexImage2D: format != internalFormat, "
                                "format=" + StringConverter::toString(format) + 
                                ", internalFormat=" + StringConverter::toString(internalformat));
                        }
#endif
                        glTexImage2D(GL_TEXTURE_2D,
                                     mip,
                                     internalformat,
                                     width, height,
                                     0,
                                     format,
                                     datatype, 0);
                        GL_CHECK_ERROR;
                        break;
					case TEX_TYPE_CUBE_MAP:
						for(int face = 0; face < 6; face++) {
							glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat,
								width, height, 0, 
								format, datatype, 0);
						}
						break;
					case TEX_TYPE_3D:
                    default:
                        break;
                };

                if (width > 1)
                {
                    width = width / 2;
                }
                if (height > 1)
                {
                    height = height / 2;
                }
            }
        }

        _createSurfaceList();

        // Get final internal format
        mFormat = getBuffer(0,0)->getFormat();
    }