Browse Source

Support sampler states in tinyGL renderer

rdb 11 years ago
parent
commit
8a5452b0b6

+ 63 - 44
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -34,6 +34,7 @@
 #include "lightAttrib.h"
 #include "lightAttrib.h"
 #include "scissorAttrib.h"
 #include "scissorAttrib.h"
 #include "bitMask.h"
 #include "bitMask.h"
+#include "samplerState.h"
 #include "zgl.h"
 #include "zgl.h"
 #include "zmath.h"
 #include "zmath.h"
 #include "ztriangle_table.h"
 #include "ztriangle_table.h"
@@ -118,7 +119,7 @@ reset() {
   _c->draw_triangle_back = gl_draw_triangle_fill;
   _c->draw_triangle_back = gl_draw_triangle_fill;
 
 
   _supported_geom_rendering =
   _supported_geom_rendering =
-    Geom::GR_point | 
+    Geom::GR_point |
     Geom::GR_indexed_other |
     Geom::GR_indexed_other |
     Geom::GR_triangle_strip |
     Geom::GR_triangle_strip |
     Geom::GR_flat_last_vertex;
     Geom::GR_flat_last_vertex;
@@ -568,7 +569,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     }
     }
 
 
     // Compose the modelview and projection matrices.
     // Compose the modelview and projection matrices.
-    load_matrix(&_c->matrix_model_projection, 
+    load_matrix(&_c->matrix_model_projection,
                 scissor_proj_mat->compose(_internal_transform));
                 scissor_proj_mat->compose(_internal_transform));
 
 
     /* test to accelerate computation */
     /* test to accelerate computation */
@@ -658,7 +659,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
       {
       {
         CPT(TransformState) render_transform =
         CPT(TransformState) render_transform =
           _cs_transform->compose(_scene_setup->get_world_transform());
           _cs_transform->compose(_scene_setup->get_world_transform());
-        CPT(TransformState) world_inv_transform = 
+        CPT(TransformState) world_inv_transform =
           render_transform->invert_compose(_internal_transform);
           render_transform->invert_compose(_internal_transform);
         tcdata[si]._mat = world_inv_transform->get_mat();
         tcdata[si]._mat = world_inv_transform->get_mat();
       }
       }
@@ -709,7 +710,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     needs_normal = rnormal.has_column();
     needs_normal = rnormal.has_column();
   }
   }
 
 
-  GeomVertexReader rvertex(data_reader, InternalName::get_vertex(), force); 
+  GeomVertexReader rvertex(data_reader, InternalName::get_vertex(), force);
   rvertex.set_row_unsafe(_min_vertex);
   rvertex.set_row_unsafe(_min_vertex);
 
 
   if (!rvertex.has_column()) {
   if (!rvertex.has_column()) {
@@ -1717,10 +1718,11 @@ update_texture(TextureContext *tc, bool force) {
 
 
   if (gtc->was_image_modified() || gltex->num_levels == 0) {
   if (gtc->was_image_modified() || gltex->num_levels == 0) {
     // If the texture image was modified, reload the texture.
     // If the texture image was modified, reload the texture.
-    bool okflag = upload_texture(gtc, force);
+    Texture *tex = gtc->get_texture();
+    bool okflag = upload_texture(gtc, force, tex->uses_mipmaps());
     if (!okflag) {
     if (!okflag) {
       tinydisplay_cat.error()
       tinydisplay_cat.error()
-        << "Could not load " << *gtc->get_texture() << "\n";
+        << "Could not load " << *tex << "\n";
       return false;
       return false;
     }
     }
   }
   }
@@ -1746,7 +1748,7 @@ update_texture(TextureContext *tc, bool force) {
 //               true).
 //               true).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool TinyGraphicsStateGuardian::
 bool TinyGraphicsStateGuardian::
-update_texture(TextureContext *tc, bool force, int stage_index) {
+update_texture(TextureContext *tc, bool force, int stage_index, bool uses_mipmaps) {
   if (!update_texture(tc, force)) {
   if (!update_texture(tc, force)) {
     return false;
     return false;
   }
   }
@@ -1754,6 +1756,17 @@ update_texture(TextureContext *tc, bool force, int stage_index) {
   TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
   TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
   GLTexture *gltex = &gtc->_gltex;
   GLTexture *gltex = &gtc->_gltex;
 
 
+  if (uses_mipmaps && gltex->num_levels <= 1) {
+    // We don't have mipmaps, yet we are sampling with mipmaps.
+    Texture *tex = gtc->get_texture();
+    bool okflag = upload_texture(gtc, force, true);
+    if (!okflag) {
+      tinydisplay_cat.error()
+        << "Could not load " << *tex << "\n";
+      return false;
+    }
+  }
+
   _c->current_textures[stage_index] = gltex;
   _c->current_textures[stage_index] = gltex;
 
 
   ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
   ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
@@ -1762,13 +1775,13 @@ update_texture(TextureContext *tc, bool force, int stage_index) {
   texture_def->t_max = gltex->t_max;
   texture_def->t_max = gltex->t_max;
 
 
   const V4 &bc = gltex->border_color;
   const V4 &bc = gltex->border_color;
-  int r = (int)(bc.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) 
+  int r = (int)(bc.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN)
                 + ZB_POINT_RED_MIN);
                 + ZB_POINT_RED_MIN);
-  int g = (int)(bc.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) 
+  int g = (int)(bc.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN)
                 + ZB_POINT_GREEN_MIN);
                 + ZB_POINT_GREEN_MIN);
-  int b = (int)(bc.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) 
+  int b = (int)(bc.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN)
                 + ZB_POINT_BLUE_MIN);
                 + ZB_POINT_BLUE_MIN);
-  int a = (int)(bc.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN) 
+  int a = (int)(bc.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN)
                 + ZB_POINT_ALPHA_MIN);
                 + ZB_POINT_ALPHA_MIN);
   texture_def->border_color = RGBA_TO_PIXEL(r, g, b, a);
   texture_def->border_color = RGBA_TO_PIXEL(r, g, b, a);
 
 
@@ -1809,7 +1822,7 @@ release_texture(TextureContext *tc) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TinyGraphicsStateGuardian::do_issue_light
 //     Function: TinyGraphicsStateGuardian::do_issue_light
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyGraphicsStateGuardian::
 void TinyGraphicsStateGuardian::
 do_issue_light() {
 do_issue_light() {
@@ -2016,7 +2029,7 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
     gl_light->specular.v[1] = specular[1];
     gl_light->specular.v[1] = specular[1];
     gl_light->specular.v[2] = specular[2];
     gl_light->specular.v[2] = specular[2];
     gl_light->specular.v[3] = specular[3];
     gl_light->specular.v[3] = specular[3];
-  
+
     Lens *lens = light_obj->get_lens();
     Lens *lens = light_obj->get_lens();
     nassertv(lens != (Lens *)NULL);
     nassertv(lens != (Lens *)NULL);
 
 
@@ -2267,16 +2280,19 @@ do_issue_texture() {
     TextureStage *stage = _target_texture->get_on_ff_stage(si);
     TextureStage *stage = _target_texture->get_on_ff_stage(si);
     Texture *texture = _target_texture->get_on_texture(stage);
     Texture *texture = _target_texture->get_on_texture(stage);
     nassertv(texture != (Texture *)NULL);
     nassertv(texture != (Texture *)NULL);
-    
+
     int view = get_current_tex_view_offset() + stage->get_tex_view_offset();
     int view = get_current_tex_view_offset() + stage->get_tex_view_offset();
     TextureContext *tc = texture->prepare_now(view, _prepared_objects, this);
     TextureContext *tc = texture->prepare_now(view, _prepared_objects, this);
     if (tc == (TextureContext *)NULL) {
     if (tc == (TextureContext *)NULL) {
       // Something wrong with this texture; skip it.
       // Something wrong with this texture; skip it.
       return;
       return;
     }
     }
-    
+
+    // Get the sampler state that we are supposed to use.
+    const SamplerState &sampler = _target_texture->get_on_sampler(stage);
+
     // Then, turn on the current texture mode.
     // Then, turn on the current texture mode.
-    if (!update_texture(tc, false, si)) {
+    if (!update_texture(tc, false, si, sampler.uses_mipmaps())) {
       return;
       return;
     }
     }
 
 
@@ -2297,13 +2313,13 @@ do_issue_texture() {
     best_quality_level = max(best_quality_level, quality_level);
     best_quality_level = max(best_quality_level, quality_level);
 
 
     ZTextureDef *texture_def = &_c->zb->current_textures[si];
     ZTextureDef *texture_def = &_c->zb->current_textures[si];
-    
+
     // Fill in the filter func pointers.  These may not actually get
     // Fill in the filter func pointers.  These may not actually get
     // called, if we decide below we can inline the filters.
     // called, if we decide below we can inline the filters.
-    SamplerState::FilterType minfilter = texture->get_minfilter();
-    SamplerState::FilterType magfilter = texture->get_magfilter();
+    SamplerState::FilterType minfilter = sampler.get_minfilter();
+    SamplerState::FilterType magfilter = sampler.get_magfilter();
 
 
-    if (td_ignore_mipmaps && Texture::is_mipmap(minfilter)) {
+    if (td_ignore_mipmaps && SamplerState::is_mipmap(minfilter)) {
       // Downgrade mipmaps.
       // Downgrade mipmaps.
       if (minfilter == SamplerState::FT_nearest_mipmap_nearest) {
       if (minfilter == SamplerState::FT_nearest_mipmap_nearest) {
         minfilter = SamplerState::FT_nearest;
         minfilter = SamplerState::FT_nearest;
@@ -2319,7 +2335,7 @@ do_issue_texture() {
       magfilter = SamplerState::FT_nearest;
       magfilter = SamplerState::FT_nearest;
 
 
     } else if (quality_level == Texture::QL_normal) {
     } else if (quality_level == Texture::QL_normal) {
-      if (Texture::is_mipmap(minfilter)) {
+      if (SamplerState::is_mipmap(minfilter)) {
         minfilter = SamplerState::FT_nearest_mipmap_nearest;
         minfilter = SamplerState::FT_nearest_mipmap_nearest;
       } else {
       } else {
         minfilter = SamplerState::FT_nearest;
         minfilter = SamplerState::FT_nearest;
@@ -2327,15 +2343,15 @@ do_issue_texture() {
       magfilter = SamplerState::FT_nearest;
       magfilter = SamplerState::FT_nearest;
 
 
     } else if (quality_level == Texture::QL_best) {
     } else if (quality_level == Texture::QL_best) {
-      minfilter = texture->get_effective_minfilter();
-      magfilter = texture->get_effective_magfilter();
+      minfilter = sampler.get_effective_minfilter();
+      magfilter = sampler.get_effective_magfilter();
     }
     }
 
 
     texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
     texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
     texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
     texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
-    
-    SamplerState::WrapMode wrap_u = texture->get_wrap_u();
-    SamplerState::WrapMode wrap_v = texture->get_wrap_v();
+
+    SamplerState::WrapMode wrap_u = sampler.get_wrap_u();
+    SamplerState::WrapMode wrap_v = sampler.get_wrap_v();
     if (td_ignore_clamp) {
     if (td_ignore_clamp) {
       wrap_u = SamplerState::WM_repeat;
       wrap_u = SamplerState::WM_repeat;
       wrap_v = SamplerState::WM_repeat;
       wrap_v = SamplerState::WM_repeat;
@@ -2382,7 +2398,7 @@ do_issue_texture() {
       all_mipmap_nearest = false;
       all_mipmap_nearest = false;
     }
     }
 
 
-    if (Texture::is_mipmap(minfilter)) {
+    if (SamplerState::is_mipmap(minfilter)) {
       any_mipmap = true;
       any_mipmap = true;
     }
     }
   }
   }
@@ -2419,7 +2435,7 @@ do_issue_texture() {
     // perspective correctness.
     // perspective correctness.
     _texfilter_state = 0;    // tnearest
     _texfilter_state = 0;    // tnearest
     _texturing_state = 1;    // textured (not perspective correct, no multitexture)
     _texturing_state = 1;    // textured (not perspective correct, no multitexture)
-  
+
   } else {
   } else {
     // This is the default texture filter.  We use nearest sampling if
     // This is the default texture filter.  We use nearest sampling if
     // there are no mipmaps, and mipmap_nearest if there are any
     // there are no mipmaps, and mipmap_nearest if there are any
@@ -2500,7 +2516,7 @@ apply_texture(TextureContext *tc) {
 //               the texture has no image.
 //               the texture has no image.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool TinyGraphicsStateGuardian::
 bool TinyGraphicsStateGuardian::
-upload_texture(TinyTextureContext *gtc, bool force) {
+upload_texture(TinyTextureContext *gtc, bool force, bool uses_mipmaps) {
   Texture *tex = gtc->get_texture();
   Texture *tex = gtc->get_texture();
 
 
   if (_effective_incomplete_render && !force) {
   if (_effective_incomplete_render && !force) {
@@ -2525,21 +2541,24 @@ upload_texture(TinyTextureContext *gtc, bool force) {
     return false;
     return false;
   }
   }
 
 
-  if (tinydisplay_cat.is_debug()) {
-    tinydisplay_cat.debug()
-      << "loading texture " << tex->get_name() << "\n";
-  }
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   _data_transferred_pcollector.add_level(tex->get_ram_image_size());
   _data_transferred_pcollector.add_level(tex->get_ram_image_size());
 #endif
 #endif
   GLTexture *gltex = &gtc->_gltex;
   GLTexture *gltex = &gtc->_gltex;
 
 
   int num_levels = 1;
   int num_levels = 1;
-  if (tex->uses_mipmaps()) {
-    if (!tex->has_all_ram_mipmap_images()) {
+  if (uses_mipmaps) {
+    num_levels = tex->get_expected_num_mipmap_levels();
+    if (tex->get_num_ram_mipmap_images() < num_levels) {
       tex->generate_ram_mipmap_images();
       tex->generate_ram_mipmap_images();
     }
     }
-    num_levels = tex->get_num_ram_mipmap_images();
+  }
+
+  if (tinydisplay_cat.is_debug()) {
+    tinydisplay_cat.debug()
+      << "loading texture " << tex->get_name() << ", "
+      << tex->get_x_size() << " x " << tex->get_y_size() << ", mipmaps = "
+      << num_levels << ", uses_mipmaps = " << uses_mipmaps << "\n";
   }
   }
 
 
   if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), num_levels)) {
   if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), num_levels)) {
@@ -2616,7 +2635,7 @@ upload_texture(TinyTextureContext *gtc, bool force) {
   }
   }
 
 
   gtc->update_data_size_bytes(bytecount);
   gtc->update_data_size_bytes(bytecount);
-  
+
   get_engine()->texture_uploaded(tex);
   get_engine()->texture_uploaded(tex);
   gtc->mark_loaded();
   gtc->mark_loaded();
 
 
@@ -2687,7 +2706,7 @@ bool TinyGraphicsStateGuardian::
 setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
 setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
   int s_bits = get_tex_shift(x_size);
   int s_bits = get_tex_shift(x_size);
   int t_bits = get_tex_shift(y_size);
   int t_bits = get_tex_shift(y_size);
-  
+
   if (s_bits < 0 || t_bits < 0) {
   if (s_bits < 0 || t_bits < 0) {
     return false;
     return false;
   }
   }
@@ -2701,7 +2720,7 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
   gltex->t_max = 1 << (t_bits + ZB_POINT_ST_FRAC_BITS);
   gltex->t_max = 1 << (t_bits + ZB_POINT_ST_FRAC_BITS);
 
 
   gltex->num_levels = num_levels;
   gltex->num_levels = num_levels;
-  
+
   // We allocate one big buffer, large enough to include all the
   // We allocate one big buffer, large enough to include all the
   // mipmap levels, and index into that buffer for each level.  This
   // mipmap levels, and index into that buffer for each level.  This
   // cuts down on the number of individual alloc calls we have to make
   // cuts down on the number of individual alloc calls we have to make
@@ -2746,7 +2765,7 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
     dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
     dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
     dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
     dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
     dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
     dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
-    
+
     x_size = max((x_size >> 1), 1);
     x_size = max((x_size >> 1), 1);
     y_size = max((y_size >> 1), 1);
     y_size = max((y_size >> 1), 1);
     s_bits = max(s_bits - 1, 0);
     s_bits = max(s_bits - 1, 0);
@@ -3187,7 +3206,7 @@ get_color_blend_op(ColorBlendAttrib::Operand operand) {
   }
   }
   return 0;
   return 0;
 }
 }
- 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TinyGraphicsStateGuardian::get_tex_filter_func
 //     Function: TinyGraphicsStateGuardian::get_tex_filter_func
 //       Access: Private, Static
 //       Access: Private, Static
@@ -3208,7 +3227,7 @@ get_tex_filter_func(SamplerState::FilterType filter) {
 
 
   case SamplerState::FT_nearest_mipmap_linear:
   case SamplerState::FT_nearest_mipmap_linear:
     return &lookup_texture_mipmap_linear;
     return &lookup_texture_mipmap_linear;
-      
+
   case SamplerState::FT_linear_mipmap_nearest:
   case SamplerState::FT_linear_mipmap_nearest:
     return &lookup_texture_mipmap_bilinear;
     return &lookup_texture_mipmap_bilinear;
 
 
@@ -3219,7 +3238,7 @@ get_tex_filter_func(SamplerState::FilterType filter) {
     return &lookup_texture_nearest;
     return &lookup_texture_nearest;
   }
   }
 }
 }
- 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TinyGraphicsStateGuardian::get_tex_wrap_func
 //     Function: TinyGraphicsStateGuardian::get_tex_wrap_func
 //       Access: Private, Static
 //       Access: Private, Static
@@ -3305,7 +3324,7 @@ texgen_sphere_map(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
 
 
   // Compute the reflection vector.
   // Compute the reflection vector.
   LVector3 r = u - n * dot(n, u) * 2.0f;
   LVector3 r = u - n * dot(n, u) * 2.0f;
-  
+
   // compute the denominator, m.
   // compute the denominator, m.
   PN_stdfloat m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
   PN_stdfloat m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
 
 

+ 2 - 2
panda/src/tinydisplay/tinyGraphicsStateGuardian.h

@@ -91,7 +91,7 @@ public:
 
 
   virtual TextureContext *prepare_texture(Texture *tex, int view);
   virtual TextureContext *prepare_texture(Texture *tex, int view);
   virtual bool update_texture(TextureContext *tc, bool force);
   virtual bool update_texture(TextureContext *tc, bool force);
-  bool update_texture(TextureContext *tc, bool force, int stage_index);
+  bool update_texture(TextureContext *tc, bool force, int stage_index, bool uses_mipmaps);
   virtual void release_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
 
   virtual void do_issue_light();
   virtual void do_issue_light();
@@ -115,7 +115,7 @@ private:
   void set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top);
   void set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top);
 
 
   bool apply_texture(TextureContext *tc);
   bool apply_texture(TextureContext *tc);
-  bool upload_texture(TinyTextureContext *gtc, bool force);
+  bool upload_texture(TinyTextureContext *gtc, bool force, bool uses_mipmaps);
   bool upload_simple_texture(TinyTextureContext *gtc);
   bool upload_simple_texture(TinyTextureContext *gtc);
   bool setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels);
   bool setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels);
   int get_tex_shift(int orig_size);
   int get_tex_shift(int orig_size);