From 3fd0519bd2780879490775c4149c9f7fc3c0f3c4 Mon Sep 17 00:00:00 2001 From: Latif Khalifa Date: Sat, 16 Apr 2011 16:21:41 +0000 Subject: [PATCH] Move texturing to separate thread. git-svn-id: https://radegast.googlecode.com/svn/trunk@847 f7a694da-4d33-11de-9ad6-1127a62b9fcd --- Radegast/GUI/Dialogs/PrimWorkshop.cs | 179 ++++++++++++++++++++++------------- 1 file changed, 112 insertions(+), 67 deletions(-) diff --git a/Radegast/GUI/Dialogs/PrimWorkshop.cs b/Radegast/GUI/Dialogs/PrimWorkshop.cs index 914fa90..7956a76 100644 --- a/Radegast/GUI/Dialogs/PrimWorkshop.cs +++ b/Radegast/GUI/Dialogs/PrimWorkshop.cs @@ -63,6 +63,8 @@ namespace Radegast Dictionary Textures = new Dictionary(); RadegastInstance instance; MeshmerizerR renderer; + OpenTK.Graphics.GraphicsMode GLMode = null; + AutoResetEvent TextureThreadContextReady = new AutoResetEvent(false); #endregion Form Globals @@ -89,7 +91,7 @@ namespace Radegast glControl.Dispose(); glControl = null; - OpenTK.Graphics.GraphicsMode mode = null; + GLMode = null; try { @@ -98,22 +100,22 @@ namespace Radegast var testMode = new OpenTK.Graphics.GraphicsMode(OpenTK.DisplayDevice.Default.BitsPerPixel, 24, 8, aa); if (testMode.Samples == aa) { - mode = testMode; + GLMode = testMode; } } } - catch {} + catch { } - if (mode == null) + if (GLMode == null) { Logger.Log("Failed to initialize OpenGL control", Helpers.LogLevel.Error, Client); return; } - Logger.Log("Initializing OpenGL mode: " + mode.ToString(), Helpers.LogLevel.Info); + Logger.Log("Initializing OpenGL mode: " + GLMode.ToString(), Helpers.LogLevel.Info); try { - glControl = new OpenTK.GLControl(mode); + glControl = new OpenTK.GLControl(GLMode); } catch { @@ -167,6 +169,17 @@ namespace Radegast // Call the resizing function which sets up the GL drawing window // and will also invalidate the GL control glControl_Resize(null, null); + + glControl.Context.MakeCurrent(null); + TextureThreadContextReady.Reset(); + var textureThread = new Thread(() => TextureThread()) + { + IsBackground = true, + Name = "TextureLoadingThread" + }; + textureThread.Start(); + TextureThreadContextReady.WaitOne(1000, false); + glControl.MakeCurrent(); } catch (Exception ex) { @@ -175,11 +188,85 @@ namespace Radegast } } + bool TextureThreadRunning = true; + + void TextureThread() + { + OpenTK.INativeWindow window = new OpenTK.NativeWindow(); + OpenTK.Graphics.IGraphicsContext context = new OpenTK.Graphics.GraphicsContext(GLMode, window.WindowInfo); + context.MakeCurrent(window.WindowInfo); + TextureThreadContextReady.Set(); + Logger.DebugLog("Started Texture Thread"); + + while (window.Exists && TextureThreadRunning) + { + window.ProcessEvents(); + + TextureLoadItem item = null; + + if (!PendingTextures.Dequeue(Timeout.Infinite, ref item)) continue; + + if (LoadTexture(item.TeFace.TextureID, ref item.Data.Texture, false)) + { + GL.GenTextures(1, out item.Data.TexturePointer); + GL.BindTexture(TextureTarget.Texture2D, item.Data.TexturePointer); + + Bitmap bitmap = new Bitmap(item.Data.Texture); + bool hasAlpha; + if (item.Data.Texture.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) + { + hasAlpha = true; + } + else + { + hasAlpha = false; + } + + bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); + Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height); + + + BitmapData bitmapData = + bitmap.LockBits( + rectangle, + ImageLockMode.ReadOnly, + hasAlpha ? System.Drawing.Imaging.PixelFormat.Format32bppArgb : System.Drawing.Imaging.PixelFormat.Format24bppRgb); + + GL.TexImage2D( + TextureTarget.Texture2D, + 0, + hasAlpha ? PixelInternalFormat.Rgba : PixelInternalFormat.Rgb8, + bitmap.Width, + bitmap.Height, + 0, + hasAlpha ? OpenTK.Graphics.OpenGL.PixelFormat.Bgra : OpenTK.Graphics.OpenGL.PixelFormat.Bgr, + PixelType.UnsignedByte, + bitmapData.Scan0); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); + //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1); + GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + bitmap.UnlockBits(bitmapData); + bitmap.Dispose(); + + SafeInvalidate(); + } + GL.Flush(); + Thread.Sleep(10); + } + Logger.DebugLog("Texture thread exited"); + } void frmPrimWorkshop_Disposed(object sender, EventArgs e) { Client.Objects.TerseObjectUpdate -= new EventHandler(Objects_TerseObjectUpdate); Client.Objects.ObjectUpdate -= new EventHandler(Objects_ObjectUpdate); + TextureThreadRunning = false; + PendingTextures.Close(); } void Objects_TerseObjectUpdate(object sender, TerseObjectUpdateEventArgs e) @@ -291,7 +378,7 @@ namespace Radegast Primitive.TextureEntryFace teFace = Prims[i].Prim.Textures.FaceTextures[j]; if (teFace == null) teFace = Prims[i].Prim.Textures.DefaultTexture; - + // Don't render transparent faces if (teFace.RGBA.A <= 0.01f) continue; @@ -547,10 +634,13 @@ namespace Radegast return ret; } + BlockingQueue PendingTextures = new BlockingQueue(); + private void loadPrimsBlocking(List primList) { Prims = null; Prims = new List(primList.Count); + PendingTextures.Open(); for (int i = 0; i < primList.Count; i++) { @@ -639,66 +729,14 @@ namespace Radegast data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y; } - //ThreadPool.QueueUserWorkItem(sync => - // { - // Texture for this face - if (LoadTexture(teFace.TextureID, ref data.Texture, false)) - { - if (IsHandleCreated) - { - Invoke(new MethodInvoker(() => - { - GL.GenTextures(1, out data.TexturePointer); - GL.BindTexture(TextureTarget.Texture2D, data.TexturePointer); - - Bitmap bitmap = new Bitmap(data.Texture); - bool hasAlpha; - if (data.Texture.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) - { - hasAlpha = true; - } - else - { - hasAlpha = false; - } - - bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); - Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height); - - - BitmapData bitmapData = - bitmap.LockBits( - rectangle, - ImageLockMode.ReadOnly, - hasAlpha ? System.Drawing.Imaging.PixelFormat.Format32bppArgb : System.Drawing.Imaging.PixelFormat.Format24bppRgb); - - GL.TexImage2D( - TextureTarget.Texture2D, - 0, - hasAlpha ? PixelInternalFormat.Rgba : PixelInternalFormat.Rgb8, - bitmap.Width, - bitmap.Height, - 0, - hasAlpha ? OpenTK.Graphics.OpenGL.PixelFormat.Bgra : OpenTK.Graphics.OpenGL.PixelFormat.Bgr, - PixelType.UnsignedByte, - bitmapData.Scan0); - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); - //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1); - GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); - bitmap.UnlockBits(bitmapData); - bitmap.Dispose(); - - SafeInvalidate(); - } - )); - } - } - //}); + var textureItem = new TextureLoadItem() + { + Data = data, + Prim = prim, + TeFace = teFace + }; + + PendingTextures.Enqueue(textureItem); // Set the UserData for this face to our FaceData struct face.UserData = data; @@ -908,6 +946,13 @@ namespace Radegast public System.Drawing.Image Texture; } + public class TextureLoadItem + { + public FaceData Data; + public Primitive Prim; + public Primitive.TextureEntryFace TeFace; + } + public static class Render { public static IRendering Plugin; -- 2.11.0