/// <summary> /// Requests an image for an object. /// </summary> /// <param name="assetID"></param> /// <param name="requestor"></param> public void RequestImage(UUID assetID, VObject requestor) { TextureExtended tex = null; lock (memoryTextures) { if (memoryTextures.ContainsKey(assetID)) { tex = memoryTextures[assetID]; } } if (tex != null) { // We already have the texture, jump to applyTexture applyTexture(tex, requestor, assetID); // Apply the texture to all objects that are already waiting for this texture lock (outstandingRequests) { if (outstandingRequests.ContainsKey(assetID)) { m_log.Warn("[TEXTURE]: Applying texture from memory to outstanding requestors."); foreach (VObject vObj in outstandingRequests[assetID]) { applyTexture(tex, vObj, assetID); } outstandingRequests.Remove(assetID); } } return; } // Check to see if we've got the texture on disk string texturefolderpath = imagefolder; bool alreadyRequesting = false; lock (outstandingRequests) { if (outstandingRequests.ContainsKey(assetID)) { alreadyRequesting = true; } } if (!alreadyRequesting && File.Exists(System.IO.Path.Combine(texturefolderpath, assetID.ToString() + ".tga"))) { Texture texTnorm = Reference.VideoDriver.GetTexture(System.IO.Path.Combine(texturefolderpath, assetID.ToString() + ".tga")); if (texTnorm != null) tex = new TextureExtended(texTnorm.Raw, ".tga"); if (tex != null) { lock (memoryTextures) { if (!memoryTextures.ContainsKey(assetID)) { // Add it to the texture cache. memoryTextures.Add(assetID, tex); } } // apply texture applyTexture(tex, requestor, assetID); // Apply the texture to all objects that are already waiting for this texture lock (outstandingRequests) { if (outstandingRequests.ContainsKey(assetID)) { m_log.Warn("[TEXTURE]: Applying texture from memory to outstanding requestors."); foreach (VObject vObj in outstandingRequests[assetID]) { applyTexture(tex, vObj, assetID); } outstandingRequests.Remove(assetID); } } return; } } // Check if we've already got an outstanding request for this texture lock (outstandingRequests) { if (outstandingRequests.ContainsKey(assetID)) { // Add it to the objects to be notified when this texture download is complete. outstandingRequests[assetID].Add(requestor); return; } else { // Create a new outstanding request entry List<VObject> requestors = new List<VObject>(); requestors.Add(requestor); outstandingRequests.Add(assetID,requestors); } } if (string.IsNullOrEmpty(Reference.Viewer.ProtocolManager.AvatarConnection.m_user.Network.AssetServerUri)) { this.texDownloadStyle = TextureDownloadStyle.TEX_DOWNLOAD_LIBOMV; } TextureDownloadRequest req = new TextureDownloadRequest(); req.uuid = assetID; downloadTextureQueue.Enqueue(req); // no need to lock b/c it's a BlockingQueue which needs no synchronization m_log.Info("[TEXTURE]: Added to DownloadTextureQueue current count " + downloadTextureQueue.Count); /* if (this.texDownloadStyle == TextureDownloadStyle.TEX_DOWNLOAD_LIBOMV) { // Request texture from LibOMV m_user.RequestTexture(assetID); } else { // request texture directly from assetserver via our own background thread TextureDownloadRequest req = new TextureDownloadRequest(); req.uuid = assetID; downloadTextureQueue.Enqueue(req); // no need to lock b/c it's a BlockingQueue which needs no synchronization } */ }
/// <summary> /// This loop constantly checks the downloadTextureQueue and processes the items in it /// </summary> void TextureFetchHandler() { // Add an initial wait so that prims can download to a satisfactory level before textures clog up the tubes // Thread.Sleep(10000); while (true) { // Limit outstanding requests // outstandingRequests is not increased when synchronous download is used if (downloadQueue.Count > 4) { List<UUID> pruneList = new List<UUID>(); foreach (KeyValuePair<UUID, long[]> kvp in downloadQueue) { if (kvp.Value[3] < System.DateTime.Now.Ticks - 300000000) pruneList.Add(kvp.Key); } foreach (UUID uuid in pruneList) { downloadQueue.Remove(uuid); Reference.Viewer.ProtocolManager.AvatarConnection.CancelTexture(uuid); TextureDownloadRequest req = new TextureDownloadRequest(); req.uuid = uuid; downloadTextureQueue.Enqueue(req); m_log.Debug("[TEXTUREMANAGER]: Pruned request: " + uuid); } Thread.Sleep(500); } else { // Get the next download request and process it TextureDownloadRequest req = null; req = downloadTextureQueue.Dequeue(); // blocking if (req != null) { if (this.texDownloadStyle == TextureDownloadStyle.TEX_DOWNLOAD_LIBOMV) { // Send RequestImage to server if (!downloadQueue.ContainsKey(req.uuid)) { downloadQueue.Add(req.uuid, new long[4]); downloadQueue[req.uuid][2] = 1; } downloadQueue[req.uuid][3] = System.DateTime.Now.Ticks; Reference.Viewer.ProtocolManager.AvatarConnection.RequestTexture(req.uuid); m_log.Info("[TEXTURE]: RequestedTexture " + req.uuid); } else { Reference.Viewer.IrrManager.IrrWorkItemQueue(new IrrManager.IrrWorkItem("TextureFetchJob", new WorkItemCallback(TextureFetchJob), req)); } } req = null; } } }
/// <summary> /// Requests an image for an object. /// </summary> /// <param name="assetID"></param> /// <param name="requestor"></param> public void RequestImage(UUID assetID, VObject requestor) { TextureExtended tex = null; lock (memoryTextures) { if (memoryTextures.ContainsKey(assetID)) { tex = memoryTextures[assetID]; } } if (tex != null) { #if DebugTexturePipeline m_log.Debug("[3Di Mesh]: Already have texture in memory: " + assetID); #endif #if DebugTexturePipeline m_log.Debug("RequestImage 1 calling applyTexture"); #endif // We already have the texture, jump to applyTexture applyTexture(tex, requestor, assetID); // Apply the texture to all objects that are already waiting for this texture lock (ouststandingRequests) { if (ouststandingRequests.ContainsKey(assetID)) { m_log.Warn("[TEXTURE]: Applying texture from memory to outstanding requestors."); foreach (VObject vObj in ouststandingRequests[assetID]) { applyTexture(tex, vObj, assetID); } ouststandingRequests.Remove(assetID); } } return; } // Check to see if we've got the texture on disk string texturefolderpath = imagefolder; if (File.Exists(System.IO.Path.Combine(texturefolderpath, assetID.ToString() + ".tga"))) { Texture texTnorm = driver.GetTexture(System.IO.Path.Combine(texturefolderpath, assetID.ToString() + ".tga")); if (texTnorm != null) tex = new TextureExtended(texTnorm.Raw, ".tga"); if (tex != null) { #if DebugTexturePipeline m_log.Debug("[3Di Mesh]: Already have texture locally on disk: " + assetID); #endif lock (memoryTextures) { if (!memoryTextures.ContainsKey(assetID)) { // Add it to the texture cache. memoryTextures.Add(assetID, tex); } } #if DebugTexturePipeline m_log.Debug("RequestImage 2 calling applyTexture"); #endif // apply texture applyTexture(tex, requestor, assetID); // Apply the texture to all objects that are already waiting for this texture lock (ouststandingRequests) { if (ouststandingRequests.ContainsKey(assetID)) { m_log.Warn("[TEXTURE]: Applying texture from memory to outstanding requestors."); foreach (VObject vObj in ouststandingRequests[assetID]) { applyTexture(tex, vObj, assetID); } ouststandingRequests.Remove(assetID); } } return; } } // Check if we've already got an outstanding request for this texture lock (ouststandingRequests) { if (ouststandingRequests.ContainsKey(assetID)) { // Add it to the objects to be notified when this texture download is complete. ouststandingRequests[assetID].Add(requestor); #if YK_ADD_DEFAULT_TEXTURE applyTexture(null, requestor, assetID); #endif return; } else { // Create a new outstanding request entry List<VObject> requestors = new List<VObject>(); requestors.Add(requestor); ouststandingRequests.Add(assetID,requestors); } } #if DebugTexturePipeline m_log.Debug("[3Di Mesh]: Requesting from libomv the following texture: " + assetID); #endif if (string.IsNullOrEmpty(m_user.m_user.Network.AssetServerUri)) { this.texDownloadStyle = TextureDownloadStyle.TEX_DOWNLOAD_LIBOMV; } TextureDownloadRequest req = new TextureDownloadRequest(); req.uuid = assetID; downloadTextureQueue.Enqueue(req); // no need to lock b/c it's a BlockingQueue which needs no synchronization m_log.Info("[TEXTURE]: Added to DownloadTextureQueue current count " + downloadTextureQueue.Count); /* if (this.texDownloadStyle == TextureDownloadStyle.TEX_DOWNLOAD_LIBOMV) { // Request texture from LibOMV m_user.RequestTexture(assetID); } else { // request texture directly from assetserver via our own background thread TextureDownloadRequest req = new TextureDownloadRequest(); req.uuid = assetID; downloadTextureQueue.Enqueue(req); // no need to lock b/c it's a BlockingQueue which needs no synchronization } */ }