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_Flags;
531 // data must be in RGBA format
532 uint8_t *m_pData; // will be freed by the command processor
533 };
534
535 struct SCommand_Texture_Update : public SCommand
536 {
537 SCommand_Texture_Update() :
538 SCommand(CMD_TEXTURE_UPDATE) {}
539
540 // texture information
541 int m_Slot;
542
543 int m_X;
544 int m_Y;
545 size_t m_Width;
546 size_t m_Height;
547 // data must be in RGBA format
548 uint8_t *m_pData; // will be freed by the command processor
549 };
550
551 struct SCommand_Texture_Destroy : public SCommand
552 {
553 SCommand_Texture_Destroy() :
554 SCommand(CMD_TEXTURE_DESTROY) {}
555
556 // texture information
557 int m_Slot;
558 };
559
560 struct SCommand_TextTextures_Create : public SCommand
561 {
562 SCommand_TextTextures_Create() :
563 SCommand(CMD_TEXT_TEXTURES_CREATE) {}
564
565 // texture information
566 int m_Slot;
567 int m_SlotOutline;
568
569 size_t m_Width;
570 size_t m_Height;
571
572 uint8_t *m_pTextData; // will be freed by the command processor
573 uint8_t *m_pTextOutlineData; // will be freed by the command processor
574 };
575
576 struct SCommand_TextTextures_Destroy : public SCommand
577 {
578 SCommand_TextTextures_Destroy() :
579 SCommand(CMD_TEXT_TEXTURES_DESTROY) {}
580
581 // texture information
582 int m_Slot;
583 int m_SlotOutline;
584 };
585
586 struct SCommand_TextTexture_Update : public SCommand
587 {
588 SCommand_TextTexture_Update() :
589 SCommand(CMD_TEXT_TEXTURE_UPDATE) {}
590
591 // texture information
592 int m_Slot;
593
594 int m_X;
595 int m_Y;
596 size_t m_Width;
597 size_t m_Height;
598 uint8_t *m_pData; // will be freed by the command processor
599 };
600
601 struct SCommand_WindowCreateNtf : public CCommandBuffer::SCommand
602 {
603 SCommand_WindowCreateNtf() :
604 SCommand(CMD_WINDOW_CREATE_NTF) {}
605
606 uint32_t m_WindowId;
607 };
608
609 struct SCommand_WindowDestroyNtf : public CCommandBuffer::SCommand
610 {
611 SCommand_WindowDestroyNtf() :
612 SCommand(CMD_WINDOW_DESTROY_NTF) {}
613
614 uint32_t m_WindowId;
615 };
616
617 //
618 CCommandBuffer(unsigned CmdBufferSize, unsigned DataBufferSize) :
619 m_CmdBuffer(CmdBufferSize), m_DataBuffer(DataBufferSize), m_pCmdBufferHead(nullptr), m_pCmdBufferTail(nullptr)
620 {
621 }
622
623 void *AllocData(unsigned WantedSize)
624 {
625 return m_DataBuffer.Alloc(Requested: WantedSize);
626 }
627
628 template<class T>
629 bool AddCommandUnsafe(const T &Command)
630 {
631 // make sure that we don't do something stupid like ->AddCommand(&Cmd);
632 (void)static_cast<const SCommand *>(&Command);
633
634 // allocate and copy the command into the buffer
635 T *pCmd = (T *)m_CmdBuffer.Alloc(Requested: sizeof(*pCmd), Alignment: alignof(T));
636 if(!pCmd)
637 return false;
638 *pCmd = Command;
639 pCmd->m_pNext = nullptr;
640
641 if(m_pCmdBufferTail)
642 m_pCmdBufferTail->m_pNext = pCmd;
643 if(!m_pCmdBufferHead)
644 m_pCmdBufferHead = pCmd;
645 m_pCmdBufferTail = pCmd;
646
647 ++m_CommandCount;
648
649 return true;
650 }
651
652 SCommand *Head()
653 {
654 return m_pCmdBufferHead;
655 }
656
657 void Reset()
658 {
659 m_pCmdBufferHead = m_pCmdBufferTail = nullptr;
660 m_CmdBuffer.Reset();
661 m_DataBuffer.Reset();
662
663 m_CommandCount = 0;
664 m_RenderCallCount = 0;
665 }
666
667 void AddRenderCalls(size_t RenderCallCountToAdd)
668 {
669 m_RenderCallCount += RenderCallCountToAdd;
670 }
671};
672
673enum EGraphicsBackendErrorCodes
674{
675 GRAPHICS_BACKEND_ERROR_CODE_UNKNOWN = -1,
676 GRAPHICS_BACKEND_ERROR_CODE_NONE = 0,
677 GRAPHICS_BACKEND_ERROR_CODE_GL_CONTEXT_FAILED,
678 GRAPHICS_BACKEND_ERROR_CODE_GL_VERSION_FAILED,
679 GRAPHICS_BACKEND_ERROR_CODE_SDL_INIT_FAILED,
680 GRAPHICS_BACKEND_ERROR_CODE_SDL_SCREEN_REQUEST_FAILED,
681 GRAPHICS_BACKEND_ERROR_CODE_SDL_SCREEN_INFO_REQUEST_FAILED,
682 GRAPHICS_BACKEND_ERROR_CODE_SDL_SCREEN_RESOLUTION_REQUEST_FAILED,
683 GRAPHICS_BACKEND_ERROR_CODE_SDL_WINDOW_CREATE_FAILED,
684};
685
686// interface for the graphics backend
687// all these functions are called on the main thread
688class IGraphicsBackend
689{
690public:
691 enum
692 {
693 INITFLAG_FULLSCREEN = 1 << 0,
694 INITFLAG_VSYNC = 1 << 1,
695 INITFLAG_RESIZABLE = 1 << 2,
696 INITFLAG_BORDERLESS = 1 << 3,
697 INITFLAG_HIGHDPI = 1 << 4,
698 INITFLAG_DESKTOP_FULLSCREEN = 1 << 5,
699 };
700
701 virtual ~IGraphicsBackend() = default;
702
703 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;
704 virtual int Shutdown() = 0;
705
706 virtual uint64_t TextureMemoryUsage() const = 0;
707 virtual uint64_t BufferMemoryUsage() const = 0;
708 virtual uint64_t StreamedMemoryUsage() const = 0;
709 virtual uint64_t StagingMemoryUsage() const = 0;
710
711 virtual const TTwGraphicsGpuList &GetGpus() const = 0;
712
713 virtual void GetVideoModes(CVideoMode *pModes, int MaxModes, int *pNumModes, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0;
714 virtual void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0;
715
716 virtual int GetNumScreens() const = 0;
717 virtual const char *GetScreenName(int Screen) const = 0;
718
719 virtual void Minimize() = 0;
720 virtual void Maximize() = 0;
721 virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
722 virtual bool SetWindowScreen(int Index) = 0;
723 virtual bool UpdateDisplayMode(int Index) = 0;
724 virtual int GetWindowScreen() = 0;
725 virtual int WindowActive() = 0;
726 virtual int WindowOpen() = 0;
727 virtual void SetWindowGrab(bool Grab) = 0;
728 // returns true, if the video mode changed
729 virtual bool ResizeWindow(int w, int h, int RefreshRate) = 0;
730 virtual void GetViewportSize(int &w, int &h) = 0;
731 virtual void NotifyWindow() = 0;
732
733 virtual void WindowDestroyNtf(uint32_t WindowId) = 0;
734 virtual void WindowCreateNtf(uint32_t WindowId) = 0;
735
736 virtual void RunBuffer(CCommandBuffer *pBuffer) = 0;
737 virtual void RunBufferSingleThreadedUnsafe(CCommandBuffer *pBuffer) = 0;
738 virtual bool IsIdle() const = 0;
739 virtual void WaitForIdle() = 0;
740
741 virtual bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) = 0;
742 // checks if the current values of the config are a graphics modern API
743 virtual bool IsConfigModernAPI() { return false; }
744 virtual bool UseTrianglesAsQuad() { return false; }
745 virtual bool HasTileBuffering() { return false; }
746 virtual bool HasQuadBuffering() { return false; }
747 virtual bool HasTextBuffering() { return false; }
748 virtual bool HasQuadContainerBuffering() { return false; }
749 virtual bool Uses2DTextureArrays() { return false; }
750 virtual bool HasTextureArraysSupport() { return false; }
751 virtual const char *GetErrorString() { return NULL; }
752
753 virtual const char *GetVendorString() = 0;
754 virtual const char *GetVersionString() = 0;
755 virtual const char *GetRendererString() = 0;
756
757 // be aware that this function should only be called from the graphics thread, and even then you should really know what you are doing
758 virtual TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() = 0;
759
760 virtual bool GetWarning(std::vector<std::string> &WarningStrings) = 0;
761
762 // returns true if the error msg was shown
763 virtual bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) = 0;
764};
765
766class CGraphics_Threaded : public IEngineGraphics
767{
768 enum
769 {
770 NUM_CMDBUFFERS = 2,
771
772 DRAWING_QUADS = 1,
773 DRAWING_LINES = 2,
774 DRAWING_TRIANGLES = 3
775 };
776
777 CCommandBuffer::SState m_State;
778 IGraphicsBackend *m_pBackend;
779 bool m_GLTileBufferingEnabled;
780 bool m_GLQuadBufferingEnabled;
781 bool m_GLTextBufferingEnabled;
782 bool m_GLQuadContainerBufferingEnabled;
783 bool m_GLUses2DTextureArrays;
784 bool m_GLHasTextureArraysSupport;
785 bool m_GLUseTrianglesAsQuad;
786
787 CCommandBuffer *m_apCommandBuffers[NUM_CMDBUFFERS];
788 CCommandBuffer *m_pCommandBuffer;
789 unsigned m_CurrentCommandBuffer;
790
791 //
792 class IStorage *m_pStorage;
793 class IConsole *m_pConsole;
794 class IEngine *m_pEngine;
795
796 int m_CurIndex;
797
798 CCommandBuffer::SVertex m_aVertices[CCommandBuffer::MAX_VERTICES];
799 CCommandBuffer::SVertexTex3DStream m_aVerticesTex3D[CCommandBuffer::MAX_VERTICES];
800 int m_NumVertices;
801
802 CCommandBuffer::SColor m_aColor[4];
803 CCommandBuffer::STexCoord m_aTexture[4];
804
805 bool m_RenderEnable;
806
807 float m_Rotation;
808 int m_Drawing;
809 bool m_DoScreenshot;
810 char m_aScreenshotName[IO_MAX_PATH_LENGTH];
811
812 CTextureHandle m_NullTexture;
813
814 std::vector<int> m_vTextureIndices;
815 size_t m_FirstFreeTexture;
816 int m_TextureMemoryUsage;
817
818 std::vector<uint8_t> m_vSpriteHelper;
819
820 bool m_WarnPngliteIncompatibleImages = false;
821
822 std::vector<SWarning> m_vWarnings;
823
824 // is a non full windowed (in a sense that the viewport won't include the whole window),
825 // forced viewport, so that it justifies our UI ratio needs
826 bool m_IsForcedViewport = false;
827
828 struct SVertexArrayInfo
829 {
830 SVertexArrayInfo() :
831 m_FreeIndex(-1) {}
832 // keep a reference to it, so we can free the ID
833 int m_AssociatedBufferObjectIndex;
834
835 int m_FreeIndex;
836 };
837 std::vector<SVertexArrayInfo> m_vVertexArrayInfo;
838 int m_FirstFreeVertexArrayInfo;
839
840 std::vector<int> m_vBufferObjectIndices;
841 int m_FirstFreeBufferObjectIndex;
842
843 struct SQuadContainer
844 {
845 SQuadContainer(bool AutomaticUpload = true)
846 {
847 m_vQuads.clear();
848 m_QuadBufferObjectIndex = m_QuadBufferContainerIndex = -1;
849 m_FreeIndex = -1;
850
851 m_AutomaticUpload = AutomaticUpload;
852 }
853
854 struct SQuad
855 {
856 CCommandBuffer::SVertex m_aVertices[4];
857 };
858
859 std::vector<SQuad> m_vQuads;
860
861 int m_QuadBufferObjectIndex;
862 int m_QuadBufferContainerIndex;
863
864 int m_FreeIndex;
865
866 bool m_AutomaticUpload;
867 };
868 std::vector<SQuadContainer> m_vQuadContainers;
869 int m_FirstFreeQuadContainer;
870
871 std::vector<WINDOW_RESIZE_FUNC> m_vResizeListeners;
872 std::vector<WINDOW_PROPS_CHANGED_FUNC> m_vPropChangeListeners;
873
874 void *AllocCommandBufferData(size_t AllocSize);
875
876 void AddVertices(int Count);
877 void AddVertices(int Count, CCommandBuffer::SVertex *pVertices);
878 void AddVertices(int Count, CCommandBuffer::SVertexTex3DStream *pVertices);
879
880 template<typename TName>
881 void Rotate(const CCommandBuffer::SPoint &rCenter, TName *pPoints, int NumPoints)
882 {
883 float c = std::cos(x: m_Rotation);
884 float s = std::sin(x: m_Rotation);
885 float x, y;
886 int i;
887
888 TName *pVertices = pPoints;
889 for(i = 0; i < NumPoints; i++)
890 {
891 x = pVertices[i].m_Pos.x - rCenter.x;
892 y = pVertices[i].m_Pos.y - rCenter.y;
893 pVertices[i].m_Pos.x = x * c - y * s + rCenter.x;
894 pVertices[i].m_Pos.y = x * s + y * c + rCenter.y;
895 }
896 }
897
898 template<typename TName>
899 void AddCmd(
900 TName &Cmd, std::function<bool()> FailFunc = [] { return true; })
901 {
902 if(m_pCommandBuffer->AddCommandUnsafe(Cmd))
903 return;
904
905 // kick command buffer and try again
906 KickCommandBuffer();
907
908 if(!FailFunc())
909 {
910 char aError[256];
911 str_format(buffer: aError, buffer_size: sizeof(aError), format: "graphics: failed to run fail handler for command '%s'", typeid(TName).name());
912 dbg_assert(false, aError);
913 }
914
915 if(!m_pCommandBuffer->AddCommandUnsafe(Cmd))
916 {
917 char aError[256];
918 str_format(buffer: aError, buffer_size: sizeof(aError), format: "graphics: failed to add command '%s' to command buffer", typeid(TName).name());
919 dbg_assert(false, aError);
920 }
921 }
922
923 void KickCommandBuffer();
924
925 void AddBackEndWarningIfExists();
926
927 void AdjustViewport(bool SendViewportChangeToBackend);
928
929 ivec2 m_ReadPixelPosition = ivec2(0, 0);
930 ColorRGBA *m_pReadPixelColor = nullptr;
931 void ReadPixelDirect(bool *pSwapped);
932 void ScreenshotDirect(bool *pSwapped);
933
934 int IssueInit();
935 int InitWindow();
936
937public:
938 CGraphics_Threaded();
939
940 void ClipEnable(int x, int y, int w, int h) override;
941 void ClipDisable() override;
942
943 void BlendNone() override;
944 void BlendNormal() override;
945 void BlendAdditive() override;
946
947 void WrapNormal() override;
948 void WrapClamp() override;
949
950 uint64_t TextureMemoryUsage() const override;
951 uint64_t BufferMemoryUsage() const override;
952 uint64_t StreamedMemoryUsage() const override;
953 uint64_t StagingMemoryUsage() const override;
954
955 const TTwGraphicsGpuList &GetGpus() const override;
956
957 void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) override;
958 void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY) override;
959
960 void LinesBegin() override;
961 void LinesEnd() override;
962 void LinesDraw(const CLineItem *pArray, int Num) override;
963
964 IGraphics::CTextureHandle FindFreeTextureIndex();
965 void FreeTextureIndex(CTextureHandle *pIndex);
966 int UnloadTexture(IGraphics::CTextureHandle *pIndex) override;
967 IGraphics::CTextureHandle LoadTextureRaw(const CImageInfo &Image, int Flags, const char *pTexName = nullptr) override;
968 IGraphics::CTextureHandle LoadTextureRawMove(CImageInfo &Image, int Flags, const char *pTexName = nullptr) override;
969 int LoadTextureRawSub(IGraphics::CTextureHandle TextureId, int x, int y, const CImageInfo &Image) override;
970 IGraphics::CTextureHandle NullTexture() const override;
971
972 bool LoadTextTextures(size_t Width, size_t Height, CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture, uint8_t *pTextData, uint8_t *pTextOutlineData) override;
973 bool UnloadTextTextures(CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture) override;
974 bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, const uint8_t *pData) override;
975
976 CTextureHandle LoadSpriteTextureImpl(const CImageInfo &FromImageInfo, int x, int y, size_t w, size_t h, const char *pName);
977 CTextureHandle LoadSpriteTexture(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) override;
978
979 bool IsImageSubFullyTransparent(const CImageInfo &FromImageInfo, int x, int y, int w, int h) override;
980 bool IsSpriteTextureFullyTransparent(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) override;
981
982 // simple uncompressed RGBA loaders
983 IGraphics::CTextureHandle LoadTexture(const char *pFilename, int StorageType, int Flags = 0) override;
984 bool LoadPng(CImageInfo &Image, const char *pFilename, int StorageType) override;
985
986 bool CheckImageDivisibility(const char *pFileName, CImageInfo &Img, int DivX, int DivY, bool AllowResize) override;
987 bool IsImageFormatRGBA(const char *pFileName, CImageInfo &Img) override;
988
989 void CopyTextureBufferSub(uint8_t *pDestBuffer, const CImageInfo &SourceImage, size_t SubOffsetX, size_t SubOffsetY, size_t SubCopyWidth, size_t SubCopyHeight) override;
990 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;
991
992 void TextureSet(CTextureHandle TextureId) override;
993
994 void Clear(float r, float g, float b, bool ForceClearNow = false) override;
995
996 void QuadsBegin() override;
997 void QuadsEnd() override;
998 void QuadsTex3DBegin() override;
999 void QuadsTex3DEnd() override;
1000 void TrianglesBegin() override;
1001 void TrianglesEnd() override;
1002 void QuadsEndKeepVertices() override;
1003 void QuadsDrawCurrentVertices(bool KeepVertices = true) override;
1004 void QuadsSetRotation(float Angle) override;
1005
1006 template<typename TName>
1007 void SetColor(TName *pVertex, int ColorIndex)
1008 {
1009 TName *pVert = pVertex;
1010 pVert->m_Color = m_aColor[ColorIndex];
1011 }
1012
1013 void SetColorVertex(const CColorVertex *pArray, size_t Num) override;
1014 void SetColor(float r, float g, float b, float a) override;
1015 void SetColor(ColorRGBA Color) override;
1016 void SetColor4(ColorRGBA TopLeft, ColorRGBA TopRight, ColorRGBA BottomLeft, ColorRGBA BottomRight) override;
1017
1018 // go through all vertices and change their color (only works for quads)
1019 void ChangeColorOfCurrentQuadVertices(float r, float g, float b, float a) override;
1020 void ChangeColorOfQuadVertices(size_t QuadOffset, unsigned char r, unsigned char g, unsigned char b, unsigned char a) override;
1021
1022 void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV) override;
1023 void QuadsSetSubsetFree(
1024 float x0, float y0, float x1, float y1,
1025 float x2, float y2, float x3, float y3, int Index = -1) override;
1026
1027 void QuadsDraw(CQuadItem *pArray, int Num) override;
1028
1029 template<typename TName>
1030 void QuadsDrawTLImpl(TName *pVertices, const CQuadItem *pArray, int Num)
1031 {
1032 CCommandBuffer::SPoint Center;
1033
1034 dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawTL without begin");
1035
1036 if(g_Config.m_GfxQuadAsTriangle && !m_GLUseTrianglesAsQuad)
1037 {
1038 for(int i = 0; i < Num; ++i)
1039 {
1040 // first triangle
1041 pVertices[m_NumVertices + 6 * i].m_Pos.x = pArray[i].m_X;
1042 pVertices[m_NumVertices + 6 * i].m_Pos.y = pArray[i].m_Y;
1043 pVertices[m_NumVertices + 6 * i].m_Tex = m_aTexture[0];
1044 SetColor(&pVertices[m_NumVertices + 6 * i], 0);
1045
1046 pVertices[m_NumVertices + 6 * i + 1].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1047 pVertices[m_NumVertices + 6 * i + 1].m_Pos.y = pArray[i].m_Y;
1048 pVertices[m_NumVertices + 6 * i + 1].m_Tex = m_aTexture[1];
1049 SetColor(&pVertices[m_NumVertices + 6 * i + 1], 1);
1050
1051 pVertices[m_NumVertices + 6 * i + 2].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1052 pVertices[m_NumVertices + 6 * i + 2].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1053 pVertices[m_NumVertices + 6 * i + 2].m_Tex = m_aTexture[2];
1054 SetColor(&pVertices[m_NumVertices + 6 * i + 2], 2);
1055
1056 // second triangle
1057 pVertices[m_NumVertices + 6 * i + 3].m_Pos.x = pArray[i].m_X;
1058 pVertices[m_NumVertices + 6 * i + 3].m_Pos.y = pArray[i].m_Y;
1059 pVertices[m_NumVertices + 6 * i + 3].m_Tex = m_aTexture[0];
1060 SetColor(&pVertices[m_NumVertices + 6 * i + 3], 0);
1061
1062 pVertices[m_NumVertices + 6 * i + 4].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1063 pVertices[m_NumVertices + 6 * i + 4].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1064 pVertices[m_NumVertices + 6 * i + 4].m_Tex = m_aTexture[2];
1065 SetColor(&pVertices[m_NumVertices + 6 * i + 4], 2);
1066
1067 pVertices[m_NumVertices + 6 * i + 5].m_Pos.x = pArray[i].m_X;
1068 pVertices[m_NumVertices + 6 * i + 5].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1069 pVertices[m_NumVertices + 6 * i + 5].m_Tex = m_aTexture[3];
1070 SetColor(&pVertices[m_NumVertices + 6 * i + 5], 3);
1071
1072 if(m_Rotation != 0)
1073 {
1074 Center.x = pArray[i].m_X + pArray[i].m_Width / 2;
1075 Center.y = pArray[i].m_Y + pArray[i].m_Height / 2;
1076
1077 Rotate(Center, &pVertices[m_NumVertices + 6 * i], 6);
1078 }
1079 }
1080
1081 AddVertices(3 * 2 * Num, pVertices);
1082 }
1083 else
1084 {
1085 for(int i = 0; i < Num; ++i)
1086 {
1087 pVertices[m_NumVertices + 4 * i].m_Pos.x = pArray[i].m_X;
1088 pVertices[m_NumVertices + 4 * i].m_Pos.y = pArray[i].m_Y;
1089 pVertices[m_NumVertices + 4 * i].m_Tex = m_aTexture[0];
1090 SetColor(&pVertices[m_NumVertices + 4 * i], 0);
1091
1092 pVertices[m_NumVertices + 4 * i + 1].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1093 pVertices[m_NumVertices + 4 * i + 1].m_Pos.y = pArray[i].m_Y;
1094 pVertices[m_NumVertices + 4 * i + 1].m_Tex = m_aTexture[1];
1095 SetColor(&pVertices[m_NumVertices + 4 * i + 1], 1);
1096
1097 pVertices[m_NumVertices + 4 * i + 2].m_Pos.x = pArray[i].m_X + pArray[i].m_Width;
1098 pVertices[m_NumVertices + 4 * i + 2].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1099 pVertices[m_NumVertices + 4 * i + 2].m_Tex = m_aTexture[2];
1100 SetColor(&pVertices[m_NumVertices + 4 * i + 2], 2);
1101
1102 pVertices[m_NumVertices + 4 * i + 3].m_Pos.x = pArray[i].m_X;
1103 pVertices[m_NumVertices + 4 * i + 3].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height;
1104 pVertices[m_NumVertices + 4 * i + 3].m_Tex = m_aTexture[3];
1105 SetColor(&pVertices[m_NumVertices + 4 * i + 3], 3);
1106
1107 if(m_Rotation != 0)
1108 {
1109 Center.x = pArray[i].m_X + pArray[i].m_Width / 2;
1110 Center.y = pArray[i].m_Y + pArray[i].m_Height / 2;
1111
1112 Rotate(Center, &pVertices[m_NumVertices + 4 * i], 4);
1113 }
1114 }
1115
1116 AddVertices(4 * Num, pVertices);
1117 }
1118 }
1119
1120 void QuadsDrawTL(const CQuadItem *pArray, int Num) override;
1121
1122 void QuadsTex3DDrawTL(const CQuadItem *pArray, int Num) override;
1123
1124 void QuadsDrawFreeform(const CFreeformItem *pArray, int Num) override;
1125 void QuadsText(float x, float y, float Size, const char *pText) override;
1126
1127 void DrawRectExt(float x, float y, float w, float h, float r, int Corners) override;
1128 void DrawRectExt4(float x, float y, float w, float h, ColorRGBA ColorTopLeft, ColorRGBA ColorTopRight, ColorRGBA ColorBottomLeft, ColorRGBA ColorBottomRight, float r, int Corners) override;
1129 int CreateRectQuadContainer(float x, float y, float w, float h, float r, int Corners) override;
1130 void DrawRect(float x, float y, float w, float h, ColorRGBA Color, int Corners, float Rounding) override;
1131 void DrawRect4(float x, float y, float w, float h, ColorRGBA ColorTopLeft, ColorRGBA ColorTopRight, ColorRGBA ColorBottomLeft, ColorRGBA ColorBottomRight, int Corners, float Rounding) override;
1132 void DrawCircle(float CenterX, float CenterY, float Radius, int Segments) override;
1133
1134 const GL_STexCoord *GetCurTextureCoordinates() override
1135 {
1136 return m_aTexture;
1137 }
1138
1139 const GL_SColor *GetCurColor() override
1140 {
1141 return m_aColor;
1142 }
1143
1144 int CreateQuadContainer(bool AutomaticUpload = true) override;
1145 void QuadContainerChangeAutomaticUpload(int ContainerIndex, bool AutomaticUpload) override;
1146 void QuadContainerUpload(int ContainerIndex) override;
1147 int QuadContainerAddQuads(int ContainerIndex, CQuadItem *pArray, int Num) override;
1148 int QuadContainerAddQuads(int ContainerIndex, CFreeformItem *pArray, int Num) override;
1149 void QuadContainerReset(int ContainerIndex) override;
1150 void DeleteQuadContainer(int &ContainerIndex) override;
1151 void RenderQuadContainer(int ContainerIndex, int QuadDrawNum) override;
1152 void RenderQuadContainer(int ContainerIndex, int QuadOffset, int QuadDrawNum, bool ChangeWrapMode = true) override;
1153 void RenderQuadContainerEx(int ContainerIndex, int QuadOffset, int QuadDrawNum, float X, float Y, float ScaleX = 1.f, float ScaleY = 1.f) override;
1154 void RenderQuadContainerAsSprite(int ContainerIndex, int QuadOffset, float X, float Y, float ScaleX = 1.f, float ScaleY = 1.f) override;
1155 void RenderQuadContainerAsSpriteMultiple(int ContainerIndex, int QuadOffset, int DrawCount, SRenderSpriteInfo *pRenderInfo) override;
1156
1157 template<typename TName>
1158 void FlushVerticesImpl(bool KeepVertices, int &PrimType, size_t &PrimCount, size_t &NumVerts, TName &Command, size_t VertSize)
1159 {
1160 Command.m_pVertices = nullptr;
1161 if(m_NumVertices == 0)
1162 return;
1163
1164 NumVerts = m_NumVertices;
1165
1166 if(!KeepVertices)
1167 m_NumVertices = 0;
1168
1169 if(m_Drawing == DRAWING_QUADS)
1170 {
1171 if(g_Config.m_GfxQuadAsTriangle && !m_GLUseTrianglesAsQuad)
1172 {
1173 PrimType = CCommandBuffer::PRIMTYPE_TRIANGLES;
1174 PrimCount = NumVerts / 3;
1175 }
1176 else
1177 {
1178 PrimType = CCommandBuffer::PRIMTYPE_QUADS;
1179 PrimCount = NumVerts / 4;
1180 }
1181 }
1182 else if(m_Drawing == DRAWING_LINES)
1183 {
1184 PrimType = CCommandBuffer::PRIMTYPE_LINES;
1185 PrimCount = NumVerts / 2;
1186 }
1187 else if(m_Drawing == DRAWING_TRIANGLES)
1188 {
1189 PrimType = CCommandBuffer::PRIMTYPE_TRIANGLES;
1190 PrimCount = NumVerts / 3;
1191 }
1192 else
1193 return;
1194
1195 Command.m_pVertices = (decltype(Command.m_pVertices))AllocCommandBufferData(AllocSize: VertSize * NumVerts);
1196 Command.m_State = m_State;
1197
1198 Command.m_PrimType = PrimType;
1199 Command.m_PrimCount = PrimCount;
1200
1201 AddCmd(Command, [&] {
1202 Command.m_pVertices = (decltype(Command.m_pVertices))m_pCommandBuffer->AllocData(WantedSize: VertSize * NumVerts);
1203 return Command.m_pVertices != nullptr;
1204 });
1205
1206 m_pCommandBuffer->AddRenderCalls(RenderCallCountToAdd: 1);
1207 }
1208
1209 void FlushVertices(bool KeepVertices = false) override;
1210 void FlushVerticesTex3D() override;
1211
1212 void RenderTileLayer(int BufferContainerIndex, const ColorRGBA &Color, char **pOffsets, unsigned int *pIndicedVertexDrawNum, size_t NumIndicesOffset) override;
1213 virtual void RenderBorderTiles(int BufferContainerIndex, const ColorRGBA &Color, char *pIndexBufferOffset, const vec2 &Offset, const vec2 &Scale, uint32_t DrawNum) override;
1214 void RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, size_t QuadNum, int QuadOffset) override;
1215 void RenderText(int BufferContainerIndex, int TextQuadNum, int TextureSize, int TextureTextIndex, int TextureTextOutlineIndex, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor) override;
1216
1217 // modern GL functions
1218 int CreateBufferObject(size_t UploadDataSize, void *pUploadData, int CreateFlags, bool IsMovedPointer = false) override;
1219 void RecreateBufferObject(int BufferIndex, size_t UploadDataSize, void *pUploadData, int CreateFlags, bool IsMovedPointer = false) override;
1220 void UpdateBufferObjectInternal(int BufferIndex, size_t UploadDataSize, void *pUploadData, void *pOffset, bool IsMovedPointer = false);
1221 void CopyBufferObjectInternal(int WriteBufferIndex, int ReadBufferIndex, size_t WriteOffset, size_t ReadOffset, size_t CopyDataSize);
1222 void DeleteBufferObject(int BufferIndex) override;
1223
1224 int CreateBufferContainer(SBufferContainerInfo *pContainerInfo) override;
1225 // destroying all buffer objects means, that all referenced VBOs are destroyed automatically, so the user does not need to save references to them
1226 void DeleteBufferContainer(int &ContainerIndex, bool DestroyAllBO = true) override;
1227 void UpdateBufferContainerInternal(int ContainerIndex, SBufferContainerInfo *pContainerInfo);
1228 void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) override;
1229
1230 int GetNumScreens() const override;
1231 const char *GetScreenName(int Screen) const override;
1232
1233 void Minimize() override;
1234 void Maximize() override;
1235 void WarnPngliteIncompatibleImages(bool Warn) override;
1236 void SetWindowParams(int FullscreenMode, bool IsBorderless) override;
1237 bool SetWindowScreen(int Index) override;
1238 void Move(int x, int y) override;
1239 bool Resize(int w, int h, int RefreshRate) override;
1240 void ResizeToScreen() override;
1241 void GotResized(int w, int h, int RefreshRate) override;
1242 void UpdateViewport(int X, int Y, int W, int H, bool ByResize) override;
1243 void AddWindowResizeListener(WINDOW_RESIZE_FUNC pFunc) override;
1244 void AddWindowPropChangeListener(WINDOW_PROPS_CHANGED_FUNC pFunc) override;
1245 int GetWindowScreen() override;
1246
1247 void WindowDestroyNtf(uint32_t WindowId) override;
1248 void WindowCreateNtf(uint32_t WindowId) override;
1249
1250 int WindowActive() override;
1251 int WindowOpen() override;
1252
1253 void SetWindowGrab(bool Grab) override;
1254 void NotifyWindow() override;
1255
1256 int Init() override;
1257 void Shutdown() override;
1258
1259 void ReadPixel(ivec2 Position, ColorRGBA *pColor) override;
1260 void TakeScreenshot(const char *pFilename) override;
1261 void TakeCustomScreenshot(const char *pFilename) override;
1262 void Swap() override;
1263 bool SetVSync(bool State) override;
1264 bool SetMultiSampling(uint32_t ReqMultiSamplingCount, uint32_t &MultiSamplingCountBackend) override;
1265
1266 int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen) override;
1267 void GetCurrentVideoMode(CVideoMode &CurMode, int Screen) override;
1268
1269 virtual int GetDesktopScreenWidth() const { return g_Config.m_GfxDesktopWidth; }
1270 virtual int GetDesktopScreenHeight() const { return g_Config.m_GfxDesktopHeight; }
1271
1272 // synchronization
1273 void InsertSignal(CSemaphore *pSemaphore) override;
1274 bool IsIdle() const override;
1275 void WaitForIdle() override;
1276
1277 SWarning *GetCurWarning() override;
1278 bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) override;
1279 bool IsBackendInitialized() override;
1280
1281 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); }
1282 bool IsConfigModernAPI() override { return m_pBackend->IsConfigModernAPI(); }
1283 bool IsTileBufferingEnabled() override { return m_GLTileBufferingEnabled; }
1284 bool IsQuadBufferingEnabled() override { return m_GLQuadBufferingEnabled; }
1285 bool IsTextBufferingEnabled() override { return m_GLTextBufferingEnabled; }
1286 bool IsQuadContainerBufferingEnabled() override { return m_GLQuadContainerBufferingEnabled; }
1287 bool Uses2DTextureArrays() override { return m_GLUses2DTextureArrays; }
1288 bool HasTextureArraysSupport() override { return m_GLHasTextureArraysSupport; }
1289
1290 const char *GetVendorString() override;
1291 const char *GetVersionString() override;
1292 const char *GetRendererString() override;
1293
1294 TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() override;
1295};
1296
1297typedef std::function<const char *(const char *, const char *)> TTranslateFunc;
1298extern IGraphicsBackend *CreateGraphicsBackend(TTranslateFunc &&TranslateFunc);
1299
1300#endif // ENGINE_CLIENT_GRAPHICS_THREADED_H
1301