//
// This is a patch for the Inventor 2.0 SoTexture2 node, which will
// use incorrect display lists when rendering to another gl rendering
// context (most commonly done when rendering to an
// SoOffScreenRenderer for printing).
//
//
// To apply this patch, compile this file into a .o and then link
// the .o before -lInventor.  The linker may give a warning.
// This is normal and expected.
//

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

////////////////////////////////////////////////////////////////////////
//
// Description:
//    Performs GL rendering on a texture node.
//
// Use: extender

void
SoTexture2::GLRender(SoGLRenderAction *action)
//
////////////////////////////////////////////////////////////////////////
{
    SoState *state = action->getState();

    if (! wrapS.isIgnored())
	SoTextureWrapSElement::set(state, this,
		(SoTextureWrapSElement::Wrap)wrapS.getValue());

    if (! wrapT.isIgnored())
	SoTextureWrapTElement::set(state, this,
		(SoTextureWrapTElement::Wrap)wrapT.getValue());

    if (! model.isIgnored())
	SoTextureModelElement::set(state, this,
		(SoTextureModelElement::Model)model.getValue());

    if (! blendColor.isIgnored())
	SoTextureBlendColorElement::set(state, this,
	    blendColor.getValue());
    if (! image.isIgnored()) {
	SbVec2s size;
	int nc;
	const unsigned char *bytes = image.getValue(size, nc);

	// Check for special cases of 1/2 component texture and model
	// DECAL or 3/4 component texture and model BLEND; print out
	// errors in these cases:
	
	SoTextureModelElement::Model m =
	    SoTextureModelElement::get(state);
	if (nc < 3 && m == SoTextureModelElement::DECAL) {
#ifdef DEBUG
	    SoDebugError::post("SoTexture2::GLRender",
		"Texture model is DECAL, but texture image"
		" has only %d components (must be 3 or 4).  "
		"Use imgcopy to convert the image.", nc);
#endif	    
	}
	else if (nc > 2 && m == SoTextureModelElement::BLEND) {
#ifdef DEBUG
	    SoDebugError::post("SoTexture2::GLRender",
		"Texture model is BLEND, but texture image"
		" has %d components (must be 1 or 2).  "
		"Use imgcopy to convert the image.", nc);
#endif	    
	} else {
	    // This is kind of weird-- the element builds and uses the
	    // display list (which is why we pass it in and assign
	    // it) because it sends the GL calls, and needs to know
	    // the list if the state is popped.  But this node must
	    // manage storage and deletion of the display list, since
	    // the list must go away if the node is deleted or the
	    // image is changed.

	    // See if renderList is valid (in the right context):
	    int context = SoGLCacheContextElement::get(state);
	    if (renderList != -1 && listContext == context) {
		SoGLTextureImageElement::set(
		    state, this, size, nc, bytes, renderList);
	    }
	    else {  // Not valid, try to build
		// Free up old list, if necessary:
		if (renderList != -1) {
		    SoGLCacheContextElement::freeList(state, listContext,
						      renderList, 1);
		}
		renderList = SoGLTextureImageElement::set(
		    state, this, size, nc, bytes, -1);
		listContext = context;
	    }
	}
    }
}