summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2015-09-05 16:19:52 -0400
committerGravatar bunnei2015-09-05 16:19:52 -0400
commit51e91dfd8608126b2cb409fa2e8513f28fbf293b (patch)
treef76ddff71ac10838e6429815d8267c82b602737f /src
parentMerge pull request #1087 from yuriks/opengl-glad (diff)
parentOpenGL: Use Sampler Objects to decouple sampler config from textures (diff)
downloadyuzu-51e91dfd8608126b2cb409fa2e8513f28fbf293b.tar.gz
yuzu-51e91dfd8608126b2cb409fa2e8513f28fbf293b.tar.xz
yuzu-51e91dfd8608126b2cb409fa2e8513f28fbf293b.zip
Merge pull request #1104 from yuriks/opengl-samplers
OpenGL: Use Sampler Objects to decouple sampler config from textures
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/bootmanager.cpp3
-rw-r--r--src/citra_qt/main.cpp3
-rw-r--r--src/video_core/pica.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp52
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h19
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp25
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h7
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h24
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_state.h2
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h10
11 files changed, 133 insertions, 36 deletions
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index d9bacfc3d..9aec16506 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -72,6 +72,9 @@ void EmuThread::run() {
72 } 72 }
73 } 73 }
74 74
75 // Shutdown the core emulation
76 System::Shutdown();
77
75 MicroProfileOnThreadExit(); 78 MicroProfileOnThreadExit();
76 79
77 render_window->moveContext(); 80 render_window->moveContext();
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 7fb1b0dcb..11813a2a8 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -283,9 +283,6 @@ void GMainWindow::ShutdownGame() {
283 emu_thread->wait(); 283 emu_thread->wait();
284 emu_thread = nullptr; 284 emu_thread = nullptr;
285 285
286 // Shutdown the core emulation
287 System::Shutdown();
288
289 // Update the GUI 286 // Update the GUI
290 ui.action_Start->setEnabled(false); 287 ui.action_Start->setEnabled(false);
291 ui.action_Start->setText(tr("Start")); 288 ui.action_Start->setText(tr("Start"));
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 855cb442e..c1dca5087 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -135,6 +135,7 @@ struct Regs {
135 }; 135 };
136 136
137 union { 137 union {
138 u32 raw;
138 BitField< 0, 8, u32> r; 139 BitField< 0, 8, u32> r;
139 BitField< 8, 8, u32> g; 140 BitField< 8, 8, u32> g;
140 BitField<16, 8, u32> b; 141 BitField<16, 8, u32> b;
@@ -339,6 +340,7 @@ struct Regs {
339 }; 340 };
340 341
341 union { 342 union {
343 u32 const_color;
342 BitField< 0, 8, u32> const_r; 344 BitField< 0, 8, u32> const_r;
343 BitField< 8, 8, u32> const_g; 345 BitField< 8, 8, u32> const_g;
344 BitField<16, 8, u32> const_b; 346 BitField<16, 8, u32> const_b;
@@ -389,6 +391,7 @@ struct Regs {
389 TevStageConfig tev_stage5; 391 TevStageConfig tev_stage5;
390 392
391 union { 393 union {
394 u32 raw;
392 BitField< 0, 8, u32> r; 395 BitField< 0, 8, u32> r;
393 BitField< 8, 8, u32> g; 396 BitField< 8, 8, u32> g;
394 BitField<16, 8, u32> b; 397 BitField<16, 8, u32> b;
@@ -473,6 +476,7 @@ struct Regs {
473 }; 476 };
474 477
475 union { 478 union {
479 u32 raw;
476 BitField< 0, 8, u32> r; 480 BitField< 0, 8, u32> r;
477 BitField< 8, 8, u32> g; 481 BitField< 8, 8, u32> g;
478 BitField<16, 8, u32> b; 482 BitField<16, 8, u32> b;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 80e773728..0260a28ce 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -68,6 +68,12 @@ void RasterizerOpenGL::InitObjects() {
68 uniform_tev_cfg.updates_combiner_buffer_color_alpha = glGetUniformLocation(shader.handle, (tev_ref_str + ".updates_combiner_buffer_color_alpha").c_str()); 68 uniform_tev_cfg.updates_combiner_buffer_color_alpha = glGetUniformLocation(shader.handle, (tev_ref_str + ".updates_combiner_buffer_color_alpha").c_str());
69 } 69 }
70 70
71 // Create sampler objects
72 for (int i = 0; i < texture_samplers.size(); ++i) {
73 texture_samplers[i].Create();
74 state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
75 }
76
71 // Generate VBO and VAO 77 // Generate VBO and VAO
72 vertex_buffer.Create(); 78 vertex_buffer.Create();
73 vertex_array.Create(); 79 vertex_array.Create();
@@ -445,6 +451,45 @@ void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
445 res_cache.NotifyFlush(addr, size); 451 res_cache.NotifyFlush(addr, size);
446} 452}
447 453
454void RasterizerOpenGL::SamplerInfo::Create() {
455 sampler.Create();
456 mag_filter = min_filter = TextureConfig::Linear;
457 wrap_s = wrap_t = TextureConfig::Repeat;
458 border_color = 0;
459
460 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // default is GL_LINEAR_MIPMAP_LINEAR
461 // Other attributes have correct defaults
462}
463
464void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Pica::Regs::TextureConfig& config) {
465 GLuint s = sampler.handle;
466
467 if (mag_filter != config.mag_filter) {
468 mag_filter = config.mag_filter;
469 glSamplerParameteri(s, GL_TEXTURE_MAG_FILTER, PicaToGL::TextureFilterMode(mag_filter));
470 }
471 if (min_filter != config.min_filter) {
472 min_filter = config.min_filter;
473 glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER, PicaToGL::TextureFilterMode(min_filter));
474 }
475
476 if (wrap_s != config.wrap_s) {
477 wrap_s = config.wrap_s;
478 glSamplerParameteri(s, GL_TEXTURE_WRAP_S, PicaToGL::WrapMode(wrap_s));
479 }
480 if (wrap_t != config.wrap_t) {
481 wrap_t = config.wrap_t;
482 glSamplerParameteri(s, GL_TEXTURE_WRAP_T, PicaToGL::WrapMode(wrap_t));
483 }
484
485 if (wrap_s == TextureConfig::ClampToBorder || wrap_t == TextureConfig::ClampToBorder) {
486 if (border_color != config.border_color.raw) {
487 auto gl_color = PicaToGL::ColorRGBA8(border_color);
488 glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, gl_color.data());
489 }
490 }
491}
492
448void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height) { 493void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height) {
449 GLint internal_format; 494 GLint internal_format;
450 495
@@ -658,7 +703,7 @@ void RasterizerOpenGL::SyncBlendFuncs() {
658} 703}
659 704
660void RasterizerOpenGL::SyncBlendColor() { 705void RasterizerOpenGL::SyncBlendColor() {
661 auto blend_color = PicaToGL::ColorRGBA8((u8*)&Pica::g_state.regs.output_merger.blend_const.r); 706 auto blend_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.output_merger.blend_const.raw);
662 state.blend.color.red = blend_color[0]; 707 state.blend.color.red = blend_color[0];
663 state.blend.color.green = blend_color[1]; 708 state.blend.color.green = blend_color[1];
664 state.blend.color.blue = blend_color[2]; 709 state.blend.color.blue = blend_color[2];
@@ -728,7 +773,7 @@ void RasterizerOpenGL::SyncTevOps(unsigned stage_index, const Pica::Regs::TevSta
728} 773}
729 774
730void RasterizerOpenGL::SyncTevColor(unsigned stage_index, const Pica::Regs::TevStageConfig& config) { 775void RasterizerOpenGL::SyncTevColor(unsigned stage_index, const Pica::Regs::TevStageConfig& config) {
731 auto const_color = PicaToGL::ColorRGBA8((u8*)&config.const_r); 776 auto const_color = PicaToGL::ColorRGBA8(config.const_color);
732 glUniform4fv(uniform_tev_cfgs[stage_index].const_color, 1, const_color.data()); 777 glUniform4fv(uniform_tev_cfgs[stage_index].const_color, 1, const_color.data());
733} 778}
734 779
@@ -737,7 +782,7 @@ void RasterizerOpenGL::SyncTevMultipliers(unsigned stage_index, const Pica::Regs
737} 782}
738 783
739void RasterizerOpenGL::SyncCombinerColor() { 784void RasterizerOpenGL::SyncCombinerColor() {
740 auto combiner_color = PicaToGL::ColorRGBA8((u8*)&Pica::g_state.regs.tev_combiner_buffer_color.r); 785 auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw);
741 glUniform4fv(uniform_tev_combiner_buffer_color, 1, combiner_color.data()); 786 glUniform4fv(uniform_tev_combiner_buffer_color, 1, combiner_color.data());
742} 787}
743 788
@@ -772,6 +817,7 @@ void RasterizerOpenGL::SyncDrawState() {
772 const auto& texture = pica_textures[texture_index]; 817 const auto& texture = pica_textures[texture_index];
773 818
774 if (texture.enabled) { 819 if (texture.enabled) {
820 texture_samplers[texture_index].SyncWithConfig(texture.config);
775 res_cache.LoadAndBindTexture(state, texture_index, texture); 821 res_cache.LoadAndBindTexture(state, texture_index, texture);
776 } else { 822 } else {
777 state.texture_units[texture_index].texture_2d = 0; 823 state.texture_units[texture_index].texture_2d = 0;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index a02d5c856..24560d7f8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -80,6 +80,24 @@ private:
80 GLenum gl_type; 80 GLenum gl_type;
81 }; 81 };
82 82
83 struct SamplerInfo {
84 using TextureConfig = Pica::Regs::TextureConfig;
85
86 OGLSampler sampler;
87
88 /// Creates the sampler object, initializing its state so that it's in sync with the SamplerInfo struct.
89 void Create();
90 /// Syncs the sampler object with the config, updating any necessary state.
91 void SyncWithConfig(const TextureConfig& config);
92
93 private:
94 TextureConfig::TextureFilter mag_filter;
95 TextureConfig::TextureFilter min_filter;
96 TextureConfig::WrapMode wrap_s;
97 TextureConfig::WrapMode wrap_t;
98 u32 border_color;
99 };
100
83 /// Structure that the hardware rendered vertices are composed of 101 /// Structure that the hardware rendered vertices are composed of
84 struct HardwareVertex { 102 struct HardwareVertex {
85 HardwareVertex(const Pica::Shader::OutputVertex& v) { 103 HardwareVertex(const Pica::Shader::OutputVertex& v) {
@@ -193,6 +211,7 @@ private:
193 PAddr last_fb_depth_addr; 211 PAddr last_fb_depth_addr;
194 212
195 // Hardware rasterizer 213 // Hardware rasterizer
214 std::array<SamplerInfo, 3> texture_samplers;
196 TextureInfo fb_color_texture; 215 TextureInfo fb_color_texture;
197 DepthTextureInfo fb_depth_texture; 216 DepthTextureInfo fb_depth_texture;
198 OGLShader shader; 217 OGLShader shader;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 1e38c2e6d..d9ccf2a3f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -20,9 +20,8 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
20 20
21MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); 21MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
22 22
23void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) { 23void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::DebugUtils::TextureInfo& info) {
24 PAddr texture_addr = config.config.GetPhysicalAddress(); 24 const auto cached_texture = texture_cache.find(info.physical_address);
25 const auto cached_texture = texture_cache.find(texture_addr);
26 25
27 if (cached_texture != texture_cache.end()) { 26 if (cached_texture != texture_cache.end()) {
28 state.texture_units[texture_unit].texture_2d = cached_texture->second->texture.handle; 27 state.texture_units[texture_unit].texture_2d = cached_texture->second->texture.handle;
@@ -37,26 +36,12 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
37 state.Apply(); 36 state.Apply();
38 glActiveTexture(GL_TEXTURE0 + texture_unit); 37 glActiveTexture(GL_TEXTURE0 + texture_unit);
39 38
40 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, PicaToGL::TextureFilterMode(config.config.mag_filter)); 39 u8* texture_src_data = Memory::GetPhysicalPointer(info.physical_address);
41 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, PicaToGL::TextureFilterMode(config.config.min_filter));
42
43 GLenum wrap_s = PicaToGL::WrapMode(config.config.wrap_s);
44 GLenum wrap_t = PicaToGL::WrapMode(config.config.wrap_t);
45 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
46 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
47
48 if (wrap_s == GL_CLAMP_TO_BORDER || wrap_t == GL_CLAMP_TO_BORDER) {
49 auto border_color = PicaToGL::ColorRGBA8((u8*)&config.config.border_color.r);
50 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color.data());
51 }
52
53 const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format);
54 u8* texture_src_data = Memory::GetPhysicalPointer(texture_addr);
55 40
56 new_texture->width = info.width; 41 new_texture->width = info.width;
57 new_texture->height = info.height; 42 new_texture->height = info.height;
58 new_texture->size = info.stride * info.height; 43 new_texture->size = info.stride * info.height;
59 new_texture->addr = texture_addr; 44 new_texture->addr = info.physical_address;
60 new_texture->hash = Common::ComputeHash64(texture_src_data, new_texture->size); 45 new_texture->hash = Common::ComputeHash64(texture_src_data, new_texture->size);
61 46
62 std::unique_ptr<Math::Vec4<u8>[]> temp_texture_buffer_rgba(new Math::Vec4<u8>[info.width * info.height]); 47 std::unique_ptr<Math::Vec4<u8>[]> temp_texture_buffer_rgba(new Math::Vec4<u8>[info.width * info.height]);
@@ -69,7 +54,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
69 54
70 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp_texture_buffer_rgba.get()); 55 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp_texture_buffer_rgba.get());
71 56
72 texture_cache.emplace(texture_addr, std::move(new_texture)); 57 texture_cache.emplace(info.physical_address, std::move(new_texture));
73 } 58 }
74} 59}
75 60
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index d8f9edf59..ec56237b5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -6,6 +6,7 @@
6 6
7#include "gl_state.h" 7#include "gl_state.h"
8#include "gl_resource_manager.h" 8#include "gl_resource_manager.h"
9#include "video_core/debug_utils/debug_utils.h"
9#include "video_core/pica.h" 10#include "video_core/pica.h"
10 11
11#include <memory> 12#include <memory>
@@ -16,7 +17,11 @@ public:
16 ~RasterizerCacheOpenGL(); 17 ~RasterizerCacheOpenGL();
17 18
18 /// Loads a texture from 3DS memory to OpenGL and caches it (if not already cached) 19 /// Loads a texture from 3DS memory to OpenGL and caches it (if not already cached)
19 void LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config); 20 void LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::DebugUtils::TextureInfo& info);
21
22 void LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) {
23 LoadAndBindTexture(state, texture_unit, Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format));
24 }
20 25
21 /// Flush any cached resource that touches the flushed region 26 /// Flush any cached resource that touches the flushed region
22 void NotifyFlush(PAddr addr, u32 size, bool ignore_hash = false); 27 void NotifyFlush(PAddr addr, u32 size, bool ignore_hash = false);
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index 68fc1e6d3..65034d40d 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -37,6 +37,30 @@ public:
37 GLuint handle = 0; 37 GLuint handle = 0;
38}; 38};
39 39
40class OGLSampler : private NonCopyable {
41public:
42 OGLSampler() = default;
43 OGLSampler(OGLSampler&& o) { std::swap(handle, o.handle); }
44 ~OGLSampler() { Release(); }
45 OGLSampler& operator=(OGLSampler&& o) { std::swap(handle, o.handle); return *this; }
46
47 /// Creates a new internal OpenGL resource and stores the handle
48 void Create() {
49 if (handle != 0) return;
50 glGenSamplers(1, &handle);
51 }
52
53 /// Deletes the internal OpenGL resource
54 void Release() {
55 if (handle == 0) return;
56 glDeleteSamplers(1, &handle);
57 OpenGLState::ResetSampler(handle);
58 handle = 0;
59 }
60
61 GLuint handle = 0;
62};
63
40class OGLShader : private NonCopyable { 64class OGLShader : private NonCopyable {
41public: 65public:
42 OGLShader() = default; 66 OGLShader() = default;
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index ba47ce8b8..e02c27fbf 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -44,6 +44,7 @@ OpenGLState::OpenGLState() {
44 44
45 for (auto& texture_unit : texture_units) { 45 for (auto& texture_unit : texture_units) {
46 texture_unit.texture_2d = 0; 46 texture_unit.texture_2d = 0;
47 texture_unit.sampler = 0;
47 } 48 }
48 49
49 draw.framebuffer = 0; 50 draw.framebuffer = 0;
@@ -154,10 +155,13 @@ void OpenGLState::Apply() {
154 } 155 }
155 156
156 // Textures 157 // Textures
157 for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { 158 for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) {
158 if (texture_units[texture_index].texture_2d != cur_state.texture_units[texture_index].texture_2d) { 159 if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) {
159 glActiveTexture(GL_TEXTURE0 + texture_index); 160 glActiveTexture(GL_TEXTURE0 + i);
160 glBindTexture(GL_TEXTURE_2D, texture_units[texture_index].texture_2d); 161 glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d);
162 }
163 if (texture_units[i].sampler != cur_state.texture_units[i].sampler) {
164 glBindSampler(i, texture_units[i].sampler);
161 } 165 }
162 } 166 }
163 167
@@ -192,6 +196,14 @@ void OpenGLState::ResetTexture(GLuint id) {
192 } 196 }
193} 197}
194 198
199void OpenGLState::ResetSampler(GLuint id) {
200 for (auto& unit : cur_state.texture_units) {
201 if (unit.sampler == id) {
202 unit.sampler = 0;
203 }
204 }
205}
206
195void OpenGLState::ResetProgram(GLuint id) { 207void OpenGLState::ResetProgram(GLuint id) {
196 if (cur_state.draw.shader_program == id) { 208 if (cur_state.draw.shader_program == id) {
197 cur_state.draw.shader_program = 0; 209 cur_state.draw.shader_program = 0;
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 43aa29a81..6ecbedbb4 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -57,6 +57,7 @@ public:
57 // 3 texture units - one for each that is used in PICA fragment shader emulation 57 // 3 texture units - one for each that is used in PICA fragment shader emulation
58 struct { 58 struct {
59 GLuint texture_2d; // GL_TEXTURE_BINDING_2D 59 GLuint texture_2d; // GL_TEXTURE_BINDING_2D
60 GLuint sampler; // GL_SAMPLER_BINDING
60 } texture_units[3]; 61 } texture_units[3];
61 62
62 struct { 63 struct {
@@ -77,6 +78,7 @@ public:
77 void Apply(); 78 void Apply();
78 79
79 static void ResetTexture(GLuint id); 80 static void ResetTexture(GLuint id);
81 static void ResetSampler(GLuint id);
80 static void ResetProgram(GLuint id); 82 static void ResetProgram(GLuint id);
81 static void ResetBuffer(GLuint id); 83 static void ResetBuffer(GLuint id);
82 static void ResetVertexArray(GLuint id); 84 static void ResetVertexArray(GLuint id);
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index 6344f467f..04c1d1a34 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -175,11 +175,11 @@ inline GLenum StencilOp(Pica::Regs::StencilAction action) {
175 return stencil_op_table[(unsigned)action]; 175 return stencil_op_table[(unsigned)action];
176} 176}
177 177
178inline std::array<GLfloat, 4> ColorRGBA8(const u8* bytes) { 178inline std::array<GLfloat, 4> ColorRGBA8(const u32 color) {
179 return { { bytes[0] / 255.0f, 179 return { { (color >> 0 & 0xFF) / 255.0f,
180 bytes[1] / 255.0f, 180 (color >> 8 & 0xFF) / 255.0f,
181 bytes[2] / 255.0f, 181 (color >> 16 & 0xFF) / 255.0f,
182 bytes[3] / 255.0f 182 (color >> 24 & 0xFF) / 255.0f
183 } }; 183 } };
184} 184}
185 185