mirror of https://github.com/xemu-project/xemu.git
nv2a: Support compressed 2D texture padding
This commit is contained in:
parent
14748d9bbb
commit
280a1bb6a1
|
@ -6277,41 +6277,23 @@ static void pgraph_bind_textures(NV2AState *d)
|
||||||
depth = 1 << log_depth;
|
depth = 1 << log_depth;
|
||||||
pitch = 0;
|
pitch = 0;
|
||||||
|
|
||||||
/* FIXME: What about 3D mipmaps? */
|
|
||||||
levels = MIN(levels, max_mipmap_level + 1);
|
levels = MIN(levels, max_mipmap_level + 1);
|
||||||
if (f.gl_format != 0) {
|
|
||||||
/* Discard mipmap levels that would be smaller than 1x1.
|
/* Discard mipmap levels that would be smaller than 1x1.
|
||||||
* FIXME: Is this actually needed?
|
* FIXME: Is this actually needed?
|
||||||
*
|
*
|
||||||
* >> Level 0: 32 x 4
|
* >> Level 0: 32 x 4
|
||||||
* Level 1: 16 x 2
|
* Level 1: 16 x 2
|
||||||
* Level 2: 8 x 1
|
* Level 2: 8 x 1
|
||||||
* Level 3: 4 x 1
|
* Level 3: 4 x 1
|
||||||
* Level 4: 2 x 1
|
* Level 4: 2 x 1
|
||||||
* Level 5: 1 x 1
|
* Level 5: 1 x 1
|
||||||
*/
|
*/
|
||||||
levels = MIN(levels, MAX(log_width, log_height) + 1);
|
levels = MIN(levels, MAX(log_width, log_height) + 1);
|
||||||
} else {
|
assert(levels > 0);
|
||||||
/* OpenGL requires DXT textures to always have a width and
|
|
||||||
* height a multiple of 4. The Xbox and DirectX handles DXT
|
if (dimensionality == 3) {
|
||||||
* textures smaller than 4 by padding the reset of the block.
|
/* FIXME: What about 3D mipmaps? */
|
||||||
*
|
|
||||||
* See:
|
|
||||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/bb204843(v=vs.85).aspx
|
|
||||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531%28v=vs.85%29.aspx#Virtual_Size
|
|
||||||
*
|
|
||||||
* Work around this for now by discarding mipmap levels that
|
|
||||||
* would result in too-small textures. A correct solution
|
|
||||||
* will be to decompress these levels manually, or add texture
|
|
||||||
* sampling logic.
|
|
||||||
*
|
|
||||||
* >> Level 0: 64 x 8
|
|
||||||
* Level 1: 32 x 4
|
|
||||||
* Level 2: 16 x 2 << Ignored
|
|
||||||
* >> Level 0: 16 x 16
|
|
||||||
* Level 1: 8 x 8
|
|
||||||
* Level 2: 4 x 4 << OK!
|
|
||||||
*/
|
|
||||||
if (log_width < 2 || log_height < 2) {
|
if (log_width < 2 || log_height < 2) {
|
||||||
/* Base level is smaller than 4x4... */
|
/* Base level is smaller than 4x4... */
|
||||||
levels = 1;
|
levels = 1;
|
||||||
|
@ -6319,7 +6301,6 @@ static void pgraph_bind_textures(NV2AState *d)
|
||||||
levels = MIN(levels, MIN(log_width, log_height) - 1);
|
levels = MIN(levels, MIN(log_width, log_height) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(levels > 0);
|
|
||||||
min_mipmap_level = MIN(levels-1, min_mipmap_level);
|
min_mipmap_level = MIN(levels-1, min_mipmap_level);
|
||||||
max_mipmap_level = MIN(levels-1, max_mipmap_level);
|
max_mipmap_level = MIN(levels-1, max_mipmap_level);
|
||||||
}
|
}
|
||||||
|
@ -6335,25 +6316,26 @@ static void pgraph_bind_textures(NV2AState *d)
|
||||||
int level;
|
int level;
|
||||||
if (f.gl_format != 0) {
|
if (f.gl_format != 0) {
|
||||||
for (level = 0; level < levels; level++) {
|
for (level = 0; level < levels; level++) {
|
||||||
w = MAX(w, 1); h = MAX(h, 1);
|
w = MAX(w, 1);
|
||||||
|
h = MAX(h, 1);
|
||||||
length += w * h * f.bytes_per_pixel;
|
length += w * h * f.bytes_per_pixel;
|
||||||
w /= 2;
|
w /= 2;
|
||||||
h /= 2;
|
h /= 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Compressed textures are a bit different */
|
/* Compressed textures are a bit different */
|
||||||
unsigned int block_size;
|
unsigned int block_size =
|
||||||
if (f.gl_internal_format ==
|
f.gl_internal_format ==
|
||||||
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
|
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ?
|
||||||
block_size = 8;
|
8 : 16;
|
||||||
} else {
|
|
||||||
block_size = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (level = 0; level < levels; level++) {
|
for (level = 0; level < levels; level++) {
|
||||||
w = MAX(w, 4); h = MAX(h, 4);
|
w = MAX(w, 1);
|
||||||
length += w/4 * h/4 * block_size;
|
h = MAX(h, 1);
|
||||||
w /= 2; h /= 2;
|
unsigned int phys_w = (w + 3) & ~3,
|
||||||
|
phys_h = (h + 3) & ~3;
|
||||||
|
length += phys_w/4 * phys_h/4 * block_size;
|
||||||
|
w /= 2;
|
||||||
|
h /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cubemap) {
|
if (cubemap) {
|
||||||
|
@ -6986,44 +6968,42 @@ static void upload_gl_texture(GLenum gl_target,
|
||||||
|
|
||||||
int level;
|
int level;
|
||||||
for (level = 0; level < s.levels; level++) {
|
for (level = 0; level < s.levels; level++) {
|
||||||
|
width = MAX(width, 1);
|
||||||
|
height = MAX(height, 1);
|
||||||
|
|
||||||
if (f.gl_format == 0) { /* compressed */
|
if (f.gl_format == 0) { /* compressed */
|
||||||
assert(width >= 4 && height >= 4 &&
|
// https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#virtual-size-versus-physical-size
|
||||||
"Compressed texture padding");
|
unsigned int block_size =
|
||||||
width = MAX(width, 4); height = MAX(height, 4);
|
f.gl_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ?
|
||||||
|
8 : 16;
|
||||||
unsigned int block_size;
|
unsigned int physical_width = (width + 3) & ~3,
|
||||||
if (f.gl_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
|
physical_height = (height + 3) & ~3;
|
||||||
block_size = 8;
|
if (physical_width != width) {
|
||||||
} else {
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, physical_width * 4);
|
||||||
block_size = 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *converted = decompress_2d_texture_data(
|
uint8_t *converted = decompress_2d_texture_data(
|
||||||
f.gl_internal_format, texture_data, width, height);
|
f.gl_internal_format, texture_data, physical_width,
|
||||||
|
physical_height);
|
||||||
glTexImage2D(gl_target, level, GL_RGBA, width, height, 0,
|
glTexImage2D(gl_target, level, GL_RGBA, width, height, 0,
|
||||||
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, converted);
|
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, converted);
|
||||||
g_free(converted);
|
g_free(converted);
|
||||||
|
if (physical_width != width) {
|
||||||
texture_data += width/4 * height/4 * block_size;
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
}
|
||||||
|
texture_data +=
|
||||||
|
physical_width / 4 * physical_height / 4 * block_size;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
width = MAX(width, 1); height = MAX(height, 1);
|
|
||||||
|
|
||||||
unsigned int pitch = width * f.bytes_per_pixel;
|
unsigned int pitch = width * f.bytes_per_pixel;
|
||||||
uint8_t *unswizzled = (uint8_t*)g_malloc(height * pitch);
|
uint8_t *unswizzled = (uint8_t*)g_malloc(height * pitch);
|
||||||
unswizzle_rect(texture_data, width, height,
|
unswizzle_rect(texture_data, width, height,
|
||||||
unswizzled, pitch, f.bytes_per_pixel);
|
unswizzled, pitch, f.bytes_per_pixel);
|
||||||
|
|
||||||
uint8_t *converted = convert_texture_data(s, unswizzled,
|
uint8_t *converted = convert_texture_data(s, unswizzled,
|
||||||
palette_data,
|
palette_data,
|
||||||
width, height, 1,
|
width, height, 1,
|
||||||
pitch, 0);
|
pitch, 0);
|
||||||
|
glTexImage2D(gl_target, level, f.gl_internal_format, width,
|
||||||
glTexImage2D(gl_target, level, f.gl_internal_format,
|
height, 0, f.gl_format, f.gl_type,
|
||||||
width, height, 0,
|
|
||||||
f.gl_format, f.gl_type,
|
|
||||||
converted ? converted : unswizzled);
|
converted ? converted : unswizzled);
|
||||||
|
|
||||||
if (converted) {
|
if (converted) {
|
||||||
g_free(converted);
|
g_free(converted);
|
||||||
}
|
}
|
||||||
|
@ -7047,7 +7027,8 @@ static void upload_gl_texture(GLenum gl_target,
|
||||||
int level;
|
int level;
|
||||||
for (level = 0; level < s.levels; level++) {
|
for (level = 0; level < s.levels; level++) {
|
||||||
if (f.gl_format == 0) { /* compressed */
|
if (f.gl_format == 0) { /* compressed */
|
||||||
|
assert(width % 4 == 0 && height % 4 == 0 &&
|
||||||
|
"Compressed 3D texture virtual size");
|
||||||
width = MAX(width, 4);
|
width = MAX(width, 4);
|
||||||
height = MAX(height, 4);
|
height = MAX(height, 4);
|
||||||
depth = MAX(depth, 1);
|
depth = MAX(depth, 1);
|
||||||
|
@ -7072,6 +7053,9 @@ static void upload_gl_texture(GLenum gl_target,
|
||||||
|
|
||||||
texture_data += texture_size;
|
texture_data += texture_size;
|
||||||
} else {
|
} else {
|
||||||
|
width = MAX(width, 1);
|
||||||
|
height = MAX(height, 1);
|
||||||
|
depth = MAX(depth, 1);
|
||||||
|
|
||||||
unsigned int row_pitch = width * f.bytes_per_pixel;
|
unsigned int row_pitch = width * f.bytes_per_pixel;
|
||||||
unsigned int slice_pitch = row_pitch * height;
|
unsigned int slice_pitch = row_pitch * height;
|
||||||
|
|
Loading…
Reference in New Issue