mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 17:35:34 -04:00
texture optimizations
This commit is contained in:
parent
c306244719
commit
ec83e7f9c6
@ -43,11 +43,7 @@ GraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
||||
}
|
||||
|
||||
if (want_texture) {
|
||||
_texture = new Texture();
|
||||
_texture->set_name(_name);
|
||||
_texture->set_wrapu(Texture::WM_clamp);
|
||||
_texture->set_wrapv(Texture::WM_clamp);
|
||||
_copy_texture = true;
|
||||
setup_copy_texture(_name);
|
||||
}
|
||||
|
||||
_x_size = x_size;
|
||||
|
@ -256,11 +256,7 @@ make_buffer(GraphicsStateGuardian *gsg, const string &name,
|
||||
window->request_properties(props);
|
||||
|
||||
if (want_texture) {
|
||||
window->_texture = new Texture();
|
||||
window->_texture->set_name(name);
|
||||
window->_texture->set_wrapu(Texture::WM_clamp);
|
||||
window->_texture->set_wrapv(Texture::WM_clamp);
|
||||
window->_copy_texture = true;
|
||||
window->setup_copy_texture(name);
|
||||
}
|
||||
|
||||
return window;
|
||||
@ -309,10 +305,7 @@ make_parasite(GraphicsOutput *host, const string &name,
|
||||
props.set_fixed_size(true);
|
||||
props.set_title(name);
|
||||
window->request_properties(props);
|
||||
|
||||
window->_texture = new Texture();
|
||||
window->_texture->set_name(name);
|
||||
window->_copy_texture = true;
|
||||
window->setup_copy_texture(name);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
@ -686,6 +686,43 @@ declare_channel(int index, GraphicsChannel *chan) {
|
||||
_channels[index] = chan;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::setup_copy_texture
|
||||
// Access: Protected
|
||||
// Description: Creates a new Texture object, suitable for copying
|
||||
// the contents of this buffer into, and stores it in
|
||||
// _texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
setup_copy_texture(const string &name) {
|
||||
_texture = new Texture();
|
||||
_texture->set_name(name);
|
||||
_texture->set_wrapu(Texture::WM_clamp);
|
||||
_texture->set_wrapv(Texture::WM_clamp);
|
||||
|
||||
// We should match the texture format up with the framebuffer
|
||||
// format. Easier said than done!
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||
int mode = _gsg->get_properties().get_frame_buffer_mode();
|
||||
PixelBuffer *pb = _texture->_pbuffer;
|
||||
|
||||
if (mode & FrameBufferProperties::FM_alpha) {
|
||||
pb->set_format(PixelBuffer::F_rgba8);
|
||||
pb->set_num_components(4);
|
||||
pb->set_component_width(1);
|
||||
pb->set_image_type(PixelBuffer::T_unsigned_byte);
|
||||
|
||||
} else {
|
||||
pb->set_format(PixelBuffer::F_rgb8);
|
||||
pb->set_num_components(3);
|
||||
pb->set_component_width(1);
|
||||
pb->set_image_type(PixelBuffer::T_unsigned_byte);
|
||||
}
|
||||
}
|
||||
|
||||
_copy_texture = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::do_determine_display_regions
|
||||
// Access: Private
|
||||
|
@ -145,6 +145,7 @@ public:
|
||||
|
||||
protected:
|
||||
void declare_channel(int index, GraphicsChannel *chan);
|
||||
void setup_copy_texture(const string &name);
|
||||
|
||||
protected:
|
||||
PT(GraphicsStateGuardian) _gsg;
|
||||
|
@ -44,11 +44,7 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
|
||||
<< " on " << _host->get_name() << "\n";
|
||||
}
|
||||
|
||||
_texture = new Texture();
|
||||
_texture->set_name(_name);
|
||||
_texture->set_wrapu(Texture::WM_clamp);
|
||||
_texture->set_wrapv(Texture::WM_clamp);
|
||||
_copy_texture = true;
|
||||
setup_copy_texture(_name);
|
||||
|
||||
_x_size = x_size;
|
||||
_y_size = y_size;
|
||||
|
@ -302,6 +302,8 @@ reset() {
|
||||
|
||||
_supports_bgr = has_extension("GL_EXT_bgra");
|
||||
_supports_multisample = has_extension("GL_ARB_multisample");
|
||||
_supports_generate_mipmap =
|
||||
has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4);
|
||||
|
||||
_supports_multitexture = false;
|
||||
|
||||
@ -1824,13 +1826,11 @@ TextureContext *CLP(GraphicsStateGuardian)::
|
||||
prepare_texture(Texture *tex) {
|
||||
CLP(TextureContext) *gtc = new CLP(TextureContext)(tex);
|
||||
GLP(GenTextures)(1, >c->_index);
|
||||
//cerr << "preparing texture " << tex->get_name() << ", assigning "
|
||||
// << gtc->_index << "\n";
|
||||
|
||||
bind_texture(gtc);
|
||||
GLP(PrioritizeTextures)(1, >c->_index, >c->_priority);
|
||||
specify_texture(tex);
|
||||
apply_texture_immediate(tex);
|
||||
apply_texture_immediate(gtc, tex);
|
||||
|
||||
report_my_gl_errors();
|
||||
return gtc;
|
||||
@ -1844,20 +1844,22 @@ prepare_texture(Texture *tex) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
apply_texture(TextureContext *tc) {
|
||||
add_to_texture_record(tc);
|
||||
bind_texture(tc);
|
||||
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
|
||||
|
||||
int dirty = tc->get_dirty_flags();
|
||||
add_to_texture_record(gtc);
|
||||
bind_texture(gtc);
|
||||
|
||||
int dirty = gtc->get_dirty_flags();
|
||||
if ((dirty & (Texture::DF_wrap | Texture::DF_filter)) != 0) {
|
||||
// We need to re-specify the texture properties.
|
||||
specify_texture(tc->_texture);
|
||||
specify_texture(gtc->_texture);
|
||||
}
|
||||
if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) {
|
||||
// We need to re-apply the image.
|
||||
apply_texture_immediate(tc->_texture);
|
||||
apply_texture_immediate(gtc, gtc->_texture);
|
||||
}
|
||||
|
||||
tc->clear_dirty_flags();
|
||||
gtc->clear_dirty_flags();
|
||||
|
||||
report_my_gl_errors();
|
||||
}
|
||||
@ -3201,21 +3203,28 @@ bind_texture(TextureContext *tc) {
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
specify_texture(Texture *tex) {
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
||||
get_texture_wrap_mode(tex->get_wrapu()));
|
||||
get_texture_wrap_mode(tex->get_wrapu()));
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
||||
get_texture_wrap_mode(tex->get_wrapv()));
|
||||
get_texture_wrap_mode(tex->get_wrapv()));
|
||||
|
||||
Texture::FilterType minfilter = tex->get_minfilter();
|
||||
Texture::FilterType magfilter = tex->get_magfilter();
|
||||
|
||||
bool uses_mipmaps = tex->uses_mipmaps();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (CLP(force_mipmaps)) {
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
} else {
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
get_texture_filter_type(tex->get_minfilter()));
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
get_texture_filter_type(tex->get_magfilter()));
|
||||
minfilter = Texture::FT_linear_mipmap_linear;
|
||||
magfilter = Texture::FT_linear;
|
||||
uses_mipmaps = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
get_texture_filter_type(tex->get_minfilter()));
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
get_texture_filter_type(tex->get_magfilter()));
|
||||
|
||||
report_my_gl_errors();
|
||||
}
|
||||
|
||||
@ -3292,20 +3301,22 @@ compute_gl_image_size(int xsize, int ysize, int external_format, int type) {
|
||||
// the texture has no image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
apply_texture_immediate(Texture *tex) {
|
||||
apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex) {
|
||||
PixelBuffer *pb = tex->get_ram_image();
|
||||
if (pb == (PixelBuffer *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int xsize = pb->get_xsize();
|
||||
int ysize = pb->get_ysize();
|
||||
int width = pb->get_xsize();
|
||||
int height = pb->get_ysize();
|
||||
|
||||
GLenum internal_format = get_internal_image_format(pb->get_format());
|
||||
GLenum external_format = get_external_image_format(pb->get_format());
|
||||
GLint internal_format = get_internal_image_format(pb->get_format());
|
||||
GLint external_format = get_external_image_format(pb->get_format());
|
||||
GLenum type = get_image_type(pb->get_image_type());
|
||||
|
||||
PTA_uchar image = pb->_image;
|
||||
nassertr(!image.empty(), false);
|
||||
|
||||
if (!_supports_bgr) {
|
||||
// If the GL doesn't claim to support BGR, we may have to reverse
|
||||
// the component ordering of the image.
|
||||
@ -3314,7 +3325,7 @@ apply_texture_immediate(Texture *tex) {
|
||||
|
||||
#ifndef NDEBUG
|
||||
int wanted_size =
|
||||
compute_gl_image_size(xsize, ysize, external_format, type);
|
||||
compute_gl_image_size(width, height, external_format, type);
|
||||
nassertr(wanted_size == (int)pb->_image.size(), false);
|
||||
#endif // NDEBUG
|
||||
|
||||
@ -3324,46 +3335,95 @@ apply_texture_immediate(Texture *tex) {
|
||||
GLCAT.debug()
|
||||
<< "glTexImage2D(GL_TEXTURE_2D, "
|
||||
<< (int)internal_format << ", "
|
||||
<< xsize << ", " << ysize << ", "
|
||||
<< width << ", " << height << ", "
|
||||
<< pb->get_border() << ", " << (int)external_format << ", "
|
||||
<< (int)type << ", " << tex->get_name() << ")\n";
|
||||
#endif
|
||||
|
||||
if (!CLP(ignore_mipmaps) || CLP(force_mipmaps)) {
|
||||
if (tex->uses_mipmaps() || CLP(force_mipmaps)) {
|
||||
#ifndef NDEBUG
|
||||
if (CLP(show_mipmaps)) {
|
||||
build_phony_mipmaps(tex);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLUP(Build2DMipmaps)(GL_TEXTURE_2D, internal_format,
|
||||
xsize, ysize,
|
||||
external_format, type, image);
|
||||
#ifndef NDEBUG
|
||||
if (CLP(save_mipmaps)) {
|
||||
save_mipmap_images(tex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
report_my_gl_errors();
|
||||
bool uses_mipmaps = tex->uses_mipmaps() && !CLP(ignore_mipmaps);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (CLP(force_mipmaps)) {
|
||||
uses_mipmaps = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uses_mipmaps) {
|
||||
#ifndef NDEBUG
|
||||
if (CLP(show_mipmaps)) {
|
||||
build_phony_mipmaps(tex);
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
|
||||
} else
|
||||
#endif
|
||||
if (_supports_generate_mipmap) {
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
|
||||
} else {
|
||||
// We only need to build the mipmaps by hand if the GL
|
||||
// doesn't support generating them automatically.
|
||||
GLUP(Build2DMipmaps)(GL_TEXTURE_2D, internal_format,
|
||||
width, height,
|
||||
external_format, type, image);
|
||||
|
||||
gtc->_already_applied = false;
|
||||
gtc->_internal_format = internal_format;
|
||||
gtc->_width = width;
|
||||
gtc->_height = height;
|
||||
gtc->_border = 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (CLP(save_mipmaps)) {
|
||||
save_mipmap_images(tex);
|
||||
}
|
||||
#endif
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (_supports_generate_mipmap) {
|
||||
GLP(TexParameteri)(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
nassertr(!pb->_image.empty(), false);
|
||||
GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format,
|
||||
xsize, ysize, pb->get_border(),
|
||||
external_format, type, image);
|
||||
GLint border = pb->get_border();
|
||||
|
||||
if (!gtc->_already_applied ||
|
||||
gtc->_internal_format != internal_format ||
|
||||
gtc->_width != width ||
|
||||
gtc->_height != height ||
|
||||
gtc->_border != border) {
|
||||
// We need to reload a new image.
|
||||
GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format,
|
||||
width, height, pb->get_border(),
|
||||
external_format, type, image);
|
||||
gtc->_already_applied = true;
|
||||
gtc->_internal_format = internal_format;
|
||||
gtc->_width = width;
|
||||
gtc->_height = height;
|
||||
gtc->_border = border;
|
||||
|
||||
} else {
|
||||
// We can reload the image over the previous image, saving on
|
||||
// texture memory fragmentation.
|
||||
GLP(TexSubImage2D)(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||
external_format, type, image);
|
||||
}
|
||||
|
||||
//report_my_gl_errors();
|
||||
// want to give explict error for texture creation failure
|
||||
GLenum error_code = GLP(GetError)();
|
||||
if(error_code != GL_NO_ERROR) {
|
||||
if (error_code != GL_NO_ERROR) {
|
||||
const GLubyte *error_string = GLUP(ErrorString)(error_code);
|
||||
GLCAT.error() << "GL texture creation failed for " << tex->get_name() <<
|
||||
((error_string != (const GLubyte *)NULL) ? " : " : "") << endl;
|
||||
GLCAT.error()
|
||||
<< "GL texture creation failed for " << tex->get_name();
|
||||
if (error_string != (const GLubyte *)NULL) {
|
||||
GLCAT.error(false)
|
||||
<< " : " << error_string;
|
||||
}
|
||||
GLCAT.error(false)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3696,7 +3756,7 @@ get_image_type(PixelBuffer::Type type) {
|
||||
// Description: Maps from the PixelBuffer's Format symbols
|
||||
// to GL's.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GLenum CLP(GraphicsStateGuardian)::
|
||||
GLint CLP(GraphicsStateGuardian)::
|
||||
get_external_image_format(PixelBuffer::Format format) {
|
||||
switch (format) {
|
||||
case PixelBuffer::F_color_index:
|
||||
@ -3744,7 +3804,7 @@ get_external_image_format(PixelBuffer::Format format) {
|
||||
// Description: Maps from the PixelBuffer's Format symbols to a
|
||||
// suitable internal format for GL textures.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GLenum CLP(GraphicsStateGuardian)::
|
||||
GLint CLP(GraphicsStateGuardian)::
|
||||
get_internal_image_format(PixelBuffer::Format format) {
|
||||
switch (format) {
|
||||
case PixelBuffer::F_rgba:
|
||||
@ -4621,8 +4681,8 @@ build_phony_mipmap_level(int level, int xsize, int ysize) {
|
||||
GLenum type = get_image_type(pb->get_image_type());
|
||||
|
||||
GLP(TexImage2D)(GL_TEXTURE_2D, level, internal_format,
|
||||
pb->get_xsize(), pb->get_ysize(), pb->get_border(),
|
||||
external_format, type, pb->_image );
|
||||
pb->get_xsize(), pb->get_ysize(), pb->get_border(),
|
||||
external_format, type, pb->_image );
|
||||
|
||||
delete pb;
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ protected:
|
||||
|
||||
void bind_texture(TextureContext *tc);
|
||||
void specify_texture(Texture *tex);
|
||||
bool apply_texture_immediate(Texture *tex);
|
||||
bool apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex);
|
||||
|
||||
void draw_texture(TextureContext *tc, const DisplayRegion *dr);
|
||||
void draw_texture(TextureContext *tc, const DisplayRegion *dr,
|
||||
@ -234,8 +234,8 @@ protected:
|
||||
GLenum get_texture_wrap_mode(Texture::WrapMode wm);
|
||||
GLenum get_texture_filter_type(Texture::FilterType ft);
|
||||
GLenum get_image_type(PixelBuffer::Type type);
|
||||
GLenum get_external_image_format(PixelBuffer::Format format);
|
||||
GLenum get_internal_image_format(PixelBuffer::Format format);
|
||||
GLint get_external_image_format(PixelBuffer::Format format);
|
||||
GLint get_internal_image_format(PixelBuffer::Format format);
|
||||
GLint get_texture_apply_mode_type(TextureStage::Mode am) const;
|
||||
GLint get_texture_combine_type(TextureStage::CombineMode cm) const;
|
||||
GLint get_texture_src_type(TextureStage::CombineSource cs) const;
|
||||
@ -330,6 +330,7 @@ protected:
|
||||
public:
|
||||
bool _supports_bgr;
|
||||
bool _supports_multisample;
|
||||
bool _supports_generate_mipmap;
|
||||
|
||||
bool _supports_multitexture;
|
||||
PFNGLACTIVETEXTUREPROC _glActiveTexture;
|
||||
|
@ -28,4 +28,6 @@ CLP(TextureContext)(Texture *tex) :
|
||||
{
|
||||
_index = 0;
|
||||
_priority = 0.5; // For keeping resident in texture memory
|
||||
|
||||
_already_applied = false;
|
||||
}
|
||||
|
@ -33,6 +33,15 @@ public:
|
||||
// This is a GL texture priority.
|
||||
GLfloat _priority;
|
||||
|
||||
// These are the parameters that we specified with the last
|
||||
// glTexImage2D() call. If none of these have changed, we can
|
||||
// reload the texture image with a glTexSubImage2D().
|
||||
bool _already_applied;
|
||||
GLint _internal_format;
|
||||
GLsizei _width;
|
||||
GLsizei _height;
|
||||
GLint _border;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
Loading…
x
Reference in New Issue
Block a user