internal static void UnloadUnusedTextures(double TimeElapsed) { #if DEBUG //HACK: If when running in debug mode the frame time exceeds 1s, we can assume VS has hit a breakpoint //Don't unload textures in this case, as it just causes texture bugs if (TimeElapsed > 1000) { foreach (var Texture in TextureManager.RegisteredTextures) { if (Texture != null) { Texture.LastAccess = CPreciseTimer.GetClockTicks(); } } } #endif if (Game.CurrentInterface == Game.InterfaceType.Normal) { foreach (var Texture in TextureManager.RegisteredTextures) { if (Texture != null && (CPreciseTimer.GetClockTicks() - Texture.LastAccess) > 20000) { TextureManager.UnloadTexture(Texture); } } } else { //Don't unload textures if we are in a menu/ paused, as they may be required immediately after unpause foreach (var Texture in TextureManager.RegisteredTextures) { //Texture can be null in certain cases.... if (Texture != null) { Texture.LastAccess = CPreciseTimer.GetClockTicks(); } } } }
public override bool LoadTexture(Texture Texture, OpenGlTextureWrapMode wrapMode) { return(Program.Renderer.TextureManager.LoadTexture(Texture, wrapMode, CPreciseTimer.GetClockTicks(), Interface.CurrentOptions.Interpolation, Interface.CurrentOptions.AnisotropicFilteringLevel)); }
/// <summary>Loads all registered textures.</summary> internal static void LoadAllTextures() { for (int i = 0; i < LibRender.TextureManager.RegisteredTexturesCount; i++) { LibRender.TextureManager.LoadTexture(LibRender.TextureManager.RegisteredTextures[i], OpenGlTextureWrapMode.ClampClamp, CPreciseTimer.GetClockTicks(), Interface.CurrentOptions.Interpolation, Interface.CurrentOptions.AnisotropicFilteringLevel); } }
// --- load texture --- /// <summary>Loads the specified texture into OpenGL if not already loaded.</summary> /// <param name="handle">The handle to the registered texture.</param> /// <param name="wrap">The texture type indicating the clamp mode.</param> /// <returns>Whether loading the texture was successful.</returns> internal static bool LoadTexture(Texture handle, OpenGlTextureWrapMode wrap) { //Don't try to load a texture to a null handle, this is a seriously bad idea.... if (handle == null) { return(false); } //Set last access time handle.LastAccess = CPreciseTimer.GetClockTicks(); if (handle.OpenGlTextures[(int)wrap].Valid) { return(true); } if (handle.Ignore) { return(false); } OpenBveApi.Textures.Texture texture; if (handle.Origin.GetTexture(out texture)) { if (texture.BitsPerPixel == 32) { int[] names = new int[1]; GL.GenTextures(1, names); GL.BindTexture(TextureTarget.Texture2D, names[0]); handle.OpenGlTextures[(int)wrap].Name = names[0]; handle.Width = texture.Width; handle.Height = texture.Height; handle.Transparency = texture.GetTransparencyType(); texture = UpsizeToPowerOfTwo(texture); switch (Interface.CurrentOptions.Interpolation) { case Interface.InterpolationMode.NearestNeighbor: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Nearest); break; case Interface.InterpolationMode.Bilinear: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear); break; case Interface.InterpolationMode.NearestNeighborMipmapped: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.NearestMipmapNearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Nearest); break; case Interface.InterpolationMode.BilinearMipmapped: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.NearestMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear); break; case Interface.InterpolationMode.TrilinearMipmapped: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear); break; default: GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear); break; } if ((wrap & OpenGlTextureWrapMode.RepeatClamp) != 0) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (float)TextureWrapMode.Repeat); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (float)TextureWrapMode.ClampToEdge); } if ((wrap & OpenGlTextureWrapMode.ClampRepeat) != 0) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (float)TextureWrapMode.Repeat); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (float)TextureWrapMode.ClampToEdge); } if (Interface.CurrentOptions.Interpolation == Interface.InterpolationMode.NearestNeighbor && Interface.CurrentOptions.Interpolation == Interface.InterpolationMode.Bilinear) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 0); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1); } if (Interface.CurrentOptions.Interpolation == Interface.InterpolationMode.AnisotropicFiltering) { GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)ExtTextureFilterAnisotropic.TextureMaxAnisotropyExt, Interface.CurrentOptions.AnisotropicFilteringLevel); } if (handle.Transparency == OpenBveApi.Textures.TextureTransparencyType.Opaque) { /* * If the texture is fully opaque, the alpha channel is not used. * If the graphics driver and card support 24-bits per channel, * it is best to convert the bitmap data to that format in order * to save memory on the card. If the card does not support the * format, it will likely be upconverted to 32-bits per channel * again, and this is wasted effort. * */ int width = texture.Width; int height = texture.Height; int stride = (3 * (width + 1) >> 2) << 2; byte[] oldBytes = texture.Bytes; byte[] newBytes = new byte[stride * texture.Height]; int i = 0, j = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { newBytes[j + 0] = oldBytes[i + 0]; newBytes[j + 1] = oldBytes[i + 1]; newBytes[j + 2] = oldBytes[i + 2]; i += 4; j += 3; } j += stride - 3 * width; } GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb8, texture.Width, texture.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.UnsignedByte, newBytes); } else { /* * The texture uses its alpha channel, so send the bitmap data * in 32-bits per channel as-is. * */ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, texture.Width, texture.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, texture.Bytes); } handle.OpenGlTextures[(int)wrap].Valid = true; return(true); } } handle.Ignore = true; return(false); }