Update cube texture borders when dirty.

Change-Id: Ic259645ab7950b0b2800964bbfd14f3294de50b1
Reviewed-on: https://swiftshader-review.googlesource.com/14288
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/D3D9/Direct3DCubeTexture9.cpp b/src/D3D9/Direct3DCubeTexture9.cpp
index b0b1925..7d34786 100644
--- a/src/D3D9/Direct3DCubeTexture9.cpp
+++ b/src/D3D9/Direct3DCubeTexture9.cpp
@@ -191,7 +191,7 @@
 
 		for(unsigned int face = 0; face < 6; face++)
 		{
-			if(!surfaceLevel[face][0]->hasDirtyMipmaps())
+			if(!surfaceLevel[face][0]->hasDirtyContents())
 			{
 				continue;
 			}
@@ -201,7 +201,7 @@
 				device->stretchRect(surfaceLevel[face][i], 0, surfaceLevel[face][i + 1], 0, GetAutoGenFilterType());
 			}
 
-			surfaceLevel[face][0]->cleanMipmaps();
+			surfaceLevel[face][0]->markContentsClean();
 		}
 
 		resource->unlock();
diff --git a/src/D3D9/Direct3DTexture9.cpp b/src/D3D9/Direct3DTexture9.cpp
index a964782..079fba7 100644
--- a/src/D3D9/Direct3DTexture9.cpp
+++ b/src/D3D9/Direct3DTexture9.cpp
@@ -173,7 +173,7 @@
 
 		TRACE("");
 
-		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !surfaceLevel[0]->hasDirtyMipmaps())
+		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !surfaceLevel[0]->hasDirtyContents())
 		{
 			return;
 		}
@@ -185,7 +185,7 @@
 			device->stretchRect(surfaceLevel[i], 0, surfaceLevel[i + 1], 0, GetAutoGenFilterType());
 		}
 
-		surfaceLevel[0]->cleanMipmaps();
+		surfaceLevel[0]->markContentsClean();
 
 		resource->unlock();
 	}
diff --git a/src/D3D9/Direct3DVolumeTexture9.cpp b/src/D3D9/Direct3DVolumeTexture9.cpp
index 35caf43..c9024d1 100644
--- a/src/D3D9/Direct3DVolumeTexture9.cpp
+++ b/src/D3D9/Direct3DVolumeTexture9.cpp
@@ -174,7 +174,7 @@
 
 		TRACE("");
 
-		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !volumeLevel[0]->hasDirtyMipmaps())
+		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !volumeLevel[0]->hasDirtyContents())
 		{
 			return;
 		}
@@ -230,7 +230,7 @@
 			dest->unlockInternal();
 		}
 
-		volumeLevel[0]->cleanMipmaps();
+		volumeLevel[0]->markContentsClean();
 
 		resource->unlock();
 	}
diff --git a/src/OpenGL/libGLES_CM/Texture.cpp b/src/OpenGL/libGLES_CM/Texture.cpp
index 18e9fbf..eba8f78 100644
--- a/src/OpenGL/libGLES_CM/Texture.cpp
+++ b/src/OpenGL/libGLES_CM/Texture.cpp
@@ -720,10 +720,10 @@
 
 void Texture2D::autoGenerateMipmaps()
 {
-	if(generateMipmap && image[0]->hasDirtyMipmaps())
+	if(generateMipmap && image[0]->hasDirtyContents())
 	{
 		generateMipmaps();
-		image[0]->cleanMipmaps();
+		image[0]->markContentsClean();
 	}
 }
 
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 455508b..2a80871 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3233,11 +3233,13 @@
 		}
 		else if(baseTexture->getTarget() == GL_TEXTURE_CUBE_MAP)
 		{
-			for(int face = 0; face < 6; face++)
-			{
-				TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);
+			TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);
 
-				for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
+			for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
+			{
+				cubeTexture->updateBorders(mipmapLevel);
+
+				for(int face = 0; face < 6; face++)
 				{
 					int surfaceLevel = mipmapLevel;
 
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index 273c7ad..ff58214 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -1260,6 +1260,16 @@
 		return;
 	}
 
+	if(posX->getBorder() == 0)   // Non-seamless cube map.
+	{
+		return;
+	}
+
+	if(!posX->hasDirtyContents() || !posY->hasDirtyContents() || !posZ->hasDirtyContents() || !negX->hasDirtyContents() || !negY->hasDirtyContents() || !negY->hasDirtyContents())
+	{
+		return;
+	}
+
 	// Copy top / bottom first.
 	posX->copyCubeEdge(sw::Surface::BOTTOM, negY, sw::Surface::RIGHT);
 	posY->copyCubeEdge(sw::Surface::BOTTOM, posZ, sw::Surface::TOP);
@@ -1290,6 +1300,13 @@
 	negX->copyCubeEdge(sw::Surface::LEFT, negZ, sw::Surface::RIGHT);
 	negY->copyCubeEdge(sw::Surface::LEFT, negX, sw::Surface::BOTTOM);
 	negZ->copyCubeEdge(sw::Surface::LEFT, posX, sw::Surface::RIGHT);
+
+	posX->markContentsClean();
+	posY->markContentsClean();
+	posZ->markContentsClean();
+	negX->markContentsClean();
+	negY->markContentsClean();
+	negY->markContentsClean();
 }
 
 bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index 3533d25..12d990a 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -1249,7 +1249,7 @@
 		stencil.lock = LOCK_UNLOCKED;
 		stencil.dirty = false;
 
-		dirtyMipmaps = true;
+		dirtyContents = true;
 		paletteUsed = 0;
 	}
 
@@ -1302,7 +1302,7 @@
 		stencil.lock = LOCK_UNLOCKED;
 		stencil.dirty = false;
 
-		dirtyMipmaps = true;
+		dirtyContents = true;
 		paletteUsed = 0;
 	}
 
@@ -1367,7 +1367,7 @@
 		case LOCK_WRITEONLY:
 		case LOCK_READWRITE:
 		case LOCK_DISCARD:
-			dirtyMipmaps = true;
+			dirtyContents = true;
 			break;
 		default:
 			ASSERT(false);
@@ -1446,7 +1446,7 @@
 		case LOCK_WRITEONLY:
 		case LOCK_READWRITE:
 		case LOCK_DISCARD:
-			dirtyMipmaps = true;
+			dirtyContents = true;
 			break;
 		default:
 			ASSERT(false);
@@ -3649,14 +3649,14 @@
 		return renderTarget;
 	}
 
-	bool Surface::hasDirtyMipmaps() const
+	bool Surface::hasDirtyContents() const
 	{
-		return dirtyMipmaps;
+		return dirtyContents;
 	}
 
-	void Surface::cleanMipmaps()
+	void Surface::markContentsClean()
 	{
-		dirtyMipmaps = false;
+		dirtyContents = false;
 	}
 
 	Resource *Surface::getResource()
diff --git a/src/Renderer/Surface.hpp b/src/Renderer/Surface.hpp
index 4de2b33..fbfe063 100644
--- a/src/Renderer/Surface.hpp
+++ b/src/Renderer/Surface.hpp
@@ -248,7 +248,7 @@
 			Format format;
 			AtomicInt lock;
 
-			bool dirty;
+			bool dirty;   // Sibling internal/external buffer doesn't match.
 		};
 
 	protected:
@@ -326,8 +326,8 @@
 		bool hasPalette() const;
 		bool isRenderTarget() const;
 
-		bool hasDirtyMipmaps() const;
-		void cleanMipmaps();
+		bool hasDirtyContents() const;
+		void markContentsClean();
 		inline bool isExternalDirty() const;
 		Resource *getResource();
 
@@ -474,7 +474,7 @@
 		const bool lockable;
 		const bool renderTarget;
 
-		bool dirtyMipmaps;
+		bool dirtyContents;   // Sibling surfaces need updating (mipmaps / cube borders).
 		unsigned int paletteUsed;
 
 		static unsigned int *palette;   // FIXME: Not multi-device safe