@@ -121,6 +121,37 @@ void ProjectM::RenderFrame(uint32_t targetFramebufferObject /*= 0*/)
121121 return ;
122122 }
123123
124+ // Save the host application's OpenGL state so we can restore it after rendering.
125+ // This is required when libprojectM is used inside a shared OpenGL context,
126+ // where the host expects its GL state to be preserved.
127+ GLint previousFramebuffer{};
128+ GLint previousVertexArray{};
129+ GLint previousProgram{};
130+ GLint previousActiveTexture{};
131+ GLint previousArrayBuffer{};
132+ GLint previousElementArrayBuffer{};
133+ GLboolean previousBlend{};
134+ GLboolean previousDepthTest{};
135+ GLint previousBlendSrcRgb{};
136+ GLint previousBlendDstRgb{};
137+ #ifndef USE_GLES
138+ GLboolean previousLineSmooth{};
139+ #endif
140+
141+ glGetIntegerv (GL_FRAMEBUFFER_BINDING, &previousFramebuffer);
142+ glGetIntegerv (GL_VERTEX_ARRAY_BINDING, &previousVertexArray);
143+ glGetIntegerv (GL_CURRENT_PROGRAM, &previousProgram);
144+ glGetIntegerv (GL_ACTIVE_TEXTURE, &previousActiveTexture);
145+ glGetIntegerv (GL_ARRAY_BUFFER_BINDING, &previousArrayBuffer);
146+ glGetIntegerv (GL_ELEMENT_ARRAY_BUFFER_BINDING, &previousElementArrayBuffer);
147+ glGetBooleanv (GL_BLEND, &previousBlend);
148+ glGetBooleanv (GL_DEPTH_TEST, &previousDepthTest);
149+ glGetIntegerv (GL_BLEND_SRC_RGB, &previousBlendSrcRgb);
150+ glGetIntegerv (GL_BLEND_DST_RGB, &previousBlendDstRgb);
151+ #ifndef USE_GLES
152+ glGetBooleanv (GL_LINE_SMOOTH, &previousLineSmooth);
153+ #endif
154+
124155 // Update FPS and other timer values.
125156 m_timeKeeper->UpdateTimers ();
126157
@@ -153,6 +184,13 @@ void ProjectM::RenderFrame(uint32_t targetFramebufferObject /*= 0*/)
153184 LoadIdlePreset ();
154185 if (!m_activePreset)
155186 {
187+ RestoreGLState (previousFramebuffer, previousVertexArray, previousProgram,
188+ previousActiveTexture, previousArrayBuffer, previousElementArrayBuffer,
189+ previousBlend, previousDepthTest, previousBlendSrcRgb, previousBlendDstRgb
190+ #ifndef USE_GLES
191+ , previousLineSmooth
192+ #endif
193+ );
156194 return ;
157195 }
158196
@@ -205,6 +243,83 @@ void ProjectM::RenderFrame(uint32_t targetFramebufferObject /*= 0*/)
205243
206244 m_frameCount++;
207245 m_previousFrameVolume = audioData.vol ;
246+
247+ // Restore the host application's OpenGL state.
248+ RestoreGLState (previousFramebuffer, previousVertexArray, previousProgram,
249+ previousActiveTexture, previousArrayBuffer, previousElementArrayBuffer,
250+ previousBlend, previousDepthTest, previousBlendSrcRgb, previousBlendDstRgb
251+ #ifndef USE_GLES
252+ , previousLineSmooth
253+ #endif
254+ );
255+ }
256+
257+ void ProjectM::RestoreGLState (GLint framebuffer, GLint vertexArray, GLint program,
258+ GLint activeTexture, GLint arrayBuffer, GLint elementArrayBuffer,
259+ GLboolean blend, GLboolean depthTest,
260+ GLint blendSrcRgb, GLint blendDstRgb
261+ #ifndef USE_GLES
262+ , GLboolean lineSmooth
263+ #endif
264+ )
265+ {
266+ // Restore framebuffer
267+ glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
268+
269+ // Restore VAO (must be done before restoring buffer bindings)
270+ glBindVertexArray (vertexArray);
271+
272+ // Restore shader program
273+ glUseProgram (program);
274+
275+ // Restore active texture unit and unbind any textures left on unit 0
276+ glActiveTexture (activeTexture);
277+
278+ // Restore buffer bindings
279+ glBindBuffer (GL_ARRAY_BUFFER, arrayBuffer);
280+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
281+
282+ // Restore blend state
283+ if (blend)
284+ {
285+ glEnable (GL_BLEND);
286+ }
287+ else
288+ {
289+ glDisable (GL_BLEND);
290+ }
291+ glBlendFunc (blendSrcRgb, blendDstRgb);
292+
293+ // Restore depth test state
294+ if (depthTest)
295+ {
296+ glEnable (GL_DEPTH_TEST);
297+ }
298+ else
299+ {
300+ glDisable (GL_DEPTH_TEST);
301+ }
302+
303+ #ifndef USE_GLES
304+ // Restore line smooth state
305+ if (lineSmooth)
306+ {
307+ glEnable (GL_LINE_SMOOTH);
308+ }
309+ else
310+ {
311+ glDisable (GL_LINE_SMOOTH);
312+ }
313+ #endif
314+
315+ // Reset color mask to default (projectM may have changed it via MaskDrawBuffer)
316+ glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
317+
318+ // Unbind any sampler objects left bound by projectM on common texture units
319+ for (GLuint unit = 0 ; unit < 8 ; unit++)
320+ {
321+ glBindSampler (unit, 0 );
322+ }
208323}
209324
210325void ProjectM::Initialize ()
@@ -356,6 +471,9 @@ auto ProjectM::UserSpriteIdentifiers() const -> std::vector<uint32_t>
356471
357472void ProjectM::BurnInTexture (uint32_t openGlTextureId, int left, int top, int width, int height)
358473{
474+ GLint previousFramebuffer{};
475+ glGetIntegerv (GL_FRAMEBUFFER_BINDING, &previousFramebuffer);
476+
359477 if (m_activePreset)
360478 {
361479 m_activePreset->BindFramebuffer ();
@@ -368,7 +486,7 @@ void ProjectM::BurnInTexture(uint32_t openGlTextureId, int left, int top, int wi
368486 m_textureCopier->Draw (*m_shaderCache, openGlTextureId, m_windowWidth, m_windowHeight, left, top, width, height);
369487 }
370488
371- Renderer::Framebuffer::Unbind ( );
489+ glBindFramebuffer (GL_FRAMEBUFFER, previousFramebuffer );
372490}
373491
374492void ProjectM::SetPresetLocked (bool locked)
0 commit comments