diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra_qt/bootmanager.cpp | 3 | ||||
| -rw-r--r-- | src/citra_qt/main.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/pica.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 52 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.h | 24 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 20 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/pica_to_gl.h | 10 |
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 | ||
| 454 | void 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 | |||
| 464 | void 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 | |||
| 448 | void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height) { | 493 | void 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 | ||
| 660 | void RasterizerOpenGL::SyncBlendColor() { | 705 | void 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 | ||
| 730 | void RasterizerOpenGL::SyncTevColor(unsigned stage_index, const Pica::Regs::TevStageConfig& config) { | 775 | void 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 | ||
| 739 | void RasterizerOpenGL::SyncCombinerColor() { | 784 | void 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 | ||
| 21 | MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); | 21 | MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); |
| 22 | 22 | ||
| 23 | void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) { | 23 | void 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 | ||
| 40 | class OGLSampler : private NonCopyable { | ||
| 41 | public: | ||
| 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 | |||
| 40 | class OGLShader : private NonCopyable { | 64 | class OGLShader : private NonCopyable { |
| 41 | public: | 65 | public: |
| 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 | ||
| 199 | void 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 | |||
| 195 | void OpenGLState::ResetProgram(GLuint id) { | 207 | void 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 | ||
| 178 | inline std::array<GLfloat, 4> ColorRGBA8(const u8* bytes) { | 178 | inline 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 | ||