Annotation of /trunk/DefaultRenderer/DefaultTexture.cs
Parent Directory
|
Revision Log
Revision 115 - (view) (download)
| 1 : | albert | 90 | /* |
| 2 : | * this class quoted code from: | ||
| 3 : | * http://www.openmetaverse.org/viewvc/index.cgi/omf/libopenmetaverse/trunk/Programs/PrimWorkshop/TexturePipeline.cs?view=markup | ||
| 4 : | * | ||
| 5 : | */ | ||
| 6 : | |||
| 7 : | using System; | ||
| 8 : | albert | 54 | using System.Collections.Generic; |
| 9 : | using System.Linq; | ||
| 10 : | using System.Text; | ||
| 11 : | using System.Drawing; | ||
| 12 : | using System.IO; | ||
| 13 : | using System.Threading; | ||
| 14 : | albert | 58 | using System.Runtime.InteropServices; |
| 15 : | albert | 87 | using Xenki.Framework; |
| 16 : | using OpenMetaverse.Imaging; | ||
| 17 : | using OpenMetaverse; | ||
| 18 : | using Xenki.References; | ||
| 19 : | albert | 89 | using log4net; |
| 20 : | using System.Reflection; | ||
| 21 : | albert | 54 | |
| 22 : | namespace Xenki.DefaultRenderer | ||
| 23 : | { | ||
| 24 : | |||
| 25 : | albert | 102 | public class DefaultTexture :ITextureManage |
| 26 : | albert | 54 | { |
| 27 : | albert | 115 | |
| 28 : | //texture downloaded folder in the user machines. | ||
| 29 : | albert | 87 | private string cachefolderPath = EnvironmentSettings.TextureCacheFolder; |
| 30 : | private string bmpFilePath = EnvironmentSettings.TextureTempFolder; | ||
| 31 : | albert | 89 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
| 32 : | albert | 87 | |
| 33 : | albert | 54 | private Thread MainThread; |
| 34 : | // list of current requests in process | ||
| 35 : | private Dictionary<UUID, int> CurrentRequests; | ||
| 36 : | albert | 115 | |
| 37 : | albert | 54 | private Queue<UUID> RequestQueue; |
| 38 : | private static AutoResetEvent[] resetEvents; | ||
| 39 : | |||
| 40 : | private static int[] threadpoolSlots; | ||
| 41 : | |||
| 42 : | // maximum allowed concurrent requests at once | ||
| 43 : | albert | 91 | const int MAX_TEXTURE_REQUESTS = EnvironmentSettings.DownloadTextureThreadNumber; |
| 44 : | albert | 54 | |
| 45 : | private GridClient gridClient; | ||
| 46 : | |||
| 47 : | public GridClient GridClient | ||
| 48 : | { | ||
| 49 : | get { return gridClient; } | ||
| 50 : | set | ||
| 51 : | { | ||
| 52 : | gridClient = value; | ||
| 53 : | } | ||
| 54 : | } | ||
| 55 : | albert | 87 | |
| 56 : | #region Singleton | ||
| 57 : | |||
| 58 : | albert | 90 | private static volatile DefaultTexture singleton = new DefaultTexture(); |
| 59 : | albert | 54 | |
| 60 : | public static DefaultTexture SingleTextureManager() | ||
| 61 : | { | ||
| 62 : | return singleton; | ||
| 63 : | } | ||
| 64 : | |||
| 65 : | private DefaultTexture() | ||
| 66 : | { | ||
| 67 : | RequestQueue = new Queue<UUID>(); | ||
| 68 : | CurrentRequests = new Dictionary<UUID, int>(MAX_TEXTURE_REQUESTS); | ||
| 69 : | |||
| 70 : | resetEvents = new AutoResetEvent[MAX_TEXTURE_REQUESTS]; | ||
| 71 : | threadpoolSlots = new int[MAX_TEXTURE_REQUESTS]; | ||
| 72 : | |||
| 73 : | // pre-configure autoreset events/download slots | ||
| 74 : | for (int i = 0; i < MAX_TEXTURE_REQUESTS; i++) | ||
| 75 : | { | ||
| 76 : | resetEvents[i] = new AutoResetEvent(false); | ||
| 77 : | threadpoolSlots[i] = -1; | ||
| 78 : | } | ||
| 79 : | } | ||
| 80 : | |||
| 81 : | albert | 87 | #endregion |
| 82 : | |||
| 83 : | albert | 54 | 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 : | albert | 89 | m_log.Error(er); |
| 95 : | albert | 54 | Logger.DebugLog(er.Message); |
| 96 : | } | ||
| 97 : | } | ||
| 98 : | |||
| 99 : | private void DownloadTextureThread() | ||
| 100 : | { | ||
| 101 : | int reqNbr; | ||
| 102 : | |||
| 103 : | while (true) | ||
| 104 : | { | ||
| 105 : | albert | 90 | if (RequestQueue.Count > 0) |
| 106 : | albert | 54 | { |
| 107 : | albert | 90 | reqNbr = -1; |
| 108 : | // find available slot for reset event | ||
| 109 : | for (int i = 0; i < threadpoolSlots.Length; i++) | ||
| 110 : | albert | 54 | { |
| 111 : | albert | 90 | if (threadpoolSlots[i] == -1) |
| 112 : | albert | 54 | { |
| 113 : | albert | 90 | threadpoolSlots[i] = 1; |
| 114 : | reqNbr = i; | ||
| 115 : | break; | ||
| 116 : | albert | 54 | } |
| 117 : | albert | 90 | } |
| 118 : | albert | 54 | |
| 119 : | albert | 90 | if (reqNbr != -1) |
| 120 : | { | ||
| 121 : | |||
| 122 : | UUID requestID; | ||
| 123 : | lock (RequestQueue) | ||
| 124 : | albert | 54 | requestID = RequestQueue.Dequeue(); |
| 125 : | |||
| 126 : | albert | 90 | Logger.DebugLog(String.Format("Sending Worker thread new download request {0}", reqNbr)); |
| 127 : | ThreadPool.QueueUserWorkItem(new WaitCallback(textureRequestDoWork), new TaskInfo(requestID, reqNbr)); | ||
| 128 : | albert | 54 | |
| 129 : | albert | 90 | continue; |
| 130 : | albert | 54 | } |
| 131 : | } | ||
| 132 : | |||
| 133 : | albert | 90 | Thread.Sleep(500); |
| 134 : | albert | 54 | } |
| 135 : | |||
| 136 : | } | ||
| 137 : | |||
| 138 : | albert | 115 | /// <summary> |
| 139 : | /// multi-thread downloading textures. | ||
| 140 : | /// </summary> | ||
| 141 : | /// <param name="threadContext">download task infomation </param> | ||
| 142 : | albert | 54 | void textureRequestDoWork(Object threadContext) |
| 143 : | albert | 89 | { |
| 144 : | albert | 54 | TaskInfo ti = (TaskInfo)threadContext; |
| 145 : | |||
| 146 : | albert | 84 | //rwCurrentRequests.EnterWriteLock(); |
| 147 : | albert | 54 | 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 : | albert | 84 | //rwCurrentRequests.ExitWriteLock(); |
| 160 : | albert | 54 | |
| 161 : | Logger.DebugLog(String.Format("Worker {0} Requesting {1}", ti.RequestNbr, ti.RequestID)); | ||
| 162 : | |||
| 163 : | resetEvents[ti.RequestNbr].Reset(); | ||
| 164 : | albert | 89 | GridClient.Assets.RequestImage(ti.RequestID, ImageType.Normal); |
| 165 : | albert | 54 | |
| 166 : | // don't release this worker slot until texture is downloaded or timeout occurs | ||
| 167 : | albert | 89 | if (!resetEvents[ti.RequestNbr].WaitOne(30 * 1000, false)) |
| 168 : | { | ||
| 169 : | // Timed out | ||
| 170 : | Logger.Log("Worker " + ti.RequestNbr + " Timeout waiting for Texture " + ti.RequestID + " to Download", Helpers.LogLevel.Warning); | ||
| 171 : | albert | 54 | |
| 172 : | albert | 89 | //rwCurrentRequests.EnterWriteLock(); |
| 173 : | lock (CurrentRequests) | ||
| 174 : | CurrentRequests.Remove(ti.RequestID); | ||
| 175 : | //rwCurrentRequests.ExitWriteLock(); | ||
| 176 : | albert | 54 | |
| 177 : | albert | 89 | //rwRequestQueue.EnterWriteLock(); |
| 178 : | //lock (RequestQueue) | ||
| 179 : | // RequestQueue.Enqueue(ti.RequestID); | ||
| 180 : | //rwRequestQueue.ExitWriteLock(); | ||
| 181 : | } | ||
| 182 : | albert | 84 | |
| 183 : | albert | 54 | // free up this download slot |
| 184 : | threadpoolSlots[ti.RequestNbr] = -1; | ||
| 185 : | ti = null; | ||
| 186 : | } | ||
| 187 : | |||
| 188 : | private void Assets_OnImageReceived(ImageDownload image, AssetTexture asset) | ||
| 189 : | { | ||
| 190 : | if (image.Success) | ||
| 191 : | { | ||
| 192 : | albert | 83 | lock (objFileAccess) |
| 193 : | albert | 104 | if (File.Exists(Path.Combine(bmpFilePath, |
| 194 : | image.ID.ToString() + References.EnvironmentSettings.TextureImageExtension)) == false) | ||
| 195 : | albert | 54 | { |
| 196 : | albert | 62 | SaveTexture2Image(image); |
| 197 : | albert | 54 | } |
| 198 : | } | ||
| 199 : | |||
| 200 : | albert | 103 | if (OnDownloadFinished != null) |
| 201 : | albert | 54 | { |
| 202 : | albert | 103 | OnDownloadFinished(image.ID, image.Success); |
| 203 : | albert | 54 | } |
| 204 : | } | ||
| 205 : | albert | 84 | |
| 206 : | albert | 103 | ManagedImage managedimg=null; |
| 207 : | albert | 60 | Image img; Bitmap bitmap; |
| 208 : | albert | 58 | private void SaveTexture2Image(ImageDownload image) |
| 209 : | albert | 54 | { |
| 210 : | albert | 103 | bool alpha = false; |
| 211 : | |||
| 212 : | albert | 54 | if (OpenJPEG.DecodeToImage(image.AssetData, out managedimg, out img)) |
| 213 : | { | ||
| 214 : | albert | 103 | |
| 215 : | if (managedimg != null) | ||
| 216 : | { | ||
| 217 : | if ((managedimg.Channels & ManagedImage.ImageChannels.Alpha) != 0) | ||
| 218 : | alpha = true; | ||
| 219 : | } | ||
| 220 : | //System.Drawing.Image pngimage = new Bitmap(img); | ||
| 221 : | albert | 60 | bitmap = new Bitmap(img); |
| 222 : | albert | 104 | |
| 223 : | albert | 103 | //if (alpha) |
| 224 : | // bitmap.MakeTransparent(); | ||
| 225 : | albert | 104 | //System.Drawing.Imaging.EncoderParameters eps = new System.Drawing.Imaging.EncoderParameters(); |
| 226 : | //eps.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth | ||
| 227 : | albert | 103 | |
| 228 : | albert | 104 | bitmap.Save(Path.Combine(bmpFilePath, image.ID.ToString() + |
| 229 : | References.EnvironmentSettings.TextureImageExtension)); | ||
| 230 : | albert | 54 | } |
| 231 : | } | ||
| 232 : | |||
| 233 : | albert | 115 | /// <summary> |
| 234 : | /// get the texture image via texture id | ||
| 235 : | /// </summary> | ||
| 236 : | /// <param name="textureID"></param> | ||
| 237 : | /// <returns></returns> | ||
| 238 : | albert | 54 | public ImageDownload RetireveTextureData(UUID textureID) |
| 239 : | { | ||
| 240 : | ImageDownload image =null; | ||
| 241 : | |||
| 242 : | if (gridClient.Assets.Cache.HasImage(textureID)) | ||
| 243 : | { | ||
| 244 : | image = gridClient.Assets.Cache.GetCachedImage(textureID); | ||
| 245 : | } | ||
| 246 : | else | ||
| 247 : | { | ||
| 248 : | lock (RequestQueue) | ||
| 249 : | { | ||
| 250 : | // Make sure we aren't already downloading the texture | ||
| 251 : | if (!RequestQueue.Contains(textureID)&& !CurrentRequests.ContainsKey(textureID)) | ||
| 252 : | { | ||
| 253 : | RequestQueue.Enqueue(textureID); | ||
| 254 : | } | ||
| 255 : | } | ||
| 256 : | } | ||
| 257 : | |||
| 258 : | return image; | ||
| 259 : | } | ||
| 260 : | albert | 115 | /// <summary> |
| 261 : | /// If the texture hasn't downloaded yet | ||
| 262 : | /// enter it into the download queue. | ||
| 263 : | /// </summary> | ||
| 264 : | /// <param name="textureID"></param> | ||
| 265 : | albert | 54 | public void RequestTexture(UUID textureID) |
| 266 : | albert | 84 | { |
| 267 : | albert | 90 | lock (objFileAccess) |
| 268 : | albert | 54 | { |
| 269 : | albert | 104 | if (File.Exists(Path.Combine(bmpFilePath, textureID.ToString() + |
| 270 : | References.EnvironmentSettings.TextureImageExtension)) == true) | ||
| 271 : | albert | 89 | return; |
| 272 : | albert | 90 | } |
| 273 : | if (gridClient.Assets.Cache.HasImage(textureID) == false) | ||
| 274 : | { | ||
| 275 : | //rwRequestQueue.EnterWriteLock(); | ||
| 276 : | //rwCurrentRequests.EnterReadLock(); | ||
| 277 : | lock (RequestQueue) | ||
| 278 : | albert | 54 | { |
| 279 : | albert | 90 | // Make sure we aren't already downloading the texture |
| 280 : | if (!CurrentRequests.ContainsKey(textureID) && !RequestQueue.Contains(textureID)) | ||
| 281 : | RequestQueue.Enqueue(textureID); | ||
| 282 : | albert | 54 | } |
| 283 : | albert | 90 | //rwCurrentRequests.ExitReadLock(); |
| 284 : | //rwRequestQueue.ExitWriteLock(); | ||
| 285 : | albert | 54 | } |
| 286 : | albert | 90 | else |
| 287 : | { | ||
| 288 : | albert | 91 | //lock (objFileAccess) |
| 289 : | //{ | ||
| 290 : | // ImageDownload d = gridClient.Assets.Cache.GetCachedImage(textureID); | ||
| 291 : | // SaveTexture2Image(d); | ||
| 292 : | //} | ||
| 293 : | albert | 90 | } |
| 294 : | |||
| 295 : | albert | 54 | } |
| 296 : | |||
| 297 : | object objFileAccess = new object(); | ||
| 298 : | albert | 103 | public event TextureDownloadFinished OnDownloadFinished; |
| 299 : | albert | 54 | |
| 300 : | albert | 102 | |
| 301 : | albert | 54 | } |
| 302 : | |||
| 303 : | class TaskInfo | ||
| 304 : | { | ||
| 305 : | public UUID RequestID; | ||
| 306 : | public int RequestNbr; | ||
| 307 : | |||
| 308 : | |||
| 309 : | public TaskInfo(UUID reqID, int reqNbr) | ||
| 310 : | { | ||
| 311 : | RequestID = reqID; | ||
| 312 : | RequestNbr = reqNbr; | ||
| 313 : | } | ||
| 314 : | } | ||
| 315 : | } |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

