diff --git a/panda/src/dxgsg8/Sources.pp b/panda/src/dxgsg8/Sources.pp index fc3da241f2..58b35138c5 100644 --- a/panda/src/dxgsg8/Sources.pp +++ b/panda/src/dxgsg8/Sources.pp @@ -38,7 +38,8 @@ dxTextureContext8.cxx \ dxGeomMunger8.cxx \ dxGraphicsDevice8.cxx \ - wdxGraphicsPipe8.cxx wdxGraphicsWindow8.cxx - + wdxGraphicsPipe8.cxx \ + wdxGraphicsWindow8.cxx \ + wdxGraphicsBuffer8.cxx #end lib_target diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 3475945be0..cf776991c6 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -111,12 +111,15 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) : // D3DRS_POINTSPRITEENABLE doesn't seem to support remapping the // texture coordinates via a texture matrix, so we don't advertise // GR_point_sprite_tex_matrix. - _supported_geom_rendering = + _supported_geom_rendering = Geom::GR_point | Geom::GR_point_uniform_size | Geom::GR_point_perspective | Geom::GR_point_sprite | Geom::GR_indexed_other | Geom::GR_triangle_strip | Geom::GR_triangle_fan | Geom::GR_flat_first_vertex; + + // default render to texture format + _render_to_texture_d3d_format = D3DFMT_X8R8G8B8; } //////////////////////////////////////////////////////////////////// @@ -182,20 +185,20 @@ apply_texture(int i, TextureContext *tc) { // If the texture image has changed, or if its use of mipmaps has // changed, we need to re-create the image. Ignore other types of // changes, which aren't significant for DX. - + if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) { // If this is *only* because of a mipmap change, issue a // warning--it is likely that this change is the result of an // error or oversight. if ((dirty & Texture::DF_image) == 0) { dxgsg8_cat.warning() - << "Texture " << *dtc->_texture << " has changed mipmap state.\n"; + << "Texture " << *dtc->_texture << " has changed mipmap state.\n"; } - + if (!dtc->create_texture(*_screen)) { // Oops, we can't re-create the texture for some reason. dxgsg8_cat.error() - << "Unable to re-create texture " << *dtc->_texture << endl; + << "Unable to re-create texture " << *dtc->_texture << endl; _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE); return; } @@ -211,8 +214,8 @@ apply_texture(int i, TextureContext *tc) { _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSV, get_texture_wrap_mode(wrap_v)); _d3d_device->SetTextureStageState(i, D3DTSS_ADDRESSW, get_texture_wrap_mode(wrap_w)); - _d3d_device->SetTextureStageState(i, D3DTSS_BORDERCOLOR, - Colorf_to_D3DCOLOR(tex->get_border_color())); + _d3d_device->SetTextureStageState(i, D3DTSS_BORDERCOLOR, + Colorf_to_D3DCOLOR(tex->get_border_color())); uint aniso_degree = tex->get_anisotropic_degree(); Texture::FilterType ft = tex->get_magfilter(); @@ -351,7 +354,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) { HRESULT hr = _d3d_device->SetVertexShader(dvbc->_fvf); #ifndef NDEBUG if (FAILED(hr)) { - dxgsg8_cat.error() + dxgsg8_cat.error() << "SetVertexShader(0x" << (void*)dvbc->_fvf << ") failed" << D3DERRORSTRING(hr); } @@ -622,7 +625,7 @@ prepare_lens() { // The projection matrix must always be left-handed Y-up internally, // to match DirectX's convention, even if our coordinate system of // choice is otherwise. - const LMatrix4f &convert_mat = + const LMatrix4f &convert_mat = LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()); // DirectX also uses a Z range of 0 to 1, whereas the Panda @@ -643,7 +646,7 @@ prepare_lens() { _projection_mat *= invert_mat; } - HRESULT hr = + HRESULT hr = _d3d_device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)_projection_mat.get_data()); return SUCCEEDED(hr); @@ -795,7 +798,7 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger, nassertr(vbc != (VertexBufferContext *)NULL, false); apply_vertex_buffer(vbc); - const GeomVertexAnimationSpec &animation = + const GeomVertexAnimationSpec &animation = vertex_data->get_format()->get_animation(); if (animation.get_animation_type() == Geom::AT_hardware) { // Set up vertex blending. @@ -928,10 +931,10 @@ draw_triangles(const GeomTriangles *primitive) { // Nonindexed, client arrays. draw_primitive_up(D3DPT_TRIANGLELIST, primitive->get_num_primitives(), - primitive->get_first_vertex(), - primitive->get_num_vertices(), - _vertex_data->get_array(0)->get_data(), - _vertex_data->get_format()->get_array(0)->get_stride()); + primitive->get_first_vertex(), + primitive->get_num_vertices(), + _vertex_data->get_array(0)->get_data(), + _vertex_data->get_format()->get_array(0)->get_stride()); } } } @@ -966,7 +969,7 @@ draw_tristrips(const GeomTristrips *primitive) { } else { // Indexed, client arrays, one long triangle strip. D3DFORMAT index_type = get_index_type(primitive->get_index_type()); - draw_indexed_primitive_up + draw_indexed_primitive_up (D3DPT_TRIANGLESTRIP, min_vertex, max_vertex, primitive->get_num_vertices() - 2, @@ -984,12 +987,12 @@ draw_tristrips(const GeomTristrips *primitive) { } else { // Indexed, client arrays, one long triangle strip. - draw_primitive_up(D3DPT_TRIANGLESTRIP, - primitive->get_num_vertices() - 2, - primitive->get_first_vertex(), - primitive->get_num_vertices(), - _vertex_data->get_array(0)->get_data(), - _vertex_data->get_format()->get_array(0)->get_stride()); + draw_primitive_up(D3DPT_TRIANGLESTRIP, + primitive->get_num_vertices() - 2, + primitive->get_first_vertex(), + primitive->get_num_vertices(), + _vertex_data->get_array(0)->get_data(), + _vertex_data->get_format()->get_array(0)->get_stride()); } } @@ -1040,7 +1043,7 @@ draw_tristrips(const GeomTristrips *primitive) { _vertices_tristrip_pcollector.add_level(ends[i] - start); unsigned int min = mins.get_data1i(); unsigned int max = maxs.get_data1i(); - draw_indexed_primitive_up + draw_indexed_primitive_up (D3DPT_TRIANGLESTRIP, min, max, ends[i] - start - 2, @@ -1073,10 +1076,10 @@ draw_tristrips(const GeomTristrips *primitive) { unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_tristrip_pcollector.add_level(ends[i] - start); - draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2, - first_vertex + start, - ends[i] - start, - array_data, stride); + draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2, + first_vertex + start, + ends[i] - start, + array_data, stride); start = ends[i] + 2; } @@ -1139,7 +1142,7 @@ draw_trifans(const GeomTrifans *primitive) { _vertices_trifan_pcollector.add_level(ends[i] - start); unsigned int min = mins.get_data1i(); unsigned int max = maxs.get_data1i(); - draw_indexed_primitive_up + draw_indexed_primitive_up (D3DPT_TRIANGLEFAN, min, max, ends[i] - start - 2, @@ -1172,11 +1175,11 @@ draw_trifans(const GeomTrifans *primitive) { unsigned int start = 0; for (size_t i = 0; i < ends.size(); i++) { _vertices_trifan_pcollector.add_level(ends[i] - start); - draw_primitive_up(D3DPT_TRIANGLEFAN, - ends[i] - start - 2, - first_vertex, - ends[i] - start, - array_data, stride); + draw_primitive_up(D3DPT_TRIANGLEFAN, + ends[i] - start - 2, + first_vertex, + ends[i] - start, + array_data, stride); start = ends[i]; } } @@ -1232,10 +1235,10 @@ draw_lines(const GeomLines *primitive) { } else { // Nonindexed, client arrays. draw_primitive_up(D3DPT_LINELIST, primitive->get_num_primitives(), - primitive->get_first_vertex(), - primitive->get_num_vertices(), - _vertex_data->get_array(0)->get_data(), - _vertex_data->get_format()->get_array(0)->get_stride()); + primitive->get_first_vertex(), + primitive->get_num_vertices(), + _vertex_data->get_array(0)->get_data(), + _vertex_data->get_format()->get_array(0)->get_stride()); } } } @@ -1273,10 +1276,10 @@ draw_points(const GeomPoints *primitive) { } else { // Nonindexed, client arrays. draw_primitive_up(D3DPT_POINTLIST, primitive->get_num_primitives(), - primitive->get_first_vertex(), - primitive->get_num_vertices(), - _vertex_data->get_array(0)->get_data(), - _vertex_data->get_format()->get_array(0)->get_stride()); + primitive->get_first_vertex(), + primitive->get_num_vertices(), + _vertex_data->get_array(0)->get_data(), + _vertex_data->get_format()->get_array(0)->get_stride()); } } @@ -1327,7 +1330,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, dr->get_region_pixels_i(xo, yo, w, h); tex->set_x_size(Texture::up_to_power_2(w)); tex->set_y_size(Texture::up_to_power_2(h)); - + TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { return; @@ -1388,7 +1391,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, return; } } - + IDirect3DSurface8 *render_target; hr = _d3d_device->GetRenderTarget(&render_target); if (FAILED(hr)) { @@ -1462,7 +1465,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend tex->get_format() != format || tex->get_texture_type() != texture_type) { // Re-setup the texture; its properties have changed. - tex->setup_texture(texture_type, w, h, tex->get_z_size(), + tex->setup_texture(texture_type, w, h, tex->get_z_size(), component_type, format); } @@ -1493,12 +1496,12 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend // Since we might not be able to Lock the back buffer, we will // need to copy it to a temporary surface of the appropriate type // first. - hr = _d3d_device->CreateImageSurface(w, h, _screen->_display_mode.Format, - &temp_surface); + hr = _d3d_device->CreateImageSurface(w, h, _screen->_display_mode.Format, + &temp_surface); if (FAILED(hr)) { dxgsg8_cat.error() - << "CreateImageSurface failed in copy_pixel_buffer()" - << D3DERRORSTRING(hr); + << "CreateImageSurface failed in copy_pixel_buffer()" + << D3DERRORSTRING(hr); backbuffer->Release(); return false; } @@ -1519,29 +1522,29 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend if (_screen->_presentation_params.Windowed) { // GetFrontBuffer() retrieves the entire desktop for a monitor, // so we need to reserve space for that. - + // We have to use GetMonitorInfo(), since this GSG may not be // for the primary monitor. MONITORINFO minfo; minfo.cbSize = sizeof(MONITORINFO); GetMonitorInfo(_screen->_monitor, &minfo); - + w = RECT_XSIZE(minfo.rcMonitor); h = RECT_YSIZE(minfo.rcMonitor); - + // set rect to client area of window in scrn coords ClientToScreen(_screen->_window, (POINT*)&rect.left); ClientToScreen(_screen->_window, (POINT*)&rect.right); } - + // For GetFrontBuffer(), we need a temporary surface of type // A8R8G8B8. Unlike GetBackBuffer(), GetFrontBuffer() implicitly // performs a copy. hr = _d3d_device->CreateImageSurface(w, h, D3DFMT_A8R8G8B8, &temp_surface); if (FAILED(hr)) { dxgsg8_cat.error() - << "CreateImageSurface failed in copy_pixel_buffer()" - << D3DERRORSTRING(hr); + << "CreateImageSurface failed in copy_pixel_buffer()" + << D3DERRORSTRING(hr); return false; } @@ -1549,7 +1552,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend if (hr == D3DERR_DEVICELOST) { dxgsg8_cat.error() - << "copy_pixel_buffer failed: device lost\n"; + << "copy_pixel_buffer failed: device lost\n"; temp_surface->Release(); return false; } @@ -1565,8 +1568,8 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend return false; } - DXTextureContext8::d3d_surface_to_texture(rect, temp_surface, - copy_inverted, tex, z); + DXTextureContext8::d3d_surface_to_texture(rect, temp_surface, + copy_inverted, tex, z); RELEASE(temp_surface, dxgsg8, "temp_surface", RELEASE_ONCE); @@ -1644,6 +1647,27 @@ reset() { _supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0); _supports_texture_dot3 = true; + // check for render to texture support + D3DDEVICE_CREATION_PARAMETERS creation_parameters; + + _supports_render_texture = false; + hr = _d3d_device->GetCreationParameters (&creation_parameters); + if (SUCCEEDED (hr)) { + hr = _screen->_d3d8->CheckDeviceFormat ( + creation_parameters.AdapterOrdinal, + creation_parameters.DeviceType, + _screen->_display_mode.Format, + D3DUSAGE_RENDERTARGET, + D3DRTYPE_TEXTURE, + _render_to_texture_d3d_format); + if (SUCCEEDED (hr)) { + _supports_render_texture = true; + } + } + if (dxgsg8_cat.is_debug()) { + dxgsg8_cat.debug() << "Render to Texture Support = " << _supports_render_texture << "\n"; + } + _supports_3d_texture = ((d3d_caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0); if (_supports_3d_texture) { _max_3d_texture_dimension = d3d_caps.MaxVolumeExtent; @@ -1735,7 +1759,7 @@ reset() { // turn on dithering if the rendertarget is < 8bits/color channel bool dither_enabled = ((!dx_no_dithering) && IS_16BPP_DISPLAY_FORMAT(_screen->_presentation_params.BackBufferFormat) - && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)); + && (_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)); _d3d_device->SetRenderState(D3DRS_DITHERENABLE, dither_enabled); _d3d_device->SetRenderState(D3DRS_CLIPPING, true); @@ -2083,7 +2107,7 @@ set_state_and_transform(const RenderState *target, _internal_transform = _cs_transform->compose(transform); do_issue_transform(); } - + if (target == _state_rs) { return; } @@ -2095,87 +2119,87 @@ set_state_and_transform(const RenderState *target, // There might be some physical limits to the actual target // attributes we issue. Impose them now. _target._texture = _target._texture->filter_to_max(_max_texture_stages); - + if (_target._alpha_test != _state._alpha_test) { do_issue_alpha_test(); _state._alpha_test = _target._alpha_test; } - + if (_target._antialias != _state._antialias) { // Antialias not implemented under DX8 _state._antialias = _target._antialias; } - + if (_target._clip_plane != _state._clip_plane) { do_issue_clip_plane(); _state._clip_plane = _target._clip_plane; } - + if (_target._color != _state._color) { do_issue_color(); _state._color = _target._color; } - + if (_target._color_scale != _state._color_scale) { do_issue_color_scale(); _state._color_scale = _target._color_scale; } - + if (_target._cull_face != _state._cull_face) { do_issue_cull_face(); _state._cull_face = _target._cull_face; } - + if (_target._depth_offset != _state._depth_offset) { do_issue_depth_offset(); _state._depth_offset = _target._depth_offset; } - + if (_target._depth_test != _state._depth_test) { do_issue_depth_test(); _state._depth_test = _target._depth_test; } - + if (_target._depth_write != _state._depth_write) { do_issue_depth_write(); _state._depth_write = _target._depth_write; } - + if (_target._fog != _state._fog) { do_issue_fog(); _state._fog = _target._fog; } - + if (_target._render_mode != _state._render_mode) { do_issue_render_mode(); _state._render_mode = _target._render_mode; } - + if (_target._rescale_normal != _state._rescale_normal) { do_issue_rescale_normal(); _state._rescale_normal = _target._rescale_normal; } - + if (_target._shade_model != _state._shade_model) { do_issue_shade_model(); _state._shade_model = _target._shade_model; } - + // Shaders not implemented under DX8 if (_target._shader != _state._shader) { _state._shader = _target._shader; } - + if (_target._tex_gen != _state._tex_gen) { _state._texture = 0; _state._tex_gen = _target._tex_gen; } - + if (_target._tex_matrix != _state._tex_matrix) { _state._texture = 0; _state._tex_matrix = _target._tex_matrix; } - + if ((_target._transparency != _state._transparency)|| (_target._color_write != _state._color_write)|| (_target._color_blend != _state._color_blend)) { @@ -2184,7 +2208,7 @@ set_state_and_transform(const RenderState *target, _state._color_write = _target._color_write; _state._color_blend = _target._color_blend; } - + if (_target._texture != _state._texture) { do_issue_texture(); _state._texture = _target._texture; @@ -2194,7 +2218,7 @@ set_state_and_transform(const RenderState *target, do_issue_material(); _state._material = _target._material; } - + if (_target._light != _state._light) { do_issue_light(); _state._light = _target._light; @@ -2489,7 +2513,7 @@ do_issue_texture() { if (_state._tex_matrix->has_stage(stage)) { tex_mat = _state._tex_matrix->get_transform(stage); } - + // Issue the texgen mode. TexGenAttrib::Mode mode = _state._tex_gen->get_mode(stage); bool any_point_sprite = false; @@ -2499,7 +2523,7 @@ do_issue_texture() { case TexGenAttrib::M_light_vector: _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index); break; - + case TexGenAttrib::M_eye_sphere_map: { _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, @@ -2523,7 +2547,7 @@ do_issue_texture() { // transform. In the case of a vector, we should not apply the // pos component of the transform. { - _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); texcoord_dimensions = 3; CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); @@ -2532,7 +2556,7 @@ do_issue_texture() { break; case TexGenAttrib::M_eye_cube_map: - _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); tex_mat = tex_mat->compose(_inv_cs_transform); texcoord_dimensions = 3; @@ -2544,7 +2568,7 @@ do_issue_texture() { // the case of a normal, we should not apply the pos component // of the transform. { - _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL); texcoord_dimensions = 3; CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); @@ -2553,7 +2577,7 @@ do_issue_texture() { break; case TexGenAttrib::M_eye_normal: - _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index | D3DTSS_TCI_CAMERASPACENORMAL); texcoord_dimensions = 3; tex_mat = tex_mat->compose(_inv_cs_transform); @@ -2564,7 +2588,7 @@ do_issue_texture() { // coordinates to world coordinates; i.e. apply the // camera transform. { - _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION); texcoord_dimensions = 3; CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); @@ -2573,18 +2597,18 @@ do_issue_texture() { break; case TexGenAttrib::M_eye_position: - _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index | D3DTSS_TCI_CAMERASPACEPOSITION); texcoord_dimensions = 3; tex_mat = tex_mat->compose(_inv_cs_transform); break; - + case TexGenAttrib::M_point_sprite: _d3d_device->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index); any_point_sprite = true; break; } - + _d3d_device->SetRenderState(D3DRS_POINTSPRITEENABLE, any_point_sprite); if (!tex_mat->is_identity()) { @@ -2601,12 +2625,12 @@ do_issue_texture() { } else { LMatrix4f m = tex_mat->get_mat(); _d3d_device->SetTransform(get_tex_mat_sym(i), (D3DMATRIX *)m.get_data()); - DWORD transform_flags = texcoord_dimensions; - if (m.get_col(3) != LVecBase4f(0.0f, 0.0f, 0.0f, 1.0f)) { - // If we have a projected texture matrix, we also need to - // set D3DTTFF_COUNT4. - transform_flags = D3DTTFF_COUNT4 | D3DTTFF_PROJECTED; - } + DWORD transform_flags = texcoord_dimensions; + if (m.get_col(3) != LVecBase4f(0.0f, 0.0f, 0.0f, 1.0f)) { + // If we have a projected texture matrix, we also need to + // set D3DTTFF_COUNT4. + transform_flags = D3DTTFF_COUNT4 | D3DTTFF_PROJECTED; + } _d3d_device->SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, transform_flags); } @@ -2741,12 +2765,12 @@ do_issue_blending() { if (_target._color_write->get_channels() == ColorWriteAttrib::C_off) { if (_target._color_write != _state._color_write) { if (_screen->_can_direct_disable_color_writes) { - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); _d3d_device->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)0x0); } else { - _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + _d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + _d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + _d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); } } return; @@ -2788,10 +2812,10 @@ do_issue_blending() { break; } - _d3d_device->SetRenderState(D3DRS_SRCBLEND, - get_blend_func(color_blend->get_operand_a())); - _d3d_device->SetRenderState(D3DRS_DESTBLEND, - get_blend_func(color_blend->get_operand_b())); + _d3d_device->SetRenderState(D3DRS_SRCBLEND, + get_blend_func(color_blend->get_operand_a())); + _d3d_device->SetRenderState(D3DRS_DESTBLEND, + get_blend_func(color_blend->get_operand_b())); return; } @@ -3069,7 +3093,7 @@ report_texmgr_stats() { //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::set_context // Access: Protected -// Description: +// Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: set_context(DXScreenData *new_context) { @@ -3110,13 +3134,13 @@ set_render_target() { //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::set_texture_blend_mode // Access: Protected -// Description: +// Description: //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: set_texture_blend_mode(int i, const TextureStage *stage) { switch (stage->get_mode()) { case TextureStage::M_modulate: - // emulates GL_MODULATE glTexEnv mode + // emulates GL_MODULATE glTexEnv mode _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE); _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); @@ -3160,7 +3184,7 @@ set_texture_blend_mode(int i, const TextureStage *stage) { _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_TEXTURE); _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TFACTOR); - + _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE); _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); _d3d_device->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); @@ -3171,63 +3195,63 @@ set_texture_blend_mode(int i, const TextureStage *stage) { // M_combine mode begins a collection of more sophisticated modes, // which match up more closely with DirectX's built-in modes. _d3d_device->SetTextureStageState - (i, D3DTSS_COLOROP, + (i, D3DTSS_COLOROP, get_texture_operation(stage->get_combine_rgb_mode(), stage->get_rgb_scale())); switch (stage->get_num_combine_rgb_operands()) { case 3: _d3d_device->SetTextureStageState - (i, D3DTSS_COLORARG0, + (i, D3DTSS_COLORARG0, get_texture_argument(stage->get_combine_rgb_source2(), stage->get_combine_rgb_operand2())); // fall through - + case 2: _d3d_device->SetTextureStageState - (i, D3DTSS_COLORARG2, + (i, D3DTSS_COLORARG2, get_texture_argument(stage->get_combine_rgb_source1(), stage->get_combine_rgb_operand1())); // fall through case 1: _d3d_device->SetTextureStageState - (i, D3DTSS_COLORARG1, + (i, D3DTSS_COLORARG1, get_texture_argument(stage->get_combine_rgb_source0(), stage->get_combine_rgb_operand0())); // fall through - + default: break; } _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAOP, + (i, D3DTSS_ALPHAOP, get_texture_operation(stage->get_combine_alpha_mode(), stage->get_alpha_scale())); switch (stage->get_num_combine_alpha_operands()) { case 3: _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAARG0, + (i, D3DTSS_ALPHAARG0, get_texture_argument(stage->get_combine_alpha_source2(), stage->get_combine_alpha_operand2())); // fall through - + case 2: _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAARG2, + (i, D3DTSS_ALPHAARG2, get_texture_argument(stage->get_combine_alpha_source1(), stage->get_combine_alpha_operand1())); // fall through case 1: _d3d_device->SetTextureStageState - (i, D3DTSS_ALPHAARG1, + (i, D3DTSS_ALPHAARG1, get_texture_argument(stage->get_combine_alpha_source0(), stage->get_combine_alpha_operand0())); // fall through - + default: break; } @@ -3306,7 +3330,7 @@ dx_cleanup() { // screen //////////////////////////////////////////////////////////////////// HRESULT DXGraphicsStateGuardian8:: -reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, +reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, DXScreenData **screen) { HRESULT hr; @@ -3334,9 +3358,9 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, << " presentation_params = " << presentation_params->BackBufferWidth << "x" << presentation_params->BackBufferHeight << "\n"; } - + get_engine()->reset_all_windows(false);// reset old swapchain by releasing - + if (_screen->_swap_chain) { //other windows might be using bigger buffers _presentation_reset.BackBufferWidth = max(_presentation_reset.BackBufferWidth, presentation_params->BackBufferWidth); _presentation_reset.BackBufferHeight = max(_presentation_reset.BackBufferHeight, presentation_params->BackBufferHeight); @@ -3357,12 +3381,12 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, // cheap to replace. release_all_vertex_buffers(); release_all_index_buffers(); - + hr = _d3d_device->Reset(&_presentation_reset); if (FAILED(hr)) { return hr; } - + get_engine()->reset_all_windows(true);// reset with new swapchains by creating if (screen) { *screen = NULL; @@ -3378,7 +3402,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, // release the old swapchain and create a new one if (_screen && _screen->_swap_chain) { _screen->_swap_chain->Release(); - wdxdisplay8_cat.debug() + wdxdisplay8_cat.debug() << "swap chain " << _screen->_swap_chain << " is released\n"; _screen->_swap_chain = NULL; hr = _d3d_device->CreateAdditionalSwapChain(presentation_params, &_screen->_swap_chain); @@ -3397,7 +3421,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params, //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::check_cooperative_level // Access: Protected -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian8:: check_cooperative_level() { @@ -3479,7 +3503,7 @@ show_frame() { //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::create_swap_chain // Access: Protected -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian8:: create_swap_chain(DXScreenData *new_context) { @@ -3710,10 +3734,10 @@ get_texture_argument_modifier(TextureStage::CombineOperand operand) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: draw_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int primitive_count, - unsigned int first_vertex, - unsigned int num_vertices, - const unsigned char *buffer, size_t stride) { + unsigned int primitive_count, + unsigned int first_vertex, + unsigned int num_vertices, + const unsigned char *buffer, size_t stride) { // It appears that the common ATI driver seems to fail to draw // anything in the DrawPrimitiveUP() call if the address range of @@ -3728,12 +3752,12 @@ draw_primitive_up(D3DPRIMITIVETYPE primitive_type, // Actually, the buffer doesn't fit within the required limit // anyway. Go ahead and draw it and hope for the best. _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count, - buffer_start, stride); + buffer_start, stride); } else if ((((long)buffer_end ^ (long)buffer_start) & ~0xffff) == 0) { // No problem; we can draw the buffer directly. _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count, - buffer_start, stride); + buffer_start, stride); } else { // We have a problem--the buffer crosses over a 0x10000 boundary. @@ -3742,8 +3766,8 @@ draw_primitive_up(D3DPRIMITIVETYPE primitive_type, unsigned char *safe_buffer_start = get_safe_buffer_start(); memcpy(safe_buffer_start, buffer_start, buffer_end - buffer_start); _d3d_device->DrawPrimitiveUP(primitive_type, primitive_count, - safe_buffer_start, stride); - + safe_buffer_start, stride); + } } @@ -3760,11 +3784,11 @@ draw_primitive_up(D3DPRIMITIVETYPE primitive_type, //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int min_index, unsigned int max_index, - unsigned int num_primitives, - const unsigned char *index_data, - D3DFORMAT index_type, - const unsigned char *buffer, size_t stride) { + unsigned int min_index, unsigned int max_index, + unsigned int num_primitives, + const unsigned char *index_data, + D3DFORMAT index_type, + const unsigned char *buffer, size_t stride) { // As above, we'll hack the case of the buffer crossing the 0x10000 // boundary. const unsigned char *buffer_start = buffer + stride * min_index; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 799acb6f31..633db21d38 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -74,7 +74,7 @@ public: virtual void end_scene(); virtual void end_frame(); - virtual bool begin_draw_primitives(const Geom *geom, + virtual bool begin_draw_primitives(const Geom *geom, const GeomMunger *munger, const GeomVertexData *vertex_data); virtual void draw_triangles(const GeomTriangles *primitive); @@ -94,11 +94,11 @@ public: virtual void apply_fog(Fog *fog); - virtual void bind_light(PointLight *light_obj, const NodePath &light, + virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id); - virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, + virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id); - virtual void bind_light(Spotlight *light_obj, const NodePath &light, + virtual void bind_light(Spotlight *light_obj, const NodePath &light, int light_id); static D3DFORMAT get_index_type(Geom::NumericType numeric_type); @@ -123,7 +123,7 @@ protected: void do_issue_material(); void do_issue_texture(); void do_issue_blending(); - + virtual void enable_lighting(bool enable); virtual void set_ambient_light(const Colorf &color); virtual void enable_light(int light_id, bool enable); @@ -154,7 +154,7 @@ protected: void set_texture_blend_mode(int i, const TextureStage *stage); void dx_cleanup(); - HRESULT reset_d3d_device(D3DPRESENT_PARAMETERS *p_presentation_params, + HRESULT reset_d3d_device(D3DPRESENT_PARAMETERS *p_presentation_params, DXScreenData **screen = NULL); bool check_cooperative_level(); @@ -173,16 +173,16 @@ protected: static DWORD get_texture_argument_modifier(TextureStage::CombineOperand operand); void draw_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int primitive_count, - unsigned int first_vertex, - unsigned int num_vertices, - const unsigned char *buffer, size_t stride); + unsigned int primitive_count, + unsigned int first_vertex, + unsigned int num_vertices, + const unsigned char *buffer, size_t stride); void draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type, - unsigned int min_index, unsigned int max_index, - unsigned int num_primitives, - const unsigned char *index_data, - D3DFORMAT index_type, - const unsigned char *buffer, size_t stride); + unsigned int min_index, unsigned int max_index, + unsigned int num_primitives, + const unsigned char *index_data, + D3DFORMAT index_type, + const unsigned char *buffer, size_t stride); INLINE static unsigned char *get_safe_buffer_start(); @@ -234,6 +234,8 @@ protected: static unsigned char *_temp_buffer; static unsigned char *_safe_buffer_start; + D3DFORMAT _render_to_texture_d3d_format; + public: virtual TypeHandle get_type() const { return get_class_type(); @@ -255,6 +257,7 @@ private: static TypeHandle _type_handle; friend class wdxGraphicsWindow8; + friend class wdxGraphicsBuffer8; friend class wdxGraphicsPipe8; friend class wdxGraphicsWindowGroup8; friend class DXTextureContext8; diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h index c8a6f7c267..9222344316 100644 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ b/panda/src/dxgsg8/dxTextureContext8.h @@ -41,10 +41,10 @@ public: INLINE IDirect3DVolumeTexture8 *get_d3d_volume_texture() const; INLINE IDirect3DCubeTexture8 *get_d3d_cube_texture() const; - static HRESULT d3d_surface_to_texture(RECT &source_rect, - IDirect3DSurface8 *d3d_surface, - bool inverted, Texture *result, - int z); + static HRESULT d3d_surface_to_texture(RECT &source_rect, + IDirect3DSurface8 *d3d_surface, + bool inverted, Texture *result, + int z); private: HRESULT fill_d3d_texture_pixels(); @@ -77,6 +77,8 @@ public: private: static TypeHandle _type_handle; + + friend class wdxGraphicsBuffer8; }; #include "dxTextureContext8.I" diff --git a/panda/src/dxgsg8/dxgsg8_composite1.cxx b/panda/src/dxgsg8/dxgsg8_composite1.cxx index e94bbf8dde..8e3cc0e6f9 100644 --- a/panda/src/dxgsg8/dxgsg8_composite1.cxx +++ b/panda/src/dxgsg8/dxgsg8_composite1.cxx @@ -6,4 +6,5 @@ #include "dxGeomMunger8.cxx" #include "wdxGraphicsPipe8.cxx" #include "wdxGraphicsWindow8.cxx" +#include "wdxGraphicsBuffer8.cxx" #include "dxGraphicsDevice8.cxx" diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx new file mode 100644 index 0000000000..a44e4ce265 --- /dev/null +++ b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx @@ -0,0 +1,502 @@ +// Filename: wdxGraphicsBuffer8.cxx +// Created by: drose (08Feb04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// 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 +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "wdxGraphicsPipe8.h" +#include "wdxGraphicsBuffer8.h" +#include "pStatTimer.h" + + +// ISSUES: + // size issues + // texture size must not exeeed the original frame buffer width + // or height due to the size of the original depth/stencil buffer + // render to texure format + // can be specified via the DXGraphicsStateGuardian8 member + // _render_to_texture_d3d_format default = D3DFMT_X8R8G8B8 + + // LOST DEVICE case for D3DPOOL_DEFAULT buffers + // should check texture creation with CheckDepthStencilMatch + // support copy from texture to ram? + // check D3DCAPS2_DYNAMICTEXTURES + +TypeHandle wdxGraphicsBuffer8::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +wdxGraphicsBuffer8:: +wdxGraphicsBuffer8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, + const string &name, + int x_size, int y_size) : + GraphicsBuffer(pipe, gsg, name, x_size, y_size) +{ + // initialize all class members + _cube_map_index = -1; + _back_buffer = NULL; + _z_stencil_buffer = NULL; + _direct_3d_surface = NULL; + _dx_texture_context8 = NULL; + +// 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; +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +wdxGraphicsBuffer8:: +~wdxGraphicsBuffer8() { +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::begin_frame +// Access: Public, Virtual +// Description: This function will be called within the draw thread +// before beginning rendering for a given frame. It +// should do whatever setup is required, and return true +// if the frame should be rendered, or false if it +// should be skipped. +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsBuffer8:: +begin_frame() { + if (_gsg == (GraphicsStateGuardian *)NULL) { + return false; + } + + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_R(dxgsg, _gsg, false); + + return GraphicsBuffer::begin_frame(); +} + +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsStateGuardian::begin_render_texture +// Access: Public, Virtual +// 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. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +begin_render_texture() { + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + + HRESULT hr; + bool state; + + state = false; + + // 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; + } + } + + // set render context + if (state && _dx_texture_context8) + { + int tex_index; + DXTextureContext8 *dx_texture_context8; + + // ***** assume 0 ??? + tex_index = 0; + + Texture *tex = get_texture(tex_index); + + // ***** ??? CAST + + // 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)) { + hr = dxgsg -> _d3d_device -> SetRenderTarget (_direct_3d_surface, + _z_stencil_buffer); + if (SUCCEEDED (hr)) { + + } + } + } + + // 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)) { + hr = dxgsg -> _d3d_device -> SetRenderTarget (_direct_3d_surface, + _z_stencil_buffer); + if (SUCCEEDED (hr)) { + + } + } + } else { + // error: invalid cube map face index + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::end_render_texture +// Access: Public, Virtual +// 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. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +end_render_texture() { + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + +// is this really needed ??? seems to work without it though +/* + + // Find the color texture, if there is one. That one can be bound to + // the framebuffer. All others must be marked RTM_copy_to_texture. + + int tex_index = -1; + for (int i=0; iget_format() != Texture::F_depth_component)&& + (get_texture(i)->get_format() != Texture::F_stencil_index)&& + (tex_index < 0)) { + tex_index = i; + } else { + _textures[i]._rtm_mode = RTM_copy_texture; + } + } + } + + if (tex_index >= 0) { + Texture *tex = get_texture(tex_index); + TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg); + nassertv(tc != (TextureContext *)NULL); + } + +*/ + + // restore render context + HRESULT hr; + + if (_back_buffer) { + hr = dxgsg -> _d3d_device -> SetRenderTarget (_back_buffer, + _z_stencil_buffer); + if (SUCCEEDED (hr)) { + _back_buffer -> Release ( ); + } + _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; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::select_cube_map +// Access: Public, Virtual +// Description: Called internally when the window is in +// render-to-a-texture mode and we are in the process of +// rendering the six faces of a cube map. This should +// do whatever needs to be done to switch the buffer to +// the indicated face. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +select_cube_map(int cube_map_index) { + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + + _cube_map_index = cube_map_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::make_current +// Access: Public, Virtual +// Description: This function will be called within the draw thread +// during begin_frame() to ensure the graphics context +// is ready for drawing. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +make_current() { + PStatTimer timer(_make_current_pcollector); + + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + + // do nothing here +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::release_gsg +// Access: Public, Virtual +// Description: Releases the current GSG pointer, if it is currently +// held, and resets the GSG to NULL. The window will be +// permanently unable to render; this is normally called +// only just before destroying the window. This should +// only be called from within the draw thread. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +release_gsg() { + GraphicsBuffer::release_gsg(); +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::process_events +// Access: Public, Virtual +// Description: Do whatever processing is necessary to ensure that +// the window responds to user events. Also, honor any +// requests recently made via request_properties() +// +// This function is called only within the window +// thread. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +process_events() { + GraphicsBuffer::process_events(); + + MSG msg; + + // Handle all the messages on the queue in a row. Some of these + // might be for another window, but they will get dispatched + // appropriately. + while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + process_1_event(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::close_buffer +// Access: Protected, Virtual +// Description: Closes the buffer right now. Called from the window +// thread. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +close_buffer() { + + if (_gsg != (GraphicsStateGuardian *)NULL) { + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_V(dxgsg, _gsg); + + DXTextureContext8 *dx_texture_context8; + + dx_texture_context8 = _dx_texture_context8; + if (dx_texture_context8) { + // release render texture + if (dx_texture_context8 -> _d3d_texture) { + dx_texture_context8 -> _d3d_texture -> Release ( ); + } + dx_texture_context8 -> _d3d_texture = NULL; + dx_texture_context8 -> _d3d_2d_texture = NULL; + dx_texture_context8 -> _d3d_volume_texture = NULL; + dx_texture_context8 -> _d3d_cube_texture = NULL; + } + } + + _cube_map_index = -1; + + _is_valid = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::open_buffer +// Access: Protected, Virtual +// Description: Opens the window right now. Called from the window +// thread. Returns true if the window is successfully +// opened, or false if there was a problem. +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsBuffer8:: +open_buffer() { + bool state; + DXGraphicsStateGuardian8 *dxgsg; + DCAST_INTO_R(dxgsg, _gsg, false); + + // create texture + int tex_index; + UINT texture_depth; + DXTextureContext8 *dx_texture_context8; + + state = false; + _is_valid = false; + +// **** assume tex_index is 0 ??? + tex_index = 0; + texture_depth = 1; + + Texture *tex = get_texture(tex_index); + TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg); + +// ***** ??? CAST + dx_texture_context8 = (DXTextureContext8 *) tc; + + // release managed texture + if (dx_texture_context8 -> _d3d_texture) { + dx_texture_context8 -> _d3d_texture -> Release ( ); + } + dx_texture_context8 -> _d3d_texture = NULL; + dx_texture_context8 -> _d3d_2d_texture = NULL; + dx_texture_context8 -> _d3d_volume_texture = NULL; + dx_texture_context8 -> _d3d_cube_texture = NULL; + + // save dx_texture_context8 + _dx_texture_context8 = dx_texture_context8; + + // create render texture + if (wdxGraphicsBuffer8::create_render_texture ( + get_x_size ( ), + get_y_size ( ), + texture_depth, + dxgsg -> _render_to_texture_d3d_format, + dx_texture_context8, + dxgsg -> _d3d_device)) { + + // override texture managed format + dx_texture_context8 -> _d3d_format = dxgsg -> _render_to_texture_d3d_format; + dx_texture_context8 -> _has_mipmaps = false; + + _is_valid = true; + + state = true; + } + + return state; +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::process_1_event +// Access: Private, Static +// Description: Handles one event from the message queue. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer8:: +process_1_event() { + MSG msg; + + if (!GetMessage(&msg, NULL, 0, 0)) { + // WM_QUIT received. We need a cleaner way to deal with this. + // DestroyAllWindows(false); + exit(msg.wParam); // this will invoke AtExitFn + } + + // Translate virtual key messages + TranslateMessage(&msg); + // Call window_proc + DispatchMessage(&msg); +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer8::create_render_texture +// Access: Private +// Description: Creates a texture that can be rendered into +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsBuffer8:: +create_render_texture (UINT texture_width, UINT texture_height, UINT texture_depth, D3DFORMAT texture_format, DXTextureContext8 *dx_texture_context8, IDirect3DDevice8 *direct_3d_device) +{ + bool state; + HRESULT hr; + DWORD usage; + D3DPOOL pool; + UINT mip_level_count; + D3DFORMAT pixel_format; + int texture_type; + + state = false; + + texture_type = dx_texture_context8 -> _texture -> get_texture_type ( ); + + // assume 1 mip level + mip_level_count = 1; + + // REQUIRED pool and usage + pool = D3DPOOL_DEFAULT; + usage = D3DUSAGE_RENDERTARGET; + +// ??? +// usage |= D3DUSAGE_DYNAMIC; + + pixel_format = texture_format; + + switch (texture_type) + { + case Texture::TT_2d_texture: + hr = direct_3d_device->CreateTexture + (texture_width, texture_height, mip_level_count, usage, + pixel_format, pool, &dx_texture_context8 -> _d3d_2d_texture); + dx_texture_context8 -> _d3d_texture = dx_texture_context8 -> _d3d_2d_texture; + break; + + case Texture::TT_3d_texture: + // DX8 does not support rendering to volume textures so this should fail + hr = direct_3d_device->CreateVolumeTexture + (texture_width, texture_height, texture_depth, mip_level_count, usage, + pixel_format, pool, &dx_texture_context8 -> _d3d_volume_texture); + dx_texture_context8 -> _d3d_texture = dx_texture_context8 -> _d3d_volume_texture; + break; + + case Texture::TT_cube_map: + hr = direct_3d_device->CreateCubeTexture + (texture_width, mip_level_count, usage, + pixel_format, pool, &dx_texture_context8 -> _d3d_cube_texture); + dx_texture_context8 -> _d3d_texture = dx_texture_context8 -> _d3d_cube_texture; + break; + + default: + break; + } + + if (FAILED(hr)) { + dxgsg8_cat.error() + << "create_render_texture failed" << D3DERRORSTRING(hr); + } + else { + state = true; + } + + return state; +} + diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.h b/panda/src/dxgsg8/wdxGraphicsBuffer8.h new file mode 100644 index 0000000000..4fb3e15db7 --- /dev/null +++ b/panda/src/dxgsg8/wdxGraphicsBuffer8.h @@ -0,0 +1,94 @@ +// Filename: wdxGraphicsBuffer8.h +// Created by: drose (08Feb04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// 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 +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef wdxGraphicsBuffer8_H +#define wdxGraphicsBuffer8_H + +#include "pandabase.h" +#include "graphicsBuffer.h" +#include "dxgsg8base.h" + + +//////////////////////////////////////////////////////////////////// +// Class : wdxGraphicsBuffer8 +// Description : An offscreen render buffer. In OpenGL under Windows, +// this simply renders into a window that is never made +// visible. There's a Windows interface for rendering +// into a DIB, but this puts restrictions on the kind of +// pixelformat we can use, and thus makes it difficult +// to support one GSG rendering into an offscreen buffer +// and also into a window. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDADX wdxGraphicsBuffer8 : public GraphicsBuffer { +public: + wdxGraphicsBuffer8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, + const string &name, + int x_size, int y_size); + virtual ~wdxGraphicsBuffer8(); + + virtual bool begin_frame(); + virtual void select_cube_map(int cube_map_index); + + virtual void make_current(); + virtual void release_gsg(); + + virtual void begin_render_texture(); + virtual void end_render_texture(); + + virtual void process_events(); + +protected: + virtual void close_buffer(); + virtual bool open_buffer(); + +private: + static void process_1_event(); + + int _cube_map_index; + IDirect3DSurface8 *_back_buffer; + IDirect3DSurface8 *_z_stencil_buffer; + IDirect3DSurface8 *_direct_3d_surface; + DXTextureContext8 *_dx_texture_context8; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GraphicsBuffer::init_type(); + register_type(_type_handle, "wdxGraphicsBuffer8", + GraphicsBuffer::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + bool create_render_texture (UINT texture_width, UINT texture_height, UINT texture_depth, D3DFORMAT texture_format, DXTextureContext8 *dx_texture_context8, IDirect3DDevice8 *direct_3d_device); + +private: + static TypeHandle _type_handle; + + friend class DXGraphicsStateGuardian8; + friend class DXTextureContext8; +}; + +// #include "wdxGraphicsBuffer8.I" + +#endif diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.cxx b/panda/src/dxgsg8/wdxGraphicsPipe8.cxx index 3eb3e45b12..6a7ece141c 100644 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsPipe8.cxx @@ -19,6 +19,7 @@ #include "wdxGraphicsPipe8.h" #include "dxGraphicsDevice8.h" #include "wdxGraphicsWindow8.h" +#include "wdxGraphicsBuffer8.h" #include "config_dxgsg8.h" TypeHandle wdxGraphicsPipe8::_type_handle; @@ -97,6 +98,25 @@ make_window(GraphicsStateGuardian *gsg, const string &name) { return new wdxGraphicsWindow8(this, gsg, name); } +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsPipe8::make_buffer +// Access: Protected, Virtual +// Description: Creates a new offscreen buffer on the pipe, if possible. +//////////////////////////////////////////////////////////////////// +PT(GraphicsBuffer) wdxGraphicsPipe8:: +make_buffer(GraphicsStateGuardian *gsg, const string &name, + int x_size, int y_size) { + +// hmmmm must return NULL if render to texture is supported and you don't +// want to use it, otherwise it doesn't work + if (support_render_texture && gsg->get_supports_render_texture ( )) { + return new wdxGraphicsBuffer8(this, gsg, name, x_size, y_size); + } + else { + return NULL; + } +} + //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsPipe8::init // Access: Private diff --git a/panda/src/dxgsg8/wdxGraphicsPipe8.h b/panda/src/dxgsg8/wdxGraphicsPipe8.h index 253fd0b6eb..0344ed52ed 100644 --- a/panda/src/dxgsg8/wdxGraphicsPipe8.h +++ b/panda/src/dxgsg8/wdxGraphicsPipe8.h @@ -54,11 +54,13 @@ public: D3DFORMAT *pSuggestedPixFmt, bool bForce16bppZBuffer, bool bVerboseMode = false); - + bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size); protected: virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, const string &name); + virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, const string &name, + int x_size, int y_size); private: bool init(); @@ -90,7 +92,7 @@ private: GUID DX7_DeviceGUID; DWORD VendorID, DeviceID; }; - + typedef pvector CardIDs; CardIDs _card_ids; bool __is_dx8_1;