|
|
@ -6,6 +6,7 @@
|
|
|
|
#include <array>
|
|
|
|
#include <array>
|
|
|
|
#include <atomic>
|
|
|
|
#include <atomic>
|
|
|
|
#include <bitset>
|
|
|
|
#include <bitset>
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cstring>
|
|
|
|
#include <iterator>
|
|
|
|
#include <iterator>
|
|
|
|
#include <memory>
|
|
|
|
#include <memory>
|
|
|
@ -250,8 +251,14 @@ OGLTexture RasterizerCacheOpenGL::AllocateSurfaceTexture(const FormatTuple& form
|
|
|
|
cur_state.Apply();
|
|
|
|
cur_state.Apply();
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (GL_ARB_texture_storage) {
|
|
|
|
|
|
|
|
// Allocate all possible mipmap levels upfront
|
|
|
|
|
|
|
|
auto levels = std::log2(std::max(width, height)) + 1;
|
|
|
|
|
|
|
|
glTexStorage2D(GL_TEXTURE_2D, levels, format_tuple.internal_format, width, height);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
|
|
|
|
format_tuple.format, format_tuple.type, nullptr);
|
|
|
|
format_tuple.format, format_tuple.type, nullptr);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
@ -273,7 +280,11 @@ static void AllocateTextureCube(GLuint texture, const FormatTuple& format_tuple,
|
|
|
|
cur_state.texture_cube_unit.texture_cube = texture;
|
|
|
|
cur_state.texture_cube_unit.texture_cube = texture;
|
|
|
|
cur_state.Apply();
|
|
|
|
cur_state.Apply();
|
|
|
|
glActiveTexture(TextureUnits::TextureCube.Enum());
|
|
|
|
glActiveTexture(TextureUnits::TextureCube.Enum());
|
|
|
|
|
|
|
|
if (GL_ARB_texture_storage) {
|
|
|
|
|
|
|
|
// Allocate all possible mipmap levels in case the game uses them later
|
|
|
|
|
|
|
|
auto levels = std::log2(width) + 1;
|
|
|
|
|
|
|
|
glTexStorage2D(GL_TEXTURE_CUBE_MAP, levels, format_tuple.internal_format, width, width);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
for (auto faces : {
|
|
|
|
for (auto faces : {
|
|
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
|
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
|
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
|
|
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
|
|
@ -282,8 +293,9 @@ static void AllocateTextureCube(GLuint texture, const FormatTuple& format_tuple,
|
|
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
|
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
|
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
|
|
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
|
|
|
}) {
|
|
|
|
}) {
|
|
|
|
glTexImage2D(faces, 0, format_tuple.internal_format, width, width, 0, format_tuple.format,
|
|
|
|
glTexImage2D(faces, 0, format_tuple.internal_format, width, width, 0,
|
|
|
|
format_tuple.type, nullptr);
|
|
|
|
format_tuple.format, format_tuple.type, nullptr);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Restore previous texture bindings
|
|
|
|
// Restore previous texture bindings
|
|
|
@ -1250,9 +1262,14 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::Texture::TextureInf
|
|
|
|
width = surface->GetScaledWidth();
|
|
|
|
width = surface->GetScaledWidth();
|
|
|
|
height = surface->GetScaledHeight();
|
|
|
|
height = surface->GetScaledHeight();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we are using ARB_texture_storage then we've already allocated all of the mipmap
|
|
|
|
|
|
|
|
// levels
|
|
|
|
|
|
|
|
if (!GL_ARB_texture_storage) {
|
|
|
|
for (u32 level = surface->max_level + 1; level <= max_level; ++level) {
|
|
|
|
for (u32 level = surface->max_level + 1; level <= max_level; ++level) {
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, level, format_tuple.internal_format, width >> level,
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, level, format_tuple.internal_format, width >> level,
|
|
|
|
height >> level, 0, format_tuple.format, format_tuple.type, nullptr);
|
|
|
|
height >> level, 0, format_tuple.format, format_tuple.type,
|
|
|
|
|
|
|
|
nullptr);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (surface->is_custom || !texture_filterer->IsNull()) {
|
|
|
|
if (surface->is_custom || !texture_filterer->IsNull()) {
|
|
|
|
// TODO: proper mipmap support for custom textures
|
|
|
|
// TODO: proper mipmap support for custom textures
|
|
|
|