1#ifndef ENGINE_CLIENT_GRAPHICS_THREADED_H
2#define ENGINE_CLIENT_GRAPHICS_THREADED_H
3
4#include <base/system.h>
5#include <engine/graphics.h>
6#include <engine/shared/config.h>
7
8#include <cstddef>
9#include <string>
10#include <vector>
11
12constexpr int CMD_BUFFER_DATA_BUFFER_SIZE = 1024 * 1024 * 2;
13constexpr int CMD_BUFFER_CMD_BUFFER_SIZE = 1024 * 256;
14
15class CCommandBuffer
16{
17 class CBuffer
18 {
19 unsigned char *m_pData;
20 unsigned m_Size;
21 unsigned m_Used;
22
23 public:
24 CBuffer(unsigned BufferSize)
25 {
26 m_Size = BufferSize;
27 m_pData = new unsigned char[m_Size];
28 m_Used = 0;
29 }
30
31 ~CBuffer()
32 {
33 delete[] m_pData;
34 m_pData = 0x0;
35 m_Used = 0;
36 m_Size = 0;
37 }
38
39 void Reset()
40 {
41 m_Used = 0;
42 }
43
44 void *Alloc(unsigned Requested, unsigned Alignment = alignof(std::max_align_t))
45 {
46 size_t Offset = reinterpret_cast<uintptr_t>(m_pData + m_Used) % Alignment;
47 if(Offset)
48 Offset = Alignment - Offset;
49
50 if(Requested + Offset + m_Used > m_Size)
51 return 0;
52
53 void *pPtr = &m_pData[m_Used + Offset];
54 m_Used += Requested + Offset;
55 return pPtr;
56 }
57
58 unsigned char *DataPtr() { return m_pData; }
59 unsigned DataSize() const { return m_Size; }
60 unsigned DataUsed() const { return m_Used; }
61 };
62
63public:
64 CBuffer m_CmdBuffer;
65 size_t m_CommandCount = 0;
66 size_t m_RenderCallCount = 0;
67
68 CBuffer m_DataBuffer;
69
70 enum
71 {
72 MAX_TEXTURES = 1024 * 8,
73 MAX_VERTICES = 32 * 1024,
74 };
75
76 enum ECommandBufferCMD
77 {
78 // command groups
79 CMDGROUP_CORE = 0, // commands that everyone has to implement
80 CMDGROUP_PLATFORM_GL = 10000, // commands specific to a platform
81 CMDGROUP_PLATFORM_SDL = 20000,
82
83 //
84 CMD_FIRST = CMDGROUP_CORE,
85 CMD_NOP = CMD_FIRST,
86
87 //
88 CMD_RUNBUFFER,
89
90 // synchronization
91 CMD_SIGNAL,
92
93 // texture commands
94 CMD_TEXTURE_CREATE,
95 CMD_TEXTURE_DESTROY,
96 CMD_TEXTURE_UPDATE,
97 CMD_TEXT_TEXTURES_CREATE,
98 CMD_TEXT_TEXTURES_DESTROY,
99 CMD_TEXT_TEXTURE_UPDATE,
100
101 // rendering
102 CMD_CLEAR,
103 CMD_RENDER,
104 CMD_RENDER_TEX3D,
105
106 // opengl 2.0+ commands (some are just emulated and only exist in opengl 3.3+)
107 CMD_CREATE_BUFFER_OBJECT, // create vbo
108 CMD_RECREATE_BUFFER_OBJECT, // recreate vbo
109 CMD_UPDATE_BUFFER_OBJECT, // update vbo
110 CMD_COPY_BUFFER_OBJECT, // copy vbo to another
111 CMD_DELETE_BUFFER_OBJECT, // delete vbo
112
113 CMD_CREATE_BUFFER_CONTAINER, // create vao
114 CMD_DELETE_BUFFER_CONTAINER, // delete vao
115 CMD_UPDATE_BUFFER_CONTAINER, // update vao
116
117 CMD_INDICES_REQUIRED_NUM_NOTIFY, // create indices that are required
118
119 CMD_RENDER_TILE_LAYER, // render a tilelayer
120 CMD_RENDER_BORDER_TILE, // render one tile multiple times
121 CMD_RENDER_QUAD_LAYER, // render a quad layer
122 CMD_RENDER_TEXT, // render text
123 CMD_RENDER_QUAD_CONTAINER, // render a quad buffer container
124 CMD_RENDER_QUAD_CONTAINER_EX, // render a quad buffer container with extended parameters
125 CMD_RENDER_QUAD_CONTAINER_SPRITE_MULTIPLE, // render a quad buffer container as sprite multiple times
126
127 // swap
128 CMD_SWAP,
129
130 // misc
131 CMD_MULTISAMPLING,
132 CMD_VSYNC,
133 CMD_TRY_SWAP_AND_READ_PIXEL,
134 CMD_TRY_SWAP_AND_SCREENSHOT,
135 CMD_UPDATE_VIEWPORT,
136
137 // in Android a window that minimizes gets destroyed
138 CMD_WINDOW_CREATE_NTF,
139 CMD_WINDOW_DESTROY_NTF,
140
141 CMD_COUNT,
142 };
143
144 enum
145 {
146 TEXFORMAT_INVALID = 0,
147 TEXFORMAT_RGBA,
148
149 TEXFLAG_NOMIPMAPS = 1,
150 TEXFLAG_TO_3D_TEXTURE = (1 << 3),
151 TEXFLAG_TO_2D_ARRAY_TEXTURE = (1 << 4),
152 TEXFLAG_NO_2D_TEXTURE = (1 << 5),
153 };
154
155 enum
156 {
157 //
158 PRIMTYPE_INVALID = 0,
159 PRIMTYPE_LINES,
160 PRIMTYPE_QUADS,
161 PRIMTYPE_TRIANGLES,
162 };
163
164 enum
165 {
166 BLEND_NONE = 0,
167 BLEND_ALPHA,
168 BLEND_ADDITIVE,
169 };
170
171 enum
172 {
173 WRAP_REPEAT = 0,
174 WRAP_CLAMP,
175 };
176
177 typedef vec2 SPoint;
178 typedef vec2 STexCoord;
179 typedef GL_SColorf SColorf;
180 typedef GL_SColor SColor;
181 typedef GL_SVertex SVertex;
182 typedef GL_SVertexTex3D SVertexTex3D;
183 typedef GL_SVertexTex3DStream SVertexTex3DStream;
184
185 struct SCommand
186 {
187 public:
188 SCommand(unsigned Cmd) :
189 m_Cmd(Cmd), m_pNext(nullptr) {}
190 unsigned m_Cmd;
191 SCommand *m_pNext;
192 };
193 SCommand *m_pCmdBufferHead;
194 SCommand *m_pCmdBufferTail;
195
196 struct SState
197 {
198 int m_BlendMode;
199 int m_WrapMode;
200 int m_Texture;
201 SPoint m_ScreenTL;
202 SPoint m_ScreenBR;
203
204 // clip
205 bool m_ClipEnable;
206 int m_ClipX;
207 int m_ClipY;
208 int m_ClipW;
209 int m_ClipH;
210 };
211
212 struct SCommand_Clear : public SCommand
213 {
214 SCommand_Clear() :
215 SCommand(CMD_CLEAR) {}
216 SColorf m_Color;
217 bool m_ForceClear;
218 };
219
220 struct SCommand_Signal : public SCommand
221 {
222 SCommand_Signal() :
223 SCommand(CMD_SIGNAL) {}
224 CSemaphore *m_pSemaphore;
225 };
226
227 struct SCommand_RunBuffer : public SCommand
228 {
229 SCommand_RunBuffer() :
230 SCommand(CMD_RUNBUFFER) {}
231 CCommandBuffer *m_pOtherBuffer;
232 };
233
234 struct SCommand_Render : public SCommand
235 {
236 SCommand_Render() :
237 SCommand(CMD_RENDER) {}
238 SState m_State;
239 unsigned m_PrimType;
240 unsigned m_PrimCount;
241 SVertex *m_pVertices; // you should use the command buffer data to allocate vertices for this command
242 };
243
244 struct SCommand_RenderTex3D : public SCommand
245 {
246 SCommand_RenderTex3D() :
247 SCommand(CMD_RENDER_TEX3D) {}
248 SState m_State;
249 unsigned m_PrimType;
250 unsigned m_PrimCount;
251 SVertexTex3DStream *m_pVertices; // you should use the command buffer data to allocate vertices for this command
252 };
253
254 struct SCommand_CreateBufferObject : public SCommand
255 {
256 SCommand_CreateBufferObject() :
257 SCommand(CMD_CREATE_BUFFER_OBJECT) {}
258
259 int m_BufferIndex;
260
261 bool m_DeletePointer;
262 void *m_pUploadData;
263 size_t m_DataSize;
264
265 int m_Flags; // @see EBufferObjectCreateFlags
266 };
267
268 struct SCommand_RecreateBufferObject : public SCommand
269 {
270 SCommand_RecreateBufferObject() :
271 SCommand(CMD_RECREATE_BUFFER_OBJECT) {}
272
273 int m_BufferIndex;
274
275 bool m_DeletePointer;
276 void *m_pUploadData;
277 size_t m_DataSize;
278
279 int m_Flags; // @see EBufferObjectCreateFlags
280 };
281
282 struct SCommand_UpdateBufferObject : public SCommand
283 {
284 SCommand_UpdateBufferObject() :
285 SCommand(CMD_UPDATE_BUFFER_OBJECT) {}
286
287 int m_BufferIndex;
288
289 bool m_DeletePointer;
290 void *m_pOffset;
291 void *m_pUploadData;
292 size_t m_DataSize;
293 };
294
295 struct SCommand_CopyBufferObject : public SCommand
296 {
297 SCommand_CopyBufferObject() :
298 SCommand(CMD_COPY_BUFFER_OBJECT) {}
299
300 int m_WriteBufferIndex;
301 int m_ReadBufferIndex;
302
303 size_t m_ReadOffset;
304 size_t m_WriteOffset;
305 size_t m_CopySize;
306 };
307
308 struct SCommand_DeleteBufferObject : public SCommand
309 {
310 SCommand_DeleteBufferObject() :
311 SCommand(CMD_DELETE_BUFFER_OBJECT) {}
312
313 int m_BufferIndex;
314 };
315
316 struct SCommand_CreateBufferContainer : public SCommand
317 {
318 SCommand_CreateBufferContainer() :
319 SCommand(CMD_CREATE_BUFFER_CONTAINER) {}
320
321 int m_BufferContainerIndex;
322
323 int m_Stride;
324 int m_VertBufferBindingIndex;
325
326 size_t m_AttrCount;
327 SBufferContainerInfo::SAttribute *m_pAttributes;
328 };
329
330 struct SCommand_UpdateBufferContainer : public SCommand
331 {
332 SCommand_UpdateBufferContainer() :
333 SCommand(CMD_UPDATE_BUFFER_CONTAINER) {}
334
335 int m_BufferContainerIndex;
336
337 int m_Stride;
338 int m_VertBufferBindingIndex;
339
340 size_t m_AttrCount;
341 SBufferContainerInfo::SAttribute *m_pAttributes;
342 };
343
344 struct SCommand_DeleteBufferContainer : public SCommand
345 {
346 SCommand_DeleteBufferContainer() :
347 SCommand(CMD_DELETE_BUFFER_CONTAINER) {}
348
349 int m_BufferContainerIndex;
350 bool m_DestroyAllBO;
351 };
352
353 struct SCommand_IndicesRequiredNumNotify : public SCommand
354 {
355 SCommand_IndicesRequiredNumNotify() :
356 SCommand(CMD_INDICES_REQUIRED_NUM_NOTIFY) {}
357
358 unsigned int m_RequiredIndicesNum;
359 };
360
361 struct SCommand_RenderTileLayer : public SCommand
362 {
363 SCommand_RenderTileLayer() :
364 SCommand(CMD_RENDER_TILE_LAYER) {}
365 SState m_State;
366 SColorf m_Color; // the color of the whole tilelayer -- already enveloped
367
368 // the char offset of all indices that should be rendered, and the amount of renders
369 char **m_pIndicesOffsets;
370 unsigned int *m_pDrawCount;
371
372 int m_IndicesDrawNum;
373 int m_BufferContainerIndex;
374 };
375
376 struct SCommand_RenderBorderTile : public SCommand
377 {
378 SCommand_RenderBorderTile() :
379 SCommand(CMD_RENDER_BORDER_TILE) {}
380 SState m_State;
381 SColorf m_Color; // the color of the whole tilelayer -- already enveloped
382 char *m_pIndicesOffset;
383 uint32_t m_DrawNum;
384 int m_BufferContainerIndex;
385
386 vec2 m_Offset;
387 vec2 m_Scale;
388 };
389
390 struct SCommand_RenderQuadLayer : public SCommand
391 {
392 SCommand_RenderQuadLayer() :
393 SCommand(CMD_RENDER_QUAD_LAYER) {}
394 SState m_State;
395
396 int m_BufferContainerIndex;
397 SQuadRenderInfo *m_pQuadInfo;
398 size_t m_QuadNum;
399 int m_QuadOffset;
400 };
401
402 struct SCommand_RenderText : public SCommand
403 {
404 SCommand_RenderText() :
405 SCommand(CMD_RENDER_TEXT) {}
406 SState m_State;
407
408 int m_BufferContainerIndex;
409 int m_TextureSize;
410
411 int m_TextTextureIndex;
412 int m_TextOutlineTextureIndex;
413
414 int m_DrawNum;
415 ColorRGBA m_TextColor;
416 ColorRGBA m_TextOutlineColor;
417 };
418
419 struct SCommand_RenderQuadContainer : public SCommand
420 {
421 SCommand_RenderQuadContainer() :
422 SCommand(CMD_RENDER_QUAD_CONTAINER) {}
423 SState m_State;
424
425 int m_BufferContainerIndex;
426
427 unsigned int m_DrawNum;
428 void *m_pOffset;
429 };
430
431 struct SCommand_RenderQuadContainerEx : public SCommand
432 {
433 SCommand_RenderQuadContainerEx() :
434 SCommand(CMD_RENDER_QUAD_CONTAINER_EX) {}
435 SState m_State;
436
437 int m_BufferContainerIndex;
438
439 float m_Rotation;
440 SPoint m_Center;
441
442 SColorf m_VertexColor;
443
444 unsigned int m_DrawNum;
445 void *m_pOffset;
446 };
447
448 struct SCommand_RenderQuadContainerAsSpriteMultiple : public SCommand
449 {
450 SCommand_RenderQuadContainerAsSpriteMultiple() :
451 SCommand(CMD_RENDER_QUAD_CONTAINER_SPRITE_MULTIPLE) {}
452 SState m_State;
453
454 int m_BufferContainerIndex;
455
456 IGraphics::SRenderSpriteInfo *m_pRenderInfo;
457
458 SPoint m_Center;
459 SColorf m_VertexColor;
460
461 unsigned int m_DrawNum;
462 unsigned int m_DrawCount;
463 void *m_pOffset;
464 };
465
466 struct SCommand_TrySwapAndReadPixel : public SCommand
467 {
468 SCommand_TrySwapAndReadPixel() :
469 SCommand(CMD_TRY_SWAP_AND_READ_PIXEL) {}
470 ivec2 m_Position;
471 SColorf *m_pColor; // processor will fill this out
472 bool *m_pSwapped; // processor may set this to true, must be initialized to false by the caller
473 };
474
475 struct SCommand_TrySwapAndScreenshot : public SCommand
476 {
477 SCommand_TrySwapAndScreenshot() :
478 SCommand(CMD_TRY_SWAP_AND_SCREENSHOT) {}
479 CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well
480 bool *m_pSwapped; // processor may set this to true, must be initialized to false by the caller
481 };
482
483 struct SCommand_Swap : public SCommand
484 {
485 SCommand_Swap() :
486 SCommand(CMD_SWAP) {}
487 };
488
489 struct SCommand_VSync : public SCommand
490 {
491 SCommand_VSync() :
492 SCommand(CMD_VSYNC) {}
493
494 int m_VSync;
495 bool *m_pRetOk;
496 };
497
498 struct SCommand_MultiSampling : public SCommand
499 {
500 SCommand_MultiSampling() :
501 SCommand(CMD_MULTISAMPLING) {}
502
503 uint32_t m_RequestedMultiSamplingCount;
504 uint32_t *m_pRetMultiSamplingCount;
505 bool *m_pRetOk;
506 };
507
508 struct SCommand_Update_Viewport : public SCommand
509 {
510 SCommand_Update_Viewport() :
511 SCommand(CMD_UPDATE_VIEWPORT) {}
512
513 int m_X;
514 int m_Y;
515 int m_Width;
516 int m_Height;
517 bool m_ByResize; // resized by an resize event.. a hint to make clear that the viewport update can be deferred if wanted
518 };
519
520 struct SCommand_Texture_Create : public SCommand
521 {
522 SCommand_Texture_Create() :
523 SCommand(CMD_TEXTURE_CREATE) {}
524
525 // texture information
526 int m_Slot;
527
528 size_t m_Width;
529 size_t m_Height;
530 int m_Format;
531 int m_StoreFormat;
532 int m_Flags;
533 uint8_t *m_pData; // will be freed by the command processor
534 };
535
536 struct SCommand_Texture_Update : public SCommand
537 {
538 SCommand_Texture_Update() :
539 SCommand(CMD_TEXTURE_UPDATE) {}
540
541 // texture information
542 int m_Slot;
543
544 int m_X;
545 int m_Y;
546 size_t m_Width;
547 size_t m_Height;
548 int m_Format;
549 uint8_t *m_pData; // will be freed by the command processor
550 };
551
552 struct SCommand_Texture_Destroy : public SCommand
553 {
554 SCommand_Texture_Destroy() :
555 SCommand(CMD_TEXTURE_DESTROY) {}
556
557 // texture information
558 int m_Slot;
559 };
560
561 struct SCommand_TextTextures_Create : public SCommand
562 {
563 SCommand_TextTextures_Create() :
564 SCommand(CMD_TEXT_TEXTURES_CREATE) {}
565
566 // texture information
567 int m_Slot;
568 int m_SlotOutline;
569
570 size_t m_Width;
571 size_t m_Height;
572
573 uint8_t *m_pTextData; // will be freed by the command processor
574 uint8_t *m_pTextOutlineData; // will be freed by the command processor
575 };
576
577 struct SCommand_TextTextures_Destroy : public SCommand
578 {
579 SCommand_TextTextures_Destroy() :
580 SCommand(CMD_TEXT_TEXTURES_DESTROY) {}
581
582 // texture information
583 int m_Slot;
584 int m_SlotOutline;
585 };
586
587 struct SCommand_TextTexture_Update : public SCommand
588 {
589 SCommand_TextTexture_Update() :
590 SCommand(CMD_TEXT_TEXTURE_UPDATE) {}
591
592 // texture information
593 int m_Slot;
594
595 int m_X;
596 int m_Y;
597 size_t m_Width;
598 size_t m_Height;
599 uint8_t *m_pData; // will be freed by the command processor
600 };
601
602 struct SCommand_WindowCreateNtf : public CCommandBuffer::SCommand
603 {
604 SCommand_WindowCreateNtf() :
605 SCommand(CMD_WINDOW_CREATE_NTF) {}
606
607 uint32_t m_WindowId;
608 };
609
610 struct SCommand_WindowDestroyNtf : public CCommandBuffer::SCommand
611 {
612 SCommand_WindowDestroyNtf() :
613 SCommand(CMD_WINDOW_DESTROY_NTF) {}
614
615 uint32_t m_WindowId;
616 };
617
618 //
619 CCommandBuffer(unsigned CmdBufferSize, unsigned DataBufferSize) :
620 m_CmdBuffer(CmdBufferSize), m_DataBuffer(DataBufferSize), m_pCmdBufferHead(nullptr), m_pCmdBufferTail(nullptr)
621 {
622 }
623
624 void *AllocData(unsigned WantedSize)
625 {
626 return m_DataBuffer.Alloc(Requested: WantedSize);
627 }
628
629 template<class T>
630 bool AddCommandUnsafe(const T &Command)
631 {
632 // make sure that we don't do something stupid like ->AddCommand(&Cmd);
633 (void)static_cast<const SCommand *>(&Command);
634
635 // allocate and copy the command into the buffer
636 T *pCmd = (T *)m_CmdBuffer.Alloc(Requested: sizeof(*pCmd), Alignment: alignof(T));
637 if(!pCmd)
638 return false;
639 *pCmd = Command;
640 pCmd->m_pNext = nullptr;
641
642 if(m_pCmdBufferTail)
643 m_pCmdBufferTail->m_pNext = pCmd;
644 if(!m_pCmdBufferHead)
645 m_pCmdBufferHead = pCmd;
646 m_pCmdBufferTail = pCmd;
647
648 ++m_CommandCount;
649
650 return true;
651 }
652
653 SCommand *Head()
654 {
655 return m_pCmdBufferHead;
656 }
657
658 void Reset()
659 {
660 m_pCmdBufferHead = m_pCmdBufferTail = nullptr;
661 m_CmdBuffer.Reset();
662 m_DataBuffer.Reset();
663
664 m_CommandCount = 0;
665 m_RenderCallCount = 0;
666 }
667
668 void AddRenderCalls(size_t RenderCallCountToAdd)
669 {
670 m_RenderCallCount += RenderCallCountToAdd;
671 }
672};
673
674enum EGraphicsBackendErrorCodes
675{
676 GRAPHICS_BACKEND_ERROR_CODE_UNKNOWN = -1,
677 GRAPHICS_BACKEND_ERROR_CODE_NONE = 0,
678 GRAPHICS_BACKEND_ERROR_CODE_GL_CONTEXT_FAILED,
679 GRAPHICS_BACKEND_ERROR_CODE_GL_VERSION_FAILED,
680 GRAPHICS_BACKEND_ERROR_CODE_SDL_INIT_FAILED,
681 GRAPHICS_BACKEND_ERROR_CODE_SDL_SCREEN_REQUEST_FAILED,
682 GRAPHICS_BACKEND_ERROR_CODE_SDL_SCREEN_INFO_REQUEST_FAILED,
683 GRAPHICS_BACKEND_ERROR_CODE_SDL_SCREEN_RESOLUTION_REQUEST_FAILED,
684 GRAPHICS_BACKEND_ERROR_CODE_SDL_WINDOW_CREATE_FAILED,
685};
686
687// interface for the graphics backend
688// all these functions are called on the main thread
689class IGraphicsBackend
690{
691public:
692 enum
693 {
694 INITFLAG_FULLSCREEN = 1 << 0,
695 INITFLAG_VSYNC = 1 << 1,
696 INITFLAG_RESIZABLE = 1 << 2,
697 INITFLAG_BORDERLESS = 1 << 3,
698 INITFLAG_HIGHDPI = 1 << 4,
699 INITFLAG_DESKTOP_FULLSCREEN = 1 << 5,
700 };
701
702 virtual ~IGraphicsBackend() = default;
703
704 virtual int Init(const char *pName, int *pScreen, int *pWidth, int *pHeight, int *pRefreshRate, int *pFsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight, int *pCurrentWidth, int *pCurrentHeight, class IStorage *pStorage) = 0;
705 virtual int Shutdown() = 0;
706
707 virtual uint64_t TextureMemoryUsage() const = 0;
708 virtual uint64_t BufferMemoryUsage() const = 0;
709 virtual uint64_t StreamedMemoryUsage() const = 0;
710 virtual uint64_t StagingMemoryUsage() const = 0;
711
712 virtual const TTwGraphicsGpuList &GetGpus() const = 0;
713
714 virtual void GetVideoModes(CVideoMode *pModes, int MaxModes, int *pNumModes, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0;
715 virtual void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0;
716
717 virtual int GetNumScreens() const = 0;
718 virtual const char *GetScreenName(int Screen) const = 0;
719
720 virtual void Minimize() = 0;
721 virtual void Maximize() = 0;
722 virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
723 virtual bool SetWindowScreen(int Index) = 0;
724 virtual bool UpdateDisplayMode(int Index) = 0;
725 virtual int GetWindowScreen() = 0;
726 virtual int WindowActive() = 0;
727 virtual int WindowOpen() = 0;
728 virtual void SetWindowGrab(bool Grab) = 0;
729 // returns true, if the video mode changed
730 virtual bool ResizeWindow(int w, int h, int RefreshRate) = 0;
731 virtual void GetViewportSize(int &w, int &h) = 0;
732 virtual void NotifyWindow() = 0;
733
734 virtual void WindowDestroyNtf(uint32_t WindowId) = 0;
735 virtual void WindowCreateNtf(uint32_t WindowId) = 0;
736
737 virtual void RunBuffer(CCommandBuffer *pBuffer) = 0;
738 virtual void RunBufferSingleThreadedUnsafe(CCommandBuffer *pBuffer) = 0;
739 virtual bool IsIdle() const = 0;
740 virtual void WaitForIdle() = 0;
741
742 virtual bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) = 0;
743 // checks if the current values of the config are a graphics modern API
744 virtual bool IsConfigModernAPI() { return false; }
745 virtual bool UseTrianglesAsQuad() { return false; }
746 virtual bool HasTileBuffering() { return false; }
747 virtual bool HasQuadBuffering() { return false; }
748 virtual bool HasTextBuffering() { return false; }
749 virtual bool HasQuadContainerBuffering() { return false; }
750 virtual bool Uses2DTextureArrays() { return false; }
751 virtual bool HasTextureArraysSupport() { return false; }
752 virtual const char *GetErrorString() { return NULL; }
753
754 virtual const char *GetVendorString() = 0;
755 virtual const char *GetVersionString() = 0;
756 virtual const char *GetRendererString() = 0;
757
758 // be aware that this function should only be called from the graphics thread, and even then you should really know what you are doing
759 virtual TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() = 0;
760
761 virtual bool GetWarning(std::vector<std::string> &WarningStrings) = 0;
762
763 // returns true if the error msg was shown
764 virtual bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) = 0;
765};
766
767class CGraphics_Threaded : public IEngineGraphics
768{
769 enum
770 {
771 NUM_CMDBUFFERS = 2,
772
773 DRAWING_QUADS = 1,
774 DRAWING_LINES = 2,
775 DRAWING_TRIANGLES = 3
776 };
777
778 CCommandBuffer::SState m_State;
779 IGraphicsBackend *m_pBackend;
780 bool m_GLTileBufferingEnabled;
781 bool m_GLQuadBufferingEnabled;
782 bool m_GLTextBufferingEnabled;
783 bool m_GLQuadContainerBufferingEnabled;
784 bool m_GLUses2DTextureArrays;
785 bool m_GLHasTextureArraysSupport;
786 bool m_GLUseTrianglesAsQuad;
787
788 CCommandBuffer *m_apCommandBuffers[NUM_CMDBUFFERS];
789 CCommandBuffer *m_pCommandBuffer;
790 unsigned m_CurrentCommandBuffer;
791
792 //
793 class IStorage *m_pStorage;
794 class IConsole *m_pConsole;
795 class IEngine *m_pEngine;
796
797 int m_CurIndex;
798
799 CCommandBuffer::SVertex m_aVertices[CCommandBuffer::MAX_VERTICES];
800 CCommandBuffer::SVertexTex3DStream m_aVerticesTex3D[CCommandBuffer::MAX_VERTICES];
801 int m_NumVertices;
802
803 CCommandBuffer::SColor m_aColor[4];
804 CCommandBuffer::STexCoord m_aTexture[4];
805
806 bool m_RenderEnable;
807
808 float m_Rotation;
809 int m_Drawing;
810 bool m_DoScreenshot;
811 char m_aScreenshotName[IO_MAX_PATH_LENGTH];
812
813 CTextureHandle m_NullTexture;
814
815 std::vector<int> m_vTextureIndices;
816 size_t m_FirstFreeTexture;
817 int m_TextureMemoryUsage;
818
819 std::vector<uint8_t> m_vSpriteHelper;
820
821 bool m_WarnPngliteIncompatibleImages = false;
822
823 std::vector<SWarning> m_vWarnings;
824
825 // is a non full windowed (in a sense that the viewport won't include the whole window),
826 // forced viewport, so that it justifies our UI ratio needs
827 bool m_IsForcedViewport = false;
828
829 struct SVertexArrayInfo
830 {
831 SVertexArrayInfo() :
832 m_FreeIndex(-1) {}
833 // keep a reference to it, so we can free the ID
834 int m_AssociatedBufferObjectIndex;
835
836 int m_FreeIndex;
837 };
838 std::vector<SVertexArrayInfo> m_vVertexArrayInfo;
839 int m_FirstFreeVertexArrayInfo;
840
841 std::vector<int> m_vBufferObjectIndices;
842 int m_FirstFreeBufferObjectIndex;
843
844 struct SQuadContainer
845 {
846 SQuadContainer(bool AutomaticUpload = true)
847 {
848 m_vQuads.clear();
849 m_QuadBufferObjectIndex = m_QuadBufferContainerIndex = -1;
850 m_FreeIndex = -1;
851
852 m_AutomaticUpload = AutomaticUpload;
853 }
854
855 struct SQuad
856 {
857 CCommandBuffer::SVertex m_aVertices[4];
858 };
859
860 std::vector<SQuad> m_vQuads;
861
862 int m_QuadBufferObjectIndex;
863 int m_QuadBufferContainerIndex;
864
865 int m_FreeIndex;
866
867 bool m_AutomaticUpload;
868 };
869 std::vector<SQuadContainer> m_vQuadContainers;
870 int m_FirstFreeQuadContainer;
871
872 std::vector<WINDOW_RESIZE_FUNC> m_vResizeListeners;
873 std::vector<WINDOW_PROPS_CHANGED_FUNC> m_vPropChangeListeners;
874
875 void *AllocCommandBufferData(size_t AllocSize);
876
877 void AddVertices(int Count);
878 void AddVertices(int Count, CCommandBuffer::SVertex *pVertices);
879 void AddVertices(int Count, CCommandBuffer::SVertexTex3DStream *pVertices);
880
881 template<typename TName>
882 void Rotate(const CCommandBuffer::SPoint &rCenter, TName *pPoints, int NumPoints)
883 {
884 float c = std::cos(x: m_Rotation);
885 float s = std::sin(x: m_Rotation);
886 float x, y;
887 int i;
888
889 TName *pVertices = pPoints;
890 for(i = 0; i < NumPoints; i++)
891 {
892 x = pVertices[i].m_Pos.x - rCenter.x;
893 y = pVertices[i].m_Pos.y - rCenter.y;
894 pVertices[i].m_Pos.x = x * c - y * s + rCenter.x;
895 pVertices[i].m_Pos.y = x * s + y * c + rCenter.y;
896 }
897 }
898
899 template<typename TName>
900 void AddCmd(
901 TName &Cmd, std::function<bool()> FailFunc = [] { return true; })
902 {
903 if(m_pCommandBuffer->AddCommandUnsafe(Cmd))
904 return;
905
906 // kick command buffer and try again
907 KickCommandBuffer();
908
909 if(!FailFunc())
910 {
911 char aError[256];
912 str_format(buffer: aError, buffer_size: sizeof(aError), format: "graphics: failed to run fail handler for command '%s'", typeid(TName).name());
913 dbg_assert(false, aError);
914 }
915
916 if(!m_pCommandBuffer->AddCommandUnsafe(Cmd))
917 {
918 char aError[256];
919 str_format(buffer: aError, buffer_size: sizeof(aError), format: "graphics: failed to add command '%s' to command buffer", typeid(TName).name());
920 dbg_assert(false, aError);
921 }
922 }
923
924 void KickCommandBuffer();
925
926 void AddBackEndWarningIfExists();
927
928 void AdjustViewport(bool SendViewportChangeToBackend);
929
930 ivec2 m_ReadPixelPosition = ivec2(0, 0);
931 ColorRGBA *m_pReadPixelColor = nullptr;
932 void ReadPixelDirect(bool *pSwapped);
933 void ScreenshotDirect(bool *pSwapped);
934
935 int IssueInit();
936 int InitWindow();
937
938public:
939 CGraphics_Threaded();
940
941 void ClipEnable(int x, int y, int w, int h) override;
942 void ClipDisable() override;
943
944 void BlendNone() override;
945 void BlendNormal() override;
946 void BlendAdditive() override;
947
948 void WrapNormal() override;
949 void WrapClamp() override;
950
951 uint64_t TextureMemoryUsage() const override;
952 uint64_t BufferMemoryUsage() const override;
953 uint64_t StreamedMemoryUsage() const override;
954 uint64_t StagingMemoryUsage() const override;
955
956 const TTwGraphicsGpuList &GetGpus() const override;
957
958 void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) override;
959 void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY) override;
960
961 void LinesBegin() override;
962 void LinesEnd() override;
963 void LinesDraw(const CLineItem *pArray, int Num) override;
964
965 IGraphics::CTextureHandle FindFreeTextureIndex();
966 void FreeTextureIndex(CTextureHandle *pIndex);
967 int UnloadTexture(IGraphics::CTextureHandle *pIndex) override;
968 IGraphics::CTextureHandle LoadTextureRaw(const CImageInfo &Image, int Flags, const char *pTexName = nullptr) override;
969 IGraphics::CTextureHandle LoadTextureRawMove(CImageInfo &Image, int Flags, const char *pTexName = nullptr) override;
970 int LoadTextureRawSub(IGraphics::CTextureHandle TextureId, int x, int y, const CImageInfo &Image) override;
971 IGraphics::CTextureHandle NullTexture() const override;
972
973 bool LoadTextTextures(size_t Width, size_t Height, CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture, uint8_t *pTextData, uint8_t *pTextOutlineData) override;
974 bool UnloadTextTextures(CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture) override;
975 bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, const uint8_t *pData) override;
976
977 CTextureHandle LoadSpriteTextureImpl(const CImageInfo &FromImageInfo, int x, int y, size_t w, size_t h, const char *pName);
978 CTextureHandle LoadSpriteTexture(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) override;
979
980 bool IsImageSubFullyTransparent(const CImageInfo &FromImageInfo, int x, int y, int w, int h) override;
981 bool IsSpriteTextureFullyTransparent(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) override;
982
983 // simple uncompressed RGBA loaders
984 IGraphics::CTextureHandle LoadTexture(const char *pFilename, int StorageType, int Flags = 0) override;
985 bool LoadPng(CImageInfo &Image, const char *pFilename, int StorageType) override;
986
987 bool CheckImageDivisibility(const char *pFileName, CImageInfo &Img, int DivX, int DivY, bool AllowResize) override;
988 bool IsImageFormatRGBA(const char *pFileName, CImageInfo &Img) override;
989
990 void CopyTextureBufferSub(uint8_t *pDestBuffer, const CImageInfo &SourceImage, size_t SubOffsetX, size_t SubOffsetY, size_t SubCopyWidth, size_t SubCopyHeight) override;
991 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) override;
992
993 void TextureSet(CTextureHandle TextureId) override;
994
995 void Clear(float r, float g, float b, bool ForceClearNow = false) override;
996
997 void QuadsBegin() override;
998 void QuadsEnd() override;
999 void QuadsTex3DBegin() override;
1000 void QuadsTex3DEnd() override;
1001 void TrianglesBegin() override;
1002 void TrianglesEnd() override;
1003 void QuadsEndKeepVertices() override;
1004 void QuadsDrawCurrentVertices(bool KeepVertices = true) override;
1005 void QuadsSetRotation(float Angle) override;
1006
1007 template<typename TName>
1008 void SetColor(TName *pVertex, int ColorIndex)
1009 {
1010 TName *pVert = pVertex;
1011 pVert->m_Color = m_aColor[ColorIndex];
1012 }
1013
1014 void SetColorVertex(const CColorVertex *pArray, size_t Num) override;
1015 void SetColor(float r, float g, float b, float a) override;
1016 void SetColor(ColorRGBA Color) override;
1017 void SetColor4(ColorRGBA TopLeft, ColorRGBA TopRight, ColorRGBA BottomLeft, ColorRGBA BottomRight) override;
1018
1019 // go through all vertices and change their color (only works for quads)
1020 void ChangeColorOfCurrentQuadVertices(float r, float g, float b, float a) override;
1021 void ChangeColorOfQuadVertices(size_t QuadOffset, unsigned char r, unsigned char g, unsigned char b, unsigned char a) override;
1022
1023 void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV) override;
1024 void QuadsSetSubsetFree(
1025 float x0, float y0, float x1, float y1,
1026 float x2, float y2, float x3, float y3, int Index = -1) override;
1027
1028 void QuadsDraw(CQuadItem *pArray, int Num) override;
1029
1030 template<typename TName>
1031 void QuadsDrawTLImpl(TName *pVertices, const CQuadItem *pArray, int Num)
1032 {
1033 CCommandBuffer::SPoint Center;
1034
1035 dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawTL without begin");
1036
1037 if(g_Config.m_GfxQuadAsTriangle && !m_GLUseTrianglesAsQuad)
1038 {
1039 for(int i = 0; i < Num; ++i)
1040 {
1041 // first triangle
1042 pVertices[m_NumVertices + 6 * i].m_Pos.x = pArray[i].m_X;
1043 pVertices[m_NumVertices + 6 * i].m_Pos.y = pArray[i].m_Y;
1044 pVertices[m_NumVertices + 6 * i].m_Tex = m_aTexture[0];
1045 SetColor(&pVertices[m_NumVertices + 6 * i], 0);
1046
1047 pVertices[m_NumVertices + 6 * i + 1].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1048 pVertices[m_NumVertices + 6 * i + 1].m_Pos.y = pArray[i].m_Y;
1049 pVertices[m_NumVertices + 6 * i + 1].m_Tex = m_aTexture[1];
1050 SetColor(&pVertices[m_NumVertices + 6 * i + 1], 1);
1051
1052 pVertices[m_NumVertices + 6 * i + 2].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1053 pVertices[m_NumVertices + 6 * i + 2].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1054 pVertices[m_NumVertices + 6 * i + 2].m_Tex = m_aTexture[2];
1055 SetColor(&pVertices[m_NumVertices + 6 * i + 2], 2);
1056
1057 // second triangle
1058 pVertices[m_NumVertices + 6 * i + 3].m_Pos.x = pArray[i].m_X;
1059 pVertices[m_NumVertices + 6 * i + 3].m_Pos.y = pArray[i].m_Y;
1060 pVertices[m_NumVertices + 6 * i + 3].m_Tex = m_aTexture[0];
1061 SetColor(&pVertices[m_NumVertices + 6 * i + 3], 0);
1062
1063 pVertices[m_NumVertices + 6 * i + 4].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1064 pVertices[m_NumVertices + 6 * i + 4].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1065 pVertices[m_NumVertices + 6 * i + 4].m_Tex = m_aTexture[2];
1066 SetColor(&pVertices[m_NumVertices + 6 * i + 4], 2);
1067
1068 pVertices[m_NumVertices + 6 * i + 5].m_Pos.x = pArray[i].m_X;
1069 pVertices[m_NumVertices + 6 * i + 5].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1070 pVertices[m_NumVertices + 6 * i + 5].m_Tex = m_aTexture[3];
1071 SetColor(&pVertices[m_NumVertices + 6 * i + 5], 3);
1072
1073 if(m_Rotation != 0)
1074 {
1075 Center.x = pArray[i].m_X + pArray[i].m_Width / 2;
1076 Center.y = pArray[i].m_Y + pArray[i].m_Height / 2;
1077
1078 Rotate(Center, &pVertices[m_NumVertices + 6 * i], 6);
1079 }
1080 }
1081
1082 AddVertices(3 * 2 * Num, pVertices);
1083 }
1084 else
1085 {
1086 for(int i = 0; i < Num; ++i)
1087 {
1088 pVertices[m_NumVertices + 4 * i].m_Pos.x = pArray[i].m_X;
1089 pVertices[m_NumVertices + 4 * i].m_Pos.y = pArray[i].m_Y;
1090 pVertices[m_NumVertices + 4 * i].m_Tex = m_aTexture[0];
1091 SetColor(&pVertices[m_NumVertices + 4 * i], 0);
1092
1093 pVertices[m_NumVertices + 4 * i + 1].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1094 pVertices[m_NumVertices + 4 * i + 1].m_Pos.y = pArray[i].m_Y;
1095 pVertices[m_NumVertices + 4 * i + 1].m_Tex = m_aTexture[1];
1096 SetColor(&pVertices[m_NumVertices + 4 * i + 1], 1);
1097
1098 pVertices[m_NumVertices + 4 * i + 2].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1099 pVertices[m_NumVertices + 4 * i + 2].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1100 pVertices[m_NumVertices + 4 * i + 2].m_Tex = m_aTexture[2];
1101 SetColor(&pVertices[m_NumVertices + 4 * i + 2], 2);
1102
1103 pVertices[m_NumVertices + 4 * i + 3].m_Pos.x = pArray[i].m_X;
1104 pVertices[m_NumVertices + 4 * i + 3].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1105 pVertices[m_NumVertices + 4 * i + 3].m_Tex = m_aTexture[3];
1106 SetColor(&pVertices[m_NumVertices + 4 * i + 3], 3);
1107
1108 if(m_Rotation != 0)
1109 {
1110 Center.x = pArray[i].m_X + pArray[i].m_Width / 2;
1111 Center.y = pArray[i].m_Y + pArray[i].m_Height / 2;
1112
1113 Rotate(Center, &pVertices[m_NumVertices + 4 * i], 4);
1114 }
1115 }
1116
1117 AddVertices(4 * Num, pVertices);
1118 }
1119 }
1120
1121 void QuadsDrawTL(const CQuadItem *pArray, int Num) override;
1122
1123 void QuadsTex3DDrawTL(const CQuadItem *pArray, int Num) override;
1124
1125 void QuadsDrawFreeform(const CFreeformItem *pArray, int Num) override;
1126 void QuadsText(float x, float y, float Size, const char *pText) override;
1127
1128 void DrawRectExt(float x, float y, float w, float h, float r, int Corners) override;
1129 void DrawRectExt4(float x, float y, float w, float h, ColorRGBA ColorTopLeft, ColorRGBA ColorTopRight, ColorRGBA ColorBottomLeft, ColorRGBA ColorBottomRight, float r, int Corners) override;
1130 int CreateRectQuadContainer(float x, float y, float w, float h, float r, int Corners) override;
1131 void DrawRect(float x, float y, float w, float h, ColorRGBA Color, int Corners, float Rounding) override;
1132 void DrawRect4(float x, float y, float w, float h, ColorRGBA ColorTopLeft, ColorRGBA ColorTopRight, ColorRGBA ColorBottomLeft, ColorRGBA ColorBottomRight, int Corners, float Rounding) override;
1133 void DrawCircle(float CenterX, float CenterY, float Radius, int Segments) override;
1134
1135 const GL_STexCoord *GetCurTextureCoordinates() override
1136 {
1137 return m_aTexture;
1138 }
1139
1140 const GL_SColor *GetCurColor() override
1141 {
1142 return m_aColor;
1143 }
1144
1145 int CreateQuadContainer(bool AutomaticUpload = true) override;
1146 void QuadContainerChangeAutomaticUpload(int ContainerIndex, bool AutomaticUpload) override;
1147 void QuadContainerUpload(int ContainerIndex) override;
1148 int QuadContainerAddQuads(int ContainerIndex, CQuadItem *pArray, int Num) override;
1149 int QuadContainerAddQuads(int ContainerIndex, CFreeformItem *pArray, int Num) override;
1150 void QuadContainerReset(int ContainerIndex) override;
1151 void DeleteQuadContainer(int &ContainerIndex) override;
1152 void RenderQuadContainer(int ContainerIndex, int QuadDrawNum) override;
1153 void RenderQuadContainer(int ContainerIndex, int QuadOffset, int QuadDrawNum, bool ChangeWrapMode = true) override;
1154 void RenderQuadContainerEx(int ContainerIndex, int QuadOffset, int QuadDrawNum, float X, float Y, float ScaleX = 1.f, float ScaleY = 1.f) override;
1155 void RenderQuadContainerAsSprite(int ContainerIndex, int QuadOffset, float X, float Y, float ScaleX = 1.f, float ScaleY = 1.f) override;
1156 void RenderQuadContainerAsSpriteMultiple(int ContainerIndex, int QuadOffset, int DrawCount, SRenderSpriteInfo *pRenderInfo) override;
1157
1158 template<typename TName>
1159 void FlushVerticesImpl(bool KeepVertices, int &PrimType, size_t &PrimCount, size_t &NumVerts, TName &Command, size_t VertSize)
1160 {
1161 Command.m_pVertices = nullptr;
1162 if(m_NumVertices == 0)
1163 return;
1164
1165 NumVerts = m_NumVertices;
1166
1167 if(!KeepVertices)
1168 m_NumVertices = 0;
1169
1170 if(m_Drawing == DRAWING_QUADS)
1171 {
1172 if(g_Config.m_GfxQuadAsTriangle && !m_GLUseTrianglesAsQuad)
1173 {
1174 PrimType = CCommandBuffer::PRIMTYPE_TRIANGLES;
1175 PrimCount = NumVerts / 3;
1176 }
1177 else
1178 {
1179 PrimType = CCommandBuffer::PRIMTYPE_QUADS;
1180 PrimCount = NumVerts / 4;
1181 }
1182 }
1183 else if(m_Drawing == DRAWING_LINES)
1184 {
1185 PrimType = CCommandBuffer::PRIMTYPE_LINES;
1186 PrimCount = NumVerts / 2;
1187 }
1188 else if(m_Drawing == DRAWING_TRIANGLES)
1189 {
1190 PrimType = CCommandBuffer::PRIMTYPE_TRIANGLES;
1191 PrimCount = NumVerts / 3;
1192 }
1193 else
1194 return;
1195
1196 Command.m_pVertices = (decltype(Command.m_pVertices))AllocCommandBufferData(AllocSize: VertSize * NumVerts);
1197 Command.m_State = m_State;
1198
1199 Command.m_PrimType = PrimType;
1200 Command.m_PrimCount = PrimCount;
1201
1202 AddCmd(Command, [&] {
1203 Command.m_pVertices = (decltype(Command.m_pVertices))m_pCommandBuffer->AllocData(WantedSize: VertSize * NumVerts);
1204 return Command.m_pVertices != nullptr;
1205 });
1206
1207 m_pCommandBuffer->AddRenderCalls(RenderCallCountToAdd: 1);
1208 }
1209
1210 void FlushVertices(bool KeepVertices = false) override;
1211 void FlushVerticesTex3D() override;
1212
1213 void RenderTileLayer(int BufferContainerIndex, const ColorRGBA &Color, char **pOffsets, unsigned int *pIndicedVertexDrawNum, size_t NumIndicesOffset) override;
1214 virtual void RenderBorderTiles(int BufferContainerIndex, const ColorRGBA &Color, char *pIndexBufferOffset, const vec2 &Offset, const vec2 &Scale, uint32_t DrawNum) override;
1215 void RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, size_t QuadNum, int QuadOffset) override;
1216 void RenderText(int BufferContainerIndex, int TextQuadNum, int TextureSize, int TextureTextIndex, int TextureTextOutlineIndex, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor) override;
1217
1218 // modern GL functions
1219 int CreateBufferObject(size_t UploadDataSize, void *pUploadData, int CreateFlags, bool IsMovedPointer = false) override;
1220 void RecreateBufferObject(int BufferIndex, size_t UploadDataSize, void *pUploadData, int CreateFlags, bool IsMovedPointer = false) override;
1221 void UpdateBufferObjectInternal(int BufferIndex, size_t UploadDataSize, void *pUploadData, void *pOffset, bool IsMovedPointer = false);
1222 void CopyBufferObjectInternal(int WriteBufferIndex, int ReadBufferIndex, size_t WriteOffset, size_t ReadOffset, size_t CopyDataSize);
1223 void DeleteBufferObject(int BufferIndex) override;
1224
1225 int CreateBufferContainer(SBufferContainerInfo *pContainerInfo) override;
1226 // destroying all buffer objects means, that all referenced VBOs are destroyed automatically, so the user does not need to save references to them
1227 void DeleteBufferContainer(int &ContainerIndex, bool DestroyAllBO = true) override;
1228 void UpdateBufferContainerInternal(int ContainerIndex, SBufferContainerInfo *pContainerInfo);
1229 void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) override;
1230
1231 int GetNumScreens() const override;
1232 const char *GetScreenName(int Screen) const override;
1233
1234 void Minimize() override;
1235 void Maximize() override;
1236 void WarnPngliteIncompatibleImages(bool Warn) override;
1237 void SetWindowParams(int FullscreenMode, bool IsBorderless) override;
1238 bool SetWindowScreen(int Index) override;
1239 void Move(int x, int y) override;
1240 bool Resize(int w, int h, int RefreshRate) override;
1241 void ResizeToScreen() override;
1242 void GotResized(int w, int h, int RefreshRate) override;
1243 void UpdateViewport(int X, int Y, int W, int H, bool ByResize) override;
1244 void AddWindowResizeListener(WINDOW_RESIZE_FUNC pFunc) override;
1245 void AddWindowPropChangeListener(WINDOW_PROPS_CHANGED_FUNC pFunc) override;
1246 int GetWindowScreen() override;
1247
1248 void WindowDestroyNtf(uint32_t WindowId) override;
1249 void WindowCreateNtf(uint32_t WindowId) override;
1250
1251 int WindowActive() override;
1252 int WindowOpen() override;
1253
1254 void SetWindowGrab(bool Grab) override;
1255 void NotifyWindow() override;
1256
1257 int Init() override;
1258 void Shutdown() override;
1259
1260 void ReadPixel(ivec2 Position, ColorRGBA *pColor) override;
1261 void TakeScreenshot(const char *pFilename) override;
1262 void TakeCustomScreenshot(const char *pFilename) override;
1263 void Swap() override;
1264 bool SetVSync(bool State) override;
1265 bool SetMultiSampling(uint32_t ReqMultiSamplingCount, uint32_t &MultiSamplingCountBackend) override;
1266
1267 int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) override;
1268 void GetCurrentVideoMode(CVideoMode &CurMode, int Screen) override;
1269
1270 virtual int GetDesktopScreenWidth() const { return g_Config.m_GfxDesktopWidth; }
1271 virtual int GetDesktopScreenHeight() const { return g_Config.m_GfxDesktopHeight; }
1272
1273 // synchronization
1274 void InsertSignal(CSemaphore *pSemaphore) override;
1275 bool IsIdle() const override;
1276 void WaitForIdle() override;
1277
1278 SWarning *GetCurWarning() override;
1279 bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) override;
1280 bool IsBackendInitialized() override;
1281
1282 bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) override { return m_pBackend->GetDriverVersion(DriverAgeType, Major, Minor, Patch, pName, BackendType); }
1283 bool IsConfigModernAPI() override { return m_pBackend->IsConfigModernAPI(); }
1284 bool IsTileBufferingEnabled() override { return m_GLTileBufferingEnabled; }
1285 bool IsQuadBufferingEnabled() override { return m_GLQuadBufferingEnabled; }
1286 bool IsTextBufferingEnabled() override { return m_GLTextBufferingEnabled; }
1287 bool IsQuadContainerBufferingEnabled() override { return m_GLQuadContainerBufferingEnabled; }
1288 bool Uses2DTextureArrays() override { return m_GLUses2DTextureArrays; }
1289 bool HasTextureArraysSupport() override { return m_GLHasTextureArraysSupport; }
1290
1291 const char *GetVendorString() override;
1292 const char *GetVersionString() override;
1293 const char *GetRendererString() override;
1294
1295 TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() override;
1296};
1297
1298typedef std::function<const char *(const char *, const char *)> TTranslateFunc;
1299extern IGraphicsBackend *CreateGraphicsBackend(TTranslateFunc &&TranslateFunc);
1300
1301#endif // ENGINE_CLIENT_GRAPHICS_THREADED_H
1302