mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
Implement texture clear, fix immutable tex support
This commit is contained in:
parent
cb66a51bbc
commit
01b669ccd8
@ -800,6 +800,21 @@ reset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_supports_clear_texture = false;
|
||||||
|
#ifndef OPENGLES
|
||||||
|
if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_clear_texture")) {
|
||||||
|
_glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)
|
||||||
|
get_extension_func("glClearTexImage");
|
||||||
|
|
||||||
|
if (_glClearTexImage == NULL) {
|
||||||
|
GLCAT.warning()
|
||||||
|
<< "GL_ARB_clear_texture advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
|
||||||
|
} else {
|
||||||
|
_supports_clear_texture = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
_supports_2d_texture_array = false;
|
_supports_2d_texture_array = false;
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
_supports_2d_texture_array = has_extension("GL_EXT_texture_array");
|
_supports_2d_texture_array = has_extension("GL_EXT_texture_array");
|
||||||
@ -7519,7 +7534,7 @@ get_external_image_format(Texture *tex) const {
|
|||||||
// suitable internal format for GL textures.
|
// suitable internal format for GL textures.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GLint CLP(GraphicsStateGuardian)::
|
GLint CLP(GraphicsStateGuardian)::
|
||||||
get_internal_image_format(Texture *tex) const {
|
get_internal_image_format(Texture *tex, bool force_sized) const {
|
||||||
Texture::CompressionMode compression = tex->get_compression();
|
Texture::CompressionMode compression = tex->get_compression();
|
||||||
if (compression == Texture::CM_default) {
|
if (compression == Texture::CM_default) {
|
||||||
compression = (compressed_textures) ? Texture::CM_on : Texture::CM_off;
|
compression = (compressed_textures) ? Texture::CM_on : Texture::CM_off;
|
||||||
@ -7752,7 +7767,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return GL_DEPTH_STENCIL;
|
return force_sized ? GL_DEPTH24_STENCIL8 : GL_DEPTH_STENCIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fall through.
|
// Fall through.
|
||||||
@ -7764,7 +7779,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return GL_DEPTH_COMPONENT;
|
return force_sized ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT;
|
||||||
}
|
}
|
||||||
case Texture::F_depth_component16:
|
case Texture::F_depth_component16:
|
||||||
#ifdef OPENGLES
|
#ifdef OPENGLES
|
||||||
@ -7811,7 +7826,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return GL_RGBA;
|
return force_sized ? GL_RGBA8 : GL_RGBA;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Texture::F_rgba4:
|
case Texture::F_rgba4:
|
||||||
@ -7821,7 +7836,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
case Texture::F_rgba8:
|
case Texture::F_rgba8:
|
||||||
return GL_RGBA8_OES;
|
return GL_RGBA8_OES;
|
||||||
case Texture::F_rgba12:
|
case Texture::F_rgba12:
|
||||||
return GL_RGBA;
|
return force_sized ? GL_RGBA8 : GL_RGBA;
|
||||||
#else
|
#else
|
||||||
case Texture::F_rgba8:
|
case Texture::F_rgba8:
|
||||||
return GL_RGBA8;
|
return GL_RGBA8;
|
||||||
@ -7843,7 +7858,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
if (tex->get_component_type() == Texture::T_float) {
|
if (tex->get_component_type() == Texture::T_float) {
|
||||||
return GL_RGB16F;
|
return GL_RGB16F;
|
||||||
} else {
|
} else {
|
||||||
return GL_RGB;
|
return force_sized ? GL_RGB8 : GL_RGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Texture::F_rgb5:
|
case Texture::F_rgb5:
|
||||||
@ -7860,7 +7875,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
case Texture::F_rgb8:
|
case Texture::F_rgb8:
|
||||||
return GL_RGB8_OES;
|
return GL_RGB8_OES;
|
||||||
case Texture::F_rgb12:
|
case Texture::F_rgb12:
|
||||||
return GL_RGB;
|
return force_sized ? GL_RGB8 : GL_RGB;
|
||||||
case Texture::F_rgb16:
|
case Texture::F_rgb16:
|
||||||
return GL_RGB16F;
|
return GL_RGB16F;
|
||||||
#else
|
#else
|
||||||
@ -7912,25 +7927,26 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
case Texture::F_red:
|
case Texture::F_red:
|
||||||
case Texture::F_green:
|
case Texture::F_green:
|
||||||
case Texture::F_blue:
|
case Texture::F_blue:
|
||||||
return GL_RED;
|
return force_sized ? GL_R8 : GL_RED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case Texture::F_alpha:
|
case Texture::F_alpha:
|
||||||
return GL_ALPHA;
|
return force_sized ? GL_ALPHA8 : GL_ALPHA;
|
||||||
|
|
||||||
case Texture::F_luminance:
|
case Texture::F_luminance:
|
||||||
if (tex->get_component_type() == Texture::T_float) {
|
if (tex->get_component_type() == Texture::T_float) {
|
||||||
return GL_LUMINANCE16F_ARB;
|
return GL_LUMINANCE16F_ARB;
|
||||||
} else if (tex->get_component_type() == Texture::T_unsigned_short) {
|
} else if (tex->get_component_type() == Texture::T_unsigned_short) {
|
||||||
return GL_LUMINANCE16;
|
return GL_LUMINANCE16;
|
||||||
} else {
|
} else {
|
||||||
return GL_LUMINANCE;
|
return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE;
|
||||||
}
|
}
|
||||||
case Texture::F_luminance_alpha:
|
case Texture::F_luminance_alpha:
|
||||||
case Texture::F_luminance_alphamask:
|
case Texture::F_luminance_alphamask:
|
||||||
if (tex->get_component_type() == Texture::T_float || tex->get_component_type() == Texture::T_unsigned_short) {
|
if (tex->get_component_type() == Texture::T_float || tex->get_component_type() == Texture::T_unsigned_short) {
|
||||||
return GL_LUMINANCE_ALPHA16F_ARB;
|
return GL_LUMINANCE_ALPHA16F_ARB;
|
||||||
} else {
|
} else {
|
||||||
return GL_LUMINANCE_ALPHA;
|
return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENGLES_1
|
#ifndef OPENGLES_1
|
||||||
@ -7953,7 +7969,7 @@ get_internal_image_format(Texture *tex) const {
|
|||||||
GLCAT.error()
|
GLCAT.error()
|
||||||
<< "Invalid image format in get_internal_image_format(): "
|
<< "Invalid image format in get_internal_image_format(): "
|
||||||
<< (int)tex->get_format() << "\n";
|
<< (int)tex->get_format() << "\n";
|
||||||
return GL_RGB;
|
return force_sized ? GL_RGB8 : GL_RGB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9359,6 +9375,8 @@ update_show_usage_texture_bindings(int show_stage_index) {
|
|||||||
GLuint index = (*ui).second;
|
GLuint index = (*ui).second;
|
||||||
glBindTexture(GL_TEXTURE_2D, index);
|
glBindTexture(GL_TEXTURE_2D, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: glBindSampler(0) ?
|
||||||
}
|
}
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
@ -10052,7 +10070,11 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
|
|||||||
int height = tex->get_y_size();
|
int height = tex->get_y_size();
|
||||||
int depth = tex->get_z_size();
|
int depth = tex->get_z_size();
|
||||||
|
|
||||||
GLint internal_format = get_internal_image_format(tex);
|
// If we'll use immutable texture storage, we have to pick a sized
|
||||||
|
// image format.
|
||||||
|
bool force_sized = (gl_immutable_texture_storage && _supports_tex_storage);
|
||||||
|
|
||||||
|
GLint internal_format = get_internal_image_format(tex, force_sized);
|
||||||
GLint external_format = get_external_image_format(tex);
|
GLint external_format = get_external_image_format(tex);
|
||||||
GLenum component_type = get_component_type(tex->get_component_type());
|
GLenum component_type = get_component_type(tex->get_component_type());
|
||||||
|
|
||||||
@ -10207,6 +10229,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
|
|||||||
CPTA_uchar image = tex->get_ram_mipmap_image(mipmap_bias);
|
CPTA_uchar image = tex->get_ram_mipmap_image(mipmap_bias);
|
||||||
|
|
||||||
if (image.is_null()) {
|
if (image.is_null()) {
|
||||||
|
// We don't even have a RAM image, so we have no choice but to let
|
||||||
|
// mipmaps be generated on the GPU.
|
||||||
if (uses_mipmaps) {
|
if (uses_mipmaps) {
|
||||||
if (_supports_generate_mipmap) {
|
if (_supports_generate_mipmap) {
|
||||||
num_levels = tex->get_expected_num_mipmap_levels() - mipmap_bias;
|
num_levels = tex->get_expected_num_mipmap_levels() - mipmap_bias;
|
||||||
@ -10372,7 +10396,9 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
|
|||||||
component_type, false, 0, image_compression);
|
component_type, false, 0, image_compression);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gtc->_generate_mipmaps && _glGenerateMipmap != NULL) {
|
if (gtc->_generate_mipmaps && _glGenerateMipmap != NULL &&
|
||||||
|
!image.is_null()) {
|
||||||
|
// We uploaded an image; we may need to generate mipmaps.
|
||||||
if (GLCAT.is_debug()) {
|
if (GLCAT.is_debug()) {
|
||||||
GLCAT.debug()
|
GLCAT.debug()
|
||||||
<< "generating mipmaps for texture " << tex->get_name() << ", "
|
<< "generating mipmaps for texture " << tex->get_name() << ", "
|
||||||
@ -10470,6 +10496,11 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
|||||||
int depth = tex->get_expected_mipmap_z_size(mipmap_bias);
|
int depth = tex->get_expected_mipmap_z_size(mipmap_bias);
|
||||||
|
|
||||||
// Determine the number of images to upload.
|
// Determine the number of images to upload.
|
||||||
|
int num_levels = 1;
|
||||||
|
if (uses_mipmaps) {
|
||||||
|
num_levels = tex->get_expected_num_mipmap_levels();
|
||||||
|
}
|
||||||
|
|
||||||
int num_ram_mipmap_levels = 0;
|
int num_ram_mipmap_levels = 0;
|
||||||
if (!image.is_null()) {
|
if (!image.is_null()) {
|
||||||
if (uses_mipmaps) {
|
if (uses_mipmaps) {
|
||||||
@ -10494,36 +10525,72 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
|||||||
|
|
||||||
if (GLCAT.is_debug()) {
|
if (GLCAT.is_debug()) {
|
||||||
if (num_ram_mipmap_levels == 0) {
|
if (num_ram_mipmap_levels == 0) {
|
||||||
|
if (tex->has_clear_color()) {
|
||||||
GLCAT.debug()
|
GLCAT.debug()
|
||||||
<< "not loading NULL image for tex " << tex->get_name() << ", " << width << " x " << height
|
<< "clearing texture " << tex->get_name() << ", "
|
||||||
<< " x " << depth << ", z = " << z << ", uses_mipmaps = " << uses_mipmaps << "\n";
|
<< width << " x " << height << " x " << depth << ", z = " << z
|
||||||
|
<< ", uses_mipmaps = " << uses_mipmaps << ", clear_color = "
|
||||||
|
<< tex->get_clear_color() << "\n";
|
||||||
} else {
|
} else {
|
||||||
GLCAT.debug()
|
GLCAT.debug()
|
||||||
<< "updating image data of texture " << tex->get_name() << ", " << width << " x " << height
|
<< "not loading NULL image for texture " << tex->get_name()
|
||||||
<< " x " << depth << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels
|
<< ", " << width << " x " << height << " x " << depth
|
||||||
|
<< ", z = " << z << ", uses_mipmaps = " << uses_mipmaps << "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GLCAT.debug()
|
||||||
|
<< "updating image data of texture " << tex->get_name()
|
||||||
|
<< ", " << width << " x " << height << " x " << depth
|
||||||
|
<< ", z = " << z << ", mipmaps " << num_ram_mipmap_levels
|
||||||
<< ", uses_mipmaps = " << uses_mipmaps << "\n";
|
<< ", uses_mipmaps = " << uses_mipmaps << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n = mipmap_bias; n < num_ram_mipmap_levels; ++n) {
|
for (int n = mipmap_bias; n < num_levels; ++n) {
|
||||||
// we grab the mipmap pointer first, if it is NULL we grab the
|
// we grab the mipmap pointer first, if it is NULL we grab the
|
||||||
// normal mipmap image pointer which is a PTA_uchar
|
// normal mipmap image pointer which is a PTA_uchar
|
||||||
const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
|
const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
|
||||||
CPTA_uchar ptimage;
|
CPTA_uchar ptimage;
|
||||||
if (image_ptr == (const unsigned char *)NULL) {
|
if (image_ptr == (const unsigned char *)NULL) {
|
||||||
ptimage = tex->get_ram_mipmap_image(n);
|
ptimage = tex->get_ram_mipmap_image(n);
|
||||||
if (ptimage == (const unsigned char *)NULL) {
|
if (ptimage.is_null()) {
|
||||||
|
if (n < num_ram_mipmap_levels) {
|
||||||
|
// We were told we'd have this many RAM mipmap images, but
|
||||||
|
// we don't. Raise a warning.
|
||||||
GLCAT.warning()
|
GLCAT.warning()
|
||||||
<< "No mipmap level " << n << " defined for " << tex->get_name()
|
<< "No mipmap level " << n << " defined for " << tex->get_name()
|
||||||
<< "\n";
|
<< "\n";
|
||||||
// No mipmap level n; stop here.
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tex->has_clear_color()) {
|
||||||
|
// The texture has a clear color, so we should fill this mipmap
|
||||||
|
// level to a solid color.
|
||||||
|
if (_supports_clear_texture) {
|
||||||
|
// We can do that with the convenient glClearTexImage function.
|
||||||
|
string clear_data = tex->get_clear_data();
|
||||||
|
|
||||||
|
_glClearTexImage(gtc->_index, n - mipmap_bias, external_format,
|
||||||
|
component_type, (void *)clear_data.data());
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Ask the Texture class to create the mipmap level in RAM.
|
||||||
|
// It'll fill it in with the correct clear color, which we
|
||||||
|
// can then upload.
|
||||||
|
ptimage = tex->make_ram_mipmap_image(n);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No clear color and no more images.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
image_ptr = ptimage;
|
image_ptr = ptimage;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char *orig_image_ptr = image_ptr;
|
PTA_uchar bgr_image;
|
||||||
size_t view_size = tex->get_ram_mipmap_view_size(n);
|
size_t view_size = tex->get_ram_mipmap_view_size(n);
|
||||||
|
if (image_ptr != (const unsigned char *)NULL) {
|
||||||
|
const unsigned char *orig_image_ptr = image_ptr;
|
||||||
image_ptr += view_size * gtc->get_view();
|
image_ptr += view_size * gtc->get_view();
|
||||||
if (one_page_only) {
|
if (one_page_only) {
|
||||||
view_size = tex->get_ram_mipmap_page_size(n);
|
view_size = tex->get_ram_mipmap_page_size(n);
|
||||||
@ -10531,13 +10598,13 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
|||||||
}
|
}
|
||||||
nassertr(image_ptr >= orig_image_ptr && image_ptr + view_size <= orig_image_ptr + tex->get_ram_mipmap_image_size(n), false);
|
nassertr(image_ptr >= orig_image_ptr && image_ptr + view_size <= orig_image_ptr + tex->get_ram_mipmap_image_size(n), false);
|
||||||
|
|
||||||
PTA_uchar bgr_image;
|
|
||||||
if (!_supports_bgr && image_compression == Texture::CM_off) {
|
if (!_supports_bgr && image_compression == Texture::CM_off) {
|
||||||
// If the GL doesn't claim to support BGR, we may have to reverse
|
// If the GL doesn't claim to support BGR, we may have to reverse
|
||||||
// the component ordering of the image.
|
// the component ordering of the image.
|
||||||
image_ptr = fix_component_ordering(bgr_image, image_ptr, view_size,
|
image_ptr = fix_component_ordering(bgr_image, image_ptr, view_size,
|
||||||
external_format, tex);
|
external_format, tex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int width = tex->get_expected_mipmap_x_size(n);
|
int width = tex->get_expected_mipmap_x_size(n);
|
||||||
int height = tex->get_expected_mipmap_y_size(n);
|
int height = tex->get_expected_mipmap_y_size(n);
|
||||||
@ -10651,37 +10718,20 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
|||||||
component_type = GL_UNSIGNED_INT_24_8_EXT;
|
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) {
|
|
||||||
#ifndef OPENGLES
|
|
||||||
case GL_TEXTURE_1D:
|
|
||||||
glTexImage1D(page_target, 0, internal_format, width, 0, external_format, component_type, NULL);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_2D_ARRAY:
|
|
||||||
#endif
|
|
||||||
#ifndef OPENGLES_1
|
|
||||||
case GL_TEXTURE_3D:
|
|
||||||
_glTexImage3D(page_target, 0, internal_format, width, height, depth, 0, external_format, component_type, NULL);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
glTexImage2D(page_target, 0, internal_format, width, height, 0, external_format, component_type, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n = mipmap_bias; n < num_ram_mipmap_levels; ++n) {
|
for (int n = mipmap_bias; n < num_levels; ++n) {
|
||||||
const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
|
const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
|
||||||
CPTA_uchar ptimage;
|
CPTA_uchar ptimage;
|
||||||
if (image_ptr == (const unsigned char *)NULL) {
|
if (image_ptr == (const unsigned char *)NULL) {
|
||||||
ptimage = tex->get_ram_mipmap_image(n);
|
ptimage = tex->get_ram_mipmap_image(n);
|
||||||
if (ptimage == (const unsigned char *)NULL) {
|
if (ptimage.is_null()) {
|
||||||
|
if (n < num_ram_mipmap_levels) {
|
||||||
|
// We were told we'd have this many RAM mipmap images, but
|
||||||
|
// we don't. Raise a warning.
|
||||||
GLCAT.warning()
|
GLCAT.warning()
|
||||||
<< "No mipmap level " << n << " defined for " << tex->get_name()
|
<< "No mipmap level " << n << " defined for " << tex->get_name()
|
||||||
<< "\n";
|
<< "\n";
|
||||||
// No mipmap level n; stop here.
|
|
||||||
#ifndef OPENGLES
|
#ifndef OPENGLES
|
||||||
if (is_at_least_gl_version(1, 2)) {
|
if (is_at_least_gl_version(1, 2)) {
|
||||||
// Tell the GL we have no more mipmaps for it to use.
|
// Tell the GL we have no more mipmaps for it to use.
|
||||||
@ -10690,11 +10740,21 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tex->has_clear_color()) {
|
||||||
|
// Ask the Texture class to create the mipmap level in RAM.
|
||||||
|
// It'll fill it in with the correct clear color, which we
|
||||||
|
// can then upload.
|
||||||
|
ptimage = tex->make_ram_mipmap_image(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
image_ptr = ptimage;
|
image_ptr = ptimage;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char *orig_image_ptr = image_ptr;
|
PTA_uchar bgr_image;
|
||||||
size_t view_size = tex->get_ram_mipmap_view_size(n);
|
size_t view_size = tex->get_ram_mipmap_view_size(n);
|
||||||
|
if (image_ptr != (const unsigned char *)NULL) {
|
||||||
|
const unsigned char *orig_image_ptr = image_ptr;
|
||||||
image_ptr += view_size * gtc->get_view();
|
image_ptr += view_size * gtc->get_view();
|
||||||
if (one_page_only) {
|
if (one_page_only) {
|
||||||
view_size = tex->get_ram_mipmap_page_size(n);
|
view_size = tex->get_ram_mipmap_page_size(n);
|
||||||
@ -10702,13 +10762,13 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
|
|||||||
}
|
}
|
||||||
nassertr(image_ptr >= orig_image_ptr && image_ptr + view_size <= orig_image_ptr + tex->get_ram_mipmap_image_size(n), false);
|
nassertr(image_ptr >= orig_image_ptr && image_ptr + view_size <= orig_image_ptr + tex->get_ram_mipmap_image_size(n), false);
|
||||||
|
|
||||||
PTA_uchar bgr_image;
|
|
||||||
if (!_supports_bgr && image_compression == Texture::CM_off) {
|
if (!_supports_bgr && image_compression == Texture::CM_off) {
|
||||||
// If the GL doesn't claim to support BGR, we may have to reverse
|
// If the GL doesn't claim to support BGR, we may have to reverse
|
||||||
// the component ordering of the image.
|
// the component ordering of the image.
|
||||||
image_ptr = fix_component_ordering(bgr_image, image_ptr, view_size,
|
image_ptr = fix_component_ordering(bgr_image, image_ptr, view_size,
|
||||||
external_format, tex);
|
external_format, tex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int width = tex->get_expected_mipmap_x_size(n);
|
int width = tex->get_expected_mipmap_x_size(n);
|
||||||
int height = tex->get_expected_mipmap_y_size(n);
|
int height = tex->get_expected_mipmap_y_size(n);
|
||||||
|
@ -194,6 +194,8 @@ typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pna
|
|||||||
typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
|
typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
|
||||||
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
|
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
|
||||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
|
typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
|
||||||
|
typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
|
||||||
|
typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
|
||||||
typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
|
typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
|
||||||
typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers);
|
typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers);
|
||||||
typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
|
typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
|
||||||
@ -461,7 +463,7 @@ protected:
|
|||||||
static SamplerState::FilterType get_panda_filter_type(GLenum ft);
|
static SamplerState::FilterType get_panda_filter_type(GLenum ft);
|
||||||
GLenum get_component_type(Texture::ComponentType component_type);
|
GLenum get_component_type(Texture::ComponentType component_type);
|
||||||
GLint get_external_image_format(Texture *tex) const;
|
GLint get_external_image_format(Texture *tex) const;
|
||||||
GLint get_internal_image_format(Texture *tex) const;
|
GLint get_internal_image_format(Texture *tex, bool force_sized=false) const;
|
||||||
static bool is_mipmap_filter(GLenum min_filter);
|
static bool is_mipmap_filter(GLenum min_filter);
|
||||||
static bool is_compressed_format(GLenum format);
|
static bool is_compressed_format(GLenum format);
|
||||||
static GLint get_texture_apply_mode_type(TextureStage::Mode am);
|
static GLint get_texture_apply_mode_type(TextureStage::Mode am);
|
||||||
@ -644,6 +646,11 @@ public:
|
|||||||
PFNGLTEXSTORAGE2DPROC _glTexStorage2D;
|
PFNGLTEXSTORAGE2DPROC _glTexStorage2D;
|
||||||
PFNGLTEXSTORAGE3DPROC _glTexStorage3D;
|
PFNGLTEXSTORAGE3DPROC _glTexStorage3D;
|
||||||
|
|
||||||
|
bool _supports_clear_texture;
|
||||||
|
#ifndef OPENGLES
|
||||||
|
PFNGLCLEARTEXIMAGEPROC _glClearTexImage;
|
||||||
|
#endif
|
||||||
|
|
||||||
PFNGLCOMPRESSEDTEXIMAGE1DPROC _glCompressedTexImage1D;
|
PFNGLCOMPRESSEDTEXIMAGE1DPROC _glCompressedTexImage1D;
|
||||||
PFNGLCOMPRESSEDTEXIMAGE2DPROC _glCompressedTexImage2D;
|
PFNGLCOMPRESSEDTEXIMAGE2DPROC _glCompressedTexImage2D;
|
||||||
PFNGLCOMPRESSEDTEXIMAGE3DPROC _glCompressedTexImage3D;
|
PFNGLCOMPRESSEDTEXIMAGE3DPROC _glCompressedTexImage3D;
|
||||||
|
@ -1228,17 +1228,14 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
} else {
|
} else {
|
||||||
//TODO: automatically convert to sized type instead of plain GL_RGBA
|
//TODO: automatically convert to sized type instead of plain GL_RGBA
|
||||||
// If a base type is used, it will crash.
|
// If a base type is used, it will crash.
|
||||||
if (gtc->_internal_format == GL_RGBA || gtc->_internal_format == GL_RGB) {
|
GLenum internal_format = gtc->_internal_format;
|
||||||
|
if (internal_format == GL_RGBA || internal_format == GL_RGB) {
|
||||||
GLCAT.error()
|
GLCAT.error()
|
||||||
<< "Texture " << tex->get_name() << " has an unsized format. Textures bound "
|
<< "Texture " << tex->get_name() << " has an unsized format. Textures bound "
|
||||||
<< "to a shader as an image need a sized format.\n";
|
<< "to a shader as an image need a sized format.\n";
|
||||||
|
|
||||||
// This may not actually be right, but may still prevent a crash.
|
// This may not actually be right, but may still prevent a crash.
|
||||||
if (gtc->_internal_format == GL_RGBA) {
|
internal_format = _glgsg->get_internal_image_format(tex, true);
|
||||||
gtc->_internal_format = GL_RGBA8;
|
|
||||||
} else {
|
|
||||||
gtc->_internal_format = GL_RGB8;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum access = GL_READ_ONLY;
|
GLenum access = GL_READ_ONLY;
|
||||||
|
@ -55,7 +55,8 @@ clear() {
|
|||||||
// Description: Sets the texture to the indicated type and
|
// Description: Sets the texture to the indicated type and
|
||||||
// dimensions, presumably in preparation for calling
|
// dimensions, presumably in preparation for calling
|
||||||
// read() or load(), or set_ram_image() or
|
// read() or load(), or set_ram_image() or
|
||||||
// modify_ram_image().
|
// modify_ram_image(), or use set_clear_color to let
|
||||||
|
// the texture be cleared to a solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
||||||
@ -71,7 +72,9 @@ setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
|||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Sets the texture as an empty 1-d texture with no
|
// Description: Sets the texture as an empty 1-d texture with no
|
||||||
// dimensions. Follow up with read() or load() to fill
|
// dimensions. Follow up with read() or load() to fill
|
||||||
// the texture properties and image data.
|
// the texture properties and image data, or use
|
||||||
|
// set_clear_color to let the texture be cleared to a
|
||||||
|
// solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_1d_texture() {
|
setup_1d_texture() {
|
||||||
@ -84,7 +87,8 @@ setup_1d_texture() {
|
|||||||
// Description: Sets the texture as an empty 1-d texture with the
|
// Description: Sets the texture as an empty 1-d texture with the
|
||||||
// specified dimensions and properties. Follow up with
|
// specified dimensions and properties. Follow up with
|
||||||
// set_ram_image() or modify_ram_image() to fill the
|
// set_ram_image() or modify_ram_image() to fill the
|
||||||
// image data.
|
// image data, or use set_clear_color to let the
|
||||||
|
// texture be cleared to a solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_1d_texture(int x_size, ComponentType component_type, Format format) {
|
setup_1d_texture(int x_size, ComponentType component_type, Format format) {
|
||||||
@ -96,7 +100,9 @@ setup_1d_texture(int x_size, ComponentType component_type, Format format) {
|
|||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Sets the texture as an empty 2-d texture with no
|
// Description: Sets the texture as an empty 2-d texture with no
|
||||||
// dimensions. Follow up with read() or load() to fill
|
// dimensions. Follow up with read() or load() to fill
|
||||||
// the texture properties and image data.
|
// the texture properties and image data, or use
|
||||||
|
// set_clear_color to let the texture be cleared to a
|
||||||
|
// solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_2d_texture() {
|
setup_2d_texture() {
|
||||||
@ -109,7 +115,8 @@ setup_2d_texture() {
|
|||||||
// Description: Sets the texture as an empty 2-d texture with the
|
// Description: Sets the texture as an empty 2-d texture with the
|
||||||
// specified dimensions and properties. Follow up with
|
// specified dimensions and properties. Follow up with
|
||||||
// set_ram_image() or modify_ram_image() to fill the
|
// set_ram_image() or modify_ram_image() to fill the
|
||||||
// image data.
|
// image data, or use set_clear_color to let the
|
||||||
|
// texture be cleared to a solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_2d_texture(int x_size, int y_size, ComponentType component_type,
|
setup_2d_texture(int x_size, int y_size, ComponentType component_type,
|
||||||
@ -124,7 +131,8 @@ setup_2d_texture(int x_size, int y_size, ComponentType component_type,
|
|||||||
// dimensions (though if you know the depth ahead
|
// dimensions (though if you know the depth ahead
|
||||||
// of time, it saves a bit of reallocation later).
|
// of time, it saves a bit of reallocation later).
|
||||||
// Follow up with read() or load() to fill the texture
|
// Follow up with read() or load() to fill the texture
|
||||||
// properties and image data.
|
// properties and image data, or use set_clear_color
|
||||||
|
// to let the texture be cleared to a solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_3d_texture(int z_size) {
|
setup_3d_texture(int z_size) {
|
||||||
@ -152,7 +160,8 @@ setup_3d_texture(int x_size, int y_size, int z_size,
|
|||||||
// no dimensions (though if you know the depth ahead
|
// no dimensions (though if you know the depth ahead
|
||||||
// of time, it saves a bit of reallocation later).
|
// of time, it saves a bit of reallocation later).
|
||||||
// Follow up with read() or load() to fill the texture
|
// Follow up with read() or load() to fill the texture
|
||||||
// properties and image data.
|
// properties and image data, or use set_clear_color
|
||||||
|
// to let the texture be cleared to a solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_2d_texture_array(int z_size) {
|
setup_2d_texture_array(int z_size) {
|
||||||
@ -165,7 +174,8 @@ setup_2d_texture_array(int z_size) {
|
|||||||
// Description: Sets the texture as an empty 2-d texture array with the
|
// Description: Sets the texture as an empty 2-d texture array with the
|
||||||
// specified dimensions and properties. Follow up with
|
// specified dimensions and properties. Follow up with
|
||||||
// set_ram_image() or modify_ram_image() to fill the
|
// set_ram_image() or modify_ram_image() to fill the
|
||||||
// image data.
|
// image data, or use set_clear_color to let the
|
||||||
|
// texture be cleared to a solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_2d_texture_array(int x_size, int y_size, int z_size,
|
setup_2d_texture_array(int x_size, int y_size, int z_size,
|
||||||
@ -178,7 +188,9 @@ setup_2d_texture_array(int x_size, int y_size, int z_size,
|
|||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Sets the texture as an empty cube map texture with no
|
// Description: Sets the texture as an empty cube map texture with no
|
||||||
// dimensions. Follow up with read() or load() to fill
|
// dimensions. Follow up with read() or load() to fill
|
||||||
// the texture properties and image data.
|
// the texture properties and image data, or use
|
||||||
|
// set_clear_color to let the texture be cleared to a
|
||||||
|
// solid color.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void Texture::
|
INLINE void Texture::
|
||||||
setup_cube_map() {
|
setup_cube_map() {
|
||||||
@ -191,7 +203,8 @@ setup_cube_map() {
|
|||||||
// Description: Sets the texture as an empty cube map texture with
|
// Description: Sets the texture as an empty cube map texture with
|
||||||
// the specified dimensions and properties. Follow up
|
// the specified dimensions and properties. Follow up
|
||||||
// with set_ram_image() or modify_ram_image() to fill
|
// with set_ram_image() or modify_ram_image() to fill
|
||||||
// the image data.
|
// the image data, or use set_clear_color to let the
|
||||||
|
// texture be cleared to a solid color.
|
||||||
//
|
//
|
||||||
// Note that a cube map should always consist of six
|
// Note that a cube map should always consist of six
|
||||||
// square images, so x_size and y_size will be the same,
|
// square images, so x_size and y_size will be the same,
|
||||||
@ -202,6 +215,87 @@ setup_cube_map(int size, ComponentType component_type, Format format) {
|
|||||||
setup_texture(TT_cube_map, size, size, 6, component_type, format);
|
setup_texture(TT_cube_map, size, size, 6, component_type, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::clear_image
|
||||||
|
// Access: Published
|
||||||
|
// Description: Clears the texture data without changing its format
|
||||||
|
// or resolution. The texture is cleared on both the
|
||||||
|
// graphics hardware and from RAM, unlike clear_ram_image,
|
||||||
|
// which only removes the data from RAM.
|
||||||
|
//
|
||||||
|
// If a clear color has been specified using
|
||||||
|
// set_clear_color, the texture will be cleared using
|
||||||
|
// a solid color.
|
||||||
|
//
|
||||||
|
// The texture data will be cleared the first time in
|
||||||
|
// which the texture is used after this method is called.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void Texture::
|
||||||
|
clear_image() {
|
||||||
|
CDWriter cdata(_cycler, true);
|
||||||
|
do_clear_ram_image(cdata);
|
||||||
|
do_clear_simple_ram_image(cdata);
|
||||||
|
cdata->inc_image_modified();
|
||||||
|
cdata->inc_simple_image_modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::has_clear_color
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if a color was previously set using
|
||||||
|
// set_clear_color.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool Texture::
|
||||||
|
has_clear_color() const {
|
||||||
|
CDReader cdata(_cycler);
|
||||||
|
return cdata->_has_clear_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::get_clear_color
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the color that was previously set using
|
||||||
|
// set_clear_color.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE LColor Texture::
|
||||||
|
get_clear_color() const {
|
||||||
|
CDReader cdata(_cycler);
|
||||||
|
return cdata->_clear_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::set_clear_color
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the color that will be used to fill the
|
||||||
|
// texture image in absence of any image data. It is
|
||||||
|
// used when any of the setup_texture functions or
|
||||||
|
// clear_image is called and image data is not
|
||||||
|
// provided using read() or modify_ram_image().
|
||||||
|
//
|
||||||
|
// This does not affect a texture that has already
|
||||||
|
// been cleared; call clear_image to clear it again.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void Texture::
|
||||||
|
set_clear_color(const LColor &color) {
|
||||||
|
CDWriter cdata(_cycler, true);
|
||||||
|
cdata->_clear_color = color;
|
||||||
|
cdata->_has_clear_color = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::get_clear_data
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the raw image data for a single pixel if
|
||||||
|
// it were set to the clear color.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE string Texture::
|
||||||
|
get_clear_data() const {
|
||||||
|
CDReader cdata(_cycler);
|
||||||
|
unsigned char data[16];
|
||||||
|
int size = do_get_clear_data(cdata, data);
|
||||||
|
return string((char *)data, size);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Texture::write
|
// Function: Texture::write
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -4258,12 +4258,26 @@ do_modify_ram_image(CData *cdata) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PTA_uchar Texture::
|
PTA_uchar Texture::
|
||||||
do_make_ram_image(CData *cdata) {
|
do_make_ram_image(CData *cdata) {
|
||||||
|
int image_size = do_get_expected_ram_image_size(cdata);
|
||||||
cdata->_ram_images.clear();
|
cdata->_ram_images.clear();
|
||||||
cdata->_ram_images.push_back(RamImage());
|
cdata->_ram_images.push_back(RamImage());
|
||||||
cdata->_ram_images[0]._page_size = do_get_expected_ram_page_size(cdata);
|
cdata->_ram_images[0]._page_size = do_get_expected_ram_page_size(cdata);
|
||||||
cdata->_ram_images[0]._image = PTA_uchar::empty_array(do_get_expected_ram_image_size(cdata), get_class_type());
|
cdata->_ram_images[0]._image = PTA_uchar::empty_array(image_size, get_class_type());
|
||||||
cdata->_ram_images[0]._pointer_image = NULL;
|
cdata->_ram_images[0]._pointer_image = NULL;
|
||||||
cdata->_ram_image_compression = CM_off;
|
cdata->_ram_image_compression = CM_off;
|
||||||
|
|
||||||
|
if (cdata->_has_clear_color) {
|
||||||
|
// Fill the image with the clear color.
|
||||||
|
unsigned char pixel[16];
|
||||||
|
const int pixel_size = do_get_clear_data(cdata, pixel);
|
||||||
|
nassertr(pixel_size > 0, cdata->_ram_images[0]._image);
|
||||||
|
|
||||||
|
unsigned char *image_data = cdata->_ram_images[0]._image;
|
||||||
|
for (int i = 0; i < image_size; i += pixel_size) {
|
||||||
|
memcpy(image_data + i, pixel, pixel_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cdata->_ram_images[0]._image;
|
return cdata->_ram_images[0]._image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4331,9 +4345,23 @@ do_make_ram_mipmap_image(CData *cdata, int n) {
|
|||||||
cdata->_ram_images.push_back(RamImage());
|
cdata->_ram_images.push_back(RamImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
cdata->_ram_images[n]._image = PTA_uchar::empty_array(do_get_expected_ram_mipmap_image_size(cdata, n), get_class_type());
|
size_t image_size = do_get_expected_ram_mipmap_image_size(cdata, n);
|
||||||
|
cdata->_ram_images[n]._image = PTA_uchar::empty_array(image_size, get_class_type());
|
||||||
cdata->_ram_images[n]._pointer_image = NULL;
|
cdata->_ram_images[n]._pointer_image = NULL;
|
||||||
cdata->_ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
|
cdata->_ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
|
||||||
|
|
||||||
|
if (cdata->_has_clear_color) {
|
||||||
|
// Fill the image with the clear color.
|
||||||
|
unsigned char pixel[16];
|
||||||
|
const int pixel_size = do_get_clear_data(cdata, pixel);
|
||||||
|
nassertr(pixel_size > 0, cdata->_ram_images[n]._image);
|
||||||
|
|
||||||
|
unsigned char *image_data = cdata->_ram_images[n]._image;
|
||||||
|
for (int i = 0; i < image_size; i += pixel_size) {
|
||||||
|
memcpy(image_data + i, pixel, pixel_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cdata->_ram_images[n]._image;
|
return cdata->_ram_images[n]._image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4362,6 +4390,116 @@ do_set_ram_mipmap_image(CData *cdata, int n, CPTA_uchar image, size_t page_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::do_get_clear_color
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns a string with a single pixel representing
|
||||||
|
// the clear color of the texture in the format of
|
||||||
|
// this texture.
|
||||||
|
//
|
||||||
|
// In other words, to create an uncompressed RAM
|
||||||
|
// texture filled with the clear color, it should
|
||||||
|
// be initialized with this string repeated for
|
||||||
|
// every pixel.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int Texture::
|
||||||
|
do_get_clear_data(const CData *cdata, unsigned char *into) const {
|
||||||
|
nassertr(cdata->_has_clear_color, 0);
|
||||||
|
nassertr(cdata->_num_components <= 4, 0);
|
||||||
|
|
||||||
|
//TODO: encode the color into the sRGB color space if used
|
||||||
|
switch (cdata->_component_type) {
|
||||||
|
case T_unsigned_byte:
|
||||||
|
{
|
||||||
|
LColorf scaled = cdata->_clear_color.fmin(LColorf(1)).fmax(LColorf::zero());
|
||||||
|
scaled *= 255;
|
||||||
|
switch (cdata->_num_components) {
|
||||||
|
case 2:
|
||||||
|
into[1] = (unsigned char)scaled[1];
|
||||||
|
case 1:
|
||||||
|
into[0] = (unsigned char)scaled[0];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
into[3] = (unsigned char)scaled[3];
|
||||||
|
case 3: // BGR <-> RGB
|
||||||
|
into[0] = (unsigned char)scaled[2];
|
||||||
|
into[1] = (unsigned char)scaled[1];
|
||||||
|
into[2] = (unsigned char)scaled[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case T_unsigned_short:
|
||||||
|
{
|
||||||
|
LColorf scaled = cdata->_clear_color.fmin(LColorf(1)).fmax(LColorf::zero());
|
||||||
|
scaled *= 65535;
|
||||||
|
switch (cdata->_num_components) {
|
||||||
|
case 2:
|
||||||
|
((unsigned short *)into)[1] = (unsigned short)scaled[1];
|
||||||
|
case 1:
|
||||||
|
((unsigned short *)into)[0] = (unsigned short)scaled[0];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
((unsigned short *)into)[3] = (unsigned short)scaled[3];
|
||||||
|
case 3: // BGR <-> RGB
|
||||||
|
((unsigned short *)into)[0] = (unsigned short)scaled[2];
|
||||||
|
((unsigned short *)into)[1] = (unsigned short)scaled[1];
|
||||||
|
((unsigned short *)into)[2] = (unsigned short)scaled[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case T_float:
|
||||||
|
switch (cdata->_num_components) {
|
||||||
|
case 2:
|
||||||
|
((float *)into)[1] = cdata->_clear_color[1];
|
||||||
|
case 1:
|
||||||
|
((float *)into)[0] = cdata->_clear_color[0];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
((float *)into)[3] = cdata->_clear_color[3];
|
||||||
|
case 3: // BGR <-> RGB
|
||||||
|
((float *)into)[0] = cdata->_clear_color[2];
|
||||||
|
((float *)into)[1] = cdata->_clear_color[1];
|
||||||
|
((float *)into)[2] = cdata->_clear_color[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_unsigned_int_24_8:
|
||||||
|
nassertr(cdata->_num_components == 1, 0);
|
||||||
|
*((unsigned int *)into) =
|
||||||
|
((unsigned int)(cdata->_clear_color[0] * 16777215) << 8) +
|
||||||
|
(unsigned int)max(min(cdata->_clear_color[1], 255), 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_int:
|
||||||
|
{
|
||||||
|
// Note: there are no 32-bit UNORM textures. Therefore, we don't
|
||||||
|
// do any normalization here, either.
|
||||||
|
switch (cdata->_num_components) {
|
||||||
|
case 2:
|
||||||
|
((int *)into)[1] = (int)cdata->_clear_color[1];
|
||||||
|
case 1:
|
||||||
|
((int *)into)[0] = (int)cdata->_clear_color[0];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
((int *)into)[3] = (int)cdata->_clear_color[3];
|
||||||
|
case 3: // BGR <-> RGB
|
||||||
|
((int *)into)[0] = (int)cdata->_clear_color[2];
|
||||||
|
((int *)into)[1] = (int)cdata->_clear_color[1];
|
||||||
|
((int *)into)[2] = (int)cdata->_clear_color[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cdata->_num_components * cdata->_component_width;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Texture::consider_auto_process_ram_image
|
// Function: Texture::consider_auto_process_ram_image
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -8151,6 +8289,8 @@ CData() {
|
|||||||
_simple_x_size = 0;
|
_simple_x_size = 0;
|
||||||
_simple_y_size = 0;
|
_simple_y_size = 0;
|
||||||
_simple_ram_image._page_size = 0;
|
_simple_ram_image._page_size = 0;
|
||||||
|
|
||||||
|
_has_clear_color = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -234,6 +234,12 @@ PUBLISHED:
|
|||||||
void generate_normalization_cube_map(int size);
|
void generate_normalization_cube_map(int size);
|
||||||
void generate_alpha_scale_map();
|
void generate_alpha_scale_map();
|
||||||
|
|
||||||
|
INLINE void clear_image();
|
||||||
|
INLINE bool has_clear_color() const;
|
||||||
|
INLINE LColor get_clear_color() const;
|
||||||
|
INLINE void set_clear_color(const LColor &color);
|
||||||
|
INLINE string get_clear_data() const;
|
||||||
|
|
||||||
BLOCKING bool read(const Filename &fullpath, const LoaderOptions &options = LoaderOptions());
|
BLOCKING bool read(const Filename &fullpath, const LoaderOptions &options = LoaderOptions());
|
||||||
BLOCKING bool read(const Filename &fullpath, const Filename &alpha_fullpath,
|
BLOCKING bool read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||||
int primary_file_num_channels, int alpha_file_channel,
|
int primary_file_num_channels, int alpha_file_channel,
|
||||||
@ -569,6 +575,7 @@ protected:
|
|||||||
PTA_uchar do_modify_ram_mipmap_image(CData *cdata, int n);
|
PTA_uchar do_modify_ram_mipmap_image(CData *cdata, int n);
|
||||||
PTA_uchar do_make_ram_mipmap_image(CData *cdata, int n);
|
PTA_uchar do_make_ram_mipmap_image(CData *cdata, int n);
|
||||||
void do_set_ram_mipmap_image(CData *cdata, int n, CPTA_uchar image, size_t page_size);
|
void do_set_ram_mipmap_image(CData *cdata, int n, CPTA_uchar image, size_t page_size);
|
||||||
|
int do_get_clear_data(const CData *cdata, unsigned char *into) const;
|
||||||
|
|
||||||
bool consider_auto_process_ram_image(bool generate_mipmaps, bool allow_compression);
|
bool consider_auto_process_ram_image(bool generate_mipmaps, bool allow_compression);
|
||||||
bool do_consider_auto_process_ram_image(CData *cdata, bool generate_mipmaps,
|
bool do_consider_auto_process_ram_image(CData *cdata, bool generate_mipmaps,
|
||||||
@ -844,6 +851,10 @@ protected:
|
|||||||
int _simple_y_size;
|
int _simple_y_size;
|
||||||
PN_int32 _simple_image_date_generated;
|
PN_int32 _simple_image_date_generated;
|
||||||
|
|
||||||
|
// This is the color that should be used when no image was given.
|
||||||
|
bool _has_clear_color;
|
||||||
|
LColor _clear_color;
|
||||||
|
|
||||||
UpdateSeq _properties_modified;
|
UpdateSeq _properties_modified;
|
||||||
UpdateSeq _image_modified;
|
UpdateSeq _image_modified;
|
||||||
UpdateSeq _simple_image_modified;
|
UpdateSeq _simple_image_modified;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user