Browse Source

glgsg: Implement partial updates of texture arrays / cube maps

Also, simplify the cube map upload mechanism somewhat.

Fixes #1168
rdb 4 years ago
parent
commit
bfe595f4dc

+ 131 - 118
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1084,10 +1084,12 @@ reset() {
   if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_clear_texture")) {
   if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_clear_texture")) {
     _glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)
     _glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)
       get_extension_func("glClearTexImage");
       get_extension_func("glClearTexImage");
+    _glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC)
+      get_extension_func("glClearTexSubImage");
 
 
-    if (_glClearTexImage == nullptr) {
+    if (_glClearTexImage == nullptr || _glClearTexSubImage == nullptr) {
       GLCAT.warning()
       GLCAT.warning()
-        << "GL_ARB_clear_texture advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n";
+        << "GL_ARB_clear_texture advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
     } else {
     } else {
       _supports_clear_texture = true;
       _supports_clear_texture = true;
     }
     }
@@ -13458,59 +13460,9 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
     }
     }
   }
   }
 
 
-  bool success = true;
-  if (texture_type == Texture::TT_cube_map) {
-    // A cube map must load six different 2-d images (which are stored as the
-    // six pages of the system ram image).
-    if (!_supports_cube_map) {
-      report_my_gl_errors();
-      return false;
-    }
-    nassertr(target == GL_TEXTURE_CUBE_MAP, false);
-
-    success = success && upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias,
-       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
-       internal_format, external_format, component_type,
-       true, 0, image_compression);
-
-    success = success && upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias,
-       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
-       internal_format, external_format, component_type,
-       true, 1, image_compression);
-
-    success = success && upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias,
-       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
-       internal_format, external_format, component_type,
-       true, 2, image_compression);
-
-    success = success && upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias,
-       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
-       internal_format, external_format, component_type,
-       true, 3, image_compression);
-
-    success = success && upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias,
-       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-       internal_format, external_format, component_type,
-       true, 4, image_compression);
-
-    success = success && upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias,
-       GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
-       internal_format, external_format, component_type,
-       true, 5, image_compression);
-
-  } else {
-    // Any other kind of texture can be loaded all at once.
-    success = upload_texture_image
-      (gtc, needs_reload, uses_mipmaps, mipmap_bias, target,
-       target, internal_format, external_format,
-       component_type, false, 0, image_compression);
-  }
+  bool success = upload_texture_image
+    (gtc, needs_reload, uses_mipmaps, mipmap_bias, target,
+     internal_format, external_format, component_type, image_compression);
 
 
   if (gtc->_generate_mipmaps && _glGenerateMipmap != nullptr &&
   if (gtc->_generate_mipmaps && _glGenerateMipmap != nullptr &&
       !image.is_null()) {
       !image.is_null()) {
@@ -13571,21 +13523,13 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
 /**
 /**
  * Loads a texture image, or one page of a cube map image, from system RAM to
  * Loads a texture image, or one page of a cube map image, from system RAM to
  * texture memory.
  * texture memory.
- *
- * texture_target is normally the same thing as page_target; both represent
- * the GL target onto which the texture image is loaded, e.g.  GL_TEXTURE_1D,
- * GL_TEXTURE_2D, etc.  The only time they may differ is in the case of cube
- * mapping, in which case texture_target will be target for the overall
- * texture, e.g.  GL_TEXTURE_CUBE_MAP, and page_target will be the target for
- * this particular page, e.g.  GL_TEXTURE_CUBE_MAP_POSITIVE_X.
  */
  */
 bool CLP(GraphicsStateGuardian)::
 bool CLP(GraphicsStateGuardian)::
 upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
 upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
                      bool uses_mipmaps, int mipmap_bias,
                      bool uses_mipmaps, int mipmap_bias,
-                     GLenum texture_target, GLenum page_target,
+                     GLenum texture_target,
                      GLint internal_format,
                      GLint internal_format,
                      GLint external_format, GLenum component_type,
                      GLint external_format, GLenum component_type,
-                     bool one_page_only, int z,
                      Texture::CompressionMode image_compression) {
                      Texture::CompressionMode image_compression) {
   // Make sure the error stack is cleared out before we begin.
   // Make sure the error stack is cleared out before we begin.
   clear_my_gl_errors();
   clear_my_gl_errors();
@@ -13635,29 +13579,32 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
     // saving on texture memory fragmentation.
     // saving on texture memory fragmentation.
 
 
     if (GLCAT.is_debug()) {
     if (GLCAT.is_debug()) {
+      SparseArray pages = gtc->get_image_modified_pages(0);
       if (num_ram_mipmap_levels == 0) {
       if (num_ram_mipmap_levels == 0) {
         if (tex->has_clear_color()) {
         if (tex->has_clear_color()) {
           GLCAT.debug()
           GLCAT.debug()
             << "clearing texture " << tex->get_name() << ", "
             << "clearing texture " << tex->get_name() << ", "
-            << width << " x " << height << " x " << depth << ", z = " << z
+            << width << " x " << height << " x " << depth << ", pages " << pages
             << ", uses_mipmaps = " << uses_mipmaps << ", clear_color = "
             << ", uses_mipmaps = " << uses_mipmaps << ", clear_color = "
             << tex->get_clear_color() << "\n";
             << tex->get_clear_color() << "\n";
         } else {
         } else {
           GLCAT.debug()
           GLCAT.debug()
             << "not loading NULL image for texture " << tex->get_name()
             << "not loading NULL image for texture " << tex->get_name()
             << ", " << width << " x " << height << " x " << depth
             << ", " << width << " x " << height << " x " << depth
-            << ", z = " << z << ", uses_mipmaps = " << uses_mipmaps << "\n";
+            << ", pages " << pages << ", uses_mipmaps = " << uses_mipmaps << "\n";
         }
         }
       } else {
       } else {
         GLCAT.debug()
         GLCAT.debug()
           << "updating image data of texture " << tex->get_name()
           << "updating image data of texture " << tex->get_name()
           << ", " << width << " x " << height << " x " << depth
           << ", " << width << " x " << height << " x " << depth
-          << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels
+          << ", pages " << pages << ", mipmaps " << num_ram_mipmap_levels
           << ", uses_mipmaps = " << uses_mipmaps << "\n";
           << ", uses_mipmaps = " << uses_mipmaps << "\n";
       }
       }
     }
     }
 
 
     for (int n = mipmap_bias; n < num_levels; ++n) {
     for (int n = mipmap_bias; n < num_levels; ++n) {
+      SparseArray pages = gtc->get_image_modified_pages(n);
+
       // we grab the mipmap pointer first, if it is NULL we grab the normal
       // we grab the mipmap pointer first, if it is NULL we grab the normal
       // mipmap image pointer which is a PTA_uchar
       // 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);
@@ -13684,8 +13631,17 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
                 // function.
                 // function.
                 vector_uchar clear_data = tex->get_clear_data();
                 vector_uchar clear_data = tex->get_clear_data();
 
 
-                _glClearTexImage(gtc->_index, n - mipmap_bias, external_format,
-                                 component_type, (void *)&clear_data[0]);
+                if (pages.has_all_of(0, depth)) {
+                  _glClearTexImage(gtc->_index, n - mipmap_bias, external_format,
+                                   component_type, (void *)&clear_data[0]);
+                }
+                else for (size_t sri = 0; sri < pages.get_num_subranges(); ++sri) {
+                  int begin = pages.get_subrange_begin(sri);
+                  int num_pages = pages.get_subrange_end(sri) - begin;
+                  _glClearTexSubImage(gtc->_index, n - mipmap_bias, 0, 0, begin,
+                                      width, height, num_pages, external_format,
+                                      component_type, (void *)&clear_data[0]);
+                }
                 continue;
                 continue;
               }
               }
             } else {
             } else {
@@ -13714,14 +13670,11 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
       }
       }
 
 
       PTA_uchar bgr_image;
       PTA_uchar bgr_image;
-      size_t view_size = tex->get_ram_mipmap_view_size(n);
+      size_t page_size = tex->get_ram_mipmap_page_size(n);
       if (image_ptr != nullptr) {
       if (image_ptr != nullptr) {
         const unsigned char *orig_image_ptr = image_ptr;
         const unsigned char *orig_image_ptr = image_ptr;
+        size_t view_size = tex->get_ram_mipmap_view_size(n);
         image_ptr += view_size * gtc->get_view();
         image_ptr += view_size * gtc->get_view();
-        if (one_page_only) {
-          view_size = tex->get_ram_mipmap_page_size(n);
-          image_ptr += view_size * z;
-        }
         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);
 
 
         if (image_compression == Texture::CM_off) {
         if (image_compression == Texture::CM_off) {
@@ -13734,23 +13687,29 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
 
 
       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);
-#ifndef OPENGLES_1
-      int depth = tex->get_expected_mipmap_z_size(n);
-#endif
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
-      _data_transferred_pcollector.add_level(view_size);
+      _data_transferred_pcollector.add_level(page_size * pages.get_num_on_bits());
 #endif
 #endif
       switch (texture_target) {
       switch (texture_target) {
 #ifndef OPENGLES_1
 #ifndef OPENGLES_1
       case GL_TEXTURE_3D:
       case GL_TEXTURE_3D:
         if (_supports_3d_texture) {
         if (_supports_3d_texture) {
-          if (image_compression == Texture::CM_off) {
-            _glTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth,
-                             external_format, component_type, image_ptr);
-          } else {
-            _glCompressedTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth,
-                                       external_format, view_size, image_ptr);
+          for (size_t sri = 0; sri < pages.get_num_subranges(); ++sri) {
+            int begin = pages.get_subrange_begin(sri);
+            int num_pages = pages.get_subrange_end(sri) - begin;
+            const unsigned char *page_ptr = image_ptr + page_size * begin;
+
+            if (image_compression == Texture::CM_off) {
+              _glTexSubImage3D(texture_target, n - mipmap_bias,
+                               0, 0, begin, width, height, num_pages,
+                               external_format, component_type, page_ptr);
+            } else {
+              _glCompressedTexSubImage3D(texture_target, n - mipmap_bias,
+                                         0, 0, begin, width, height, num_pages,
+                                         external_format,
+                                         page_size * num_pages, page_ptr);
+            }
           }
           }
         } else {
         } else {
           report_my_gl_errors();
           report_my_gl_errors();
@@ -13762,11 +13721,11 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
 #ifndef OPENGLES
 #ifndef OPENGLES
       case GL_TEXTURE_1D:
       case GL_TEXTURE_1D:
         if (image_compression == Texture::CM_off) {
         if (image_compression == Texture::CM_off) {
-          glTexSubImage1D(page_target, n - mipmap_bias, 0, width,
+          glTexSubImage1D(texture_target, n - mipmap_bias, 0, width,
                           external_format, component_type, image_ptr);
                           external_format, component_type, image_ptr);
         } else {
         } else {
-          _glCompressedTexSubImage1D(page_target, n - mipmap_bias, 0, width,
-                                     external_format, view_size, image_ptr);
+          _glCompressedTexSubImage1D(texture_target, n - mipmap_bias, 0, width,
+                                     external_format, page_size, image_ptr);
         }
         }
         break;
         break;
 #endif  // OPENGLES
 #endif  // OPENGLES
@@ -13775,12 +13734,21 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
       case GL_TEXTURE_2D_ARRAY:
       case GL_TEXTURE_2D_ARRAY:
       case GL_TEXTURE_CUBE_MAP_ARRAY:
       case GL_TEXTURE_CUBE_MAP_ARRAY:
         if (_supports_2d_texture_array) {
         if (_supports_2d_texture_array) {
-          if (image_compression == Texture::CM_off) {
-            _glTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth,
-                             external_format, component_type, image_ptr);
-          } else {
-            _glCompressedTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth,
-                                       external_format, view_size, image_ptr);
+          for (size_t sri = 0; sri < pages.get_num_subranges(); ++sri) {
+            int begin = pages.get_subrange_begin(sri);
+            int num_pages = pages.get_subrange_end(sri) - begin;
+            const unsigned char *page_ptr = image_ptr + page_size * begin;
+
+            if (image_compression == Texture::CM_off) {
+              _glTexSubImage3D(texture_target, n - mipmap_bias,
+                               0, 0, begin, width, height, num_pages,
+                               external_format, component_type, page_ptr);
+            } else {
+              _glCompressedTexSubImage3D(texture_target, n - mipmap_bias,
+                                         0, 0, begin, width, height, num_pages,
+                                         external_format,
+                                         page_size * num_pages, page_ptr);
+            }
           }
           }
         } else {
         } else {
           report_my_gl_errors();
           report_my_gl_errors();
@@ -13792,7 +13760,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
 #ifndef OPENGLES
 #ifndef OPENGLES
       case GL_TEXTURE_BUFFER:
       case GL_TEXTURE_BUFFER:
         if (_supports_buffer_texture) {
         if (_supports_buffer_texture) {
-          _glBufferSubData(GL_TEXTURE_BUFFER, 0, view_size, image_ptr);
+          _glBufferSubData(GL_TEXTURE_BUFFER, 0, page_size, image_ptr);
         } else {
         } else {
           report_my_gl_errors();
           report_my_gl_errors();
           return false;
           return false;
@@ -13800,18 +13768,46 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
         break;
         break;
 #endif  // OPENGLES
 #endif  // OPENGLES
 
 
+      case GL_TEXTURE_CUBE_MAP:
+        if (_supports_cube_map) {
+          // This is the only texture type that must be specified using separate
+          // per-page calls.
+          if (n == 0) {
+            height = tex->get_y_size() - tex->get_pad_y_size();
+          }
+          for (int z = 0; z < 6; ++z) {
+            if (pages.get_bit(z)) {
+              GLenum page_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z;
+              const unsigned char *page_ptr = image_ptr + page_size * z;
+
+              if (image_compression == Texture::CM_off) {
+                glTexSubImage2D(page_target, n - mipmap_bias, 0, 0, width, height,
+                                external_format, component_type, page_ptr);
+              } else {
+                _glCompressedTexSubImage2D(page_target, n - mipmap_bias,
+                                           0, 0, width, height,
+                                           external_format, page_size, page_ptr);
+              }
+            }
+          }
+        } else {
+          report_my_gl_errors();
+          return false;
+        }
+        break;
+
       default:
       default:
         if (image_compression == Texture::CM_off) {
         if (image_compression == Texture::CM_off) {
-          if (n==0) {
+          if (n == 0) {
             // It's unfortunate that we can't adjust the width, too, but
             // It's unfortunate that we can't adjust the width, too, but
             // TexSubImage2D doesn't accept a row-stride parameter.
             // TexSubImage2D doesn't accept a row-stride parameter.
             height = tex->get_y_size() - tex->get_pad_y_size();
             height = tex->get_y_size() - tex->get_pad_y_size();
           }
           }
-          glTexSubImage2D(page_target, n - mipmap_bias, 0, 0, width, height,
+          glTexSubImage2D(texture_target, n - mipmap_bias, 0, 0, width, height,
                           external_format, component_type, image_ptr);
                           external_format, component_type, image_ptr);
         } else {
         } else {
-          _glCompressedTexSubImage2D(page_target, n - mipmap_bias, 0, 0, width, height,
-                                     external_format, view_size, image_ptr);
+          _glCompressedTexSubImage2D(texture_target, n - mipmap_bias, 0, 0, width, height,
+                                     external_format, page_size, image_ptr);
         }
         }
         break;
         break;
       }
       }
@@ -13835,7 +13831,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
     if (GLCAT.is_debug()) {
     if (GLCAT.is_debug()) {
       GLCAT.debug()
       GLCAT.debug()
         << "loading new texture object for " << tex->get_name() << ", " << width
         << "loading new texture object for " << tex->get_name() << ", " << width
-        << " x " << height << " x " << depth << ", z = " << z << ", mipmaps "
+        << " x " << height << " x " << depth << ", mipmaps "
         << num_ram_mipmap_levels << ", uses_mipmaps = " << uses_mipmaps << "\n";
         << num_ram_mipmap_levels << ", uses_mipmaps = " << uses_mipmaps << "\n";
     }
     }
 
 
@@ -13900,10 +13896,6 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
       if (image_ptr != nullptr) {
       if (image_ptr != nullptr) {
         const unsigned char *orig_image_ptr = image_ptr;
         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) {
-          view_size = tex->get_ram_mipmap_page_size(n);
-          image_ptr += view_size * z;
-        }
         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);
 
 
         if (image_compression == Texture::CM_off) {
         if (image_compression == Texture::CM_off) {
@@ -13927,12 +13919,11 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
 #ifndef OPENGLES  // 1-d textures not supported by OpenGL ES.  Fall through.
 #ifndef OPENGLES  // 1-d textures not supported by OpenGL ES.  Fall through.
       case GL_TEXTURE_1D:
       case GL_TEXTURE_1D:
         if (image_compression == Texture::CM_off) {
         if (image_compression == Texture::CM_off) {
-          glTexImage1D(page_target, n - mipmap_bias, internal_format,
-                       width, 0,
-                       external_format, component_type, image_ptr);
+          glTexImage1D(texture_target, n - mipmap_bias, internal_format,
+                       width, 0, external_format, component_type, image_ptr);
         } else {
         } else {
-          _glCompressedTexImage1D(page_target, n - mipmap_bias, external_format, width,
-                                  0, view_size, image_ptr);
+          _glCompressedTexImage1D(texture_target, n - mipmap_bias, external_format,
+                                  width, 0, view_size, image_ptr);
         }
         }
         break;
         break;
 #endif  // OPENGLES  // OpenGL ES will fall through.
 #endif  // OPENGLES  // OpenGL ES will fall through.
@@ -13941,13 +13932,12 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
       case GL_TEXTURE_3D:
       case GL_TEXTURE_3D:
         if (_supports_3d_texture) {
         if (_supports_3d_texture) {
           if (image_compression == Texture::CM_off) {
           if (image_compression == Texture::CM_off) {
-            _glTexImage3D(page_target, n - mipmap_bias, internal_format,
+            _glTexImage3D(texture_target, n - mipmap_bias, internal_format,
                           width, height, depth, 0,
                           width, height, depth, 0,
                           external_format, component_type, image_ptr);
                           external_format, component_type, image_ptr);
           } else {
           } else {
-            _glCompressedTexImage3D(page_target, n - mipmap_bias, external_format, width,
-                                    height, depth,
-                                    0, view_size, image_ptr);
+            _glCompressedTexImage3D(texture_target, n - mipmap_bias, external_format,
+                                    width, height, depth, 0, view_size, image_ptr);
           }
           }
         } else {
         } else {
           report_my_gl_errors();
           report_my_gl_errors();
@@ -13961,13 +13951,12 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
       case GL_TEXTURE_CUBE_MAP_ARRAY:
       case GL_TEXTURE_CUBE_MAP_ARRAY:
         if (_supports_2d_texture_array) {
         if (_supports_2d_texture_array) {
           if (image_compression == Texture::CM_off) {
           if (image_compression == Texture::CM_off) {
-            _glTexImage3D(page_target, n - mipmap_bias, internal_format,
+            _glTexImage3D(texture_target, n - mipmap_bias, internal_format,
                           width, height, depth, 0,
                           width, height, depth, 0,
                           external_format, component_type, image_ptr);
                           external_format, component_type, image_ptr);
           } else {
           } else {
-            _glCompressedTexImage3D(page_target, n - mipmap_bias, external_format, width,
-                                    height, depth,
-                                    0, view_size, image_ptr);
+            _glCompressedTexImage3D(texture_target, n - mipmap_bias, external_format,
+                                    width, height, depth, 0, view_size, image_ptr);
           }
           }
         } else {
         } else {
           report_my_gl_errors();
           report_my_gl_errors();
@@ -13988,13 +13977,37 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
         break;
         break;
 #endif  // OPENGLES
 #endif  // OPENGLES
 
 
+      case GL_TEXTURE_CUBE_MAP:
+        if (_supports_cube_map) {
+          // This is the only texture type that must be specified using separate
+          // per-page calls.
+          size_t page_size = tex->get_ram_mipmap_page_size(n);
+          for (int z = 0; z < 6; ++z) {
+            GLenum page_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z;
+            const unsigned char *page_ptr = image_ptr + page_size * z;
+
+            if (image_compression == Texture::CM_off) {
+              glTexImage2D(page_target, n - mipmap_bias, internal_format,
+                           width, height, 0,
+                           external_format, component_type, page_ptr);
+            } else {
+              _glCompressedTexImage2D(page_target, n - mipmap_bias, external_format,
+                                      width, height, 0, page_size, page_ptr);
+            }
+          }
+        } else {
+          report_my_gl_errors();
+          return false;
+        }
+        break;
+
       default:
       default:
         if (image_compression == Texture::CM_off) {
         if (image_compression == Texture::CM_off) {
-          glTexImage2D(page_target, n - mipmap_bias, internal_format,
+          glTexImage2D(texture_target, n - mipmap_bias, internal_format,
                        width, height, 0,
                        width, height, 0,
                        external_format, component_type, image_ptr);
                        external_format, component_type, image_ptr);
         } else {
         } else {
-          _glCompressedTexImage2D(page_target, n - mipmap_bias, external_format,
+          _glCompressedTexImage2D(texture_target, n - mipmap_bias, external_format,
                                   width, height, 0, view_size, image_ptr);
                                   width, height, 0, view_size, image_ptr);
         }
         }
       }
       }

+ 2 - 2
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -616,10 +616,9 @@ protected:
   bool upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps);
   bool upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps);
   bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
   bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
                             bool uses_mipmaps, int mipmap_bias,
                             bool uses_mipmaps, int mipmap_bias,
-                            GLenum texture_target, GLenum page_target,
+                            GLenum texture_target,
                             GLint internal_format, GLint external_format,
                             GLint internal_format, GLint external_format,
                             GLenum component_type,
                             GLenum component_type,
-                            bool one_page_only, int z,
                             Texture::CompressionMode image_compression);
                             Texture::CompressionMode image_compression);
   void generate_mipmaps(CLP(TextureContext) *gtc);
   void generate_mipmaps(CLP(TextureContext) *gtc);
   bool upload_simple_texture(CLP(TextureContext) *gtc);
   bool upload_simple_texture(CLP(TextureContext) *gtc);
@@ -808,6 +807,7 @@ public:
   bool _supports_clear_texture;
   bool _supports_clear_texture;
 #ifndef OPENGLES
 #ifndef OPENGLES
   PFNGLCLEARTEXIMAGEPROC _glClearTexImage;
   PFNGLCLEARTEXIMAGEPROC _glClearTexImage;
+  PFNGLCLEARTEXSUBIMAGEPROC _glClearTexSubImage;
 #endif
 #endif
 
 
   bool _supports_clear_buffer;
   bool _supports_clear_buffer;