Panda3D

wdxGraphicsBuffer9.cxx

00001 // Filename: wdxGraphicsBuffer8.cxx
00002 // Created by:  drose (08Feb04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "wdxGraphicsPipe9.h"
00016 #include "wdxGraphicsBuffer9.h"
00017 #include "dxGraphicsStateGuardian9.h"
00018 #include "pStatTimer.h"
00019 
00020 
00021 #define FL << "\n" << __FILE__ << " " << __LINE__ << "\n"
00022 
00023 TypeHandle wdxGraphicsBuffer9::_type_handle;
00024 
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: wdxGraphicsBuffer9::Constructor
00028 //       Access: Public
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 wdxGraphicsBuffer9::
00032 wdxGraphicsBuffer9(GraphicsEngine *engine, GraphicsPipe *pipe,
00033                    const string &name,
00034                    const FrameBufferProperties &fb_prop,
00035                    const WindowProperties &win_prop,
00036                    int flags,
00037                    GraphicsStateGuardian *gsg,
00038                    GraphicsOutput *host):
00039   GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00040 {
00041   // initialize all class members
00042   _cube_map_index = -1;
00043   _saved_color_buffer = NULL;
00044   _saved_depth_buffer = NULL;
00045   _color_backing_store = NULL;
00046   _depth_backing_store = NULL;
00047 
00048   // is this correct ???
00049   // Since the pbuffer never gets flipped, we get screenshots from the
00050   // same buffer we draw into.
00051   _screenshot_buffer_type = _draw_buffer_type;
00052 
00053   _shared_depth_buffer = 0;
00054   _debug = 0;
00055   _this = 0;
00056 
00057   if (_debug) {
00058     cout << "+++++ wdxGraphicsBuffer9 constructor " << this << " " << this -> get_name ( ) << "\n";
00059   }
00060   
00061   if (_gsg) {
00062     // save to GSG list to handle device lost issues
00063     DXGraphicsStateGuardian9 *dxgsg;
00064 
00065     dxgsg = DCAST (DXGraphicsStateGuardian9, _gsg);
00066     _this = new (wdxGraphicsBuffer9 *);
00067     *_this = this;
00068     dxgsg -> _graphics_buffer_list.push_back(_this);
00069   }
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: wdxGraphicsBuffer9::Destructor
00074 //       Access: Public, Virtual
00075 //  Description:
00076 ////////////////////////////////////////////////////////////////////
00077 wdxGraphicsBuffer9::
00078 ~wdxGraphicsBuffer9() {
00079 
00080   if (_debug) {
00081     cout << "----- wdxGraphicsBuffer9 destructor " << this << " " << this -> get_name ( ) << "\n";
00082   }
00083 
00084   if (_gsg) {
00085     // remove from GSG list
00086     DXGraphicsStateGuardian9 *dxgsg;
00087 
00088     dxgsg = DCAST (DXGraphicsStateGuardian9, _gsg);
00089     if (_this) {
00090       dxgsg -> _graphics_buffer_list.remove(_this);
00091     }
00092     _this = 0;
00093     _gsg.clear();
00094     _gsg = 0;
00095   }
00096 
00097   // unshare shared depth buffer if any
00098   this -> unshare_depth_buffer();  
00099 
00100   // unshare all buffers that are sharing this object's depth buffer
00101   {
00102     wdxGraphicsBuffer9 *graphics_buffer;
00103     list <wdxGraphicsBuffer9 *>::iterator graphics_buffer_iterator;
00104 
00105     graphics_buffer_iterator = _shared_depth_buffer_list.begin( );
00106     while (graphics_buffer_iterator != _shared_depth_buffer_list.end( )) {
00107       graphics_buffer = (*graphics_buffer_iterator);
00108       if (graphics_buffer) {      
00109         // this call removes the entry from the list
00110         graphics_buffer -> unshare_depth_buffer();
00111       }      
00112       graphics_buffer_iterator = _shared_depth_buffer_list.begin( );
00113     }
00114   }  
00115   
00116   this -> close_buffer ( );
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: wdxGraphicsBuffer9::begin_frame
00121 //       Access: Public, Virtual
00122 //  Description: This function will be called within the draw thread
00123 //               before beginning rendering for a given frame.  It
00124 //               should do whatever setup is required, and return true
00125 //               if the frame should be rendered, or false if it
00126 //               should be skipped.
00127 ////////////////////////////////////////////////////////////////////
00128 bool wdxGraphicsBuffer9::
00129 begin_frame(FrameMode mode, Thread *current_thread) {
00130 
00131   begin_frame_spam(mode);
00132   if (_gsg == (GraphicsStateGuardian *)NULL) {
00133     return false;
00134   }
00135   if (_dxgsg -> _d3d_device == 0) {
00136     return false;
00137   }
00138 
00139   if (mode == FM_render) {
00140     if (!save_bitplanes()) {
00141       return false;
00142     }
00143     if (!rebuild_bitplanes()) {
00144       restore_bitplanes();
00145       return false;
00146     }
00147     clear_cube_map_selection();
00148   }
00149 
00150   _gsg->set_current_properties(&get_fb_properties());
00151   return _gsg->begin_frame(current_thread);
00152 }
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: wdxGraphicsBuffer9::end_frame
00156 //       Access: Public, Virtual
00157 //  Description: This function will be called within the draw thread
00158 //               after rendering is completed for a given frame.  It
00159 //               should do whatever finalization is required.
00160 ////////////////////////////////////////////////////////////////////
00161 void wdxGraphicsBuffer9::
00162 end_frame(FrameMode mode, Thread *current_thread) {
00163 
00164   end_frame_spam(mode);
00165   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00166 
00167   if (mode == FM_render) {
00168     copy_to_textures();
00169   }
00170 
00171   _gsg->end_frame(current_thread);
00172 
00173   if (mode == FM_render) {
00174     trigger_flip();
00175     clear_cube_map_selection();
00176     restore_bitplanes();
00177   }
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: wdxGraphicsBuffer9::save_bitplanes
00182 //       Access: Public
00183 //  Description: After rendering, d3d_device will need to be restored
00184 //               to its initial state.  This function saves the state.
00185 ////////////////////////////////////////////////////////////////////
00186 bool wdxGraphicsBuffer9::
00187 save_bitplanes() {
00188   HRESULT hr;
00189   DWORD render_target_index;
00190   
00191   render_target_index = 0;
00192 
00193   hr = _dxgsg -> _d3d_device -> GetRenderTarget (render_target_index, &_saved_color_buffer);
00194   if (!SUCCEEDED (hr)) {
00195     dxgsg9_cat.error ( ) << "GetRenderTarget " << D3DERRORSTRING(hr) FL;
00196     return false;
00197   }
00198   
00199   _saved_depth_buffer = 0;
00200   hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_saved_depth_buffer);
00201   if (hr == D3DERR_NOTFOUND) {
00202     // this case is actually ok
00203   }
00204   else {
00205     if (!SUCCEEDED (hr)) {
00206       dxgsg9_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
00207       return false;
00208     }
00209   }
00210   return true;
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: wdxGraphicsBuffer9::restore_bitplanes
00215 //       Access: Public
00216 //  Description: After rendering, d3d_device will need to be restored
00217 //               to its initial state.  This function restores the state.
00218 ////////////////////////////////////////////////////////////////////
00219 void wdxGraphicsBuffer9::
00220 restore_bitplanes() {
00221   DXGraphicsStateGuardian9 *dxgsg;
00222   DCAST_INTO_V(dxgsg, _gsg);
00223 
00224   HRESULT hr;
00225   DWORD render_target_index;
00226   
00227   render_target_index = 0;
00228 
00229   hr = dxgsg -> _d3d_device ->
00230     SetRenderTarget (render_target_index, _saved_color_buffer);
00231   if (!SUCCEEDED (hr)) {
00232     dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
00233   }
00234   if (_saved_depth_buffer) {
00235     hr = _dxgsg -> _d3d_device -> SetDepthStencilSurface (_saved_depth_buffer);
00236     if (!SUCCEEDED (hr)) {
00237       dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
00238     }
00239   }
00240   
00241   // clear all render targets, except for the main render target
00242   for (int i = 1; i<count_textures(); i++) {
00243     hr = _dxgsg -> _d3d_device -> SetRenderTarget (i, NULL);
00244     if (!SUCCEEDED (hr)) {
00245       dxgsg9_cat.error ( ) << "SetRenderTarget " << i << " " << D3DERRORSTRING(hr) FL;
00246     }
00247   }
00248 
00249   _saved_color_buffer->Release();
00250   if (_saved_depth_buffer) {
00251     _saved_depth_buffer->Release();
00252   }
00253   _saved_color_buffer = NULL;
00254   _saved_depth_buffer = NULL;
00255 }
00256 
00257 
00258 
00259 ////////////////////////////////////////////////////////////////////
00260 //     Function: wdxGraphicsBuffer9::rebuild_bitplanes
00261 //       Access: Public
00262 //  Description: If necessary, reallocates (or allocates) the
00263 //               bitplanes for the buffer.
00264 ////////////////////////////////////////////////////////////////////
00265 bool wdxGraphicsBuffer9::
00266 rebuild_bitplanes() {
00267   HRESULT hr;
00268   Texture *color_tex = 0;
00269   Texture *depth_tex = 0;
00270   DXTextureContext9 *color_ctx = 0;
00271   DXTextureContext9 *depth_ctx = 0;
00272   IDirect3DTexture9 *color_d3d_tex = 0;
00273   IDirect3DTexture9 *depth_d3d_tex = 0;
00274   IDirect3DCubeTexture9 *color_cube = 0;
00275   IDirect3DCubeTexture9 *depth_cube = 0;
00276   IDirect3DSurface9 *color_surf = 0;
00277   IDirect3DSurface9 *depth_surf = 0;
00278   DWORD render_target_index;
00279   
00280   render_target_index = 0;
00281   
00282   // Decide how big the bitplanes should be.
00283 
00284   if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) {
00285     if ((_host->get_x_size() != _x_size)||
00286         (_host->get_y_size() != _y_size)) {
00287       set_size_and_recalc(_host->get_x_size(),
00288                           _host->get_y_size());
00289     }
00290   }
00291   int bitplane_x = _x_size;
00292   int bitplane_y = _y_size;
00293   if (Texture::get_textures_power_2() != ATS_none) {
00294     bitplane_x = Texture::up_to_power_2(bitplane_x);
00295     bitplane_y = Texture::up_to_power_2(bitplane_y);
00296   }
00297   
00298   // Find the color and depth textures.  Either may be present,
00299   // or neither.
00300   //
00301   // NOTE: Currently, depth-stencil textures are not implemented,
00302   // but since it's coming soon, we're structuring for it.
00303 
00304   int color_tex_index = -1;
00305   int depth_tex_index = -1;
00306   {
00307     CDLockedReader cdata(_cycler);
00308     for (size_t i = 0; i != cdata->_textures.size(); ++i) {
00309       const RenderTexture &rt = cdata->_textures[i];
00310       RenderTextureMode rtm_mode = rt._rtm_mode;
00311       if (rtm_mode == RTM_bind_or_copy) {
00312         RenderTexturePlane plane = rt._plane;
00313 
00314         switch (plane) {
00315         case RTP_color:
00316           color_tex_index = i;
00317           break;
00318 
00319         case RTP_aux_rgba_0:
00320         case RTP_aux_rgba_1:
00321         case RTP_aux_rgba_2:
00322         case RTP_aux_rgba_3:
00323         case RTP_aux_hrgba_0:
00324         case RTP_aux_hrgba_1:
00325         case RTP_aux_hrgba_2:
00326         case RTP_aux_hrgba_3:
00327         case RTP_aux_float_0:
00328         case RTP_aux_float_1:
00329         case RTP_aux_float_2:
00330         case RTP_aux_float_3:
00331           {
00332             CDWriter cdataw(_cycler, cdata, false);
00333             nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
00334             cdataw->_textures[i]._rtm_mode = RTM_none;
00335           }
00336           break;
00337         default:
00338           {
00339             CDWriter cdataw(_cycler, cdata, false);
00340             nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
00341             cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
00342           }
00343           break;
00344         }
00345       }                
00346     }
00347   }
00348 
00349   if (color_tex_index < 0) {
00350     // Maintain the backing color surface.
00351     if ((_color_backing_store)&&
00352         ((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) {
00353       _color_backing_store->Release();
00354       _color_backing_store = NULL;
00355     }
00356     if (!_color_backing_store) {
00357       hr = _dxgsg -> _d3d_device ->
00358         CreateOffscreenPlainSurface(bitplane_x, bitplane_y, _saved_color_desc.Format,
00359                                     D3DPOOL_DEFAULT, &_color_backing_store, NULL);
00360       if (!SUCCEEDED(hr)) {
00361         dxgsg9_cat.error ( ) << "CreateImageSurface " << D3DERRORSTRING(hr) FL;
00362       }
00363     }
00364     color_surf = _color_backing_store;
00365   } else {
00366     // Maintain the color texture.
00367     if (_color_backing_store) {
00368       _color_backing_store->Release();
00369       _color_backing_store = NULL;
00370     }
00371     color_tex = get_texture(color_tex_index);
00372     color_tex->set_size_padded(_x_size, _y_size);
00373 //    color_tex->set_format(Texture::F_rgba);
00374     color_ctx =
00375       DCAST(DXTextureContext9,
00376             color_tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg));
00377 
00378     if (color_ctx) {
00379       if (!color_ctx->create_texture(*_dxgsg->_screen)) {
00380         dxgsg9_cat.error()
00381           << "Unable to re-create texture " << *color_ctx->get_texture() << endl;
00382         return false;
00383       }
00384       if (color_tex->get_texture_type() == Texture::TT_2d_texture) {
00385         color_d3d_tex = color_ctx->_d3d_2d_texture;
00386         nassertr(color_d3d_tex != 0, false);
00387         hr = color_d3d_tex -> GetSurfaceLevel(0, &color_surf);
00388         if (!SUCCEEDED(hr)) {
00389           dxgsg9_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
00390         }
00391       }
00392       if (color_tex->get_texture_type() == Texture::TT_cube_map) {
00393         color_cube = color_ctx->_d3d_cube_texture;
00394         nassertr(color_cube != 0, false);
00395 
00396         if (_cube_map_index >= 0 && _cube_map_index < 6) {
00397           hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf);
00398           if (!SUCCEEDED(hr)) {
00399             dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
00400           }
00401         }
00402       }
00403     }
00404   }
00405 
00406   bool release_depth;
00407   
00408   release_depth = true;  
00409   if (depth_tex_index < 0) {
00410     if (_shared_depth_buffer) {
00411       if (_shared_depth_buffer -> _depth_backing_store) {
00412         if (_debug) {
00413           printf ("SHARE DEPTH BUFFER\n");
00414         }
00415         depth_surf = _shared_depth_buffer -> _depth_backing_store;
00416         release_depth = false;
00417       }
00418     }
00419     if (depth_surf == 0) {
00420       // Maintain the backing depth surface.
00421       if ((_depth_backing_store)&&
00422           ((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) {
00423         _depth_backing_store->Release();
00424         _depth_backing_store = NULL;
00425       }
00426       if (!_depth_backing_store) {
00427         hr = _dxgsg -> _d3d_device ->
00428           CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format,
00429                                      _saved_depth_desc.MultiSampleType, _saved_depth_desc.MultiSampleQuality,
00430                                      false, &_depth_backing_store, NULL);
00431         if (!SUCCEEDED(hr)) {
00432           dxgsg9_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL;
00433         }
00434       }
00435       depth_surf = _depth_backing_store;
00436     }
00437   } else {
00438     // Maintain the depth texture.
00439     if (_depth_backing_store) {
00440       _depth_backing_store->Release();
00441       _depth_backing_store = NULL;
00442     }
00443 
00444     if (_shared_depth_buffer) {      
00445       depth_tex = _shared_depth_buffer -> get_texture(depth_tex_index);
00446     }
00447     if (depth_tex == 0) {        
00448       depth_tex = get_texture(depth_tex_index);
00449     }
00450 
00451     depth_tex->set_size_padded(_x_size, _y_size);
00452     depth_tex->set_format(Texture::F_depth_stencil);
00453     depth_ctx =
00454       DCAST(DXTextureContext9,
00455             depth_tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg));
00456     if (depth_ctx) {
00457       if (!depth_ctx->create_texture(*_dxgsg->_screen)) {
00458         dxgsg9_cat.error()
00459           << "Unable to re-create texture " << *color_ctx->get_texture() << endl;
00460         return false;
00461       }
00462       if (depth_tex->get_texture_type() == Texture::TT_2d_texture) {
00463         depth_d3d_tex = depth_ctx->_d3d_2d_texture;
00464         nassertr(depth_d3d_tex != 0, false);
00465         hr = color_d3d_tex -> GetSurfaceLevel(0, &depth_surf);
00466         if (!SUCCEEDED(hr)) {
00467           dxgsg9_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
00468         }
00469       }
00470       if (depth_tex->get_texture_type() == Texture::TT_cube_map) {
00471         depth_cube = depth_ctx->_d3d_cube_texture;
00472         nassertr(depth_cube != 0, false);
00473         hr = depth_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &depth_surf);
00474         if (!SUCCEEDED(hr)) {
00475           dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
00476         }
00477       }
00478     }
00479   }
00480 
00481   _backing_sizex = bitplane_x;
00482   _backing_sizey = bitplane_y;
00483 
00484   // Load up the bitplanes.
00485   if (color_surf) {
00486     hr = _dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, color_surf);
00487     if (!SUCCEEDED (hr)) {
00488       dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
00489     }
00490   }
00491 
00492   if (depth_surf) {
00493     hr = _dxgsg -> _d3d_device -> SetDepthStencilSurface (depth_surf);
00494     if (!SUCCEEDED (hr)) {
00495       dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
00496     }
00497   }
00498 
00499   render_target_index = 1;
00500   for (int i=0; i<count_textures(); i++) {
00501 
00502     Texture *tex = get_texture(i);
00503     RenderTexturePlane plane = get_texture_plane(i);
00504 
00505     if (_debug) {
00506 //      printf ("i = %d, RenderTexturePlane = %d \n", i, plane);
00507     }
00508 
00509     switch (plane) {
00510       case RTP_color:
00511         break;
00512       case RTP_aux_rgba_0:
00513       case RTP_aux_rgba_1:
00514       case RTP_aux_rgba_2:
00515       case RTP_aux_rgba_3:
00516       case RTP_aux_hrgba_0:
00517       case RTP_aux_hrgba_1:
00518       case RTP_aux_hrgba_2:
00519       case RTP_aux_hrgba_3:
00520       case RTP_aux_float_0:
00521       case RTP_aux_float_1:
00522       case RTP_aux_float_2:
00523       case RTP_aux_float_3:
00524         {
00525           DXTextureContext9 *color_ctx = 0;
00526           IDirect3DTexture9 *color_d3d_tex = 0;
00527           IDirect3DSurface9 *color_surf = 0;
00528           IDirect3DCubeTexture9 *color_cube = 0;
00529 
00530           color_ctx = DCAST(DXTextureContext9, tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg));
00531           if (color_ctx) {
00532             if (!color_ctx->create_texture(*_dxgsg->_screen)) {
00533               dxgsg9_cat.error()
00534                 << "Unable to re-create texture " << *color_ctx->get_texture() << endl;
00535               return false;
00536             }
00537             if (tex->get_texture_type() == Texture::TT_2d_texture) {
00538               color_d3d_tex = color_ctx->_d3d_2d_texture;
00539               nassertr(color_d3d_tex != 0, false);
00540 
00541               hr = color_d3d_tex -> GetSurfaceLevel(0, &color_surf);
00542               if (!SUCCEEDED(hr)) {
00543                 dxgsg9_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
00544               }
00545               if (color_surf) {
00546                 hr = _dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, color_surf);
00547                 if (SUCCEEDED (hr)) {
00548                   render_target_index++;
00549                 } else {
00550                   dxgsg9_cat.error ( ) << "SetRenderTarget " << render_target_index << " " << D3DERRORSTRING(hr) FL;
00551                 }
00552                 color_surf->Release();
00553               }
00554             }
00555           }
00556         }
00557         break;
00558 
00559       default:
00560         break;
00561     }    
00562   }
00563 
00564   // Decrement the reference counts on these surfaces. The refcounts
00565   // were incremented earlier when we called GetSurfaceLevel.
00566 
00567   if ((color_surf != 0)&&(color_surf != _color_backing_store)) {
00568     color_surf->Release();
00569   }
00570 
00571   if (release_depth) {
00572     if ((depth_surf != 0)&&(depth_surf != _depth_backing_store)) {
00573       depth_surf->Release();
00574     }
00575   }
00576   
00577   return true;
00578 }
00579 
00580 ////////////////////////////////////////////////////////////////////
00581 //     Function: wdxGraphicsBuffer9::select_cube_map
00582 //       Access: Public, Virtual
00583 //  Description: Called internally when the window is in
00584 //               render-to-a-texture mode and we are in the process of
00585 //               rendering the six faces of a cube map.  This should
00586 //               do whatever needs to be done to switch the buffer to
00587 //               the indicated face.
00588 ////////////////////////////////////////////////////////////////////
00589 void wdxGraphicsBuffer9::
00590 select_cube_map(int cube_map_index) {
00591 
00592   DWORD render_target_index;
00593   
00594   render_target_index = 0;
00595 
00596   _cube_map_index = cube_map_index;
00597 
00598   HRESULT hr;
00599   Texture *color_tex = 0;
00600   DXTextureContext9 *color_ctx = 0;
00601   IDirect3DCubeTexture9 *color_cube = 0;
00602   IDirect3DSurface9 *color_surf = 0;
00603   int color_tex_index = -1;
00604 
00605   {
00606     CDLockedReader cdata(_cycler);
00607     for (size_t i = 0; i != cdata->_textures.size(); ++i) {
00608       const RenderTexture &rt = cdata->_textures[i];
00609       RenderTextureMode rtm_mode = rt._rtm_mode;
00610       if (rtm_mode == RTM_bind_or_copy) {
00611         Texture *tex = rt._texture;
00612         if ((tex->get_format() != Texture::F_depth_stencil)&&
00613             (tex->get_format() != Texture::F_depth_component)&&
00614             (color_tex_index < 0)) {
00615           color_tex_index = i;
00616         } else {
00617           CDWriter cdataw(_cycler, cdata, false);
00618           nassertv(cdata->_textures.size() == cdataw->_textures.size());
00619           cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
00620         }
00621       }
00622     }
00623   }
00624 
00625   color_tex = get_texture(color_tex_index);
00626   if (color_tex) {
00627     color_ctx =
00628       DCAST(DXTextureContext9,
00629             color_tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg));
00630     color_cube = color_ctx->_d3d_cube_texture;
00631     if (color_cube && _cube_map_index >= 0 && _cube_map_index < 6) {
00632       hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf);
00633       if (!SUCCEEDED(hr)) {
00634         dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
00635       }
00636 
00637       hr = _dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, color_surf);
00638       if (!SUCCEEDED (hr)) {
00639         dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
00640       }
00641       else {
00642         color_surf->Release();
00643       }
00644     }
00645   }
00646 
00647   render_target_index = 1;
00648   for (int i=0; i<count_textures(); i++) {
00649 
00650     Texture *tex = get_texture(i);
00651     RenderTexturePlane plane = get_texture_plane(i);
00652 
00653     switch (plane) {
00654       case RTP_color:
00655         break;
00656       case RTP_aux_rgba_0:
00657       case RTP_aux_rgba_1:
00658       case RTP_aux_rgba_2:
00659       case RTP_aux_rgba_3:
00660       case RTP_aux_hrgba_0:
00661       case RTP_aux_hrgba_1:
00662       case RTP_aux_hrgba_2:
00663       case RTP_aux_hrgba_3:
00664       case RTP_aux_float_0:
00665       case RTP_aux_float_1:
00666       case RTP_aux_float_2:
00667       case RTP_aux_float_3:
00668         {
00669           DXTextureContext9 *color_ctx = 0;
00670           IDirect3DSurface9 *color_surf = 0;
00671           IDirect3DCubeTexture9 *color_cube = 0;
00672 
00673           color_ctx = DCAST(DXTextureContext9, tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg));
00674           if (color_ctx) {
00675             if (tex->get_texture_type() == Texture::TT_cube_map) {
00676 
00677               if (_debug) {
00678                 printf ("CUBEMAP i = %d, RenderTexturePlane = %d, _cube_map_index %d \n", i, plane, _cube_map_index);
00679               }
00680 
00681               color_cube = color_ctx->_d3d_cube_texture;
00682               if (color_cube && _cube_map_index >= 0 && _cube_map_index < 6) {
00683                 hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf);
00684                 if (!SUCCEEDED(hr)) {
00685                   dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
00686                 }
00687                 if (color_surf) {
00688                   hr = _dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, color_surf);
00689                   if (SUCCEEDED (hr)) {
00690                     render_target_index++;
00691                   } else {
00692                     dxgsg9_cat.error ( ) << "cube map SetRenderTarget " << render_target_index << " " << D3DERRORSTRING(hr) FL;
00693                   }
00694                   color_surf->Release();
00695                 }
00696               }
00697             }
00698           }
00699         }
00700         break;
00701 
00702       default:
00703         break;
00704     }    
00705   }
00706 }
00707 
00708 ////////////////////////////////////////////////////////////////////
00709 //     Function: wdxGraphicsBuffer9::process_events
00710 //       Access: Public, Virtual
00711 //  Description: Do whatever processing is necessary to ensure that
00712 //               the window responds to user events.  Also, honor any
00713 //               requests recently made via request_properties()
00714 //
00715 //               This function is called only within the window
00716 //               thread.
00717 ////////////////////////////////////////////////////////////////////
00718 void wdxGraphicsBuffer9::
00719 process_events() {
00720   GraphicsBuffer::process_events();
00721 
00722   MSG msg;
00723 
00724   // Handle all the messages on the queue in a row.  Some of these
00725   // might be for another window, but they will get dispatched
00726   // appropriately.
00727   while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
00728     process_1_event();
00729   }
00730 }
00731 
00732 ////////////////////////////////////////////////////////////////////
00733 //     Function: wdxGraphicsBuffer9::close_buffer
00734 //       Access: Protected, Virtual
00735 //  Description: Closes the buffer right now.  Called from the window
00736 //               thread.
00737 ////////////////////////////////////////////////////////////////////
00738 void wdxGraphicsBuffer9::
00739 close_buffer() {
00740 
00741   if (_color_backing_store) {
00742     _color_backing_store->Release();
00743     _color_backing_store = NULL;
00744   }
00745   if (_depth_backing_store) {
00746     _depth_backing_store->Release();
00747     _depth_backing_store = NULL;
00748   }
00749 
00750   _cube_map_index = -1;
00751   _is_valid = false;
00752 }
00753 
00754 ////////////////////////////////////////////////////////////////////
00755 //     Function: wdxGraphicsBuffer9::open_buffer
00756 //       Access: Protected, Virtual
00757 //  Description: Opens the window right now.  Called from the window
00758 //               thread.  Returns true if the window is successfully
00759 //               opened, or false if there was a problem.
00760 ////////////////////////////////////////////////////////////////////
00761 bool wdxGraphicsBuffer9::
00762 open_buffer() {
00763 
00764   // GSG creation/initialization.
00765   if (_gsg == 0) {
00766     // The code below doesn't support creating a GSG on the fly.
00767     // Just error out for now.
00768     //_dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
00769     //_gsg = _dxgsg;
00770     return false;
00771   }
00772    
00773   DCAST_INTO_R(_dxgsg, _gsg, false);
00774 
00775   if (!save_bitplanes()) {
00776     return false;
00777   }
00778 
00779   HRESULT hr;
00780   hr = _saved_color_buffer -> GetDesc (&_saved_color_desc);
00781   if (!SUCCEEDED (hr)) {
00782     dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
00783     return false;
00784   }
00785   hr = _saved_depth_buffer -> GetDesc (&_saved_depth_desc);
00786   if (!SUCCEEDED (hr)) {
00787     dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
00788     return false;
00789   }
00790   _fb_properties = _dxgsg->
00791     calc_fb_properties(_saved_color_desc.Format,
00792                        _saved_depth_desc.Format,
00793                        _saved_depth_desc.MultiSampleType,
00794                        _saved_depth_desc.MultiSampleQuality);
00795   _fb_properties.set_force_hardware(1); // Wild guess.
00796 
00797 
00798   if (!rebuild_bitplanes()) {
00799     restore_bitplanes();
00800     return false;
00801   }
00802 
00803   restore_bitplanes();
00804   return true;
00805 }
00806 
00807 ////////////////////////////////////////////////////////////////////
00808 //     Function: wdxGraphicsBuffer9::process_1_event
00809 //       Access: Private, Static
00810 //  Description: Handles one event from the message queue.
00811 ////////////////////////////////////////////////////////////////////
00812 void wdxGraphicsBuffer9::
00813 process_1_event() {
00814   MSG msg;
00815 
00816   if (!GetMessage(&msg, NULL, 0, 0)) {
00817     // WM_QUIT received.  We need a cleaner way to deal with this.
00818     //    DestroyAllWindows(false);
00819     exit(msg.wParam);  // this will invoke AtExitFn
00820   }
00821 
00822   // Translate virtual key messages
00823   TranslateMessage(&msg);
00824   // Call window_proc
00825   DispatchMessage(&msg);
00826 }
00827 
00828 
00829 
00830 
00831 ////////////////////////////////////////////////////////////////////
00832 //     Function: wdxGraphicsBuffer9::share_depth_buffer
00833 //       Access: Published 
00834 //  Description: Will attempt to use the depth buffer of the input
00835 //               graphics_output. The buffer sizes must be exactly 
00836 //               the same. 
00837 ////////////////////////////////////////////////////////////////////
00838 bool wdxGraphicsBuffer9::
00839 share_depth_buffer(GraphicsOutput *graphics_output) {
00840 
00841   bool state;
00842   wdxGraphicsBuffer9 *input_graphics_output;
00843   
00844   state = false;
00845   input_graphics_output = DCAST (wdxGraphicsBuffer9, graphics_output);
00846   if (this != input_graphics_output && input_graphics_output) {
00847 
00848     state = true;
00849     this -> unshare_depth_buffer();
00850 
00851     if (_debug) {
00852       printf ("share_depth_buffer\n");
00853     }
00854     
00855     // check buffer sizes
00856     if (this -> get_x_size() != input_graphics_output -> get_x_size()) {    
00857       if (_debug) {
00858         printf ("ERROR: share_depth_buffer: non matching width \n");
00859       }
00860       state = false;    
00861     }
00862 
00863     if (this -> get_y_size() != input_graphics_output -> get_y_size()) {     
00864       if (_debug) {
00865         printf ("ERROR: share_depth_buffer: non matching height \n");
00866       }
00867       state = false;    
00868     }
00869 
00870     if (state) {    
00871       // let the input GraphicsOutput know that there is an object 
00872       // sharing its depth buffer      
00873       input_graphics_output -> register_shared_depth_buffer(this);
00874       _shared_depth_buffer = input_graphics_output;
00875       state = true;
00876     }
00877   }
00878   
00879   return state;
00880 }
00881 
00882 ////////////////////////////////////////////////////////////////////
00883 //     Function: wdxGraphicsBuffer9::unshare_depth_buffer
00884 //       Access: Published 
00885 //  Description: Discontinue sharing the depth buffer.
00886 ////////////////////////////////////////////////////////////////////
00887 void wdxGraphicsBuffer9::
00888 unshare_depth_buffer() {
00889   if (_shared_depth_buffer) {
00890     if (_debug) {
00891       printf ("wdxGraphicsBuffer9 unshare_depth_buffer \n");
00892     }
00893     
00894     // let the GraphicsOutput know that this object is no longer
00895     // sharing its depth buffer
00896     _shared_depth_buffer -> unregister_shared_depth_buffer(this);  
00897     _shared_depth_buffer = 0;
00898   }
00899 }
00900 
00901 ////////////////////////////////////////////////////////////////////
00902 //     Function: wdxGraphicsBuffer9::register_shared_depth_buffer
00903 //       Access: Public
00904 //  Description: Register/save who is sharing the depth buffer.
00905 ////////////////////////////////////////////////////////////////////
00906 void wdxGraphicsBuffer9::
00907 register_shared_depth_buffer(GraphicsOutput *graphics_output) {
00908   wdxGraphicsBuffer9 *input_graphics_output;
00909   
00910   input_graphics_output = DCAST (wdxGraphicsBuffer9, graphics_output);
00911   if (input_graphics_output) {
00912     // add to list  
00913     _shared_depth_buffer_list.push_back(input_graphics_output);
00914   }
00915 }
00916 
00917 ////////////////////////////////////////////////////////////////////
00918 //     Function: wdxGraphicsBuffer9::unregister_shared_depth_buffer
00919 //       Access: Public
00920 //  Description: Unregister who is sharing the depth buffer.
00921 ////////////////////////////////////////////////////////////////////
00922 void wdxGraphicsBuffer9::
00923 unregister_shared_depth_buffer(GraphicsOutput *graphics_output) {
00924   wdxGraphicsBuffer9 *input_graphics_output;
00925   
00926   input_graphics_output = DCAST (wdxGraphicsBuffer9, graphics_output);
00927   if (input_graphics_output) {
00928     // remove from list  
00929     _shared_depth_buffer_list.remove(input_graphics_output);
00930   }
00931 }
 All Classes Functions Variables Enumerations