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