summaryrefslogtreecommitdiff
path: root/src/video/opengl.h
blob: d910ca3bf42d76cecef049741518ecdbaacd5ecb (plain)
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
/* $Id$ */

/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file opengl.h OpenGL video driver support. */

#ifndef VIDEO_OPENGL_H
#define VIDEO_OPENGL_H

#include "../core/alloc_type.hpp"
#include "../core/geometry_type.hpp"
#include "../gfx_type.h"
#include "../spriteloader/spriteloader.hpp"
#include "../misc/lrucache.hpp"

typedef void (*OGLProc)();
typedef OGLProc (*GetOGLProcAddressProc)(const char *proc);

bool IsOpenGLVersionAtLeast(byte major, byte minor);
const char *FindStringInExtensionList(const char *string, const char *substring);

class OpenGLSprite;

/** Platform-independent back-end class for OpenGL video drivers. */
class OpenGLBackend : public ZeroedMemoryAllocator, SpriteEncoder {
private:
	static OpenGLBackend *instance; ///< Singleton instance pointer.

	bool persistent_mapping_supported; ///< Persistent pixel buffer mapping supported.
	GLsync sync_vid_mapping;           ///< Sync object for the persistently mapped video buffer.
	GLsync sync_anim_mapping;          ///< Sync object for the persistently mapped animation buffer.

	void *vid_buffer;   ///< Pointer to the mapped video buffer.
	GLuint vid_pbo;     ///< Pixel buffer object storing the memory used for the video driver to draw to.
	GLuint vid_texture; ///< Texture handle for the video buffer texture.
	GLuint vid_program; ///< Shader program for rendering a RGBA video buffer.
	GLuint pal_program; ///< Shader program for rendering a paletted video buffer.
	GLuint vao_quad;    ///< Vertex array object storing the rendering state for the fullscreen quad.
	GLuint vbo_quad;    ///< Vertex buffer with a fullscreen quad.
	GLuint pal_texture; ///< Palette lookup texture.

	void *anim_buffer;   ///< Pointer to the mapped animation buffer.
	GLuint anim_pbo;     ///< Pixel buffer object storing the memory used for the animation buffer.
	GLuint anim_texture; ///< Texture handle for the animation buffer texture.

	GLuint remap_program;    ///< Shader program for blending and rendering a RGBA + remap texture.
	GLint  remap_sprite_loc; ///< Uniform location for sprite parameters.
	GLint  remap_screen_loc; ///< Uniform location for screen size;
	GLint  remap_zoom_loc;   ///< Uniform location for sprite zoom;
	GLint  remap_rgb_loc;    ///< Uniform location for RGB mode flag;

	LRUCache<SpriteID, Sprite> cursor_cache; ///< Cache of encoded cursor sprites.

	OpenGLBackend();
	~OpenGLBackend();

	const char *Init();
	bool InitShaders();

	void RenderOglSprite(OpenGLSprite *gl_sprite, uint x, uint y, ZoomLevel zoom);

public:
	/** Get singleton instance of this class. */
	static inline OpenGLBackend *Get()
	{
		return OpenGLBackend::instance;
	}
	static const char *Create(GetOGLProcAddressProc get_proc);
	static void Destroy();

	void UpdatePalette(const Colour *pal, uint first, uint length);
	bool Resize(int w, int h, bool force = false);
	void Paint();

	void DrawMouseCursor();
	void ClearCursorCache();

	void *GetVideoBuffer();
	uint8 *GetAnimBuffer();
	void ReleaseVideoBuffer(const Rect &update_rect);
	void ReleaseAnimBuffer(const Rect &update_rect);

	/* SpriteEncoder */

	bool Is32BppSupported() override { return true; }
	uint GetSpriteAlignment() override { return 1u << (ZOOM_LVL_COUNT - 1); }
	Sprite *Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) override;
};


/** Class that encapsulates a RGBA texture together with a paletted remap texture. */
class OpenGLSprite {
private:
	/** Enum of all used OpenGL texture objects. */
	enum Texture {
		TEX_RGBA,    ///< RGBA texture part.
		TEX_REMAP,   ///< Remap texture part.
		NUM_TEX
	};

	Dimension dim;
	GLuint tex[NUM_TEX]; ///< The texture objects.

	static GLuint dummy_tex[NUM_TEX]; ///< 1x1 dummy textures to substitute for unused sprite components.

	static bool Create();
	static void Destroy();

	bool BindTextures();

public:
	OpenGLSprite(uint width, uint height, uint levels, SpriteColourComponent components);
	~OpenGLSprite();

	void Update(uint width, uint height, uint level, const SpriteLoader::CommonPixel *data);
	Dimension GetSize(ZoomLevel level) const;

	friend class OpenGLBackend;
};

#endif /* VIDEO_OPENGL_H */