using System;
using System.Runtime.InteropServices;
using OpenTK.Graphics.OpenGL;

namespace SharpQuake
{
	internal static class Drawer
	{
		public static PixelInternalFormat AlphaFormat
		{
			get
			{
				return Drawer._AlphaFormat;
			}
		}

		public static PixelInternalFormat SolidFormat
		{
			get
			{
				return Drawer._SolidFormat;
			}
		}

		public static glpic_t Disc
		{
			get
			{
				return Drawer._Disc;
			}
		}

		public static float glMaxSize
		{
			get
			{
				return Drawer._glMaxSize.Value;
			}
		}

		public static void Init()
		{
			for (int i = 0; i < Drawer._MenuCachePics.Length; i++)
			{
				Drawer._MenuCachePics[i] = new cachepic_t();
			}
			if (Drawer._glNoBind == null)
			{
				Drawer._glNoBind = new cvar("gl_nobind", "0");
				Drawer._glMaxSize = new cvar("gl_max_size", "1024");
				Drawer._glPicMip = new cvar("gl_picmip", "0");
			}
			string @string = GL.GetString(StringName.Renderer);
			if (@string.Contains("3dfx") || @string.Contains("Glide"))
			{
				cvar.Set("gl_max_size", "256");
			}
			cmd.Add("gl_texturemode", new xcommand_t(Drawer.TextureMode_f));
			cmd.Add("imagelist", new xcommand_t(Drawer.Imagelist_f));
			int lumpNameOffset = wad.GetLumpNameOffset("conchars");
			byte[] data = wad.Data;
			for (int j = 0; j < 16384; j++)
			{
				if (data[lumpNameOffset + j] == 0)
				{
					data[lumpNameOffset + j] = byte.MaxValue;
				}
			}
			Drawer._CharTexture = Drawer.LoadTexture("charset", 128, 128, new ByteArraySegment(data, lumpNameOffset), false, true, "");
			byte[] array = common.LoadFile("gfx/conback.lmp");
			if (array == null)
			{
				sys.Error("Couldn't load gfx/conback.lmp", Array.Empty<object>());
			}
			dqpicheader_t dqpicheader_t = sys.BytesToStructure<dqpicheader_t>(array, 0);
			wad.SwapPic(dqpicheader_t);
			string text = string.Format("(c# {0,7:F2}) {1,7:F2}", 1.2f, 1.09f);
			int num = Marshal.SizeOf(typeof(dqpicheader_t)) + 59520 + 320 - 11 - 8 * text.Length;
			int length = text.Length;
			for (int k = 0; k < length; k++)
			{
				Drawer.CharToConback((int)text[k], new ByteArraySegment(array, num + (k << 3)), new ByteArraySegment(data, lumpNameOffset));
			}
			Drawer._ConBack = new glpic_t();
			Drawer._ConBack.width = dqpicheader_t.width;
			Drawer._ConBack.height = dqpicheader_t.height;
			int startIndex = Marshal.SizeOf(typeof(dqpicheader_t));
			Drawer.SetTextureFilters(TextureMinFilter.Nearest, TextureMagFilter.Nearest);
			Drawer._ConBack.texnum = Drawer.LoadTexture("conback", Drawer._ConBack.width, Drawer._ConBack.height, new ByteArraySegment(array, startIndex), false, false, "");
			Drawer._ConBack.width = Scr.vid.width;
			Drawer._ConBack.height = Scr.vid.height;
			Drawer._TranslateTexture = Drawer._TextureExtensionNumber++;
			Drawer._ScrapTexNum = Drawer._TextureExtensionNumber;
			Drawer._TextureExtensionNumber += 2;
			Drawer._Disc = Drawer.PicFromWad("disc");
			Drawer._BackTile = Drawer.PicFromWad("backtile");
		}

		public static void SetTextureFilters(TextureMinFilter min, TextureMagFilter mag)
		{
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)min);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)mag);
		}

		public static int GenerateTextureNumber()
		{
			return Drawer._TextureExtensionNumber++;
		}

		public static int GenerateTextureNumberRange(int count)
		{
			int textureExtensionNumber = Drawer._TextureExtensionNumber;
			Drawer._TextureExtensionNumber += count;
			return textureExtensionNumber;
		}

		public static void DrawPic(int x, int y, glpic_t pic)
		{
			if (Drawer._ScrapDirty)
			{
				Drawer.UploadScrap();
			}
			GL.Color4(1f, 1f, 1f, 1f);
			Drawer.Bind(pic.texnum);
			GL.Begin(PrimitiveType.Quads);
			GL.TexCoord2(pic.sl, pic.tl);
			GL.Vertex2(x, y);
			GL.TexCoord2(pic.sh, pic.tl);
			GL.Vertex2(x + pic.width, y);
			GL.TexCoord2(pic.sh, pic.th);
			GL.Vertex2(x + pic.width, y + pic.height);
			GL.TexCoord2(pic.sl, pic.th);
			GL.Vertex2(x, y + pic.height);
			GL.End();
		}

		public static void BeginDisc()
		{
			if (Drawer._Disc != null)
			{
				GL.DrawBuffer(DrawBufferMode.Front);
				Drawer.DrawPic(Scr.vid.width - 24, 0, Drawer._Disc);
				GL.DrawBuffer(DrawBufferMode.Back);
			}
		}

		public static void EndDisc()
		{
		}

		public static void TileClear(int x, int y, int w, int h)
		{
			GL.Color3(1f, 1f, 1f);
			Drawer.Bind(Drawer._BackTile.texnum);
			GL.Begin(PrimitiveType.Quads);
			GL.TexCoord2((float)x / 64f, (float)y / 64f);
			GL.Vertex2(x, y);
			GL.TexCoord2((float)(x + w) / 64f, (float)y / 64f);
			GL.Vertex2(x + w, y);
			GL.TexCoord2((float)(x + w) / 64f, (float)(y + h) / 64f);
			GL.Vertex2(x + w, y + h);
			GL.TexCoord2((float)x / 64f, (float)(y + h) / 64f);
			GL.Vertex2(x, y + h);
			GL.End();
		}

		public static glpic_t PicFromWad(string name)
		{
			int num = wad.GetLumpNameOffset(name);
			dqpicheader_t dqpicheader_t = (dqpicheader_t)Marshal.PtrToStructure(new IntPtr(wad.DataPointer.ToInt64() + (long)num), typeof(dqpicheader_t));
			glpic_t glpic_t = new glpic_t();
			glpic_t.width = dqpicheader_t.width;
			glpic_t.height = dqpicheader_t.height;
			num += Marshal.SizeOf(typeof(dqpicheader_t));
			if (glpic_t.width < 64 && glpic_t.height < 64)
			{
				int num3;
				int num4;
				int num2 = Drawer.AllocScrapBlock(glpic_t.width, glpic_t.height, out num3, out num4);
				Drawer._ScrapDirty = true;
				int num5 = 0;
				for (int i = 0; i < glpic_t.height; i++)
				{
					int j = 0;
					while (j < glpic_t.width)
					{
						Drawer._ScrapTexels[num2][(num4 + i) * 256 + num3 + j] = wad.Data[num + num5];
						j++;
						num5++;
					}
				}
				num2 += Drawer._ScrapTexNum;
				glpic_t.texnum = num2;
				glpic_t.sl = (float)(((double)num3 + 0.01) / 256.0);
				glpic_t.sh = (float)(((double)(num3 + glpic_t.width) - 0.01) / 256.0);
				glpic_t.tl = (float)(((double)num4 + 0.01) / 256.0);
				glpic_t.th = (float)(((double)(num4 + glpic_t.height) - 0.01) / 256.0);
				Drawer._PicCount++;
				Drawer._PicTexels += glpic_t.width * glpic_t.height;
			}
			else
			{
				glpic_t.texnum = Drawer.LoadTexture(glpic_t, new ByteArraySegment(wad.Data, num));
			}
			return glpic_t;
		}

		public static void Bind(int texnum)
		{
			if (Drawer.CurrentTexture == texnum)
			{
				return;
			}
			Drawer.CurrentTexture = texnum;
			GL.BindTexture(TextureTarget.Texture2D, texnum);
		}

		public static void FadeScreen()
		{
			GL.Enable(EnableCap.Blend);
			GL.Disable(EnableCap.Texture2D);
			GL.Color4(0f, 0f, 0f, 0.8f);
			GL.Begin(PrimitiveType.Quads);
			GL.Vertex2(0f, 0f);
			GL.Vertex2((float)Scr.vid.width, 0f);
			GL.Vertex2((float)Scr.vid.width, (float)Scr.vid.height);
			GL.Vertex2(0f, (float)Scr.vid.height);
			GL.End();
			GL.Color4(1f, 1f, 1f, 1f);
			GL.Enable(EnableCap.Texture2D);
			GL.Disable(EnableCap.Blend);
			sbar.Changed();
		}

		public static int LoadTexture(string identifier, int width, int height, ByteArraySegment data, bool mipmap, bool alpha, string owner = "")
		{
			if (!string.IsNullOrEmpty(identifier))
			{
				for (int i = 0; i < Drawer._NumTextures; i++)
				{
					Drawer.gltexture_t gltexture_t = Drawer._glTextures[i];
					if (gltexture_t.identifier == identifier && gltexture_t.owner == owner)
					{
						if (width != gltexture_t.width || height != gltexture_t.height)
						{
							sys.Error("GL_LoadTexture: cache mismatch!", Array.Empty<object>());
						}
						return gltexture_t.texnum;
					}
				}
			}
			if (Drawer._NumTextures == Drawer._glTextures.Length)
			{
				sys.Error("GL_LoadTexture: no more texture slots available!", Array.Empty<object>());
			}
			Drawer.gltexture_t gltexture_t2 = new Drawer.gltexture_t();
			Drawer._glTextures[Drawer._NumTextures] = gltexture_t2;
			Drawer._NumTextures++;
			gltexture_t2.identifier = identifier;
			gltexture_t2.owner = owner;
			gltexture_t2.texnum = Drawer._TextureExtensionNumber;
			gltexture_t2.width = width;
			gltexture_t2.height = height;
			gltexture_t2.mipmap = mipmap;
			Drawer.Bind(gltexture_t2.texnum);
			Drawer.Upload8(data, width, height, mipmap, alpha);
			Drawer._TextureExtensionNumber++;
			return gltexture_t2.texnum;
		}

		public static void DrawCharacter(int x, int y, int num)
		{
			if (num == 32)
			{
				return;
			}
			num &= 255;
			if (y <= -8)
			{
				return;
			}
			float num2 = (float)(num >> 4);
			int num3 = num & 15;
			float num4 = num2 * 0.0625f;
			float num5 = (float)num3 * 0.0625f;
			float num6 = 0.0625f;
			Drawer.Bind(Drawer._CharTexture);
			GL.Begin(PrimitiveType.Quads);
			GL.TexCoord2(num5, num4);
			GL.Vertex2(x, y);
			GL.TexCoord2(num5 + num6, num4);
			GL.Vertex2(x + 8, y);
			GL.TexCoord2(num5 + num6, num4 + num6);
			GL.Vertex2(x + 8, y + 8);
			GL.TexCoord2(num5, num4 + num6);
			GL.Vertex2(x, y + 8);
			GL.End();
		}

		public static void DrawString(int x, int y, string str)
		{
			int i = 0;
			while (i < str.Length)
			{
				Drawer.DrawCharacter(x, y, (int)str[i]);
				i++;
				x += 8;
			}
		}

		public static glpic_t CachePic(string path)
		{
			for (int i = 0; i < Drawer._MenuNumCachePics; i++)
			{
				cachepic_t cachepic_t = Drawer._MenuCachePics[i];
				if (cachepic_t.name == path)
				{
					return cachepic_t.pic;
				}
			}
			if (Drawer._MenuNumCachePics == 128)
			{
				sys.Error("menu_numcachepics == MAX_CACHED_PICS", Array.Empty<object>());
			}
			cachepic_t cachepic_t2 = Drawer._MenuCachePics[Drawer._MenuNumCachePics];
			Drawer._MenuNumCachePics++;
			cachepic_t2.name = path;
			byte[] array = common.LoadFile(path);
			if (array == null)
			{
				sys.Error("Draw_CachePic: failed to load {0}", new object[]
				{
					path
				});
			}
			dqpicheader_t dqpicheader_t = sys.BytesToStructure<dqpicheader_t>(array, 0);
			wad.SwapPic(dqpicheader_t);
			int num = Marshal.SizeOf(typeof(dqpicheader_t));
			if (path == "gfx/menuplyr.lmp")
			{
				System.Buffer.BlockCopy(array, num, Drawer._MenuPlayerPixels, 0, dqpicheader_t.width * dqpicheader_t.height);
			}
			glpic_t glpic_t = new glpic_t();
			glpic_t.width = dqpicheader_t.width;
			glpic_t.height = dqpicheader_t.height;
			glpic_t.texnum = Drawer.LoadTexture(glpic_t, new ByteArraySegment(array, num));
			glpic_t.sl = 0f;
			glpic_t.sh = 1f;
			glpic_t.tl = 0f;
			glpic_t.th = 1f;
			cachepic_t2.pic = glpic_t;
			return glpic_t;
		}

		public static void Fill(int x, int y, int w, int h, int c)
		{
			GL.Disable(EnableCap.Texture2D);
			byte[] basePal = host.BasePal;
			GL.Color3((float)basePal[c * 3] / 255f, (float)basePal[c * 3 + 1] / 255f, (float)basePal[c * 3 + 2] / 255f);
			GL.Begin(PrimitiveType.Quads);
			GL.Vertex2(x, y);
			GL.Vertex2(x + w, y);
			GL.Vertex2(x + w, y + h);
			GL.Vertex2(x, y + h);
			GL.End();
			GL.Color3(1f, 1f, 1f);
			GL.Enable(EnableCap.Texture2D);
		}

		public static void DrawTransPic(int x, int y, glpic_t pic)
		{
			if (x < 0 || (ulong)(x + pic.width) > (ulong)((long)Scr.vid.width) || y < 0 || (ulong)(y + pic.height) > (ulong)((long)Scr.vid.height))
			{
				sys.Error("Draw_TransPic: bad coordinates", Array.Empty<object>());
			}
			Drawer.DrawPic(x, y, pic);
		}

		public static void TransPicTranslate(int x, int y, glpic_t pic, byte[] translation)
		{
			Drawer.Bind(Drawer._TranslateTexture);
			int width = pic.width;
			int height = pic.height;
			int num = 0;
			uint[] array = new uint[4096];
			int i = 0;
			while (i < 64)
			{
				int num2 = (i * pic.height >> 6) * pic.width;
				for (int j = 0; j < 64; j++)
				{
					uint num3 = (uint)Drawer._MenuPlayerPixels[num2 + (j * pic.width >> 6)];
					if (num3 == 255u)
					{
						array[num + j] = num3;
					}
					else
					{
						array[num + j] = vid.Table8to24[(int)translation[(int)num3]];
					}
				}
				i++;
				num += 64;
			}
			GCHandle gchandle = GCHandle.Alloc(array, GCHandleType.Pinned);
			try
			{
				GL.TexImage2D(TextureTarget.Texture2D, 0, Drawer.AlphaFormat, 64, 64, 0, PixelFormat.Rgba, PixelType.UnsignedByte, gchandle.AddrOfPinnedObject());
			}
			finally
			{
				gchandle.Free();
			}
			Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear);
			GL.Color3(1f, 1f, 1f);
			GL.Begin(PrimitiveType.Quads);
			GL.TexCoord2(0f, 0f);
			GL.Vertex2((float)x, (float)y);
			GL.TexCoord2(1f, 0f);
			GL.Vertex2((float)x + (float)pic.width, (float)y);
			GL.TexCoord2(1f, 1f);
			GL.Vertex2((float)x + (float)pic.width, (float)(y + pic.height));
			GL.TexCoord2(0f, 1f);
			GL.Vertex2((float)x, (float)(y + pic.height));
			GL.End();
		}

		public static void DrawConsoleBackground(int lines)
		{
			int num = Scr.vid.height * 3 >> 2;
			if (lines > num)
			{
				Drawer.DrawPic(0, lines - Scr.vid.height, Drawer._ConBack);
				return;
			}
			Drawer.DrawAlphaPic(0, lines - Scr.vid.height, Drawer._ConBack, (float)(1.2 * (double)lines) / (float)num);
		}

		public static void DrawAlphaPic(int x, int y, glpic_t pic, float alpha)
		{
			if (Drawer._ScrapDirty)
			{
				Drawer.UploadScrap();
			}
			GL.Disable(EnableCap.AlphaTest);
			GL.Enable(EnableCap.Blend);
			GL.Color4(1f, 1f, 1f, alpha);
			Drawer.Bind(pic.texnum);
			GL.Begin(PrimitiveType.Quads);
			GL.TexCoord2(pic.sl, pic.tl);
			GL.Vertex2(x, y);
			GL.TexCoord2(pic.sh, pic.tl);
			GL.Vertex2(x + pic.width, y);
			GL.TexCoord2(pic.sh, pic.th);
			GL.Vertex2(x + pic.width, y + pic.height);
			GL.TexCoord2(pic.sl, pic.th);
			GL.Vertex2(x, y + pic.height);
			GL.End();
			GL.Color4(1f, 1f, 1f, 1f);
			GL.Enable(EnableCap.AlphaTest);
			GL.Disable(EnableCap.Blend);
		}

		public static void SelectTexture(MTexTarget target)
		{
			if (!vid.glMTexable)
			{
				return;
			}
			if (target != MTexTarget.TEXTURE0_SGIS)
			{
				if (target != MTexTarget.TEXTURE1_SGIS)
				{
					sys.Error("GL_SelectTexture: Unknown target\n", Array.Empty<object>());
				}
				else
				{
					GL.Arb.ActiveTexture(TextureUnit.Texture1);
				}
			}
			else
			{
				GL.Arb.ActiveTexture(TextureUnit.Texture0);
			}
			if (target == Drawer._OldTarget)
			{
				return;
			}
			Drawer._CntTextures[Drawer._OldTarget - MTexTarget.TEXTURE0_SGIS] = Drawer.CurrentTexture;
			Drawer.CurrentTexture = Drawer._CntTextures[target - MTexTarget.TEXTURE0_SGIS];
			Drawer._OldTarget = target;
		}

		private static void TextureMode_f()
		{
			int i;
			if (cmd.Argc == 1)
			{
				for (i = 0; i < 6; i++)
				{
					if (Drawer._MinFilter == Drawer._Modes[i].minimize)
					{
						Con.Print("{0}\n", new object[]
						{
							Drawer._Modes[i].name
						});
						return;
					}
				}
				Con.Print("current filter is unknown???\n", Array.Empty<object>());
				return;
			}
			i = 0;
			while (i < Drawer._Modes.Length && !common.SameText(Drawer._Modes[i].name, cmd.Argv(1)))
			{
				i++;
			}
			if (i == Drawer._Modes.Length)
			{
				Con.Print("bad filter name!\n", Array.Empty<object>());
				return;
			}
			Drawer._MinFilter = Drawer._Modes[i].minimize;
			Drawer._MagFilter = Drawer._Modes[i].maximize;
			for (i = 0; i < Drawer._NumTextures; i++)
			{
				Drawer.gltexture_t gltexture_t = Drawer._glTextures[i];
				if (gltexture_t.mipmap)
				{
					Drawer.Bind(gltexture_t.texnum);
					Drawer.SetTextureFilters(Drawer._MinFilter, Drawer._MagFilter);
				}
			}
		}

		private static void Imagelist_f()
		{
			short num = 0;
			foreach (Drawer.gltexture_t gltexture_t in Drawer._glTextures)
			{
				if (gltexture_t != null)
				{
					Con.Print("{0} x {1}   {2}:{3}\n", new object[]
					{
						gltexture_t.width,
						gltexture_t.height,
						gltexture_t.owner,
						gltexture_t.identifier
					});
					num += 1;
				}
			}
			Con.Print("{0} textures currently loaded.\n", new object[]
			{
				num
			});
		}

		private static int LoadTexture(glpic_t pic, ByteArraySegment data)
		{
			return Drawer.LoadTexture(string.Empty, pic.width, pic.height, data, false, true, "");
		}

		private static void CharToConback(int num, ByteArraySegment dest, ByteArraySegment drawChars)
		{
			int num2 = num >> 4;
			int num3 = num & 15;
			int num4 = dest.StartIndex;
			int num5 = drawChars.StartIndex + (num2 << 10) + (num3 << 3);
			int num6 = 8;
			while (num6-- > 0)
			{
				for (int i = 0; i < 8; i++)
				{
					if (drawChars.Data[num5 + i] != 255)
					{
						dest.Data[num4 + i] = 96 + drawChars.Data[num5 + i];
					}
				}
				num5 += 128;
				num4 += 320;
			}
		}

		private static void Upload8(ByteArraySegment data, int width, int height, bool mipmap, bool alpha)
		{
			int num = width * height;
			uint[] array = new uint[num];
			uint[] table8to = vid.Table8to24;
			byte[] data2 = data.Data;
			int num2 = data.StartIndex;
			if (alpha)
			{
				bool flag = true;
				int i = 0;
				while (i < num)
				{
					byte b = data2[num2];
					if (b == 255)
					{
						flag = false;
					}
					array[i] = table8to[(int)b];
					i++;
					num2++;
				}
				if (alpha && flag)
				{
					alpha = false;
				}
			}
			else
			{
				if ((num & 3) != 0)
				{
					sys.Error("GL_Upload8: s&3", Array.Empty<object>());
				}
				int j = 0;
				while (j < num)
				{
					array[j] = table8to[(int)data2[num2]];
					array[j + 1] = table8to[(int)data2[num2 + 1]];
					array[j + 2] = table8to[(int)data2[num2 + 2]];
					array[j + 3] = table8to[(int)data2[num2 + 3]];
					j += 4;
					num2 += 4;
				}
			}
			Drawer.Upload32(array, width, height, mipmap, alpha);
		}

		private static void Upload32(uint[] data, int width, int height, bool mipmap, bool alpha)
		{
			int i;
			for (i = 1; i < width; i <<= 1)
			{
			}
			int j;
			for (j = 1; j < height; j <<= 1)
			{
			}
			i >>= (int)Drawer._glPicMip.Value;
			j >>= (int)Drawer._glPicMip.Value;
			if ((float)i > Drawer._glMaxSize.Value)
			{
				i = (int)Drawer._glMaxSize.Value;
			}
			if ((float)j > Drawer._glMaxSize.Value)
			{
				j = (int)Drawer._glMaxSize.Value;
			}
			PixelInternalFormat internalformat = alpha ? Drawer._AlphaFormat : Drawer._SolidFormat;
			Drawer._Texels += i * j;
			uint[] array;
			if (i == width && j == height)
			{
				if (!mipmap)
				{
					GCHandle gchandle = GCHandle.Alloc(data, GCHandleType.Pinned);
					try
					{
						GL.TexImage2D(TextureTarget.Texture2D, 0, internalformat, i, j, 0, PixelFormat.Rgba, PixelType.UnsignedByte, gchandle.AddrOfPinnedObject());
						goto IL_178;
					}
					finally
					{
						gchandle.Free();
					}
				}
				array = new uint[i * j];
				data.CopyTo(array, 0);
			}
			else
			{
				Drawer.ResampleTexture(data, width, height, out array, i, j);
			}
			GCHandle gchandle2 = GCHandle.Alloc(array, GCHandleType.Pinned);
			try
			{
				IntPtr pixels = gchandle2.AddrOfPinnedObject();
				GL.TexImage2D(TextureTarget.Texture2D, 0, internalformat, i, j, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
				GL.GetError();
				if (mipmap)
				{
					int num = 0;
					while (i > 1 || j > 1)
					{
						Drawer.MipMap(array, i, j);
						i >>= 1;
						j >>= 1;
						if (i < 1)
						{
							i = 1;
						}
						if (j < 1)
						{
							j = 1;
						}
						num++;
						GL.TexImage2D(TextureTarget.Texture2D, num, internalformat, i, j, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
					}
				}
			}
			finally
			{
				gchandle2.Free();
			}
			IL_178:
			if (mipmap)
			{
				Drawer.SetTextureFilters(Drawer._MinFilter, Drawer._MagFilter);
				return;
			}
			Drawer.SetTextureFilters((TextureMinFilter)Drawer._MagFilter, Drawer._MagFilter);
		}

		private static void ResampleTexture(uint[] src, int srcWidth, int srcHeight, out uint[] dest, int destWidth, int destHeight)
		{
			dest = new uint[destWidth * destHeight];
			int num = srcWidth * 65536 / destWidth;
			int num2 = 0;
			for (int i = 0; i < destHeight; i++)
			{
				int num3 = srcWidth * (i * srcHeight / destHeight);
				int num4 = num >> 1;
				for (int j = 0; j < destWidth; j += 4)
				{
					dest[num2 + j] = src[num3 + (num4 >> 16)];
					num4 += num;
					dest[num2 + j + 1] = src[num3 + (num4 >> 16)];
					num4 += num;
					dest[num2 + j + 2] = src[num3 + (num4 >> 16)];
					num4 += num;
					dest[num2 + j + 3] = src[num3 + (num4 >> 16)];
					num4 += num;
				}
				num2 += destWidth;
			}
		}

		private static void MipMap(uint[] src, int width, int height)
		{
			Union4b empty = Union4b.Empty;
			Union4b empty2 = Union4b.Empty;
			Union4b empty3 = Union4b.Empty;
			Union4b empty4 = Union4b.Empty;
			width >>= 1;
			height >>= 1;
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					empty.ui0 = src[num];
					int num3 = num + 1;
					empty2.ui0 = ((num3 < src.Length) ? src[num3] : empty.ui0);
					num3 = num + (width << 1);
					empty3.ui0 = ((num3 < src.Length) ? src[num3] : empty.ui0);
					num3 = num + (width << 1) + 1;
					empty4.ui0 = ((num3 < src.Length) ? src[num3] : empty.ui0);
					empty.b0 = (byte)(empty.b0 + empty2.b0 + empty3.b0 + empty4.b0 >> 2);
					empty.b1 = (byte)(empty.b1 + empty2.b1 + empty3.b1 + empty4.b1 >> 2);
					empty.b2 = (byte)(empty.b2 + empty2.b2 + empty3.b2 + empty4.b2 >> 2);
					empty.b3 = (byte)(empty.b3 + empty2.b3 + empty3.b3 + empty4.b3 >> 2);
					src[num2] = empty.ui0;
					num2++;
					num += 2;
				}
				num += width << 1;
			}
		}

		private static int AllocScrapBlock(int w, int h, out int x, out int y)
		{
			x = -1;
			y = -1;
			for (int i = 0; i < 2; i++)
			{
				int num = 256;
				for (int j = 0; j < 256 - w; j++)
				{
					int num2 = 0;
					int num3 = 0;
					while (num3 < w && Drawer._ScrapAllocated[i][j + num3] < num)
					{
						if (Drawer._ScrapAllocated[i][j + num3] > num2)
						{
							num2 = Drawer._ScrapAllocated[i][j + num3];
						}
						num3++;
					}
					if (num3 == w)
					{
						x = j;
						num = (y = num2);
					}
				}
				if (num + h <= 256)
				{
					for (int k = 0; k < w; k++)
					{
						Drawer._ScrapAllocated[i][x + k] = num + h;
					}
					return i;
				}
			}
			sys.Error("Scrap_AllocBlock: full", Array.Empty<object>());
			return -1;
		}

		private static void UploadScrap()
		{
			Drawer._ScrapUploads++;
			for (int i = 0; i < 2; i++)
			{
				Drawer.Bind(Drawer._ScrapTexNum + i);
				Drawer.Upload8(new ByteArraySegment(Drawer._ScrapTexels[i]), 256, 256, false, true);
			}
			Drawer._ScrapDirty = false;
		}

		static Drawer()
		{
			Drawer._ScrapAllocated = new int[2][];
			for (int i = 0; i < Drawer._ScrapAllocated.GetLength(0); i++)
			{
				Drawer._ScrapAllocated[i] = new int[256];
			}
			Drawer._ScrapTexels = new byte[2][];
			for (int j = 0; j < Drawer._ScrapTexels.GetLength(0); j++)
			{
				Drawer._ScrapTexels[j] = new byte[262144];
			}
		}

		public static int CurrentTexture = -1;

		public static PixelFormat LightMapFormat = PixelFormat.Rgba;

		private const int MAX_GLTEXTURES = 1024;

		private const int MAX_CACHED_PICS = 128;

		private const int MAX_SCRAPS = 2;

		private const int BLOCK_WIDTH = 256;

		private const int BLOCK_HEIGHT = 256;

		private static readonly Drawer.glmode_t[] _Modes = new Drawer.glmode_t[]
		{
			new Drawer.glmode_t("GL_NEAREST", TextureMinFilter.Nearest, TextureMagFilter.Nearest),
			new Drawer.glmode_t("GL_LINEAR", TextureMinFilter.Linear, TextureMagFilter.Linear),
			new Drawer.glmode_t("GL_NEAREST_MIPMAP_NEAREST", TextureMinFilter.NearestMipmapNearest, TextureMagFilter.Nearest),
			new Drawer.glmode_t("GL_LINEAR_MIPMAP_NEAREST", TextureMinFilter.LinearMipmapNearest, TextureMagFilter.Linear),
			new Drawer.glmode_t("GL_NEAREST_MIPMAP_LINEAR", TextureMinFilter.NearestMipmapLinear, TextureMagFilter.Nearest),
			new Drawer.glmode_t("GL_LINEAR_MIPMAP_LINEAR", TextureMinFilter.LinearMipmapLinear, TextureMagFilter.Linear)
		};

		private static readonly Drawer.gltexture_t[] _glTextures = new Drawer.gltexture_t[1024];

		private static readonly cachepic_t[] _MenuCachePics = new cachepic_t[128];

		private static readonly byte[] _MenuPlayerPixels = new byte[4096];

		private static int[][] _ScrapAllocated;

		private static byte[][] _ScrapTexels;

		private static bool _ScrapDirty;

		private static int _ScrapTexNum;

		private static int _ScrapUploads;

		private static int _NumTextures;

		private static int _Texels;

		private static int _PicTexels;

		private static int _PicCount;

		private static cvar _glNoBind;

		private static cvar _glMaxSize;

		private static cvar _glPicMip;

		private static glpic_t _Disc;

		private static glpic_t _BackTile;

		private static glpic_t _ConBack;

		private static int _CharTexture;

		private static int _TranslateTexture;

		private static int _TextureExtensionNumber = 1;

		private static MTexTarget _OldTarget = MTexTarget.TEXTURE0_SGIS;

		private static int[] _CntTextures = new int[]
		{
			-1,
			-1
		};

		private static TextureMinFilter _MinFilter = TextureMinFilter.LinearMipmapNearest;

		private static TextureMagFilter _MagFilter = TextureMagFilter.Linear;

		private static PixelInternalFormat _SolidFormat = PixelInternalFormat.Three;

		private static PixelInternalFormat _AlphaFormat = PixelInternalFormat.Four;

		private static int _MenuNumCachePics;

		private class glmode_t
		{
			public glmode_t(string name, TextureMinFilter minFilter, TextureMagFilter magFilter)
			{
				this.name = name;
				this.minimize = minFilter;
				this.maximize = magFilter;
			}

			public string name;

			public TextureMinFilter minimize;

			public TextureMagFilter maximize;
		}

		private class gltexture_t
		{
			public int texnum;

			public string owner;

			public string identifier;

			public int width;

			public int height;

			public bool mipmap;
		}
	}
}
