More efficient clears for FBO
This commit is contained in:
parent
dc0f40cadd
commit
88e5cdfd86
|
|
@ -1262,7 +1262,7 @@ set_size_and_recalc(int x, int y) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::clear
|
||||
// Access: Public
|
||||
// Access: Public, Virtual
|
||||
// Description: Clears the entire framebuffer before rendering,
|
||||
// according to the settings of get_color_clear_active()
|
||||
// and get_depth_clear_active() (inherited from
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ public:
|
|||
// It is an error to call any of the following methods from any
|
||||
// thread other than the draw thread. These methods are normally
|
||||
// called by the GraphicsEngine.
|
||||
void clear(Thread *current_thread);
|
||||
virtual void clear(Thread *current_thread);
|
||||
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_frame(FrameMode mode, Thread *current_thread);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "depthWriteAttrib.h"
|
||||
|
||||
TypeHandle CLP(GraphicsBuffer)::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -84,6 +86,121 @@ CLP(GraphicsBuffer)::
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef OPENGLES
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsBuffer::clear
|
||||
// Access: Public, Virtual
|
||||
// Description: Clears the entire framebuffer before rendering,
|
||||
// according to the settings of get_color_clear_active()
|
||||
// and get_depth_clear_active() (inherited from
|
||||
// DrawableRegion).
|
||||
//
|
||||
// This function is called only within the draw thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsBuffer)::
|
||||
clear(Thread *current_thread) {
|
||||
if (!is_any_clear_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
|
||||
if (glgsg->_glClearBufferfv == NULL) {
|
||||
// We can't efficiently clear the buffer. Fall back to the
|
||||
// inefficient default implementation for now.
|
||||
GraphicsOutput::clear(current_thread);
|
||||
return;
|
||||
}
|
||||
|
||||
if (display_cat.is_spam()) {
|
||||
display_cat.spam()
|
||||
<< "clear(): " << get_type() << " "
|
||||
<< get_name() << " " << (void *)this << "\n";
|
||||
}
|
||||
|
||||
PStatGPUTimer timer(glgsg, glgsg->_clear_pcollector);
|
||||
|
||||
// Disable the scissor test, so we can clear the whole buffer.
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glgsg->_scissor_enabled = false;
|
||||
glgsg->_scissor_array.clear();
|
||||
glgsg->_scissor_attrib_active = false;
|
||||
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< "glDisable(GL_SCISSOR_TEST)\n";
|
||||
}
|
||||
|
||||
// Set the buffers into which we'll be indexing with glClearBuffer.
|
||||
int draw_buffer_type = _draw_buffer_type & _fb_properties.get_buffer_mask();
|
||||
draw_buffer_type |= _fb_properties.get_aux_mask();
|
||||
glgsg->_color_write_mask = ColorWriteAttrib::C_all;
|
||||
glgsg->set_draw_buffer(draw_buffer_type);
|
||||
|
||||
int index = 0;
|
||||
if (_fb_properties.get_color_bits() > 0) {
|
||||
if (_fb_properties.is_stereo()) {
|
||||
// Clear both left and right attachments.
|
||||
if (get_clear_active(RTP_color)) {
|
||||
LColorf v = LCAST(float, get_clear_value(RTP_color));
|
||||
glgsg->_glClearBufferfv(GL_COLOR, index, v.get_data());
|
||||
glgsg->_glClearBufferfv(GL_COLOR, index + 1, v.get_data());
|
||||
}
|
||||
index += 2;
|
||||
} else {
|
||||
if (get_clear_active(RTP_color)) {
|
||||
LColorf v = LCAST(float, get_clear_value(RTP_color));
|
||||
glgsg->_glClearBufferfv(GL_COLOR, index, v.get_data());
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < _fb_properties.get_aux_rgba(); ++i) {
|
||||
int layerid = RTP_aux_rgba_0 + i;
|
||||
if (get_clear_active(layerid)) {
|
||||
LColorf v = LCAST(float, get_clear_value(layerid));
|
||||
glgsg->_glClearBufferfv(GL_COLOR, index, v.get_data());
|
||||
}
|
||||
++index;
|
||||
}
|
||||
for (int i = 0; i < _fb_properties.get_aux_hrgba(); ++i) {
|
||||
int layerid = RTP_aux_hrgba_0 + i;
|
||||
if (get_clear_active(layerid)) {
|
||||
LColorf v = LCAST(float, get_clear_value(layerid));
|
||||
glgsg->_glClearBufferfv(GL_COLOR, index, v.get_data());
|
||||
}
|
||||
++index;
|
||||
}
|
||||
for (int i = 0; i < _fb_properties.get_aux_float(); ++i) {
|
||||
int layerid = RTP_aux_float_0 + i;
|
||||
if (get_clear_active(layerid)) {
|
||||
LColorf v = LCAST(float, get_clear_value(layerid));
|
||||
glgsg->_glClearBufferfv(GL_COLOR, index, v.get_data());
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
if (get_clear_depth_active()) {
|
||||
glDepthMask(GL_TRUE);
|
||||
glgsg->_state_mask.clear_bit(DepthWriteAttrib::get_class_slot());
|
||||
|
||||
if (get_clear_stencil_active()) {
|
||||
glStencilMask(~0);
|
||||
glgsg->_glClearBufferfi(GL_DEPTH_STENCIL, 0, get_clear_depth(), get_clear_stencil());
|
||||
} else {
|
||||
GLfloat depth = get_clear_depth();
|
||||
glgsg->_glClearBufferfv(GL_DEPTH, 0, &depth);
|
||||
}
|
||||
} else if (get_clear_stencil_active()) {
|
||||
GLint stencil = get_clear_stencil();
|
||||
glgsg->_glClearBufferiv(GL_STENCIL, 0, &stencil);
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: glGraphicsBuffer::begin_frame
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ public:
|
|||
GraphicsOutput *host);
|
||||
virtual ~CLP(GraphicsBuffer)();
|
||||
|
||||
#ifndef OPENGLES
|
||||
virtual void clear(Thread *current_thread);
|
||||
#endif
|
||||
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_frame(FrameMode mode, Thread *current_thread);
|
||||
|
||||
|
|
|
|||
|
|
@ -1954,7 +1954,6 @@ reset() {
|
|||
|
||||
#if defined(OPENGLES_1)
|
||||
_glDrawBuffers = NULL;
|
||||
_glClearBufferfv = NULL;
|
||||
_max_color_targets = 1;
|
||||
|
||||
#elif defined(OPENGLES_2)
|
||||
|
|
@ -1997,8 +1996,15 @@ reset() {
|
|||
if (is_at_least_gl_version(3, 0)) {
|
||||
_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)
|
||||
get_extension_func("glClearBufferfv");
|
||||
_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)
|
||||
get_extension_func("glClearBufferiv");
|
||||
_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)
|
||||
get_extension_func("glClearBufferfi");
|
||||
|
||||
} else {
|
||||
_glClearBufferfv = NULL;
|
||||
_glClearBufferiv = NULL;
|
||||
_glClearBufferfi = NULL;
|
||||
}
|
||||
#endif // !OPENGLES
|
||||
|
||||
|
|
@ -2798,7 +2804,8 @@ clear(DrawableRegion *clearable) {
|
|||
return;
|
||||
}
|
||||
|
||||
//XXX rdb: Is this line really necessary?
|
||||
//XXX rdb: Is this line really necessary? Could we perhaps just
|
||||
// reset the color write mask and other relevant attributes?
|
||||
set_state_and_transform(RenderState::make_empty(), _internal_transform);
|
||||
|
||||
int mask = 0;
|
||||
|
|
|
|||
|
|
@ -814,7 +814,13 @@ public:
|
|||
INLINE bool get_supports_framebuffer_blit();
|
||||
PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer;
|
||||
PFNGLDRAWBUFFERSPROC _glDrawBuffers;
|
||||
|
||||
#ifndef OPENGLES
|
||||
PFNGLCLEARBUFFERFVPROC _glClearBufferfv;
|
||||
PFNGLCLEARBUFFERIVPROC _glClearBufferiv;
|
||||
PFNGLCLEARBUFFERFIPROC _glClearBufferfi;
|
||||
#endif
|
||||
|
||||
int _max_fb_samples;
|
||||
bool _supports_viewport_arrays;
|
||||
bool _supports_bindless_texture;
|
||||
|
|
|
|||
Loading…
Reference in New Issue