gl_rasterizer_cache: Handle compressed texture sizes.
This commit is contained in:
		
							parent
							
								
									4415e00181
								
							
						
					
					
						commit
						bc0f1896fc
					
				@ -41,18 +41,15 @@ struct FormatTuple {
 | 
			
		||||
    GLenum format;
 | 
			
		||||
    GLenum type;
 | 
			
		||||
    bool compressed;
 | 
			
		||||
    // How many pixels in the original texture are equivalent to one pixel in the compressed
 | 
			
		||||
    // texture.
 | 
			
		||||
    u32 compression_factor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
 | 
			
		||||
    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1},                     // ABGR8
 | 
			
		||||
    {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1},                        // B5G6R5
 | 
			
		||||
    {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false, 1},               // A2B10G10R10
 | 
			
		||||
    {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16},   // DXT1
 | 
			
		||||
    {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23
 | 
			
		||||
    {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45
 | 
			
		||||
    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false},                    // ABGR8
 | 
			
		||||
    {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false},                       // B5G6R5
 | 
			
		||||
    {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false},              // A2B10G10R10
 | 
			
		||||
    {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true},   // DXT1
 | 
			
		||||
    {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23
 | 
			
		||||
    {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
 | 
			
		||||
@ -476,7 +473,7 @@ void CachedSurface::LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr loa
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (gl_buffer == nullptr) {
 | 
			
		||||
        gl_buffer_size = width * height * GetGLBytesPerPixel(pixel_format);
 | 
			
		||||
        gl_buffer_size = GetActualWidth() * GetActualHeight() * GetGLBytesPerPixel(pixel_format);
 | 
			
		||||
        gl_buffer.reset(new u8[gl_buffer_size]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -491,8 +488,9 @@ void CachedSurface::LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr loa
 | 
			
		||||
        std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
 | 
			
		||||
                    bytes_per_pixel * width * height);
 | 
			
		||||
    } else {
 | 
			
		||||
        morton_to_gl_fns[static_cast<size_t>(pixel_format)](
 | 
			
		||||
            stride, block_height, height, &gl_buffer[0], addr, load_start, load_end);
 | 
			
		||||
        morton_to_gl_fns[static_cast<size_t>(pixel_format)](GetActualWidth(), block_height,
 | 
			
		||||
                                                            GetActualHeight(), &gl_buffer[0], addr,
 | 
			
		||||
                                                            load_start, load_end);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -548,7 +546,8 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_TextureUL);
 | 
			
		||||
 | 
			
		||||
    ASSERT(gl_buffer_size == width * height * GetGLBytesPerPixel(pixel_format));
 | 
			
		||||
    ASSERT(gl_buffer_size ==
 | 
			
		||||
           GetActualWidth() * GetActualHeight() * GetGLBytesPerPixel(pixel_format));
 | 
			
		||||
 | 
			
		||||
    // Load data from memory to the surface
 | 
			
		||||
    GLint x0 = static_cast<GLint>(rect.left);
 | 
			
		||||
@ -583,11 +582,9 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
 | 
			
		||||
    glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
    if (tuple.compressed) {
 | 
			
		||||
        glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format,
 | 
			
		||||
                               static_cast<GLsizei>(rect.GetWidth()),
 | 
			
		||||
                               static_cast<GLsizei>(rect.GetHeight()), 0,
 | 
			
		||||
                               rect.GetWidth() * rect.GetHeight() *
 | 
			
		||||
                                   GetGLBytesPerPixel(pixel_format) / tuple.compression_factor,
 | 
			
		||||
                               &gl_buffer[buffer_offset]);
 | 
			
		||||
                               static_cast<GLsizei>(rect.GetWidth() * GetCompresssionFactor()),
 | 
			
		||||
                               static_cast<GLsizei>(rect.GetHeight() * GetCompresssionFactor()), 0,
 | 
			
		||||
                               size, &gl_buffer[buffer_offset]);
 | 
			
		||||
    } else {
 | 
			
		||||
        glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
 | 
			
		||||
                        static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
			
		||||
@ -1041,10 +1038,10 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
 | 
			
		||||
 | 
			
		||||
    SurfaceParams params;
 | 
			
		||||
    params.addr = config.tic.Address();
 | 
			
		||||
    params.width = config.tic.Width();
 | 
			
		||||
    params.height = config.tic.Height();
 | 
			
		||||
    params.is_tiled = config.tic.IsTiled();
 | 
			
		||||
    params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
 | 
			
		||||
    params.width = config.tic.Width() / params.GetCompresssionFactor();
 | 
			
		||||
    params.height = config.tic.Height() / params.GetCompresssionFactor();
 | 
			
		||||
 | 
			
		||||
    // TODO(Subv): Different types per component are not supported.
 | 
			
		||||
    ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
 | 
			
		||||
 | 
			
		||||
@ -84,23 +84,49 @@ struct SurfaceParams {
 | 
			
		||||
        Invalid = 4,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static constexpr unsigned int GetFormatBpp(PixelFormat format) {
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the compression factor for the specified PixelFormat. This applies to just the
 | 
			
		||||
     * "compressed width" and "compressed height", not the overall compression factor of a
 | 
			
		||||
     * compressed image. This is used for maintaining proper surface sizes for compressed texture
 | 
			
		||||
     * formats.
 | 
			
		||||
     */
 | 
			
		||||
    static constexpr u32 GetCompresssionFactor(PixelFormat format) {
 | 
			
		||||
        if (format == PixelFormat::Invalid)
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = {
 | 
			
		||||
        constexpr std::array<u32, MaxPixelFormat> compression_factor_table = {{
 | 
			
		||||
            1, // ABGR8
 | 
			
		||||
            1, // B5G6R5
 | 
			
		||||
            1, // A2B10G10R10
 | 
			
		||||
            4, // DXT1
 | 
			
		||||
            4, // DXT23
 | 
			
		||||
            4, // DXT45
 | 
			
		||||
        }};
 | 
			
		||||
 | 
			
		||||
        ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
 | 
			
		||||
        return compression_factor_table[static_cast<size_t>(format)];
 | 
			
		||||
    }
 | 
			
		||||
    u32 GetCompresssionFactor() const {
 | 
			
		||||
        return GetCompresssionFactor(pixel_format);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static constexpr u32 GetFormatBpp(PixelFormat format) {
 | 
			
		||||
        if (format == PixelFormat::Invalid)
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
 | 
			
		||||
            32,  // ABGR8
 | 
			
		||||
            16,  // B5G6R5
 | 
			
		||||
            32,  // A2B10G10R10
 | 
			
		||||
            64,  // DXT1
 | 
			
		||||
            128, // DXT23
 | 
			
		||||
            128, // DXT45
 | 
			
		||||
        };
 | 
			
		||||
        }};
 | 
			
		||||
 | 
			
		||||
        ASSERT(static_cast<size_t>(format) < bpp_table.size());
 | 
			
		||||
        return bpp_table[static_cast<size_t>(format)];
 | 
			
		||||
    }
 | 
			
		||||
    unsigned int GetFormatBpp() const {
 | 
			
		||||
    u32 GetFormatBpp() const {
 | 
			
		||||
        return GetFormatBpp(pixel_format);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -255,6 +281,24 @@ struct SurfaceParams {
 | 
			
		||||
    // Returns the region of the biggest valid rectange within interval
 | 
			
		||||
    SurfaceInterval GetCopyableInterval(const Surface& src_surface) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the actual width (in pixels) of the surface. This is provided because `width` is used
 | 
			
		||||
     * for tracking the surface region in memory, which may be compressed for certain formats. In
 | 
			
		||||
     * this scenario, `width` is actually the compressed width.
 | 
			
		||||
     */
 | 
			
		||||
    u32 GetActualWidth() const {
 | 
			
		||||
        return width * GetCompresssionFactor();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the actual height (in pixels) of the surface. This is provided because `height` is used
 | 
			
		||||
     * for tracking the surface region in memory, which may be compressed for certain formats. In
 | 
			
		||||
     * this scenario, `height` is actually the compressed height.
 | 
			
		||||
     */
 | 
			
		||||
    u32 GetActualHeight() const {
 | 
			
		||||
        return height * GetCompresssionFactor();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u32 GetScaledWidth() const {
 | 
			
		||||
        return width * res_scale;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user