/ src / Ryujinx.Graphics.OpenGL / DrawTextureEmulation.cs
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  }