1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-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 /* A wrapper class to OpenGL and Direct3d */
18 
19 #ifndef INC_STDDDRAW2
20 #define INC_STDDDRAW2
21 
22 #include "lib/StdMeshMaterial.h"
23 #include "graphics/C4Surface.h"
24 #include "graphics/C4BltTransform.h"
25 
26 // Global Draw access pointer
27 extern C4Draw *pDraw;
28 
DwTo4UB(DWORD dwClr,unsigned char (& r)[4])29 inline void DwTo4UB(DWORD dwClr, unsigned char (&r)[4])
30 {
31 	r[0] = (unsigned char)( (dwClr >> 16) & 0xff);
32 	r[1] = (unsigned char)( (dwClr >>  8) & 0xff);
33 	r[2] = (unsigned char)( (dwClr      ) & 0xff);
34 	r[3] = (unsigned char)( (dwClr >> 24) & 0xff);
35 }
36 
37 // pattern
38 class C4Pattern
39 {
40 private:
41 	// pattern surface for new-style patterns
42 	class C4Surface *sfcPattern32;
43 	// Faster access
44 	uint32_t * CachedPattern; int Wdt; int Hgt;
45 	// pattern zoom factor; 0 means no zoom
46 	int Zoom;
47 public:
48 	C4Pattern& operator=(const C4Pattern&);
getSurface()49 	const C4Surface *getSurface() const { return sfcPattern32; }
50 	DWORD PatternClr(unsigned int iX, unsigned int iY) const; // apply pattern to color
51 	bool Set(class C4Surface *sfcSource, int iZoom=0); // set and enable pattern
SetZoom(int iZoom)52 	void SetZoom(int iZoom) { Zoom = iZoom; }
53 	void Clear();                     // clear pattern
54 	C4Pattern();         // ctor
~C4Pattern()55 	~C4Pattern() { Clear(); }          // dtor
56 };
57 
58 // blit position on screen
59 // This is the format required by GL_T2F_C4UB_V3F
60 struct C4BltVertex
61 {
62 	float tx, ty; // texture positions
63 	unsigned char color[4]; // color modulation
64 	float ftx,fty,ftz; // blit positions
65 };
66 
67 // helper struct
68 struct ZoomData
69 {
70 	float Zoom;
71 	float X, Y;
72 };
73 
74 class C4FoWRegion;
75 
76 // Shader combinations
77 static const int C4SSC_MOD2 = 1; // signed addition instead of multiplication for clrMod
78 static const int C4SSC_BASE = 2; // use a base texture instead of just a single color
79 static const int C4SSC_OVERLAY = 4; // use a colored overlay on top of base texture
80 static const int C4SSC_LIGHT = 8; // use dynamic+ambient lighting
81 static const int C4SSC_NORMAL = 16; // extract normals from normal map instead of (0,0,1)
82 
83 // direct draw encapsulation
84 class C4Draw
85 {
86 public:
87 	enum DrawOperation { OP_POINTS, OP_TRIANGLES };
88 
89 	static constexpr int COLOR_DEPTH = 32;
90 	static constexpr int COLOR_DEPTH_BYTES = COLOR_DEPTH / 8;
91 
92 	C4Draw() = default;
~C4Draw()93 	virtual ~C4Draw() { pDraw=nullptr; }
94 public:
95 	C4AbstractApp * pApp; // the application
96 	bool Active;                    // set if device is ready to render, etc.
97 	float gamma[C4MaxGammaRamps][3]; // input gammas
98 	float gammaOut[3]; // combined gamma
99 	int MaxTexSize{0};
100 	C4ScriptUniform scriptUniform; // uniforms added to all draw calls
101 protected:
102 	float fClipX1,fClipY1,fClipX2,fClipY2; // clipper in unzoomed coordinates
103 	float fStClipX1,fStClipY1,fStClipX2,fStClipY2; // stored clipper in unzoomed coordinates
104 	int32_t iClipX1,iClipY1,iClipX2,iClipY2; // clipper in pixel coordinates
105 	bool ClipAll; // set if clipper clips everything away
106 	bool PrimaryLocked;             // set if primary surface is locked (-> can't blit)
107 	C4Surface *RenderTarget;         // current render target
108 	bool BlitModulated;             // set if blits should be modulated with BlitModulateClr
109 	DWORD BlitModulateClr;          // modulation color for blitting
110 	DWORD dwBlitMode;               // extra flags for blit
111 	const C4FoWRegion* pFoW;     // new-style FoW
112 	float ZoomX; float ZoomY;
113 	const StdMeshMatrix* MeshTransform; // Transformation to apply to mesh before rendering
114 	bool fUsePerspective;
115 public:
116 	float Zoom;
117 	// General
118 	bool Init(C4AbstractApp * pApp, unsigned int iXRes, unsigned int iYRes, unsigned int iMonitor);
119 	virtual void Clear();
120 	virtual void Default();
CreateContext(C4Window *,C4AbstractApp *)121 	virtual CStdGLCtx *CreateContext(C4Window *, C4AbstractApp *) { return nullptr; }
122 	virtual bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes) = 0; // reinit clipper for new resolution
123 	// Clipper
124 	bool GetPrimaryClipper(int &rX1, int &rY1, int &rX2, int &rY2);
125 	bool SetPrimaryClipper(int iX1, int iY1, int iX2, int iY2);
126 	bool SubPrimaryClipper(int iX1, int iY1, int iX2, int iY2);
127 	C4Rect GetClipRect() const;
128 	C4Rect GetOutRect() const;
129 	bool StorePrimaryClipper();
130 	bool RestorePrimaryClipper();
131 	bool NoPrimaryClipper();
132 	bool ApplyPrimaryClipper(C4Surface * sfcSurface);
133 	bool DetachPrimaryClipper(C4Surface * sfcSurface);
134 	virtual bool UpdateClipper() = 0; // set current clipper to render target
135 	// Surface
136 	bool GetSurfaceSize(C4Surface * sfcSurface, int &iWdt, int &iHgt);
137 	void Grayscale(C4Surface * sfcSfc, int32_t iOffset = 0);
LockingPrimary()138 	void LockingPrimary() { PrimaryLocked=true; }
PrimaryUnlocked()139 	void PrimaryUnlocked() { PrimaryLocked=false; }
140 	virtual bool PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat) = 0; // Find best technique, fail if there is none
141 	virtual bool PrepareRendering(C4Surface * sfcToSurface) = 0; // check if/make rendering possible to given surface
142 	virtual bool EnsureMainContextSelected() = 0;
143 	virtual bool PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices) = 0; // create sprite shader
144 	// Blit
145 	virtual void BlitLandscape(C4Surface * sfcSource, float fx, float fy,
146 	                           C4Surface * sfcTarget, float tx, float ty, float wdt, float hgt);
147 	void Blit8Fast(CSurface8 * sfcSource, int fx, int fy,
148 	               C4Surface * sfcTarget, int tx, int ty, int wdt, int hgt);
149 	bool Blit(C4Surface * sfcSource, float fx, float fy, float fwdt, float fhgt,
150 	          C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt,
151 	          bool fSrcColKey=false, const C4BltTransform *pTransform=nullptr);
152 	bool BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt, float fhgt,
153 	                  C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt,
154 	                  bool fSrcColKey=false, const C4BltTransform *pTransform=nullptr);
155 	bool RenderMesh(StdMeshInstance &instance, C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform); // Call PrepareMaterial with Mesh's material before
156 	virtual void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform) = 0;
157 	bool Blit8(C4Surface * sfcSource, int fx, int fy, int fwdt, int fhgt, // force 8bit-blit (inline)
158 	           C4Surface * sfcTarget, int tx, int ty, int twdt, int thgt,
159 	           bool fSrcColKey=false, const C4BltTransform *pTransform=nullptr);
160 	bool BlitSimple(C4Surface * sfcSource, int fx, int fy, int fwdt, int fhgt,
161 	                C4Surface * sfcTarget, int tx, int ty, int twdt, int thgt,
162 	                bool fTransparency=true);
163 	bool BlitSurface(C4Surface * sfcSurface, C4Surface * sfcTarget, int tx, int ty, bool fBlitBase);
164 	bool BlitSurfaceTile(C4Surface * sfcSurface, C4Surface * sfcTarget, float iToX, float iToY, float iToWdt, float iToHgt, float iOffsetX, float iOffsetY, C4ShaderCall* shader_call);
165 	virtual void FillBG(DWORD dwClr=0) = 0;
166 	// Text
167 	enum { DEFAULT_MESSAGE_COLOR = 0xffffffff };
168 	bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface * sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true);
169 	bool StringOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface * sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true);
170 	// Drawing
171 	virtual void PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, C4ShaderCall* shader_call) = 0;
172 	virtual void PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, float width, C4ShaderCall* shader_call) = 0;
173 	virtual 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) = 0; // blit the same texture many times
174 	// Convenience drawing functions
175 	void DrawBoxDw(C4Surface * sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr); // calls DrawBoxFade
176 	void DrawBoxFade(C4Surface * sfcDest, float iX, float iY, float iWdt, float iHgt, DWORD dwClr1, DWORD dwClr2, DWORD dwClr3, DWORD dwClr4, C4ShaderCall* shader_call); // calls DrawQuadDw
177 	void DrawPatternedCircle(C4Surface * sfcDest, int x, int y, int r, BYTE col, C4Pattern & Pattern, CStdPalette &rPal);
178 	void DrawFrameDw(C4Surface * sfcDest, int x1, int y1, int x2, int y2, DWORD dwClr, float width=1.0f);
179 	void DrawQuadDw(C4Surface * sfcTarget, float *ipVtx, DWORD dwClr1, DWORD dwClr2, DWORD dwClr3, DWORD dwClr4, C4ShaderCall* shader_call);
180 	void DrawPix(C4Surface * sfcDest, float tx, float ty, DWORD dwCol); // Consider using PerformMultiPix if you draw more than one pixel
181 	void DrawLineDw(C4Surface * sfcTarget, float x1, float y1, float x2, float y2, DWORD dwClr, float width = 1.0f); // Consider using PerformMultiLines if you draw more than one line
182 	void DrawCircleDw(C4Surface * sfcTarget, float cx, float cy, float r, DWORD dwClr, float width = 1.0f);
183 	// gamma
184 	void SetGamma(float r, float g, float b, int32_t iRampIndex);  // set gamma
185 	void ResetGamma(); // reset gamma to default
186 	DWORD ApplyGammaTo(DWORD dwClr); // apply gamma to given color
187 	// blit states
ActivateBlitModulation(DWORD dwWithClr)188 	void ActivateBlitModulation(DWORD dwWithClr) { BlitModulated=true; BlitModulateClr=dwWithClr; } // modulate following blits with a given color
DeactivateBlitModulation()189 	void DeactivateBlitModulation() { BlitModulated=false; }  // stop color modulation of blits
GetBlitModulation(DWORD & rdwColor)190 	bool GetBlitModulation(DWORD &rdwColor) { rdwColor=BlitModulateClr; return BlitModulated; }
SetBlitMode(DWORD dwBlitMode)191 	void SetBlitMode(DWORD dwBlitMode) { this->dwBlitMode=dwBlitMode & C4GFXBLIT_ALL; } // set blit mode extra flags (additive blits, mod2-modulation, etc.)
ResetBlitMode()192 	void ResetBlitMode() { dwBlitMode=0; }
SetFoW(const C4FoWRegion * fow)193 	void SetFoW(const C4FoWRegion* fow) { pFoW = fow; }
GetFoW()194 	const C4FoWRegion* GetFoW() const { return pFoW; }
195 	void SetZoom(float X, float Y, float Zoom);
SetZoom(const ZoomData & zoom)196 	void SetZoom(const ZoomData &zoom) { SetZoom(zoom.X, zoom.Y, zoom.Zoom); }
GetZoom(ZoomData * r)197 	void GetZoom(ZoomData *r) { r->Zoom=Zoom; r->X=ZoomX; r->Y=ZoomY; }
198 	void ApplyZoom(float & X, float & Y);
199 	void RemoveZoom(float & X, float & Y);
SetMeshTransform(const StdMeshMatrix * Transform)200 	void SetMeshTransform(const StdMeshMatrix* Transform) { MeshTransform = Transform; } // if non-nullptr make sure to keep matrix valid
SetPerspective(bool fSet)201 	void SetPerspective(bool fSet) { fUsePerspective = fSet; }
202 
203 	// device objects
204 	virtual bool RestoreDeviceObjects() = 0;    // restore device dependant objects
205 	virtual bool InvalidateDeviceObjects() = 0; // free device dependant objects
206 	virtual bool DeviceReady() = 0;             // return whether device exists
207 
208 protected:
209 	bool StringOut(const char *szText, C4Surface * sfcDest, float iTx, float iTy, DWORD dwFCol, BYTE byForm, bool fDoMarkup, C4Markup &Markup, CStdFont *pFont, float fZoom);
210 	bool CreatePrimaryClipper(unsigned int iXRes, unsigned int iYRes);
211 	virtual bool Error(const char *szMsg);
212 
213 	friend class C4Surface;
214 	friend class C4TexRef;
215 	friend class C4Pattern;
216 };
217 
218 struct ZoomDataStackItem: public ZoomData
219 {
ZoomDataStackItemZoomDataStackItem220 	ZoomDataStackItem(float newzoom) { pDraw->GetZoom(this); pDraw->SetZoom(X, Y, newzoom); }
ZoomDataStackItemZoomDataStackItem221 	ZoomDataStackItem(float X, float Y, float newzoom) { pDraw->GetZoom(this); pDraw->SetZoom(X, Y, newzoom); }
~ZoomDataStackItemZoomDataStackItem222 	~ZoomDataStackItem() { pDraw->SetZoom(*this); }
223 };
224 
225 bool DDrawInit(C4AbstractApp * pApp, unsigned int iXRes, unsigned int iYRes, unsigned int iMonitor);
226 #endif // INC_STDDDRAW2
227