View of /trunk/DefaultRenderer/DefaultTexture.cs
Parent Directory
|
Revision Log
Revision 84 -
(download)
(annotate)
Tue Dec 9 10:52:56 2008 UTC (4 years, 5 months ago) by albert
File size: 10247 byte(s)
Tue Dec 9 10:52:56 2008 UTC (4 years, 5 months ago) by albert
File size: 10247 byte(s)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xenki.Framework;
using OpenMetaverse;
using System.Drawing;
using System.IO;
using System.Threading;
using OpenMetaverse.Imaging;
using System.Runtime.InteropServices;
namespace Xenki.DefaultRenderer
{
public class DefaultTexture
{
private event TextureDownloadFinished onDownloadFinished;
string cachefolderPath = Mainform.TextureCacheFolder;
string bmpFilePath = Mainform.TextureTempFolder;
//the textures have load in memory.
// private readonly Dictionary<UUID, byte[]> CurruntTextures = new Dictionary<UUID, byte[]>();
private Thread MainThread;
// list of current requests in process
private Dictionary<UUID, int> CurrentRequests;
//private ReaderWriterLockSlim rwCurrentRequests = new ReaderWriterLockSlim();
private Queue<UUID> RequestQueue;
//private ReaderWriterLockSlim rwRequestQueue = new ReaderWriterLockSlim();
private static AutoResetEvent[] resetEvents;
private static int[] threadpoolSlots;
// maximum allowed concurrent requests at once
const int MAX_TEXTURE_REQUESTS = 5;
private GridClient gridClient;
public GridClient GridClient
{
get { return gridClient; }
set
{
gridClient = value;
gridClient.Settings.USE_TEXTURE_CACHE = true;
if (Directory.Exists(cachefolderPath) == false)
Directory.CreateDirectory(cachefolderPath);
if (Directory.Exists(bmpFilePath) == false)
Directory.CreateDirectory(bmpFilePath);
gridClient.Throttle.Texture = 440000.0f;
gridClient.Settings.TEXTURE_CACHE_DIR = cachefolderPath;
gridClient.Settings.TEXTURE_CACHE_MAX_SIZE = 700;//Mb
}
}
private static readonly DefaultTexture singleton = new DefaultTexture();
public static DefaultTexture SingleTextureManager()
{
return singleton;
}
private DefaultTexture()
{
RequestQueue = new Queue<UUID>();
CurrentRequests = new Dictionary<UUID, int>(MAX_TEXTURE_REQUESTS);
resetEvents = new AutoResetEvent[MAX_TEXTURE_REQUESTS];
threadpoolSlots = new int[MAX_TEXTURE_REQUESTS];
// pre-configure autoreset events/download slots
for (int i = 0; i < MAX_TEXTURE_REQUESTS; i++)
{
resetEvents[i] = new AutoResetEvent(false);
threadpoolSlots[i] = -1;
}
}
public void StartDownload()
{
try
{
GridClient.Assets.OnImageReceived += new AssetManager.ImageReceivedCallback(Assets_OnImageReceived);
MainThread = new Thread(new ThreadStart(DownloadTextureThread));
MainThread.Start();
}
catch (Exception er)
{
Logger.DebugLog(er.Message);
}
}
private void DownloadTextureThread()
{
int reqNbr;
while (true)
{
lock (RequestQueue)
//rwRequestQueue.EnterUpgradeableReadLock();
{
if (RequestQueue.Count > 0)
{
reqNbr = -1;
// find available slot for reset event
for (int i = 0; i < threadpoolSlots.Length; i++)
{
if (threadpoolSlots[i] == -1)
{
threadpoolSlots[i] = 1;
reqNbr = i;
break;
}
}
if (reqNbr != -1)
{
UUID requestID;
//rwRequestQueue.EnterWriteLock();
requestID = RequestQueue.Dequeue();
//rwRequestQueue.ExitWriteLock();
Logger.DebugLog(String.Format("Sending Worker thread new download request {0}", reqNbr));
ThreadPool.QueueUserWorkItem(new WaitCallback(textureRequestDoWork), new TaskInfo(requestID, reqNbr));
//rwRequestQueue.ExitUpgradeableReadLock();
continue;
}
}
}
// rwRequestQueue.ExitUpgradeableReadLock();
Thread.Sleep(500);
}
}
void textureRequestDoWork(Object threadContext)
{
TaskInfo ti = (TaskInfo)threadContext;
//rwCurrentRequests.EnterWriteLock();
lock (CurrentRequests)
{
if (CurrentRequests.ContainsKey(ti.RequestID))
{
threadpoolSlots[ti.RequestNbr] = -1;
return;
}
else
{
CurrentRequests.Add(ti.RequestID, ti.RequestNbr);
}
}
//rwCurrentRequests.ExitWriteLock();
Logger.DebugLog(String.Format("Worker {0} Requesting {1}", ti.RequestNbr, ti.RequestID));
resetEvents[ti.RequestNbr].Reset();
GridClient.Assets.RequestImage(ti.RequestID, ImageType.Normal);
// don't release this worker slot until texture is downloaded or timeout occurs
if (!resetEvents[ti.RequestNbr].WaitOne(30 * 1000, false))
{
// Timed out
Logger.Log("Worker " + ti.RequestNbr + " Timeout waiting for Texture " + ti.RequestID + " to Download", Helpers.LogLevel.Warning);
//rwCurrentRequests.EnterWriteLock();
lock (CurrentRequests)
CurrentRequests.Remove(ti.RequestID);
//rwCurrentRequests.ExitWriteLock();
//rwRequestQueue.EnterWriteLock();
lock (RequestQueue)
RequestQueue.Enqueue(ti.RequestID);
//rwRequestQueue.ExitWriteLock();
}
// free up this download slot
threadpoolSlots[ti.RequestNbr] = -1;
ti = null;
}
private void Assets_OnImageReceived(ImageDownload image, AssetTexture asset)
{
if (image.Success)
{
lock (objFileAccess)
if (File.Exists(Path.Combine(bmpFilePath, image.ID.ToString() + ".png")) == false)
{
SaveTexture2Image(image);
}
}
if (onDownloadFinished != null)
{
onDownloadFinished(image.ID, image.Success);
}
}
ManagedImage managedimg;
Image img; Bitmap bitmap;
private void SaveTexture2Image(ImageDownload image)
{
if (OpenJPEG.DecodeToImage(image.AssetData, out managedimg, out img))
{
bitmap = new Bitmap(img);
bitmap.Save(Path.Combine(bmpFilePath, image.ID.ToString() + ".png"),
System.Drawing.Imaging.ImageFormat.Png);
}
}
public ImageDownload RetireveTextureData(UUID textureID)
{
ImageDownload image =null;
if (gridClient.Assets.Cache.HasImage(textureID))
{
image = gridClient.Assets.Cache.GetCachedImage(textureID);
}
else
{
//rwCurrentRequests.EnterReadLock();
//rwRequestQueue.EnterWriteLock();
lock (RequestQueue)
{
// Make sure we aren't already downloading the texture
if (!RequestQueue.Contains(textureID)&& !CurrentRequests.ContainsKey(textureID))
{
RequestQueue.Enqueue(textureID);
}
}
//rwRequestQueue.ExitWriteLock();
// rwCurrentRequests.ExitReadLock();
}
return image;
}
public void RequestTexture(UUID textureID)
{
// lock (objFileAccess)
{
//if (File.Exists(Path.Combine(bmpFilePath, textureID.ToString() + ".png")) == true)
// return;
if (gridClient.Assets.Cache.HasImage(textureID) == false)
{
//rwRequestQueue.EnterWriteLock();
//rwCurrentRequests.EnterReadLock();
lock (RequestQueue)
{
// Make sure we aren't already downloading the texture
if (!CurrentRequests.ContainsKey(textureID) && !RequestQueue.Contains(textureID))
RequestQueue.Enqueue(textureID);
}
//rwCurrentRequests.ExitReadLock();
//rwRequestQueue.ExitWriteLock();
}
}
}
object objFileAccess = new object();
public TextureDownloadFinished OnDownloadFinished
{
get
{
return onDownloadFinished;
}
set
{
onDownloadFinished = value;
}
}
}
class TaskInfo
{
public UUID RequestID;
public int RequestNbr;
public TaskInfo(UUID reqID, int reqNbr)
{
RequestID = reqID;
RequestNbr = reqNbr;
}
}
}
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

