OpenClonk
C4DrawGL.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2010-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 /* OpenGL implementation of NewGfx */
18 
20 #if !defined(INC_StdGL) && !defined(USE_CONSOLE)
21 #define INC_StdGL
22 
23 #ifdef _WIN32
25 #endif
26 
27 #include <epoxy/gl.h>
28 
29 #ifdef USE_COCOA
31 #endif
32 #include "graphics/C4Draw.h"
33 #include "graphics/C4Shader.h"
34 
35 class C4Window;
36 
37 class C4DrawGLError: public std::exception
38 {
39 public:
40  C4DrawGLError(const StdStrBuf& buf): Buf(buf) {}
41  ~C4DrawGLError() throw() override = default;
42 
43  const char* what() const throw() override { return Buf.getData(); }
44 
45 private:
46  StdCopyStrBuf Buf;
47 };
48 
49 // Uniform data we give the sprite shader (constants from its viewpoint)
51 {
54  C4SSU_NormalMatrix, // 3x3, transpose-inverse of modelview matrix
55 
56  C4SSU_ClrMod, // always
57  C4SSU_Gamma, // always
58  C4SSU_Resolution, // always
59 
60  C4SSU_BaseTex, // C4SSC_BASE
61  C4SSU_OverlayTex, // C4SSC_OVERLAY
62  C4SSU_OverlayClr, // C4SSC_OVERLAY
63 
64  C4SSU_LightTex, // C4SSC_LIGHT
65  C4SSU_LightTransform, // C4SSC_LIGHT
66  C4SSU_NormalTex, // C4SSC_LIGHT | C4SSC_NORMAL
67 
68  C4SSU_AmbientTex, // C4SSC_LIGHT
69  C4SSU_AmbientTransform, // C4SSC_LIGHT
70  C4SSU_AmbientBrightness, // C4SSC_LIGHT
71 
72  C4SSU_MaterialAmbient, // for meshes
73  C4SSU_MaterialDiffuse, // for meshes
74  C4SSU_MaterialSpecular, // for meshes
75  C4SSU_MaterialEmission, // for meshes
76  C4SSU_MaterialShininess, // for meshes
77 
78  C4SSU_Bones, // for meshes
79  C4SSU_CullMode, // for meshes
80 
81  C4SSU_FrameCounter, // for custom shaders
82 
84 };
85 
86 // Attribute data for sprites and meshes
88 {
89  C4SSA_Position, // 2d for sprites, 3d for meshes
90  C4SSA_Normal, // meshes only
92  C4SSA_Color, // sprites only, 4d
93 
96 
99 
101 };
102 
103 // one OpenGL context
105 #ifdef USE_COCOA
106  : public ObjectiveCAssociated
107 #endif
108 {
109 public:
110  CStdGLCtx(); // ctor
111  virtual ~CStdGLCtx() { Clear(); } // dtor
112 
113  virtual void Clear(bool multisample_change = false); // clear objects
114 
115 #ifdef USE_WGL
116  std::vector<int> EnumerateMultiSamples() const;
117 #endif
118  virtual bool Init(C4Window * pWindow, C4AbstractApp *pApp);
119 
120  virtual bool Select(bool verbose = false); // select this context
121  virtual void Deselect(); // select this context
122 
123  virtual bool PageFlip(); // present scene
124 
125 protected:
126  void SelectCommon();
127  // this handles are declared as pointers to structs
128  C4Window * pWindow{nullptr}; // window to draw in
129 #ifdef USE_WGL
130  HDC hDC{nullptr}; // device context handle
131 #elif defined(USE_SDL_MAINLOOP)
132  void * ctx;
133 #endif
134 
135  // Global list of all OpenGL contexts in use
136  static std::list<CStdGLCtx*> contexts;
137  std::list<CStdGLCtx*>::iterator this_context;
138 
139  // VAOs available on this context
140  std::vector<GLuint> hVAOs;
141  // VAOs to be deleted the next time this context is being made current.
142  std::vector<unsigned int> VAOsToBeDeleted;
143 
144  friend class CStdGL;
145  friend class C4Surface;
146 };
147 
148 #ifdef WITH_QT_EDITOR
149 // OpenGL context with Qt as backend. Implemented as subclass to allow co-existance with a different backend for fullscreen.
150 class CStdGLCtxQt : public CStdGLCtx
151 {
152 public:
153  CStdGLCtxQt();
154  ~CStdGLCtxQt() override { Clear(); }
155 
156  void Clear(bool multisample_change = false) override; // clear objects
157  bool Init(C4Window * pWindow, C4AbstractApp *pApp) override;
158  bool Select(bool verbose = false) override; // select this context
159  void Deselect() override; // select this context
160  bool PageFlip() override; // present scene
161 
162 private:
163  class QOpenGLContext *context = nullptr;
164  class QOffscreenSurface *surface = nullptr;
165 };
166 #endif
167 
168 // OpenGL encapsulation
169 class CStdGL : public C4Draw
170 {
171 public:
172  CStdGL();
173  ~CStdGL() override;
174 protected:
175 
176  int iPixelFormat; // used pixel format
177 
178  GLenum sfcFmt; // texture surface format
179  CStdGLCtx * pMainCtx{nullptr}; // main GL context
180  CStdGLCtx *pCurrCtx; // current context (owned if fullscreen)
181  // texture for smooth lines
182  GLuint lines_tex;
183 
184  // The orthographic projection matrix
186 
187  // programs for drawing points, lines, quads
188 
189  // Sprite shaders -- there is a variety of shaders to avoid
190  // conditionals in the GLSL code.
197 
208 
209  // Generic VBOs for rendering arbitrary points, lines and
210  // triangles, used by PerformMultiBlt. Use more than one VBO, so that
211  // two PerformMultiBlt calls in quick succession can use two different
212  // buffers. Otherwise, the second call would need to wait until the
213  // rendering pipeline has actually drained the buffer. Each buffer
214  // starts with a fixed size. If more than this many vertices need to
215  // be rendered (can happen e.g. for PXS), then the buffer is resized.
216  static const unsigned int N_GENERIC_VBOS = 16;
217  static const unsigned int GENERIC_VBO_SIZE = 3 * 64; // vertices
220  unsigned int CurrentVBO{0};
221  // We need twice as much VAOs, since the sprite rendering routines work
222  // both with and without textures (in which case we either need texture
223  // coordinates or not).
224  unsigned int GenericVAOs[N_GENERIC_VBOS * 2];
225 
226  // VAO IDs currently in use.
227  std::set<unsigned int> VAOIDs;
228  std::set<unsigned int>::iterator NextVAOID;
229 
231 
232 public:
233  // Create a new (unique) VAO ID. A VAO ID is a number that identifies
234  // a certain VAO across all OpenGL contexts. This indirection is needed
235  // because, unlike most other GL state, VAOs are not shared between
236  // OpenGL contexts.
237  unsigned int GenVAOID();
238 
239  // Free the given VAO ID, i.e. it can be re-used for new VAOs. This causes
240  // the VAO associated with this ID to be deleted in all OpenGL contexts.
241  void FreeVAOID(unsigned int vaoid);
242 
243  // Return a VAO with the given vao ID in the "vao" output variable.
244  // If the function returns false, the VAO was newly created, otherwise
245  // an existing VAO is returned.
246  bool GetVAO(unsigned int vaoid, GLuint& vao);
247 
248  // General
249  void Clear() override;
250  void Default() override ;
251  bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes) override; // reinit clipper for new resolution
252  // Clipper
253  bool UpdateClipper() override; // set current clipper to render target
255  bool PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat) override;
256  // Surface
257  bool PrepareRendering(C4Surface * sfcToSurface) override; // check if/make rendering possible to given surface
258  bool PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices) override;
259  bool EnsureMainContextSelected() override;
260 
261  CStdGLCtx *CreateContext(C4Window * pWindow, C4AbstractApp *pApp) override;
262  // Blit
263  void SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix* out_modelview);
264  void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform) override;
265  void FillBG(DWORD dwClr=0) override;
266  // Drawing
267  void PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, C4ShaderCall* shader_call) override;
268  void PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, float width, C4ShaderCall* shader_call) override;
269  void PerformMultiTris(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, const C4BltTransform* pTransform, C4TexRef* pTex, C4TexRef* pOverlay, C4TexRef* pNormal, DWORD dwOverlayClrMod, C4ShaderCall* shader_call) override;
270  void PerformMultiBlt(C4Surface* sfcTarget, DrawOperation op, const C4BltVertex* vertices, unsigned int n_vertices, bool has_tex, C4ShaderCall* shader_call);
271  // device objects
272  bool RestoreDeviceObjects() override; // restore device dependent objects
273  bool InvalidateDeviceObjects() override; // free device dependent objects
274  bool DeviceReady() override { return !!pMainCtx; }
275  bool InitShaders(C4GroupSet* pGroups); // load shaders from given group
276  C4Shader* GetSpriteShader(int ssc);
277  C4Shader* GetSpriteShader(bool haveBase, bool haveOverlay, bool haveNormal);
278 
279  struct
280  {
281  bool LowMaxVertexUniformCount;
282  bool ForceSoftwareTransform;
284  void ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char * label);
285 
286 protected:
287  bool CheckGLError(const char *szAtOp);
288  const char* GLErrorString(GLenum code);
289  bool Error(const char *szMsg) override;
290 
291  friend class C4Surface;
292  friend class C4TexRef;
293  friend class C4Pattern;
294  friend class CStdGLCtx;
295  friend class C4StartupOptionsDlg;
296  friend class C4FullScreen;
297  friend class C4Window;
298  friend class C4ShaderCall;
299  friend class C4FoWRegion;
300 #ifdef WITH_QT_EDITOR
301  friend class CStdGLCtxQt;
302 #endif
303 };
304 
305 // Global access pointer
306 extern CStdGL *pGL;
307 
308 #endif // INC_StdGL
C4SS_Attributes
Definition: C4DrawGL.h:88
@ C4SSA_TexCoord
Definition: C4DrawGL.h:91
@ C4SSA_BoneIndices0
Definition: C4DrawGL.h:94
@ C4SSA_Normal
Definition: C4DrawGL.h:90
@ C4SSA_Count
Definition: C4DrawGL.h:100
@ C4SSA_BoneIndices1
Definition: C4DrawGL.h:95
@ C4SSA_Color
Definition: C4DrawGL.h:92
@ C4SSA_BoneWeights1
Definition: C4DrawGL.h:98
@ C4SSA_BoneWeights0
Definition: C4DrawGL.h:97
@ C4SSA_Position
Definition: C4DrawGL.h:89
CStdGL * pGL
Definition: C4DrawGL.cpp:907
C4SS_Uniforms
Definition: C4DrawGL.h:51
@ C4SSU_MaterialEmission
Definition: C4DrawGL.h:75
@ C4SSU_LightTransform
Definition: C4DrawGL.h:65
@ C4SSU_FrameCounter
Definition: C4DrawGL.h:81
@ C4SSU_NormalMatrix
Definition: C4DrawGL.h:54
@ C4SSU_NormalTex
Definition: C4DrawGL.h:66
@ C4SSU_OverlayClr
Definition: C4DrawGL.h:62
@ C4SSU_AmbientTex
Definition: C4DrawGL.h:68
@ C4SSU_ModelViewMatrix
Definition: C4DrawGL.h:53
@ C4SSU_BaseTex
Definition: C4DrawGL.h:60
@ C4SSU_LightTex
Definition: C4DrawGL.h:64
@ C4SSU_Resolution
Definition: C4DrawGL.h:58
@ C4SSU_MaterialAmbient
Definition: C4DrawGL.h:72
@ C4SSU_AmbientBrightness
Definition: C4DrawGL.h:70
@ C4SSU_Count
Definition: C4DrawGL.h:83
@ C4SSU_OverlayTex
Definition: C4DrawGL.h:61
@ C4SSU_ClrMod
Definition: C4DrawGL.h:56
@ C4SSU_MaterialDiffuse
Definition: C4DrawGL.h:73
@ C4SSU_AmbientTransform
Definition: C4DrawGL.h:69
@ C4SSU_ProjectionMatrix
Definition: C4DrawGL.h:52
@ C4SSU_Bones
Definition: C4DrawGL.h:78
@ C4SSU_MaterialSpecular
Definition: C4DrawGL.h:74
@ C4SSU_MaterialShininess
Definition: C4DrawGL.h:76
@ C4SSU_CullMode
Definition: C4DrawGL.h:79
@ C4SSU_Gamma
Definition: C4DrawGL.h:57
uint32_t DWORD
C4DrawGLError(const StdStrBuf &buf)
Definition: C4DrawGL.h:40
const char * what() const override
Definition: C4DrawGL.h:43
~C4DrawGLError() override=default
Definition: C4Draw.h:85
DrawOperation
Definition: C4Draw.h:87
C4AbstractApp * pApp
Definition: C4Draw.h:95
void SelectCommon()
Definition: C4DrawGLCtx.cpp:35
std::vector< unsigned int > VAOsToBeDeleted
Definition: C4DrawGL.h:142
virtual bool Init(C4Window *pWindow, C4AbstractApp *pApp)
virtual bool Select(bool verbose=false)
virtual void Clear(bool multisample_change=false)
std::vector< GLuint > hVAOs
Definition: C4DrawGL.h:140
virtual bool PageFlip()
static std::list< CStdGLCtx * > contexts
Definition: C4DrawGL.h:136
std::list< CStdGLCtx * >::iterator this_context
Definition: C4DrawGL.h:137
virtual ~CStdGLCtx()
Definition: C4DrawGL.h:111
virtual void Deselect()
C4Window * pWindow
Definition: C4DrawGL.h:128
std::set< unsigned int > VAOIDs
Definition: C4DrawGL.h:227
C4Shader SpriteShaderLightBaseNormalMod2
Definition: C4DrawGL.h:205
void SetupMultiBlt(C4ShaderCall &call, const C4BltTransform *pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix *out_modelview)
Definition: C4DrawGL.cpp:356
void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform *pTransform) override
unsigned int GenericVBOSizes[N_GENERIC_VBOS]
Definition: C4DrawGL.h:219
StdProjectionMatrix ProjectionMatrix
Definition: C4DrawGL.h:185
bool has_khr_debug
Definition: C4DrawGL.h:230
bool EnsureMainContextSelected() override
Definition: C4DrawGL.cpp:757
C4Shader SpriteShaderLightBase
Definition: C4DrawGL.h:200
C4Shader SpriteShaderBaseOverlayMod2
Definition: C4DrawGL.h:196
void PerformMultiBlt(C4Surface *sfcTarget, DrawOperation op, const C4BltVertex *vertices, unsigned int n_vertices, bool has_tex, C4ShaderCall *shader_call)
Definition: C4DrawGL.cpp:593
C4Shader SpriteShaderBaseOverlay
Definition: C4DrawGL.h:195
C4Shader SpriteShaderLightMod2
Definition: C4DrawGL.h:199
CStdGLCtx * pCurrCtx
Definition: C4DrawGL.h:180
void ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char *label)
Definition: C4DrawGL.cpp:267
bool InvalidateDeviceObjects() override
Definition: C4DrawGL.cpp:808
unsigned int CurrentVBO
Definition: C4DrawGL.h:220
C4Shader SpriteShaderBaseMod2
Definition: C4DrawGL.h:194
unsigned int GenericVAOs[N_GENERIC_VBOS *2]
Definition: C4DrawGL.h:224
C4Shader SpriteShaderMod2
Definition: C4DrawGL.h:192
const StdProjectionMatrix & GetProjectionMatrix() const
Definition: C4DrawGL.h:254
~CStdGL() override
Definition: C4DrawGL.cpp:100
bool InitShaders(C4GroupSet *pGroups)
Definition: C4DrawGL.cpp:714
C4Shader SpriteShaderLightBaseNormal
Definition: C4DrawGL.h:204
const char * GLErrorString(GLenum code)
Definition: C4DrawGL.cpp:882
bool PrepareRendering(C4Surface *sfcToSurface) override
Definition: C4DrawGL.cpp:161
C4Shader SpriteShader
Definition: C4DrawGL.h:191
bool PrepareSpriteShader(C4Shader &shader, const char *name, int ssc, C4GroupSet *pGroups, const char *const *additionalDefines, const char *const *additionalSlices) override
Definition: C4DrawGL.cpp:190
GLuint GenericVBOs[N_GENERIC_VBOS]
Definition: C4DrawGL.h:218
bool PrepareMaterial(StdMeshMatManager &mat_manager, StdMeshMaterialLoader &loader, StdMeshMaterial &mat) override
void Default() override
Definition: C4DrawGL.cpp:917
unsigned int GenVAOID()
Definition: C4DrawGL.cpp:927
bool CheckGLError(const char *szAtOp)
Definition: C4DrawGL.cpp:898
bool Error(const char *szMsg) override
Definition: C4DrawGL.cpp:855
static const unsigned int N_GENERIC_VBOS
Definition: C4DrawGL.h:216
void PerformMultiPix(C4Surface *sfcTarget, const C4BltVertex *vertices, unsigned int n_vertices, C4ShaderCall *shader_call) override
Definition: C4DrawGL.cpp:490
bool DeviceReady() override
Definition: C4DrawGL.h:274
C4Shader SpriteShaderLightBaseOverlay
Definition: C4DrawGL.h:202
void FillBG(DWORD dwClr=0) override
Definition: C4DrawGL.cpp:136
std::set< unsigned int >::iterator NextVAOID
Definition: C4DrawGL.h:228
C4Shader SpriteShaderLightBaseMod2
Definition: C4DrawGL.h:201
void FreeVAOID(unsigned int vaoid)
Definition: C4DrawGL.cpp:969
bool UpdateClipper() override
Definition: C4DrawGL.cpp:143
bool GetVAO(unsigned int vaoid, GLuint &vao)
Definition: C4DrawGL.cpp:1015
CStdGLCtx * pMainCtx
Definition: C4DrawGL.h:179
C4Shader SpriteShaderBase
Definition: C4DrawGL.h:193
bool RestoreDeviceObjects() override
Definition: C4DrawGL.cpp:762
GLuint lines_tex
Definition: C4DrawGL.h:182
CStdGL()
Definition: C4DrawGL.cpp:90
int iPixelFormat
Definition: C4DrawGL.h:176
bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes) override
Definition: C4DrawGL.cpp:909
C4Shader SpriteShaderLightBaseNormalOverlay
Definition: C4DrawGL.h:206
C4Shader SpriteShaderLight
Definition: C4DrawGL.h:198
CStdGLCtx * CreateContext(C4Window *pWindow, C4AbstractApp *pApp) override
Definition: C4DrawGL.cpp:273
C4Shader * GetSpriteShader(int ssc)
Definition: C4DrawGL.cpp:673
void Clear() override
Definition: C4DrawGL.cpp:106
GLenum sfcFmt
Definition: C4DrawGL.h:178
void PerformMultiTris(C4Surface *sfcTarget, const C4BltVertex *vertices, unsigned int n_vertices, const C4BltTransform *pTransform, C4TexRef *pTex, C4TexRef *pOverlay, C4TexRef *pNormal, DWORD dwOverlayClrMod, C4ShaderCall *shader_call) override
Definition: C4DrawGL.cpp:577
void PerformMultiLines(C4Surface *sfcTarget, const C4BltVertex *vertices, unsigned int n_vertices, float width, C4ShaderCall *shader_call) override
Definition: C4DrawGL.cpp:517
C4Shader SpriteShaderLightBaseOverlayMod2
Definition: C4DrawGL.h:203
static const unsigned int GENERIC_VBO_SIZE
Definition: C4DrawGL.h:217
C4Shader SpriteShaderLightBaseNormalOverlayMod2
Definition: C4DrawGL.h:207
struct CStdGL::@10 Workarounds
const char * getData() const
Definition: StdBuf.h:442