diff --git a/plugins/GSdx/GSDrawingContext.h b/plugins/GSdx/GSDrawingContext.h
index ef54e543d6..7f76434278 100644
--- a/plugins/GSdx/GSDrawingContext.h
+++ b/plugins/GSdx/GSDrawingContext.h
@@ -125,6 +125,88 @@ public:
 		return ZBUF.ZMSK == 0 && TEST.ZTE != 0; // ZTE == 0 is bug on the real hardware, write is blocked then
 	}
 
+	GIFRegTEX0 GetSizeFixedTEX0(const GSVector4i& uvmax, bool mipmap)
+	{
+		// find max value for TW/TH by analyzing vertex trace and clamp values, only for region clamp modes, no mipmaping allowed
+
+		if(mipmap) return TEX0;
+
+		int tw = TEX0.TW;
+		int th = TEX0.TH;
+
+		int wms = (int)CLAMP.WMS;
+		int wmt = (int)CLAMP.WMT;
+
+		int minu = (int)CLAMP.MINU;
+		int minv = (int)CLAMP.MINV;
+		int maxu = (int)CLAMP.MAXU;
+		int maxv = (int)CLAMP.MAXV;
+
+		GSVector4i uv = uvmax;// GSVector4i(m_vt.m_max.t.ceil());
+
+		if(wms == CLAMP_REGION_CLAMP)
+		{
+			int x = uv.x;
+
+			if(x < minu) x = minu;
+			if(x > maxu + 1) x = maxu + 1;
+
+			while(tw < 10 && (1 << tw) < x)
+			{
+				tw++;
+			}
+		}
+		else if(wms == CLAMP_REGION_REPEAT)
+		{
+			int x = maxu + (minu + 1);
+
+			while(tw < 10 && (1 << tw) < x)
+			{
+				tw++;
+			}
+		}
+
+		if(wmt == CLAMP_REGION_CLAMP)
+		{
+			int y = uv.y;
+
+			if(y < minv) y = minv;
+			if(y > maxv + 1) y = maxv + 1;
+
+			while(th < 10 && (1 << th) < y)
+			{
+				th++;
+			}
+		}
+		else if(wmt == CLAMP_REGION_REPEAT)
+		{
+			int y = maxv + (minv + 1);
+
+			while(th < 10 && (1 << th) < y)
+			{
+				th++;
+			}
+		}
+
+#ifdef _DEBUG
+		if(TEX0.TW != tw || TEX0.TH != th)
+		{
+			printf("FixedTEX0 %05x %d %d tw %d=>%d th %d=>%d uvmax %d,%d wm %d,%d (%d,%d,%d,%d)\n",
+				(int)TEX0.TBP0, (int)TEX0.TBW, (int)TEX0.PSM,
+				(int)TEX0.TW, tw, (int)TEX0.TH, th,
+				uv.x, uv.y,
+				wms, wmt, minu, maxu, minv, maxv);
+		}
+#endif
+
+		GIFRegTEX0 res = TEX0;
+
+		res.TW = tw;
+		res.TH = th;
+
+		return res;
+	}
+
 	void Dump(const std::string& filename)
 	{
 		// Append on purpose so env + context are merged into a single file
diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp
index 64a9b8f027..a246ad472a 100644
--- a/plugins/GSdx/GSRenderer.cpp
+++ b/plugins/GSdx/GSRenderer.cpp
@@ -40,7 +40,6 @@ GSRenderer::GSRenderer()
 	m_filter = theApp.GetConfig("filter", 1);
 	m_vsync = !!theApp.GetConfig("vsync", 0);
 	m_aa1 = !!theApp.GetConfig("aa1", 0);
-	m_mipmap = !!theApp.GetConfig("mipmap", 1);
 	m_fxaa = !!theApp.GetConfig("fxaa", 0);
 	m_shaderfx = !!theApp.GetConfig("shaderfx", 0);
 	m_shadeboost = !!theApp.GetConfig("ShadeBoost", 0);
diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h
index 64f82e3d37..332a7aa0b5 100644
--- a/plugins/GSdx/GSRenderer.h
+++ b/plugins/GSdx/GSRenderer.h
@@ -45,7 +45,6 @@ protected:
 	int m_filter;
 	bool m_vsync;
 	bool m_aa1;
-	bool m_mipmap;
 	bool m_framelimit;
 	bool m_shaderfx;
 	bool m_fxaa;
diff --git a/plugins/GSdx/GSRendererCL.cpp b/plugins/GSdx/GSRendererCL.cpp
index e3e4224803..960bf657c7 100644
--- a/plugins/GSdx/GSRendererCL.cpp
+++ b/plugins/GSdx/GSRendererCL.cpp
@@ -1440,9 +1440,15 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver
 				sel.tfx = TFX_DECAL;
 			}
 
+			GSVector4i uvmax = GSVector4i(m_vt.m_max.t.ceil());
+
+			bool mipmap = IsMipMapActive();
+
+			GIFRegTEX0 TEX0 = m_context->GetSizeFixedTEX0(uvmax, mipmap);
+
 			GSVector4i r;
 
-			GetTextureMinMax(r, context->TEX0, context->CLAMP, sel.ltf);
+			GetTextureMinMax(r, TEX0, context->CLAMP, sel.ltf);
 
 			GSVector4i* src_pages = job->GetSrcPages();
 
@@ -1455,7 +1461,7 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver
 				src_pages[i] |= m_tmp_pages[i];
 			}
 
-			if(m_mipmap && context->TEX1.MXL > 0 && context->TEX1.MMIN >= 2 && context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0)
+			if(mipmap)
 			{
 				// TEX1.MMIN
 				// 000 p
@@ -1521,7 +1527,7 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver
 					pb->k = (float)k;
 				}
 
-				GIFRegTEX0 MIP_TEX0 = context->TEX0;
+				GIFRegTEX0 MIP_TEX0 = TEX0;
 				GIFRegCLAMP MIP_CLAMP = context->CLAMP;
 
 				GSVector4 tmin = m_vt.m_min.t;
@@ -1638,8 +1644,8 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver
 				}
 			}
 
-			int tw = 1 << context->TEX0.TW;
-			int th = 1 << context->TEX0.TH;
+			int tw = 1 << TEX0.TW;
+			int th = 1 << TEX0.TH;
 
 			switch(context->CLAMP.WMS)
 			{
diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp
index 43bc1d5db9..44bde051a1 100644
--- a/plugins/GSdx/GSRendererSW.cpp
+++ b/plugins/GSdx/GSRendererSW.cpp
@@ -1121,19 +1121,25 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
 				gd.sel.tfx = TFX_DECAL;
 			}
 
-			GSTextureCacheSW::Texture* t = m_tc->Lookup(context->TEX0, env.TEXA);
+			GSVector4i uvmax = GSVector4i(m_vt.m_max.t.ceil());
 
-			if(t == NULL) {ASSERT(0); return false;}
+			bool mipmap = IsMipMapActive();
+
+			GIFRegTEX0 TEX0 = m_context->GetSizeFixedTEX0(uvmax, mipmap);
 
 			GSVector4i r;
 
-			GetTextureMinMax(r, context->TEX0, context->CLAMP, gd.sel.ltf);
+			GetTextureMinMax(r, TEX0, context->CLAMP, gd.sel.ltf);
+
+			GSTextureCacheSW::Texture* t = m_tc->Lookup(TEX0, env.TEXA);
+
+			if(t == NULL) {ASSERT(0); return false;}
 
 			data->SetSource(t, r, 0);
 
 			gd.sel.tw = t->m_tw - 3;
 
-			if(m_mipmap && context->TEX1.MXL > 0 && context->TEX1.MMIN >= 2 && context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0)
+			if(mipmap)
 			{
 				// TEX1.MMIN
 				// 000 p
@@ -1200,7 +1206,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
 					gd.k = GSVector4((float)k);
 				}
 
-				GIFRegTEX0 MIP_TEX0 = context->TEX0;
+				GIFRegTEX0 MIP_TEX0 = TEX0;
 				GIFRegCLAMP MIP_CLAMP = context->CLAMP;
 
 				GSVector4 tmin = m_vt.m_min.t;
@@ -1329,8 +1335,8 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
 				}
 			}
 
-			uint16 tw = 1u << context->TEX0.TW;
-			uint16 th = 1u << context->TEX0.TH;
+			uint16 tw = 1u << TEX0.TW;
+			uint16 th = 1u << TEX0.TH;
 
 			switch(context->CLAMP.WMS)
 			{
diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp
index be60ef2b97..f14186b3cf 100644
--- a/plugins/GSdx/GSState.cpp
+++ b/plugins/GSdx/GSState.cpp
@@ -47,6 +47,7 @@ GSState::GSState()
 	, m_crcinited(false)
 {
 	m_nativeres = !!theApp.GetConfig("nativeres", 1);
+	m_mipmap = !!theApp.GetConfig("mipmap", 1);
 
 	s_n     = 0;
 	s_dump  = !!theApp.GetConfig("dump", 0);
@@ -2713,6 +2714,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR
 		int mask = 0;
 
 		// See commented code below for the meaning of mask
+
 		if(wms == CLAMP_REPEAT || wmt == CLAMP_REPEAT)
 		{
 			u = uv & GSVector4i::xffffffff().srl32(32 - tw);
@@ -2985,6 +2987,11 @@ bool GSState::IsOpaque()
 	return context->ALPHA.IsOpaque(amin, amax);
 }
 
+bool GSState::IsMipMapActive()
+{
+	return m_mipmap && m_context->TEX1.MXL > 0 && m_context->TEX1.MMIN >= 2 && m_context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0; 
+}
+
 // GSTransferBuffer
 
 GSState::GSTransferBuffer::GSTransferBuffer()
diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h
index 9c155a739c..6a9954464a 100644
--- a/plugins/GSdx/GSState.h
+++ b/plugins/GSdx/GSState.h
@@ -184,6 +184,7 @@ protected:
 	void GetAlphaMinMax();
 	bool TryAlphaTest(uint32& fm, uint32& zm);
 	bool IsOpaque();
+	bool IsMipMapActive();
 
 public:
 	GIFPath m_path[4];
@@ -201,6 +202,7 @@ public:
 	CRC::Game m_game;
 	GSDump m_dump;
 	bool m_nativeres;
+	bool m_mipmap;
 
 	int s_n;
 	bool s_dump;