OpenGL ES environment texture partial implementation

Change-Id: I0dcce9f2659cfdde8cc4d5a0a541bea7728b3f97
Reviewed-on: https://swiftshader-review.googlesource.com/1850
Tested-by: Maxime Grégoire <mgregoire@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp
index 653933e..ba0025a 100644
--- a/src/OpenGL/libGLES_CM/Context.cpp
+++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -103,6 +103,8 @@
     mState.colorMaskAlpha = true;

     mState.depthMask = true;

 

+	mState.textureEnvMode = GL_MODULATE;

+

     if(shareContext != NULL)

     {

         mResourceManager = shareContext->mResourceManager;

@@ -1757,7 +1759,9 @@
 

 void Context::applyTextures()

 {

-    for(int samplerIndex = 0; samplerIndex < MAX_TEXTURE_UNITS; samplerIndex++)

+	GLenum texEnvMode = getTextureEnvMode();

+

+	for(int samplerIndex = 0; samplerIndex < MAX_TEXTURE_UNITS; samplerIndex++)

     {

         Texture *texture = getSamplerTexture(samplerIndex, TEXTURE_2D);

 

@@ -1784,29 +1788,57 @@
 

 			applyTexture(samplerIndex, texture);

 

-			device->setStageOperation(samplerIndex, sw::TextureStage::STAGE_MODULATE);

-            device->setFirstArgument(samplerIndex, sw::TextureStage::SOURCE_TEXTURE);

-            device->setSecondArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			GLenum texFormat = texture->getFormat(GL_TEXTURE_2D, 0);

+			sw::TextureStage::StageOperation rgbOperation, alphaOperation;

+			es2sw::ConvertTextureOperations(texEnvMode, texFormat, &rgbOperation, &alphaOperation);

 

-            device->setStageOperationAlpha(samplerIndex, sw::TextureStage::STAGE_MODULATE);

-            device->setFirstArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_TEXTURE);

-            device->setSecondArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setStageOperation(samplerIndex, rgbOperation);

+            device->setFirstArgument(samplerIndex, sw::TextureStage::SOURCE_TEXTURE);

+			device->setFirstModifier(samplerIndex, sw::TextureStage::MODIFIER_COLOR);

+			device->setSecondArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setSecondModifier(samplerIndex, sw::TextureStage::MODIFIER_COLOR);

+

+            device->setStageOperationAlpha(samplerIndex, alphaOperation);

+			device->setFirstArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_TEXTURE);

+			device->setFirstModifierAlpha(samplerIndex, sw::TextureStage::MODIFIER_ALPHA);

+			device->setSecondArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setSecondModifierAlpha(samplerIndex, sw::TextureStage::MODIFIER_ALPHA);

         }

         else

         {

             applyTexture(samplerIndex, 0);

 

 			device->setStageOperation(samplerIndex, sw::TextureStage::STAGE_SELECTARG1);

-            device->setFirstArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

-            device->setSecondArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setFirstArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setFirstModifier(samplerIndex, sw::TextureStage::MODIFIER_COLOR);

+			device->setSecondArgument(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setSecondModifier(samplerIndex, sw::TextureStage::MODIFIER_COLOR);

 

             device->setStageOperationAlpha(samplerIndex, sw::TextureStage::STAGE_SELECTARG1);

-            device->setFirstArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

-            device->setSecondArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setFirstArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setFirstModifierAlpha(samplerIndex, sw::TextureStage::MODIFIER_ALPHA);

+			device->setSecondArgumentAlpha(samplerIndex, sw::TextureStage::SOURCE_CURRENT);

+			device->setSecondModifierAlpha(samplerIndex, sw::TextureStage::MODIFIER_ALPHA);

         }

     }

 }

 

+void Context::setTextureEnvMode(GLenum texEnvMode)

+{

+	switch(texEnvMode)

+	{

+	case GL_MODULATE:

+	case GL_DECAL:

+	case GL_BLEND:

+	case GL_ADD:

+	case GL_REPLACE:

+		mState.textureEnvMode = texEnvMode;

+		break;

+	default:

+		UNREACHABLE();

+	}

+}

+

 void Context::applyTexture(int index, Texture *baseTexture)

 {

 	sw::Resource *resource = 0;

@@ -2633,6 +2665,11 @@
 	return mState.activeSampler;

 }

 

+GLenum Context::getTextureEnvMode()

+{

+	return mState.textureEnvMode;

+}

+

 }

 

 // Exported functions for use by EGL

diff --git a/src/OpenGL/libGLES_CM/Context.h b/src/OpenGL/libGLES_CM/Context.h
index 58af663..cdffd6f 100644
--- a/src/OpenGL/libGLES_CM/Context.h
+++ b/src/OpenGL/libGLES_CM/Context.h
@@ -252,6 +252,8 @@
 

     GLint unpackAlignment;

     GLint packAlignment;

+

+	GLenum textureEnvMode;

 };

 

 class Context : public egl::Context

@@ -326,6 +328,9 @@
 	GLenum getClientActiveTexture() const;

 	unsigned int getActiveTexture() const;

 

+	void setTextureEnvMode(GLenum texEnvMode);

+	GLenum getTextureEnvMode();

+

     void setLineWidth(GLfloat width);

 

     void setGenerateMipmapHint(GLenum hint);

diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
index c4a9283..3cac667 100644
--- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp
+++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
@@ -3269,7 +3269,85 @@
 

 void GL_APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param)

 {

-	UNIMPLEMENTED();

+	es1::Context *context = es1::getContext();

+	if(context)

+	{

+		switch(target)

+		{

+		case GL_POINT_SPRITE_OES:

+			UNIMPLEMENTED();

+			break;

+		case GL_TEXTURE_ENV:

+			switch(pname)

+			{

+			case GL_TEXTURE_ENV_MODE:

+				switch((GLenum)param)

+				{

+				case GL_REPLACE:

+				case GL_MODULATE:

+				case GL_DECAL:

+				case GL_BLEND:

+				case GL_ADD:

+				case GL_COMBINE:

+					break;

+				default:

+					error(GL_INVALID_ENUM);

+				}

+

+				context->setTextureEnvMode((GLenum)param);

+				break;

+			case GL_TEXTURE_ENV_COLOR:

+				UNIMPLEMENTED();

+				break;

+			case GL_COMBINE_RGB:

+				switch((GLenum)param)

+				{

+				case GL_REPLACE:

+					UNIMPLEMENTED();

+					break;

+				case GL_MODULATE:

+					UNIMPLEMENTED();

+					break;

+				case GL_ADD:

+					context->setTextureEnvMode((GLenum)param);	

+					break;

+				case GL_ADD_SIGNED:

+					UNIMPLEMENTED();

+					break;

+				case GL_INTERPOLATE:

+					UNIMPLEMENTED();

+					break;

+				case GL_SUBTRACT:

+					UNIMPLEMENTED();

+					break;

+				case GL_DOT3_RGB:

+					UNIMPLEMENTED();

+					break;

+				case GL_DOT3_RGBA:

+					UNIMPLEMENTED();

+					break;

+				default:

+					error(GL_INVALID_ENUM);

+				}

+

+				break;

+			case GL_COMBINE_ALPHA:

+				UNIMPLEMENTED();

+				break;

+			case GL_RGB_SCALE:

+				UNIMPLEMENTED();

+				break;

+			case GL_ALPHA_SCALE:

+				UNIMPLEMENTED();

+				break;

+			default:

+				return error(GL_INVALID_ENUM);

+			}

+			break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+	}	

 }

 

 void GL_APIENTRY glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params)

@@ -3279,7 +3357,7 @@
 

 void GL_APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param)

 {

-	UNIMPLEMENTED();

+	glTexEnvf(target, pname, (float)param);

 }

 

 void GL_APIENTRY glTexEnvx(GLenum target, GLenum pname, GLfixed param)

diff --git a/src/OpenGL/libGLES_CM/utilities.cpp b/src/OpenGL/libGLES_CM/utilities.cpp
index c275089..d91d5ca 100644
--- a/src/OpenGL/libGLES_CM/utilities.cpp
+++ b/src/OpenGL/libGLES_CM/utilities.cpp
@@ -467,6 +467,59 @@
 		default: UNREACHABLE();       return sw::FORMAT_A8R8G8B8;

 		}

 	}

+

+	void ConvertTextureOperations(GLenum texEnvMode, GLenum texFormat, sw::TextureStage::StageOperation *rgbOperation, sw::TextureStage::StageOperation *alphaOperation)

+	{

+		switch(texEnvMode)

+		{

+		case GL_MODULATE:

+			switch(texFormat)

+			{

+			case GL_LUMINANCE_ALPHA:

+				*rgbOperation = sw::TextureStage::STAGE_MODULATE;

+				*alphaOperation = sw::TextureStage::STAGE_MODULATE;

+				break;

+			case GL_RGB:

+				*rgbOperation = sw::TextureStage::STAGE_MODULATE;

+				*alphaOperation = sw::TextureStage::STAGE_SELECTARG2;

+				break;

+			case GL_RGBA:

+				*rgbOperation = sw::TextureStage::STAGE_MODULATE;

+				*alphaOperation = sw::TextureStage::STAGE_MODULATE;

+				break;

+			case GL_ALPHA:

+			case GL_LUMINANCE:

+				UNIMPLEMENTED();

+				// Default operations for compatibility

+				*rgbOperation = sw::TextureStage::STAGE_MODULATE;

+				*alphaOperation = sw::TextureStage::STAGE_MODULATE;

+				break;

+			default: UNREACHABLE();

+			}

+			break;

+

+		case GL_REPLACE:

+			*rgbOperation = sw::TextureStage::STAGE_SELECTARG1;

+			*alphaOperation = sw::TextureStage::STAGE_SELECTARG1;

+			break;

+

+		case GL_ADD:

+			*rgbOperation = sw::TextureStage::STAGE_ADD;

+			*alphaOperation = sw::TextureStage::STAGE_SELECTARG1;

+			break; 

+

+		case GL_DECAL:

+		case GL_BLEND:

+			// Default operations for compatibility

+			*rgbOperation = sw::TextureStage::STAGE_MODULATE;

+			*alphaOperation = sw::TextureStage::STAGE_MODULATE;

+			UNIMPLEMENTED();

+			break;

+

+		default:

+			UNREACHABLE();

+		}

+	}

 }

 

 namespace sw2es

diff --git a/src/OpenGL/libGLES_CM/utilities.h b/src/OpenGL/libGLES_CM/utilities.h
index 4f6421f..c64d600 100644
--- a/src/OpenGL/libGLES_CM/utilities.h
+++ b/src/OpenGL/libGLES_CM/utilities.h
@@ -61,6 +61,7 @@
 	void ConvertMinFilter(GLenum texFilter, sw::FilterType *minFilter, sw::MipmapType *mipFilter, float maxAnisotropy);

 	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,  es1::PrimitiveType &swPrimitiveType, int &primitiveCount);

 	sw::Format ConvertRenderbufferFormat(GLenum format);

+	void ConvertTextureOperations(GLenum texOperation, GLenum texFormat, sw::TextureStage::StageOperation *rgbOperation, sw::TextureStage::StageOperation *alphaOperation);

 }

 

 namespace sw2es