From ae83ab543673c5c8f025a8d9ce5146ff5ab8e33a Mon Sep 17 00:00:00 2001 From: DHrpcs3 Date: Mon, 21 Dec 2015 04:14:56 +0200 Subject: [PATCH] GLTexture excluded from GLGSRender and renamed to rsx::gl::texture --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 518 ---------------------------- rpcs3/Emu/RSX/GL/GLGSRender.h | 44 +-- rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp | 469 +++++++++++++++++++++++++ rpcs3/Emu/RSX/GL/rsx_gl_texture.h | 45 +++ rpcs3/GLGSRender.vcxproj | 2 + rpcs3/GLGSRender.vcxproj.filters | 2 + 6 files changed, 521 insertions(+), 559 deletions(-) create mode 100644 rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp create mode 100644 rpcs3/Emu/RSX/GL/rsx_gl_texture.h diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index ba10d04aa0..9b0c5d0146 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -9,524 +9,6 @@ #define DUMP_VERTEX_DATA 0 -void GLTexture::create() -{ - if (m_id) - { - remove(); - } - - glGenTextures(1, &m_id); - bind(); -} - -int GLTexture::gl_wrap(int wrap) -{ - switch (wrap) - { - case CELL_GCM_TEXTURE_WRAP: return GL_REPEAT; - case CELL_GCM_TEXTURE_MIRROR: return GL_MIRRORED_REPEAT; - case CELL_GCM_TEXTURE_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE; - case CELL_GCM_TEXTURE_BORDER: return GL_CLAMP_TO_BORDER; - case CELL_GCM_TEXTURE_CLAMP: return GL_CLAMP; - case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP_TO_EDGE: return GL_MIRROR_CLAMP_TO_EDGE_EXT; - case CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER: return GL_MIRROR_CLAMP_TO_BORDER_EXT; - case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP: return GL_MIRROR_CLAMP_EXT; - } - - LOG_ERROR(RSX, "Texture wrap error: bad wrap (%d).", wrap); - return GL_REPEAT; -} - -float GLTexture::max_aniso(int aniso) -{ - switch (aniso) - { - case CELL_GCM_TEXTURE_MAX_ANISO_1: return 1.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_2: return 2.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_4: return 4.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_6: return 6.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_8: return 8.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_10: return 10.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_12: return 12.0f; - case CELL_GCM_TEXTURE_MAX_ANISO_16: return 16.0f; - } - - LOG_ERROR(RSX, "Texture anisotropy error: bad max aniso (%d).", aniso); - return 1.0f; -} - -void GLTexture::init(rsx::texture& tex) -{ - if (!m_id) - create(); - - bind(); - - const u32 texaddr = rsx::get_address(tex.offset(), tex.location()); - //LOG_WARNING(RSX, "texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x", - // m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod); - - //TODO: safe init - - int format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); - bool is_swizzled = !(tex.format() & CELL_GCM_TEXTURE_LN); - - const u8* pixels = vm::ps3::_ptr(texaddr); - u8 *unswizzledPixels; - static const GLint glRemapStandard[4] = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE }; - // NOTE: This must be in ARGB order in all forms below. - const GLint *glRemap = glRemapStandard; - - switch (format) - { - case CELL_GCM_TEXTURE_B8: // One 8-bit fixed-point number - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels); - - static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE }; - glRemap = swizzleMaskB8; - break; - } - - case CELL_GCM_TEXTURE_A1R5G5B5: - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - - // TODO: texture swizzling - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - break; - } - - case CELL_GCM_TEXTURE_A4R4G4B4: - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels); - - // We read it in as R4G4B4A4, so we need to remap each component. - static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN }; - glRemap = swizzleMaskA4R4G4B4; - break; - } - - case CELL_GCM_TEXTURE_R5G6B5: - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.width(), tex.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - break; - } - - case CELL_GCM_TEXTURE_A8R8G8B8: - { - if (is_swizzled) - { - u32 *src, *dst; - u16 height = tex.height(); - u16 width = tex.width(); - - unswizzledPixels = (u8*)malloc(width * height * 4); - src = (u32*)pixels; - dst = (u32*)unswizzledPixels; - - if ((height & (height - 1)) || (width & (width - 1))) - { - LOG_ERROR(RSX, "Swizzle Texture: Width or height not power of 2! (h=%d,w=%d).", height, width); - } - - rsx::convert_linear_swizzle(src, dst, width, height, true); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, is_swizzled ? unswizzledPixels : pixels); - break; - } - - case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes - { - u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 8; - - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.width(), tex.height(), 0, size, pixels); - break; - } - - case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes - { - u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 16; - - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.width(), tex.height(), 0, size, pixels); - } - break; - - case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes - { - u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 16; - - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.width(), tex.height(), 0, size, pixels); - break; - } - - case CELL_GCM_TEXTURE_G8B8: - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_BYTE, pixels); - - static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; - glRemap = swizzleMaskG8B8; - break; - } - - case CELL_GCM_TEXTURE_R6G5B5: - { - // TODO: Probably need to actually unswizzle if is_swizzled. - const u32 numPixels = tex.width() * tex.height(); - unswizzledPixels = (u8 *)malloc(numPixels * 4); - // TODO: Speed. - for (u32 i = 0; i < numPixels; ++i) { - u16 c = reinterpret_cast *>(pixels)[i]; - unswizzledPixels[i * 4 + 0] = convert_6_to_8((c >> 10) & 0x3F); - unswizzledPixels[i * 4 + 1] = convert_5_to_8((c >> 5) & 0x1F); - unswizzledPixels[i * 4 + 2] = convert_5_to_8((c >> 0) & 0x1F); - unswizzledPixels[i * 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); - - free(unswizzledPixels); - break; - } - - case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels); - break; - } - - case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); - break; - } - - case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels); - break; - } - - case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); - break; - } - - case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - - static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE }; - glRemap = swizzleMaskX16; - break; - } - - case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; - glRemap = swizzleMaskX32_Y16_X16; - break; - } - - case CELL_GCM_TEXTURE_R5G5B5A1: - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - break; - } - - case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_HALF_FLOAT, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - break; - } - - case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_FLOAT, pixels); - break; - } - - case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_FLOAT, pixels); - - static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE }; - glRemap = swizzleMaskX32_FLOAT; - break; - } - - case CELL_GCM_TEXTURE_D1R5G5B5: - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - - - // TODO: Texture swizzling - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels); - - static const GLint swizzleMaskX32_D1R5G5B5[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; - glRemap = swizzleMaskX32_D1R5G5B5; - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - break; - } - - case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels); - - static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; - glRemap = swizzleMaskX32_D8R8G8B8; - break; - } - - - case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_HALF_FLOAT, pixels); - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - - static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; - glRemap = swizzleMaskX32_Y16_X16_FLOAT; - break; - } - - case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: - { - const u32 numPixels = tex.width() * tex.height(); - unswizzledPixels = (u8 *)malloc(numPixels * 4); - // TODO: Speed. - for (u32 i = 0; i < numPixels; i += 2) - { - unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3]; - unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2]; - unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0]; - unswizzledPixels[i * 4 + 0 + 3] = 255; - - // The second pixel is the same, except for red. - unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 1]; - unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 2]; - unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 0]; - unswizzledPixels[i * 4 + 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); - free(unswizzledPixels); - break; - } - - case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: - { - const u32 numPixels = tex.width() * tex.height(); - unswizzledPixels = (u8 *)malloc(numPixels * 4); - // TODO: Speed. - for (u32 i = 0; i < numPixels; i += 2) - { - unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2]; - unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3]; - unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1]; - unswizzledPixels[i * 4 + 0 + 3] = 255; - - // The second pixel is the same, except for red. - unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 0]; - unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 3]; - unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 1]; - unswizzledPixels[i * 4 + 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); - free(unswizzledPixels); - break; - } - - default: - { - LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.format() & 0x40); - break; - } - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.mipmap() - 1); - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.mipmap() > 1); - - if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT) - { - u8 remap_a = tex.remap() & 0x3; - u8 remap_r = (tex.remap() >> 2) & 0x3; - u8 remap_g = (tex.remap() >> 4) & 0x3; - u8 remap_b = (tex.remap() >> 6) & 0x3; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]); - } - else - { - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[1]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[3]); - } - - static const int gl_tex_zfunc[] = - { - GL_NEVER, - GL_LESS, - GL_EQUAL, - GL_LEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_GEQUAL, - GL_ALWAYS, - }; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s())); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t())); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r())); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]); - - glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.bias()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8)); - - - - static const int gl_tex_min_filter[] = - { - GL_NEAREST, // unused - GL_NEAREST, - GL_LINEAR, - GL_NEAREST_MIPMAP_NEAREST, - GL_LINEAR_MIPMAP_NEAREST, - GL_NEAREST_MIPMAP_LINEAR, - GL_LINEAR_MIPMAP_LINEAR, - GL_NEAREST, // CELL_GCM_TEXTURE_CONVOLUTION_MIN - }; - - static const int gl_tex_mag_filter[] = { - GL_NEAREST, // unused - GL_NEAREST, - GL_LINEAR, - GL_NEAREST, // unused - GL_LINEAR // CELL_GCM_TEXTURE_CONVOLUTION_MAG - }; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter[tex.min_filter()]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter[tex.mag_filter()]); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso())); - - //Unbind(); - - if (is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8) - { - free(unswizzledPixels); - } -} - -void GLTexture::save(rsx::texture& tex, const std::string& name) -{ - if (!m_id || !tex.offset() || !tex.width() || !tex.height()) return; - - const u32 texPixelCount = tex.width() * tex.height(); - - u32* alldata = new u32[texPixelCount]; - - bind(); - - switch (tex.format() & ~(0x20 | 0x40)) - { - case CELL_GCM_TEXTURE_B8: - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata); - break; - - case CELL_GCM_TEXTURE_A8R8G8B8: - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, alldata); - break; - - default: - delete[] alldata; - return; - } - - fs::file(fs::get_config_dir() + name + ".raw", fom::rewrite).write(alldata, texPixelCount * 4); - - u8* data = new u8[texPixelCount * 3]; - u8* alpha = new u8[texPixelCount]; - - u8* src = (u8*)alldata; - u8* dst_d = data; - u8* dst_a = alpha; - for (u32 i = 0; i < texPixelCount; i++) - { - *dst_d++ = *src++; - *dst_d++ = *src++; - *dst_d++ = *src++; - *dst_a++ = *src++; - } - - rImage out; - out.Create(tex.width(), tex.height(), data, alpha); - out.SaveFile(name, rBITMAP_TYPE_PNG); - - delete[] alldata; - //free(data); - //free(alpha); -} - -void GLTexture::save(rsx::texture& tex) -{ - static const std::string& dir_path = "textures"; - static const std::string& file_fmt = dir_path + "/" + "tex[%d].png"; - - if (!fs::is_dir(dir_path)) fs::create_dir(dir_path); - - u32 count = 0; - while (fs::is_file(fmt::format(file_fmt.c_str(), count))) count++; - save(tex, fmt::format(file_fmt.c_str(), count)); -} - -void GLTexture::bind() -{ - glBindTexture(GL_TEXTURE_2D, m_id); -} - -void GLTexture::unbind() -{ - glBindTexture(GL_TEXTURE_2D, 0); -} - -void GLTexture::remove() -{ - if (m_id) - { - glDeleteTextures(1, &m_id); - m_id = 0; - } -} - -u32 GLTexture::id() const -{ - return m_id; -} - GLGSRender::GLGSRender() : GSRender(frame_type::OpenGL) { } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 3dbf1fd678..b49d52a569 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -1,6 +1,7 @@ #pragma once #include "Emu/RSX/GSRender.h" #include "gl_helpers.h" +#include "rsx_gl_texture.h" #define RSX_DEBUG 1 @@ -8,53 +9,14 @@ #pragma comment(lib, "opengl32.lib") -class GLTexture -{ - u32 m_id = 0; - -public: - void create(); - - int gl_wrap(int wrap); - - float max_aniso(int aniso); - - inline static u8 convert_4_to_8(u8 v) - { - // Swizzle bits: 00001234 -> 12341234 - return (v << 4) | (v); - } - - inline static u8 convert_5_to_8(u8 v) - { - // Swizzle bits: 00012345 -> 12345123 - return (v << 3) | (v >> 2); - } - - inline static u8 convert_6_to_8(u8 v) - { - // Swizzle bits: 00123456 -> 12345612 - return (v << 2) | (v >> 4); - } - - void init(rsx::texture& tex); - void save(rsx::texture& tex, const std::string& name); - void save(rsx::texture& tex); - void bind(); - void unbind(); - void remove(); - - u32 id() const; -}; - class GLGSRender : public GSRender { private: GLFragmentProgram m_fragment_prog; GLVertexProgram m_vertex_prog; - GLTexture m_gl_textures[rsx::limits::textures_count]; - GLTexture m_gl_vertex_textures[rsx::limits::vertex_textures_count]; + rsx::gl::texture m_gl_textures[rsx::limits::textures_count]; + rsx::gl::texture m_gl_vertex_textures[rsx::limits::vertex_textures_count]; gl::glsl::program *m_program; diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp new file mode 100644 index 0000000000..b50d7a1d33 --- /dev/null +++ b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp @@ -0,0 +1,469 @@ +#include "stdafx.h" +#include "rsx_gl_texture.h" +#include "gl_helpers.h" +#include "../GCM.h" +#include "../RSXThread.h" +#include "../RSXTexture.h" +#include "Utilities/Log.h" + +namespace rsx +{ + namespace gl + { + void texture::create() + { + if (m_id) + { + remove(); + } + + glGenTextures(1, &m_id); + bind(); + } + + int texture::gl_wrap(int wrap) + { + switch (wrap) + { + case CELL_GCM_TEXTURE_WRAP: return GL_REPEAT; + case CELL_GCM_TEXTURE_MIRROR: return GL_MIRRORED_REPEAT; + case CELL_GCM_TEXTURE_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE; + case CELL_GCM_TEXTURE_BORDER: return GL_CLAMP_TO_BORDER; + case CELL_GCM_TEXTURE_CLAMP: return GL_CLAMP; + case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP_TO_EDGE: return GL_MIRROR_CLAMP_TO_EDGE_EXT; + case CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER: return GL_MIRROR_CLAMP_TO_BORDER_EXT; + case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP: return GL_MIRROR_CLAMP_EXT; + } + + LOG_ERROR(RSX, "Texture wrap error: bad wrap (%d).", wrap); + return GL_REPEAT; + } + + float texture::max_aniso(int aniso) + { + switch (aniso) + { + case CELL_GCM_TEXTURE_MAX_ANISO_1: return 1.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_2: return 2.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_4: return 4.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_6: return 6.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_8: return 8.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_10: return 10.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_12: return 12.0f; + case CELL_GCM_TEXTURE_MAX_ANISO_16: return 16.0f; + } + + LOG_ERROR(RSX, "Texture anisotropy error: bad max aniso (%d).", aniso); + return 1.0f; + } + + void texture::init(rsx::texture& tex) + { + if (!m_id) + create(); + + bind(); + + const u32 texaddr = rsx::get_address(tex.offset(), tex.location()); + //LOG_WARNING(RSX, "texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x", + // m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod); + + //TODO: safe init + + int format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + bool is_swizzled = !(tex.format() & CELL_GCM_TEXTURE_LN); + + const u8* pixels = vm::ps3::_ptr(texaddr); + u8 *unswizzledPixels; + static const GLint glRemapStandard[4] = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE }; + // NOTE: This must be in ARGB order in all forms below. + const GLint *glRemap = glRemapStandard; + + switch (format) + { + case CELL_GCM_TEXTURE_B8: // One 8-bit fixed-point number + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels); + + static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE }; + glRemap = swizzleMaskB8; + break; + } + + case CELL_GCM_TEXTURE_A1R5G5B5: + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + + // TODO: texture swizzling + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + break; + } + + case CELL_GCM_TEXTURE_A4R4G4B4: + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels); + + // We read it in as R4G4B4A4, so we need to remap each component. + static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN }; + glRemap = swizzleMaskA4R4G4B4; + break; + } + + case CELL_GCM_TEXTURE_R5G6B5: + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.width(), tex.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + break; + } + + case CELL_GCM_TEXTURE_A8R8G8B8: + { + if (is_swizzled) + { + u32 *src, *dst; + u16 height = tex.height(); + u16 width = tex.width(); + + unswizzledPixels = (u8*)malloc(width * height * 4); + src = (u32*)pixels; + dst = (u32*)unswizzledPixels; + + if ((height & (height - 1)) || (width & (width - 1))) + { + LOG_ERROR(RSX, "Swizzle Texture: Width or height not power of 2! (h=%d,w=%d).", height, width); + } + + rsx::convert_linear_swizzle(src, dst, width, height, true); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, is_swizzled ? unswizzledPixels : pixels); + break; + } + + case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes + { + u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 8; + + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.width(), tex.height(), 0, size, pixels); + break; + } + + case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes + { + u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 16; + + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.width(), tex.height(), 0, size, pixels); + } + break; + + case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes + { + u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 16; + + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.width(), tex.height(), 0, size, pixels); + break; + } + + case CELL_GCM_TEXTURE_G8B8: + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_BYTE, pixels); + + static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; + glRemap = swizzleMaskG8B8; + break; + } + + case CELL_GCM_TEXTURE_R6G5B5: + { + // TODO: Probably need to actually unswizzle if is_swizzled. + const u32 numPixels = tex.width() * tex.height(); + unswizzledPixels = (u8 *)malloc(numPixels * 4); + // TODO: Speed. + for (u32 i = 0; i < numPixels; ++i) { + u16 c = reinterpret_cast *>(pixels)[i]; + unswizzledPixels[i * 4 + 0] = convert_6_to_8((c >> 10) & 0x3F); + unswizzledPixels[i * 4 + 1] = convert_5_to_8((c >> 5) & 0x1F); + unswizzledPixels[i * 4 + 2] = convert_5_to_8((c >> 0) & 0x1F); + unswizzledPixels[i * 4 + 3] = 255; + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); + + free(unswizzledPixels); + break; + } + + case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels); + break; + } + + case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); + break; + } + + case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels); + break; + } + + case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); + break; + } + + case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + + static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE }; + glRemap = swizzleMaskX16; + break; + } + + case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; + glRemap = swizzleMaskX32_Y16_X16; + break; + } + + case CELL_GCM_TEXTURE_R5G5B5A1: + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + break; + } + + case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_HALF_FLOAT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + break; + } + + case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_FLOAT, pixels); + break; + } + + case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_FLOAT, pixels); + + static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE }; + glRemap = swizzleMaskX32_FLOAT; + break; + } + + case CELL_GCM_TEXTURE_D1R5G5B5: + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + + + // TODO: Texture swizzling + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels); + + static const GLint swizzleMaskX32_D1R5G5B5[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; + glRemap = swizzleMaskX32_D1R5G5B5; + + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + break; + } + + case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels); + + static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; + glRemap = swizzleMaskX32_D8R8G8B8; + break; + } + + + case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_HALF_FLOAT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + + static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; + glRemap = swizzleMaskX32_Y16_X16_FLOAT; + break; + } + + case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: + { + const u32 numPixels = tex.width() * tex.height(); + unswizzledPixels = (u8 *)malloc(numPixels * 4); + // TODO: Speed. + for (u32 i = 0; i < numPixels; i += 2) + { + unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3]; + unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2]; + unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0]; + unswizzledPixels[i * 4 + 0 + 3] = 255; + + // The second pixel is the same, except for red. + unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 1]; + unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 2]; + unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 0]; + unswizzledPixels[i * 4 + 4 + 3] = 255; + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); + free(unswizzledPixels); + break; + } + + case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: + { + const u32 numPixels = tex.width() * tex.height(); + unswizzledPixels = (u8 *)malloc(numPixels * 4); + // TODO: Speed. + for (u32 i = 0; i < numPixels; i += 2) + { + unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2]; + unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3]; + unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1]; + unswizzledPixels[i * 4 + 0 + 3] = 255; + + // The second pixel is the same, except for red. + unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 0]; + unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 3]; + unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 1]; + unswizzledPixels[i * 4 + 4 + 3] = 255; + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels); + free(unswizzledPixels); + break; + } + + default: + { + LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.format() & 0x40); + break; + } + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.mipmap() - 1); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.mipmap() > 1); + + if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT) + { + u8 remap_a = tex.remap() & 0x3; + u8 remap_r = (tex.remap() >> 2) & 0x3; + u8 remap_g = (tex.remap() >> 4) & 0x3; + u8 remap_b = (tex.remap() >> 6) & 0x3; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]); + } + else + { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[1]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[3]); + } + + static const int gl_tex_zfunc[] = + { + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS, + }; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s())); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t())); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r())); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]); + + glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.bias()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8)); + + + + static const int gl_tex_min_filter[] = + { + GL_NEAREST, // unused + GL_NEAREST, + GL_LINEAR, + GL_NEAREST_MIPMAP_NEAREST, + GL_LINEAR_MIPMAP_NEAREST, + GL_NEAREST_MIPMAP_LINEAR, + GL_LINEAR_MIPMAP_LINEAR, + GL_NEAREST, // CELL_GCM_TEXTURE_CONVOLUTION_MIN + }; + + static const int gl_tex_mag_filter[] = { + GL_NEAREST, // unused + GL_NEAREST, + GL_LINEAR, + GL_NEAREST, // unused + GL_LINEAR // CELL_GCM_TEXTURE_CONVOLUTION_MAG + }; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter[tex.min_filter()]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter[tex.mag_filter()]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso())); + + //Unbind(); + + if (is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8) + { + free(unswizzledPixels); + } + } + + void texture::bind() + { + glBindTexture(GL_TEXTURE_2D, m_id); + } + + void texture::unbind() + { + glBindTexture(GL_TEXTURE_2D, 0); + } + + void texture::remove() + { + if (m_id) + { + glDeleteTextures(1, &m_id); + m_id = 0; + } + } + + u32 texture::id() const + { + return m_id; + } + } +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_texture.h b/rpcs3/Emu/RSX/GL/rsx_gl_texture.h new file mode 100644 index 0000000000..df6fe0c3ce --- /dev/null +++ b/rpcs3/Emu/RSX/GL/rsx_gl_texture.h @@ -0,0 +1,45 @@ + +namespace rsx +{ + class texture; + + namespace gl + { + class texture + { + u32 m_id = 0; + + public: + void create(); + + int gl_wrap(int wrap); + + float max_aniso(int aniso); + + inline static u8 convert_4_to_8(u8 v) + { + // Swizzle bits: 00001234 -> 12341234 + return (v << 4) | (v); + } + + inline static u8 convert_5_to_8(u8 v) + { + // Swizzle bits: 00012345 -> 12345123 + return (v << 3) | (v >> 2); + } + + inline static u8 convert_6_to_8(u8 v) + { + // Swizzle bits: 00123456 -> 12345612 + return (v << 2) | (v >> 4); + } + + void init(rsx::texture& tex); + void bind(); + void unbind(); + void remove(); + + u32 id() const; + }; + } +} \ No newline at end of file diff --git a/rpcs3/GLGSRender.vcxproj b/rpcs3/GLGSRender.vcxproj index 720e48242b..e47df409ab 100644 --- a/rpcs3/GLGSRender.vcxproj +++ b/rpcs3/GLGSRender.vcxproj @@ -124,6 +124,7 @@ + @@ -132,6 +133,7 @@ + diff --git a/rpcs3/GLGSRender.vcxproj.filters b/rpcs3/GLGSRender.vcxproj.filters index 83c53a7b4e..b955e42804 100644 --- a/rpcs3/GLGSRender.vcxproj.filters +++ b/rpcs3/GLGSRender.vcxproj.filters @@ -19,6 +19,7 @@ Source Files + @@ -45,6 +46,7 @@ Source Files +