summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_texture_cache.h
blob: b165187d998a1813d4d0406df6d999ed41fba5e0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <array>
#include <functional>
#include <utility>
#include <vector>

#include <glad/glad.h>

#include "common/common_types.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/texture_cache/texture_cache_contextless.h"

namespace OpenGL {

using VideoCommon::SurfaceParams;
using VideoCommon::ViewKey;
using VideoCore::Surface::ComponentType;
using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::SurfaceTarget;
using VideoCore::Surface::SurfaceType;

class CachedSurfaceView;
class CachedSurface;
class TextureCacheOpenGL;

using Surface = std::shared_ptr<CachedSurface>;
using TextureCacheBase = VideoCommon::TextureCacheContextless<CachedSurface, CachedSurfaceView>;

class CachedSurface final
    : public VideoCommon::SurfaceBaseContextless<TextureCacheOpenGL, CachedSurfaceView> {
    friend CachedSurfaceView;

public:
    explicit CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params);
    ~CachedSurface();

    GLenum GetTarget() const {
        return target;
    }

    GLuint GetTexture() const {
        return texture.handle;
    }

protected:
    void DecorateSurfaceName();

    std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key);

    void UploadTextureImpl();
    void DownloadTextureImpl();

private:
    void UploadTextureMipmap(u32 level);

    GLenum internal_format{};
    GLenum format{};
    GLenum type{};
    bool is_compressed{};
    GLenum target{};

    OGLTexture texture;
};

class CachedSurfaceView final {
public:
    explicit CachedSurfaceView(CachedSurface& surface, ViewKey key);
    ~CachedSurfaceView();

    /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
    void Attach(GLenum attachment) const;

    GLuint GetTexture(Tegra::Shader::TextureType texture_type, bool is_array,
                      Tegra::Texture::SwizzleSource x_source,
                      Tegra::Texture::SwizzleSource y_source,
                      Tegra::Texture::SwizzleSource z_source,
                      Tegra::Texture::SwizzleSource w_source);

    void MarkAsModified(bool is_modified) {
        surface.MarkAsModified(is_modified);
    }

    const SurfaceParams& GetSurfaceParams() const {
        return params;
    }

    u32 GetWidth() const {
        return params.GetMipWidth(GetBaseLevel());
    }

    u32 GetHeight() const {
        return params.GetMipHeight(GetBaseLevel());
    }

    u32 GetDepth() const {
        return params.GetMipDepth(GetBaseLevel());
    }

    u32 GetBaseLayer() const {
        return key.base_layer;
    }

    u32 GetNumLayers() const {
        return key.num_layers;
    }

    u32 GetBaseLevel() const {
        return key.base_level;
    }

    u32 GetNumLevels() const {
        return key.num_levels;
    }

private:
    struct TextureView {
        OGLTexture texture;
        std::array<Tegra::Texture::SwizzleSource, 4> swizzle{
            Tegra::Texture::SwizzleSource::R, Tegra::Texture::SwizzleSource::G,
            Tegra::Texture::SwizzleSource::B, Tegra::Texture::SwizzleSource::A};
    };

    void ApplySwizzle(TextureView& texture_view, Tegra::Texture::SwizzleSource x_source,
                      Tegra::Texture::SwizzleSource y_source,
                      Tegra::Texture::SwizzleSource z_source,
                      Tegra::Texture::SwizzleSource w_source);

    TextureView CreateTextureView(GLenum target) const;

    std::pair<std::reference_wrapper<TextureView>, GLenum> GetTextureView(
        Tegra::Shader::TextureType texture_type, bool is_array);

    CachedSurface& surface;
    const ViewKey key;
    const SurfaceParams params;

    TextureView texture_view_1d;
    TextureView texture_view_1d_array;
    TextureView texture_view_2d;
    TextureView texture_view_2d_array;
    TextureView texture_view_3d;
    TextureView texture_view_cube;
    TextureView texture_view_cube_array;
};

class TextureCacheOpenGL final : public TextureCacheBase {
public:
    explicit TextureCacheOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer);
    ~TextureCacheOpenGL();

protected:
    CachedSurfaceView* TryFastGetSurfaceView(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
                                             const SurfaceParams& new_params,
                                             bool preserve_contents,
                                             const std::vector<Surface>& overlaps);

    Surface CreateSurface(const SurfaceParams& params);

private:
    CachedSurfaceView* SurfaceCopy(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
                                   const SurfaceParams& new_params, const Surface& old_surface,
                                   const SurfaceParams& old_params);

    CachedSurfaceView* TryCopyAsViews(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
                                      const SurfaceParams& new_params,
                                      const std::vector<Surface>& overlaps);
};

} // namespace OpenGL