DrawTextureEmulation.cs
1 using OpenTK.Graphics.OpenGL; 2 using Ryujinx.Graphics.OpenGL.Image; 3 using System; 4 5 namespace Ryujinx.Graphics.OpenGL 6 { 7 class DrawTextureEmulation 8 { 9 private const string VertexShader = @"#version 430 core 10 11 uniform float srcX0; 12 uniform float srcY0; 13 uniform float srcX1; 14 uniform float srcY1; 15 16 layout (location = 0) out vec2 texcoord; 17 18 void main() 19 { 20 bool x1 = (gl_VertexID & 1) != 0; 21 bool y1 = (gl_VertexID & 2) != 0; 22 gl_Position = vec4(x1 ? 1 : -1, y1 ? -1 : 1, 0, 1); 23 texcoord = vec2(x1 ? srcX1 : srcX0, y1 ? srcY1 : srcY0); 24 }"; 25 26 private const string FragmentShader = @"#version 430 core 27 28 layout (location = 0) uniform sampler2D tex; 29 30 layout (location = 0) in vec2 texcoord; 31 layout (location = 0) out vec4 colour; 32 33 void main() 34 { 35 colour = texture(tex, texcoord); 36 }"; 37 38 private int _vsHandle; 39 private int _fsHandle; 40 private int _programHandle; 41 private int _uniformSrcX0Location; 42 private int _uniformSrcY0Location; 43 private int _uniformSrcX1Location; 44 private int _uniformSrcY1Location; 45 private bool _initialized; 46 47 public void Draw( 48 TextureView texture, 49 Sampler sampler, 50 float x0, 51 float y0, 52 float x1, 53 float y1, 54 float s0, 55 float t0, 56 float s1, 57 float t1) 58 { 59 EnsureInitialized(); 60 61 GL.UseProgram(_programHandle); 62 63 texture.Bind(0); 64 sampler.Bind(0); 65 66 if (x0 > x1) 67 { 68 (s1, s0) = (s0, s1); 69 } 70 71 if (y0 > y1) 72 { 73 (t1, t0) = (t0, t1); 74 } 75 76 GL.Uniform1(_uniformSrcX0Location, s0); 77 GL.Uniform1(_uniformSrcY0Location, t0); 78 GL.Uniform1(_uniformSrcX1Location, s1); 79 GL.Uniform1(_uniformSrcY1Location, t1); 80 81 GL.ViewportIndexed(0, MathF.Min(x0, x1), MathF.Min(y0, y1), MathF.Abs(x1 - x0), MathF.Abs(y1 - y0)); 82 83 GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); 84 } 85 86 private void EnsureInitialized() 87 { 88 if (_initialized) 89 { 90 return; 91 } 92 93 _initialized = true; 94 95 _vsHandle = GL.CreateShader(ShaderType.VertexShader); 96 _fsHandle = GL.CreateShader(ShaderType.FragmentShader); 97 98 GL.ShaderSource(_vsHandle, VertexShader); 99 GL.ShaderSource(_fsHandle, FragmentShader); 100 101 GL.CompileShader(_vsHandle); 102 GL.CompileShader(_fsHandle); 103 104 _programHandle = GL.CreateProgram(); 105 106 GL.AttachShader(_programHandle, _vsHandle); 107 GL.AttachShader(_programHandle, _fsHandle); 108 109 GL.LinkProgram(_programHandle); 110 111 GL.DetachShader(_programHandle, _vsHandle); 112 GL.DetachShader(_programHandle, _fsHandle); 113 114 _uniformSrcX0Location = GL.GetUniformLocation(_programHandle, "srcX0"); 115 _uniformSrcY0Location = GL.GetUniformLocation(_programHandle, "srcY0"); 116 _uniformSrcX1Location = GL.GetUniformLocation(_programHandle, "srcX1"); 117 _uniformSrcY1Location = GL.GetUniformLocation(_programHandle, "srcY1"); 118 } 119 120 public void Dispose() 121 { 122 if (!_initialized) 123 { 124 return; 125 } 126 127 GL.DeleteShader(_vsHandle); 128 GL.DeleteShader(_fsHandle); 129 GL.DeleteProgram(_programHandle); 130 131 _initialized = false; 132 } 133 } 134 }