aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs8
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs152
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs81
3 files changed, 166 insertions, 75 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index 5ba5df1..6cffd70 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -260,7 +260,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
260 return false; 260 return false;
261 } 261 }
262 } 262 }
263 public bool SendPackets(LLClientView client) 263 public bool SendPackets(LLClientView client, int maxpack)
264 { 264 {
265 265
266 if (!m_completedSendAtCurrentDiscardLevel) 266 if (!m_completedSendAtCurrentDiscardLevel)
@@ -284,7 +284,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
284 } 284 }
285 285
286 int count = 0; 286 int count = 0;
287 while (SendMore && count < 5 && m_packetNumber <= m_stopPacket) 287 while (SendMore && count < maxpack && m_packetNumber <= m_stopPacket)
288 { 288 {
289 count++; 289 count++;
290 SendMore = SendPacket(client); 290 SendMore = SendPacket(client);
@@ -391,6 +391,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
391 } 391 }
392 } 392 }
393 } 393 }
394 else
395 {
396 m_packetNumber = m_stopPacket;
397 }
394 } 398 }
395 } 399 }
396 } 400 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index cda4d49..2884268 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -80,6 +80,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = 80 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates =
81 new List<ObjectUpdatePacket.ObjectDataBlock>(); 81 new List<ObjectUpdatePacket.ObjectDataBlock>();
82 82
83 private Timer m_textureRequestTimer;
84
83 private bool m_clientBlocked; 85 private bool m_clientBlocked;
84 86
85 private int m_probesWithNoIngressPackets; 87 private int m_probesWithNoIngressPackets;
@@ -140,6 +142,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
140 protected int m_primTerseUpdateRate = 10; 142 protected int m_primTerseUpdateRate = 10;
141 protected int m_primFullUpdateRate = 14; 143 protected int m_primFullUpdateRate = 14;
142 144
145 protected int m_textureRequestRate = 100;
146 protected int m_textureSendLimit = 10;
147 protected int m_textureDataLimit = 5;
148
143 protected int m_packetMTU = 1400; 149 protected int m_packetMTU = 1400;
144 150
145 protected IAssetService m_assetService; 151 protected IAssetService m_assetService;
@@ -344,6 +350,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
344 350
345 private readonly IGroupsModule m_GroupsModule; 351 private readonly IGroupsModule m_GroupsModule;
346 352
353 private AgentUpdateArgs lastarg = null;
354
347 //private TerrainUnacked handlerUnackedTerrain = null; 355 //private TerrainUnacked handlerUnackedTerrain = null;
348 356
349 //** 357 //**
@@ -544,6 +552,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
544 m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate", 552 m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate",
545 m_primFullUpdateRate); 553 m_primFullUpdateRate);
546 554
555 m_textureRequestRate = clientConfig.GetInt("TextureRequestRate",
556 m_textureRequestRate);
557
558 m_textureSendLimit = clientConfig.GetInt("TextureSendLimit",
559 m_textureSendLimit);
560
561 m_textureDataLimit = clientConfig.GetInt("TextureDataLimit",
562 m_textureDataLimit);
563
547 m_packetMTU = clientConfig.GetInt("PacketMTU", 1400); 564 m_packetMTU = clientConfig.GetInt("PacketMTU", 1400);
548 } 565 }
549 } 566 }
@@ -577,6 +594,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
577 m_avatarTerseUpdateTimer.Stop(); 594 m_avatarTerseUpdateTimer.Stop();
578 m_primTerseUpdateTimer.Stop(); 595 m_primTerseUpdateTimer.Stop();
579 m_primFullUpdateTimer.Stop(); 596 m_primFullUpdateTimer.Stop();
597 m_textureRequestTimer.Stop();
580 598
581 // This is just to give the client a reasonable chance of 599 // This is just to give the client a reasonable chance of
582 // flushing out all it's packets. There should probably 600 // flushing out all it's packets. There should probably
@@ -660,6 +678,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
660 m_avatarTerseUpdateTimer.Stop(); 678 m_avatarTerseUpdateTimer.Stop();
661 m_primTerseUpdateTimer.Stop(); 679 m_primTerseUpdateTimer.Stop();
662 m_primFullUpdateTimer.Stop(); 680 m_primFullUpdateTimer.Stop();
681 m_textureRequestTimer.Stop();
663 } 682 }
664 683
665 public void Restart() 684 public void Restart()
@@ -682,6 +701,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
682 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); 701 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
683 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); 702 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
684 m_primFullUpdateTimer.AutoReset = false; 703 m_primFullUpdateTimer.AutoReset = false;
704
705 m_textureRequestTimer = new Timer(m_textureRequestRate);
706 m_textureRequestTimer.Elapsed += new ElapsedEventHandler(ProcessTextureRequests);
707 m_textureRequestTimer.AutoReset = false;
708
685 } 709 }
686 710
687 public void Terminate() 711 public void Terminate()
@@ -914,6 +938,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
914 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); 938 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
915 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); 939 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
916 m_primFullUpdateTimer.AutoReset = false; 940 m_primFullUpdateTimer.AutoReset = false;
941
942 m_textureRequestTimer = new Timer(m_textureRequestRate);
943 m_textureRequestTimer.Elapsed += new ElapsedEventHandler(ProcessTextureRequests);
944 m_textureRequestTimer.AutoReset = false;
945
917 m_scene.AddNewClient(this); 946 m_scene.AddNewClient(this);
918 947
919 RefreshGroupMembership(); 948 RefreshGroupMembership();
@@ -985,6 +1014,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
985 } 1014 }
986 } 1015 }
987 1016
1017 protected virtual void TextureRequestHandler()
1018 {
1019 m_log.DebugFormat("[TRH] Thread started");
1020 while (m_imageManager != null)
1021 {
1022 try
1023 {
1024 while (m_imageManager != null)
1025 {
1026 }
1027 }
1028 catch (Exception e)
1029 {
1030 m_log.WarnFormat("[TRH] Exception in handler loop: {0}", e.Message);
1031 m_log.Debug(e);
1032 }
1033 }
1034 m_log.DebugFormat("[TRH] Thread terminated");
1035 }
1036
988 # endregion 1037 # endregion
989 1038
990 // Previously ClientView.API partial class 1039 // Previously ClientView.API partial class
@@ -3032,6 +3081,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3032 } 3081 }
3033 } 3082 }
3034 3083
3084 // Unlike the other timers, this one is only started after
3085 // the first request is seen.
3086
3087 void ProcessTextureRequests(object sender, ElapsedEventArgs e)
3088 {
3089 if (m_imageManager != null)
3090 {
3091 if (m_imageManager.ProcessImageQueue(m_textureSendLimit,
3092 m_textureDataLimit))
3093 {
3094 m_textureRequestTimer.Start();
3095 }
3096 }
3097 }
3098
3035 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3099 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e)
3036 { 3100 {
3037 lock (m_primFullUpdates) 3101 lock (m_primFullUpdates)
@@ -3237,7 +3301,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3237 ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) 3301 ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
3238 { 3302 {
3239 ImageDataPacket im = new ImageDataPacket(); 3303 ImageDataPacket im = new ImageDataPacket();
3240 im.Header.Reliable = true; 3304 im.Header.Reliable = false;
3241 im.ImageID.Packets = numParts; 3305 im.ImageID.Packets = numParts;
3242 im.ImageID.ID = ImageUUID; 3306 im.ImageID.ID = ImageUUID;
3243 3307
@@ -3253,7 +3317,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3253 public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) 3317 public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
3254 { 3318 {
3255 ImagePacketPacket im = new ImagePacketPacket(); 3319 ImagePacketPacket im = new ImagePacketPacket();
3256 im.Header.Reliable = true; 3320 im.Header.Reliable = false;
3257 im.ImageID.Packet = partNumber; 3321 im.ImageID.Packet = partNumber;
3258 im.ImageID.ID = imageUuid; 3322 im.ImageID.ID = imageUuid;
3259 im.ImageData.Data = imageData; 3323 im.ImageData.Data = imageData;
@@ -4727,14 +4791,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4727 /// <param name="Pack">OpenMetaverse.packet</param> 4791 /// <param name="Pack">OpenMetaverse.packet</param>
4728 public void ProcessInPacket(Packet Pack) 4792 public void ProcessInPacket(Packet Pack)
4729 { 4793 {
4730 // check if we've got a local packet handler for this packet.type. See RegisterLocalPacketHandlers() 4794
4731 if (ProcessPacketMethod(Pack)) 4795 if (ProcessPacketMethod(Pack))
4732 { 4796 {
4733 //there is a handler registered that handled this packet type
4734
4735 // in the end, we dereference this, so we have to check if it's null
4736 if (m_imageManager != null)
4737 m_imageManager.ProcessImageQueue(5);
4738 return; 4797 return;
4739 } 4798 }
4740 4799
@@ -5303,6 +5362,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5303 case PacketType.AgentUpdate: 5362 case PacketType.AgentUpdate:
5304 if (OnAgentUpdate != null) 5363 if (OnAgentUpdate != null)
5305 { 5364 {
5365 bool update = false;
5306 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; 5366 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5307 5367
5308 #region Packet Session and User Check 5368 #region Packet Session and User Check
@@ -5315,26 +5375,58 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5315 #endregion 5375 #endregion
5316 5376
5317 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; 5377 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
5318 AgentUpdateArgs arg = new AgentUpdateArgs();
5319 arg.AgentID = x.AgentID;
5320 arg.BodyRotation = x.BodyRotation;
5321 arg.CameraAtAxis = x.CameraAtAxis;
5322 arg.CameraCenter = x.CameraCenter;
5323 arg.CameraLeftAxis = x.CameraLeftAxis;
5324 arg.CameraUpAxis = x.CameraUpAxis;
5325 arg.ControlFlags = x.ControlFlags;
5326 arg.Far = x.Far;
5327 arg.Flags = x.Flags;
5328 arg.HeadRotation = x.HeadRotation;
5329 arg.SessionID = x.SessionID;
5330 arg.State = x.State;
5331 5378
5332 handlerAgentUpdate = OnAgentUpdate; 5379 // We can only check when we have something to check
5333 if (handlerAgentUpdate != null) 5380 // against.
5334 OnAgentUpdate(this, arg); 5381
5382 if (lastarg != null)
5383 {
5384 update =
5385 (
5386 (x.BodyRotation != lastarg.BodyRotation) ||
5387 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
5388 (x.CameraCenter != lastarg.CameraCenter) ||
5389 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5390 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5391 (x.ControlFlags != lastarg.ControlFlags) ||
5392 (x.Far != lastarg.Far) ||
5393 (x.Flags != lastarg.Flags) ||
5394 (x.State != lastarg.State) ||
5395 (x.HeadRotation != lastarg.HeadRotation) ||
5396 (x.SessionID != lastarg.SessionID) ||
5397 (x.AgentID != lastarg.AgentID)
5398 );
5399 }
5400 else
5401 update = true;
5402
5403 // These should be ordered from most-likely to
5404 // least likely to change. I've made an initial
5405 // guess at that.
5406
5407 if (update)
5408 {
5409 AgentUpdateArgs arg = new AgentUpdateArgs();
5410 arg.AgentID = x.AgentID;
5411 arg.BodyRotation = x.BodyRotation;
5412 arg.CameraAtAxis = x.CameraAtAxis;
5413 arg.CameraCenter = x.CameraCenter;
5414 arg.CameraLeftAxis = x.CameraLeftAxis;
5415 arg.CameraUpAxis = x.CameraUpAxis;
5416 arg.ControlFlags = x.ControlFlags;
5417 arg.Far = x.Far;
5418 arg.Flags = x.Flags;
5419 arg.HeadRotation = x.HeadRotation;
5420 arg.SessionID = x.SessionID;
5421 arg.State = x.State;
5422 handlerAgentUpdate = OnAgentUpdate;
5423 lastarg = arg; // save this set of arguments for nexttime
5424 if (handlerAgentUpdate != null)
5425 OnAgentUpdate(this, arg);
5426
5427 handlerAgentUpdate = null;
5428 }
5335 5429
5336 handlerAgentUpdate = null;
5337 //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa);
5338 } 5430 }
5339 break; 5431 break;
5340 5432
@@ -6392,10 +6484,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6392 6484
6393 // in the end, we null this, so we have to check if it's null 6485 // in the end, we null this, so we have to check if it's null
6394 if (m_imageManager != null) 6486 if (m_imageManager != null)
6487 {
6395 m_imageManager.EnqueueReq(args); 6488 m_imageManager.EnqueueReq(args);
6489 m_textureRequestTimer.Start();
6490 }
6396 } 6491 }
6397 } 6492 }
6398 break; 6493 break;
6494
6399 case PacketType.TransferRequest: 6495 case PacketType.TransferRequest:
6400 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); 6496 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
6401 6497
@@ -9502,10 +9598,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9502 #endregion 9598 #endregion
9503 } 9599 }
9504 9600
9505 // in the end, we dereference this, so we have to check if it's null
9506 if (m_imageManager != null)
9507 m_imageManager.ProcessImageQueue(10);
9508 PacketPool.Instance.ReturnPacket(Pack); 9601 PacketPool.Instance.ReturnPacket(Pack);
9602
9509 } 9603 }
9510 9604
9511 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 9605 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index 587579d..295a5e6 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenMetaverse.Imaging; 32using OpenMetaverse.Imaging;
@@ -96,46 +97,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
96 97
97 J2KImage imgrequest = m_imagestore[newRequest.RequestedAssetID]; 98 J2KImage imgrequest = m_imagestore[newRequest.RequestedAssetID];
98 99
100 // This is the inbound request sequence number. We can ignore
101 // "old" ones.
102
99 if (newRequest.requestSequence > imgrequest.m_lastSequence) 103 if (newRequest.requestSequence > imgrequest.m_lastSequence)
100 { 104 {
105
101 imgrequest.m_lastSequence = newRequest.requestSequence; 106 imgrequest.m_lastSequence = newRequest.requestSequence;
102 107
103 //First of all, is this being killed? 108 //Check the priority
104 //if (newRequest.Priority == 0.0f && newRequest.DiscardLevel == -1)
105 //{
106 //Do nothing (leaving the if for future use)
107 //}
108 //else
109 //{
110 109
110 double priority = imgrequest.m_requestedPriority;
111 if (priority != newRequest.Priority)
112 {
113 //Remove the old priority
114 m_priorities.Remove(imgrequest.m_designatedPriorityKey);
115 //Assign a new unique priority
116 imgrequest.m_requestedPriority = newRequest.Priority;
117 imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority);
118 }
111 119
112 //Check the priority 120 //Update the requested discard level
113 double priority = imgrequest.m_requestedPriority; 121 imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel;
114 if (priority != newRequest.Priority)
115 {
116 //Remove the old priority
117 m_priorities.Remove(imgrequest.m_designatedPriorityKey);
118 //Assign a new unique priority
119 imgrequest.m_requestedPriority = newRequest.Priority;
120 imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority);
121 }
122 122
123 //Update the requested discard level 123 //Update the requested packet number
124 imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; 124 imgrequest.m_requestedPacketNumber = newRequest.PacketNumber;
125 125
126 //Update the requested packet number 126 //Check if this will create an outstanding texture request
127 imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; 127 bool activated = imgrequest.m_completedSendAtCurrentDiscardLevel;
128 //Run an update
128 129
129 //Check if this will create an outstanding texture request 130 imgrequest.RunUpdate();
130 bool activated = imgrequest.m_completedSendAtCurrentDiscardLevel;
131 //Run an update
132 imgrequest.RunUpdate();
133 if (activated && !imgrequest.m_completedSendAtCurrentDiscardLevel && imgrequest.m_decoded)
134 {
135 m_outstandingtextures++;
136 }
137 131
138 //} 132 if (activated && !imgrequest.m_completedSendAtCurrentDiscardLevel && imgrequest.m_decoded)
133 {
134 Interlocked.Increment(ref m_outstandingtextures);
135 }
139 } 136 }
140 } 137 }
141 else 138 else
@@ -198,10 +195,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
198 195
199 } 196 }
200 197
201 public void ProcessImageQueue(int count) 198 public bool ProcessImageQueue(int count, int maxpack)
202 { 199 {
200
203 // this can happen during Close() 201 // this can happen during Close()
204 if (m_client == null) return; 202 if (m_client == null)
203 return false;
205 204
206 //Count is the number of textures we want to process in one go. 205 //Count is the number of textures we want to process in one go.
207 //As part of this class re-write, that number will probably rise 206 //As part of this class re-write, that number will probably rise
@@ -214,7 +213,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
214 if (m_lastloopprocessed == 0) 213 if (m_lastloopprocessed == 0)
215 { 214 {
216 if (m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null || m_client.PacketHandler.PacketQueue.TextureThrottle == null) 215 if (m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null || m_client.PacketHandler.PacketQueue.TextureThrottle == null)
217 return; 216 return false;
218 //This is decent for a semi fast machine, but we'll calculate it more accurately based on time below 217 //This is decent for a semi fast machine, but we'll calculate it more accurately based on time below
219 threshold = m_client.PacketHandler.PacketQueue.TextureThrottle.Current / 6300; 218 threshold = m_client.PacketHandler.PacketQueue.TextureThrottle.Current / 6300;
220 m_lastloopprocessed = DateTime.Now.Ticks; 219 m_lastloopprocessed = DateTime.Now.Ticks;
@@ -239,10 +238,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
239 } 238 }
240 239
241 if (m_client.PacketHandler == null) 240 if (m_client.PacketHandler == null)
242 return; 241 return false;
243 242
244 if (m_client.PacketHandler.PacketQueue == null) 243 if (m_client.PacketHandler.PacketQueue == null)
245 return; 244 return false;
246 245
247 //First of all make sure our packet queue isn't above our threshold 246 //First of all make sure our packet queue isn't above our threshold
248 247
@@ -252,24 +251,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
252 { 251 {
253 bool justreset = false; 252 bool justreset = false;
254 253
255
256
257 for (int x = m_priorities.Count - 1; x > -1; x--) 254 for (int x = m_priorities.Count - 1; x > -1; x--)
258 { 255 {
259 256
260 J2KImage imagereq = m_imagestore[m_priorities.Values[x]]; 257 J2KImage imagereq = m_imagestore[m_priorities.Values[x]];
261 if (imagereq.m_decoded == true && !imagereq.m_completedSendAtCurrentDiscardLevel) 258 if (imagereq.m_decoded == true && !imagereq.m_completedSendAtCurrentDiscardLevel)
262 { 259 {
263
264 numCollected++; 260 numCollected++;
265 //SendPackets will send up to ten packets per cycle 261 //SendPackets will send up to ten packets per cycle
266 if (imagereq.SendPackets(m_client)) 262 if (imagereq.SendPackets(m_client, maxpack))
267 { 263 {
268 //Send complete 264 //Send complete
269 if (!imagereq.m_completedSendAtCurrentDiscardLevel) 265 if (!imagereq.m_completedSendAtCurrentDiscardLevel)
270 { 266 {
271 imagereq.m_completedSendAtCurrentDiscardLevel = true; 267 imagereq.m_completedSendAtCurrentDiscardLevel = true;
272 m_outstandingtextures--; 268 Interlocked.Decrement(ref m_outstandingtextures);
273 //Re-assign priority to bottom 269 //Re-assign priority to bottom
274 //Remove the old priority 270 //Remove the old priority
275 m_priorities.Remove(imagereq.m_designatedPriorityKey); 271 m_priorities.Remove(imagereq.m_designatedPriorityKey);
@@ -310,13 +306,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 306
311 justreset = true; //prevents us from getting stuck in a loop 307 justreset = true; //prevents us from getting stuck in a loop
312 } 308 }
313
314
315 } 309 }
316 } 310 }
317 311
318 312 return m_outstandingtextures != 0;
319
320 } 313 }
321 314
322 //Faux destructor 315 //Faux destructor