Repairs to DX buffers

This commit is contained in:
Josh Yelon 2006-06-08 17:52:57 +00:00
parent c7a4859e3c
commit 40db93b374
6 changed files with 531 additions and 606 deletions

View File

@ -119,8 +119,10 @@ process_events() {
return;
case OR_open:
open_buffer();
set_inverted(_gsg->get_copy_texture_inverted());
if (open_buffer()) {
_is_valid = true;
set_inverted(_gsg->get_copy_texture_inverted());
}
break;
case OR_close:

View File

@ -51,13 +51,12 @@ wdxGraphicsBuffer8(GraphicsPipe *pipe,
{
// initialize all class members
_cube_map_index = -1;
_back_buffer = NULL;
_z_stencil_buffer = NULL;
_direct_3d_surface = NULL;
_dx_texture_context8 = NULL;
_new_z_stencil_surface = NULL;
_saved_color_buffer = NULL;
_saved_depth_buffer = NULL;
_color_backing_store = NULL;
_depth_backing_store = NULL;
// is this correct ???
// is this correct ???
// Since the pbuffer never gets flipped, we get screenshots from the
// same buffer we draw into.
_screenshot_buffer_type = _draw_buffer_type;
@ -89,9 +88,18 @@ begin_frame(FrameMode mode, Thread *current_thread) {
if (_gsg == (GraphicsStateGuardian *)NULL) {
return false;
}
if (_dxgsg -> _d3d_device == 0) {
return false;
}
if (mode == FM_render) {
begin_render_texture();
if (!save_bitplanes()) {
return false;
}
if (!rebuild_bitplanes()) {
restore_bitplanes();
return false;
}
clear_cube_map_selection();
}
@ -113,7 +121,6 @@ end_frame(FrameMode mode, Thread *current_thread) {
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
if (mode == FM_render) {
end_render_texture();
copy_to_textures();
}
@ -125,138 +132,232 @@ end_frame(FrameMode mode, Thread *current_thread) {
prepare_for_deletion();
}
clear_cube_map_selection();
restore_bitplanes();
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::begin_render_texture
// Function: wglGraphicsStateGuardian::save_bitplanes
// Access: Public
// Description: If the GraphicsOutput supports direct render-to-texture,
// and if any setup needs to be done during begin_frame,
// then the setup code should go here. Any textures that
// can not be rendered to directly should be reflagged
// as RTM_copy_texture.
// Description: After rendering, d3d_device will need to be restored
// to its initial state. This function saves the state.
////////////////////////////////////////////////////////////////////
void wdxGraphicsBuffer8::
begin_render_texture() {
bool wdxGraphicsBuffer8::
save_bitplanes() {
HRESULT hr;
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian8 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
HRESULT hr;
bool state;
state = false;
if (dxgsg -> _d3d_device) {
Texture *tex = get_texture(0);
tex->set_render_to_texture(true);
TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg);
_dx_texture_context8 = DCAST (DXTextureContext8, tc);
// save render context
hr = dxgsg -> _d3d_device -> GetRenderTarget (&_back_buffer);
if (SUCCEEDED (hr)) {
hr = dxgsg -> _d3d_device -> GetDepthStencilSurface (&_z_stencil_buffer);
if (SUCCEEDED (hr)) {
state = true;
}
else {
dxgsg8_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
else {
dxgsg8_cat.error ( ) << "GetRenderTarget " << D3DERRORSTRING(hr) FL;
}
// set render context
if (state && _dx_texture_context8)
{
DXTextureContext8 *dx_texture_context8;
// use saved dx_texture_context8
dx_texture_context8 = _dx_texture_context8;
UINT mipmap_level;
mipmap_level = 0;
_direct_3d_surface = NULL;
// render to texture 2D
IDirect3DTexture8 *direct_3d_texture;
direct_3d_texture = dx_texture_context8 -> _d3d_2d_texture;
if (direct_3d_texture) {
hr = direct_3d_texture -> GetSurfaceLevel (mipmap_level, &_direct_3d_surface);
if (SUCCEEDED (hr)) {
IDirect3DSurface8 *z_stencil_buffer;
if (this -> _new_z_stencil_surface) {
z_stencil_buffer = this -> _new_z_stencil_surface;
}
else {
z_stencil_buffer = _z_stencil_buffer;
}
hr = dxgsg -> _d3d_device -> SetRenderTarget (_direct_3d_surface, z_stencil_buffer);
if (SUCCEEDED (hr)) {
} else {
dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
} else {
dxgsg8_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
}
}
}
}
hr = _dxgsg -> _d3d_device -> GetRenderTarget (&_saved_color_buffer);
if (!SUCCEEDED (hr)) {
dxgsg8_cat.error ( ) << "GetRenderTarget " << D3DERRORSTRING(hr) FL;
return false;
}
hr = _saved_color_buffer -> GetDesc (&_saved_color_desc);
if (!SUCCEEDED (hr)) {
dxgsg8_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
return false;
}
hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_saved_depth_buffer);
if (!SUCCEEDED (hr)) {
dxgsg8_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
return false;
}
hr = _saved_depth_buffer -> GetDesc (&_saved_depth_desc);
if (!SUCCEEDED (hr)) {
dxgsg8_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::end_render_texture
// Function: wglGraphicsStateGuardian::restore_bitplanes
// Access: Public
// Description: If the GraphicsOutput supports direct render-to-texture,
// and if any setup needs to be done during end_frame,
// then the setup code should go here. Any textures that
// could not be rendered to directly should be reflagged
// as RTM_copy_texture.
// Description: After rendering, d3d_device will need to be restored
// to its initial state. This function restores the state.
////////////////////////////////////////////////////////////////////
void wdxGraphicsBuffer8::
end_render_texture() {
restore_bitplanes() {
DXGraphicsStateGuardian8 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
if (_gsg != (GraphicsStateGuardian *)NULL) {
HRESULT hr;
hr = dxgsg -> _d3d_device ->
SetRenderTarget (_saved_color_buffer, _saved_depth_buffer);
if (!SUCCEEDED (hr)) {
dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
_saved_color_buffer->Release();
_saved_depth_buffer->Release();
_saved_color_buffer = NULL;
_saved_depth_buffer = NULL;
}
DXGraphicsStateGuardian8 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
if (dxgsg -> _d3d_device) {
// restore render context
HRESULT hr;
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::rebuild_bitplanes
// Access: Public
// Description: If necessary, reallocates (or allocates) the
// bitplanes for the buffer.
////////////////////////////////////////////////////////////////////
bool wdxGraphicsBuffer8::
rebuild_bitplanes() {
if (_back_buffer) {
hr = dxgsg -> _d3d_device -> SetRenderTarget (_back_buffer,
_z_stencil_buffer);
if (SUCCEEDED (hr)) {
_back_buffer -> Release ( );
} else {
dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
_back_buffer = NULL;
}
if (_z_stencil_buffer) {
_z_stencil_buffer -> Release ( );
_z_stencil_buffer = NULL;
}
if (_direct_3d_surface) {
_direct_3d_surface -> Release ( );
_direct_3d_surface = NULL;
HRESULT hr;
Texture *color_tex = 0;
Texture *depth_tex = 0;
DXTextureContext8 *color_ctx = 0;
DXTextureContext8 *depth_ctx = 0;
IDirect3DTexture8 *color_d3d_tex = 0;
IDirect3DTexture8 *depth_d3d_tex = 0;
IDirect3DCubeTexture8 *color_cube = 0;
IDirect3DCubeTexture8 *depth_cube = 0;
IDirect3DSurface8 *color_surf = 0;
IDirect3DSurface8 *depth_surf = 0;
// Decide how big the bitplanes should be.
int bitplane_x = _x_size;
int bitplane_y = _y_size;
if (!_gsg->get_supports_tex_non_pow2()) {
bitplane_x = Texture::up_to_power_2(bitplane_x);
bitplane_y = Texture::up_to_power_2(bitplane_y);
}
// Find the color and depth textures. Either may be present,
// or neither.
//
// NOTE: Currently, depth-stencil textures are not implemented,
// but since it's coming soon, we're structuring for it.
int color_tex_index = -1;
int depth_tex_index = -1;
for (int i=0; i<count_textures(); i++) {
if (get_rtm_mode(i) == RTM_bind_or_copy) {
if ((get_texture(i)->get_format() != Texture::F_depth_component)&&
(get_texture(i)->get_format() != Texture::F_stencil_index)&&
(color_tex_index < 0)) {
color_tex_index = i;
} else {
_textures[i]._rtm_mode = RTM_copy_texture;
}
}
}
if (color_tex_index < 0) {
// Maintain the backing color surface.
if ((_color_backing_store)&&
((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) {
_color_backing_store->Release();
_color_backing_store = NULL;
}
if (!_color_backing_store) {
hr = _dxgsg -> _d3d_device ->
CreateImageSurface(bitplane_x, bitplane_y, _saved_color_desc.Format, &_color_backing_store);
if (!SUCCEEDED(hr)) {
dxgsg8_cat.error ( ) << "CreateImageSurface " << D3DERRORSTRING(hr) FL;
}
}
color_surf = _color_backing_store;
} else {
// Maintain the color texture.
if (_color_backing_store) {
_color_backing_store->Release();
_color_backing_store = NULL;
}
color_tex = get_texture(color_tex_index);
color_tex->set_x_size(bitplane_x);
color_tex->set_y_size(bitplane_y);
color_tex->set_format(Texture::F_rgba);
color_ctx =
DCAST(DXTextureContext8,
color_tex->prepare_now(_gsg->get_prepared_objects(), _gsg));
if (color_tex->get_texture_type() == Texture::TT_2d_texture) {
color_d3d_tex = color_ctx->_d3d_2d_texture;
nassertr(color_d3d_tex != 0, false);
hr = color_d3d_tex -> GetSurfaceLevel(0, &color_surf);
if (!SUCCEEDED(hr)) {
dxgsg8_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
}
} else {
color_cube = color_ctx->_d3d_cube_texture;
nassertr(color_cube != 0, false);
hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf);
if (!SUCCEEDED(hr)) {
dxgsg8_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
}
}
}
if (depth_tex_index < 0) {
// Maintain the backing depth surface.
if ((_depth_backing_store)&&
((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) {
_depth_backing_store->Release();
_depth_backing_store = NULL;
}
if (!_depth_backing_store) {
hr = _dxgsg -> _d3d_device ->
CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format,
_saved_depth_desc.MultiSampleType, &_depth_backing_store);
if (!SUCCEEDED(hr)) {
dxgsg8_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
depth_surf = _depth_backing_store;
} else {
// Maintain the depth texture.
if (_depth_backing_store) {
_depth_backing_store->Release();
_depth_backing_store = NULL;
}
depth_tex = get_texture(depth_tex_index);
depth_tex->set_x_size(bitplane_x);
depth_tex->set_y_size(bitplane_y);
depth_tex->set_format(Texture::F_depth_component); // Should say depth_stencil
depth_ctx =
DCAST(DXTextureContext8,
depth_tex->prepare_now(_gsg->get_prepared_objects(), _gsg));
if (depth_tex->get_texture_type() == Texture::TT_2d_texture) {
depth_d3d_tex = depth_ctx->_d3d_2d_texture;
nassertr(depth_d3d_tex != 0, false);
hr = color_d3d_tex -> GetSurfaceLevel(0, &depth_surf);
if (!SUCCEEDED(hr)) {
dxgsg8_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
}
} else {
depth_cube = depth_ctx->_d3d_cube_texture;
nassertr(depth_cube != 0, false);
hr = depth_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &depth_surf);
if (!SUCCEEDED(hr)) {
dxgsg8_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
}
}
}
_backing_sizex = bitplane_x;
_backing_sizey = bitplane_y;
// Load up the bitplanes.
hr = _dxgsg -> _d3d_device -> SetRenderTarget (color_surf, depth_surf);
if (!SUCCEEDED (hr)) {
dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
// Decrement the reference counts on these surfaces. The refcounts
// were incremented earlier when we called GetSurfaceLevel.
if ((color_surf != 0)&&(color_surf != _color_backing_store)) {
color_surf->Release();
}
if ((depth_surf != 0)&&(depth_surf != _depth_backing_store)) {
depth_surf->Release();
}
return true;
}
////////////////////////////////////////////////////////////////////
@ -270,63 +371,7 @@ end_render_texture() {
////////////////////////////////////////////////////////////////////
void wdxGraphicsBuffer8::
select_cube_map(int cube_map_index) {
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian8 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
_cube_map_index = cube_map_index;
HRESULT hr;
UINT mipmap_level;
int render_target_index;
DXTextureContext8 *dx_texture_context8;
mipmap_level = 0;
render_target_index = 0;
dx_texture_context8 = _dx_texture_context8;
if (_direct_3d_surface) {
_direct_3d_surface -> Release ( );
_direct_3d_surface = NULL;
}
if (dxgsg -> _d3d_device) {
// render to cubemap face
IDirect3DCubeTexture8 *direct_3d_cube_texture;
direct_3d_cube_texture = dx_texture_context8 -> _d3d_cube_texture;
if (direct_3d_cube_texture) {
if (_cube_map_index >= 0 && _cube_map_index < 6) {
hr = direct_3d_cube_texture -> GetCubeMapSurface (
(D3DCUBEMAP_FACES) _cube_map_index, mipmap_level, &_direct_3d_surface);
if (SUCCEEDED (hr)) {
IDirect3DSurface8 *z_stencil_buffer;
if (this -> _new_z_stencil_surface) {
z_stencil_buffer = this -> _new_z_stencil_surface;
}
else {
z_stencil_buffer = _z_stencil_buffer;
}
hr = dxgsg -> _d3d_device -> SetRenderTarget (_direct_3d_surface, z_stencil_buffer);
if (SUCCEEDED (hr)) {
} else {
dxgsg8_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
} else {
dxgsg8_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
}
} else {
dxgsg8_cat.error ( ) << "Invalid Cube Map Face Index " << _cube_map_index FL;
}
}
}
}
_cube_map_index = cube_map_index;
}
////////////////////////////////////////////////////////////////////
@ -363,23 +408,20 @@ void wdxGraphicsBuffer8::
close_buffer() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian8 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
_dx_texture_context8 = NULL;
// release new depth stencil buffer if one was created
if (this -> _new_z_stencil_surface) {
this -> _new_z_stencil_surface -> Release ( );
this -> _new_z_stencil_surface = NULL;
}
_gsg.clear();
_active = false;
}
if (_color_backing_store) {
_color_backing_store->Release();
_color_backing_store = NULL;
}
if (_depth_backing_store) {
_depth_backing_store->Release();
_depth_backing_store = NULL;
}
_active = false;
_cube_map_index = -1;
_is_valid = false;
}
@ -392,97 +434,26 @@ close_buffer() {
////////////////////////////////////////////////////////////////////
bool wdxGraphicsBuffer8::
open_buffer() {
bool state;
// GSG creation/initialization.
if (_gsg == 0) {
_dxgsg = new DXGraphicsStateGuardian8(_pipe);
_gsg = _dxgsg;
} else {
DCAST_INTO_R(_dxgsg, _gsg, false);
}
if (!save_bitplanes()) {
return false;
}
// create texture
int tex_index;
state = false;
_is_valid = false;
// assume tex_index is 0
tex_index = 0;
Texture *tex = get_texture(tex_index);
// render to texture must be set
tex->set_render_to_texture(true);
TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg);
if (tc != NULL) {
HRESULT hr;
IDirect3DSurface8 *_depth_stencil_surface;
_dx_texture_context8 = DCAST (DXTextureContext8, tc);
// create a depth stencil buffer if needed
hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_depth_stencil_surface);
if (SUCCEEDED (hr))
{
D3DSURFACE_DESC surface_description;
// get and copy the current depth stencil's parameters for the new buffer
hr = _depth_stencil_surface -> GetDesc (&surface_description);
if (SUCCEEDED (hr)) {
UINT width;
UINT height;
D3DFORMAT format;
D3DMULTISAMPLE_TYPE multisample_type;
// DWORD multisample_quality;
BOOL discard;
width = tex -> get_x_size ( );
height = tex -> get_y_size ( );
// dxgsg8_cat.error ( ) << "-------------RTT SIZE " << "t width " << width << " t height " << height << "\n";
if (surface_description.Width < width || surface_description.Height < height) {
format = surface_description.Format;
multisample_type = surface_description.MultiSampleType;
// multisample_quality = surface_description.MultiSampleQuality;
discard = false;
hr = _dxgsg -> _d3d_device -> CreateDepthStencilSurface (
width, height, format, multisample_type, /* multisample_quality,
discard, */ &this -> _new_z_stencil_surface);
if (SUCCEEDED (hr)) {
// dxgsg8_cat.error ( ) << "-------------CreatedDepthStencilSurface for RTT \n";
state = true;
} else {
dxgsg8_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
else {
// no need to create a separate depth stencil buffer since
// the current depth stencil buffer size is big enough
state = true;
}
}
else {
dxgsg8_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
}
_depth_stencil_surface -> Release ( );
}
else {
dxgsg8_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
if (state) {
_is_valid = true;
}
if (!rebuild_bitplanes()) {
restore_bitplanes();
return false;
}
return state;
restore_bitplanes();
return true;
}
////////////////////////////////////////////////////////////////////

View File

@ -56,18 +56,21 @@ protected:
virtual bool open_buffer();
private:
void begin_render_texture();
void end_render_texture();
bool save_bitplanes();
bool rebuild_bitplanes();
void restore_bitplanes();
static void process_1_event();
int _cube_map_index;
DXGraphicsStateGuardian8 *_dxgsg;
IDirect3DSurface8 *_back_buffer;
IDirect3DSurface8 *_z_stencil_buffer;
IDirect3DSurface8 *_direct_3d_surface;
DXTextureContext8 *_dx_texture_context8;
IDirect3DSurface8 *_new_z_stencil_surface;
IDirect3DSurface8 *_saved_color_buffer;
IDirect3DSurface8 *_saved_depth_buffer;
D3DSURFACE_DESC _saved_color_desc;
D3DSURFACE_DESC _saved_depth_desc;
IDirect3DSurface8 *_color_backing_store;
IDirect3DSurface8 *_depth_backing_store;
int _backing_sizex;
int _backing_sizey;
public:
static TypeHandle get_class_type() {

View File

@ -275,6 +275,8 @@ open_window() {
if (_gsg == 0) {
_dxgsg = new DXGraphicsStateGuardian8(_pipe);
_gsg = _dxgsg;
} else {
DCAST_INTO_R(_dxgsg, _gsg, false);
}
if (!choose_device()) {

View File

@ -1,10 +1,10 @@
// Filename: wdxGraphicsBuffer9.cxx
// Filename: wdxGraphicsBuffer8.cxx
// Created by: drose (08Feb04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2006, Disney Enterprises, Inc. All rights reserved
// Copyright (c) 2001 - 2005, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
@ -21,8 +21,11 @@
#include "dxGraphicsStateGuardian9.h"
#include "pStatTimer.h"
// ISSUES:
// render to texure format
// can be specified via the DXGraphicsStateGuardian8 member
// _render_to_texture_d3d_format default = D3DFMT_X8R8G8B8
// should check texture creation with CheckDepthStencilMatch
// support copy from texture to ram?
// check D3DCAPS2_DYNAMICTEXTURES
@ -40,19 +43,18 @@ TypeHandle wdxGraphicsBuffer9::_type_handle;
wdxGraphicsBuffer9::
wdxGraphicsBuffer9(GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &prop,
const FrameBufferProperties &properties,
int x_size, int y_size, int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host):
GraphicsBuffer(pipe, name, prop, x_size, y_size, flags, gsg, host)
GraphicsBuffer(pipe, name, properties, x_size, y_size, flags, gsg, host)
{
// initialize all class members
_cube_map_index = -1;
_back_buffer = NULL;
_z_stencil_buffer = NULL;
_direct_3d_surface = NULL;
_dx_texture_context9 = NULL;
_new_z_stencil_surface = NULL;
_saved_color_buffer = NULL;
_saved_depth_buffer = NULL;
_color_backing_store = NULL;
_depth_backing_store = NULL;
// is this correct ???
// Since the pbuffer never gets flipped, we get screenshots from the
@ -81,15 +83,23 @@ wdxGraphicsBuffer9::
////////////////////////////////////////////////////////////////////
bool wdxGraphicsBuffer9::
begin_frame(FrameMode mode, Thread *current_thread) {
DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::begin_frame\n"; DBG_E
begin_frame_spam();
if (_gsg == (GraphicsStateGuardian *)NULL) {
return false;
}
if (_dxgsg -> _d3d_device == 0) {
return false;
}
if (mode == FM_render) {
begin_render_texture();
if (!save_bitplanes()) {
return false;
}
if (!rebuild_bitplanes()) {
restore_bitplanes();
return false;
}
clear_cube_map_selection();
}
@ -111,7 +121,6 @@ end_frame(FrameMode mode, Thread *current_thread) {
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
if (mode == FM_render) {
end_render_texture();
copy_to_textures();
}
@ -123,162 +132,242 @@ end_frame(FrameMode mode, Thread *current_thread) {
prepare_for_deletion();
}
clear_cube_map_selection();
restore_bitplanes();
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::begin_render_texture
// Function: wglGraphicsStateGuardian::save_bitplanes
// Access: Public
// Description: If the GraphicsOutput supports direct render-to-texture,
// and if any setup needs to be done during begin_frame,
// then the setup code should go here. Any textures that
// can not be rendered to directly should be reflagged
// as RTM_copy_texture.
// Description: After rendering, d3d_device will need to be restored
// to its initial state. This function saves the state.
////////////////////////////////////////////////////////////////////
void wdxGraphicsBuffer9::
begin_render_texture() {
bool wdxGraphicsBuffer9::
save_bitplanes() {
HRESULT hr;
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian9 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
HRESULT hr;
bool state;
int render_target_index;
state = false;
render_target_index = 0;
DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::begin_render_texture\n"; DBG_E
if (dxgsg -> _d3d_device) {
Texture *tex = get_texture(0);
tex->set_render_to_texture(true);
TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg);
_dx_texture_context9 = DCAST (DXTextureContext9, tc);
// save render context
hr = dxgsg -> _d3d_device -> GetRenderTarget (render_target_index, &_back_buffer);
if (SUCCEEDED (hr)) {
hr = dxgsg -> _d3d_device -> GetDepthStencilSurface (&_z_stencil_buffer);
if (SUCCEEDED (hr)) {
state = true;
}
else {
dxgsg9_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
else {
dxgsg9_cat.error ( ) << "GetRenderTarget " << D3DERRORSTRING(hr) FL;
}
// set render context
if (state && _dx_texture_context9)
{
DXTextureContext9 *dx_texture_context9;
// use saved dx_texture_context9
dx_texture_context9 = _dx_texture_context9;
UINT mipmap_level;
mipmap_level = 0;
_direct_3d_surface = NULL;
// render to texture 2D
IDirect3DTexture9 *direct_3d_texture;
direct_3d_texture = dx_texture_context9 -> _d3d_2d_texture;
if (direct_3d_texture) {
// Make sure texturing is fully disabled (and all of our
// textures are therefore unbound in the GSG) before we try
// to render to this texture.
dxgsg->disable_texturing();
hr = direct_3d_texture -> GetSurfaceLevel (mipmap_level, &_direct_3d_surface);
if (SUCCEEDED (hr)) {
hr = dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, _direct_3d_surface);
if (SUCCEEDED (hr)) {
if (this -> _new_z_stencil_surface) {
hr = dxgsg -> _d3d_device -> SetDepthStencilSurface (this -> _new_z_stencil_surface);
if (SUCCEEDED (hr)) {
} else {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
} else {
hr = dxgsg -> _d3d_device -> SetDepthStencilSurface (_z_stencil_buffer);
if (SUCCEEDED (hr)) {
} else {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
} else {
dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
} else {
dxgsg9_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
}
}
}
}
hr = _dxgsg -> _d3d_device -> GetRenderTarget (0, &_saved_color_buffer);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "GetRenderTarget " << D3DERRORSTRING(hr) FL;
return false;
}
hr = _saved_color_buffer -> GetDesc (&_saved_color_desc);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
return false;
}
hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_saved_depth_buffer);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
return false;
}
hr = _saved_depth_buffer -> GetDesc (&_saved_depth_desc);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::end_render_texture
// Function: wglGraphicsStateGuardian::restore_bitplanes
// Access: Public
// Description: If the GraphicsOutput supports direct render-to-texture,
// and if any setup needs to be done during end_frame,
// then the setup code should go here. Any textures that
// could not be rendered to directly should be reflagged
// as RTM_copy_texture.
// Description: After rendering, d3d_device will need to be restored
// to its initial state. This function restores the state.
////////////////////////////////////////////////////////////////////
void wdxGraphicsBuffer9::
end_render_texture() {
restore_bitplanes() {
DXGraphicsStateGuardian9 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::end_render_texture\n"; DBG_E
HRESULT hr;
hr = dxgsg -> _d3d_device ->
SetRenderTarget (0, _saved_color_buffer);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
hr = _dxgsg -> _d3d_device -> SetDepthStencilSurface (_saved_depth_buffer);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
_saved_color_buffer->Release();
_saved_depth_buffer->Release();
_saved_color_buffer = NULL;
_saved_depth_buffer = NULL;
}
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian9 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::rebuild_bitplanes
// Access: Public
// Description: If necessary, reallocates (or allocates) the
// bitplanes for the buffer.
////////////////////////////////////////////////////////////////////
bool wdxGraphicsBuffer9::
rebuild_bitplanes() {
if (dxgsg -> _d3d_device) {
// restore render context
HRESULT hr;
int render_target_index;
HRESULT hr;
Texture *color_tex = 0;
Texture *depth_tex = 0;
DXTextureContext9 *color_ctx = 0;
DXTextureContext9 *depth_ctx = 0;
IDirect3DTexture9 *color_d3d_tex = 0;
IDirect3DTexture9 *depth_d3d_tex = 0;
IDirect3DCubeTexture9 *color_cube = 0;
IDirect3DCubeTexture9 *depth_cube = 0;
IDirect3DSurface9 *color_surf = 0;
IDirect3DSurface9 *depth_surf = 0;
render_target_index = 0;
// Decide how big the bitplanes should be.
if (_back_buffer) {
hr = dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, _back_buffer);
if (SUCCEEDED (hr)) {
_back_buffer -> Release ( );
} else {
dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
_back_buffer = NULL;
}
if (_z_stencil_buffer) {
hr = dxgsg -> _d3d_device -> SetDepthStencilSurface (_z_stencil_buffer);
if (SUCCEEDED (hr)) {
_z_stencil_buffer -> Release ( );
} else {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
_z_stencil_buffer = NULL;
}
if (_direct_3d_surface) {
_direct_3d_surface -> Release ( );
_direct_3d_surface = NULL;
int bitplane_x = _x_size;
int bitplane_y = _y_size;
if (!_gsg->get_supports_tex_non_pow2()) {
bitplane_x = Texture::up_to_power_2(bitplane_x);
bitplane_y = Texture::up_to_power_2(bitplane_y);
}
// Find the color and depth textures. Either may be present,
// or neither.
//
// NOTE: Currently, depth-stencil textures are not implemented,
// but since it's coming soon, we're structuring for it.
int color_tex_index = -1;
int depth_tex_index = -1;
for (int i=0; i<count_textures(); i++) {
if (get_rtm_mode(i) == RTM_bind_or_copy) {
if ((get_texture(i)->get_format() != Texture::F_depth_component)&&
(get_texture(i)->get_format() != Texture::F_stencil_index)&&
(color_tex_index < 0)) {
color_tex_index = i;
} else {
_textures[i]._rtm_mode = RTM_copy_texture;
}
}
}
if (color_tex_index < 0) {
// Maintain the backing color surface.
if ((_color_backing_store)&&
((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) {
_color_backing_store->Release();
_color_backing_store = NULL;
}
if (!_color_backing_store) {
hr = _dxgsg -> _d3d_device ->
CreateOffscreenPlainSurface(bitplane_x, bitplane_y, _saved_color_desc.Format,
D3DPOOL_DEFAULT, &_color_backing_store, NULL);
if (!SUCCEEDED(hr)) {
dxgsg9_cat.error ( ) << "CreateImageSurface " << D3DERRORSTRING(hr) FL;
}
}
color_surf = _color_backing_store;
} else {
// Maintain the color texture.
if (_color_backing_store) {
_color_backing_store->Release();
_color_backing_store = NULL;
}
color_tex = get_texture(color_tex_index);
color_tex->set_x_size(bitplane_x);
color_tex->set_y_size(bitplane_y);
color_tex->set_format(Texture::F_rgba);
color_ctx =
DCAST(DXTextureContext9,
color_tex->prepare_now(_gsg->get_prepared_objects(), _gsg));
if (color_tex->get_texture_type() == Texture::TT_2d_texture) {
color_d3d_tex = color_ctx->_d3d_2d_texture;
nassertr(color_d3d_tex != 0, false);
hr = color_d3d_tex -> GetSurfaceLevel(0, &color_surf);
if (!SUCCEEDED(hr)) {
dxgsg9_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
}
} else {
color_cube = color_ctx->_d3d_cube_texture;
nassertr(color_cube != 0, false);
hr = color_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &color_surf);
if (!SUCCEEDED(hr)) {
dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
}
}
}
if (depth_tex_index < 0) {
// Maintain the backing depth surface.
if ((_depth_backing_store)&&
((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) {
_depth_backing_store->Release();
_depth_backing_store = NULL;
}
if (!_depth_backing_store) {
hr = _dxgsg -> _d3d_device ->
CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format,
_saved_depth_desc.MultiSampleType, _saved_depth_desc.MultiSampleQuality,
false, &_depth_backing_store, NULL);
if (!SUCCEEDED(hr)) {
dxgsg9_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
depth_surf = _depth_backing_store;
} else {
// Maintain the depth texture.
if (_depth_backing_store) {
_depth_backing_store->Release();
_depth_backing_store = NULL;
}
depth_tex = get_texture(depth_tex_index);
depth_tex->set_x_size(bitplane_x);
depth_tex->set_y_size(bitplane_y);
depth_tex->set_format(Texture::F_depth_component); // Should say depth_stencil
depth_ctx =
DCAST(DXTextureContext9,
depth_tex->prepare_now(_gsg->get_prepared_objects(), _gsg));
if (depth_tex->get_texture_type() == Texture::TT_2d_texture) {
depth_d3d_tex = depth_ctx->_d3d_2d_texture;
nassertr(depth_d3d_tex != 0, false);
hr = color_d3d_tex -> GetSurfaceLevel(0, &depth_surf);
if (!SUCCEEDED(hr)) {
dxgsg9_cat.error ( ) << "GetSurfaceLevel " << D3DERRORSTRING(hr) FL;
}
} else {
depth_cube = depth_ctx->_d3d_cube_texture;
nassertr(depth_cube != 0, false);
hr = depth_cube -> GetCubeMapSurface ((D3DCUBEMAP_FACES) _cube_map_index, 0, &depth_surf);
if (!SUCCEEDED(hr)) {
dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
}
}
}
_backing_sizex = bitplane_x;
_backing_sizey = bitplane_y;
// Load up the bitplanes.
hr = _dxgsg -> _d3d_device -> SetRenderTarget (0, color_surf);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
hr = _dxgsg -> _d3d_device -> SetDepthStencilSurface (depth_surf);
if (!SUCCEEDED (hr)) {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
// Decrement the reference counts on these surfaces. The refcounts
// were incremented earlier when we called GetSurfaceLevel.
if ((color_surf != 0)&&(color_surf != _color_backing_store)) {
color_surf->Release();
}
if ((depth_surf != 0)&&(depth_surf != _depth_backing_store)) {
depth_surf->Release();
}
return true;
}
////////////////////////////////////////////////////////////////////
@ -292,77 +381,7 @@ DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::end_render_texture\n"; DBG_E
////////////////////////////////////////////////////////////////////
void wdxGraphicsBuffer9::
select_cube_map(int cube_map_index) {
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian9 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
_cube_map_index = cube_map_index;
HRESULT hr;
UINT mipmap_level;
int render_target_index;
DXTextureContext9 *dx_texture_context9;
mipmap_level = 0;
render_target_index = 0;
dx_texture_context9 = _dx_texture_context9;
if (_direct_3d_surface) {
_direct_3d_surface -> Release ( );
_direct_3d_surface = NULL;
}
if (dxgsg -> _d3d_device) {
// render to cubemap face
IDirect3DCubeTexture9 *direct_3d_cube_texture;
direct_3d_cube_texture = dx_texture_context9 -> _d3d_cube_texture;
if (direct_3d_cube_texture) {
if (_cube_map_index >= 0 && _cube_map_index < 6) {
hr = direct_3d_cube_texture -> GetCubeMapSurface (
(D3DCUBEMAP_FACES) _cube_map_index, mipmap_level, &_direct_3d_surface);
if (SUCCEEDED (hr)) {
// Make sure texturing is fully disabled (and all of our
// textures are therefore unbound in the GSG) before we try
// to render to this texture.
dxgsg->disable_texturing();
hr = dxgsg -> _d3d_device -> SetRenderTarget (render_target_index, _direct_3d_surface);
if (SUCCEEDED (hr)) {
if (this -> _new_z_stencil_surface) {
hr = dxgsg -> _d3d_device -> SetDepthStencilSurface (_new_z_stencil_surface);
if (SUCCEEDED (hr)) {
} else {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
} else {
hr = dxgsg -> _d3d_device -> SetDepthStencilSurface (_z_stencil_buffer);
if (SUCCEEDED (hr)) {
} else {
dxgsg9_cat.error ( ) << "SetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
DBG_S dxgsg9_cat.debug ( ) << "select_cube_map " << _cube_map_index << "\n"; DBG_E
} else {
dxgsg9_cat.error ( ) << "SetRenderTarget " << D3DERRORSTRING(hr) FL;
}
} else {
dxgsg9_cat.error ( ) << "GetCubeMapSurface " << D3DERRORSTRING(hr) FL;
}
} else {
dxgsg9_cat.error ( ) << "Invalid Cube Map Face Index " << _cube_map_index FL;
}
}
}
}
_cube_map_index = cube_map_index;
}
////////////////////////////////////////////////////////////////////
@ -399,23 +418,20 @@ void wdxGraphicsBuffer9::
close_buffer() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
DXGraphicsStateGuardian9 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
_dx_texture_context9 = NULL;
// release new depth stencil buffer if one was created
if (this -> _new_z_stencil_surface) {
this -> _new_z_stencil_surface -> Release ( );
this -> _new_z_stencil_surface = NULL;
}
_gsg.clear();
_active = false;
}
if (_color_backing_store) {
_color_backing_store->Release();
_color_backing_store = NULL;
}
if (_depth_backing_store) {
_depth_backing_store->Release();
_depth_backing_store = NULL;
}
_active = false;
_cube_map_index = -1;
_is_valid = false;
}
@ -428,97 +444,26 @@ close_buffer() {
////////////////////////////////////////////////////////////////////
bool wdxGraphicsBuffer9::
open_buffer() {
bool state;
// GSG creation/initialization.
if (_gsg == 0) {
_dxgsg = new DXGraphicsStateGuardian9(_pipe);
_gsg = _dxgsg;
} else {
DCAST_INTO_R(_dxgsg, _gsg, false);
}
if (!save_bitplanes()) {
return false;
}
// create texture
int tex_index;
state = false;
_is_valid = false;
// assume tex_index is 0
tex_index = 0;
Texture *tex = get_texture(tex_index);
// render to texture must be set
tex->set_render_to_texture(true);
TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg);
if (tc != NULL) {
HRESULT hr;
IDirect3DSurface9 *_depth_stencil_surface;
_dx_texture_context9 = DCAST (DXTextureContext9, tc);
// create a depth stencil buffer if needed
hr = _dxgsg -> _d3d_device -> GetDepthStencilSurface (&_depth_stencil_surface);
if (SUCCEEDED (hr))
{
D3DSURFACE_DESC surface_description;
// get and copy the current depth stencil's parameters for the new buffer
hr = _depth_stencil_surface -> GetDesc (&surface_description);
if (SUCCEEDED (hr)) {
UINT width;
UINT height;
D3DFORMAT format;
D3DMULTISAMPLE_TYPE multisample_type;
DWORD multisample_quality;
BOOL discard;
width = tex -> get_x_size ( );
height = tex -> get_y_size ( );
DBG_S dxgsg9_cat.debug ( ) << "-------------RTT SIZE " << "t width " << width << " t height " << height FL; DBG_E
if (surface_description.Width < width || surface_description.Height < height) {
format = surface_description.Format;
multisample_type = surface_description.MultiSampleType;
multisample_quality = surface_description.MultiSampleQuality;
discard = false;
hr = _dxgsg -> _d3d_device -> CreateDepthStencilSurface (
width, height, format, multisample_type, multisample_quality,
discard, &this -> _new_z_stencil_surface, NULL);
if (SUCCEEDED (hr)) {
DBG_S dxgsg9_cat.debug ( ) << "-------------OK CreatedDepthStencilSurface " << D3DERRORSTRING(hr) FL; DBG_E
state = true;
} else {
dxgsg9_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
}
else {
// no need to create a separate depth stencil buffer since
// the current depth stencil buffer size is big enough
state = true;
}
}
else {
dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL;
}
_depth_stencil_surface -> Release ( );
}
else {
dxgsg9_cat.error ( ) << "GetDepthStencilSurface " << D3DERRORSTRING(hr) FL;
}
if (state) {
_is_valid = true;
}
if (!rebuild_bitplanes()) {
restore_bitplanes();
return false;
}
return state;
restore_bitplanes();
return true;
}
////////////////////////////////////////////////////////////////////
@ -541,4 +486,3 @@ process_1_event() {
// Call window_proc
DispatchMessage(&msg);
}

View File

@ -55,18 +55,21 @@ protected:
virtual bool open_buffer();
private:
void begin_render_texture();
void end_render_texture();
bool save_bitplanes();
bool rebuild_bitplanes();
void restore_bitplanes();
static void process_1_event();
int _cube_map_index;
DXGraphicsStateGuardian9 *_dxgsg;
IDirect3DSurface9 *_back_buffer;
IDirect3DSurface9 *_z_stencil_buffer;
IDirect3DSurface9 *_direct_3d_surface;
DXTextureContext9 *_dx_texture_context9;
IDirect3DSurface9 *_new_z_stencil_surface;
IDirect3DSurface9 *_saved_color_buffer;
IDirect3DSurface9 *_saved_depth_buffer;
D3DSURFACE_DESC _saved_color_desc;
D3DSURFACE_DESC _saved_depth_desc;
IDirect3DSurface9 *_color_backing_store;
IDirect3DSurface9 *_depth_backing_store;
int _backing_sizex;
int _backing_sizey;
public:
static TypeHandle get_class_type() {