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 <GL/glew.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
218  GLuint GenericVBOs[N_GENERIC_VBOS];
219  unsigned int GenericVBOSizes[N_GENERIC_VBOS];
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 
230 public:
231  // Create a new (unique) VAO ID. A VAO ID is a number that identifies
232  // a certain VAO across all OpenGL contexts. This indirection is needed
233  // because, unlike most other GL state, VAOs are not shared between
234  // OpenGL contexts.
235  unsigned int GenVAOID();
236 
237  // Free the given VAO ID, i.e. it can be re-used for new VAOs. This causes
238  // the VAO associated with this ID to be deleted in all OpenGL contexts.
239  void FreeVAOID(unsigned int vaoid);
240 
241  // Return a VAO with the given vao ID in the "vao" output variable.
242  // If the function returns false, the VAO was newly created, otherwise
243  // an existing VAO is returned.
244  bool GetVAO(unsigned int vaoid, GLuint& vao);
245 
246  // General
247  void Clear() override;
248  void Default() override ;
249  bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes) override; // reinit clipper for new resolution
250  // Clipper
251  bool UpdateClipper() override; // set current clipper to render target
252  const StdProjectionMatrix& GetProjectionMatrix() const { return ProjectionMatrix; }
253  bool PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat) override;
254  // Surface
255  bool PrepareRendering(C4Surface * sfcToSurface) override; // check if/make rendering possible to given surface
256  bool PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices) override;
257  bool EnsureMainContextSelected() override;
258 
259  CStdGLCtx *CreateContext(C4Window * pWindow, C4AbstractApp *pApp) override;
260  // Blit
261  void SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix* out_modelview);
262  void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform) override;
263  void FillBG(DWORD dwClr=0) override;
264  // Drawing
265  void PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, C4ShaderCall* shader_call) override;
266  void PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, float width, C4ShaderCall* shader_call) override;
267  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;
268  void PerformMultiBlt(C4Surface* sfcTarget, DrawOperation op, const C4BltVertex* vertices, unsigned int n_vertices, bool has_tex, C4ShaderCall* shader_call);
269  // device objects
270  bool RestoreDeviceObjects() override; // restore device dependent objects
271  bool InvalidateDeviceObjects() override; // free device dependent objects
272  bool DeviceReady() override { return !!pMainCtx; }
273  bool InitShaders(C4GroupSet* pGroups); // load shaders from given group
274  C4Shader* GetSpriteShader(int ssc);
275  C4Shader* GetSpriteShader(bool haveBase, bool haveOverlay, bool haveNormal);
276 
277  struct
278  {
279  bool LowMaxVertexUniformCount;
280  bool ForceSoftwareTransform;
281  } Workarounds;
282  void ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char * label);
283 
284 protected:
285  bool CheckGLError(const char *szAtOp);
286  const char* GLErrorString(GLenum code);
287  bool Error(const char *szMsg) override;
288 
289  friend class C4Surface;
290  friend class C4TexRef;
291  friend class C4Pattern;
292  friend class CStdGLCtx;
293  friend class C4StartupOptionsDlg;
294  friend class C4FullScreen;
295  friend class C4Window;
296  friend class C4ShaderCall;
297  friend class C4FoWRegion;
298 #ifdef WITH_QT_EDITOR
299  friend class CStdGLCtxQt;
300 #endif
301 };
302 
303 // Global access pointer
304 extern CStdGL *pGL;
305 
306 #endif // INC_StdGL
C4Shader SpriteShaderLightBaseNormalOverlay
Definition: C4DrawGL.h:206
static std::list< CStdGLCtx * > contexts
Definition: C4DrawGL.h:136
CStdGLCtx * pCurrCtx
Definition: C4DrawGL.h:180
C4Shader SpriteShaderBase
Definition: C4DrawGL.h:193
std::set< unsigned int >::iterator NextVAOID
Definition: C4DrawGL.h:228
C4Shader SpriteShaderLightBaseNormalMod2
Definition: C4DrawGL.h:205
C4SS_Attributes
Definition: C4DrawGL.h:87
bool DeviceReady() override
Definition: C4DrawGL.h:272
C4Shader SpriteShaderBaseOverlay
Definition: C4DrawGL.h:195
~C4DrawGLError() override=default
std::vector< unsigned int > VAOsToBeDeleted
Definition: C4DrawGL.h:142
C4Shader SpriteShaderLightBaseOverlay
Definition: C4DrawGL.h:202
const char * what() const override
Definition: C4DrawGL.h:43
C4Shader SpriteShaderLightBaseMod2
Definition: C4DrawGL.h:201
C4Shader SpriteShaderBaseMod2
Definition: C4DrawGL.h:194
GLenum sfcFmt
Definition: C4DrawGL.h:178
C4Shader SpriteShaderBaseOverlayMod2
Definition: C4DrawGL.h:196
int iPixelFormat
Definition: C4DrawGL.h:176
std::list< CStdGLCtx * >::iterator this_context
Definition: C4DrawGL.h:137
C4Shader SpriteShaderLightBaseNormalOverlayMod2
Definition: C4DrawGL.h:207
virtual ~CStdGLCtx()
Definition: C4DrawGL.h:111
C4Shader SpriteShader
Definition: C4DrawGL.h:191
GLuint lines_tex
Definition: C4DrawGL.h:182
C4Shader SpriteShaderMod2
Definition: C4DrawGL.h:192
const char * getData() const
Definition: StdBuf.h:442
C4Shader SpriteShaderLightBaseOverlayMod2
Definition: C4DrawGL.h:203
C4Shader SpriteShaderLightBaseNormal
Definition: C4DrawGL.h:204
const StdProjectionMatrix & GetProjectionMatrix() const
Definition: C4DrawGL.h:252
C4DrawGLError(const StdStrBuf &buf)
Definition: C4DrawGL.h:40
std::set< unsigned int > VAOIDs
Definition: C4DrawGL.h:227
C4Shader SpriteShaderLight
Definition: C4DrawGL.h:198
C4Shader SpriteShaderLightBase
Definition: C4DrawGL.h:200
Definition: C4Draw.h:84
uint32_t DWORD
StdProjectionMatrix ProjectionMatrix
Definition: C4DrawGL.h:185
DrawOperation
Definition: C4Draw.h:87
C4SS_Uniforms
Definition: C4DrawGL.h:50
std::vector< GLuint > hVAOs
Definition: C4DrawGL.h:140
CStdGL * pGL
Definition: C4DrawGL.cpp:918
C4Shader SpriteShaderLightMod2
Definition: C4DrawGL.h:199