inline void VL_glGenerateMipmap(GLenum target)
 {
   if (glGenerateMipmapOES)
     glGenerateMipmapOES(target);
   else
     VL_TRAP();
 }
Texture::Texture(const TextureData &data)
{
    glGenTextures(1, &_textureID);
    glBindTexture(GL_TEXTURE_2D, _textureID);
    
    if (_textureID)
    {
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        
        glTexImage2D(GL_TEXTURE_2D, 0, data.getFormat(), data.getWidth(), data.getHeight(), 0, data.getFormat(), GL_UNSIGNED_BYTE, data.getImageData().get());
        
#ifndef USE_GL_ES2
        glGenerateMipmapOES(GL_TEXTURE_2D);
#else
        glGenerateMipmap(GL_TEXTURE_2D);
#endif
        
    }
}
Example #3
0
/*
=================
gl_texture_create
=================
*/
erbool gl_texture_create (image_t *image, int flags, int *gltex, int *texw, int *texh)
{
    int    max, sw, sh, mip;
    GLuint tex;

    if (NULL == image || NULL == gltex || NULL == texw || NULL == texh)
    {
        sys_printf("bad args (image=%p, flags=%i, gltex=%p, texw=%p, texh=%p)\n",
                   image, flags, gltex, texw, texh);
        return false;
    }

    if (flags & GL_TEX_FL_TEX3D)
    {
        max = gl_texture3d_size_max;
    }
    else if (flags & GL_TEX_FL_CUBEMAP)
    {
        max = gl_texture_cube_map_size_max;
    }
    else
    {
        max = gl_max_texture_size;
    }

    if (GL_TEX_FL_NOPICMIP)
    {
        sw = CLAMP(image->width,  1, max);
        sh = CLAMP(image->height, 1, max);
    }
    else
    {
        sw = CLAMP(image->width  >> gl_picmip->i, 1, max);
        sh = CLAMP(image->height >> gl_picmip->i, 1, max);
    }

    if (!ext_gl_arb_texture_non_power_of_two || !gl_arb_texture_non_power_of_two->i)
    {
        sw = ceil_pwrov2(sw);
        sh = ceil_pwrov2(sh);
    }

    sw = CLAMP(sw, GL_MIN_TEXTURE_DIMENSION, max);
    sh = CLAMP(sh, GL_MIN_TEXTURE_DIMENSION, max);

    if (flags & GL_TEX_FL_NOSCALE)
    {
        *texw = sw;
        *texh = sh;

        if (!image_resize(image, sw, sh))
            return false;
    }
    else
    {
        *texw = image->width;
        *texh = image->height;

        if (!image_scale(image, sw, sh))
            return false;
    }

    glGenTextures(1, &tex);
    GLERROR();
    eglBindTexture(GL_TEXTURE_2D, tex);
    GLERROR();

    *gltex = tex;

    if (NULL != image->teximage2d)
    {
        image->teximage2d(image);
    }
    else
    {
        if (ext_gl_sgis_generate_mipmap && gl_sgis_generate_mipmap->i)
        {
#ifdef ENGINE_OS_IPHONE
            glGenerateMipmapOES(GL_TEXTURE_2D);
#else
            glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
#endif
            GLERROR();
            GL_IMAGE_DATA2D(0, image);
            GLERROR();
        }
        else
        {
            GL_IMAGE_DATA2D(0, image);
            GLERROR();

            for (mip = 1; image->width > 1 || image->height > 1 ; mip++)
            {
                int status;

                if (0 > (status = image_mipmap(image)))
                {
                    sys_printf("mipmap failed\n");
                    goto error;
                }
                else if (status > 0)
                {
                    break;
                }

                GL_IMAGE_DATA2D(mip, image);
                GLERROR();
            }
        }
    }

    if (flags & GL_TEX_FL_NOFILTER)
    {
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        GLERROR();
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        GLERROR();
    }
    else
    {
        glTexParameteri(GL_TEXTURE_2D,
                        GL_TEXTURE_MIN_FILTER,
                        gl_trilinear->i ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR_MIPMAP_NEAREST);
        GLERROR();
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GLERROR();
    }

    if (!(flags & GL_TEX_FL_NOANISO) &&
            ext_gl_ext_texture_filter_anisotropic &&
            gl_ext_texture_filter_anisotropic->i)
    {
        GLfloat ani = CLAMP(gl_anisotropy_level->f, 1, gl_anisotropy_max);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ani);
        GLERROR();
    }

    if (!(flags & GL_TEX_FL_NOLOD) &&
            ext_gl_ext_texture_lod_bias &&
            gl_ext_texture_lod_bias->i)
    {
        GLfloat lod = CLAMP(gl_lod_bias->f, 0, gl_lod_bias_max);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS_EXT, lod);
        GLERROR();
    }

    return true;

error:
    glDeleteTextures(1, &tex);
    GLERROR();

    return false;
}
    //-----------------------------------------------------------------------------  
    // Very fast texture-to-texture blitter and hardware bi/trilinear scaling implementation using FBO
    // Destination texture must be 2D
    // Source texture must be 2D
    // Supports compressed formats as both source and destination format, it will use the hardware DXT compressor
    // if available.
    // @author W.J. van der Laan
    void GLESTextureBuffer::blitFromTexture(GLESTextureBuffer *src, const Image::Box &srcBox, const Image::Box &dstBox)
    {
        if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_FBO) == false)
        {
            // the following code depends on FBO support, it crashes if FBO is not supported.
            // TODO - write PBUFFER version of this function or a version that doesn't require FBO
            return; // for now - do nothing.
        }

//        std::cerr << "GLESTextureBuffer::blitFromTexture " <<
//        src->mTextureID << ":" << srcBox.left << "," << srcBox.top << "," << srcBox.right << "," << srcBox.bottom << " " << 
//        mTextureID << ":" << dstBox.left << "," << dstBox.top << "," << dstBox.right << "," << dstBox.bottom << std::endl;

        // Store reference to FBO manager
        GLESFBOManager *fboMan = static_cast<GLESFBOManager *>(GLESRTTManager::getSingletonPtr());
        
        // Save and clear GL state for rendering
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |  GL_STENCIL_BUFFER_BIT);
        
        RenderSystem* rsys = Root::getSingleton().getRenderSystem();
        rsys->_disableTextureUnitsFrom(0);

        // Disable alpha, depth and scissor testing, disable blending, 
        // disable culling, disble lighting, disable fog and reset foreground
        // colour.
        glDisable(GL_ALPHA_TEST);
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_SCISSOR_TEST);
        glDisable(GL_BLEND);
        glDisable(GL_CULL_FACE);
        glDisable(GL_LIGHTING);
        glDisable(GL_FOG);
        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
        GL_CHECK_ERROR;

        // Save and reset matrices
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glMatrixMode(GL_TEXTURE);
        glPushMatrix();
        glLoadIdentity();
        GL_CHECK_ERROR;
        
        // Set up source texture
        glBindTexture(src->mTarget, src->mTextureID);
        GL_CHECK_ERROR;
        
        // Set filtering modes depending on the dimensions and source
        if(srcBox.getWidth()==dstBox.getWidth() &&
           srcBox.getHeight()==dstBox.getHeight() &&
           srcBox.getDepth()==dstBox.getDepth())
        {
            // Dimensions match -- use nearest filtering (fastest and pixel correct)
            glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
            GL_CHECK_ERROR;
            glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            GL_CHECK_ERROR;
        }
        else
        {
            // Dimensions don't match -- use bi or trilinear filtering depending on the
            // source texture.
            if(src->mUsage & TU_AUTOMIPMAP)
            {
                // Automatic mipmaps, we can safely use trilinear filter which
                // brings greatly imporoved quality for minimisation.
                glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                GL_CHECK_ERROR;
                glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);    
                GL_CHECK_ERROR;
            }
            else
            {
                // Manual mipmaps, stay safe with bilinear filtering so that no
                // intermipmap leakage occurs.
                glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                GL_CHECK_ERROR;
                glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                GL_CHECK_ERROR;
            }
        }
        // Clamp to edge (fastest)
        glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_ERROR;
        glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_ERROR;
        
        // Store old binding so it can be restored later
        GLint oldfb;
        glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldfb);
        GL_CHECK_ERROR;

        // Set up temporary FBO
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, fboMan->getTemporaryFBO());
        GL_CHECK_ERROR;

        GLuint tempTex = 0;
        if(!fboMan->checkFormat(mFormat))
        {
            // If target format not directly supported, create intermediate texture
            GLenum tempFormat = GLESPixelUtil::getClosestGLInternalFormat(fboMan->getSupportedAlternative(mFormat));
            glGenTextures(1, &tempTex);
            GL_CHECK_ERROR;
            glBindTexture(GL_TEXTURE_2D, tempTex);
            GL_CHECK_ERROR;
            // Allocate temporary texture of the size of the destination area
            glTexImage2D(GL_TEXTURE_2D, 0, tempFormat, 
                         GLESPixelUtil::optionalPO2(dstBox.getWidth()), GLESPixelUtil::optionalPO2(dstBox.getHeight()), 
                         0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
            GL_CHECK_ERROR;
            glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
                                      GL_TEXTURE_2D, tempTex, 0);
            GL_CHECK_ERROR;
            // Set viewport to size of destination slice
            glViewport(0, 0, dstBox.getWidth(), dstBox.getHeight());
            GL_CHECK_ERROR;
        }
        else
        {
            // We are going to bind directly, so set viewport to size and position of destination slice
            glViewport(dstBox.left, dstBox.top, dstBox.getWidth(), dstBox.getHeight());
            GL_CHECK_ERROR;
        }
        
        // Process each destination slice
        for(size_t slice=dstBox.front; slice<dstBox.back; ++slice)
        {
            if(!tempTex)
            {
                /// Bind directly
                bindToFramebuffer(GL_COLOR_ATTACHMENT0_OES, slice);
            }

            if(tempTex)
            {
                // Copy temporary texture
                glBindTexture(mTarget, mTextureID);
                GL_CHECK_ERROR;
                switch(mTarget)
                {
                    case GL_TEXTURE_2D:
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
                    case GL_TEXTURE_CUBE_MAP_OES:
#endif
                        glCopyTexSubImage2D(mFaceTarget, mLevel, 
                                            dstBox.left, dstBox.top, 
                                            0, 0, dstBox.getWidth(), dstBox.getHeight());
                        GL_CHECK_ERROR;
                        break;
                }
            }
        }
        // Finish up 
        if(!tempTex)
        {
            // Generate mipmaps
            if(mUsage & TU_AUTOMIPMAP)
            {
                glBindTexture(mTarget, mTextureID);
                GL_CHECK_ERROR;
                glGenerateMipmapOES(mTarget);
                GL_CHECK_ERROR;
            }
        }
        
        // Reset source texture to sane state
        glBindTexture(src->mTarget, src->mTextureID);
        GL_CHECK_ERROR;
        
        // Detach texture from temporary framebuffer
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
                                     GL_RENDERBUFFER_OES, 0);
        GL_CHECK_ERROR;
        // Restore old framebuffer
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldfb);
        GL_CHECK_ERROR;
        // Restore matrix stacks and render state
        glMatrixMode(GL_TEXTURE);
        glPopMatrix();
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
        GL_CHECK_ERROR;
        glDeleteTextures(1, &tempTex);
        GL_CHECK_ERROR;
    }
void glGenerateMipmapOESLogged(GLenum target) {
	printf("glGenerateMipmapOES(%s)\n", GLEnumName(target));
	glGenerateMipmapOES(target);
}
void RETextureInternal::update(GLuint identifier,
							   const REUByte * pixelsData, 
							   const REImagePixelFormat pixelsFormat,
							   const REUInt32 width,
							   const REUInt32 height,
							   RETextureFilterType filterType)
{
	GLenum textureType = 0;
	switch (pixelsFormat) 
	{
		case REImagePixelFormatR8G8B8:
			textureType = GL_RGB;
			break;
		case REImagePixelFormatR8G8B8A8:
			textureType = GL_RGBA;
			break;
		case REImagePixelFormatLuminance8Alpha8:
			textureType = GL_LUMINANCE_ALPHA;
			break;	
		case REImagePixelFormatAlpha8:
			textureType = GL_ALPHA;
			break;	
		default:
			return;
			break;
	}
	glBindTexture(GL_TEXTURE_2D, identifier);
	
	
#if defined(IS_OPENGL_MIPMAPS)	
	/* MIPMAPS */
	
	const REBOOL isGenerateMipmaps = RETextureInternal::isMipmaped(filterType);
	if (isGenerateMipmaps) 
	{
#if defined(HAVE_FUNCTION_GLUBUILD2DMIPMAPS)		
		gluBuild2DMipmaps(GL_TEXTURE_2D, textureType, width, height, textureType, GL_UNSIGNED_BYTE, pixelsData);
#else
		
#if defined(HAVE_FUNCTION_GLTEXIMAGE2D)		
		glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType, GL_UNSIGNED_BYTE, pixelsData);
#endif	
#if defined(HAVE_FUNCTION_GLGENERATEMIPMAPOES)
		glGenerateMipmapOES(GL_TEXTURE_2D);		
#endif	
		
#endif		
	}
	else
	{
#if defined(HAVE_FUNCTION_GLTEXIMAGE2D)		
		glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType, GL_UNSIGNED_BYTE, pixelsData);
#endif	
	}
	
	/* MIPMAPS */
#else 
	/* NO MIPMAPS */
	
#if defined(HAVE_FUNCTION_GLTEXIMAGE2D)		
	glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType, GL_UNSIGNED_BYTE, pixelsData);
#endif /* HAVE_FUNCTION_GLTEXIMAGE2D */
	
	/* NO MIPMAPS */
#endif	

}
Example #7
0
void GLTexture_setImage(void * selfPtr, GLint mipmapLevel, GLsizei width, GLsizei height, unsigned int bytesPerRow, void * bitmapData) {
	GLTexture * self = selfPtr;
	
	if (self->textureName == 0) {
		glGenTextures(1, &self->textureName);
	}
	self->pixelWidth = width;
	self->pixelHeight = height;
	glBindTexture(GL_TEXTURE_2D, self->textureName);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, self->wrapS);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, self->wrapT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, self->magFilter);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, self->minFilter);
	
#if defined(GL_EXT_texture_filter_anisotropic) && GL_EXT_texture_filter_anisotropic
	if (self->anisotropicFilter) {
		GLfloat maxAnisotropy;
		
		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
	}
#endif
	
	if (bytesPerRow % 4 == 0) {
		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
	} else if (bytesPerRow % 2 == 0) {
		glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
	} else {
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	}
	
#if !TARGET_OPENGL_ES
	if (self->autoMipmap) {
		switch (GLGraphics_getOpenGLAPIVersion()) {
			case GL_API_VERSION_DESKTOP_1:
			case GL_API_VERSION_DESKTOP_2:
			case GL_API_VERSION_DESKTOP_3:
				glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
				break;
			default:
				break;
		}
	}
#endif
	
	glTexImage2D(GL_TEXTURE_2D, mipmapLevel, self->bitmapDataFormat, width, height, 0, self->bitmapDataFormat, self->bitmapDataType, bitmapData);
	
#if TARGET_OPENGL_ES
	if (self->autoMipmap) {
		switch (GLGraphics_getOpenGLAPIVersion()) {
			case GL_API_VERSION_ES1:
				glGenerateMipmapOES(GL_TEXTURE_2D);
				break;
				
			case GL_API_VERSION_ES2:
				glGenerateMipmap(GL_TEXTURE_2D);
				break;
				
			default:
				break;
		}
	}
#endif
}
Example #8
0
bool cfxSampler::apply(cfxParam* param)
{
    // lookup source for the matching surface;
    if (surface == NULL)
    {
        surface = effect->getSurfaceByName(source);

        // only go through this if the surface is newly initialized
        // this will update the textureId
        // bind the texture and initialize the sampler states
        // generate mipmaps if needed
        if (surface)
        {
            surface->addReferencingParam(param);

            const std::string surfaceSource = surface->getInitFrom();
            //cfxPrint("Found surface init from %p %s\n", surface, surfaceSource.c_str());

            // get the texture object from the surface that is its source, or if that can't be found
            // just try using texture 1 as the default which is definitely  not the solution but may
            // be interesting until this feature is fully supported

            // the mechanism to pair a texture with a surface for use by a parameter is in place.
            // the support for loading textures, as would probably be done by the surface is out
            // of the scope of this library.  this is something that needs to exist
            // in a lower layer that can do resource management.  this is something that
            // needs to exist in a layer that allows this other aspect of resource management.

            // this uses a static map (which has its own set of disadvantages) from surface to lookup
            // texture ids from images that were loaded elsewhere and pushed into cfx
            textureId = cfxSurface::getTexIdByImageId(surfaceSource);

            if (textureId > 0)
            {
                //cfxPrint("Set sampler state\n");
                // this works on the currently bound texture object
                // not important which texture unit is used, we just need to use one to
                // allow cgSetSamplerState() to work properly.
                cfxPrint("going to bind %d\n", textureId);
                glBindTexture(GL_TEXTURE_2D, textureId);

                // apply the state settings
                std::vector<cfxGlSamplerSetting*>::iterator settingIter = settingArray.begin();
                while (settingIter != settingArray.end())
                {
                    (*settingIter)->apply(param);
                    settingIter++;
                }

                // calling this before generate mipmaps is better cause then the call
                // to generate mipmaps already has the space set up for it to use
                cgSetSamplerState(param->getParameter());

                if (generateMipmaps)
                {
#ifdef SN_TARGET_PS3
                    glGenerateMipmapOES(GL_TEXTURE_2D);
#endif
                }
            }
            else
            {
                cfxPrint("Texture not found for surface: %s\n", surfaceSource.c_str());
                return false;
            }
        }
    }

    return true;
}