Skip to content

Commit 266ecc5

Browse files
MutsiMutsitomspilmanThomasFOGharry-cpp
authored andcommitted
Remove temp buffer alloc get data when reading full texture (MonoGame#8590)
When GetData is called on an OpenGL Texture2D a temporary buffer is allocated which causes heap allocations. In scenarios where you request the entire texture (rect param is not given, or rect param is of full extend (0,0,width,height). We do not have to allocate a temporary buffer, and we can also skip Array.Copy in this case. ### Description of Change The proposed implementation checks for this specific condition, and then proceeds to fill the given T[]Data directly with GetTexImage results. --------- Co-authored-by: Tom Spilman <[email protected]> Co-authored-by: Thomas Altenburger <[email protected]> Co-authored-by: Harry <[email protected]>
1 parent c2d4958 commit 266ecc5

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

MonoGame.Framework/Platform/Graphics/Texture2D.OpenGL.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,15 @@ private void PlatformGetData<T>(int level, int arraySlice, Rectangle rect, T[] d
243243
GL.DeleteFramebuffers(1, ref framebufferId);
244244
#else
245245
var tSizeInByte = ReflectionHelpers.SizeOf<T>.Get();
246+
var pixelToT = Format.GetSize() / tSizeInByte;
247+
246248
GL.BindTexture(TextureTarget.Texture2D, this.glTexture);
247249
GL.PixelStore(PixelStoreParameter.PackAlignment, Math.Min(tSizeInByte, 8));
248250

251+
249252
if (glFormat == GLPixelFormat.CompressedTextureFormats)
250253
{
251254
// Note: for compressed format Format.GetSize() returns the size of a 4x4 block
252-
var pixelToT = Format.GetSize() / tSizeInByte;
253255
var tFullWidth = Math.Max(this.width >> level, 1) / 4 * pixelToT;
254256
var temp = new T[Math.Max(this.height >> level, 1) / 4 * tFullWidth];
255257
GL.GetCompressedTexImage(TextureTarget.Texture2D, level, temp);
@@ -264,6 +266,12 @@ private void PlatformGetData<T>(int level, int arraySlice, Rectangle rect, T[] d
264266
Array.Copy(temp, tempStart, data, dataStart, tRectWidth);
265267
}
266268
}
269+
//If we want the full texture rect == (0,0,width,height), we dont have to allocate a temp buffer to copy from.
270+
else if (rect.X == 0 && rect.Y == 0 && this.width == rect.Width && this.height == rect.Height && pixelToT == 1)
271+
{
272+
GL.GetTexImage(TextureTarget.Texture2D, level, glFormat, glType, data);
273+
GraphicsExtensions.CheckGLError();
274+
}
267275
else
268276
{
269277
// we need to convert from our format size to the size of T here
@@ -272,7 +280,6 @@ private void PlatformGetData<T>(int level, int arraySlice, Rectangle rect, T[] d
272280
GL.GetTexImage(TextureTarget.Texture2D, level, glFormat, glType, temp);
273281
GraphicsExtensions.CheckGLError();
274282

275-
var pixelToT = Format.GetSize() / tSizeInByte;
276283
var rowCount = rect.Height;
277284
var tRectWidth = rect.Width * pixelToT;
278285
for (var r = 0; r < rowCount; r++)

0 commit comments

Comments
 (0)