Просмотр исходного кода

make multipass work (sort of) on dx8

David Rose 22 лет назад
Родитель
Сommit
0e084fe310

+ 1 - 2
panda/src/display/graphicsOutput.cxx

@@ -566,8 +566,7 @@ end_frame() {
     nassertv(has_texture());
     DisplayRegion dr(this, _x_size, _y_size);
     RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
-    TextureContext *tc = get_texture()->prepare_now(_gsg->get_prepared_objects(), _gsg);
-    _gsg->copy_texture(tc, &dr, buffer);
+    _gsg->copy_texture(get_texture(), &dr, buffer);
   }
 
   // If we're not single-buffered, we're now ready to flip.

+ 4 - 0
panda/src/distort/projectionScreen.cxx

@@ -677,6 +677,10 @@ make_mesh_geom(Geom *geom, Lens *lens, LMatrix4f &rel_mat) {
     // dimensions so the Z coordinate remains meaningful.
     LPoint3f film(0.0f, 0.0f, 0.0f);
     lens->project(vert * rel_mat, film);
+    
+    // This might be necessary to compensate for DX's weird near plane
+    // definition.  Investigate further later.
+    //film[2] = ((film[2] + 1.0f) / 2.0f);
 
     new_coords.push_back(film);
   }

+ 4 - 66
panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx

@@ -3490,81 +3490,19 @@ release_texture(TextureContext *tc) {
     delete gtc;
 }
 
-#if 1
-
 void DXGraphicsStateGuardian7::
-copy_texture(TextureContext *tc, const DisplayRegion *dr) {
-    dxgsg7_cat.fatal() << "DX copy_texture unimplemented!!!";
-}
-
-#else
-static int logs[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
-    4096, 0};
-
-// This function returns the smallest power of two greater than or
-// equal to x.
-static int binary_log_cap(const int x) {
-    int i = 0;
-    for (; (x > logs[i]) && (logs[i] != 0); ++i);
-    if (logs[i] == 0)
-        return 4096;
-    return logs[i];
+copy_texture(Texture *tex, const DisplayRegion *dr) {
+    dxgsg7_cat.error() << "DX copy_texture unimplemented!!!";
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DXGraphicsStateGuardian7::copy_texture
-//       Access: Public, Virtual
-//  Description: Copy the pixel region indicated by the display
-//       region from the framebuffer into texture memory
-////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian7::
-copy_texture(TextureContext *tc, const DisplayRegion *dr) {
-
-    nassertv(tc != NULL && dr != NULL);
-
-    Texture *tex = tc->_texture;
-
-    // Determine the size of the grab from the given display region
-    // If the requested region is not a power of two, grab a region that is
-    // a power of two that contains the requested region
-    int xo, yo, req_w, req_h;
-    dr->get_region_pixels(xo, yo, req_w, req_h);
-    int w = binary_log_cap(req_w);
-    int h = binary_log_cap(req_h);
-    if (w != req_w || h != req_h) {
-        tex->_requested_w = req_w;
-        tex->_requested_h = req_h;
-        tex->_has_requested_size = true;
-    }
-
-    PixelBuffer *pb = tex->_pbuffer;
-
-    pb->set_xorg(xo);
-    pb->set_yorg(yo);
-    pb->set_xsize(w);
-    pb->set_ysize(h);
-
-
-    bind_texture(tc);
-    glCopyTexImage2D( GL_TEXTURE_2D, tex->get_level(),
-                      get_internal_image_format(pb->get_format()),
-                      pb->get_xorg(), pb->get_yorg(),
-                      pb->get_xsize(), pb->get_ysize(), pb->get_border() );
-}
-#endif
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian7::copy_texture
 //       Access: Public, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian7::
-copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb) {
-    dxgsg7_cat.fatal() << "DX copy_texture unimplemented!!!";
-    return;
-
-    set_read_buffer(rb);
-    copy_texture(tc, dr);
+copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) {
+    dxgsg7_cat.error() << "DX copy_texture unimplemented!!!";
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/dxgsg7/dxGraphicsStateGuardian7.h

@@ -98,8 +98,8 @@ public:
   virtual void apply_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr);
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr,
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr);
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr,
                             const RenderBuffer &rb);
 
   virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb);

+ 52 - 43
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -29,6 +29,7 @@
 #include "graphicsChannel.h"
 #include "lens.h"
 #include "perspectiveLens.h"
+#include "orthographicLens.h"
 #include "ambientLight.h"
 #include "directionalLight.h"
 #include "pointLight.h"
@@ -1040,17 +1041,17 @@ prepare_lens() {
     LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
     projection_mat;
   
-  float vfov = _current_lens->get_vfov();
   float nearf = _current_lens->get_near();
   float farf = _current_lens->get_far();
 
   //dxgsg8_cat.debug() << new_projection_mat << endl;
   
   HRESULT hr;
-  if (_current_lens->get_type().get_name() == "PerspectiveLens") {
-#if 0
+  if (false && _current_lens->is_of_type(PerspectiveLens::get_class_type())) {
+    /*
     const LMatrix4f mat_temp;
 
+    float vfov = _current_lens->get_vfov();
     float hfov = _current_lens->get_hfov();
     float ar = _current_lens->get_aspect_ratio();
     float nearf = _current_lens->get_near();
@@ -1063,25 +1064,32 @@ prepare_lens() {
     hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
                                    (D3DMATRIX*)mat_temp.get_data());
     dxgsg8_cat.debug() << mat_temp << endl;
-#endif
-    
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_33 = farf / (farf-nearf);
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_43 = -nearf * farf / (farf - nearf);
+    */
+
+    new_projection_mat(2, 2) = farf / (farf-nearf);
+    new_projection_mat(3, 2) = -nearf * farf / (farf - nearf);
 
     hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
                                    (D3DMATRIX*)new_projection_mat.get_data());
     //dxgsg8_cat.debug() << new_projection_mat << endl;
     //dxgsg8_cat.debug() << "using perspective projection" << endl;
-  }
-  else {
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_33 = 1/(farf-nearf);
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_43 = -nearf/(farf-nearf);
+
+  } else if (false && _current_lens->is_of_type(OrthographicLens::get_class_type())) {
+    new_projection_mat(2, 2) = 1 / (farf - nearf);
+    new_projection_mat(3, 2) = -nearf / (farf - nearf);
     
     hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
                                    (D3DMATRIX*)new_projection_mat.get_data());
     //dxgsg8_cat.debug() << new_projection_mat << endl;
     //dxgsg8_cat.debug() << "using ortho projection" << endl;
+
+  } else {
+    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
+                                   (D3DMATRIX*)new_projection_mat.get_data());
+    //dxgsg8_cat.debug() << new_projection_mat << endl;
+    //dxgsg8_cat.debug() << "using matrix projection" << endl;
   }
+
   return SUCCEEDED(hr);
 }
 
@@ -3021,17 +3029,19 @@ prepare_texture(Texture *tex) {
 void DXGraphicsStateGuardian8::
 apply_texture(TextureContext *tc) {
     if (tc==NULL) {
-        return;  // use enable_texturing to disable/enable
+      // The texture wasn't bound properly or something, so ensure
+      // texturing is disabled and just return.
+      enable_texturing(false);
+      return;
     }
+
     #ifdef DO_PSTATS
        add_to_texture_record(tc);
     #endif
 
-//  bind_texture(tc);
-
-//  specify_texture(tc->_texture);
-    // Note: if this code changes, make sure to change initialization SetTSS code in dx_init as well
-    // so DX TSS renderstate matches dxgsg state
+    // Note: if this code changes, make sure to change initialization
+    // SetTSS code in dx_init as well so DX TSS renderstate matches
+    // dxgsg state
 
     DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
 
@@ -3057,7 +3067,6 @@ apply_texture(TextureContext *tc) {
             // Oops, we can't re-create the texture for some reason.
             dxgsg8_cat.error() << "Unable to re-create texture " << *dtc->_texture << endl;
 
-            release_texture(dtc);
             enable_texturing(false);
             return;
           }
@@ -3065,7 +3074,8 @@ apply_texture(TextureContext *tc) {
       dtc->clear_dirty_flags();
     } else {
        if(_pCurTexContext == dtc) {
-          return;  // tex already set (and possible problem in state-sorting?)
+          enable_texturing(true);
+          return;
        }
     }
 
@@ -3171,6 +3181,7 @@ apply_texture(TextureContext *tc) {
 #endif
 
     _pCurTexContext = dtc;   // enable_texturing needs this
+    enable_texturing(true);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3189,30 +3200,34 @@ release_texture(TextureContext *tc) {
 // copies current display region in framebuffer to the texture
 // usually its more efficient to do SetRenderTgt
 void DXGraphicsStateGuardian8::
-copy_texture(TextureContext *tc, const DisplayRegion *dr) {
+copy_texture(Texture *tex, const DisplayRegion *dr) {
 
   HRESULT hr;
   int xo, yo, w, h;
   dr->get_region_pixels(xo, yo, w, h);
 
-  DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
-  PixelBuffer *pb = dtc->_tex->_pbuffer;
+  PixelBuffer *pb = tex->_pbuffer;
   pb->set_size(0,0,w-xo,h-yo);
 
+  TextureContext *tc = tex->prepare_now(get_prepared_objects(), this);
+  if (tc == (TextureContext *)NULL) {
+    return;
+  }
+  DXTextureContext8 *dtc = DCAST(DXTextureContext8, tc);
+
   IDirect3DSurface8 *pTexSurfaceLev0,*pCurRenderTarget;
   hr = dtc->_pD3DTexture8->GetSurfaceLevel(0,&pTexSurfaceLev0);
   if(FAILED(hr)) {
     dxgsg8_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
-    exit(1);
+    return;
   }
 
   hr = _pD3DDevice->GetRenderTarget(&pCurRenderTarget);
   if(FAILED(hr)) {
     dxgsg8_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr);
-    exit(1);
+    return;
   }
 
-
   RECT SrcRect;
 
   SrcRect.left = xo;
@@ -3224,7 +3239,7 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) {
   hr = _pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,NULL);
   if(FAILED(hr)) {
     dxgsg8_cat.error() << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr);
-    exit(1);
+    return;
   }
 
   SAFE_RELEASE(pCurRenderTarget);
@@ -3238,9 +3253,9 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
-copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb) {
+copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) {
     set_read_buffer(rb);
-    copy_texture(tc, dr);
+    copy_texture(tex, dr);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3561,20 +3576,15 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB
 ////////////////////////////////////////////////////////////////////
 INLINE void DXGraphicsStateGuardian8::
 enable_texturing(bool val) {
-//  if (_texturing_enabled == val) {  // this check is mostly for internal gsg calls, panda already screens out redundant state changes
-//        return;
-//  }
-
-    _texturing_enabled = val;
-
-//  assert(_pCurTexContext!=NULL);  we're definitely called with it NULL for both true and false
-//  I'm going to allow enabling texturing even if no tex has been set yet, seems to cause no probs
+  _texturing_enabled = val;
+  
+  if (!val) {
+    _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
 
-    if (val == false) {
-        _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
-    } else {
-          SetTextureBlendMode(_CurTexBlendMode,true);
-    }
+  } else {
+    nassertv(_pCurTexContext!=NULL);
+    SetTextureBlendMode(_CurTexBlendMode,true);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3643,7 +3653,6 @@ issue_texture(const TextureAttrib *attrib) {
   if (attrib->is_off()) {
     enable_texturing(false);
   } else {
-    enable_texturing(true);
     Texture *tex = attrib->get_texture();
     nassertv(tex != (Texture *)NULL);
 
@@ -4494,7 +4503,7 @@ save_frame_buffer(const RenderBuffer &buffer,
     if (buffer._buffer_type & RenderBuffer::T_back) {
         // Save the color buffer.
         sfb->_back_rgba = new Texture;
-        copy_texture(sfb->_back_rgba->prepare(this), dr, buffer);
+        copy_texture(sfb->_back_rgba, dr, buffer);
     }
 
     return sfb;

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

@@ -102,8 +102,8 @@ public:
   virtual void apply_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr);
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr,
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr);
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr,
                             const RenderBuffer &rb);
 
   virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb);

+ 7 - 30
panda/src/dxgsg8/dxTextureContext8.cxx

@@ -1429,17 +1429,9 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
 #endif
 #endif
 
-    // Note: user may want to create an empty "texture" that will be written to by rendering and copy operations.
-    //       this will never have a backing store of main memory in panda fmt, and on disk in a file.
-    //       so for this case, you dont want to call FillDDSurf.
-    //       need a better way for user to indicate this usage than lack of ram_image, because it conflicts
-    //       with the multi-open case mentioned below
-
-    if(_texture->has_ram_image()) {
-        hr = FillDDSurfTexturePixels();
-        if(FAILED(hr)) {
-            goto error_exit;
-        }
+    hr = FillDDSurfTexturePixels();
+    if(FAILED(hr)) {
+      goto error_exit;
     }
 
     // PRINT_REFCNT(dxgsg8,scrn.pD3D8);
@@ -1458,27 +1450,12 @@ FillDDSurfTexturePixels(void) {
     HRESULT hr=E_FAIL;
     assert(IS_VALID_PTR(_texture));
 
-    // It is a mistake to insist that has_ram_image() be true before
-    // we try to load the texture.  This function only indicates
-    // whether the texture image is already present in main ram or
-    // not; it has nothing to do with whether get_ram_image() will
-    // fail.  When there is only one GSG in the world, has_ram_image()
-    // will generally be true whenever the texture has not been loaded
-    // before, but when there are multiple GSG's (for instance, if we
-    // close and reopen the main window), then has_ram_image() is
-    // largely irrelevant to the GSG.
-    /*
-    if(!_texture->has_ram_image()) {
-      dxgsg8_cat.warning() << "CreateTexture: tried to fill surface that has no ram image!\n";
-      return S_OK;
-    }
-    */
-
     PixelBuffer *pbuf = _texture->get_ram_image();
     if (pbuf == (PixelBuffer *)NULL) {
-      dxgsg8_cat.fatal() << "CreateTexture: get_ram_image() failed\n";
-      // The texture doesn't have an image to load.
-      return E_FAIL;
+      // The texture doesn't have an image to load.  That's ok; it
+      // might be a texture we've rendered to by frame buffer
+      // operations or something.
+      return S_OK;
     }
 
     assert(IS_VALID_PTR(_pD3DTexture8));

+ 53 - 44
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -29,6 +29,7 @@
 #include "graphicsChannel.h"
 #include "lens.h"
 #include "perspectiveLens.h"
+#include "orthographicLens.h"
 #include "ambientLight.h"
 #include "directionalLight.h"
 #include "pointLight.h"
@@ -1055,17 +1056,17 @@ prepare_lens() {
     LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
     projection_mat;
   
-  float vfov = _current_lens->get_vfov();
   float nearf = _current_lens->get_near();
   float farf = _current_lens->get_far();
 
   //dxgsg9_cat.debug() << new_projection_mat << endl;
   
   HRESULT hr;
-  if (_current_lens->get_type().get_name() == "PerspectiveLens") {
-#if 0
+  if (false && _current_lens->is_of_type(PerspectiveLens::get_class_type())) {
+    /*
     const LMatrix4f mat_temp;
 
+    float vfov = _current_lens->get_vfov();
     float hfov = _current_lens->get_hfov();
     float ar = _current_lens->get_aspect_ratio();
     float nearf = _current_lens->get_near();
@@ -1078,25 +1079,32 @@ prepare_lens() {
     hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
                                    (D3DMATRIX*)mat_temp.get_data());
     dxgsg9_cat.debug() << mat_temp << endl;
-#endif
-    
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_33 = farf / (farf-nearf);
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_43 = -nearf * farf / (farf - nearf);
+    */
+
+    new_projection_mat(2, 2) = farf / (farf-nearf);
+    new_projection_mat(3, 2) = -nearf * farf / (farf - nearf);
 
     hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
                                    (D3DMATRIX*)new_projection_mat.get_data());
     //dxgsg9_cat.debug() << new_projection_mat << endl;
     //dxgsg9_cat.debug() << "using perspective projection" << endl;
-  }
-  else {
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_33 = 1/(farf-nearf);
-    ((D3DXMATRIX*)new_projection_mat.get_data())->_43 = -nearf/(farf-nearf);
+
+  } else if (false && _current_lens->is_of_type(OrthographicLens::get_class_type())) {
+    new_projection_mat(2, 2) = 1 / (farf - nearf);
+    new_projection_mat(3, 2) = -nearf / (farf - nearf);
     
     hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
                                    (D3DMATRIX*)new_projection_mat.get_data());
     //dxgsg9_cat.debug() << new_projection_mat << endl;
     //dxgsg9_cat.debug() << "using ortho projection" << endl;
+
+  } else {
+    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
+                                   (D3DMATRIX*)new_projection_mat.get_data());
+    //dxgsg9_cat.debug() << new_projection_mat << endl;
+    //dxgsg9_cat.debug() << "using matrix projection" << endl;
   }
+
   return SUCCEEDED(hr);
 }
 
@@ -3037,17 +3045,19 @@ prepare_texture(Texture *tex) {
 void DXGraphicsStateGuardian9::
 apply_texture(TextureContext *tc) {
     if (tc==NULL) {
-        return;  // use enable_texturing to disable/enable
+      // The texture wasn't bound properly or something, so ensure
+      // texturing is disabled and just return.
+      enable_texturing(false);
+      return;
     }
+
     #ifdef DO_PSTATS
        add_to_texture_record(tc);
     #endif
 
-//  bind_texture(tc);
-
-//  specify_texture(tc->_texture);
-    // Note: if this code changes, make sure to change initialization SetTSS code in dx_init as well
-    // so DX TSS renderstate matches dxgsg state
+    // Note: if this code changes, make sure to change initialization
+    // SetTSS code in dx_init as well so DX TSS renderstate matches
+    // dxgsg state
 
     DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
 
@@ -3073,7 +3083,6 @@ apply_texture(TextureContext *tc) {
             // Oops, we can't re-create the texture for some reason.
             dxgsg9_cat.error() << "Unable to re-create texture " << *dtc->_texture << endl;
 
-            release_texture(dtc);
             enable_texturing(false);
             return;
           }
@@ -3081,7 +3090,8 @@ apply_texture(TextureContext *tc) {
       dtc->clear_dirty_flags();
     } else {
        if(_pCurTexContext == dtc) {
-          return;  // tex already set (and possible problem in state-sorting?)
+          enable_texturing(true);
+          return;
        }
     }
 
@@ -3187,6 +3197,7 @@ apply_texture(TextureContext *tc) {
 #endif
 
     _pCurTexContext = dtc;   // enable_texturing needs this
+    enable_texturing(true);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3205,30 +3216,34 @@ release_texture(TextureContext *tc) {
 // copies current display region in framebuffer to the texture
 // usually its more efficient to do SetRenderTgt
 void DXGraphicsStateGuardian9::
-copy_texture(TextureContext *tc, const DisplayRegion *dr) {
+copy_texture(Texture *tex, const DisplayRegion *dr) {
 
   HRESULT hr;
   int xo, yo, w, h;
   dr->get_region_pixels(xo, yo, w, h);
 
-  DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
-  PixelBuffer *pb = dtc->_tex->_pbuffer;
+  PixelBuffer *pb = tex->_pbuffer;
   pb->set_size(0,0,w-xo,h-yo);
 
+  TextureContext *tc = tex->prepare_now(get_prepared_objects(), this);
+  if (tc == (TextureContext *)NULL) {
+    return;
+  }
+  DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
+
   IDirect3DSurface9 *pTexSurfaceLev0,*pCurRenderTarget;
   hr = dtc->_pD3DTexture9->GetSurfaceLevel(0,&pTexSurfaceLev0);
   if(FAILED(hr)) {
     dxgsg9_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
-    exit(1);
+    return;
   }
 
   hr = _pD3DDevice->GetRenderTarget(0, &pCurRenderTarget);
   if(FAILED(hr)) {
     dxgsg9_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr);
-    exit(1);
+    return;
   }
 
-
   RECT SrcRect;
 
   SrcRect.left = xo;
@@ -3240,8 +3255,8 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) {
   hr = _pD3DDevice->UpdateSurface(pCurRenderTarget,&SrcRect,pTexSurfaceLev0,NULL);
   
   if(FAILED(hr)) {
-    dxgsg9_cat.error() << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr);
-    exit(1);
+    dxgsg9_cat.error() << "UpdateSurface failed in copy_texture" << D3DERRORSTRING(hr);
+    return;
   }
 
   SAFE_RELEASE(pCurRenderTarget);
@@ -3255,9 +3270,9 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
-copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb) {
+copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) {
     set_read_buffer(rb);
-    copy_texture(tc, dr);
+    copy_texture(tex, dr);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3578,20 +3593,15 @@ void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexB
 ////////////////////////////////////////////////////////////////////
 INLINE void DXGraphicsStateGuardian9::
 enable_texturing(bool val) {
-//  if (_texturing_enabled == val) {  // this check is mostly for internal gsg calls, panda already screens out redundant state changes
-//        return;
-//  }
-
-    _texturing_enabled = val;
-
-//  assert(_pCurTexContext!=NULL);  we're definitely called with it NULL for both true and false
-//  I'm going to allow enabling texturing even if no tex has been set yet, seems to cause no probs
+  _texturing_enabled = val;
+  
+  if (!val) {
+    _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
 
-    if (val == false) {
-        _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
-    } else {
-          SetTextureBlendMode(_CurTexBlendMode,true);
-    }
+  } else {
+    nassertv(_pCurTexContext!=NULL);
+    SetTextureBlendMode(_CurTexBlendMode,true);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3660,7 +3670,6 @@ issue_texture(const TextureAttrib *attrib) {
   if (attrib->is_off()) {
     enable_texturing(false);
   } else {
-    enable_texturing(true);
     Texture *tex = attrib->get_texture();
     nassertv(tex != (Texture *)NULL);
 
@@ -4511,7 +4520,7 @@ save_frame_buffer(const RenderBuffer &buffer,
     if (buffer._buffer_type & RenderBuffer::T_back) {
         // Save the color buffer.
         sfb->_back_rgba = new Texture;
-        copy_texture(sfb->_back_rgba->prepare(this), dr, buffer);
+        copy_texture(sfb->_back_rgba, dr, buffer);
     }
 
     return sfb;

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

@@ -102,8 +102,8 @@ public:
   virtual void apply_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr);
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr,
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr);
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr,
                             const RenderBuffer &rb);
 
   virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb);

+ 7 - 30
panda/src/dxgsg9/dxTextureContext9.cxx

@@ -1429,17 +1429,9 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) {
 #endif
 #endif
 
-    // Note: user may want to create an empty "texture" that will be written to by rendering and copy operations.
-    //       this will never have a backing store of main memory in panda fmt, and on disk in a file.
-    //       so for this case, you dont want to call FillDDSurf.
-    //       need a better way for user to indicate this usage than lack of ram_image, because it conflicts
-    //       with the multi-open case mentioned below
-
-    if(_texture->has_ram_image()) {
-        hr = FillDDSurfTexturePixels();
-        if(FAILED(hr)) {
-            goto error_exit;
-        }
+    hr = FillDDSurfTexturePixels();
+    if(FAILED(hr)) {
+      goto error_exit;
     }
 
     // PRINT_REFCNT(dxgsg9,scrn.pD3D9);
@@ -1458,27 +1450,12 @@ FillDDSurfTexturePixels(void) {
     HRESULT hr=E_FAIL;
     assert(IS_VALID_PTR(_texture));
 
-    // It is a mistake to insist that has_ram_image() be true before
-    // we try to load the texture.  This function only indicates
-    // whether the texture image is already present in main ram or
-    // not; it has nothing to do with whether get_ram_image() will
-    // fail.  When there is only one GSG in the world, has_ram_image()
-    // will generally be true whenever the texture has not been loaded
-    // before, but when there are multiple GSG's (for instance, if we
-    // close and reopen the main window), then has_ram_image() is
-    // largely irrelevant to the GSG.
-    /*
-    if(!_texture->has_ram_image()) {
-      dxgsg9_cat.warning() << "CreateTexture: tried to fill surface that has no ram image!\n";
-      return S_OK;
-    }
-    */
-
     PixelBuffer *pbuf = _texture->get_ram_image();
     if (pbuf == (PixelBuffer *)NULL) {
-      dxgsg9_cat.fatal() << "CreateTexture: get_ram_image() failed\n";
-      // The texture doesn't have an image to load.
-      return E_FAIL;
+      // The texture doesn't have an image to load.  That's ok; it
+      // might be a texture we've rendered to by frame buffer
+      // operations or something.
+      return S_OK;
     }
 
     assert(IS_VALID_PTR(_pD3DTexture9));

+ 9 - 9
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1907,9 +1907,8 @@ static int binary_log_cap(const int x) {
 //               region from the framebuffer into texture memory
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
-copy_texture(TextureContext *tc, const DisplayRegion *dr) {
-  nassertv(tc != NULL && dr != NULL);
-  Texture *tex = tc->_texture;
+copy_texture(Texture *tex, const DisplayRegion *dr) {
+  nassertv(tex != NULL && dr != NULL);
 
   int xo, yo, w, h;
 
@@ -1937,11 +1936,13 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) {
   PixelBuffer *pb = tex->_pbuffer;
   pb->set_size(xo,yo,w,h);
 
+  TextureContext *tc = tex->prepare_now(get_prepared_objects(), this);
+  nassertv(tc != (TextureContext *)NULL);
   bind_texture(tc);
 
   GLP(CopyTexImage2D)(GL_TEXTURE_2D, 0,
-                   get_internal_image_format(pb->get_format()),
-                   xo, yo, w, h, pb->get_border());
+                      get_internal_image_format(pb->get_format()),
+                      xo, yo, w, h, pb->get_border());
 
   // Clear the internal texture state, since we've just monkeyed with it.
   modify_state(get_untextured_state());
@@ -1953,9 +1954,9 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr) {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
-copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb) {
+copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) {
   set_read_buffer(rb);
-  copy_texture(tc, dr);
+  copy_texture(tex, dr);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3969,8 +3970,7 @@ save_frame_buffer(const RenderBuffer &buffer,
   if (buffer._buffer_type & RenderBuffer::T_back) {
     // Save the color buffer.
     sfb->_back_rgba = new Texture;
-    TextureContext *tc = sfb->_back_rgba->prepare_now(_prepared_objects, this);
-    copy_texture(tc, dr, buffer);
+    copy_texture(sfb->_back_rgba, dr, buffer);
   }
 
   return sfb;

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

@@ -75,8 +75,8 @@ public:
                               GeomNodeContext *gnc);
   virtual void release_geom_node(GeomNodeContext *gnc);
 
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr);
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr,
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr);
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr,
                             const RenderBuffer &rb);
 
   virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb);

+ 6 - 3
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -196,10 +196,13 @@ prepare_texture_now(Texture *tex, GraphicsStateGuardianBase *gsg) {
   // all shared anyway).
   TextureContext *tc = gsg->prepare_texture(tex);
 
-  bool prepared = _prepared_textures.insert(tc).second;
-  nassertr(prepared, tc);
+  if (tc != (TextureContext *)NULL) {
+    bool prepared = _prepared_textures.insert(tc).second;
+    nassertr(prepared, tc);
+
+    _total_texusage_pcollector.add_level(tc->estimate_texture_memory());
+  }
 
-  _total_texusage_pcollector.add_level(tc->estimate_texture_memory());
   return tc;
 }
 

+ 19 - 18
panda/src/gobj/texture.cxx

@@ -502,26 +502,27 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
   }
 
   TextureContext *tc = prepared_objects->prepare_texture_now(this, gsg);
-  _contexts[prepared_objects] = tc;
-
-  // Now that we have a new TextureContext with zero dirty flags, our
-  // intersection of all dirty flags must be zero.  This doesn't mean
-  // that some other contexts aren't still dirty, but at least one
-  // context isn't.
-  _all_dirty_flags = 0;
-
-  if (!keep_texture_ram && !_keep_ram_image) {
-    // Once we have prepared the texture, we can generally safely
-    // remove the pixels from main RAM.  The GSG is now responsible
-    // for remembering what it looks like.
-
-    if (gobj_cat.is_debug()) {
-      gobj_cat.debug()
-        << "Dumping RAM for texture " << get_name() << "\n";
+  if (tc != (TextureContext *)NULL) {
+    _contexts[prepared_objects] = tc;
+
+    // Now that we have a new TextureContext with zero dirty flags, our
+    // intersection of all dirty flags must be zero.  This doesn't mean
+    // that some other contexts aren't still dirty, but at least one
+    // context isn't.
+    _all_dirty_flags = 0;
+
+    if (!keep_texture_ram && !_keep_ram_image) {
+      // Once we have prepared the texture, we can generally safely
+      // remove the pixels from main RAM.  The GSG is now responsible
+      // for remembering what it looks like.
+
+      if (gobj_cat.is_debug()) {
+        gobj_cat.debug()
+          << "Dumping RAM for texture " << get_name() << "\n";
+      }
+      _pbuffer->_image.clear();
     }
-    _pbuffer->_image.clear();
   }
-
   return tc;
 }
 

+ 2 - 2
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -165,8 +165,8 @@ public:
   virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0;
   virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0;
 
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr)=0;
-  virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr,
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr)=0;
+  virtual void copy_texture(Texture *tex, const DisplayRegion *dr,
                             const RenderBuffer &rb)=0;
 
   virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb)=0;

+ 1 - 2
panda/src/wgldisplay/wglGraphicsBuffer.cxx

@@ -130,8 +130,7 @@ end_frame() {
 
     DisplayRegion dr(this, _x_size, _y_size);
     RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type());
-    TextureContext *tc = get_texture()->prepare_now(_gsg->get_prepared_objects(), _gsg);
-    _gsg->copy_texture(tc, &dr, buffer);
+    _gsg->copy_texture(get_texture(), &dr, buffer);
   }
 }