DOES NOT COMPILE - working on resource management

This commit is contained in:
codeimp 2008-09-26 15:15:56 +00:00
parent 4d67cc7dd4
commit 996a56dafc
7 changed files with 228 additions and 192 deletions

View file

@ -77,6 +77,7 @@
<Compile Include="Data\DirectoryReader.cs" />
<Compile Include="Data\FileImage.cs" />
<Compile Include="Data\FlatImage.cs" />
<Compile Include="Data\ImageLoadState.cs" />
<Compile Include="Data\NullImage.cs" />
<Compile Include="Data\PatchNames.cs" />
<Compile Include="Data\PK3Reader.cs" />

View file

@ -60,7 +60,7 @@ namespace CodeImp.DoomBuilder.Data
private Dictionary<long, ImageData> sprites;
// Background loading
private LinkedList<ImageData> loadlist;
private Queue<ImageData> imageque;
private Thread backgroundloader;
// Image previews
@ -77,6 +77,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Properties
public Playpal Palette { get { return palette; } }
internal PreviewManager Previews { get { return previews; } }
public ICollection<ImageData> Textures { get { return textures.Values; } }
public ICollection<ImageData> Flats { get { return flats.Values; } }
public List<string> TextureNames { get { return texturenames; } }
@ -351,35 +352,48 @@ namespace CodeImp.DoomBuilder.Data
{
// Get next item
ImageData image = null;
lock(loadlist)
lock(imageque)
{
// Anything to do?
if(loadlist.Count > 0)
{
// Fetch image
image = loadlist.First.Value;
image.LoadingTicket = null;
loadlist.RemoveFirst();
// Load or unload this image?
switch(image.LoadState)
{
// Load image
case ImageData.LOADSTATE_LOAD:
image.LoadImage();
//image.CreateTexture(); // Impossible from different thread
break;
// Unload image
case ImageData.LOADSTATE_TRASH:
image.UnloadImage();
break;
}
}
// Fethc next image to process
if(imageque.Count > 0) image = imageque.Dequeue();
}
// Did we do something?
// Any image to process?
if(image != null)
{
// Load this image?
if(image.ImageState == ImageLoadState.Loading)
{
// Still referenced?
if(image.IsReferenced)
image.LoadImage();
else
image.ImageState = ImageLoadState.None;
}
// Unload this image?
if(image.ImageState == ImageLoadState.Unloading)
{
// Still unreferenced?
if(!image.IsReferenced)
image.UnloadImage();
else
image.ImageState = ImageLoadState.Ready;
}
}
// Doing something?
if(image != null)
{
// Wait a bit and update icon
General.MainWindow.UpdateStatusIcon();
Thread.Sleep(1);
}
else
{
// Process previews only when we don't have images to process
// because these are lower priority than the actual images
if(previews.BackgroundLoad())
{
// Wait a bit and update icon
General.MainWindow.UpdateStatusIcon();
@ -391,6 +405,10 @@ namespace CodeImp.DoomBuilder.Data
Thread.Sleep(50);
}
}
// Done
image = null;
}
while(true);
}
catch(ThreadInterruptedException)
@ -400,54 +418,28 @@ namespace CodeImp.DoomBuilder.Data
}
// This adds an image for background loading or unloading
public void BackgroundLoadImage(ImageData img, bool load)
internal void ProcessImage(ImageData img)
{
int loadstate = load ? ImageData.LOADSTATE_LOAD : ImageData.LOADSTATE_TRASH;
// Load this image?
if((img.ImageState == ImageLoadState.None) && img.IsReferenced)
{
// Add for loading
img.ImageState = ImageLoadState.Loading;
lock(imageque) { imageque.Enqueue(img); }
}
lock(loadlist)
// Unload this image?
if((img.ImageState == ImageLoadState.Ready) && !img.IsReferenced)
{
// Already in the list?
if(img.LoadingTicket != null)
{
// Just change the state
img.LoadState = loadstate;
}
else
{
// Set load state and add to list
img.LoadState = loadstate;
img.LoadingTicket = loadlist.AddLast(img);
}
// Add for unloading
img.ImageState = ImageLoadState.Unloading;
lock(imageque) { imageque.Enqueue(img); }
}
// Update icon
General.MainWindow.UpdateStatusIcon();
}
// This removes an image from background loading
// This does not work for images that are being unloaded!
public void BackgroundCancelImage(ImageData img)
{
// Queued?
if(img.LoadingTicket != null)
{
// Not being trashed?
if(img.LoadState != ImageData.LOADSTATE_TRASH)
{
lock(loadlist)
{
// Remove it from queue
LinkedListNode<ImageData> ticket = img.LoadingTicket;
img.LoadingTicket = null;
loadlist.Remove(ticket);
}
// Update icon
General.MainWindow.UpdateStatusIcon();
}
}
}
#endregion
#region ================== Palette

View file

@ -37,10 +37,6 @@ namespace CodeImp.DoomBuilder.Data
{
#region ================== Constants
internal const int LOADSTATE_NONE = 0;
internal const int LOADSTATE_LOAD = 1;
internal const int LOADSTATE_TRASH = 2;
#endregion
#region ================== Variables
@ -54,19 +50,20 @@ namespace CodeImp.DoomBuilder.Data
protected float scaledheight;
protected bool usecolorcorrection;
// Background loading
private LinkedListNode<ImageData> loadingticket;
private int loadstate;
private bool temporary;
// Loading
private LinkedListNode<ImageData> processticket;
private ImageLoadState previewstate;
private ImageLoadState imagestate;
// References
private bool usedinmap;
private int references;
// GDI bitmap
protected Bitmap bitmap;
// 2D rendering data
private PixelColorBlock pixeldata;
// Direct3D texture
private int mipmaplevels = 0; // 0 creates the full chain
private int mipmaplevels = 0; // 0 = all mipmaps
private Texture texture;
// Disposing
@ -79,14 +76,16 @@ namespace CodeImp.DoomBuilder.Data
public string Name { get { return name; } }
public long LongName { get { return longname; } }
public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } }
public PixelColorBlock PixelData { get { lock(this) { return pixeldata; } } }
public Bitmap Bitmap { get { lock(this) { if(bitmap != null) return new Bitmap(bitmap); else return CodeImp.DoomBuilder.Properties.Resources.Hourglass; } } }
public Texture Texture { get { lock(this) { return texture; } } }
public bool IsLoaded { get { return (bitmap != null) && (loadstate != ImageData.LOADSTATE_LOAD); } }
public bool IsPreviewLoaded { get { lock(this) { return (previewstate == ImageLoadState.Ready); } } }
public bool IsImageLoaded { get { lock(this) { return (imagestate == ImageLoadState.Ready); } } }
public bool IsDisposed { get { return isdisposed; } }
internal bool Temporary { get { return temporary; } set { temporary = value; } }
internal int LoadState { get { return loadstate; } set { loadstate = value; } }
internal LinkedListNode<ImageData> LoadingTicket { get { return loadingticket; } set { loadingticket = value; } }
internal ImageLoadState ImageState { get { return imagestate; } set { imagestate = value; } }
internal ImageLoadState PreviewState { get { return previewstate; } set { previewstate = value; } }
internal LinkedListNode<ImageData> ProcessTicket { get { return processticket; } set { processticket = value; } }
internal bool IsReferenced { get { return (references > 0) || usedinmap; } }
internal bool UsedInMap { get { return usedinmap; } set { usedinmap = value; } }
public int MipMapLevels { get { return mipmaplevels; } set { mipmaplevels = value; } }
public int Width { get { return width; } }
public int Height { get { return height; } }
@ -120,9 +119,12 @@ namespace CodeImp.DoomBuilder.Data
if(texture != null) texture.Dispose();
bitmap = null;
texture = null;
pixeldata = null;
// Done
usedinmap = false;
references = 0;
imagestate = ImageLoadState.None;
previewstate = ImageLoadState.None;
isdisposed = true;
}
}
@ -132,6 +134,19 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Management
// This adds a reference
public void AddReference()
{
references++;
}
// This removes a reference
public void RemoveReference()
{
references--;
if(references < 0) General.Fail("FAIL! (references < 0)", "Somewhere this image is dereferenced more than it was referenced.");
}
// This sets the name
protected void SetName(string name)
{
@ -146,7 +161,7 @@ namespace CodeImp.DoomBuilder.Data
{
if(bitmap != null) bitmap.Dispose();
bitmap = null;
loadstate = ImageData.LOADSTATE_NONE;
imagestate = ImageLoadState.None;
}
}
@ -155,10 +170,8 @@ namespace CodeImp.DoomBuilder.Data
{
BitmapData bmpdata = null;
// Determine amounts
float gamma = (float)(General.Settings.ImageBrightness + 10) * 0.1f;
float bright = (float)General.Settings.ImageBrightness * 5f;
lock(this)
{
// This applies brightness correction on the image
if((bitmap != null) && usecolorcorrection)
{
@ -176,45 +189,14 @@ namespace CodeImp.DoomBuilder.Data
if(bmpdata != null)
{
// Apply color correction
byte* pixels = (byte*)(bmpdata.Scan0.ToPointer());
for(int p = 0; p < bmpdata.Stride * bmpdata.Height; p += 4)
{
// Apply color correction for individual colors
float r = (float)pixels[p + 0] * gamma + bright;
float g = (float)pixels[p + 1] * gamma + bright;
float b = (float)pixels[p + 2] * gamma + bright;
// Clamp to 0..255 range
if(r < 0f) pixels[p + 0] = 0; else if(r > 255f) pixels[p + 0] = 255; else pixels[p + 0] = (byte)r;
if(g < 0f) pixels[p + 1] = 0; else if(g > 255f) pixels[p + 1] = 255; else pixels[p + 1] = (byte)g;
if(b < 0f) pixels[p + 2] = 0; else if(b > 255f) pixels[p + 2] = 255; else pixels[p + 2] = (byte)b;
}
// Done with the lock
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
General.Colors.ApplColorCorrection(pixels, bmpdata.Width * bmpdata.Height);
bitmap.UnlockBits(bmpdata);
}
}
// Done, reset load state
loadstate = ImageData.LOADSTATE_NONE;
}
// This creates the 2D pixel data
internal virtual void CreatePixelData()
{
BitmapData bmpdata;
lock(this)
{
// Only do this when data is not created yet
if((pixeldata == null) && IsLoaded)
{
// Make a data copy of the bits for the 2D renderer
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
pixeldata = new PixelColorBlock(bitmap.Size.Width, bitmap.Size.Height);
General.CopyMemory((void*)pixeldata.Pointer, bmpdata.Scan0.ToPointer(), new UIntPtr(pixeldata.Length));
bitmap.UnlockBits(bmpdata);
}
// Image is ready
imagestate = ImageLoadState.Ready;
}
}
@ -226,7 +208,7 @@ namespace CodeImp.DoomBuilder.Data
lock(this)
{
// Only do this when texture is not created yet
if(((texture == null) || (texture.Disposed)) && IsLoaded)
if(((texture == null) || (texture.Disposed)) && this.IsLoaded)
{
// Write to memory stream and read from memory
memstream = new MemoryStream();

View file

@ -0,0 +1,43 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Drawing;
using SlimDX.Direct3D9;
using System.Drawing.Imaging;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.IO;
using System.IO;
using System.Windows.Forms;
#endregion
namespace CodeImp.DoomBuilder.Data
{
internal enum ImageLoadState : int
{
None,
Loading,
Ready,
Unloading
}
}

View file

@ -138,6 +138,14 @@ namespace CodeImp.DoomBuilder.Data
if(GetAtlasIndex(nextpreviewindex) > (atlases.Count - 1)) MakeNewAtlas();
}
// Background loading
// Return true when we have more work to do, so that the
// thread will not wait too long before calling again
internal bool BackgroundLoad()
{
}
#endregion

View file

@ -99,6 +99,9 @@ namespace CodeImp.DoomBuilder.Rendering
private PixelColor[] brightcolors;
private PixelColor[] darkcolors;
// Color-correction table
private byte[] correctiontable;
#endregion
#region ================== Properties
@ -174,24 +177,8 @@ namespace CodeImp.DoomBuilder.Rendering
// Create assist colors
CreateAssistColors();
// We have no destructor
GC.SuppressFinalize(this);
}
// Copy constructor
internal ColorCollection(ColorCollection collection)
{
// Initialize
colors = new PixelColor[NUM_COLORS];
brightcolors = new PixelColor[NUM_COLORS];
darkcolors = new PixelColor[NUM_COLORS];
// Copy all colors
for(int i = 0; i < NUM_COLORS; i++)
colors[i] = collection.colors[i];
// Create assist colors
CreateAssistColors();
// Create color correction table
General.Colors.CreateCorrectionTable();
// We have no destructor
GC.SuppressFinalize(this);
@ -201,6 +188,37 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Methods
// This generates a color-correction table
internal void CreateCorrectionTable()
{
// Determine amounts
float gamma = (float)(General.Settings.ImageBrightness + 10) * 0.1f;
float bright = (float)General.Settings.ImageBrightness * 5f;
// Make table
correctiontable = new byte[256];
// Fill table
for(int i = 0; i < 256; i++)
{
byte b;
float a = (float)i * gamma + bright;
if(a < 0f) b = 0; else if(a > 255f) b = 255; else b = (byte)a;
correctiontable[i] = b;
}
}
// This applies color-correction over a block of pixel data
internal unsafe void ApplColorCorrection(PixelColor* pixels, int numpixels)
{
for(int i = 0; i < numpixels; i++)
{
pixels[i].r = correctiontable[pixels[i].r];
pixels[i].g = correctiontable[pixels[i].g];
pixels[i].b = correctiontable[pixels[i].b];
}
}
// This clamps a value between 0 and 1
private float Saturate(float v)
{
@ -233,17 +251,6 @@ namespace CodeImp.DoomBuilder.Rendering
}
}
// This applies colors to this collection
internal void Apply(ColorCollection collection)
{
// Copy all colors
for(int i = 0; i < NUM_COLORS; i++)
colors[i] = collection.colors[i];
// Rebuild assist colors
CreateAssistColors();
}
// This saves colors to configuration
internal void SaveColors(Configuration cfg)
{

View file

@ -1695,6 +1695,9 @@ namespace CodeImp.DoomBuilder.Windows
// Update shortcut keys in menus
ApplyShortcutKeys();
// Generate new color correction table
General.Colors.CreateCorrectionTable();
// Let the plugins know
General.Plugins.ProgramReconfigure();