diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index bc13a435c7..79de507955 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -1280,7 +1280,7 @@ open_buffer() { // A lot of code seems to depend on being able to get a // color buffer by just setting the rgb_color bit. if (_fb_properties.get_color_bits() == 0 && - _fb_properties.get_rgb_color() > 0) { + _fb_properties.get_rgb_color()) { _fb_properties.set_color_bits(1); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 6aed4d7335..dee772d370 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1423,6 +1423,7 @@ reset() { } _glDrawBuffers = NULL; + _glClearBufferfv = NULL; #ifndef OPENGLES if (is_at_least_gl_version(2, 0)) { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) @@ -1438,6 +1439,11 @@ reset() { glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); _max_color_targets = max_draw_buffers; } + + if (is_at_least_gl_version(3, 0)) { + _glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) + get_extension_func("glClearBufferfv"); + } #endif // OPENGLES #ifndef OPENGLES @@ -2178,9 +2184,7 @@ clear(DrawableRegion *clearable) { PStatTimer timer(_clear_pcollector); report_my_gl_errors(); - if ((!clearable->get_clear_color_active())&& - (!clearable->get_clear_depth_active())&& - (!clearable->get_clear_stencil_active())) { + if (!clearable->is_any_clear_active()) { return; } @@ -2188,56 +2192,110 @@ clear(DrawableRegion *clearable) { int mask = 0; - for (int i=0; i<_current_properties->get_aux_rgba(); i++) { - int layerid = GraphicsOutput::RTP_aux_rgba_0 + i; - int layerbit = RenderBuffer::T_aux_rgba_0 << i; - if (clearable->get_clear_active(layerid)) { - LColor v = clearable->get_clear_value(layerid); - glClearColor(v[0],v[1],v[2],v[3]); - set_draw_buffer(layerbit); - glClear(GL_COLOR_BUFFER_BIT); - } - } - for (int i=0; i<_current_properties->get_aux_hrgba(); i++) { - int layerid = GraphicsOutput::RTP_aux_hrgba_0 + i; - int layerbit = RenderBuffer::T_aux_hrgba_0 << i; - if (clearable->get_clear_active(layerid)) { - LColor v = clearable->get_clear_value(layerid); - glClearColor(v[0],v[1],v[2],v[3]); - set_draw_buffer(layerbit); - glClear(GL_COLOR_BUFFER_BIT); - } - } - for (int i=0; i<_current_properties->get_aux_float(); i++) { - int layerid = GraphicsOutput::RTP_aux_float_0 + i; - int layerbit = RenderBuffer::T_aux_float_0 << i; - if (clearable->get_clear_active(layerid)) { - LColor v = clearable->get_clear_value(layerid); - glClearColor(v[0],v[1],v[2],v[3]); - set_draw_buffer(layerbit); - glClear(GL_COLOR_BUFFER_BIT); - } - } +#ifndef OPENGLES + if (_current_fbo != 0 && _glClearBufferfv != NULL) { + // We can use glClearBuffer to clear all the color attachments, + // which protects us from the overhead of having to call set_draw_buffer + // for every single attachment. + int index = 0; - // In the past, it was possible to set the draw buffer - // once in prepare_display_region and then forget about it. - // Now, with aux layers, it is necessary to occasionally - // change the draw buffer. In time, I think there will need - // to be a draw buffer attrib. Until then, this little hack - // to put things back the way they were after - // prepare_display_region will do. - - set_draw_buffer(_draw_buffer_type); - - if (_current_properties->get_color_bits() > 0) { - if (clearable->get_clear_color_active()) { - LColor v = clearable->get_clear_color(); - glClearColor(v[0],v[1],v[2],v[3]); - if (gl_color_mask) { - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (_current_properties->get_color_bits() > 0) { + if (_current_properties->is_stereo()) { + // Clear both left and right attachments. + if (clearable->get_clear_active(GraphicsOutput::RTP_color)) { + LColorf v = LCAST(float, clearable->get_clear_value(GraphicsOutput::RTP_color)); + _glClearBufferfv(GL_COLOR, index, v.get_data()); + _glClearBufferfv(GL_COLOR, index + 1, v.get_data()); + } + index += 2; + } else { + if (clearable->get_clear_active(GraphicsOutput::RTP_color)) { + LColorf v = LCAST(float, clearable->get_clear_value(GraphicsOutput::RTP_color)); + _glClearBufferfv(GL_COLOR, index, v.get_data()); + } + ++index; + } + } + for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) { + int layerid = GraphicsOutput::RTP_aux_rgba_0 + i; + if (clearable->get_clear_active(layerid)) { + LColorf v = LCAST(float, clearable->get_clear_value(layerid)); + _glClearBufferfv(GL_COLOR, index, v.get_data()); + } + ++index; + } + for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) { + int layerid = GraphicsOutput::RTP_aux_hrgba_0 + i; + if (clearable->get_clear_active(layerid)) { + LColorf v = LCAST(float, clearable->get_clear_value(layerid)); + _glClearBufferfv(GL_COLOR, index, v.get_data()); + } + ++index; + } + for (int i = 0; i < _current_properties->get_aux_float(); ++i) { + int layerid = GraphicsOutput::RTP_aux_float_0 + i; + if (clearable->get_clear_active(layerid)) { + LColorf v = LCAST(float, clearable->get_clear_value(layerid)); + _glClearBufferfv(GL_COLOR, index, v.get_data()); + } + ++index; + } + } else +#endif + { + if (_current_properties->get_aux_mask() != 0) { + for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) { + int layerid = GraphicsOutput::RTP_aux_rgba_0 + i; + int layerbit = RenderBuffer::T_aux_rgba_0 << i; + if (clearable->get_clear_active(layerid)) { + LColor v = clearable->get_clear_value(layerid); + glClearColor(v[0], v[1], v[2], v[3]); + set_draw_buffer(layerbit); + glClear(GL_COLOR_BUFFER_BIT); + } + } + for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) { + int layerid = GraphicsOutput::RTP_aux_hrgba_0 + i; + int layerbit = RenderBuffer::T_aux_hrgba_0 << i; + if (clearable->get_clear_active(layerid)) { + LColor v = clearable->get_clear_value(layerid); + glClearColor(v[0], v[1], v[2], v[3]); + set_draw_buffer(layerbit); + glClear(GL_COLOR_BUFFER_BIT); + } + } + for (int i = 0; i < _current_properties->get_aux_float(); ++i) { + int layerid = GraphicsOutput::RTP_aux_float_0 + i; + int layerbit = RenderBuffer::T_aux_float_0 << i; + if (clearable->get_clear_active(layerid)) { + LColor v = clearable->get_clear_value(layerid); + glClearColor(v[0], v[1], v[2], v[3]); + set_draw_buffer(layerbit); + glClear(GL_COLOR_BUFFER_BIT); + } + } + + // In the past, it was possible to set the draw buffer + // once in prepare_display_region and then forget about it. + // Now, with aux layers, it is necessary to occasionally + // change the draw buffer. In time, I think there will need + // to be a draw buffer attrib. Until then, this little hack + // to put things back the way they were after + // prepare_display_region will do. + + set_draw_buffer(_draw_buffer_type); + } + + if (_current_properties->get_color_bits() > 0) { + if (clearable->get_clear_color_active()) { + LColor v = clearable->get_clear_color(); + glClearColor(v[0], v[1], v[2], v[3]); + if (gl_color_mask) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + _state_mask.clear_bit(ColorWriteAttrib::get_class_slot()); + mask |= GL_COLOR_BUFFER_BIT; } - _state_mask.clear_bit(ColorWriteAttrib::get_class_slot()); - mask |= GL_COLOR_BUFFER_BIT; } } @@ -6322,19 +6380,19 @@ set_draw_buffer(int rbtype) { ++index; } } - for (int i=0; i<_current_properties->get_aux_rgba(); i++) { + for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) { if (rbtype & (RenderBuffer::T_aux_rgba_0 << i)) { buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; } ++index; } - for (int i=0; i<_current_properties->get_aux_hrgba(); i++) { + for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) { if (rbtype & (RenderBuffer::T_aux_hrgba_0 << i)) { buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; } ++index; } - for (int i=0; i<_current_properties->get_aux_float(); i++) { + for (int i = 0; i < _current_properties->get_aux_float(); ++i) { if (rbtype & (RenderBuffer::T_aux_float_0 << i)) { buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; } @@ -6423,19 +6481,19 @@ set_read_buffer(int rbtype) { } ++index; } - for (int i=0; i<_current_properties->get_aux_rgba(); i++) { + for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) { if (rbtype & (RenderBuffer::T_aux_rgba_0 << i)) { buffer = GL_COLOR_ATTACHMENT0_EXT + index; } ++index; } - for (int i=0; i<_current_properties->get_aux_hrgba(); i++) { + for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) { if (rbtype & (RenderBuffer::T_aux_hrgba_0 << i)) { buffer = GL_COLOR_ATTACHMENT0_EXT + index; } ++index; } - for (int i=0; i<_current_properties->get_aux_float(); i++) { + for (int i = 0; i < _current_properties->get_aux_float(); ++i) { if (rbtype & (RenderBuffer::T_aux_float_0 << i)) { buffer = GL_COLOR_ATTACHMENT0_EXT + index; } @@ -6487,8 +6545,6 @@ set_read_buffer(int rbtype) { #endif // OPENGLES } - - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::get_numeric_type // Access: Protected, Static diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index fa3bbcccfd..6eba1a7632 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -88,6 +88,7 @@ typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); @@ -689,6 +690,7 @@ public: INLINE bool get_supports_framebuffer_blit(); PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer; PFNGLDRAWBUFFERSPROC _glDrawBuffers; + PFNGLCLEARBUFFERFVPROC _glClearBufferfv; int _max_fb_samples; bool _supports_viewport_arrays; bool _supports_bindless_texture;