diff options
Diffstat (limited to 'Ryujinx.Graphics.OpenGL')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/BackgroundContextWorker.cs | 2 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Buffer.cs | 2 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/FormatTable.cs | 2 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/HwCapabilities.cs | 8 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureView.cs | 22 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs (renamed from Ryujinx.Graphics.OpenGL/Renderer.cs) | 18 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Pipeline.cs | 94 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs | 1 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Window.cs | 4 |
13 files changed, 98 insertions, 71 deletions
diff --git a/Ryujinx.Graphics.OpenGL/BackgroundContextWorker.cs b/Ryujinx.Graphics.OpenGL/BackgroundContextWorker.cs index 3f1c055b..764ea715 100644 --- a/Ryujinx.Graphics.OpenGL/BackgroundContextWorker.cs +++ b/Ryujinx.Graphics.OpenGL/BackgroundContextWorker.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common; +using Ryujinx.Common; using System; using System.Collections.Generic; using System.Threading; diff --git a/Ryujinx.Graphics.OpenGL/Buffer.cs b/Ryujinx.Graphics.OpenGL/Buffer.cs index 0f6a90e3..68c82f95 100644 --- a/Ryujinx.Graphics.OpenGL/Buffer.cs +++ b/Ryujinx.Graphics.OpenGL/Buffer.cs @@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.OpenGL (IntPtr)size); } - public static unsafe ReadOnlySpan<byte> GetData(Renderer renderer, BufferHandle buffer, int offset, int size) + public static unsafe ReadOnlySpan<byte> GetData(OpenGLRenderer renderer, BufferHandle buffer, int offset, int size) { if (HwCapabilities.UsePersistentBufferForFlush) { diff --git a/Ryujinx.Graphics.OpenGL/FormatTable.cs b/Ryujinx.Graphics.OpenGL/FormatTable.cs index 1a739b5c..e6717eb4 100644 --- a/Ryujinx.Graphics.OpenGL/FormatTable.cs +++ b/Ryujinx.Graphics.OpenGL/FormatTable.cs @@ -94,9 +94,7 @@ namespace Ryujinx.Graphics.OpenGL Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm)); Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat)); Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat)); - Add(Format.Etc2RgbUnorm, new FormatInfo(3, false, false, All.CompressedRgb8Etc2)); Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac)); - Add(Format.Etc2RgbSrgb, new FormatInfo(3, false, false, All.CompressedSrgb8Etc2)); Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac)); Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte)); Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte)); diff --git a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index 13b5b412..ba2cc2df 100644 --- a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.OpenGL private static readonly Lazy<bool> _supportsDrawTexture = new Lazy<bool>(() => HasExtension("GL_NV_draw_texture")); private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock")); private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering")); + private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new Lazy<bool>(() => HasExtension("GL_NV_geometry_shader_passthrough")); private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted")); private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters")); private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile")); @@ -17,6 +18,9 @@ namespace Ryujinx.Graphics.OpenGL private static readonly Lazy<bool> _supportsQuads = new Lazy<bool>(SupportsQuadsCheck); private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new Lazy<bool>(() => HasExtension("GL_ARB_seamless_cubemap_per_texture")); private static readonly Lazy<bool> _supportsShaderBallot = new Lazy<bool>(() => HasExtension("GL_ARB_shader_ballot")); + private static readonly Lazy<bool> _supportsTextureCompressionBptc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_bptc")); + private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_rgtc")); + private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_s3tc")); private static readonly Lazy<bool> _supportsTextureShadowLod = new Lazy<bool>(() => HasExtension("GL_EXT_texture_shadow_lod")); private static readonly Lazy<bool> _supportsViewportSwizzle = new Lazy<bool>(() => HasExtension("GL_NV_viewport_swizzle")); @@ -49,6 +53,7 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsDrawTexture => _supportsDrawTexture.Value; public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value; public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value; + public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value; public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value; public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value; public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value; @@ -56,6 +61,9 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsQuads => _supportsQuads.Value; public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value; public static bool SupportsShaderBallot => _supportsShaderBallot.Value; + public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value; + public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value; + public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value; public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value; public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value; diff --git a/Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs b/Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs index bd6efc76..218a245e 100644 --- a/Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs +++ b/Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs @@ -6,10 +6,10 @@ namespace Ryujinx.Graphics.OpenGL.Image { class IntermmediatePool : IDisposable { - private readonly Renderer _renderer; + private readonly OpenGLRenderer _renderer; private readonly List<TextureView> _entries; - public IntermmediatePool(Renderer renderer) + public IntermmediatePool(OpenGLRenderer renderer) { _renderer = renderer; _entries = new List<TextureView>(); diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs index dc9bf6af..e5b39aa6 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs @@ -6,14 +6,14 @@ namespace Ryujinx.Graphics.OpenGL.Image { class TextureBuffer : TextureBase, ITexture { - private Renderer _renderer; + private OpenGLRenderer _renderer; private int _bufferOffset; private int _bufferSize; private int _bufferCount; private BufferHandle _buffer; - public TextureBuffer(Renderer renderer, TextureCreateInfo info) : base(info) + public TextureBuffer(OpenGLRenderer renderer, TextureCreateInfo info) : base(info) { _renderer = renderer; } diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs index 44804d43..d7915445 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.OpenGL.Image { class TextureCopy : IDisposable { - private readonly Renderer _renderer; + private readonly OpenGLRenderer _renderer; public IntermmediatePool IntermmediatePool { get; } @@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.OpenGL.Image private int _copyPboHandle; private int _copyPboSize; - public TextureCopy(Renderer renderer) + public TextureCopy(OpenGLRenderer renderer) { _renderer = renderer; IntermmediatePool = new IntermmediatePool(renderer); diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs b/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs index 215446ec..c058ac88 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs @@ -12,13 +12,13 @@ namespace Ryujinx.Graphics.OpenGL.Image public TextureCreateInfo Info { get; } - private readonly Renderer _renderer; + private readonly OpenGLRenderer _renderer; private int _viewsCount; internal ITexture DefaultView { get; private set; } - public TextureStorage(Renderer renderer, TextureCreateInfo info, float scaleFactor) + public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor) { _renderer = renderer; Info = info; diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index afb9a278..8f9e2a66 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.OpenGL.Image { class TextureView : TextureBase, ITexture, ITextureInfo { - private readonly Renderer _renderer; + private readonly OpenGLRenderer _renderer; private readonly TextureStorage _parent; @@ -16,14 +16,14 @@ namespace Ryujinx.Graphics.OpenGL.Image public int FirstLevel { get; private set; } public TextureView( - Renderer renderer, - TextureStorage parent, + OpenGLRenderer renderer, + TextureStorage parent, TextureCreateInfo info, - int firstLayer, - int firstLevel) : base(info, parent.ScaleFactor) + int firstLayer, + int firstLevel) : base(info, parent.ScaleFactor) { _renderer = renderer; - _parent = parent; + _parent = parent; FirstLayer = firstLayer; FirstLevel = firstLevel; @@ -306,7 +306,7 @@ namespace Ryujinx.Graphics.OpenGL.Image FormatInfo format = FormatTable.GetFormatInfo(Info.Format); PixelFormat pixelFormat = format.PixelFormat; - PixelType pixelType = format.PixelType; + PixelType pixelType = format.PixelType; if (forceBgra) { @@ -580,9 +580,9 @@ namespace Ryujinx.Graphics.OpenGL.Image FormatInfo format = FormatTable.GetFormatInfo(Info.Format); - int width = Info.Width; + int width = Info.Width; int height = Info.Height; - int depth = Info.Depth; + int depth = Info.Depth; int levels = Info.GetLevelsClamped(); int offset = 0; @@ -725,10 +725,10 @@ namespace Ryujinx.Graphics.OpenGL.Image break; } - data += mipSize; + data += mipSize; offset += mipSize; - width = Math.Max(1, width >> 1); + width = Math.Max(1, width >> 1); height = Math.Max(1, height >> 1); if (Target == Target.Texture3D) diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index 2a9ab422..4df81cef 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -9,7 +9,7 @@ using System; namespace Ryujinx.Graphics.OpenGL { - public sealed class Renderer : IRenderer + public sealed class OpenGLRenderer : IRenderer { private readonly Pipeline _pipeline; @@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.OpenGL public bool PreferThreading => true; - public Renderer() + public OpenGLRenderer() { _pipeline = new Pipeline(); _counters = new Counters(); @@ -87,6 +87,11 @@ namespace Ryujinx.Graphics.OpenGL Buffer.Delete(buffer); } + public HardwareInfo GetHardwareInfo() + { + return new HardwareInfo(GpuVendor, GpuRenderer); + } + public ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size) { return Buffer.GetData(this, buffer, offset, size); @@ -100,18 +105,27 @@ namespace Ryujinx.Graphics.OpenGL hasFrontFacingBug: HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows, hasVectorIndexingBug: HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows, supportsAstcCompression: HwCapabilities.SupportsAstcCompression, + supportsBc123Compression: HwCapabilities.SupportsTextureCompressionS3tc, + supportsBc45Compression: HwCapabilities.SupportsTextureCompressionRgtc, + supportsBc67Compression: true, // Should check BPTC extension, but for some reason NVIDIA is not exposing the extension. supports3DTextureCompression: false, supportsBgraFormat: false, supportsR4G4Format: false, supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock, supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering, + supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough, supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted, supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat, + supportsCubemapView: true, supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset, supportsShaderBallot: HwCapabilities.SupportsShaderBallot, supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod, supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle, supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters, + maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver? + maximumStorageBuffersPerStage: 16, + maximumTexturesPerStage: 32, + maximumImagesPerStage: 8, maximumComputeSharedMemorySize: HwCapabilities.MaximumComputeSharedMemorySize, maximumSupportedAnisotropy: HwCapabilities.MaximumSupportedAnisotropy, storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment); diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index fde86424..457f6a4a 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL private CounterQueueEvent _activeConditionalRender; private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount]; - private Vector4<float>[] _renderScale = new Vector4<float>[65]; + private Vector4<float>[] _renderScale = new Vector4<float>[73]; private int _fragmentScaleCount; private TextureBase _unit0Texture; @@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.OpenGL _tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers]; } - public void Initialize(Renderer renderer) + public void Initialize(OpenGLRenderer renderer) { _supportBuffer = new SupportBufferUpdater(renderer); GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer.Handle)); @@ -1134,45 +1134,45 @@ namespace Ryujinx.Graphics.OpenGL _framebuffer.SetDrawBuffers(colors.Length); } - public void SetSampler(int binding, ISampler sampler) + public void SetScissors(ReadOnlySpan<Rectangle<int>> regions) { - if (sampler == null) - { - return; - } + int count = Math.Min(regions.Length, Constants.MaxViewports); - Sampler samp = (Sampler)sampler; + Span<int> v = stackalloc int[count * 4]; - if (binding == 0) + for (int index = 0; index < count; index++) { - _unit0Sampler = samp; - } + int vIndex = index * 4; - samp.Bind(binding); - } + var region = regions[index]; - public void SetScissor(int index, bool enable, int x, int y, int width, int height) - { - uint mask = 1u << index; + bool enabled = (region.X | region.Y) != 0 || region.Width != 0xffff || region.Height != 0xffff; + uint mask = 1u << index; - if (!enable) - { - if ((_scissorEnables & mask) != 0) + if (enabled) { - _scissorEnables &= ~mask; - GL.Disable(IndexedEnableCap.ScissorTest, index); - } + v[vIndex] = region.X; + v[vIndex + 1] = region.Y; + v[vIndex + 2] = region.Width; + v[vIndex + 3] = region.Height; - return; - } - - if ((_scissorEnables & mask) == 0) - { - _scissorEnables |= mask; - GL.Enable(IndexedEnableCap.ScissorTest, index); + if ((_scissorEnables & mask) == 0) + { + _scissorEnables |= mask; + GL.Enable(IndexedEnableCap.ScissorTest, index); + } + } + else + { + if ((_scissorEnables & mask) != 0) + { + _scissorEnables &= ~mask; + GL.Disable(IndexedEnableCap.ScissorTest, index); + } + } } - GL.ScissorIndexed(index, x, y, width, height); + GL.ScissorArray(0, count, ref v[0]); } public void SetStencilTest(StencilTestDescriptor stencilTest) @@ -1223,23 +1223,31 @@ namespace Ryujinx.Graphics.OpenGL SetBuffers(first, buffers, isStorage: true); } - public void SetTexture(int binding, ITexture texture) + public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) { - if (texture == null) + if (texture != null) { - return; + if (binding == 0) + { + _unit0Texture = (TextureBase)texture; + } + else + { + ((TextureBase)texture).Bind(binding); + } } + Sampler glSampler = (Sampler)sampler; + + glSampler?.Bind(binding); + if (binding == 0) { - _unit0Texture = (TextureBase)texture; - } - else - { - ((TextureBase)texture).Bind(binding); + _unit0Sampler = glSampler; } } + public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers) { if (_tfEnabled) @@ -1306,7 +1314,7 @@ namespace Ryujinx.Graphics.OpenGL _vertexArray.SetVertexBuffers(vertexBuffers); } - public void SetViewports(int first, ReadOnlySpan<Viewport> viewports, bool disableTransform) + public void SetViewports(ReadOnlySpan<Viewport> viewports, bool disableTransform) { Array.Resize(ref _viewportArray, viewports.Length * 4); Array.Resize(ref _depthRangeArray, viewports.Length * 2); @@ -1343,8 +1351,8 @@ namespace Ryujinx.Graphics.OpenGL SetOrigin(flipY ? ClipOrigin.UpperLeft : ClipOrigin.LowerLeft); - GL.ViewportArray(first, viewports.Length, viewportArray); - GL.DepthRangeArray(first, viewports.Length, depthRangeArray); + GL.ViewportArray(0, viewports.Length, viewportArray); + GL.DepthRangeArray(0, viewports.Length, depthRangeArray); float disableTransformF = disableTransform ? 1.0f : 0.0f; if (_supportBuffer.Data.ViewportInverse.W != disableTransformF || disableTransform) @@ -1352,8 +1360,8 @@ namespace Ryujinx.Graphics.OpenGL float scale = _renderScale[0].X; _supportBuffer.UpdateViewportInverse(new Vector4<float> { - X = scale * 2f / viewports[first].Region.Width, - Y = scale * 2f / viewports[first].Region.Height, + X = scale * 2f / viewports[0].Region.Width, + Y = scale * 2f / viewports[0].Region.Height, Z = 1, W = disableTransformF }); diff --git a/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs b/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs index 8b0ae30e..81451389 100644 --- a/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs +++ b/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs @@ -1,5 +1,4 @@ using OpenTK.Graphics.OpenGL; -using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using System; using System.Threading; diff --git a/Ryujinx.Graphics.OpenGL/Window.cs b/Ryujinx.Graphics.OpenGL/Window.cs index ae74558e..e5a7ebf0 100644 --- a/Ryujinx.Graphics.OpenGL/Window.cs +++ b/Ryujinx.Graphics.OpenGL/Window.cs @@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.OpenGL class Window : IWindow, IDisposable { private const int TextureCount = 3; - private readonly Renderer _renderer; + private readonly OpenGLRenderer _renderer; private int _width; private int _height; @@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.OpenGL internal bool ScreenCaptureRequested { get; set; } - public Window(Renderer renderer) + public Window(OpenGLRenderer renderer) { _renderer = renderer; _stagingTextures = new int[TextureCount]; |