Annotation of /trunk/DefaultRenderer/DefaultTexture.cs
Parent Directory
|
Revision Log
Revision 54 - (view) (download)
| 1 : | albert | 54 | using System; |
| 2 : | using System.Collections.Generic; | ||
| 3 : | using System.Linq; | ||
| 4 : | using System.Text; | ||
| 5 : | using Xenki.Framework; | ||
| 6 : | using OpenMetaverse; | ||
| 7 : | using System.Drawing; | ||
| 8 : | using System.IO; | ||
| 9 : | using System.Threading; | ||
| 10 : | using OpenMetaverse.Imaging; | ||
| 11 : | |||
| 12 : | namespace Xenki.DefaultRenderer | ||
| 13 : | { | ||
| 14 : | |||
| 15 : | public class DefaultTexture //: ITextureManage | ||
| 16 : | { | ||
| 17 : | |||
| 18 : | private event TextureDownloadFinished onDownloadFinished; | ||
| 19 : | |||
| 20 : | string cachefolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "textures"); | ||
| 21 : | |||
| 22 : | string bmpFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "texture"); | ||
| 23 : | |||
| 24 : | //the textures have load in memory. | ||
| 25 : | // private readonly Dictionary<UUID, byte[]> CurruntTextures = new Dictionary<UUID, byte[]>(); | ||
| 26 : | |||
| 27 : | private Thread MainThread; | ||
| 28 : | // list of current requests in process | ||
| 29 : | private Dictionary<UUID, int> CurrentRequests; | ||
| 30 : | |||
| 31 : | private Queue<UUID> RequestQueue; | ||
| 32 : | |||
| 33 : | private static AutoResetEvent[] resetEvents; | ||
| 34 : | |||
| 35 : | private static int[] threadpoolSlots; | ||
| 36 : | |||
| 37 : | |||
| 38 : | // maximum allowed concurrent requests at once | ||
| 39 : | const int MAX_TEXTURE_REQUESTS = 3; | ||
| 40 : | |||
| 41 : | private GridClient gridClient; | ||
| 42 : | |||
| 43 : | public GridClient GridClient | ||
| 44 : | { | ||
| 45 : | get { return gridClient; } | ||
| 46 : | set | ||
| 47 : | { | ||
| 48 : | gridClient = value; | ||
| 49 : | |||
| 50 : | gridClient.Settings.USE_TEXTURE_CACHE = true; | ||
| 51 : | if (Directory.Exists(cachefolderPath) == false) | ||
| 52 : | Directory.CreateDirectory(cachefolderPath); | ||
| 53 : | |||
| 54 : | gridClient.Settings.TEXTURE_CACHE_DIR = cachefolderPath; | ||
| 55 : | gridClient.Settings.TEXTURE_CACHE_MAX_SIZE = 5120;//M? or number? | ||
| 56 : | |||
| 57 : | } | ||
| 58 : | } | ||
| 59 : | private static readonly DefaultTexture singleton = new DefaultTexture(); | ||
| 60 : | |||
| 61 : | public static DefaultTexture SingleTextureManager() | ||
| 62 : | { | ||
| 63 : | return singleton; | ||
| 64 : | } | ||
| 65 : | |||
| 66 : | private DefaultTexture() | ||
| 67 : | { | ||
| 68 : | RequestQueue = new Queue<UUID>(); | ||
| 69 : | |||
| 70 : | CurrentRequests = new Dictionary<UUID, int>(MAX_TEXTURE_REQUESTS); | ||
| 71 : | |||
| 72 : | resetEvents = new AutoResetEvent[MAX_TEXTURE_REQUESTS]; | ||
| 73 : | threadpoolSlots = new int[MAX_TEXTURE_REQUESTS]; | ||
| 74 : | |||
| 75 : | // pre-configure autoreset events/download slots | ||
| 76 : | for (int i = 0; i < MAX_TEXTURE_REQUESTS; i++) | ||
| 77 : | { | ||
| 78 : | resetEvents[i] = new AutoResetEvent(false); | ||
| 79 : | threadpoolSlots[i] = -1; | ||
| 80 : | } | ||
| 81 : | } | ||
| 82 : | |||
| 83 : | public void StartDownload() | ||
| 84 : | { | ||
| 85 : | try | ||
| 86 : | { | ||
| 87 : | GridClient.Assets.OnImageReceived += new AssetManager.ImageReceivedCallback(Assets_OnImageReceived); | ||
| 88 : | |||
| 89 : | MainThread = new Thread(new ThreadStart(DownloadTextureThread)); | ||
| 90 : | MainThread.Start(); | ||
| 91 : | } | ||
| 92 : | catch (Exception er) | ||
| 93 : | { | ||
| 94 : | Logger.DebugLog(er.Message); | ||
| 95 : | } | ||
| 96 : | } | ||
| 97 : | //public void StopDownload() | ||
| 98 : | //{ | ||
| 99 : | |||
| 100 : | //} | ||
| 101 : | |||
| 102 : | private void DownloadTextureThread() | ||
| 103 : | { | ||
| 104 : | int reqNbr; | ||
| 105 : | |||
| 106 : | while (true) | ||
| 107 : | { | ||
| 108 : | if (RequestQueue.Count > 0) | ||
| 109 : | { | ||
| 110 : | reqNbr = -1; | ||
| 111 : | // find available slot for reset event | ||
| 112 : | for (int i = 0; i < threadpoolSlots.Length; i++) | ||
| 113 : | { | ||
| 114 : | if (threadpoolSlots[i] == -1) | ||
| 115 : | { | ||
| 116 : | threadpoolSlots[i] = 1; | ||
| 117 : | reqNbr = i; | ||
| 118 : | break; | ||
| 119 : | } | ||
| 120 : | } | ||
| 121 : | |||
| 122 : | if (reqNbr != -1) | ||
| 123 : | { | ||
| 124 : | |||
| 125 : | UUID requestID; | ||
| 126 : | lock (RequestQueue) | ||
| 127 : | requestID = RequestQueue.Dequeue(); | ||
| 128 : | |||
| 129 : | Logger.DebugLog(String.Format("Sending Worker thread new download request {0}", reqNbr)); | ||
| 130 : | ThreadPool.QueueUserWorkItem(new WaitCallback(textureRequestDoWork), new TaskInfo(requestID, reqNbr)); | ||
| 131 : | |||
| 132 : | //gridClient.Assets.RequestImage(requestID, ImageType.Normal); | ||
| 133 : | |||
| 134 : | continue; | ||
| 135 : | } | ||
| 136 : | } | ||
| 137 : | |||
| 138 : | Thread.Sleep(1000); | ||
| 139 : | } | ||
| 140 : | |||
| 141 : | } | ||
| 142 : | |||
| 143 : | void textureRequestDoWork(Object threadContext) | ||
| 144 : | { | ||
| 145 : | TaskInfo ti = (TaskInfo)threadContext; | ||
| 146 : | |||
| 147 : | lock (CurrentRequests) | ||
| 148 : | { | ||
| 149 : | if (CurrentRequests.ContainsKey(ti.RequestID)) | ||
| 150 : | { | ||
| 151 : | threadpoolSlots[ti.RequestNbr] = -1; | ||
| 152 : | return; | ||
| 153 : | } | ||
| 154 : | else | ||
| 155 : | { | ||
| 156 : | CurrentRequests.Add(ti.RequestID, ti.RequestNbr); | ||
| 157 : | } | ||
| 158 : | } | ||
| 159 : | |||
| 160 : | Logger.DebugLog(String.Format("Worker {0} Requesting {1}", ti.RequestNbr, ti.RequestID)); | ||
| 161 : | |||
| 162 : | resetEvents[ti.RequestNbr].Reset(); | ||
| 163 : | GridClient.Assets.RequestImage(ti.RequestID, ImageType.Normal); | ||
| 164 : | |||
| 165 : | // don't release this worker slot until texture is downloaded or timeout occurs | ||
| 166 : | if (!resetEvents[ti.RequestNbr].WaitOne(300 * 1000, false)) | ||
| 167 : | { | ||
| 168 : | // Timed out | ||
| 169 : | Logger.Log("Worker " + ti.RequestNbr + " Timeout waiting for Texture " + ti.RequestID + " to Download", Helpers.LogLevel.Warning); | ||
| 170 : | |||
| 171 : | lock (CurrentRequests) | ||
| 172 : | CurrentRequests.Remove(ti.RequestID); | ||
| 173 : | } | ||
| 174 : | |||
| 175 : | // free up this download slot | ||
| 176 : | threadpoolSlots[ti.RequestNbr] = -1; | ||
| 177 : | ti = null; | ||
| 178 : | } | ||
| 179 : | |||
| 180 : | private void Assets_OnImageReceived(ImageDownload image, AssetTexture asset) | ||
| 181 : | { | ||
| 182 : | if (image.Success) | ||
| 183 : | { | ||
| 184 : | //lock (CurruntTextures) | ||
| 185 : | //{ | ||
| 186 : | // if (!CurruntTextures.ContainsKey(image.ID)) | ||
| 187 : | // { | ||
| 188 : | // CurruntTextures.Add(image.ID, image.AssetData); | ||
| 189 : | // } | ||
| 190 : | // else | ||
| 191 : | // { | ||
| 192 : | // CurruntTextures.Remove(image.ID); | ||
| 193 : | // CurruntTextures.Add(image.ID, image.AssetData); | ||
| 194 : | // } | ||
| 195 : | //} | ||
| 196 : | lock(objFileAccess) | ||
| 197 : | if (File.Exists(Path.Combine(bmpFilePath, image.ID.ToString() + ".jpg")) == false) | ||
| 198 : | { | ||
| 199 : | //SaveTexture2Image(image); | ||
| 200 : | } | ||
| 201 : | } | ||
| 202 : | |||
| 203 : | if (onDownloadFinished != null) | ||
| 204 : | { | ||
| 205 : | onDownloadFinished(image.ID, image.Success); | ||
| 206 : | } | ||
| 207 : | } | ||
| 208 : | |||
| 209 : | private void SaveTexture2Image(ImageDownload image) | ||
| 210 : | { | ||
| 211 : | ManagedImage managedimg; | ||
| 212 : | Image img; | ||
| 213 : | //byte[] bytes = GetTextureDataByTextureID(downLoadedTextureID); | ||
| 214 : | |||
| 215 : | if (OpenJPEG.DecodeToImage(image.AssetData, out managedimg, out img)) | ||
| 216 : | { | ||
| 217 : | Bitmap bitmap = new Bitmap(img); | ||
| 218 : | bitmap.Save(Path.Combine(bmpFilePath, image.ID.ToString() + ".jpg"), System.Drawing.Imaging.ImageFormat.Jpeg); | ||
| 219 : | |||
| 220 : | bitmap.Dispose(); | ||
| 221 : | bitmap = null; | ||
| 222 : | } | ||
| 223 : | |||
| 224 : | img.Dispose(); | ||
| 225 : | img = null; | ||
| 226 : | managedimg = null; | ||
| 227 : | } | ||
| 228 : | |||
| 229 : | public ImageDownload RetireveTextureData(UUID textureID) | ||
| 230 : | { | ||
| 231 : | ImageDownload image =null; | ||
| 232 : | |||
| 233 : | if (gridClient.Assets.Cache.HasImage(textureID)) | ||
| 234 : | { | ||
| 235 : | image = gridClient.Assets.Cache.GetCachedImage(textureID); | ||
| 236 : | } | ||
| 237 : | else | ||
| 238 : | { | ||
| 239 : | lock (RequestQueue) | ||
| 240 : | { | ||
| 241 : | // Make sure we aren't already downloading the texture | ||
| 242 : | if (!RequestQueue.Contains(textureID)&& !CurrentRequests.ContainsKey(textureID)) | ||
| 243 : | { | ||
| 244 : | RequestQueue.Enqueue(textureID); | ||
| 245 : | } | ||
| 246 : | } | ||
| 247 : | } | ||
| 248 : | |||
| 249 : | return image; | ||
| 250 : | } | ||
| 251 : | |||
| 252 : | public void RequestTexture(UUID textureID) | ||
| 253 : | { | ||
| 254 : | //bool hasDownloaded = false; | ||
| 255 : | |||
| 256 : | //lock (CurruntTextures) | ||
| 257 : | //{ | ||
| 258 : | // if (CurruntTextures.ContainsKey(textureID)) | ||
| 259 : | // { | ||
| 260 : | // hasDownloaded = true; | ||
| 261 : | // } | ||
| 262 : | //} | ||
| 263 : | //if (hasDownloaded) | ||
| 264 : | // return; | ||
| 265 : | |||
| 266 : | //if (gridClient.Assets.Cache.HasImage(textureID)) | ||
| 267 : | //{ | ||
| 268 : | // // Add to rendering dictionary | ||
| 269 : | // lock (CurruntTextures) | ||
| 270 : | // { | ||
| 271 : | // if (!CurruntTextures.ContainsKey(textureID)) | ||
| 272 : | // { | ||
| 273 : | // CurruntTextures.Add(textureID, gridClient.Assets.Cache.GetCachedImage(textureID).AssetData); | ||
| 274 : | // } | ||
| 275 : | // } | ||
| 276 : | //} | ||
| 277 : | //else | ||
| 278 : | lock (objFileAccess) | ||
| 279 : | { | ||
| 280 : | if (File.Exists(Path.Combine(bmpFilePath, textureID.ToString() + ".jpg")) == false) | ||
| 281 : | { | ||
| 282 : | if (gridClient.Assets.Cache.HasImage(textureID) == false) | ||
| 283 : | { | ||
| 284 : | lock (RequestQueue) | ||
| 285 : | { | ||
| 286 : | // Make sure we aren't already downloading the texture | ||
| 287 : | if (!RequestQueue.Contains(textureID) && !CurrentRequests.ContainsKey(textureID)) | ||
| 288 : | { | ||
| 289 : | RequestQueue.Enqueue(textureID); | ||
| 290 : | } | ||
| 291 : | } | ||
| 292 : | } | ||
| 293 : | else | ||
| 294 : | { | ||
| 295 : | |||
| 296 : | // ImageDownload down = gridClient.Assets.Cache.GetCachedImage(textureID); | ||
| 297 : | // SaveTexture2Image(down); | ||
| 298 : | |||
| 299 : | } | ||
| 300 : | } | ||
| 301 : | } | ||
| 302 : | } | ||
| 303 : | |||
| 304 : | object objFileAccess = new object(); | ||
| 305 : | |||
| 306 : | public TextureDownloadFinished OnDownloadFinished | ||
| 307 : | { | ||
| 308 : | get | ||
| 309 : | { | ||
| 310 : | return onDownloadFinished; | ||
| 311 : | } | ||
| 312 : | set | ||
| 313 : | { | ||
| 314 : | onDownloadFinished = value; | ||
| 315 : | } | ||
| 316 : | } | ||
| 317 : | |||
| 318 : | |||
| 319 : | } | ||
| 320 : | |||
| 321 : | class TaskInfo | ||
| 322 : | { | ||
| 323 : | public UUID RequestID; | ||
| 324 : | public int RequestNbr; | ||
| 325 : | |||
| 326 : | |||
| 327 : | public TaskInfo(UUID reqID, int reqNbr) | ||
| 328 : | { | ||
| 329 : | RequestID = reqID; | ||
| 330 : | RequestNbr = reqNbr; | ||
| 331 : | } | ||
| 332 : | } | ||
| 333 : | } |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

