Cogs.Core
GraphicsDeviceGL20.cpp
1#include "GraphicsDeviceGL20.h"
2
3#include "Foundation/Logging/Logger.h"
4#include "Foundation/Platform/Unicode.h"
5
6// In an ideal world this would be above the platform includes so as not to hide any
7// missing dependencies. However... glxext uses Bool which is "defined" in xlib.h by
8// muppets (included via glx.h in GraphicsDeviceGL20.h), which causes additional
9// conflicts in other places in our code, so WindowData.h (which also needs to include
10// xlib.h) undefines Bool.
11#include "Foundation/Platform/WindowData.h"
12
13#include <algorithm>
14
15namespace {
16 Cogs::Logging::Log logger = Cogs::Logging::getLogger("GraphicsDeviceGL20");
17}
18
19Cogs::GraphicsDeviceGL20::GraphicsDeviceGL20(RenderingAllocatorInfo*) : defaultSwapChain(this, true) {
20}
21
22Cogs::GraphicsDeviceGL20::~GraphicsDeviceGL20() {
24 defaultSwapChain.destroy();
25}
26
32 assert(!initialized && "Initialize invoked multiple times.");
33
34 if (settings.windowData->windowHandle == (WindowData::nativeHandleType)nullptr) {
35 LOG_ERROR(logger, "No window handle");
36 return false;
37 }
38 bool enableDiagnostics = isDebug() || ((settings.flags & GraphicsDeviceFlags::EnableDiagnostics) == GraphicsDeviceFlags::EnableDiagnostics);
39
40#if defined( __APPLE__ )
41 glShareContext = GLContext(settings.windowData->defaultContext);
42 glShareContext.makeCurrent();
43#else
44#ifdef __linux__
45 GLContext::NativeDisplay display = settings.windowData->display;
46#else
47 GLContext::NativeDisplay display = nullptr;
48#endif
49 if (!glShareContext.create(display, nullptr, nullptr, &settings, GLContext::Platform::GL, enableDiagnostics)) {
50 LOG_ERROR(logger, "Failed to create share context.");
51 return false;
52 }
53#endif
54
55 defaultSwapChain.initialize(settings.windowData, enableDiagnostics);
56
57 bool useClipControl = (settings.flags & GraphicsDeviceFlags::UseOpenGLClipControl) != 0;
58#ifdef __APPLE__
59 useClipControl = false;
60#else
61 if(!glClipControl) useClipControl = false;
62#endif
63
64 capabilities.initialize(useClipControl);
65 context.initialize(&capabilities, &buffers, &textures, &effects, &renderTargets, &syncObjects);
66 effects.initialize(this, &capabilities, &buffers);
67 renderTargets.initialize(&textures);
68 textures.initialize(this);
69
70 glEnable(GL_PROGRAM_POINT_SIZE);
71
72 if (settings.colorFormat == TextureFormat::R8G8B8A8_UNORM_SRGB) {
73 glEnable(GL_FRAMEBUFFER_SRGB);
74 }
75
76#ifndef __APPLE__
77 if(useClipControl){
78 LOG_DEBUG(logger, "glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE)");
79 glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
80 }
81#endif
82
83 initialized = true;
84 return true;
85}
86
93
94 if (settings.ioHandler) {
95 effects.setIOHandler(settings.ioHandler);
96 }
97
98 return true;
99}
100
105 SwapChainGL20* swapChain = new SwapChainGL20(this, false);
106
107 bool enableDiagnostics = isDebug() || ((settings.flags & GraphicsDeviceFlags::EnableDiagnostics) == GraphicsDeviceFlags::EnableDiagnostics);
108 if (swapChain->initialize(windowData, enableDiagnostics)) {
109 swapChains.push_back(swapChain);
110 return swapChain;
111 }
112 delete swapChain;
113 return nullptr;
114}
115
120 auto e = swapChains.end();
121 auto i = std::find(swapChains.begin(), e, swapChain);
122
123 if (i != e) {
124 swapChains.erase(i);
125 delete swapChain;
126 }
127}
128
133void Cogs::GraphicsDeviceGL20::setSize(int newWidth, int newHeight) {
134 defaultSwapChain.setSize(newWidth, newHeight);
135}
136
140bool Cogs::GraphicsDeviceGL20::getSize(int& w, int& h) const {
141 w = defaultSwapChain.getWidth();
142 h = defaultSwapChain.getHeight();
143 return true;
144}
145
150 defaultSwapChain.beginFrame();
151
152 for (ISwapChain* swapChain : swapChains) {
153 swapChain->beginFrame();
154 }
155
156 // On frame start for the current device. This ensures that if
157 // e.g. the GL driver provides different
158 //::threadContext = &glContext;
159
160 context.setDefaults();
161}
162
166void Cogs::GraphicsDeviceGL20::endFrame(uint32_t syncInterval, uint32_t presentFlags) {
167 for (ISwapChain* swapChain : swapChains) {
168 swapChain->endFrame(0, presentFlags);
169 }
170 defaultSwapChain.endFrame(syncInterval, presentFlags);
171}
172
173
178 // Avoid using fence sync on FireGL series cards, since they seem to return without waiting.
179 if (capabilities.getSeries() != Series::FireGL) {
180 GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
181
182 glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
183 glDeleteSync(sync);
184 }
185 else {
186 glFinish();
187 }
188}
189
194 // Ensure the primary context is selected...
195 defaultSwapChain.beginFrame();
196
197 context.releaseResources();
198 effects.releaseResources();
199 renderTargets.releaseResources();
200 textures.releaseResources();
201
202 //TODO: Fix pinned effect/buffer relationships, reintroduce.
203 //buffers.releaseResources();
204
205 context.defaultSamplerStateHandle = SamplerStateHandle::NoHandle;
206}
207
212 ResourceStatistics stats{};
213
214 stats.bufferMemoryConsumption = buffers.bufferMemoryConsumption;
215 stats.textureMemoryConsumption = 0;
216 stats.bufferCount = static_cast<uint32_t>(buffers.buffers.size());
217 stats.inputLayoutCount = static_cast<uint32_t>(buffers.inputLayouts.size());
218 stats.textureCount = static_cast<uint32_t>(textures.textures.size());
219 stats.samplerStateCount = ~0u;
220 stats.effectCount = static_cast<uint32_t>(effects.effects.size());
221 stats.blendStateCount = static_cast<uint32_t>(renderTargets.blendStates.size());
222 stats.rasterizerStateCount = static_cast<uint32_t>(renderTargets.rasterizerStates.size());
223 stats.depthStencilStateCount = static_cast<uint32_t>(renderTargets.depthStencilStates.size());
224 stats.rendertargetsCount = static_cast<uint32_t>(renderTargets.renderTargets.size());
225 stats.framebufferCount = ~0u;
226
227 return stats;
228}
229
230namespace Cogs {
232 {
233 GLContext context;
234 };
235}
236
238{
239 bool enableDiagnostics = isDebug() || ((settings.flags & GraphicsDeviceFlags::EnableDiagnostics) == GraphicsDeviceFlags::EnableDiagnostics);
240 SharedGraphicsContext* sharedContext = new SharedGraphicsContext();
241 if (sharedContext->context.create(nullptr, nullptr, &glShareContext, &settings, GLContext::Platform::GL, enableDiagnostics)) {
242 return sharedContext;
243 }
244 sharedContext->context.destroy();
245 delete sharedContext;
246 return nullptr;
247}
248
250{
251 if (sharedContext) {
252 sharedContext->context.makeCurrent();
253 }
254}
255
257{
258 if (sharedContext) {
259 sharedContext->context.destroy();
260 delete sharedContext;
261 }
262}
virtual bool initialize() override
Initialises this graphics device.
virtual void activateSharedContext(SharedGraphicsContext *) override
Activates the given shared context on the calling thread.
virtual void endFrame(uint32_t syncInterval=0, uint32_t presentFlags=PresentFlags::None) override
Finalises frame rendering and presents the new frames to the display (if applicable).
virtual SharedGraphicsContext * createSharedContext() override
Create a shared graphics context that can be used to activate another thread for rendering.
virtual void releaseResources() override
Release all resources used by this graphics device.
virtual void beginFrame() override
Prepares the current frame for rendering.
virtual bool getSize(int &w, int &h) const override
Retrieve the current size of this graphics device's default swap chain.
virtual bool setSettings(const GraphicsDeviceSettings &newSettings) override
Updates settings for this graphics device.
virtual void waitForCommandSync() override
Forces the calling thread to synchronise with the GPU.
virtual void deleteSwapChain(ISwapChain *swapChain) override
Delete the specified SwapChain.
virtual void releaseSharedContext(SharedGraphicsContext *) override
Releases the given shared context.
virtual ISwapChain * createSwapChain(struct WindowData *windowData) override
Create a new SwapChain and attach it to the provided window.
virtual void setSize(int width, int height) override
Resizes the output of this graphics device.
virtual ResourceStatistics getResourceStatistics() override
Retrieve statistics about resources currently in use by this graphics device instance.
virtual bool setSettings(const GraphicsDeviceSettings &newSettings)
Updates the settings associated with this device.
Log implementation class.
Definition: LogManager.h:139
bool initialize(WindowData *windowData, bool debugLogging)
Initialises this swap chain and attaches it to the window provided.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ EnableDiagnostics
If available, the device will print diagnostic information to the log.
@ UseOpenGLClipControl
For OpenGL / OpenGLES backends.
Settings for graphics device initialization.
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
@ FireGL
AMD FireGL series.
Definition: ICapabilities.h:43