1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
3 | #ifndef ENGINE_GRAPHICS_H |
4 | #define ENGINE_GRAPHICS_H |
5 | |
6 | #include "kernel.h" |
7 | #include "warning.h" |
8 | |
9 | #include <base/color.h> |
10 | #include <base/system.h> |
11 | |
12 | #include <cstddef> |
13 | #include <cstdint> |
14 | #include <functional> |
15 | #include <vector> |
16 | |
17 | #define GRAPHICS_TYPE_UNSIGNED_BYTE 0x1401 |
18 | #define GRAPHICS_TYPE_UNSIGNED_SHORT 0x1403 |
19 | #define GRAPHICS_TYPE_INT 0x1404 |
20 | #define GRAPHICS_TYPE_UNSIGNED_INT 0x1405 |
21 | #define GRAPHICS_TYPE_FLOAT 0x1406 |
22 | |
23 | struct SBufferContainerInfo |
24 | { |
25 | int m_Stride; |
26 | int m_VertBufferBindingIndex; |
27 | |
28 | // the attributes of the container |
29 | struct SAttribute |
30 | { |
31 | int m_DataTypeCount; |
32 | unsigned int m_Type; |
33 | bool m_Normalized; |
34 | void *m_pOffset; |
35 | |
36 | //0: float, 1:integer |
37 | unsigned int m_FuncType; |
38 | }; |
39 | std::vector<SAttribute> m_vAttributes; |
40 | }; |
41 | |
42 | struct SQuadRenderInfo |
43 | { |
44 | ColorRGBA m_Color; |
45 | vec2 m_Offsets; |
46 | float m_Rotation; |
47 | // allows easier upload for uniform buffers because of the alignment requirements |
48 | float m_Padding; |
49 | }; |
50 | |
51 | struct SGraphicTile |
52 | { |
53 | vec2 m_TopLeft; |
54 | vec2 m_TopRight; |
55 | vec2 m_BottomRight; |
56 | vec2 m_BottomLeft; |
57 | }; |
58 | |
59 | struct SGraphicTileTexureCoords |
60 | { |
61 | ubvec4 m_TexCoordTopLeft; |
62 | ubvec4 m_TexCoordTopRight; |
63 | ubvec4 m_TexCoordBottomRight; |
64 | ubvec4 m_TexCoordBottomLeft; |
65 | }; |
66 | |
67 | class CImageInfo |
68 | { |
69 | public: |
70 | enum EImageFormat |
71 | { |
72 | FORMAT_ERROR = -1, |
73 | FORMAT_RGB = 0, |
74 | FORMAT_RGBA = 1, |
75 | FORMAT_SINGLE_COMPONENT = 2, |
76 | }; |
77 | |
78 | /** |
79 | * Contains the width of the image |
80 | */ |
81 | int m_Width = 0; |
82 | |
83 | /** |
84 | * Contains the height of the image |
85 | */ |
86 | int m_Height = 0; |
87 | |
88 | /** |
89 | * Contains the format of the image. |
90 | * |
91 | * @see EImageFormat |
92 | */ |
93 | EImageFormat m_Format = FORMAT_ERROR; |
94 | |
95 | /** |
96 | * Pointer to the image data. |
97 | */ |
98 | uint8_t *m_pData = nullptr; |
99 | |
100 | void Free() |
101 | { |
102 | m_Width = 0; |
103 | m_Height = 0; |
104 | m_Format = FORMAT_ERROR; |
105 | free(ptr: m_pData); |
106 | m_pData = nullptr; |
107 | } |
108 | |
109 | static size_t PixelSize(EImageFormat Format) |
110 | { |
111 | dbg_assert(Format != FORMAT_ERROR, "Format invalid" ); |
112 | static const size_t s_aSizes[] = {3, 4, 1}; |
113 | return s_aSizes[(int)Format]; |
114 | } |
115 | |
116 | size_t PixelSize() const |
117 | { |
118 | return PixelSize(Format: m_Format); |
119 | } |
120 | |
121 | size_t DataSize() const |
122 | { |
123 | return (size_t)m_Width * m_Height * PixelSize(Format: m_Format); |
124 | } |
125 | |
126 | static EImageFormat ImageFormatFromInt(int Format) |
127 | { |
128 | if(Format < (int)FORMAT_RGB || Format > (int)FORMAT_SINGLE_COMPONENT) |
129 | return FORMAT_ERROR; |
130 | return (EImageFormat)Format; |
131 | } |
132 | }; |
133 | |
134 | /* |
135 | Structure: CVideoMode |
136 | */ |
137 | class CVideoMode |
138 | { |
139 | public: |
140 | int m_CanvasWidth, m_CanvasHeight; |
141 | int m_WindowWidth, m_WindowHeight; |
142 | int m_RefreshRate; |
143 | int m_Red, m_Green, m_Blue; |
144 | uint32_t m_Format; |
145 | }; |
146 | |
147 | typedef vec2 GL_SPoint; |
148 | typedef vec2 GL_STexCoord; |
149 | |
150 | struct GL_STexCoord3D |
151 | { |
152 | GL_STexCoord3D &operator=(const GL_STexCoord &TexCoord) |
153 | { |
154 | u = TexCoord.u; |
155 | v = TexCoord.v; |
156 | return *this; |
157 | } |
158 | |
159 | GL_STexCoord3D &operator=(const vec3 &TexCoord) |
160 | { |
161 | u = TexCoord.u; |
162 | v = TexCoord.v; |
163 | w = TexCoord.w; |
164 | return *this; |
165 | } |
166 | |
167 | float u, v, w; |
168 | }; |
169 | |
170 | typedef ColorRGBA GL_SColorf; |
171 | //use normalized color values |
172 | typedef vector4_base<unsigned char> GL_SColor; |
173 | |
174 | struct GL_SVertex |
175 | { |
176 | GL_SPoint m_Pos; |
177 | GL_STexCoord m_Tex; |
178 | GL_SColor m_Color; |
179 | }; |
180 | |
181 | struct GL_SVertexTex3D |
182 | { |
183 | GL_SPoint m_Pos; |
184 | GL_SColorf m_Color; |
185 | GL_STexCoord3D m_Tex; |
186 | }; |
187 | |
188 | struct GL_SVertexTex3DStream |
189 | { |
190 | GL_SPoint m_Pos; |
191 | GL_SColor m_Color; |
192 | GL_STexCoord3D m_Tex; |
193 | }; |
194 | |
195 | static constexpr size_t gs_GraphicsMaxQuadsRenderCount = 256; |
196 | static constexpr size_t gs_GraphicsMaxParticlesRenderCount = 512; |
197 | |
198 | enum EGraphicsDriverAgeType |
199 | { |
200 | GRAPHICS_DRIVER_AGE_TYPE_LEGACY = 0, |
201 | GRAPHICS_DRIVER_AGE_TYPE_DEFAULT, |
202 | GRAPHICS_DRIVER_AGE_TYPE_MODERN, |
203 | |
204 | GRAPHICS_DRIVER_AGE_TYPE_COUNT, |
205 | }; |
206 | |
207 | enum EBackendType |
208 | { |
209 | BACKEND_TYPE_OPENGL = 0, |
210 | BACKEND_TYPE_OPENGL_ES, |
211 | BACKEND_TYPE_VULKAN, |
212 | |
213 | // special value to tell the backend to identify the current backend |
214 | BACKEND_TYPE_AUTO, |
215 | |
216 | BACKEND_TYPE_COUNT, |
217 | }; |
218 | |
219 | struct STWGraphicGpu |
220 | { |
221 | enum ETWGraphicsGpuType |
222 | { |
223 | GRAPHICS_GPU_TYPE_DISCRETE = 0, |
224 | GRAPHICS_GPU_TYPE_INTEGRATED, |
225 | GRAPHICS_GPU_TYPE_VIRTUAL, |
226 | GRAPHICS_GPU_TYPE_CPU, |
227 | |
228 | // should stay at last position in this enum |
229 | GRAPHICS_GPU_TYPE_INVALID, |
230 | }; |
231 | |
232 | struct STWGraphicGpuItem |
233 | { |
234 | char m_aName[256]; |
235 | ETWGraphicsGpuType m_GpuType; |
236 | }; |
237 | std::vector<STWGraphicGpuItem> m_vGpus; |
238 | STWGraphicGpuItem m_AutoGpu; |
239 | }; |
240 | |
241 | typedef STWGraphicGpu TTwGraphicsGpuList; |
242 | |
243 | typedef std::function<void()> WINDOW_RESIZE_FUNC; |
244 | typedef std::function<void()> WINDOW_PROPS_CHANGED_FUNC; |
245 | |
246 | typedef std::function<bool(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData)> TGLBackendReadPresentedImageData; |
247 | |
248 | class IGraphics : public IInterface |
249 | { |
250 | MACRO_INTERFACE("graphics" ) |
251 | protected: |
252 | int m_ScreenWidth; |
253 | int m_ScreenHeight; |
254 | int m_ScreenRefreshRate; |
255 | float m_ScreenHiDPIScale; |
256 | |
257 | public: |
258 | enum |
259 | { |
260 | TEXLOAD_NOMIPMAPS = 1 << 1, |
261 | TEXLOAD_NO_COMPRESSION = 1 << 2, |
262 | TEXLOAD_TO_3D_TEXTURE = (1 << 3), |
263 | TEXLOAD_TO_2D_ARRAY_TEXTURE = (1 << 4), |
264 | TEXLOAD_NO_2D_TEXTURE = (1 << 5), |
265 | }; |
266 | |
267 | class CTextureHandle |
268 | { |
269 | friend class IGraphics; |
270 | int m_Id; |
271 | |
272 | public: |
273 | CTextureHandle() : |
274 | m_Id(-1) |
275 | { |
276 | } |
277 | |
278 | bool IsValid() const { return Id() >= 0; } |
279 | bool IsNullTexture() const { return Id() == 0; } |
280 | int Id() const { return m_Id; } |
281 | void Invalidate() { m_Id = -1; } |
282 | }; |
283 | |
284 | int ScreenWidth() const { return m_ScreenWidth; } |
285 | int ScreenHeight() const { return m_ScreenHeight; } |
286 | float ScreenAspect() const { return (float)ScreenWidth() / (float)ScreenHeight(); } |
287 | float ScreenHiDPIScale() const { return m_ScreenHiDPIScale; } |
288 | int WindowWidth() const { return m_ScreenWidth / m_ScreenHiDPIScale; } |
289 | int WindowHeight() const { return m_ScreenHeight / m_ScreenHiDPIScale; } |
290 | |
291 | virtual void WarnPngliteIncompatibleImages(bool Warn) = 0; |
292 | virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0; |
293 | virtual bool SetWindowScreen(int Index) = 0; |
294 | virtual bool SetVSync(bool State) = 0; |
295 | virtual bool SetMultiSampling(uint32_t ReqMultiSamplingCount, uint32_t &MultiSamplingCountBackend) = 0; |
296 | virtual int GetWindowScreen() = 0; |
297 | virtual void Move(int x, int y) = 0; |
298 | virtual void Resize(int w, int h, int RefreshRate) = 0; |
299 | virtual void GotResized(int w, int h, int RefreshRate) = 0; |
300 | virtual void UpdateViewport(int X, int Y, int W, int H, bool ByResize) = 0; |
301 | |
302 | /** |
303 | * Listens to a resize event of the canvas, which is usually caused by a window resize. |
304 | * Will only be triggered if the actual size changed. |
305 | */ |
306 | virtual void AddWindowResizeListener(WINDOW_RESIZE_FUNC pFunc) = 0; |
307 | /** |
308 | * Listens to various window property changes, such as minimize, maximize, move, fullscreen mode |
309 | */ |
310 | virtual void AddWindowPropChangeListener(WINDOW_PROPS_CHANGED_FUNC pFunc) = 0; |
311 | |
312 | virtual void WindowDestroyNtf(uint32_t WindowId) = 0; |
313 | virtual void WindowCreateNtf(uint32_t WindowId) = 0; |
314 | |
315 | // ForceClearNow forces the backend to trigger a clear, even at performance cost, else it might be delayed by one frame |
316 | virtual void Clear(float r, float g, float b, bool ForceClearNow = false) = 0; |
317 | |
318 | virtual void ClipEnable(int x, int y, int w, int h) = 0; |
319 | virtual void ClipDisable() = 0; |
320 | |
321 | virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) = 0; |
322 | virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY) = 0; |
323 | |
324 | // TODO: These should perhaps not be virtuals |
325 | virtual void BlendNone() = 0; |
326 | virtual void BlendNormal() = 0; |
327 | virtual void BlendAdditive() = 0; |
328 | virtual void WrapNormal() = 0; |
329 | virtual void WrapClamp() = 0; |
330 | |
331 | virtual uint64_t TextureMemoryUsage() const = 0; |
332 | virtual uint64_t BufferMemoryUsage() const = 0; |
333 | virtual uint64_t StreamedMemoryUsage() const = 0; |
334 | virtual uint64_t StagingMemoryUsage() const = 0; |
335 | |
336 | virtual const TTwGraphicsGpuList &GetGpus() const = 0; |
337 | |
338 | virtual bool LoadPng(CImageInfo &Image, const char *pFilename, int StorageType) = 0; |
339 | |
340 | virtual bool CheckImageDivisibility(const char *pFileName, CImageInfo &Img, int DivX, int DivY, bool AllowResize) = 0; |
341 | virtual bool IsImageFormatRGBA(const char *pFileName, CImageInfo &Img) = 0; |
342 | |
343 | // destination and source buffer require to have the same width and height |
344 | virtual void CopyTextureBufferSub(uint8_t *pDestBuffer, const CImageInfo &SourceImage, size_t SubOffsetX, size_t SubOffsetY, size_t SubCopyWidth, size_t SubCopyHeight) = 0; |
345 | |
346 | // destination width must be equal to the subwidth of the source |
347 | virtual void CopyTextureFromTextureBufferSub(uint8_t *pDestBuffer, size_t DestWidth, size_t DestHeight, const CImageInfo &SourceImage, size_t SrcSubOffsetX, size_t SrcSubOffsetY, size_t SrcSubCopyWidth, size_t SrcSubCopyHeight) = 0; |
348 | |
349 | virtual int UnloadTexture(CTextureHandle *pIndex) = 0; |
350 | virtual CTextureHandle LoadTextureRaw(const CImageInfo &Image, int Flags, const char *pTexName = nullptr) = 0; |
351 | virtual CTextureHandle LoadTextureRawMove(CImageInfo &Image, int Flags, const char *pTexName = nullptr) = 0; |
352 | virtual int LoadTextureRawSub(CTextureHandle TextureId, int x, int y, const CImageInfo &Image) = 0; |
353 | virtual CTextureHandle LoadTexture(const char *pFilename, int StorageType, int Flags = 0) = 0; |
354 | virtual CTextureHandle NullTexture() const = 0; |
355 | virtual void TextureSet(CTextureHandle Texture) = 0; |
356 | void TextureClear() { TextureSet(Texture: CTextureHandle()); } |
357 | |
358 | // pTextData & pTextOutlineData are automatically free'd |
359 | virtual bool LoadTextTextures(size_t Width, size_t Height, CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture, uint8_t *pTextData, uint8_t *pTextOutlineData) = 0; |
360 | virtual bool UnloadTextTextures(CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture) = 0; |
361 | virtual bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, const uint8_t *pData) = 0; |
362 | |
363 | virtual CTextureHandle LoadSpriteTexture(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) = 0; |
364 | |
365 | virtual bool IsImageSubFullyTransparent(const CImageInfo &FromImageInfo, int x, int y, int w, int h) = 0; |
366 | virtual bool IsSpriteTextureFullyTransparent(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) = 0; |
367 | |
368 | virtual void FlushVertices(bool KeepVertices = false) = 0; |
369 | virtual void FlushVerticesTex3D() = 0; |
370 | |
371 | // specific render functions |
372 | virtual void RenderTileLayer(int BufferContainerIndex, const ColorRGBA &Color, char **pOffsets, unsigned int *pIndicedVertexDrawNum, size_t NumIndicesOffset) = 0; |
373 | virtual void RenderBorderTiles(int BufferContainerIndex, const ColorRGBA &Color, char *pIndexBufferOffset, const vec2 &Offset, const vec2 &Scale, uint32_t DrawNum) = 0; |
374 | virtual void RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, size_t QuadNum, int QuadOffset) = 0; |
375 | virtual void RenderText(int BufferContainerIndex, int TextQuadNum, int TextureSize, int TextureTextIndex, int TextureTextOutlineIndex, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor) = 0; |
376 | |
377 | // opengl 3.3 functions |
378 | |
379 | enum EBufferObjectCreateFlags |
380 | { |
381 | // tell the backend that the buffer only needs to be valid for the span of one frame. Buffer size is not allowed to be bigger than GL_SVertex * MAX_VERTICES |
382 | BUFFER_OBJECT_CREATE_FLAGS_ONE_TIME_USE_BIT = 1 << 0, |
383 | }; |
384 | |
385 | // if a pointer is passed as moved pointer, it requires to be allocated with malloc() |
386 | virtual int CreateBufferObject(size_t UploadDataSize, void *pUploadData, int CreateFlags, bool IsMovedPointer = false) = 0; |
387 | virtual void RecreateBufferObject(int BufferIndex, size_t UploadDataSize, void *pUploadData, int CreateFlags, bool IsMovedPointer = false) = 0; |
388 | virtual void DeleteBufferObject(int BufferIndex) = 0; |
389 | |
390 | virtual int CreateBufferContainer(struct SBufferContainerInfo *pContainerInfo) = 0; |
391 | // destroying all buffer objects means, that all referenced VBOs are destroyed automatically, so the user does not need to save references to them |
392 | virtual void DeleteBufferContainer(int &ContainerIndex, bool DestroyAllBO = true) = 0; |
393 | virtual void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) = 0; |
394 | |
395 | // returns true if the driver age type is supported, passing BACKEND_TYPE_AUTO for BackendType will query the values for the currently used backend |
396 | virtual bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) = 0; |
397 | virtual bool IsConfigModernAPI() = 0; |
398 | virtual bool IsTileBufferingEnabled() = 0; |
399 | virtual bool IsQuadBufferingEnabled() = 0; |
400 | virtual bool IsTextBufferingEnabled() = 0; |
401 | virtual bool IsQuadContainerBufferingEnabled() = 0; |
402 | virtual bool Uses2DTextureArrays() = 0; |
403 | virtual bool HasTextureArraysSupport() = 0; |
404 | |
405 | virtual const char *GetVendorString() = 0; |
406 | virtual const char *GetVersionString() = 0; |
407 | virtual const char *GetRendererString() = 0; |
408 | |
409 | struct CLineItem |
410 | { |
411 | float m_X0, m_Y0, m_X1, m_Y1; |
412 | CLineItem() {} |
413 | CLineItem(float x0, float y0, float x1, float y1) : |
414 | m_X0(x0), m_Y0(y0), m_X1(x1), m_Y1(y1) {} |
415 | }; |
416 | virtual void LinesBegin() = 0; |
417 | virtual void LinesEnd() = 0; |
418 | virtual void LinesDraw(const CLineItem *pArray, int Num) = 0; |
419 | |
420 | virtual void QuadsBegin() = 0; |
421 | virtual void QuadsEnd() = 0; |
422 | virtual void QuadsTex3DBegin() = 0; |
423 | virtual void QuadsTex3DEnd() = 0; |
424 | virtual void TrianglesBegin() = 0; |
425 | virtual void TrianglesEnd() = 0; |
426 | virtual void QuadsEndKeepVertices() = 0; |
427 | virtual void QuadsDrawCurrentVertices(bool KeepVertices = true) = 0; |
428 | virtual void QuadsSetRotation(float Angle) = 0; |
429 | virtual void QuadsSetSubset(float TopLeftU, float TopLeftV, float BottomRightU, float BottomRightV) = 0; |
430 | virtual void QuadsSetSubsetFree(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, int Index = -1) = 0; |
431 | |
432 | struct CFreeformItem |
433 | { |
434 | float m_X0, m_Y0, m_X1, m_Y1, m_X2, m_Y2, m_X3, m_Y3; |
435 | CFreeformItem() {} |
436 | CFreeformItem(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) : |
437 | m_X0(x0), m_Y0(y0), m_X1(x1), m_Y1(y1), m_X2(x2), m_Y2(y2), m_X3(x3), m_Y3(y3) {} |
438 | }; |
439 | |
440 | struct CQuadItem |
441 | { |
442 | float m_X, m_Y, m_Width, m_Height; |
443 | CQuadItem() {} |
444 | CQuadItem(float x, float y, float w, float h) : |
445 | m_X(x), m_Y(y), m_Width(w), m_Height(h) {} |
446 | void Set(float x, float y, float w, float h) |
447 | { |
448 | m_X = x; |
449 | m_Y = y; |
450 | m_Width = w; |
451 | m_Height = h; |
452 | } |
453 | |
454 | CFreeformItem ToFreeForm() const |
455 | { |
456 | return CFreeformItem(m_X, m_Y, m_X + m_Width, m_Y, m_X, m_Y + m_Height, m_X + m_Width, m_Y + m_Height); |
457 | } |
458 | }; |
459 | virtual void QuadsDraw(CQuadItem *pArray, int Num) = 0; |
460 | virtual void QuadsDrawTL(const CQuadItem *pArray, int Num) = 0; |
461 | |
462 | virtual void QuadsTex3DDrawTL(const CQuadItem *pArray, int Num) = 0; |
463 | |
464 | virtual const GL_STexCoord *GetCurTextureCoordinates() = 0; |
465 | virtual const GL_SColor *GetCurColor() = 0; |
466 | |
467 | virtual int CreateQuadContainer(bool AutomaticUpload = true) = 0; |
468 | virtual void QuadContainerChangeAutomaticUpload(int ContainerIndex, bool AutomaticUpload) = 0; |
469 | virtual void QuadContainerUpload(int ContainerIndex) = 0; |
470 | virtual int QuadContainerAddQuads(int ContainerIndex, CQuadItem *pArray, int Num) = 0; |
471 | virtual int QuadContainerAddQuads(int ContainerIndex, CFreeformItem *pArray, int Num) = 0; |
472 | virtual void QuadContainerReset(int ContainerIndex) = 0; |
473 | virtual void DeleteQuadContainer(int &ContainerIndex) = 0; |
474 | virtual void RenderQuadContainer(int ContainerIndex, int QuadDrawNum) = 0; |
475 | virtual void RenderQuadContainer(int ContainerIndex, int QuadOffset, int QuadDrawNum, bool ChangeWrapMode = true) = 0; |
476 | virtual void RenderQuadContainerEx(int ContainerIndex, int QuadOffset, int QuadDrawNum, float X, float Y, float ScaleX = 1.f, float ScaleY = 1.f) = 0; |
477 | virtual void RenderQuadContainerAsSprite(int ContainerIndex, int QuadOffset, float X, float Y, float ScaleX = 1.f, float ScaleY = 1.f) = 0; |
478 | |
479 | struct SRenderSpriteInfo |
480 | { |
481 | vec2 m_Pos; |
482 | float m_Scale; |
483 | float m_Rotation; |
484 | }; |
485 | |
486 | virtual void RenderQuadContainerAsSpriteMultiple(int ContainerIndex, int QuadOffset, int DrawCount, SRenderSpriteInfo *pRenderInfo) = 0; |
487 | |
488 | virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num) = 0; |
489 | virtual void QuadsText(float x, float y, float Size, const char *pText) = 0; |
490 | |
491 | enum |
492 | { |
493 | CORNER_NONE = 0, |
494 | CORNER_TL = 1, |
495 | CORNER_TR = 2, |
496 | CORNER_BL = 4, |
497 | CORNER_BR = 8, |
498 | |
499 | CORNER_T = CORNER_TL | CORNER_TR, |
500 | CORNER_B = CORNER_BL | CORNER_BR, |
501 | CORNER_R = CORNER_TR | CORNER_BR, |
502 | CORNER_L = CORNER_TL | CORNER_BL, |
503 | |
504 | CORNER_ALL = CORNER_T | CORNER_B, |
505 | }; |
506 | virtual void DrawRectExt(float x, float y, float w, float h, float r, int Corners) = 0; |
507 | virtual void DrawRectExt4(float x, float y, float w, float h, ColorRGBA ColorTopLeft, ColorRGBA ColorTopRight, ColorRGBA ColorBottomLeft, ColorRGBA ColorBottomRight, float r, int Corners) = 0; |
508 | virtual int CreateRectQuadContainer(float x, float y, float w, float h, float r, int Corners) = 0; |
509 | virtual void DrawRect(float x, float y, float w, float h, ColorRGBA Color, int Corners, float Rounding) = 0; |
510 | virtual void DrawRect4(float x, float y, float w, float h, ColorRGBA ColorTopLeft, ColorRGBA ColorTopRight, ColorRGBA ColorBottomLeft, ColorRGBA ColorBottomRight, int Corners, float Rounding) = 0; |
511 | virtual void DrawCircle(float CenterX, float CenterY, float Radius, int Segments) = 0; |
512 | |
513 | struct CColorVertex |
514 | { |
515 | int m_Index; |
516 | float m_R, m_G, m_B, m_A; |
517 | CColorVertex() {} |
518 | CColorVertex(int i, float r, float g, float b, float a) : |
519 | m_Index(i), m_R(r), m_G(g), m_B(b), m_A(a) {} |
520 | CColorVertex(int i, ColorRGBA Color) : |
521 | m_Index(i), m_R(Color.r), m_G(Color.g), m_B(Color.b), m_A(Color.a) {} |
522 | }; |
523 | virtual void SetColorVertex(const CColorVertex *pArray, size_t Num) = 0; |
524 | virtual void SetColor(float r, float g, float b, float a) = 0; |
525 | virtual void SetColor(ColorRGBA Color) = 0; |
526 | virtual void SetColor4(ColorRGBA TopLeft, ColorRGBA TopRight, ColorRGBA BottomLeft, ColorRGBA BottomRight) = 0; |
527 | virtual void ChangeColorOfCurrentQuadVertices(float r, float g, float b, float a) = 0; |
528 | virtual void ChangeColorOfQuadVertices(size_t QuadOffset, unsigned char r, unsigned char g, unsigned char b, unsigned char a) = 0; |
529 | |
530 | /** |
531 | * Reads the color at the specified position from the backbuffer once, |
532 | * after the next swap operation. |
533 | * |
534 | * @param Position The pixel position to read. |
535 | * @param pColor Pointer that will receive the read pixel color. |
536 | * The pointer must be valid until the next swap operation. |
537 | */ |
538 | virtual void ReadPixel(ivec2 Position, ColorRGBA *pColor) = 0; |
539 | virtual void TakeScreenshot(const char *pFilename) = 0; |
540 | virtual void TakeCustomScreenshot(const char *pFilename) = 0; |
541 | virtual int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) = 0; |
542 | virtual void GetCurrentVideoMode(CVideoMode &CurMode, int Screen) = 0; |
543 | virtual void Swap() = 0; |
544 | virtual int GetNumScreens() const = 0; |
545 | virtual const char *GetScreenName(int Screen) const = 0; |
546 | |
547 | // synchronization |
548 | virtual void InsertSignal(class CSemaphore *pSemaphore) = 0; |
549 | virtual bool IsIdle() const = 0; |
550 | virtual void WaitForIdle() = 0; |
551 | |
552 | virtual void SetWindowGrab(bool Grab) = 0; |
553 | virtual void NotifyWindow() = 0; |
554 | |
555 | // be aware that this function should only be called from the graphics thread, and even then you should really know what you are doing |
556 | // this function always returns the pixels in RGB |
557 | virtual TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() = 0; |
558 | |
559 | virtual SWarning *GetCurWarning() = 0; |
560 | |
561 | // returns true if the error msg was shown |
562 | virtual bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) = 0; |
563 | virtual bool IsBackendInitialized() = 0; |
564 | |
565 | protected: |
566 | inline CTextureHandle CreateTextureHandle(int Index) |
567 | { |
568 | CTextureHandle Tex; |
569 | Tex.m_Id = Index; |
570 | return Tex; |
571 | } |
572 | }; |
573 | |
574 | class IEngineGraphics : public IGraphics |
575 | { |
576 | MACRO_INTERFACE("enginegraphics" ) |
577 | public: |
578 | virtual int Init() = 0; |
579 | virtual void Shutdown() override = 0; |
580 | |
581 | virtual void Minimize() = 0; |
582 | virtual void Maximize() = 0; |
583 | |
584 | virtual int WindowActive() = 0; |
585 | virtual int WindowOpen() = 0; |
586 | }; |
587 | |
588 | extern IEngineGraphics *CreateEngineGraphicsThreaded(); |
589 | |
590 | #endif |
591 | |