1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2021, The LegacyClonk 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 DirectDraw surfaces */
18
19#pragma once
20
21#include "C4Rect.h"
22#include "Standard.h"
23#include "StdColors.h"
24
25#ifndef USE_CONSOLE
26#include <GL/glew.h>
27#endif
28
29#include <list>
30
31// config settings
32#define C4GFXCFG_NO_ALPHA_ADD 1
33#define C4GFXCFG_POINT_FILTERING 2
34#define C4GFXCFG_NOADDITIVEBLTS 8
35#define C4GFXCFG_NOBOXFADES 16
36#define C4GFXCFG_NOACCELERATION 512
37
38// blitting modes
39#define C4GFXBLIT_NORMAL 0 // regular blit
40#define C4GFXBLIT_ADDITIVE 1 // all blits additive
41#define C4GFXBLIT_MOD2 2 // additive color modulation
42#define C4GFXBLIT_CLRSFC_OWNCLR 4 // do not apply global modulation to ColorByOwner-surface
43#define C4GFXBLIT_CLRSFC_MOD2 8 // additive color modulation for ClrByOwner-surface
44
45#define C4GFXBLIT_ALL 15 // bist mask covering all blit modes
46#define C4GFXBLIT_NOADD 14 // bit mask covering all blit modes except additive
47
48#define C4GFXBLIT_CUSTOM 128 // custom blitting mode - ignored by gfx system
49#define C4GFXBLIT_PARENT 256 // blitting mode inherited by parent - ignored by gfx system
50
51const int ALeft = 0, ACenter = 1, ARight = 2;
52
53#ifndef USE_CONSOLE
54class CStdGL;
55extern CStdGL *pGL;
56#endif
57
58// class predefs
59class C4TexRef;
60class C4TexMgr;
61class CPattern;
62class CStdDDraw;
63
64extern CStdDDraw *lpDDraw;
65
66class C4Group;
67class C4GroupSet;
68
69class C4Surface
70{
71public:
72 C4Surface();
73 ~C4Surface();
74 C4Surface(std::int32_t width, std::int32_t height);
75
76 C4Surface(const C4Surface &other) = delete;
77 C4Surface &operator=(const C4Surface &other) = delete;
78
79 C4Surface(C4Surface &&other);
80 C4Surface &operator=(C4Surface &&other);
81
82public:
83 bool IsRenderTarget(); // surface can be used as a render target?
84
85 void SetBackground() { fIsBackground = true; }
86 // Note: This uses partial locks, anything but SetPixDw and Unlock is undefined afterwards until unlock.
87 void ClearBoxDw(int iX, int iY, int iWdt, int iHgt);
88 bool Unlock(bool noUpload = false);
89 bool Lock();
90 bool LockForUpdate(C4Rect rect);
91 bool GetTexAt(C4TexRef **ppTexRef, int &rX, int &rY); // get texture and adjust x/y
92 bool GetLockTexAt(C4TexRef **ppTexRef, int &rX, int &rY); // get texture; ensure it's locked and adjust x/y
93 bool SetPix(int iX, int iY, uint8_t byCol); // set 8bit-px
94 uint32_t GetPixDw(int iX, int iY, bool fApplyModulation, float scale = 1.0); // get 32bit-px
95 bool IsPixTransparent(int iX, int iY); // is pixel's alpha value 0xff?
96 bool SetPixDw(int iX, int iY, uint32_t dwCol); // set pix in surface only
97 bool BltPix(int iX, int iY, C4Surface *sfcSource, int iSrcX, int iSrcY, bool fTransparency); // blit pixel from source to this surface (assumes clipped coordinates!)
98 bool Create(int iWdt, int iHgt, bool fOwnPal = false, bool fIsRenderTarget = false);
99 bool CreateColorByOwner(C4Surface *pBySurface); // create ColorByOwner-surface
100 bool SetAsClrByOwnerOf(C4Surface *pOfSurface); // assume that ColorByOwner-surface has been created, and just assign it; fails if the size doesn't match
101 bool AttachSfc(void *sfcSurface);
102 void Clear();
103 void Default();
104 void Clip(int iX, int iY, int iX2, int iY2);
105 void NoClip();
106 bool Read(C4Group &hGroup, bool fOwnPal = false);
107 bool SavePNG(const char *szFilename, bool fSaveAlpha, bool fApplyGamma, bool fSaveOverlayOnly, float scale = 1.0f);
108 bool Wipe(); // empty to transparent
109 bool GetSurfaceSize(int &irX, int &irY); // get surface size
110 void SetClr(uint32_t toClr) { ClrByOwnerClr = toClr ? toClr : 0xff; }
111 uint32_t GetClr() { return ClrByOwnerClr; }
112 bool CopyBytes(uint8_t *pImageData); // assumes an array of wdt*hgt*4 and copies data directly from it
113
114 bool LoadAny(C4Group &hGroup, const char *szFilename, bool fOwnPal = false, bool fNoErrIfNotFound = false);
115 bool LoadAny(C4GroupSet &hGroupset, const char *szFilename, bool fOwnPal = false, bool fNoErrIfNotFound = false);
116 bool Load(C4Group &hGroup, const char *szFilename, bool fOwnPal = false, bool fNoErrIfNotFound = false);
117 bool SavePNG(C4Group &hGroup, const char *szFilename, bool fSaveAlpha = true, bool fApplyGamma = false, bool fSaveOverlayOnly = false);
118 bool Copy(C4Surface &fromSfc);
119 bool ReadPNG(C4Group &hGroup);
120 bool ReadJPEG(C4Group &hGroup);
121
122private:
123 bool CreateTextures(); // create ppTex-array
124 void FreeTextures(); // free ppTex-array if existent
125
126 friend class CStdDDraw;
127 friend class CPattern;
128 friend class CStdGL;
129
130public:
131 int Wdt, Hgt; // size of surface
132 int PrimarySurfaceLockPitch; uint8_t *PrimarySurfaceLockBits; // lock data if primary surface is locked
133 int iTexSize; // size of textures
134 int iTexX, iTexY; // number of textures in x/y-direction
135 int ClipX, ClipY, ClipX2, ClipY2;
136 bool fIsRenderTarget; // set for surfaces to be used as offscreen render targets
137 bool fIsBackground; // background surfaces fill unused pixels with black, rather than transparency - must be set prior to loading
138#ifndef NDEBUG
139 int *dbg_idx;
140#endif
141#ifndef USE_CONSOLE
142 GLenum Format; // used color format in textures
143#endif
144 C4TexRef **ppTex; // textures
145 C4Surface *pMainSfc; // main surface for simple ColorByOwner-surfaces
146 uint32_t ClrByOwnerClr; // current color to be used for ColorByOwner-blits
147
148private:
149 int Locked;
150 bool fPrimary;
151
152 bool IsSingleSurface() const { return iTexX * iTexY == 1; } // return whether surface is not split
153};
154
155struct D3DLOCKED_RECT
156{
157 int Pitch;
158 unsigned char *pBits;
159};
160
161// one texture encapsulation
162class C4TexRef
163{
164public:
165 D3DLOCKED_RECT texLock; // current lock-data
166#ifndef USE_CONSOLE
167 GLuint texName;
168#endif
169 int iSize;
170 bool fIntLock; // if set, texref is locked internally only
171 C4Rect LockSize;
172
173 C4TexRef(int iSize, bool fAsRenderTarget); // create texture with given size
174 ~C4TexRef(); // release texture
175 bool Lock(); // lock texture
176 // Lock a part of the rect, discarding the content
177 // Note: Calling Lock afterwards without an Unlock first is undefined
178 bool LockForUpdate(C4Rect rect);
179 void Unlock(bool noUpload = false); // unlock texture
180 bool ClearRect(C4Rect rect); // clear rect in texture to transparent
181 bool FillBlack(); // fill complete texture in black
182
183 void SetPix(int iX, int iY, uint32_t v)
184 {
185 *reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(texLock.pBits) + (iY - LockSize.y) * texLock.Pitch + (iX - LockSize.x) * 4) = v;
186 }
187
188private:
189 int32_t LockCount;
190};
191
192// texture management
193class C4TexMgr
194{
195public:
196 std::list<C4TexRef *> Textures;
197
198public:
199 C4TexMgr();
200 ~C4TexMgr();
201
202 void RegTex(C4TexRef *pTex);
203 void UnregTex(C4TexRef *pTex);
204
205 void IntLock(); // do an internal lock
206 void IntUnlock(); // undo internal lock
207};
208
209extern C4TexMgr *pTexMgr;
210