FBO overhaul: support layered framebuffers (RTM_bind_layered), support render-to-2d-array, better respect FrameBufferProperties, more simple handling of RTP_depth_stencil
This commit is contained in:
parent
a6eeaf42b5
commit
2274f2e651
|
|
@ -314,7 +314,8 @@ make_output(const string &name,
|
|||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_color)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
((flags&BF_can_bind_every)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
|
|
@ -359,7 +360,8 @@ make_output(const string &name,
|
|||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)) {
|
||||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -368,7 +368,8 @@ make_output(GraphicsPipe *pipe,
|
|||
((flags&GraphicsPipe::BF_refuse_parasite)==0)&&
|
||||
((flags&GraphicsPipe::BF_can_bind_color)==0)&&
|
||||
((flags&GraphicsPipe::BF_can_bind_every)==0)&&
|
||||
((flags&GraphicsPipe::BF_rtt_cumulative)==0)) {
|
||||
((flags&GraphicsPipe::BF_rtt_cumulative)==0)&&
|
||||
((flags&GraphicsPipe::BF_can_bind_layered)==0)) {
|
||||
if ((flags&GraphicsPipe::BF_fb_props_optional) ||
|
||||
(host->get_fb_properties().subsumes(fb_prop))) {
|
||||
can_use_parasite = true;
|
||||
|
|
|
|||
|
|
@ -322,9 +322,9 @@ add_render_texture(Texture *tex, RenderTextureMode mode,
|
|||
|
||||
// Choose a default bitplane.
|
||||
if (plane == RTP_COUNT) {
|
||||
if (tex->get_format()==Texture::F_depth_stencil) {
|
||||
if (tex->get_format() == Texture::F_depth_stencil) {
|
||||
plane = RTP_depth_stencil;
|
||||
} else if (tex->get_format()==Texture::F_depth_component) {
|
||||
} else if (tex->get_format() == Texture::F_depth_component) {
|
||||
plane = RTP_depth;
|
||||
} else {
|
||||
plane = RTP_color;
|
||||
|
|
@ -339,6 +339,7 @@ add_render_texture(Texture *tex, RenderTextureMode mode,
|
|||
tex->set_match_framebuffer_format(true);
|
||||
} else if (plane == RTP_depth_stencil) {
|
||||
tex->set_format(Texture::F_depth_stencil);
|
||||
tex->set_component_type(Texture::T_unsigned_int_24_8);
|
||||
tex->set_match_framebuffer_format(true);
|
||||
} else if ((plane == RTP_color)||
|
||||
(plane == RTP_aux_rgba_0)||
|
||||
|
|
@ -358,6 +359,7 @@ add_render_texture(Texture *tex, RenderTextureMode mode,
|
|||
(plane == RTP_aux_float_2)||
|
||||
(plane == RTP_aux_float_3)) {
|
||||
tex->set_format(Texture::F_rgba32);
|
||||
tex->set_component_type(Texture::T_float);
|
||||
tex->set_match_framebuffer_format(true);
|
||||
} else {
|
||||
display_cat.error() <<
|
||||
|
|
@ -368,17 +370,32 @@ add_render_texture(Texture *tex, RenderTextureMode mode,
|
|||
// Go ahead and tell the texture our anticipated size, even if it
|
||||
// might be inaccurate (particularly if this is a GraphicsWindow,
|
||||
// which has system-imposed restrictions on size).
|
||||
tex->set_size_padded(get_x_size(), get_y_size());
|
||||
tex->set_size_padded(get_x_size(), get_y_size(), tex->get_z_size());
|
||||
|
||||
if (mode == RTM_bind_or_copy) {
|
||||
if (!support_render_texture || !get_supports_render_texture()) {
|
||||
// Binding is not supported or it is disabled, so just fall back
|
||||
// to copy instead.
|
||||
if (!support_render_texture || !get_supports_render_texture()) {
|
||||
// Binding is not supported or it is disabled, so just fall back
|
||||
// to copy instead.
|
||||
if (mode == RTM_bind_or_copy) {
|
||||
mode = RTM_copy_texture;
|
||||
} else if (mode == RTM_bind_layered) {
|
||||
// We can't fallback to copy, because that doesn't work
|
||||
// for layered textures. The best thing we can do is raise
|
||||
// an error message.
|
||||
display_cat.error() <<
|
||||
"add_render_texture: RTM_bind_layered was requested but "
|
||||
"render-to-texture is not supported or has been disabled!\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == RTM_bind_or_copy) {
|
||||
if (mode == RTM_bind_layered && _gsg != NULL && !_gsg->get_supports_geometry_shaders()) {
|
||||
// Layered FBOs require a geometry shader to write to
|
||||
// any but the first layer.
|
||||
display_cat.warning() <<
|
||||
"add_render_texture: RTM_bind_layered was requested but "
|
||||
"geometry shaders are not supported!\n";
|
||||
}
|
||||
|
||||
if (mode == RTM_bind_or_copy || mode == RTM_bind_layered) {
|
||||
// If we're still planning on binding, indicate it in texture
|
||||
// properly.
|
||||
tex->set_render_to_texture(true);
|
||||
|
|
@ -1037,8 +1054,7 @@ make_cube_map(const string &name, int size, NodePath &camera_rig,
|
|||
buffer->set_clear_depth_active(false);
|
||||
buffer->set_clear_stencil_active(false);
|
||||
|
||||
PT(Lens) lens = new PerspectiveLens;
|
||||
lens->set_fov(90.0f);
|
||||
PT(Lens) lens = new PerspectiveLens(90, 90);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
PT(Camera) camera = new Camera(cube_faces[i]._name);
|
||||
|
|
@ -1336,7 +1352,7 @@ change_scenes(DisplayRegionPipelineReader *new_dr) {
|
|||
RenderTextureMode rtm_mode = (*ri)._rtm_mode;
|
||||
Texture *texture = (*ri)._texture;
|
||||
if (rtm_mode != RTM_none) {
|
||||
if (rtm_mode == RTM_bind_or_copy) {
|
||||
if (rtm_mode == RTM_bind_or_copy || rtm_mode == RTM_bind_layered) {
|
||||
// In render-to-texture mode, switch the rendering backend to
|
||||
// the new cube map face, so that the subsequent frame will be
|
||||
// rendered to the new face.
|
||||
|
|
@ -1469,7 +1485,7 @@ prepare_for_deletion() {
|
|||
// buffer until all the textures are gone too.
|
||||
RenderTextures::iterator ri;
|
||||
for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) {
|
||||
if ((*ri)._rtm_mode == RTM_bind_or_copy) {
|
||||
if ((*ri)._rtm_mode == RTM_bind_or_copy || (*ri)._rtm_mode == RTM_bind_layered) {
|
||||
_hold_textures.push_back((*ri)._texture);
|
||||
}
|
||||
}
|
||||
|
|
@ -1488,7 +1504,10 @@ prepare_for_deletion() {
|
|||
// Function: GraphicsOutput::promote_to_copy_texture
|
||||
// Access: Protected
|
||||
// Description: If any textures are marked RTM_bind_or_copy, change
|
||||
// them to RTM_copy_texture.
|
||||
// them to RTM_copy_texture. This does not change
|
||||
// textures that are set to RTM_bind_layered, as
|
||||
// layered framebuffers aren't supported with
|
||||
// RTM_copy_texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
promote_to_copy_texture() {
|
||||
|
|
|
|||
|
|
@ -83,11 +83,29 @@ private:
|
|||
PUBLISHED:
|
||||
enum RenderTextureMode {
|
||||
RTM_none,
|
||||
|
||||
// Try to render to the texture directly, but if that is
|
||||
// not possible, fall back to RTM_copy_texture.
|
||||
RTM_bind_or_copy,
|
||||
|
||||
// Copy the image from the buffer to the texture every frame.
|
||||
RTM_copy_texture,
|
||||
|
||||
// Copy the image from the buffer to system RAM every frame.
|
||||
RTM_copy_ram,
|
||||
|
||||
// Copy the image from the buffer to the texture after a
|
||||
// call to trigger_copy().
|
||||
RTM_triggered_copy_texture,
|
||||
|
||||
// Copy the image from the buffer to system RAM after a
|
||||
// call to trigger_copy().
|
||||
RTM_triggered_copy_ram,
|
||||
|
||||
// Render directly to a layered texture, such as a cube map,
|
||||
// 3D texture or 2D texture array. The layer that is being
|
||||
// rendered to is selected by a geometry shader.
|
||||
RTM_bind_layered,
|
||||
};
|
||||
|
||||
// There are many reasons to call begin_frame/end_frame.
|
||||
|
|
@ -167,7 +185,7 @@ PUBLISHED:
|
|||
INLINE int get_child_sort() const;
|
||||
|
||||
INLINE void trigger_copy();
|
||||
|
||||
|
||||
INLINE DisplayRegion *make_display_region();
|
||||
INLINE DisplayRegion *make_display_region(PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t);
|
||||
DisplayRegion *make_display_region(const LVecBase4 &dimensions);
|
||||
|
|
@ -233,7 +251,7 @@ public:
|
|||
virtual void clear_pipe();
|
||||
|
||||
void set_size_and_recalc(int x, int y);
|
||||
|
||||
|
||||
// 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.
|
||||
|
|
@ -262,7 +280,7 @@ protected:
|
|||
void prepare_for_deletion();
|
||||
void promote_to_copy_texture();
|
||||
bool copy_to_textures();
|
||||
|
||||
|
||||
INLINE void begin_frame_spam(FrameMode mode);
|
||||
INLINE void end_frame_spam(FrameMode mode);
|
||||
INLINE void clear_cube_map_selection();
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ PUBLISHED:
|
|||
BF_fb_props_optional = 0x0800, // FrameBufferProperties can be ignored.
|
||||
BF_size_square = 0x1000, // x_size must equal y_size (e.g. for cube maps)
|
||||
BF_size_power_2 = 0x2000, // x_size and y_size must each be a power of two
|
||||
BF_can_bind_layered = 0x4000, // Need capability: support RTM_bind_layered.
|
||||
};
|
||||
|
||||
INLINE bool is_valid() const;
|
||||
|
|
|
|||
|
|
@ -2722,9 +2722,9 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
|
|||
display_cat.error()
|
||||
<< "PointLight shadow buffers must have an equal width and height!\n";
|
||||
}
|
||||
tex->setup_cube_map(light->_sb_xsize, Texture::T_float, Texture::F_depth_component);
|
||||
tex->setup_cube_map(light->_sb_xsize, Texture::T_unsigned_byte, Texture::F_depth_component);
|
||||
} else {
|
||||
tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_float, Texture::F_depth_component);
|
||||
tex->setup_2d_texture(light->_sb_xsize, light->_sb_ysize, Texture::T_unsigned_byte, Texture::F_depth_component);
|
||||
}
|
||||
tex->make_ram_image();
|
||||
sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
TypeHandle CLP(GraphicsBuffer)::_type_handle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: glGraphicsBuffer::Constructor
|
||||
|
|
@ -37,8 +36,6 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe,
|
|||
_screenshot_buffer_type = RenderBuffer::T_front;
|
||||
|
||||
// Initialize these.
|
||||
_num_faces = 0;
|
||||
memset(_fbo, 0, sizeof(_fbo));
|
||||
_fbo_multisample = 0;
|
||||
_initial_clear = true;
|
||||
_needs_rebuild = true;
|
||||
|
|
@ -75,6 +72,7 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe,
|
|||
|
||||
_rb_size_x = 0;
|
||||
_rb_size_y = 0;
|
||||
_rb_size_z = 0;
|
||||
for (int i=0; i<RTP_COUNT; i++) {
|
||||
_rb[i] = 0;
|
||||
_tex[i] = 0;
|
||||
|
|
@ -100,14 +98,14 @@ CLP(GraphicsBuffer)::
|
|||
CLP(GraphicsBuffer) *graphics_buffer;
|
||||
list <CLP(GraphicsBuffer) *>::iterator graphics_buffer_iterator;
|
||||
|
||||
graphics_buffer_iterator = _shared_depth_buffer_list.begin( );
|
||||
while (graphics_buffer_iterator != _shared_depth_buffer_list.end( )) {
|
||||
graphics_buffer_iterator = _shared_depth_buffer_list.begin();
|
||||
while (graphics_buffer_iterator != _shared_depth_buffer_list.end()) {
|
||||
graphics_buffer = (*graphics_buffer_iterator);
|
||||
if (graphics_buffer) {
|
||||
// this call removes the entry from the list
|
||||
graphics_buffer -> unshare_depth_buffer();
|
||||
graphics_buffer->unshare_depth_buffer();
|
||||
}
|
||||
graphics_buffer_iterator = _shared_depth_buffer_list.begin( );
|
||||
graphics_buffer_iterator = _shared_depth_buffer_list.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -164,9 +162,9 @@ begin_frame(FrameMode mode, Thread *current_thread) {
|
|||
_needs_rebuild = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rebuild_bitplanes();
|
||||
|
||||
|
||||
if (_needs_rebuild) {
|
||||
// If we still need rebuild, something went wrong with
|
||||
// rebuild_bitplanes().
|
||||
|
|
@ -196,24 +194,28 @@ check_fbo() {
|
|||
GLCAT.error() << "EXT_framebuffer_object reports non-framebuffer-completeness:\n";
|
||||
switch(status) {
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_UNSUPPORTED_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_UNSUPPORTED"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; break;
|
||||
#ifndef OPENGLES_2
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_FORMATS"; break;
|
||||
#endif
|
||||
#ifndef OPENGLES
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT"; break;
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB:
|
||||
GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_LAYER_COUNT"; break;
|
||||
#endif
|
||||
default:
|
||||
GLCAT.error() << "UNKNOWN PROBLEM " << (int)status; break;
|
||||
|
|
@ -246,10 +248,14 @@ rebuild_bitplanes() {
|
|||
DCAST_INTO_V(glgsg, _gsg);
|
||||
|
||||
if (!_needs_rebuild) {
|
||||
glgsg->bind_fbo(_fbo[0]);
|
||||
if (_fbo.size() > 0) {
|
||||
glgsg->bind_fbo(_fbo[0]);
|
||||
} else {
|
||||
glgsg->bind_fbo(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Calculate bitplane size. This can be larger than the buffer.
|
||||
if (_creation_flags & GraphicsPipe::BF_size_track_host) {
|
||||
if ((_host->get_x_size() != _x_size)||
|
||||
|
|
@ -271,34 +277,69 @@ rebuild_bitplanes() {
|
|||
_rb_size_y = bitplane_y;
|
||||
rb_resize = true;
|
||||
}
|
||||
|
||||
_rb_size_z = 1;
|
||||
|
||||
int num_fbos = 1;
|
||||
|
||||
// These variables indicate what should be bound to each bitplane.
|
||||
Texture *attach[RTP_COUNT];
|
||||
memset(attach, 0, sizeof(Texture *) * RTP_COUNT);
|
||||
|
||||
|
||||
// Sort the textures list into appropriate slots.
|
||||
bool any_cube_maps = false;
|
||||
{
|
||||
CDReader cdata(_cycler);
|
||||
|
||||
// Determine whether this will be a layered or a regular FBO.
|
||||
// If layered, the number of _rb_size_z will be higher than 1.
|
||||
for (size_t i = 0; i != cdata->_textures.size(); ++i) {
|
||||
const RenderTexture &rt = cdata->_textures[i];
|
||||
RenderTextureMode rtm_mode = rt._rtm_mode;
|
||||
if (rtm_mode != RTM_bind_or_copy) {
|
||||
Texture *tex = rt._texture;
|
||||
|
||||
if (rtm_mode == RTM_bind_layered) {
|
||||
_rb_size_z = max(_rb_size_z, tex->get_z_size());
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != cdata->_textures.size(); ++i) {
|
||||
const RenderTexture &rt = cdata->_textures[i];
|
||||
RenderTextureMode rtm_mode = rt._rtm_mode;
|
||||
Texture *tex = rt._texture;
|
||||
|
||||
if (rtm_mode == RTM_bind_layered) {
|
||||
if (tex->get_z_size() != _rb_size_z) {
|
||||
GLCAT.warning()
|
||||
<< "All textures attached to layered FBO should have the same layer count!\n";
|
||||
}
|
||||
} else if (tex->get_z_size() > 1) {
|
||||
num_fbos = max(num_fbos, tex->get_z_size());
|
||||
}
|
||||
|
||||
if (rtm_mode != RTM_bind_or_copy && rtm_mode != RTM_bind_layered) {
|
||||
continue;
|
||||
}
|
||||
Texture *tex = rt._texture;
|
||||
RenderTexturePlane plane = rt._plane;
|
||||
|
||||
// If it's a not a 2D texture or a cube map, punt it.
|
||||
|
||||
// If we can't bind this type of texture, punt it.
|
||||
if ((tex->get_texture_type() != Texture::TT_2d_texture) &&
|
||||
(tex->get_texture_type() != Texture::TT_3d_texture) &&
|
||||
(tex->get_texture_type() != Texture::TT_2d_texture_array) &&
|
||||
(tex->get_texture_type() != Texture::TT_cube_map)) {
|
||||
((CData *)cdata.p())->_textures[i]._rtm_mode = RTM_copy_texture;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_rb_size_z > 1 && tex->get_texture_type() == Texture::TT_2d_texture) {
|
||||
// We can't bind a 2D texture to a layered FBO. If the user happened
|
||||
// to request RTM_bind_layered for a 2D texture, that's just silly,
|
||||
// and we can't render to anything but the first layer anyway.
|
||||
((CData *)cdata.p())->_textures[i]._rtm_mode = RTM_copy_texture;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If I can't find an appropriate slot, or if there's
|
||||
// already a texture bound to this slot, then punt
|
||||
// this texture.
|
||||
RenderTexturePlane plane = rt._plane;
|
||||
if (attach[plane]) {
|
||||
((CData *)cdata.p())->_textures[i]._rtm_mode = RTM_copy_texture;
|
||||
continue;
|
||||
|
|
@ -306,55 +347,93 @@ rebuild_bitplanes() {
|
|||
|
||||
// Assign the texture to this slot.
|
||||
attach[plane] = tex;
|
||||
if (tex->get_texture_type() == Texture::TT_cube_map) {
|
||||
any_cube_maps = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Decide whether we should use a depth stencil or just a regular depth attachment.
|
||||
// If nothing was attached to either RTP_depth_stencil or RTP_depth, we use a
|
||||
// depth-stencil renderbuffer.
|
||||
_use_depth_stencil = false;
|
||||
if (_gsg->get_supports_depth_stencil()) {
|
||||
if (attach[RTP_depth_stencil]) {
|
||||
// This is the obvious case, of course.
|
||||
_use_depth_stencil = true;
|
||||
|
||||
} else if (attach[RTP_depth]) {
|
||||
// We won't use a depth stencil texture as the user
|
||||
// explicitly bound something to RTP_depth.
|
||||
_use_depth_stencil = false;
|
||||
|
||||
} else if (_fb_properties.get_depth_bits() > 24) {
|
||||
// We can't give more than 24 depth bits with a depth-stencil buffer.
|
||||
_use_depth_stencil = false;
|
||||
|
||||
} else if (_fb_properties.get_stencil_bits() > 0) {
|
||||
// The user requested stencil bits. Let's take the hint.
|
||||
_use_depth_stencil = true;
|
||||
|
||||
} else if (_fb_properties.get_depth_bits() > 0) {
|
||||
// Let's use a depth stencil buffer by default, if a depth
|
||||
// buffer was requested.
|
||||
_use_depth_stencil = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Knowing this, we can already be a tiny bit
|
||||
// more accurate about the framebuffer properties.
|
||||
if (_use_depth_stencil) {
|
||||
_fb_properties.set_depth_bits(24);
|
||||
_fb_properties.set_stencil_bits(8);
|
||||
} else {
|
||||
_fb_properties.set_stencil_bits(0);
|
||||
}
|
||||
|
||||
// Having both a depth texture and a depth_stencil texture is
|
||||
// invalid: depth_stencil implies depth, and we can't bind them
|
||||
// both. Detect that case, normalize it, and complain.
|
||||
if (( attach[RTP_depth] != NULL ) && ( attach[RTP_depth_stencil] != NULL )) {
|
||||
if (_use_depth_stencil && attach[RTP_depth] && attach[RTP_depth_stencil]) {
|
||||
attach[RTP_depth] = NULL;
|
||||
GLCAT.warning() << "Attempt to bind both Depth and DepthStencil bitplanes.\n";
|
||||
}
|
||||
|
||||
_num_faces = 1;
|
||||
if (any_cube_maps) {
|
||||
_num_faces = 6;
|
||||
GLCAT.warning() << "Attempt to bind both RTP_depth and RTP_depth_stencil bitplanes.\n";
|
||||
}
|
||||
|
||||
// Now create the FBO's.
|
||||
for (int face = 0; face < _num_faces; ++face) {
|
||||
_fbo.reserve(num_fbos);
|
||||
for (int layer = 0; layer < num_fbos; ++layer) {
|
||||
if (layer >= _fbo.size()) {
|
||||
_fbo.push_back(0);
|
||||
}
|
||||
|
||||
// Bind the FBO
|
||||
if (_fbo[face] == 0) {
|
||||
glgsg->_glGenFramebuffers(1, &_fbo[face]);
|
||||
if (_fbo[face] == 0) {
|
||||
if (_fbo[layer] == 0) {
|
||||
glgsg->_glGenFramebuffers(1, &_fbo[layer]);
|
||||
if (_fbo[layer] == 0) {
|
||||
report_my_gl_errors();
|
||||
return;
|
||||
}
|
||||
}
|
||||
glgsg->bind_fbo(_fbo[face]);
|
||||
glgsg->bind_fbo(_fbo[layer]);
|
||||
|
||||
// For all slots, update the slot.
|
||||
|
||||
bind_slot(face, rb_resize, attach, RTP_depth_stencil, GL_DEPTH_ATTACHMENT_EXT);
|
||||
bind_slot(face, rb_resize, attach, RTP_depth, GL_DEPTH_ATTACHMENT_EXT);
|
||||
bind_slot(face, rb_resize, attach, RTP_color, GL_COLOR_ATTACHMENT0_EXT);
|
||||
if (_use_depth_stencil) {
|
||||
bind_slot(layer, rb_resize, attach, RTP_depth_stencil, GL_DEPTH_ATTACHMENT_EXT);
|
||||
} else if (attach[RTP_depth] || _fb_properties.get_depth_bits() > 0) {
|
||||
bind_slot(layer, rb_resize, attach, RTP_depth, GL_DEPTH_ATTACHMENT_EXT);
|
||||
}
|
||||
|
||||
int next = GL_COLOR_ATTACHMENT0_EXT;
|
||||
if (attach[RTP_color] || _fb_properties.get_color_bits() > 0) {
|
||||
bind_slot(layer, rb_resize, attach, RTP_color, next++);
|
||||
}
|
||||
|
||||
#ifndef OPENGLES
|
||||
int next = GL_COLOR_ATTACHMENT1_EXT;
|
||||
for (int i=0; i<_fb_properties.get_aux_rgba(); i++) {
|
||||
bind_slot(face, rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next);
|
||||
next += 1;
|
||||
bind_slot(layer, rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next++);
|
||||
}
|
||||
for (int i=0; i<_fb_properties.get_aux_hrgba(); i++) {
|
||||
bind_slot(face, rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), next);
|
||||
next += 1;
|
||||
bind_slot(layer, rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), next++);
|
||||
}
|
||||
for (int i=0; i<_fb_properties.get_aux_float(); i++) {
|
||||
bind_slot(face, rb_resize, attach, (RenderTexturePlane)(RTP_aux_float_0+i), next);
|
||||
next += 1;
|
||||
bind_slot(layer, rb_resize, attach, (RenderTexturePlane)(RTP_aux_float_0+i), next++);
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
|
|
@ -366,26 +445,32 @@ rebuild_bitplanes() {
|
|||
}
|
||||
|
||||
#ifndef OPENGLES
|
||||
// Setup any required multisample buffers.
|
||||
if (_requested_multisamples) {
|
||||
// Setup any required multisample buffers. Does not work for layered buffers.
|
||||
if (_requested_multisamples && _rb_size_z == 1) {
|
||||
if (_fbo_multisample == 0) {
|
||||
glgsg->_glGenFramebuffers(1, &_fbo_multisample);
|
||||
}
|
||||
glgsg->bind_fbo(_fbo_multisample);
|
||||
bind_slot_multisample(rb_resize, attach, RTP_depth, GL_DEPTH_ATTACHMENT_EXT);
|
||||
bind_slot_multisample(rb_resize, attach, RTP_color, GL_COLOR_ATTACHMENT0_EXT);
|
||||
|
||||
int next = GL_COLOR_ATTACHMENT1_EXT;
|
||||
if (_use_depth_stencil || attach[RTP_depth] || _fb_properties.get_depth_bits() > 0) {
|
||||
bind_slot_multisample(rb_resize, attach, RTP_depth, GL_DEPTH_ATTACHMENT_EXT);
|
||||
}
|
||||
|
||||
int next = GL_COLOR_ATTACHMENT0_EXT;
|
||||
if (attach[RTP_color] || _fb_properties.get_color_bits() > 0) {
|
||||
bind_slot_multisample(rb_resize, attach, RTP_color, next++);
|
||||
}
|
||||
|
||||
for (int i=0; i<_fb_properties.get_aux_rgba(); i++) {
|
||||
bind_slot_multisample(rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next);
|
||||
bind_slot_multisample(rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next++);
|
||||
next += 1;
|
||||
}
|
||||
for (int i=0; i<_fb_properties.get_aux_hrgba(); i++) {
|
||||
bind_slot_multisample(rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), next);
|
||||
bind_slot_multisample(rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), next++);
|
||||
next += 1;
|
||||
}
|
||||
for (int i=0; i<_fb_properties.get_aux_float(); i++) {
|
||||
bind_slot_multisample(rb_resize, attach, (RenderTexturePlane)(RTP_aux_float_0+i), next);
|
||||
bind_slot_multisample(rb_resize, attach, (RenderTexturePlane)(RTP_aux_float_0+i), next++);
|
||||
next += 1;
|
||||
}
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
|
@ -432,96 +517,155 @@ rebuild_bitplanes() {
|
|||
// specified bitplane.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsBuffer)::
|
||||
bind_slot(int face, bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum attachpoint) {
|
||||
bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum attachpoint) {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
|
||||
#ifdef OPENGLES
|
||||
GLuint glFormat = GL_RGBA4;
|
||||
#else
|
||||
GLuint glFormat = GL_RGBA;
|
||||
switch (slot) {
|
||||
case RTP_aux_rgba_0:
|
||||
case RTP_aux_rgba_1:
|
||||
case RTP_aux_rgba_2:
|
||||
case RTP_aux_rgba_3:
|
||||
glFormat = GL_RGBA;
|
||||
break;
|
||||
case RTP_aux_hrgba_0:
|
||||
case RTP_aux_hrgba_1:
|
||||
case RTP_aux_hrgba_2:
|
||||
case RTP_aux_hrgba_3:
|
||||
glFormat = GL_RGBA16F_ARB;
|
||||
break;
|
||||
};
|
||||
#endif
|
||||
|
||||
Texture *tex = attach[slot];
|
||||
if (tex) {
|
||||
bool is_cube_map = (tex->get_texture_type() == Texture::TT_cube_map);
|
||||
_tex[slot] = tex;
|
||||
|
||||
GLenum target = GL_TEXTURE_2D;
|
||||
if (is_cube_map) {
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||
if (tex && layer >= tex->get_z_size()) {
|
||||
// If the requested layer index exceeds the number of layers
|
||||
// in the texture, we will not bind this layer.
|
||||
tex = NULL;
|
||||
}
|
||||
|
||||
if (!tex && _rb_size_z > 1) {
|
||||
// Since there is no such thing as a layered renderbuffer (to my knowledge),
|
||||
// we have to create a dummy texture to render to if no texture was provided.
|
||||
tex = new Texture();
|
||||
|
||||
if (_rb_size_z > 1) {
|
||||
// Apparently, it doesn't make a difference whether we use setup_cube_map
|
||||
// or setup_2d_texture_array here, since it's the same internal storage.
|
||||
tex->setup_2d_texture_array(_rb_size_z);
|
||||
} else {
|
||||
tex->setup_2d_texture();
|
||||
}
|
||||
}
|
||||
|
||||
if (tex) {
|
||||
GLenum target = glgsg->get_texture_target(tex->get_texture_type());
|
||||
if (target == GL_TEXTURE_CUBE_MAP) {
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
|
||||
}
|
||||
|
||||
// Bind the texture to the slot.
|
||||
tex->set_x_size(_rb_size_x);
|
||||
tex->set_y_size(_rb_size_y);
|
||||
if (target != GL_TEXTURE_CUBE_MAP && _rb_size_z > 1) {
|
||||
tex->set_z_size(_rb_size_z);
|
||||
}
|
||||
tex->set_pad_size(_rb_size_x - _x_size, _rb_size_y - _y_size);
|
||||
|
||||
// Adjust the texture format based on the requested framebuffer settings.
|
||||
switch (slot) {
|
||||
case RTP_depth:
|
||||
if (_fb_properties.get_depth_bits() >= 32) {
|
||||
tex->set_format(Texture::F_depth_component32);
|
||||
} else if (_fb_properties.get_depth_bits() > 16) {
|
||||
tex->set_format(Texture::F_depth_component24);
|
||||
} else if (_fb_properties.get_depth_bits() > 8) {
|
||||
tex->set_format(Texture::F_depth_component16);
|
||||
} else {
|
||||
tex->set_format(Texture::F_depth_component);
|
||||
}
|
||||
break;
|
||||
case RTP_depth_stencil:
|
||||
tex->set_format(Texture::F_depth_stencil);
|
||||
tex->set_component_type(Texture::T_unsigned_int_24_8);
|
||||
break;
|
||||
case RTP_aux_hrgba_0:
|
||||
case RTP_aux_hrgba_1:
|
||||
case RTP_aux_hrgba_2:
|
||||
case RTP_aux_hrgba_3:
|
||||
tex->set_format(Texture::F_rgba16);
|
||||
break;
|
||||
case RTP_aux_float_0:
|
||||
case RTP_aux_float_1:
|
||||
case RTP_aux_float_2:
|
||||
case RTP_aux_float_3:
|
||||
tex->set_format(Texture::F_rgba32);
|
||||
tex->set_component_type(Texture::T_float);
|
||||
break;
|
||||
default:
|
||||
tex->set_format(Texture::F_rgba);
|
||||
}
|
||||
|
||||
// Create the OpenGL texture object.
|
||||
TextureContext *tc = tex->prepare_now(0, glgsg->get_prepared_objects(), glgsg);
|
||||
nassertv(tc != (TextureContext *)NULL);
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
glgsg->update_texture(tc, true);
|
||||
|
||||
_use_depth_stencil = false;
|
||||
if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) {
|
||||
if ( _gsg->get_supports_depth_stencil() && tex->get_format() == Texture::F_depth_stencil ) {
|
||||
tex->set_component_type(Texture::T_unsigned_int_24_8);
|
||||
_use_depth_stencil = true;
|
||||
}
|
||||
#ifndef OPENGLES
|
||||
GLclampf priority = 1.0f;
|
||||
glPrioritizeTextures(1, >c->_index, &priority);
|
||||
#endif
|
||||
glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
target, gtc->_index, 0);
|
||||
if (_use_depth_stencil) {
|
||||
glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
target, gtc->_index, 0);
|
||||
if (_rb_size_z == 1) {
|
||||
if (target == GL_TEXTURE_3D) {
|
||||
glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
target, gtc->_index, 0, layer);
|
||||
} else if (target == GL_TEXTURE_2D_ARRAY_EXT) {
|
||||
glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
gtc->_index, 0, layer);
|
||||
} else {
|
||||
glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
target, gtc->_index, 0);
|
||||
}
|
||||
} else {
|
||||
glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
gtc->_index, 0);
|
||||
}
|
||||
|
||||
#ifndef OPENGLES
|
||||
GLint depth_size = 0, stencil_size = 0;
|
||||
GLint depth_size = 0;
|
||||
GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size);
|
||||
if (_use_depth_stencil) {
|
||||
GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
|
||||
}
|
||||
_fb_properties.set_depth_bits(depth_size);
|
||||
_fb_properties.set_stencil_bits(stencil_size);
|
||||
#endif
|
||||
|
||||
if (slot == RTP_depth_stencil) {
|
||||
if (_rb_size_z == 1) {
|
||||
if (target == GL_TEXTURE_3D) {
|
||||
glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
target, gtc->_index, 0, layer);
|
||||
} else if (target == GL_TEXTURE_2D_ARRAY_EXT) {
|
||||
glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
gtc->_index, 0, layer);
|
||||
} else {
|
||||
glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
target, gtc->_index, 0);
|
||||
}
|
||||
} else {
|
||||
glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
gtc->_index, 0);
|
||||
}
|
||||
|
||||
GLint stencil_size = 0;
|
||||
GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
|
||||
_fb_properties.set_stencil_bits(stencil_size);
|
||||
}
|
||||
|
||||
} else {
|
||||
#ifdef OPENGLES
|
||||
tex->set_format(Texture::F_rgba4);
|
||||
#else
|
||||
if (glFormat == GL_RGBA16F_ARB) {
|
||||
tex->set_format(Texture::F_rgba16);
|
||||
} else if (glFormat == GL_RGBA32F_ARB) {
|
||||
tex->set_format(Texture::F_rgba32);
|
||||
} else {
|
||||
tex->set_format(Texture::F_rgba);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES
|
||||
GLclampf priority = 1.0f;
|
||||
glPrioritizeTextures(1, >c->_index, &priority);
|
||||
#endif
|
||||
glgsg->update_texture(tc, true);
|
||||
glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
target, gtc->_index, 0);
|
||||
if (_rb_size_z == 1) {
|
||||
if (target == GL_TEXTURE_3D) {
|
||||
glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
target, gtc->_index, 0, layer);
|
||||
} else if (target == GL_TEXTURE_2D_ARRAY_EXT) {
|
||||
glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
gtc->_index, 0, layer);
|
||||
} else {
|
||||
glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
target, gtc->_index, 0);
|
||||
}
|
||||
} else {
|
||||
glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
gtc->_index, 0);
|
||||
}
|
||||
#ifndef OPENGLES
|
||||
if (attachpoint == GL_COLOR_ATTACHMENT0_EXT) {
|
||||
GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0;
|
||||
|
|
@ -536,28 +680,77 @@ bind_slot(int face, bool rb_resize, Texture **attach, RenderTexturePlane slot, G
|
|||
#endif
|
||||
}
|
||||
|
||||
_tex[slot] = tex;
|
||||
|
||||
// If there was a renderbuffer bound to this slot, delete it.
|
||||
if (_rb[slot] != 0) {
|
||||
glgsg->_glDeleteRenderbuffers(1, &(_rb[slot]));
|
||||
_rb[slot] = 0;
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
} else {
|
||||
|
||||
// Disconnect from any texture that was previously bound to this slot.
|
||||
_tex[slot] = 0;
|
||||
|
||||
#ifndef OPENGLES_2
|
||||
// Check for the tricky case of a depth_stencil buffer:
|
||||
// If we think we need one, but we have a texture bound in the depth slot,
|
||||
// then we DON'T want to create a depth_stencil buffer here (because depth is
|
||||
// a subset of depth_stencil).
|
||||
if (( slot == RTP_depth_stencil ) && ( _gsg->get_supports_depth_stencil() != false ) &&
|
||||
( attach[RTP_depth] != NULL )) {
|
||||
return;
|
||||
// No texture to bind. Instead, create a renderbuffer.
|
||||
// Choose a suitable renderbuffer format based on the requirements.
|
||||
#ifdef OPENGLES
|
||||
GLuint gl_format = GL_RGBA4;
|
||||
switch (slot) {
|
||||
case RTP_depth_stencil:
|
||||
gl_format = GL_DEPTH_STENCIL_OES;
|
||||
break;
|
||||
case RTP_depth:
|
||||
gl_format = GL_DEPTH_COMPONENT16;
|
||||
break;
|
||||
//case RTP_stencil:
|
||||
// gl_format = GL_STENCIL_INDEX8;
|
||||
// break
|
||||
default:
|
||||
if (_fb_properties.get_alpha_bits() == 0) {
|
||||
gl_format = GL_RGB565;
|
||||
} else if (_fb_properties.get_color_bits() == 15
|
||||
&& _fb_properties.get_alpha_bits() == 1) {
|
||||
gl_format = GL_RGB5_A1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
GLuint gl_format = GL_RGBA;
|
||||
switch (slot) {
|
||||
case RTP_depth_stencil:
|
||||
gl_format = GL_DEPTH_STENCIL_EXT;
|
||||
break;
|
||||
case RTP_depth:
|
||||
if (_fb_properties.get_depth_bits() >= 32) {
|
||||
gl_format = GL_DEPTH_COMPONENT32;
|
||||
} else if (_fb_properties.get_depth_bits() > 16) {
|
||||
gl_format = GL_DEPTH_COMPONENT24;
|
||||
} else if (_fb_properties.get_depth_bits() > 8) {
|
||||
gl_format = GL_DEPTH_COMPONENT16;
|
||||
} else {
|
||||
gl_format = GL_DEPTH_COMPONENT;
|
||||
}
|
||||
break;
|
||||
case RTP_aux_rgba_0:
|
||||
case RTP_aux_rgba_1:
|
||||
case RTP_aux_rgba_2:
|
||||
case RTP_aux_rgba_3:
|
||||
gl_format = GL_RGBA;
|
||||
break;
|
||||
case RTP_aux_hrgba_0:
|
||||
case RTP_aux_hrgba_1:
|
||||
case RTP_aux_hrgba_2:
|
||||
case RTP_aux_hrgba_3:
|
||||
gl_format = GL_RGBA16F_ARB;
|
||||
break;
|
||||
case RTP_aux_float_0:
|
||||
case RTP_aux_float_1:
|
||||
case RTP_aux_float_2:
|
||||
case RTP_aux_float_3:
|
||||
gl_format = GL_RGBA32F_ARB;
|
||||
break;
|
||||
default:
|
||||
if (_fb_properties.get_alpha_bits() == 0) {
|
||||
gl_format = GL_RGB;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// If there's no renderbuffer for this slot, create one.
|
||||
|
|
@ -567,71 +760,51 @@ bind_slot(int face, bool rb_resize, Texture **attach, RenderTexturePlane slot, G
|
|||
|
||||
// Allocate and bind the renderbuffer.
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rb[slot]);
|
||||
if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) {
|
||||
#ifndef OPENGLES_2
|
||||
if ( _gsg->get_supports_depth_stencil() != false ) {
|
||||
if ( slot == RTP_depth_stencil ) {
|
||||
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
|
||||
_rb_size_x, _rb_size_y);
|
||||
GLint depth_size = 0;
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &depth_size);
|
||||
_fb_properties.set_depth_bits(depth_size);
|
||||
GLint stencil_size = 0;
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_STENCIL_SIZE_EXT, &stencil_size);
|
||||
_fb_properties.set_stencil_bits(stencil_size);
|
||||
if (slot == RTP_depth_stencil) {
|
||||
// Allocate renderbuffer storage for depth stencil.
|
||||
GLint depth_size = 0, stencil_size = 0;
|
||||
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &depth_size);
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_STENCIL_SIZE_EXT, &stencil_size);
|
||||
_fb_properties.set_depth_bits(depth_size);
|
||||
_fb_properties.set_stencil_bits(stencil_size);
|
||||
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
GLuint rb;
|
||||
|
||||
rb = _rb[slot];
|
||||
if (_shared_depth_buffer) {
|
||||
rb = _shared_depth_buffer -> _rb[slot];
|
||||
}
|
||||
|
||||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, rb);
|
||||
|
||||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, rb);
|
||||
return;
|
||||
|
||||
} else if ( slot == RTP_depth ) {
|
||||
// This is the uber-tricky case, where we DON'T want to bind a depth buffer
|
||||
// if there's already any form of depth_stencil buffer bound (because depth_stencil
|
||||
// is a superset that includes depth).
|
||||
if (( _rb[RTP_depth_stencil] != 0 ) || ( attach[RTP_depth_stencil] != NULL )) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
GLuint rb = _rb[slot];
|
||||
if (_shared_depth_buffer) {
|
||||
rb = _shared_depth_buffer->_rb[slot];
|
||||
}
|
||||
|
||||
// We'll bail out before here if we set a depth_stencil buffer,
|
||||
// or figure out that we're GOING to set a depth_stencil buffer.
|
||||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, rb);
|
||||
|
||||
// If we get here, we're using the simple fallback case.
|
||||
#endif
|
||||
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
|
||||
_rb_size_x, _rb_size_y);
|
||||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, rb);
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
} else if (slot == RTP_depth) {
|
||||
// Allocate renderbuffer storage for regular depth.
|
||||
GLint depth_size = 0;
|
||||
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &depth_size);
|
||||
_fb_properties.set_depth_bits(depth_size);
|
||||
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
GLuint rb;
|
||||
|
||||
rb = _rb[slot];
|
||||
GLuint rb = _rb[slot];
|
||||
if (_shared_depth_buffer) {
|
||||
rb = _shared_depth_buffer -> _rb[slot];
|
||||
rb = _shared_depth_buffer->_rb[slot];
|
||||
}
|
||||
|
||||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, rb);
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
} else {
|
||||
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, glFormat,
|
||||
_rb_size_x, _rb_size_y);
|
||||
glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
|
||||
GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0;
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT, &red_size);
|
||||
glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT, &green_size);
|
||||
|
|
@ -643,10 +816,9 @@ bind_slot(int face, bool rb_resize, Texture **attach, RenderTexturePlane slot, G
|
|||
glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, attachpoint,
|
||||
GL_RENDERBUFFER_EXT, _rb[slot]);
|
||||
|
||||
report_my_gl_errors();
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -675,7 +847,7 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
|
||||
if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) {
|
||||
#ifndef OPENGLES_2
|
||||
if (_gsg->get_supports_depth_stencil() && _use_depth_stencil) {
|
||||
if (_use_depth_stencil) {
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rbm[slot]);
|
||||
if (_requested_coverage_samples) {
|
||||
glgsg->_glRenderbufferStorageMultisampleCoverage(GL_RENDERBUFFER_EXT, _requested_coverage_samples,
|
||||
|
|
@ -699,12 +871,17 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rbm[slot]);
|
||||
GLuint format = GL_DEPTH_COMPONENT;
|
||||
if (tex) {
|
||||
if (tex->get_format() == Texture::F_depth_component16)
|
||||
switch (tex->get_format()) {
|
||||
case Texture::F_depth_component16:
|
||||
format = GL_DEPTH_COMPONENT16;
|
||||
if (tex->get_format() == Texture::F_depth_component24)
|
||||
break;
|
||||
case Texture::F_depth_component24:
|
||||
format = GL_DEPTH_COMPONENT24;
|
||||
if (tex->get_format() == Texture::F_depth_component32)
|
||||
break;
|
||||
case Texture::F_depth_component32:
|
||||
format = GL_DEPTH_COMPONENT32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_requested_coverage_samples) {
|
||||
glgsg->_glRenderbufferStorageMultisampleCoverage(GL_RENDERBUFFER_EXT, _requested_coverage_samples,
|
||||
|
|
@ -726,29 +903,35 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
}
|
||||
} else {
|
||||
Texture *Tex = attach[slot];
|
||||
GLuint glFormat = GL_RGBA;
|
||||
GLuint gl_format = GL_RGBA;
|
||||
#ifndef OPENGLES
|
||||
switch (slot) {
|
||||
case RTP_aux_rgba_0:
|
||||
case RTP_aux_rgba_1:
|
||||
case RTP_aux_rgba_2:
|
||||
case RTP_aux_rgba_3:
|
||||
glFormat = GL_RGBA;
|
||||
gl_format = GL_RGBA;
|
||||
break;
|
||||
case RTP_aux_hrgba_0:
|
||||
case RTP_aux_hrgba_1:
|
||||
case RTP_aux_hrgba_2:
|
||||
case RTP_aux_hrgba_3:
|
||||
glFormat = GL_RGBA16F_ARB;
|
||||
gl_format = GL_RGBA16F_ARB;
|
||||
break;
|
||||
case RTP_aux_float_0:
|
||||
case RTP_aux_float_1:
|
||||
case RTP_aux_float_2:
|
||||
case RTP_aux_float_3:
|
||||
gl_format = GL_RGBA32F_ARB;
|
||||
break;
|
||||
};
|
||||
#endif
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rbm[slot]);
|
||||
if (_requested_coverage_samples) {
|
||||
glgsg->_glRenderbufferStorageMultisampleCoverage(GL_RENDERBUFFER_EXT, _requested_coverage_samples,
|
||||
_requested_multisamples, glFormat, _rb_size_x, _rb_size_y);
|
||||
_requested_multisamples, gl_format, _rb_size_x, _rb_size_y);
|
||||
} else {
|
||||
glgsg->_glRenderbufferStorageMultisample(GL_RENDERBUFFER_EXT, _requested_multisamples, glFormat,
|
||||
glgsg->_glRenderbufferStorageMultisample(GL_RENDERBUFFER_EXT, _requested_multisamples, gl_format,
|
||||
_rb_size_x, _rb_size_y);
|
||||
}
|
||||
#ifndef OPENGLES
|
||||
|
|
@ -838,13 +1021,13 @@ end_frame(FrameMode mode, Thread *current_thread) {
|
|||
// Access: Public, Virtual
|
||||
// Description: Called internally when the window is in
|
||||
// render-to-a-texture mode and we are in the process of
|
||||
// rendering the six faces of a cube map. This should
|
||||
// rendering the six layers of a cube map. This should
|
||||
// do whatever needs to be done to switch the buffer to
|
||||
// the indicated face.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsBuffer)::
|
||||
select_cube_map(int cube_map_index) {
|
||||
nassertv(cube_map_index >=0 && cube_map_index < _num_faces);
|
||||
nassertv(cube_map_index >= 0 && cube_map_index < _fbo.size());
|
||||
|
||||
if (_active_cube_map_index != -1) {
|
||||
// Resolve the multisample rendering for the previous face.
|
||||
|
|
@ -891,23 +1074,40 @@ open_buffer() {
|
|||
|
||||
// Describe the framebuffer properties of the FBO.
|
||||
//
|
||||
// The rule is that the properties should be as close
|
||||
// as possible to those requested, subject to the limits
|
||||
// of the implementation. This particular implementation
|
||||
// is fairly limited. But that's okay, we just have to
|
||||
// tell the truth about what we actually provide by setting
|
||||
// the _fb_properties accurately.
|
||||
// Unfortunately, we can't possibly predict which formats
|
||||
// the implementation will allow us to use at this point, so
|
||||
// we'll just have to make some guesses and parrot the rest
|
||||
// of the properties back to the user.
|
||||
// When we actually attach the textures, we'll update the
|
||||
// properties more appropriately.
|
||||
// This is probably safe, as we can usually bind just about
|
||||
// any supported texture format to the FBO.
|
||||
|
||||
_fb_properties.set_depth_bits(1);
|
||||
_fb_properties.set_color_bits(1);
|
||||
_fb_properties.set_alpha_bits(_host->get_fb_properties().get_alpha_bits());
|
||||
if (_gsg->get_supports_depth_stencil()) {
|
||||
_fb_properties.set_stencil_bits(1);
|
||||
} else {
|
||||
// Rounding the depth bits is not spectacular, but at least we're
|
||||
// telling the user *something* about what we're going to get.
|
||||
if (_fb_properties.get_depth_bits() >= 32) {
|
||||
_fb_properties.set_depth_bits(32);
|
||||
} else if (_fb_properties.get_depth_bits() > 16) {
|
||||
_fb_properties.set_depth_bits(24);
|
||||
} else if (_fb_properties.get_depth_bits() > 8) {
|
||||
_fb_properties.set_depth_bits(16);
|
||||
}
|
||||
|
||||
// We're not going to get more than this, ever.
|
||||
if (_fb_properties.get_color_bits() > 96) {
|
||||
_fb_properties.set_color_bits(96);
|
||||
}
|
||||
if (_fb_properties.get_alpha_bits() > 32) {
|
||||
_fb_properties.set_alpha_bits(32);
|
||||
}
|
||||
|
||||
if (!_gsg->get_supports_depth_stencil()) {
|
||||
// At least we know we won't be getting stencil bits.
|
||||
_fb_properties.set_stencil_bits(0);
|
||||
}
|
||||
_fb_properties.set_accum_bits(0);
|
||||
_fb_properties.set_multisamples(_host->get_fb_properties().get_multisamples());
|
||||
|
||||
_fb_properties.set_back_buffers(0);
|
||||
_fb_properties.set_indexed_color(0);
|
||||
_fb_properties.set_rgb_color(1);
|
||||
|
|
@ -918,6 +1118,7 @@ open_buffer() {
|
|||
_is_valid = true;
|
||||
_needs_rebuild = true;
|
||||
report_my_gl_errors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -963,10 +1164,10 @@ close_buffer() {
|
|||
report_my_gl_errors();
|
||||
|
||||
// Delete the FBO itself.
|
||||
for (int face = 0; face < _num_faces; ++face) {
|
||||
glgsg->_glDeleteFramebuffers(1, &_fbo[face]);
|
||||
for (int i = 0; i < _fbo.size(); ++i) {
|
||||
glgsg->_glDeleteFramebuffers(1, &_fbo[i]);
|
||||
}
|
||||
_num_faces = 0;
|
||||
_fbo.clear();
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
|
|
@ -994,34 +1195,34 @@ share_depth_buffer(GraphicsOutput *graphics_output) {
|
|||
if (this != input_graphics_output && input_graphics_output) {
|
||||
|
||||
state = true;
|
||||
this -> unshare_depth_buffer();
|
||||
this->unshare_depth_buffer();
|
||||
|
||||
// check buffer sizes
|
||||
if (this -> get_x_size() != input_graphics_output -> get_x_size()) {
|
||||
GLCAT.error() << "share_depth_buffer: non matching width \n";
|
||||
if (this->get_x_size() != input_graphics_output->get_x_size()) {
|
||||
GLCAT.error() << "share_depth_buffer: non-matching width\n";
|
||||
state = false;
|
||||
}
|
||||
|
||||
if (this -> get_y_size() != input_graphics_output -> get_y_size()) {
|
||||
GLCAT.error() << "share_depth_buffer: non matching height \n";
|
||||
if (this->get_y_size() != input_graphics_output->get_y_size()) {
|
||||
GLCAT.error() << "share_depth_buffer: non-matching height\n";
|
||||
state = false;
|
||||
}
|
||||
|
||||
// Check multisample compatibility.
|
||||
if ( this->get_multisample_count() != input_graphics_output->get_multisample_count() ) {
|
||||
GLCAT.error() << "share_depth_buffer: non matching multisamples \n";
|
||||
if (this->get_multisample_count() != input_graphics_output->get_multisample_count()) {
|
||||
GLCAT.error() << "share_depth_buffer: non-matching multisamples\n";
|
||||
state = false;
|
||||
}
|
||||
|
||||
if ( this->get_coverage_sample_count() != input_graphics_output->get_coverage_sample_count() ) {
|
||||
GLCAT.error() << "share_depth_buffer: non matching multisamples \n";
|
||||
if (this->get_coverage_sample_count() != input_graphics_output->get_coverage_sample_count()) {
|
||||
GLCAT.error() << "share_depth_buffer: non-matching multisamples\n";
|
||||
state = false;
|
||||
}
|
||||
|
||||
if (state) {
|
||||
// let the input GraphicsOutput know that there is an object
|
||||
// sharing its depth buffer
|
||||
input_graphics_output -> register_shared_depth_buffer(this);
|
||||
input_graphics_output->register_shared_depth_buffer(this);
|
||||
_shared_depth_buffer = input_graphics_output;
|
||||
state = true;
|
||||
}
|
||||
|
|
@ -1041,7 +1242,7 @@ unshare_depth_buffer() {
|
|||
if (_shared_depth_buffer) {
|
||||
// let the GraphicsOutput know that this object is no longer
|
||||
// sharing its depth buffer
|
||||
_shared_depth_buffer -> unregister_shared_depth_buffer(this);
|
||||
_shared_depth_buffer->unregister_shared_depth_buffer(this);
|
||||
_shared_depth_buffer = 0;
|
||||
_needs_rebuild = true;
|
||||
}
|
||||
|
|
@ -1139,13 +1340,15 @@ resolve_multisamples() {
|
|||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
|
||||
nassertv(_fbo.size() > 0);
|
||||
|
||||
glgsg->report_my_gl_errors();
|
||||
GLuint fbo = _fbo[0];
|
||||
if (_active_cube_map_index != -1) {
|
||||
fbo = _fbo[_active_cube_map_index];
|
||||
}
|
||||
glgsg->_glBindFramebuffer( GL_DRAW_FRAMEBUFFER_EXT, fbo );
|
||||
glgsg->_glBindFramebuffer( GL_READ_FRAMEBUFFER_EXT, _fbo_multisample );
|
||||
glgsg->_glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo);
|
||||
glgsg->_glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, _fbo_multisample);
|
||||
|
||||
// If the depth buffer is shared, resolve it only on the last to render FBO.
|
||||
int do_depth_blit = 0;
|
||||
|
|
|
|||
|
|
@ -103,8 +103,7 @@ private:
|
|||
|
||||
// We create one FBO for each cube map face we'll be rendering to.
|
||||
// If we aren't rendering to any cube maps, we use only _fbo[0].
|
||||
GLuint _fbo[6];
|
||||
int _num_faces;
|
||||
pvector<GLuint> _fbo;
|
||||
|
||||
// For multisample we render first to a multisample buffer, then
|
||||
// filter it to _fbo[face] at the end of the frame.
|
||||
|
|
@ -115,6 +114,7 @@ private:
|
|||
|
||||
int _rb_size_x;
|
||||
int _rb_size_y;
|
||||
int _rb_size_z;
|
||||
|
||||
// The texture or render buffer bound to each plane.
|
||||
PT(Texture) _tex[RTP_COUNT];
|
||||
|
|
@ -158,4 +158,3 @@ private:
|
|||
};
|
||||
|
||||
#include "glGraphicsBuffer_src.I"
|
||||
|
||||
|
|
|
|||
|
|
@ -581,6 +581,8 @@ reset() {
|
|||
get_extension_func(GLPREFIX_QUOTED, "TexImage3D");
|
||||
_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "TexSubImage3D");
|
||||
_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "CopyTexSubImage3D");
|
||||
|
||||
} else if (has_extension("GL_EXT_texture3D")) {
|
||||
_supports_3d_texture = true;
|
||||
|
|
@ -589,14 +591,23 @@ reset() {
|
|||
get_extension_func(GLPREFIX_QUOTED, "TexImage3DEXT");
|
||||
_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "TexSubImage3DEXT");
|
||||
} else if (has_extension("GL_OES_texture3D") || has_extension("GL_OES_texture_3D")) {
|
||||
|
||||
_glCopyTexSubImage3D = NULL;
|
||||
if (has_extension("GL_EXT_copy_texture")) {
|
||||
_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "CopyTexSubImage3DEXT");
|
||||
}
|
||||
|
||||
} else if (has_extension("GL_OES_texture_3D")) {
|
||||
_supports_3d_texture = true;
|
||||
|
||||
_glTexImage3D = (PFNGLTEXIMAGE3DPROC_P)
|
||||
get_extension_func(GLPREFIX_QUOTED, "TexImage3DOES");
|
||||
_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "TexSubImage3DOES");
|
||||
|
||||
_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "CopyTexSubImage3DOES");
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DOES)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture3DOES");
|
||||
|
|
@ -611,9 +622,18 @@ reset() {
|
|||
}
|
||||
}
|
||||
|
||||
_supports_2d_texture_array = false;
|
||||
#ifndef OPENGLES
|
||||
_supports_2d_texture_array = has_extension("GL_EXT_texture_array");
|
||||
if (_supports_2d_texture_array) {
|
||||
_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferTextureLayerEXT");
|
||||
} else {
|
||||
// ARB_geometry_shader4 also provides a version.
|
||||
_glFramebufferTextureLayer = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
_supports_cube_map = true;
|
||||
#else
|
||||
|
|
@ -1048,6 +1068,13 @@ reset() {
|
|||
if (_supports_geometry_shaders) {
|
||||
_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "ProgramParameteri");
|
||||
_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREARBPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferTextureARB");
|
||||
|
||||
if (_glFramebufferTextureLayer == NULL) {
|
||||
_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferTextureLayerARB");
|
||||
}
|
||||
}
|
||||
if (_supports_tessellation_shaders) {
|
||||
_glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)
|
||||
|
|
@ -1113,12 +1140,6 @@ reset() {
|
|||
_glCheckFramebufferStatus = glCheckFramebufferStatus;
|
||||
_glFramebufferTexture1D = NULL;
|
||||
_glFramebufferTexture2D = glFramebufferTexture2D;
|
||||
if (has_extension("GL_OES_texture3D")) {
|
||||
_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DOES)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture3DOES");
|
||||
} else {
|
||||
_glFramebufferTexture3D = NULL;
|
||||
}
|
||||
_glFramebufferRenderbuffer = glFramebufferRenderbuffer;
|
||||
_glGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
|
||||
_glGenerateMipmap = glGenerateMipmap;
|
||||
|
|
@ -1189,7 +1210,6 @@ reset() {
|
|||
_glFramebufferTexture1D = NULL;
|
||||
_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture2DOES");
|
||||
_glFramebufferTexture3D = NULL;
|
||||
_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEROESPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "FramebufferRenderbufferOES");
|
||||
_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC)
|
||||
|
|
@ -4170,8 +4190,8 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
|
|||
// Description: Copy the pixels within the indicated display
|
||||
// region from the framebuffer into texture memory.
|
||||
//
|
||||
// If z > -1, it is the cube map index into which to
|
||||
// copy.
|
||||
// If z > -1, it is the cube map index or layer index
|
||||
// into which to copy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
||||
|
|
@ -4184,7 +4204,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
|||
|
||||
int xo, yo, w, h;
|
||||
dr->get_region_pixels(xo, yo, w, h);
|
||||
tex->set_size_padded(w, h);
|
||||
tex->set_size_padded(w, h, tex->get_z_size());
|
||||
|
||||
if (tex->get_compression() == Texture::CM_default) {
|
||||
// Unless the user explicitly turned on texture compression, turn
|
||||
|
|
@ -4194,16 +4214,41 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
|||
|
||||
// Sanity check everything.
|
||||
if (z >= 0) {
|
||||
if (!_supports_cube_map) {
|
||||
if (z >= tex->get_z_size()) {
|
||||
// This can happen, when textures with different layer counts
|
||||
// are attached to a buffer. We simply ignore this if it happens.
|
||||
return false;
|
||||
}
|
||||
nassertr(z < 6, false);
|
||||
nassertr(tex->get_texture_type() == Texture::TT_cube_map, false);
|
||||
|
||||
if ((w != tex->get_x_size()) ||
|
||||
(h != tex->get_y_size()) ||
|
||||
(w != h)) {
|
||||
(h != tex->get_y_size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tex->get_texture_type() == Texture::TT_cube_map) {
|
||||
if (!_supports_cube_map) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nassertr(z < 6, false);
|
||||
if (w != h) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (tex->get_texture_type() == Texture::TT_3d_texture) {
|
||||
if (!_supports_3d_texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (tex->get_texture_type() == Texture::TT_2d_texture_array) {
|
||||
if (!_supports_2d_texture_array) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
GLCAT.error()
|
||||
<< "Don't know how to copy framebuffer to texture " << *tex << "\n";
|
||||
}
|
||||
} else {
|
||||
nassertr(tex->get_texture_type() == Texture::TT_2d_texture, false);
|
||||
}
|
||||
|
|
@ -4243,6 +4288,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
|||
GLint internal_format = get_internal_image_format(tex);
|
||||
int width = tex->get_x_size();
|
||||
int height = tex->get_y_size();
|
||||
int depth = tex->get_z_size();
|
||||
|
||||
bool uses_mipmaps = tex->uses_mipmaps() && !CLP(ignore_mipmaps);
|
||||
if (uses_mipmaps) {
|
||||
|
|
@ -4260,34 +4306,52 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
|||
}
|
||||
|
||||
bool new_image = needs_reload || gtc->was_image_modified();
|
||||
|
||||
if (z >= 0) {
|
||||
if (target == GL_TEXTURE_CUBE_MAP) {
|
||||
// Copy to a cube map face, which is treated as a 2D texture.
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z;
|
||||
depth = 1;
|
||||
z = -1;
|
||||
|
||||
// Cube map faces seem to have trouble with CopyTexSubImage, so we
|
||||
// always reload the image.
|
||||
new_image = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gtc->_already_applied ||
|
||||
internal_format != gtc->_internal_format ||
|
||||
uses_mipmaps != gtc->_uses_mipmaps ||
|
||||
width != gtc->_width ||
|
||||
height != gtc->_height ||
|
||||
1 != gtc->_depth) {
|
||||
depth != gtc->_depth) {
|
||||
// If the texture properties have changed, we need to reload the
|
||||
// image.
|
||||
new_image = true;
|
||||
}
|
||||
|
||||
if (z >= 0) {
|
||||
// Copy to a cube map face.
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z;
|
||||
if (new_image) {
|
||||
// These won't be used because we pass a NULL image, but we still
|
||||
// have to specify them. Might as well use the actual values.
|
||||
GLint external_format = get_external_image_format(tex);
|
||||
GLint component_type = get_component_type(tex->get_component_type());
|
||||
_glTexImage3D(target, 0, internal_format, width, height, depth, 0, external_format, component_type, NULL);
|
||||
}
|
||||
|
||||
// Cube map faces seem to have trouble with CopyTexSubImage, so we
|
||||
// always reload the image.
|
||||
new_image = true;
|
||||
}
|
||||
|
||||
if (new_image) {
|
||||
// We have to create a new image.
|
||||
// It seems that OpenGL accepts a size higher than the framebuffer,
|
||||
// but if we run into trouble we'll have to replace this with
|
||||
// something smarter.
|
||||
GLP(CopyTexImage2D)(target, 0, internal_format, xo, yo, width, height, 0);
|
||||
_glCopyTexSubImage3D(target, 0, 0, 0, z, xo, yo, w, h);
|
||||
} else {
|
||||
// We can overlay the existing image.
|
||||
GLP(CopyTexSubImage2D)(target, 0, 0, 0, xo, yo, w, h);
|
||||
if (new_image) {
|
||||
// We have to create a new image.
|
||||
// It seems that OpenGL accepts a size higher than the framebuffer,
|
||||
// but if we run into trouble we'll have to replace this with
|
||||
// something smarter.
|
||||
GLP(CopyTexImage2D)(target, 0, internal_format, xo, yo, width, height, 0);
|
||||
} else {
|
||||
// We can overlay the existing image.
|
||||
GLP(CopyTexSubImage2D)(target, 0, 0, 0, xo, yo, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
gtc->_already_applied = true;
|
||||
|
|
@ -4295,7 +4359,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
|||
gtc->_internal_format = internal_format;
|
||||
gtc->_width = width;
|
||||
gtc->_height = height;
|
||||
gtc->_depth = 1;
|
||||
gtc->_depth = depth;
|
||||
|
||||
gtc->mark_loaded();
|
||||
gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
|
@ -4373,6 +4437,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
|
|||
|
||||
Texture::TextureType texture_type;
|
||||
int z_size;
|
||||
//TODO: should be extended to support 3D textures and 2D arrays.
|
||||
if (z >= 0) {
|
||||
texture_type = Texture::TT_cube_map;
|
||||
z_size = 6;
|
||||
|
|
@ -4386,6 +4451,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
|
|||
tex->get_component_type() != component_type ||
|
||||
tex->get_format() != format ||
|
||||
tex->get_texture_type() != texture_type) {
|
||||
|
||||
// Re-setup the texture; its properties have changed.
|
||||
tex->setup_texture(texture_type, w, h, z_size,
|
||||
component_type, format);
|
||||
|
|
@ -5681,6 +5747,7 @@ get_extension_func(const char *prefix, const char *name) {
|
|||
{ "DrawRangeElements", (void *)&GLP(DrawRangeElements) },
|
||||
{ "TexImage3D", (void *)&GLP(TexImage3D) },
|
||||
{ "TexSubImage3D", (void *)&GLP(TexSubImage3D) },
|
||||
{ "CopyTexSubImage3D", (void *)&GLP(CopyTexSubImage3D) },
|
||||
#endif
|
||||
#ifdef EXPECT_GL_VERSION_1_3
|
||||
{ "ActiveTexture", (void *)&GLP(ActiveTexture) },
|
||||
|
|
@ -6308,15 +6375,7 @@ get_external_image_format(Texture *tex) const {
|
|||
case Texture::F_depth_component:
|
||||
return GL_DEPTH_COMPONENT;
|
||||
case Texture::F_depth_stencil:
|
||||
#ifndef OPENGLES_2
|
||||
if (CLP(force_depth_stencil)) {
|
||||
return GL_DEPTH_STENCIL_EXT;
|
||||
} else {
|
||||
#endif
|
||||
return GL_DEPTH_COMPONENT;
|
||||
#ifndef OPENGLES_2
|
||||
}
|
||||
#endif
|
||||
return _supports_depth_stencil ? GL_DEPTH_STENCIL_EXT : GL_DEPTH_COMPONENT;
|
||||
#ifndef OPENGLES
|
||||
case Texture::F_red:
|
||||
return GL_RED;
|
||||
|
|
@ -6522,7 +6581,11 @@ get_internal_image_format(Texture *tex) const {
|
|||
return GL_COLOR_INDEX;
|
||||
#endif
|
||||
case Texture::F_depth_component:
|
||||
return GL_DEPTH_COMPONENT;
|
||||
if (tex->get_component_type() == Texture::T_float) {
|
||||
return GL_DEPTH_COMPONENT32F;
|
||||
} else {
|
||||
return GL_DEPTH_COMPONENT;
|
||||
}
|
||||
case Texture::F_depth_component16:
|
||||
#ifdef OPENGLES_1
|
||||
return GL_DEPTH_COMPONENT16_OES;
|
||||
|
|
@ -6537,7 +6600,11 @@ get_internal_image_format(Texture *tex) const {
|
|||
#else
|
||||
return GL_DEPTH_COMPONENT24;
|
||||
case Texture::F_depth_component32:
|
||||
return GL_DEPTH_COMPONENT32;
|
||||
if (tex->get_component_type() == Texture::T_float) {
|
||||
return GL_DEPTH_COMPONENT32F;
|
||||
} else {
|
||||
return GL_DEPTH_COMPONENT32;
|
||||
}
|
||||
#endif
|
||||
case Texture::F_depth_stencil:
|
||||
#ifndef OPENGLES_2
|
||||
|
|
@ -7755,15 +7822,15 @@ update_standard_texture_bindings() {
|
|||
TextureContext *tc = texture->prepare_now(view, _prepared_objects, this);
|
||||
if (tc == (TextureContext *)NULL) {
|
||||
// Something wrong with this texture; skip it.
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef OPENGLES_2
|
||||
// Then, turn on the current texture mode.
|
||||
GLenum target = get_texture_target(texture->get_texture_type());
|
||||
if (target == GL_NONE) {
|
||||
if (target == GL_NONE || target == GL_TEXTURE_2D_ARRAY_EXT) {
|
||||
// Unsupported texture mode.
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
GLP(Enable)(target);
|
||||
#endif
|
||||
|
|
@ -7772,7 +7839,7 @@ update_standard_texture_bindings() {
|
|||
#ifndef OPENGLES_2
|
||||
GLP(Disable)(target);
|
||||
#endif
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stage->involves_color_scale() && _color_scale_enabled) {
|
||||
|
|
@ -8635,7 +8702,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force) {
|
|||
if (!get_supports_compressed_texture_format(image_compression)) {
|
||||
image = tex->get_uncompressed_ram_image();
|
||||
image_compression = Texture::CM_off;
|
||||
}
|
||||
}
|
||||
|
||||
if (GLCAT.is_debug()) {
|
||||
if (image.is_null()) {
|
||||
|
|
@ -9010,7 +9077,7 @@ upload_texture_image(CLP(TextureContext) *gtc,
|
|||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "subloading existing texture object, " << width << " x " << height
|
||||
<< " x " << depth << ", mipmaps " << num_ram_mipmap_levels
|
||||
<< " x " << depth << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels
|
||||
<< ", uses_mipmaps = " << uses_mipmaps << "\n";
|
||||
}
|
||||
|
||||
|
|
@ -9142,31 +9209,37 @@ upload_texture_image(CLP(TextureContext) *gtc,
|
|||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "loading new texture object, " << width << " x " << height
|
||||
<< " x " << depth << ", mipmaps " << num_ram_mipmap_levels
|
||||
<< " x " << depth << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels
|
||||
<< ", uses_mipmaps = " << uses_mipmaps << "\n";
|
||||
}
|
||||
|
||||
if (num_ram_mipmap_levels == 0) {
|
||||
#ifndef OPENGLES_2
|
||||
if ((external_format == GL_DEPTH_STENCIL_EXT) && get_supports_depth_stencil()) {
|
||||
GLP(TexImage2D)(page_target, 0, GL_DEPTH_STENCIL_EXT,
|
||||
width, height, 0, GL_DEPTH_STENCIL_EXT,
|
||||
#ifdef OPENGLES_1
|
||||
GL_UNSIGNED_INT_24_8_OES,
|
||||
component_type = GL_UNSIGNED_INT_24_8_OES;
|
||||
#else
|
||||
GL_UNSIGNED_INT_24_8_EXT,
|
||||
#endif // OPENGLES_1
|
||||
NULL);
|
||||
} else {
|
||||
#endif // OPENGLES_2
|
||||
GLP(TexImage2D)(page_target, 0, internal_format,
|
||||
width, height, 0,
|
||||
external_format, GL_UNSIGNED_BYTE, NULL);
|
||||
#ifndef OPENGLES_2
|
||||
component_type = GL_UNSIGNED_INT_24_8_EXT;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// We don't have any RAM mipmap levels, so we create an uninitialized OpenGL
|
||||
// texture. Presumably this will be used later for render-to-texture or so.
|
||||
switch (page_target) {
|
||||
case GL_TEXTURE_1D:
|
||||
GLP(TexImage1D)(page_target, 0, internal_format, width, 0, external_format, component_type, NULL);
|
||||
break;
|
||||
case GL_TEXTURE_3D:
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
_glTexImage3D(page_target, 0, internal_format, width, height, depth, 0, external_format, component_type, NULL);
|
||||
break;
|
||||
default:
|
||||
GLP(TexImage2D)(page_target, 0, internal_format, width, height, 0, external_format, component_type, NULL);
|
||||
break;
|
||||
}
|
||||
#endif // OPENGLES_2
|
||||
}
|
||||
|
||||
|
||||
for (int n = mipmap_bias; n < num_ram_mipmap_levels; ++n) {
|
||||
const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
|
||||
CPTA_uchar ptimage;
|
||||
|
|
@ -9283,7 +9356,7 @@ upload_texture_image(CLP(TextureContext) *gtc,
|
|||
GLCAT.error()
|
||||
<< "GL texture creation failed for " << tex->get_name()
|
||||
<< " : " << get_error_string(error_code) << "\n";
|
||||
|
||||
|
||||
gtc->_already_applied = false;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -9642,6 +9715,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
|
|||
break;
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
case GL_DEPTH_COMPONENT32F:
|
||||
type = Texture::T_float;
|
||||
format = Texture::F_depth_component;
|
||||
break;
|
||||
|
|
@ -10034,7 +10108,7 @@ get_supports_cg_profile(const string &name) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::bind_fbo
|
||||
// Access: Protected
|
||||
// Description: Binds an FBO object.
|
||||
// Description: Binds a framebuffer object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
bind_fbo(GLuint fbo) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start,
|
|||
// There is some trivial disagreement between different gl.h headers about this one, so we use our own typename.
|
||||
typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC_P) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, const GLfloat s);
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, const GLfloat s, const GLfloat t);
|
||||
|
|
@ -115,6 +116,8 @@ typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum att
|
|||
#else
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
|
||||
#endif
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
|
||||
|
|
@ -556,6 +559,7 @@ public:
|
|||
|
||||
PFNGLTEXIMAGE3DPROC_P _glTexImage3D;
|
||||
PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D;
|
||||
PFNGLCOPYTEXSUBIMAGE3DPROC _glCopyTexSubImage3D;
|
||||
|
||||
PFNGLCOMPRESSEDTEXIMAGE1DPROC _glCompressedTexImage1D;
|
||||
PFNGLCOMPRESSEDTEXIMAGE2DPROC _glCompressedTexImage2D;
|
||||
|
|
@ -610,6 +614,8 @@ public:
|
|||
#else
|
||||
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC _glFramebufferTexture3D;
|
||||
#endif
|
||||
PFNGLFRAMEBUFFERTEXTUREARBPROC _glFramebufferTexture;
|
||||
PFNGLFRAMEBUFFERTEXTURELAYERPROC _glFramebufferTextureLayer;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC _glFramebufferRenderbuffer;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC _glGetFramebufferAttachmentParameteriv;
|
||||
PFNGLGENERATEMIPMAPEXTPROC _glGenerateMipmap;
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ make_output(const string &name,
|
|||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_color)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
((flags&BF_can_bind_every)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
return new glxGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
|
|
@ -168,14 +169,15 @@ make_output(const string &name,
|
|||
if (!glx_support_pbuffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)) {
|
||||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!support_rtt) {
|
||||
if (((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
|
|
@ -184,7 +186,7 @@ make_output(const string &name,
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new glxGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
|
@ -199,7 +201,8 @@ make_output(const string &name,
|
|||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)) {
|
||||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +214,7 @@ make_output(const string &name,
|
|||
return new glxGraphicsPixmap(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
|
||||
// Nothing else left to try.
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -392,7 +392,8 @@ make_output(const string &name,
|
|||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_can_bind_color)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
((flags&BF_can_bind_every)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
WindowHandle *window_handle = win_prop.get_parent_window();
|
||||
|
|
@ -412,7 +413,7 @@ make_output(const string &name,
|
|||
flags, gsg, host);
|
||||
}
|
||||
|
||||
// Second thing to try: a glGraphicsBuffer
|
||||
// Second thing to try: a GLGraphicsBuffer
|
||||
|
||||
if (retry == 1) {
|
||||
if (!osx_support_gl_buffer) {
|
||||
|
|
@ -453,7 +454,8 @@ make_output(const string &name,
|
|||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
((flags&BF_can_bind_every)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
return new osxGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ make_output(const string &name,
|
|||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_color)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
((flags&BF_can_bind_every)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & BF_fb_props_optional)==0) {
|
||||
|
|
@ -201,7 +202,8 @@ make_output(const string &name,
|
|||
|
||||
if (retry == 2) {
|
||||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)) {
|
||||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
if ((wglgsg != 0) &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue