From 3bbaa98c78da8a45227fcd7abd82532f6f49851b Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 6 Jan 2019 22:36:51 -0300
Subject: [PATCH] gl_state: Use DSA and multi bind to update texture bindings

---
 src/video_core/renderer_opengl/gl_state.cpp | 30 +++++++++++++++------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index b7ba59350..997325efc 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -462,24 +462,38 @@ void OpenGLState::ApplyPolygonOffset() const {
 }
 
 void OpenGLState::ApplyTextures() const {
+    bool has_delta{};
+    std::size_t first{}, last{};
+    std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures;
+
     for (std::size_t i = 0; i < std::size(texture_units); ++i) {
         const auto& texture_unit = texture_units[i];
         const auto& cur_state_texture_unit = cur_state.texture_units[i];
+        textures[i] = texture_unit.texture;
 
-        if (texture_unit.texture != cur_state_texture_unit.texture) {
-            glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum());
-            glBindTexture(texture_unit.target, texture_unit.texture);
+        if (textures[i] != cur_state_texture_unit.texture) {
+            if (!has_delta) {
+                first = i;
+                has_delta = true;
+            }
+            last = i;
         }
+
         // Update the texture swizzle
-        if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r ||
-            texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g ||
-            texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b ||
-            texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) {
+        if (textures[i] != 0 && (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r ||
+                                 texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g ||
+                                 texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b ||
+                                 texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a)) {
             std::array<GLint, 4> mask = {texture_unit.swizzle.r, texture_unit.swizzle.g,
                                          texture_unit.swizzle.b, texture_unit.swizzle.a};
-            glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data());
+            glTextureParameteriv(texture_unit.texture, GL_TEXTURE_SWIZZLE_RGBA, mask.data());
         }
     }
+
+    if (has_delta) {
+        glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
+                       textures.data());
+    }
 }
 
 void OpenGLState::ApplySamplers() const {