diff --git a/MonoGame.Framework/Graphics/.GL/ConcreteGraphicsDevice.cs b/MonoGame.Framework/Graphics/.GL/ConcreteGraphicsDevice.cs index e0a1e496af8..756fc5acc9b 100644 --- a/MonoGame.Framework/Graphics/.GL/ConcreteGraphicsDevice.cs +++ b/MonoGame.Framework/Graphics/.GL/ConcreteGraphicsDevice.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Platform.Graphics.Utilities; @@ -59,7 +60,15 @@ public override void GetBackBufferData(Rectangle? rect, T[] data, int startIn Rectangle srcRect = rect ?? new Rectangle(0, 0, PresentationParameters.BackBufferWidth, PresentationParameters.BackBufferHeight); int tSize = ReflectionHelpers.SizeOf(); int flippedY = PresentationParameters.BackBufferHeight - srcRect.Y - srcRect.Height; - GL.ReadPixels(srcRect.X, flippedY, srcRect.Width, srcRect.Height, PixelFormat.Rgba, PixelType.UnsignedByte, data); + GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + GL.ReadPixels(srcRect.X, flippedY, srcRect.Width, srcRect.Height, PixelFormat.Rgba, PixelType.UnsignedByte, dataPtr.AddrOfPinnedObject()); + } + finally + { + dataPtr.Free(); + } // buffer is returned upside down, so we swap the rows around when copying over int rowSize = srcRect.Width * PresentationParameters.BackBufferFormat.GetSize() / tSize; diff --git a/MonoGame.Framework/Graphics/.GL/ConcreteTexture2D.cs b/MonoGame.Framework/Graphics/.GL/ConcreteTexture2D.cs index 740d1df3f00..f2e372ffe8c 100644 --- a/MonoGame.Framework/Graphics/.GL/ConcreteTexture2D.cs +++ b/MonoGame.Framework/Graphics/.GL/ConcreteTexture2D.cs @@ -181,8 +181,16 @@ public void GetData(int level, int arraySlice, Rectangle checkedRect, T[] dat GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, _glTexture, 0); GL.CheckGLError(); - GL.ReadPixels(checkedRect.X, checkedRect.Y, checkedRect.Width, checkedRect.Height, _glFormat, _glType, data); - GL.CheckGLError(); + GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + GL.ReadPixels(checkedRect.X, checkedRect.Y, checkedRect.Width, checkedRect.Height, _glFormat, _glType, dataPtr.AddrOfPinnedObject()); + GL.CheckGLError(); + } + finally + { + dataPtr.Free(); + } GL.DeleteFramebuffer(framebufferId); #else int tSizeInByte = ReflectionHelpers.SizeOf(); @@ -199,8 +207,16 @@ public void GetData(int level, int arraySlice, Rectangle checkedRect, T[] dat int pixelToT = Format.GetSize() / tSizeInByte; int tFullWidth = Math.Max(this.Width >> level, 1) / 4 * pixelToT; T[] temp = new T[Math.Max(this.Height >> level, 1) / 4 * tFullWidth]; - GL.GetCompressedTexImage(TextureTarget.Texture2D, level, temp); - GL.CheckGLError(); + GCHandle pixelsPtr = GCHandle.Alloc(temp, GCHandleType.Pinned); + try + { + GL.GetCompressedTexImage(TextureTarget.Texture2D, level, pixelsPtr.AddrOfPinnedObject()); + GL.CheckGLError(); + } + finally + { + pixelsPtr.Free(); + } int rowCount = checkedRect.Height / 4; int tRectWidth = checkedRect.Width / 4 * Format.GetSize() / tSizeInByte; @@ -216,8 +232,16 @@ public void GetData(int level, int arraySlice, Rectangle checkedRect, T[] dat // we need to convert from our format size to the size of T here int tFullWidth = Math.Max(this.Width >> level, 1) * Format.GetSize() / tSizeInByte; T[] temp = new T[Math.Max(this.Height >> level, 1) * tFullWidth]; - GL.GetTexImage(TextureTarget.Texture2D, level, _glFormat, _glType, temp); - GL.CheckGLError(); + GCHandle pixelsPtr = GCHandle.Alloc(temp, GCHandleType.Pinned); + try + { + GL.GetTexImage(TextureTarget.Texture2D, level, _glFormat, _glType, pixelsPtr.AddrOfPinnedObject()); + GL.CheckGLError(); + } + finally + { + pixelsPtr.Free(); + } int pixelToT = Format.GetSize() / tSizeInByte; int rowCount = checkedRect.Height; diff --git a/MonoGame.Framework/Graphics/.GL/ConcreteTextureCube.cs b/MonoGame.Framework/Graphics/.GL/ConcreteTextureCube.cs index 9cd090d9fae..ee9535a9884 100644 --- a/MonoGame.Framework/Graphics/.GL/ConcreteTextureCube.cs +++ b/MonoGame.Framework/Graphics/.GL/ConcreteTextureCube.cs @@ -109,8 +109,16 @@ public void GetData(CubeMapFace face, int level, Rectangle checkedRect, T[] d int pixelToT = Format.GetSize() / tSizeInByte; int tFullWidth = Math.Max(this.Size >> level, 1) / 4 * pixelToT; T[] temp = new T[Math.Max(this.Size >> level, 1) / 4 * tFullWidth]; - GL.GetCompressedTexImage(target, level, temp); - GL.CheckGLError(); + GCHandle pixelsPtr = GCHandle.Alloc(temp, GCHandleType.Pinned); + try + { + GL.GetCompressedTexImage(target, level, pixelsPtr.AddrOfPinnedObject()); + GL.CheckGLError(); + } + finally + { + pixelsPtr.Free(); + } int rowCount = checkedRect.Height / 4; int tRectWidth = checkedRect.Width / 4 * Format.GetSize() / tSizeInByte; @@ -126,8 +134,16 @@ public void GetData(CubeMapFace face, int level, Rectangle checkedRect, T[] d // we need to convert from our format size to the size of T here int tFullWidth = Math.Max(this.Size >> level, 1) * Format.GetSize() / tSizeInByte; T[] temp = new T[Math.Max(this.Size >> level, 1) * tFullWidth]; - GL.GetTexImage(target, level, _glFormat, _glType, temp); - GL.CheckGLError(); + GCHandle pixelsPtr = GCHandle.Alloc(temp, GCHandleType.Pinned); + try + { + GL.GetTexImage(target, level, _glFormat, _glType, pixelsPtr.AddrOfPinnedObject()); + GL.CheckGLError(); + } + finally + { + pixelsPtr.Free(); + } int pixelToT = Format.GetSize() / tSizeInByte; int rowCount = checkedRect.Height; diff --git a/MonoGame.Framework/Graphics/.GL/OpenGL.cs b/MonoGame.Framework/Graphics/.GL/OpenGL.cs index 31031a202ca..0647fe015d7 100644 --- a/MonoGame.Framework/Graphics/.GL/OpenGL.cs +++ b/MonoGame.Framework/Graphics/.GL/OpenGL.cs @@ -749,7 +749,7 @@ internal unsafe int GenTexture() [UnmanagedFunctionPointer(callingConvention)] [MonoNativeFunctionWrapper] internal delegate void ReadPixelsDelegate(int x, int y, int width, int height, PixelFormat format, PixelType type, IntPtr data); - internal ReadPixelsDelegate ReadPixelsInternal; + internal ReadPixelsDelegate ReadPixels; [System.Security.SuppressUnmanagedCodeSecurity()] [UnmanagedFunctionPointer(callingConvention)] @@ -1206,13 +1206,13 @@ internal delegate void TexSubImage2DDelegate(TextureTarget target, int level, [UnmanagedFunctionPointer(callingConvention)] [MonoNativeFunctionWrapper] internal delegate void GetTexImageDelegate(TextureTarget target, int level, PixelFormat format, PixelType type, [Out] IntPtr pixels); - internal GetTexImageDelegate GetTexImageInternal; + internal GetTexImageDelegate GetTexImage; [System.Security.SuppressUnmanagedCodeSecurity()] [UnmanagedFunctionPointer(callingConvention)] [MonoNativeFunctionWrapper] internal delegate void GetCompressedTexImageDelegate(TextureTarget target, int level, [Out] IntPtr pixels); - internal GetCompressedTexImageDelegate GetCompressedTexImageInternal; + internal GetCompressedTexImageDelegate GetCompressedTexImage; [System.Security.SuppressUnmanagedCodeSecurity()] [UnmanagedFunctionPointer(callingConvention)] @@ -1401,7 +1401,7 @@ private void LoadEntryPoints() UniformMatrix2fv = LoadFunctionOrNull("glUniformMatrix2fv"); UniformMatrix3fv = LoadFunctionOrNull("glUniformMatrix3fv"); UniformMatrix4fv = LoadFunctionOrNull("glUniformMatrix4fv"); - ReadPixelsInternal = LoadFunctionOrNull("glReadPixels"); + ReadPixels = LoadFunctionOrNull("glReadPixels"); // uniforms OpenGL Version >= 2.1 // ... UniformMatrix 2x3,2x4, 3x2, 3x4, 4x2, 4x3 // uniforms OpenGL Version >= 3.0 @@ -1476,8 +1476,8 @@ private void LoadEntryPoints() TexSubImage2D = LoadFunctionOrNull("glTexSubImage2D"); PixelStore = LoadFunctionOrNull("glPixelStorei"); Finish = LoadFunctionOrNull("glFinish"); - GetTexImageInternal = LoadFunctionOrNull("glGetTexImage"); - GetCompressedTexImageInternal = LoadFunctionOrNull("glGetCompressedTexImage"); + GetTexImage = LoadFunctionOrNull("glGetTexImage"); + GetCompressedTexImage = LoadFunctionOrNull("glGetCompressedTexImage"); TexImage3D = LoadFunctionOrNull("glTexImage3D"); TexSubImage3D = LoadFunctionOrNull("glTexSubImage3D"); DeleteTextures = LoadFunctionOrNull("glDeleteTextures"); @@ -1761,45 +1761,6 @@ internal void TexParameter(TextureTarget target, TextureParameterName name, int TexParameteri(target, name, value); } - internal void GetTexImage(TextureTarget target, int level, PixelFormat format, PixelType type, T[] pixels) where T : struct - { - GCHandle pixelsPtr = GCHandle.Alloc(pixels, GCHandleType.Pinned); - try - { - GetTexImageInternal(target, level, format, type, pixelsPtr.AddrOfPinnedObject()); - } - finally - { - pixelsPtr.Free(); - } - } - - internal void GetCompressedTexImage(TextureTarget target, int level, T[] pixels) where T : struct - { - GCHandle pixelsPtr = GCHandle.Alloc(pixels, GCHandleType.Pinned); - try - { - GetCompressedTexImageInternal(target, level, pixelsPtr.AddrOfPinnedObject()); - } - finally - { - pixelsPtr.Free(); - } - } - - public void ReadPixels(int x, int y, int width, int height, PixelFormat format, PixelType type, T[] data) - { - GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - ReadPixelsInternal(x, y, width, height, format, type, dataPtr.AddrOfPinnedObject()); - } - finally - { - dataPtr.Free(); - } - } - [Conditional("DEBUG")] [DebuggerHidden] diff --git a/MonoGame.Framework/Media/Android/ConcreteVideoPlayer.cs b/MonoGame.Framework/Media/Android/ConcreteVideoPlayer.cs index 11827296347..d5a7e359955 100644 --- a/MonoGame.Framework/Media/Android/ConcreteVideoPlayer.cs +++ b/MonoGame.Framework/Media/Android/ConcreteVideoPlayer.cs @@ -5,6 +5,7 @@ // Copyright (C)2023 Nick Kastellanos using System; +using System.Runtime.InteropServices; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Media; @@ -172,8 +173,16 @@ public override Texture2D PlatformGetTexture() GL.CheckGLError(); // Read the pixel data from the framebuffer - GL.ReadPixels(0, 0, this.Video.Width, this.Video.Height, GLPixelFormat.Rgba, PixelType.UnsignedByte, _frameData); - GL.CheckGLError(); + GCHandle dataPtr = GCHandle.Alloc(_frameData, GCHandleType.Pinned); + try + { + GL.ReadPixels(0, 0, this.Video.Width, this.Video.Height, GLPixelFormat.Rgba, PixelType.UnsignedByte, dataPtr.AddrOfPinnedObject()); + GL.CheckGLError(); + } + finally + { + dataPtr.Free(); + } // Dettach framebuffer GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);