1 #pragma once
2 
3 #include <solarus/graphics/Renderer.h>
4 #include <solarus/graphics/glrenderer/GlShader.h>
5 #include <solarus/graphics/VertexArray.h>
6 
7 namespace Solarus {
8 
9 class GlShader;
10 class GlTexture;
11 
12 /**
13  * @brief Opengl Renderer
14  *
15  * This renderer implements batch rendering. This minimize the state changes in
16  * the opengl driver. Sprites are accumulated in a buffer before being rendered
17  * all at once.
18  */
19 class GlRenderer : public Renderer {
20   friend class GlTexture;
21   friend class GlShader;
22 
23 public:
24   typedef void (APIENTRY *DEBUGPROC)(GLenum source,
25               GLenum type,
26               GLuint id,
27               GLenum severity,
28               GLsizei length,
29               const GLchar *message,
30               const void *userParam);
31 
32   /**
33    * @brief Draw destination
34    */
35   struct Fbo{
36     GLuint id;
37     glm::mat4 view;
38   };
39 
40   GlRenderer(SDL_GLContext ctx);
41   static RendererPtr create(SDL_Window* window, bool force_software);
42   SurfaceImplPtr create_texture(int width, int height) override;
43   SurfaceImplPtr create_texture(SDL_Surface_UniquePtr &&surface) override;
44   SurfaceImplPtr create_window_surface(SDL_Window* w, int width, int height) override;
45   ShaderPtr create_shader(const std::string& shader_id) override;
46   ShaderPtr create_shader(const std::string& vertex_source, const std::string& fragment_source, double scaling_factor) override;
47   //void set_render_target(SurfaceImpl& texture) override;
48   void set_render_target(GlTexture* target);
49   void bind_as_gl_target(SurfaceImpl &surf) override;
50   void bind_as_gl_texture(const SurfaceImpl& surf) override;
51   void draw(SurfaceImpl& dst, const SurfaceImpl& src, const DrawInfos& infos) override;
52   void clear(SurfaceImpl& dst) override;
53   void fill(SurfaceImpl& dst, const Color& color, const Rectangle& where, BlendMode mode = BlendMode::BLEND) override;
54   void invalidate(const SurfaceImpl& surf) override;
55   std::string get_name() const override;
56   void present(SDL_Window* window) override;
57   void on_window_size_changed(const Rectangle& viewport) override;
get()58   static GlRenderer& get(){
59     return *instance;
60   }
61 
62   const DrawProxy& default_terminal() const override;
63   ~GlRenderer() override;
64 private:
65   static constexpr const char* VCOLOR_ONLY_NAME = "sol_vcolor_only";
66   void draw(SurfaceImpl& dst, const SurfaceImpl& src, const DrawInfos& infos, GlShader& shader);
67 
68   /**
69    * Blend mode aggregate
70    */
71   using GLBlendMode = std::tuple<GLenum,GLenum,GLenum,GLenum,bool>;
72 
73 
74   bool use_vao() const;
75 
76   void read_pixels(GlTexture* from, void* to);
77   void put_pixels(GlTexture* to, void* data);
78 
79   void restart_batch();
80   void set_shader(GlShader* shader);
81   void set_texture(const GlTexture* texture);
82   void set_state(const GlTexture* src, GlShader* shad, GlTexture* dst, const GLBlendMode& mode, bool force = false);
83   void rebind_texture();
84   void rebind_shader();
85   void set_blend_mode(GLBlendMode mode);
86   GLBlendMode make_gl_blend_modes(const GlTexture &dst, const GlTexture *src, BlendMode mode);
87   GLBlendMode make_gl_blend_modes(BlendMode mode);
88   void create_vbo(size_t num_sprites);
89   void add_sprite(const DrawInfos& infos);
90   size_t buffered_indices() const;
91   size_t buffered_vertices() const;
92   Fbo* get_fbo(int width, int height, bool screen = false);
93 
94   void shader_about_to_change(GlShader* shader);
95 
96   static GlRenderer* instance;
97   SDL_GLContext sdl_gl_context;
98   GlShader* current_shader = nullptr;
99   const GlTexture* current_texture = nullptr;
100   GlTexture* current_target = nullptr;
101   GLBlendMode current_blend_mode =
102     GLBlendMode{GL_ONE,GL_ONE,GL_ONE,GL_ONE,false};
103   ShaderPtr main_shader;
104 
105   GLuint vao = 0;
106   GLuint vbo = 0;
107   GLuint ibo = 0;
108 
109   const GlTexture* test_texture = nullptr;
110 
111   Vertex* current_vertex = nullptr;
112   size_t buffered_sprites = 0;
113   size_t buffer_size = 0;
114 
115   std::vector<Vertex> vertex_buffer;
116 
117   Fbo screen_fbo = {0,glm::mat4(1.f)};
118   std::unordered_map<uint_fast64_t,Fbo> fbos;
119   Rectangle window_viewport;
120 
121   bool is_es_context;
122 };
123 }
124