Browse Source

async texture loading support for dx8,9

David Rose 17 years ago
parent
commit
93cef9c3bf

+ 41 - 19
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -160,7 +160,9 @@ prepare_texture(Texture *tex) {
     return NULL;
   }
 
-  if (!dtc->create_texture(*_screen)) {
+  if (!upload_texture(dtc)) {
+    dxgsg8_cat.error()
+      << "Unable to create texture " << *tex << endl;
     delete dtc;
     return NULL;
   }
@@ -186,28 +188,21 @@ apply_texture(int i, TextureContext *tc) {
   tc->set_active(true);
 
   DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
+  Texture *tex = tc->get_texture();
 
   // If the texture image has changed, or if its use of mipmaps has
   // changed, we need to re-create the image.
 
   if (dtc->was_modified()) {
-    if (!get_supports_compressed_texture_format(tc->get_texture()->get_ram_image_compression())) {
-      dxgsg8_cat.error()
-        << *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
-      _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
-      return;
-    }
-
-    if (!dtc->create_texture(*_screen)) {
+    if (!upload_texture(dtc)) {
       // Oops, we can't re-create the texture for some reason.
       dxgsg8_cat.error()
-        << "Unable to re-create texture " << *dtc->get_texture() << endl;
-      _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
+        << "Unable to re-create texture " << *tex << endl;
+        _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
       return;
     }
   }
 
-  Texture *tex = tc->get_texture();
   Texture::WrapMode wrap_u, wrap_v, wrap_w;
   wrap_u = tex->get_wrap_u();
   wrap_v = tex->get_wrap_v();
@@ -249,16 +244,10 @@ apply_texture(int i, TextureContext *tc) {
     new_mip_filter = D3DTEXF_NONE;
   }
 
-#ifndef NDEBUG
   // sanity check
-  if ((!dtc->has_mipmaps()) && (new_mip_filter != D3DTEXF_NONE)) {
-    dxgsg8_cat.error()
-      << "Trying to set mipmap filtering for texture with no generated mipmaps!! texname["
-      << tex->get_name() << "], filter("
-      << tex->get_minfilter() << ")\n";
+  if (!dtc->has_mipmaps()) {
     new_mip_filter = D3DTEXF_NONE;
   }
-#endif
 
   if (aniso_degree >= 2) {
     new_min_filter = D3DTEXF_ANISOTROPIC;
@@ -270,6 +259,39 @@ apply_texture(int i, TextureContext *tc) {
   _d3d_device->SetTexture(i, dtc->get_d3d_texture());
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian8::upload_texture
+//       Access: Public
+//  Description: Creates a texture surface on the graphics card and
+//               fills it with its pixel data.
+////////////////////////////////////////////////////////////////////
+bool DXGraphicsStateGuardian8::
+upload_texture(DXTextureContext8 *dtc) {
+  Texture *tex = dtc->get_texture();
+  if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
+    dxgsg8_cat.error()
+      << *tex << " is stored in an unsupported compressed format.\n";
+    return false;
+  }
+
+  if (_incomplete_render && 
+      !tex->has_ram_image() && tex->might_have_ram_image() &&
+      tex->has_simple_ram_image() &&
+      !_loader.is_null()) {
+    // If we don't have the texture data right now, go get it, but in
+    // the meantime load a temporary simple image in its place.
+    async_reload_texture(dtc);
+    if (!tex->has_ram_image()) {
+      if (dtc->was_simple_image_modified()) {
+        return dtc->create_simple_texture(*_screen);
+      }
+      return true;
+    }
+  }
+  
+  return dtc->create_texture(*_screen);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian8::release_texture
 //       Access: Public, Virtual

+ 2 - 0
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -31,6 +31,7 @@
 
 class Light;
 
+class DXTextureContext8;
 class DXVertexBufferContext8;
 class DXIndexBufferContext8;
 
@@ -49,6 +50,7 @@ public:
 
   virtual TextureContext *prepare_texture(Texture *tex);
   void apply_texture(int i, TextureContext *tc);
+  bool upload_texture(DXTextureContext8 *dtc);
   virtual void release_texture(TextureContext *tc);
 
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);

+ 89 - 0
panda/src/dxgsg8/dxTextureContext8.cxx

@@ -722,6 +722,95 @@ create_texture(DXScreenData &scrn) {
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXTextureContext8::create_simple_texture
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool DXTextureContext8::
+create_simple_texture(DXScreenData &scrn) {
+  nassertr(IS_VALID_PTR(get_texture()), false);
+
+  HRESULT hr;
+
+  delete_texture();
+
+  _d3d_format = D3DFMT_A8R8G8B8;
+  D3DFORMAT target_pixel_format = D3DFMT_A8R8G8B8;
+  DWORD target_bpp = 32;
+  DWORD num_color_channels = 4;
+
+  DWORD target_width = (DWORD)get_texture()->get_simple_x_size();
+  DWORD target_height = (DWORD)get_texture()->get_simple_y_size();
+  DWORD mip_level_count = 1;
+  DWORD usage = 0;
+  D3DPOOL pool = D3DPOOL_MANAGED;
+
+  int data_size = target_width * target_height * 4;
+
+  hr = scrn._d3d_device->CreateTexture
+    (target_width, target_height, mip_level_count, usage,
+     target_pixel_format, pool, &_d3d_2d_texture);
+  _d3d_texture = _d3d_2d_texture;      
+  if (FAILED(hr)) {
+    dxgsg8_cat.error()
+      << "D3D create_simple_texture failed!" << D3DERRORSTRING(hr);
+    dxgsg8_cat.error()
+      << "  width = " << target_width << " height = " << target_height << " target_pixel_format = " << target_pixel_format << "\n";
+
+    goto error_exit;
+  }
+
+  if (dxgsg8_cat.is_debug()) {
+    dxgsg8_cat.debug()
+      << "create_simple_texture: " << get_texture()->get_name()
+      << "\n";
+  }
+
+  {
+    CPTA_uchar image = get_texture()->get_simple_ram_image();
+
+    hr = -1;
+    //  hr = fill_d3d_texture_pixels(scrn._supports_automatic_mipmap_generation, scrn._d3d_device);
+
+    IDirect3DSurface8 *surface = NULL;
+    _d3d_2d_texture->GetSurfaceLevel(0, &surface);
+
+    RECT source_size;
+    source_size.left = source_size.top = 0;
+    source_size.right = target_width;
+    source_size.bottom = target_height;
+
+    DWORD mip_filter = D3DX_FILTER_LINEAR;
+
+    hr = D3DXLoadSurfaceFromMemory
+      (surface, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)image.p(),
+       target_pixel_format, target_width * 4, (PALETTEENTRY*)NULL,
+       &source_size, mip_filter, (D3DCOLOR)0x0);
+
+    RELEASE(surface, dxgsg8, "create_simple_texture Surface", RELEASE_ONCE);
+  }
+    
+  if (FAILED(hr)) {
+    dxgsg8_cat.debug ()
+      << "*** fill_d3d_texture_pixels failed ***: format "
+      << target_pixel_format
+      << "\n";
+    
+    goto error_exit;
+  }
+
+  mark_simple_loaded();
+  return true;
+
+ error_exit:
+  RELEASE(_d3d_texture, dxgsg8, "texture", RELEASE_ONCE);
+  _d3d_2d_texture = NULL;
+  _d3d_volume_texture = NULL;
+  _d3d_cube_texture = NULL;
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXTextureContext8::delete_texture
 //       Access: Public

+ 1 - 0
panda/src/dxgsg8/dxTextureContext8.h

@@ -29,6 +29,7 @@ public:
   virtual ~DXTextureContext8();
 
   bool create_texture(DXScreenData &scrn);
+  bool create_simple_texture(DXScreenData &scrn);
   void delete_texture();
 
   INLINE bool has_mipmaps() const;

+ 40 - 18
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -207,7 +207,9 @@ prepare_texture(Texture *tex) {
     return NULL;
   }
 
-  if (!dtc->create_texture(*_screen)) {
+  if (!upload_texture(dtc)) {
+    dxgsg9_cat.error()
+      << "Unable to create texture " << *tex << endl;
     delete dtc;
     return NULL;
   }
@@ -237,28 +239,21 @@ apply_texture(int i, TextureContext *tc) {
   if (_lru) {
     _lru -> access_page (dtc -> _lru_page);
   }
+  Texture *tex = tc->get_texture();
 
   // If the texture image has changed, or if its use of mipmaps has
   // changed, we need to re-create the image.
 
   if (dtc->was_modified()) {
-    if (!get_supports_compressed_texture_format(tc->get_texture()->get_ram_image_compression())) {
-      dxgsg9_cat.error()
-        << *dtc->get_texture() << " is stored in an unsupported compressed format.\n";
-      set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
-      return;
-    }
-
-    if (!dtc->create_texture(*_screen)) {
+    if (!upload_texture(dtc)) {
       // Oops, we can't re-create the texture for some reason.
       dxgsg9_cat.error()
-        << "Unable to re-create texture " << *dtc->get_texture() << endl;
+        << "Unable to re-create texture " << *tex << endl;
       set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
       return;
     }
   }
 
-  Texture *tex = tc->get_texture();
   Texture::WrapMode wrap_u, wrap_v, wrap_w;
 
   DWORD address_u;
@@ -311,16 +306,10 @@ apply_texture(int i, TextureContext *tc) {
     new_mip_filter = D3DTEXF_NONE;
   }
 
-#ifndef NDEBUG
   // sanity check
-  if ((!dtc->has_mipmaps()) && (new_mip_filter != D3DTEXF_NONE)) {
-    dxgsg9_cat.error()
-      << "Trying to set mipmap filtering for texture with no generated mipmaps!! texname["
-      << tex->get_name() << "], filter("
-      << tex->get_minfilter() << ")\n";
+  if (!dtc->has_mipmaps()) {
     new_mip_filter = D3DTEXF_NONE;
   }
-#endif
 
   if (aniso_degree >= 2) {
     new_min_filter = D3DTEXF_ANISOTROPIC;
@@ -332,6 +321,39 @@ apply_texture(int i, TextureContext *tc) {
   _d3d_device->SetTexture(i, dtc->get_d3d_texture());
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian9::upload_texture
+//       Access: Public
+//  Description: Creates a texture surface on the graphics card and
+//               fills it with its pixel data.
+////////////////////////////////////////////////////////////////////
+bool DXGraphicsStateGuardian9::
+upload_texture(DXTextureContext9 *dtc) {
+  Texture *tex = dtc->get_texture();
+  if (!get_supports_compressed_texture_format(tex->get_ram_image_compression())) {
+    dxgsg9_cat.error()
+      << *tex << " is stored in an unsupported compressed format.\n";
+    return false;
+  }
+
+  if (_incomplete_render && 
+      !tex->has_ram_image() && tex->might_have_ram_image() &&
+      tex->has_simple_ram_image() &&
+      !_loader.is_null()) {
+    // If we don't have the texture data right now, go get it, but in
+    // the meantime load a temporary simple image in its place.
+    async_reload_texture(dtc);
+    if (!tex->has_ram_image()) {
+      if (dtc->was_simple_image_modified()) {
+        return dtc->create_simple_texture(*_screen);
+      }
+      return true;
+    }
+  }
+  
+  return dtc->create_texture(*_screen);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian9::release_texture
 //       Access: Public, Virtual

+ 2 - 0
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -64,6 +64,7 @@ enum GsgPageType
 
 class Light;
 
+class DXTextureContext9;
 class DXVertexBufferContext9;
 class DXIndexBufferContext9;
 
@@ -83,6 +84,7 @@ public:
 
   virtual TextureContext *prepare_texture(Texture *tex);
   void apply_texture(int i, TextureContext *tc);
+  bool upload_texture(DXTextureContext9 *dtc);
   virtual void release_texture(TextureContext *tc);
 
   ShaderContext *prepare_shader(Shader *se);

+ 89 - 1
panda/src/dxgsg9/dxTextureContext9.cxx

@@ -88,7 +88,6 @@ create_texture(DXScreenData &scrn) {
   nassertr(IS_VALID_PTR(get_texture()), false);
 
   delete_texture();
-  mark_loaded();
 
   // bpp indicates requested fmt, not texture fmt
   DWORD target_bpp = get_bits_per_pixel(get_texture()->get_format(), &num_alpha_bits);
@@ -968,6 +967,95 @@ create_texture(DXScreenData &scrn) {
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXTextureContext9::create_simple_texture
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool DXTextureContext9::
+create_simple_texture(DXScreenData &scrn) {
+  nassertr(IS_VALID_PTR(get_texture()), false);
+
+  HRESULT hr;
+
+  delete_texture();
+
+  _d3d_format = D3DFMT_A8R8G8B8;
+  D3DFORMAT target_pixel_format = D3DFMT_A8R8G8B8;
+  DWORD target_bpp = 32;
+  DWORD num_color_channels = 4;
+
+  DWORD target_width = (DWORD)get_texture()->get_simple_x_size();
+  DWORD target_height = (DWORD)get_texture()->get_simple_y_size();
+  DWORD mip_level_count = 1;
+  DWORD usage = 0;
+  D3DPOOL pool = D3DPOOL_MANAGED;
+
+  int data_size = target_width * target_height * 4;
+
+  hr = scrn._d3d_device->CreateTexture
+    (target_width, target_height, mip_level_count, usage,
+     target_pixel_format, pool, &_d3d_2d_texture, NULL);
+  _d3d_texture = _d3d_2d_texture;      
+  if (FAILED(hr)) {
+    dxgsg9_cat.error()
+      << "D3D create_simple_texture failed!" << D3DERRORSTRING(hr);
+    dxgsg9_cat.error()
+      << "  width = " << target_width << " height = " << target_height << " target_pixel_format = " << target_pixel_format << "\n";
+
+    goto error_exit;
+  }
+
+  if (DEBUG_TEXTURES && dxgsg9_cat.is_debug()) {
+    dxgsg9_cat.debug()
+      << "create_simple_texture: " << get_texture()->get_name()
+      << "\n";
+  }
+
+  {
+    CPTA_uchar image = get_texture()->get_simple_ram_image();
+
+    hr = -1;
+    //  hr = fill_d3d_texture_pixels(scrn._supports_automatic_mipmap_generation, scrn._d3d_device);
+
+    IDirect3DSurface9 *surface = NULL;
+    _d3d_2d_texture->GetSurfaceLevel(0, &surface);
+
+    RECT source_size;
+    source_size.left = source_size.top = 0;
+    source_size.right = target_width;
+    source_size.bottom = target_height;
+
+    DWORD mip_filter = D3DX_FILTER_LINEAR;
+
+    hr = D3DXLoadSurfaceFromMemory
+      (surface, (PALETTEENTRY*)NULL, (RECT*)NULL, (LPCVOID)image.p(),
+       target_pixel_format, target_width * 4, (PALETTEENTRY*)NULL,
+       &source_size, mip_filter, (D3DCOLOR)0x0);
+
+    RELEASE(surface, dxgsg9, "create_simple_texture Surface", RELEASE_ONCE);
+  }
+    
+  if (FAILED(hr)) {
+    dxgsg9_cat.debug ()
+      << "*** fill_d3d_texture_pixels failed ***: format "
+      << target_pixel_format
+      << "\n";
+    
+    goto error_exit;
+  }
+
+  mark_simple_loaded();
+  return true;
+
+ error_exit:
+  RELEASE(_d3d_texture, dxgsg9, "texture", RELEASE_ONCE);
+  _d3d_2d_texture = NULL;
+  _d3d_volume_texture = NULL;
+  _d3d_cube_texture = NULL;
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXTextureContext9::delete_texture
 //       Access: Public

+ 1 - 0
panda/src/dxgsg9/dxTextureContext9.h

@@ -31,6 +31,7 @@ public:
   virtual ~DXTextureContext9();
 
   bool create_texture(DXScreenData &scrn);
+  bool create_simple_texture(DXScreenData &scrn);
   void delete_texture();
 
   INLINE bool has_mipmaps() const;