void VisualTextureContainer::applyConvolutionFilter(const VisualConvolutionFilter& aConvolutionFilter) {
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();

	uint16 dataType;
	uint16 pixelFormat = kGL_BGRA;
	// BGRA on intel machines and ARGB on ppc
#if TARGET_OS_WIN
	dataType = kGL_UNSIGNED_BYTE;
#else
#if __BIG_ENDIAN__
	dataType = kGL_UNSIGNED_INT_8_8_8_8_REV;
#else
	dataType = kGL_UNSIGNED_INT_8_8_8_8;
#endif
#endif
	
	if (theVisualGraphics->doesSupportGLConvolutionFilter()) {
		
		int prevReadBuffer = theVisualGraphics->getCurrentColorBufferForPixelReadingOperations();
		theVisualGraphics->setColorBufferForPixelReadingOperations(kGL_BACK_COLOR_BUFFER);
		
		int prevDrawBuffer = theVisualGraphics->getCurrentColorBufferForPixelDrawingOperations();
		theVisualGraphics->setColorBufferForPixelDrawingOperations(kGL_BACK_COLOR_BUFFER);
		
		uint32* prevPixels = NULL;
		
		char errStr[512];
		
		uint8 numberOfBytesPerChannel = 0;
		uint8 numberOfChannels = 0; // channel == color resp. alpha channel
		uint8 numberOfBytesPerPixel = 0;
		uint32 numberOfBytesPerRow = 0;
		if ((pixelFormat == kGL_RGBA) || (pixelFormat == kGL_BGRA)) {
			numberOfChannels = 4;
		} else {
			sprintf(errStr, "unknown format %d in file: %s (line: %d) [%s])", pixelFormat, __FILE__, __LINE__, __FUNCTION__);
			writeLog(errStr);
			return;
		}
		
		if ((dataType == kGL_UNSIGNED_INT_8_8_8_8_REV) || (dataType == kGL_UNSIGNED_INT_8_8_8_8) || (dataType == kGL_UNSIGNED_BYTE)) {
			numberOfBytesPerChannel = 1; // // 1 byte (== 8 bits) per color/channel
		} else {
			sprintf(errStr, "unknown type %d in file: %s (line: %d) [%s])", dataType, __FILE__, __LINE__, __FUNCTION__);
			writeLog(errStr);
			return;
		}
		
		numberOfBytesPerPixel = numberOfBytesPerChannel * numberOfChannels;
		numberOfBytesPerRow = numberOfBytesPerPixel * this->textureRect.width;
		
		// read previous pixels
		if ((pixelFormat == kGL_RGBA) || (pixelFormat == kGL_BGRA)) {
			prevPixels = (uint32*)calloc((numberOfBytesPerRow / numberOfBytesPerPixel) * this->textureRect.height, numberOfBytesPerPixel);
		}
		VisualCamera aCamera;
		aCamera.setOrthographicProjection();
		theVisualGraphics->readPixels(aCamera.getMaxLeftCoord(), aCamera.getMaxBottomCoord(), this->textureRect.width, this->textureRect.height, &prevPixels, pixelFormat, dataType, aCamera);
		
		PixelColor* pixels = NULL;
		pixels = this->createARGBImagePixels();
		if (pixels == NULL) {
			sprintf(errStr, "pixels == NULL in file: %s (line: %d) [%s])", __FILE__, __LINE__, __FUNCTION__);
			writeLog(errStr);
			return;
		}

		theVisualGraphics->drawPixels(&pixels, aCamera.getMaxLeftCoord(), aCamera.getMaxBottomCoord(), this->imageRect.width, this->imageRect.height, pixelFormat, dataType, &aConvolutionFilter);
		
		free(pixels);
		pixels = NULL;
		
		BottomLeftPositionedPixelRect clipRect;
		clipRect.bottomLeftPixel.x = 0;
		clipRect.bottomLeftPixel.y = 0;
		clipRect.pixelRect.width = this->textureRect.width;
		clipRect.pixelRect.height = this->textureRect.height;
		
		theVisualGraphics->enableTexturing(this->useRectExtension);
		theVisualGraphics->copyFramebufferToTexture(this->textureName, this->useRectExtension, clipRect, pixelFormat, dataType);
		theVisualGraphics->disableTexturing(this->useRectExtension);
		
		// restore previous pixels
		theVisualGraphics->drawPixels(&prevPixels, aCamera.getMaxLeftCoord(), aCamera.getMaxBottomCoord(), this->textureRect.width, this->textureRect.height, pixelFormat, dataType);
		
		free(prevPixels);
		
		theVisualGraphics->setColorBufferForPixelDrawingOperations(prevDrawBuffer);
		theVisualGraphics->setColorBufferForPixelReadingOperations(prevReadBuffer);
		
	} else {
		
		PixelColor* pixels = this->createARGBImagePixels();		
		PixelColor* filteredPixels = NULL;
		aConvolutionFilter.applyToPixelData(pixels, this->imageRect.width, this->imageRect.height, pixelFormat, dataType, &filteredPixels);
		free(pixels);
		pixels = NULL;
		bool success = false;
		const PixelColor* constFilteredPixels = const_cast<const PixelColor*>(filteredPixels);
		success = theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->imageRect.width, this->imageRect.height, this->useRectExtension, &constFilteredPixels);
		if (filteredPixels != NULL) {
			free(filteredPixels);
		}
	}
	
}
void VisualTextureContainer::applyConvolutionFilter(const VisualConvolutionFilter& aConvolutionFilter) {
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();

	int prevReadBuffer = theVisualGraphics->getCurrentColorBufferForPixelReadingOperations();
	theVisualGraphics->setColorBufferForPixelReadingOperations(kGL_BACK_COLOR_BUFFER);

	int prevDrawBuffer = theVisualGraphics->getCurrentColorBufferForPixelDrawingOperations();
	theVisualGraphics->setColorBufferForPixelDrawingOperations(kGL_BACK_COLOR_BUFFER);
	
	UInt32* prevPixels = NULL;

	char errStr[512];

	UInt8 numberOfBytesPerChannel = 0;
	UInt8 numberOfChannels = 0; // channel == color resp. alpha channel
	UInt8 numberOfBytesPerPixel = 0;
	UInt32 numberOfBytesPerRow = 0;
	if ((this->pixelFormat == kGL_RGBA) || (this->pixelFormat == kGL_BGRA)) {
		numberOfChannels = 4;
	} else {
		sprintf(errStr, "unknown format %d in file: %s (line: %d) [%s])", this->pixelFormat, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return;
	}
	
	if ((this->dataType == kGL_UNSIGNED_INT_8_8_8_8_REV) || (this->dataType == kGL_UNSIGNED_INT_8_8_8_8) || (this->dataType == kGL_UNSIGNED_BYTE)) {
		numberOfBytesPerChannel = 1; // // 1 byte (== 8 bits) per color/channel
	} else {
		sprintf(errStr, "unknown type %d in file: %s (line: %d) [%s])", this->dataType, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return;
	}
	
	numberOfBytesPerPixel = numberOfBytesPerChannel * numberOfChannels;
	numberOfBytesPerRow = numberOfBytesPerPixel * this->textureWidth;

	// read previous pixels
	if ((this->pixelFormat == kGL_RGBA) || (this->pixelFormat == kGL_BGRA)) {
		prevPixels = (UInt32*)calloc((numberOfBytesPerRow / numberOfBytesPerPixel) * this->textureHeight, numberOfBytesPerPixel);
	}
	theVisualGraphics->readPixels(theVisualGraphics->getMaxLeftCoordOfCanvas(), theVisualGraphics->getMaxBottomCoordOfCanvas(), this->textureWidth, this->textureHeight, &prevPixels, this->pixelFormat, this->dataType);

	UInt32* pixels = this->getTexturePixels(this->pixelFormat, this->dataType);
	UInt32* passedPixels = (UInt32*)malloc(this->textureWidth * this->textureHeight * 4);
	memcpy(passedPixels, pixels, this->textureWidth * this->textureHeight * 4); // VisualStudio does not like when we pass a non-const pointer to instance variable (crashes in runtime)
	theVisualGraphics->drawPixels((UInt32**)&(passedPixels), theVisualGraphics->getMaxLeftCoordOfCanvas(), theVisualGraphics->getMaxBottomCoordOfCanvas(), this->textureWidth, this->textureHeight, this->pixelFormat, this->dataType, &aConvolutionFilter);
	if (passedPixels != NULL) {
		free(passedPixels);
		passedPixels = NULL;
	}

	theVisualGraphics->copyFramebufferToTexture(this->textureName, this->useRectExtension, 0, 0, this->textureWidth, this->textureHeight, this->pixelFormat, this->dataType);

	// restore previous pixels
	theVisualGraphics->drawPixels(&prevPixels, theVisualGraphics->getMaxLeftCoordOfCanvas(), theVisualGraphics->getMaxBottomCoordOfCanvas(), this->textureWidth, this->textureHeight, this->pixelFormat, this->dataType);
	
	free(prevPixels);

	theVisualGraphics->setColorBufferForPixelDrawingOperations(prevDrawBuffer);
	theVisualGraphics->setColorBufferForPixelReadingOperations(prevReadBuffer);

	if (this->pixelBuffer != NULL) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}
	
}
PixelColor* VisualTextureContainer::createReadPixels(const uint16 format, const uint16 type) {
	
	PixelColor* pixels = NULL;
	PixelColor* prevPixels = NULL;
	
	char errStr[512];
	
	double scaleFactor = 1.0;
	
	uint8 numberOfBytesPerChannel = 0;
	uint8 numberOfChannels = 0; // channel == color resp. alpha channel
	uint8 numberOfBytesPerPixel = 0;
	uint32 numberOfBytesPerRow = 0;
	if ((format == kGL_RGBA) || (format == kGL_BGRA)) {
		numberOfChannels = 4;
	} else {
		sprintf(errStr, "unknown format %d in file: %s (line: %d) [%s])", format, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return pixels;
	}
	
	if ((type == kGL_UNSIGNED_INT_8_8_8_8_REV) || (type == kGL_UNSIGNED_INT_8_8_8_8) || (type == kGL_UNSIGNED_BYTE)) {
		numberOfBytesPerChannel = 1; // // 1 byte (== 8 bits) per color/channel
	} else {
		sprintf(errStr, "unknown type %d in file: %s (line: %d) [%s])", type, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return pixels;
	}
	
	numberOfBytesPerPixel = numberOfBytesPerChannel * numberOfChannels;
	numberOfBytesPerRow = numberOfBytesPerPixel * this->textureRect.width;
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	
	Coord coord;
	VisualCamera aCamera;
	aCamera.setOrthographicProjection();
	coord.x = aCamera.getMaxLeftCoord() * scaleFactor;
	coord.y = (aCamera.getMaxBottomCoord() + theVisualGraphics->yPixelToCoord(this->textureRect.height, aCamera)) * scaleFactor;
	coord.z = aCamera.getMaxNearPos();
	VertexChain aVertexChain;
	TexCoord texCoord;
	texCoord.s = 0.0;
	texCoord.t = this->getTextureLogicalHeight();
	VisualVertex* topLeftFrontVertex = new VisualVertex(coord, texCoord, white);
	aVertexChain.push_back(topLeftFrontVertex);
	
	coord.x = aCamera.getMaxLeftCoord() * scaleFactor;
	coord.y = aCamera.getMaxBottomCoord() * scaleFactor;
	coord.z = aCamera.getMaxNearPos();
	texCoord.s = 0.0;
	texCoord.t = 0.0;
	VisualVertex* bottomLeftFrontVertex = new VisualVertex(coord, texCoord, white);
	aVertexChain.push_back(bottomLeftFrontVertex);
	
	coord.x = (aCamera.getMaxLeftCoord() + theVisualGraphics->xPixelToCoord(this->textureRect.width, aCamera)) * scaleFactor;
	coord.y = aCamera.getMaxBottomCoord() * scaleFactor;
	coord.z = aCamera.getMaxNearPos();
	texCoord.s = this->getTextureLogicalWidth();
	texCoord.t = 0.0;
	VisualVertex* bottomRightFrontVertex = new VisualVertex(coord, texCoord, white);
	aVertexChain.push_back(bottomRightFrontVertex);
	
	coord.x = (aCamera.getMaxLeftCoord() + theVisualGraphics->xPixelToCoord(this->textureRect.width, aCamera)) * scaleFactor;
	coord.y = (aCamera.getMaxBottomCoord() + theVisualGraphics->yPixelToCoord(this->textureRect.height, aCamera)) * scaleFactor;
	coord.z = aCamera.getMaxNearPos();
	texCoord.s = this->getTextureLogicalWidth();
	texCoord.t = this->getTextureLogicalHeight();
	VisualVertex* topRightFrontVertex = new VisualVertex(coord, texCoord, white);
	aVertexChain.push_back(topRightFrontVertex);
	
	// read previous pixels
	if ((format == kGL_RGBA) || (format == kGL_BGRA)) {
		prevPixels = (uint32*)calloc((numberOfBytesPerRow / numberOfBytesPerPixel) * this->textureRect.height, numberOfBytesPerPixel);
	}
	theVisualGraphics->readPixels(aCamera.getMaxLeftCoord(), aCamera.getMaxBottomCoord(), this->textureRect.width, this->textureRect.height, &prevPixels, format, type, aCamera);
	
	// draw current texture
	theVisualGraphics->drawTexture(this->textureName, &aVertexChain, this->getUseRectExtension(), kReplace);
	
	// read pixels of current texture
	if ((format == kGL_RGBA) || (format == kGL_BGRA)) {
		pixels = (uint32*)calloc((numberOfBytesPerRow / numberOfBytesPerPixel) * this->textureRect.height, numberOfBytesPerPixel);
	}
	theVisualGraphics->readPixels(aCamera.getMaxLeftCoord(), aCamera.getMaxBottomCoord(), this->textureRect.width, this->textureRect.height, &pixels, format, type, aCamera);
	
	// restore previous pixels
	theVisualGraphics->drawPixels(&prevPixels, aCamera.getMaxLeftCoord(), aCamera.getMaxBottomCoord(), this->textureRect.width, this->textureRect.height, format, type);
	
	for (VertexChainIterator chainIt = aVertexChain.begin(); chainIt != aVertexChain.end(); chainIt++) {
		delete *chainIt;
		*chainIt = NULL;
	}
	aVertexChain.clear();
	
	free(prevPixels);
	
	return pixels;
}
UInt32* VisualTextureContainer::getRectPixels(const UInt16 format, const UInt16 type) {

	UInt32* pixels = NULL;
	UInt32* prevPixels = NULL;

	char errStr[512];
	
	double scaleFactor = 1.0;

	UInt8 numberOfBytesPerChannel = 0;
	UInt8 numberOfChannels = 0; // channel == color resp. alpha channel
	UInt8 numberOfBytesPerPixel = 0;
	UInt32 numberOfBytesPerRow = 0;
	if ((format == kGL_RGBA) || (format == kGL_BGRA)) {
		numberOfChannels = 4;
	} else {
		sprintf(errStr, "unknown format %d in file: %s (line: %d) [%s])", format, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return pixels;
	}
	
	if ((type == kGL_UNSIGNED_INT_8_8_8_8_REV) || (type == kGL_UNSIGNED_INT_8_8_8_8) || (type == kGL_UNSIGNED_BYTE)) {
		numberOfBytesPerChannel = 1; // // 1 byte (== 8 bits) per color/channel
	} else {
		sprintf(errStr, "unknown type %d in file: %s (line: %d) [%s])", type, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return pixels;
	}
	
	numberOfBytesPerPixel = numberOfBytesPerChannel * numberOfChannels;
	numberOfBytesPerRow = numberOfBytesPerPixel * this->textureWidth;

	VisualStageBox stageBox;

	VisualStagePosition position;
	position.horizontalAlignment = kLeftAligned;
	position.verticalAlignment = kBottomAligned;
	stageBox.setVisualStagePosition(position);

	stageBox.setContentPixelWidth(this->getImageWidth());
	stageBox.setContentPixelHeight(this->getImageHeight());

	VertexChain aVertexChain;
	Vertex* topLeftFrontVertex = new Vertex;
	topLeftFrontVertex->vertexPosition.xPos = stageBox.getLeftCoord() * scaleFactor;
	topLeftFrontVertex->vertexPosition.yPos = stageBox.getTopCoord() * scaleFactor;
	topLeftFrontVertex->vertexPosition.zPos = stageBox.getFrontPosition();
	topLeftFrontVertex->vertexColor.r = 1.0f;
	topLeftFrontVertex->vertexColor.g = 1.0f;
	topLeftFrontVertex->vertexColor.b = 1.0f;
	topLeftFrontVertex->vertexColor.a = 1.0f;
	topLeftFrontVertex->texCoordPosition.sPos = 0.0f;
	topLeftFrontVertex->texCoordPosition.tPos = this->getTextureLogicalHeight();
	aVertexChain.push_back(topLeftFrontVertex);

	Vertex* bottomLeftFrontVertex = new Vertex;
	bottomLeftFrontVertex->vertexPosition.xPos = stageBox.getLeftCoord() * scaleFactor;
	bottomLeftFrontVertex->vertexPosition.yPos = stageBox.getBottomCoord() * scaleFactor;
	bottomLeftFrontVertex->vertexPosition.zPos = stageBox.getFrontPosition();
	bottomLeftFrontVertex->vertexColor.r = 1.0f;
	bottomLeftFrontVertex->vertexColor.g = 1.0f;
	bottomLeftFrontVertex->vertexColor.b = 1.0f;
	bottomLeftFrontVertex->vertexColor.a = 1.0f;
	bottomLeftFrontVertex->texCoordPosition.sPos = 0.0f;
	bottomLeftFrontVertex->texCoordPosition.tPos = 0.0f;
	aVertexChain.push_back(bottomLeftFrontVertex);

	Vertex* bottomRightFrontVertex = new Vertex;
	bottomRightFrontVertex->vertexPosition.xPos = stageBox.getRightCoord() * scaleFactor;
	bottomRightFrontVertex->vertexPosition.yPos = stageBox.getBottomCoord() * scaleFactor;
	bottomRightFrontVertex->vertexPosition.zPos = stageBox.getFrontPosition();
	bottomRightFrontVertex->vertexColor.r = 1.0f;
	bottomRightFrontVertex->vertexColor.g = 1.0f;
	bottomRightFrontVertex->vertexColor.b = 1.0f;
	bottomRightFrontVertex->vertexColor.a = 1.0f;
	bottomRightFrontVertex->texCoordPosition.sPos = this->getTextureLogicalWidth();
	bottomRightFrontVertex->texCoordPosition.tPos = 0.0f;
	aVertexChain.push_back(bottomRightFrontVertex);

	Vertex* topRightFrontVertex = new Vertex;
	topRightFrontVertex->vertexPosition.xPos = stageBox.getRightCoord() * scaleFactor;
	topRightFrontVertex->vertexPosition.yPos = stageBox.getTopCoord() * scaleFactor;
	topRightFrontVertex->vertexPosition.zPos = stageBox.getFrontPosition();
	topRightFrontVertex->vertexColor.r = 1.0f;
	topRightFrontVertex->vertexColor.g = 1.0f;
	topRightFrontVertex->vertexColor.b = 1.0f;
	topRightFrontVertex->vertexColor.a = 1.0f;
	topRightFrontVertex->texCoordPosition.sPos = this->getTextureLogicalWidth();
	topRightFrontVertex->texCoordPosition.tPos = this->getTextureLogicalHeight();
	aVertexChain.push_back(topRightFrontVertex);

	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	
	// read previous pixels
	if ((format == kGL_RGBA) || (format == kGL_BGRA)) {
		prevPixels = (UInt32*)calloc((numberOfBytesPerRow / numberOfBytesPerPixel) * this->textureHeight, numberOfBytesPerPixel);
	}
	theVisualGraphics->readPixels(stageBox.getLeftCoord(), stageBox.getBottomCoord(), this->textureWidth, this->textureHeight, &prevPixels, format, type);

	// draw current texture
	theVisualGraphics->drawTexture(this->textureName, &aVertexChain, this->getUseRectExtension(), kReplace);

	// read pixels of current texture
	if ((format == kGL_RGBA) || (format == kGL_BGRA)) {
		pixels = (UInt32*)calloc((numberOfBytesPerRow / numberOfBytesPerPixel) * this->textureHeight, numberOfBytesPerPixel);
	}
	theVisualGraphics->readPixels(stageBox.getLeftCoord(), stageBox.getBottomCoord(), this->textureWidth, this->textureHeight, &pixels, format, type);

	// restore previous pixels
	theVisualGraphics->drawPixels(&prevPixels, stageBox.getLeftCoord(), stageBox.getBottomCoord(), this->textureWidth, this->textureHeight, format, type);

	for (VertexChainIterator chainIt = aVertexChain.begin(); chainIt != aVertexChain.end(); chainIt++) {
		delete *chainIt;
		*chainIt = NULL;
	}
	aVertexChain.clear();

	free(prevPixels);
	
	return pixels;
}