diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index ff70651b0c..0bf6ffb70b 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -17,7 +17,6 @@ displayRegionStack.I \ displayRegionStack.h \ frameBufferProperties.I frameBufferProperties.h \ - frameBufferStack.I frameBufferStack.h \ graphicsEngine.I graphicsEngine.h \ graphicsOutput.I graphicsOutput.h \ graphicsBuffer.I graphicsBuffer.h \ @@ -59,7 +58,6 @@ displayRegion.I displayRegion.h displayRegionStack.I \ displayRegionStack.h \ frameBufferProperties.I frameBufferProperties.h \ - frameBufferStack.I frameBufferStack.h \ graphicsEngine.I graphicsEngine.h \ graphicsOutput.I graphicsOutput.h \ graphicsBuffer.I graphicsBuffer.h \ diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index 9e9663bc9d..7c1147196d 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -19,10 +19,11 @@ #include "displayRegion.h" #include "graphicsOutput.h" #include "config_display.h" -#include "pixelBuffer.h" +#include "texture.h" #include "camera.h" #include "dcast.h" #include "mutexHolder.h" +#include "pnmImage.h" //////////////////////////////////////////////////////////////////// @@ -519,29 +520,26 @@ get_screenshot(PNMImage &image) { GraphicsStateGuardian *gsg = window->get_gsg(); nassertr(gsg != (GraphicsStateGuardian *)NULL, false); - - int x_size = get_pixel_width(); - int y_size = get_pixel_height(); window->make_current(); int components = 3; - PixelBuffer::Format format = PixelBuffer::F_rgb; + Texture::Format format = Texture::F_rgb; if ((gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) != 0) { components = 4; - format = PixelBuffer::F_rgba; + format = Texture::F_rgba; } - PixelBuffer p(x_size, y_size, components, 1, PixelBuffer::T_unsigned_byte, - format); + // Create a temporary texture to receive the framebuffer image. + PT(Texture) tex = new Texture; RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type()); - if (!gsg->copy_pixel_buffer(&p, this, buffer)) { + if (!gsg->framebuffer_copy_to_ram(tex, this, buffer)) { return false; } - if (!p.store(image)) { + if (!tex->store(image)) { return false; } diff --git a/panda/src/display/frameBufferStack.I b/panda/src/display/frameBufferStack.I deleted file mode 100644 index 7cf1e4f328..0000000000 --- a/panda/src/display/frameBufferStack.I +++ /dev/null @@ -1,59 +0,0 @@ -// Filename: frameBufferStack.I -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Function: FrameBufferStack::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE FrameBufferStack:: -FrameBufferStack() { - _stack_level = -1; -} - -//////////////////////////////////////////////////////////////////// -// Function: FrameBufferStack::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE FrameBufferStack:: -~FrameBufferStack() { -} - -//////////////////////////////////////////////////////////////////// -// Function: FrameBufferStack::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE FrameBufferStack:: -FrameBufferStack(const FrameBufferStack ©) : - _frame_buffer(copy._frame_buffer), - _stack_level(copy._stack_level) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: FrameBufferStack::Copy Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void FrameBufferStack:: -operator =(const FrameBufferStack ©) { - _frame_buffer = copy._frame_buffer; - _stack_level = copy._stack_level; -} diff --git a/panda/src/display/frameBufferStack.h b/panda/src/display/frameBufferStack.h deleted file mode 100644 index 1b02f14e29..0000000000 --- a/panda/src/display/frameBufferStack.h +++ /dev/null @@ -1,51 +0,0 @@ -// Filename: frameBufferStack.h -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 FRAMEBUFFERSTACK_H -#define FRAMEBUFFERSTACK_H - -#include "pandabase.h" - -#include "savedFrameBuffer.h" - -class GraphicsStateGuardian; - -//////////////////////////////////////////////////////////////////// -// Class : FrameBufferStack -// Description : An instance of this kind of object is returned by -// GraphicsStateGuardian::push_frame_buffer(). It -// holds the information needed to restore the previous -// frame buffer contents in the subsequent matching call -// to pop_frame_buffer(). -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA FrameBufferStack { -public: - INLINE FrameBufferStack(); - INLINE ~FrameBufferStack(); - INLINE FrameBufferStack(const FrameBufferStack ©); - INLINE void operator =(const FrameBufferStack ©); - -private: - PT(SavedFrameBuffer) _frame_buffer; - int _stack_level; - friend class GraphicsStateGuardian; -}; - -#include "frameBufferStack.I" - -#endif diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 2b4b3202d0..53a3bb3e6e 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -200,17 +200,16 @@ setup_render_texture() { _gsg->framebuffer_release_texture(this, get_texture()); } - _texture = new Texture(true); - _texture->set_name(get_name()); - _texture->set_wrapu(Texture::WM_clamp); - _texture->set_wrapv(Texture::WM_clamp); + _texture = new Texture(get_name()); + _texture->set_match_framebuffer_format(true); + _texture->set_wrap_u(Texture::WM_clamp); + _texture->set_wrap_v(Texture::WM_clamp); // Go ahead and tell the texture our anticipated size, even if it // might be inaccurate (particularly if this is a GraphicsWindow, // which has system-imposed restrictions on size). - PixelBuffer *pb = _texture->_pbuffer; - pb->set_xsize(get_x_size()); - pb->set_ysize(get_y_size()); + _texture->set_x_size(get_x_size()); + _texture->set_y_size(get_y_size()); _copy_texture = true; _render_texture = false; @@ -606,7 +605,7 @@ begin_frame() { make_current(); if (_render_texture) { - // Release the texture so we can render into the pbuffer. + // Release the texture so we can render into the frame buffer. _gsg->framebuffer_release_texture(this, get_texture()); } @@ -686,7 +685,7 @@ end_frame() { << "Copying texture for " << get_name() << " at frame end.\n"; } RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type()); - _gsg->copy_texture(get_texture(), _default_display_region, buffer); + _gsg->framebuffer_copy_to_texture(get_texture(), _default_display_region, buffer); } } diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 7a5b9fcf24..e683373181 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -439,40 +439,6 @@ pop_display_region(DisplayRegionStack &node) { node._stack_level = -1; } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::push_frame_buffer -// Access: Public -// Description: Saves the contents of the frame buffer (within the -// indicated display region only) so that rendering may -// be performed (for instance, to render a partial in a -// multipass algorithm) and the frame buffer later -// restored via a matching call to pop_frame_buffer(). -//////////////////////////////////////////////////////////////////// -INLINE FrameBufferStack GraphicsStateGuardian:: -push_frame_buffer(const RenderBuffer &buffer, - const DisplayRegion *dr) { - FrameBufferStack old; - old._frame_buffer = save_frame_buffer(buffer, dr); - old._stack_level = _frame_buffer_stack_level; - _frame_buffer_stack_level++; - return old; -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::pop_frame_buffer -// Access: Public -// Description: Restores the contents of the frame buffer as saved by -// a previous call to push_frame_buffer(). -//////////////////////////////////////////////////////////////////// -INLINE void GraphicsStateGuardian:: -pop_frame_buffer(FrameBufferStack &node) { - nassertv(_frame_buffer_stack_level > 0); - _frame_buffer_stack_level--; - nassertv(node._stack_level == _frame_buffer_stack_level); - restore_frame_buffer(node._frame_buffer); - node._stack_level = -1; -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_coordinate_system // Access: Public diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 8bb41e6a6b..1d7c28d2fb 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -22,7 +22,6 @@ #include "pandabase.h" #include "savedFrameBuffer.h" -#include "frameBufferStack.h" #include "frameBufferProperties.h" #include "displayRegionStack.h" #include "lensStack.h" @@ -153,9 +152,6 @@ public: INLINE DisplayRegionStack push_display_region(const DisplayRegion *dr); INLINE void pop_display_region(DisplayRegionStack &node); - INLINE FrameBufferStack push_frame_buffer(const RenderBuffer &buffer, - const DisplayRegion *dr); - INLINE void pop_frame_buffer(FrameBufferStack &node); void set_coordinate_system(CoordinateSystem cs); INLINE CoordinateSystem get_coordinate_system() const; @@ -199,10 +195,6 @@ protected: virtual void set_blend_mode(); - virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr)=0; - virtual void restore_frame_buffer(SavedFrameBuffer *frame_buffer)=0; - virtual void finish_modify_state(); virtual void free_pointers(); diff --git a/panda/src/doc/eggSyntax.txt b/panda/src/doc/eggSyntax.txt index 7f5fa15724..42f420b78d 100644 --- a/panda/src/doc/eggSyntax.txt +++ b/panda/src/doc/eggSyntax.txt @@ -284,6 +284,7 @@ appear before they are referenced. WORLD_POSITION OBJECT_POSITION EYE_POSITION + OBJECT_NORMAL stage-name { name } diff --git a/panda/src/dxgsg7/Sources.pp b/panda/src/dxgsg7/Sources.pp index f70c509b60..d9147398ea 100644 --- a/panda/src/dxgsg7/Sources.pp +++ b/panda/src/dxgsg7/Sources.pp @@ -26,7 +26,7 @@ // build dxGraphicsStateGuardian separately since its so big #define SOURCES \ - dxGraphicsStateGuardian7.cxx dxSavedFrameBuffer7.I dxSavedFrameBuffer7.h \ + dxGraphicsStateGuardian7.cxx \ wdxGraphicsPipe7.I wdxGraphicsPipe7.h \ wdxGraphicsWindow7.I wdxGraphicsWindow7.h \ $[INSTALL_HEADERS] @@ -34,7 +34,7 @@ #define INCLUDED_SOURCES \ config_dxgsg7.cxx \ dxgsg7base.cxx \ - dxSavedFrameBuffer7.cxx dxTextureContext7.cxx \ + dxTextureContext7.cxx \ wdxGraphicsPipe7.cxx wdxGraphicsWindow7.cxx #end lib_target diff --git a/panda/src/dxgsg7/config_dxgsg7.cxx b/panda/src/dxgsg7/config_dxgsg7.cxx index c0771c8548..892838c706 100644 --- a/panda/src/dxgsg7/config_dxgsg7.cxx +++ b/panda/src/dxgsg7/config_dxgsg7.cxx @@ -18,7 +18,6 @@ #include "config_dxgsg7.h" #include "dxGraphicsStateGuardian7.h" -#include "dxSavedFrameBuffer7.h" #include "dxTextureContext7.h" #include "wdxGraphicsPipe7.h" #include "wdxGraphicsWindow7.h" @@ -118,7 +117,6 @@ init_libdxgsg7() { initialized = true; DXGraphicsStateGuardian7::init_type(); - DXSavedFrameBuffer7::init_type(); DXTextureContext7::init_type(); wdxGraphicsPipe7::init_type(); diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx index 99ef9f04bf..c5cb021c31 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx @@ -1752,8 +1752,8 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { modify_state(RenderState::make (TextureAttrib::make(tex), TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); - tex_xsize = tex->_pbuffer->get_xsize(); - tex_ysize = tex->_pbuffer->get_ysize(); + tex_xsize = tex->get_x_size(); + tex_ysize = tex->get_y_size(); } // save the modelview matrix @@ -3375,8 +3375,8 @@ apply_texture(TextureContext *tc) { Texture *tex = tc->_texture; Texture::WrapMode wrapU,wrapV; - wrapU=tex->get_wrapu(); - wrapV=tex->get_wrapv(); + wrapU=tex->get_wrap_u(); + wrapV=tex->get_wrap_v(); if (wrapU!=_CurTexWrapModeU) { _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU)); @@ -3482,88 +3482,42 @@ release_texture(TextureContext *tc) { delete gtc; } +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian7::framebuffer_copy_to_texture +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian7:: -copy_texture(Texture *tex, const DisplayRegion *dr) { +framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { dxgsg7_cat.error() << "DX copy_texture unimplemented!!!"; } //////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::copy_texture -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: -copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { - dxgsg7_cat.error() << "DX copy_texture unimplemented!!!"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { - dxgsg7_cat.error() - << "texture_to_pixel_buffer unimplemented!\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr) { - dxgsg7_cat.error() - << "texture_to_pixel_buffer unimplemented!\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::copy_pixel_buffer +// Function: DXGraphicsStateGuardian7::framebuffer_copy_to_ram // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian7:: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { +framebuffer_copy_to_ram(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb) { + set_read_buffer(rb); + + extern HRESULT ConvertDDSurftoPixBuf(Texture *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf); + + nassertr(tex != NULL && dr != NULL, false); + + int xo, yo, w, h; + dr->get_region_pixels_i(xo, yo, w, h); + + // only handled simple case + nassertr(xo == 0 && yo==0, false); - extern HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf); - - nassertr(pb != NULL && dr != NULL, false); - - int xo, yo, w, h; - dr->get_region_pixels_i(xo, yo, w, h); - - // only handled simple case - nassertr(xo == 0 && yo==0 && w == pb->get_xsize() && h == pb->get_ysize(), false); - -/* - set_pack_alignment(1); - glReadPixels( pb->get_xorg() + xo, pb->get_yorg() + yo, - pb->get_xsize(), pb->get_ysize(), - get_external_image_format(pb->get_format()), - get_image_type(pb->get_image_type()), - pb->_image.p() ); -*/ - - - (void) ConvertDDSurftoPixBuf(pb,((_cur_read_pixel_buffer & RenderBuffer::T_back) ? _pScrn->pddsBack : _pScrn->pddsPrimary)); - - nassertr(!pb->_image.empty(), false); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::copy_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian7:: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb) { - set_read_buffer(rb); - return copy_pixel_buffer(pb, dr); + tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgb); + + (void) ConvertDDSurftoPixBuf(tex,((_cur_read_pixel_buffer & RenderBuffer::T_back) ? _pScrn->pddsBack : _pScrn->pddsPrimary)); + + nassertr(tex->has_ram_image(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -4637,55 +4591,6 @@ free_pointers() { #endif } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::save_frame_buffer -// Access: Public -// Description: Saves the indicated planes of the frame buffer -// (within the indicated display region) and returns it -// in some meaningful form that can be restored later -// via restore_frame_buffer(). This is a helper -// function for push_frame_buffer() and -// pop_frame_buffer(). -//////////////////////////////////////////////////////////////////// -PT(SavedFrameBuffer) DXGraphicsStateGuardian7:: -save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr) { - - dxgsg7_cat.error() << "save_frame_buffer unimplemented!!\n"; - return NULL; - -#if 0 - DXSavedFrameBuffer7 *sfb = new DXSavedFrameBuffer7(buffer, dr); - - if (buffer._buffer_type & RenderBuffer::T_depth) { - // Save the depth buffer. - sfb->_depth = - new PixelBuffer(PixelBuffer::depth_buffer(dr->get_pixel_width(), - dr->get_pixel_height())); - copy_pixel_buffer(sfb->_depth, dr, buffer); - } - - if (buffer._buffer_type & RenderBuffer::T_back) { - // Save the color buffer. - sfb->_back_rgba = new Texture; - copy_texture(sfb->_back_rgba->prepare(this), dr, buffer); - } - - return sfb; -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::restore_frame_buffer -// Access: Public -// Description: Restores the frame buffer that was previously saved. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: -restore_frame_buffer(SavedFrameBuffer *frame_buffer) { - dxgsg7_cat.error() << "restore_frame_buffer unimplemented!!\n"; - return; -} - TypeHandle DXGraphicsStateGuardian7::get_type(void) const { return get_class_type(); } @@ -5244,62 +5149,6 @@ void DXGraphicsStateGuardian7::adjust_view_rect(int x, int y) { } } -#if 0 - -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::save_mipmap_images -// Access: Protected -// Description: Saves out each mipmap level of the indicated texture -// (which must also be the currently active texture in -// the GL state) as a separate image file to disk. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7::read_mipmap_images(Texture *tex) { - Filename filename = tex->get_name(); - string name; - if (filename.empty()) { - static index = 0; - name = "texture" + format_string(index); - index++; - } else { - name = filename.get_basename_wo_extension(); - } - - PixelBuffer *pb = tex->get_ram_image(); - nassertv(pb != (PixelBuffer *)NULL); - - GLenum external_format = get_external_image_format(pb->get_format()); - GLenum type = get_image_type(pb->get_image_type()); - - int xsize = pb->get_xsize(); - int ysize = pb->get_ysize(); - - // Specify byte-alignment for the pixels on output. - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - int mipmap_level = 0; - do { - xsize = max(xsize, 1); - ysize = max(ysize, 1); - - PT(PixelBuffer) mpb = - new PixelBuffer(xsize, ysize, pb->get_num_components(), - pb->get_component_width(), pb->get_image_type(), - pb->get_format()); - glGetTexImage(GL_TEXTURE_2D, mipmap_level, external_format, - type, mpb->_image); - Filename mipmap_filename = name + "_" + format_string(mipmap_level) + ".pnm"; - nout << "Writing mipmap level " << mipmap_level - << " (" << xsize << " by " << ysize << ") " - << mipmap_filename << "\n"; - mpb->write(mipmap_filename); - - xsize >>= 1; - ysize >>= 1; - mipmap_level++; - } while (xsize > 0 && ysize > 0); -} -#endif - #if 0 //----------------------------------------------------------------------------- diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h index 80c45a4907..d378ff8b09 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h @@ -28,7 +28,6 @@ #include "graphicsStateGuardian.h" #include "geomprimitives.h" #include "texture.h" -#include "pixelBuffer.h" #include "displayRegion.h" #include "material.h" #include "depthTestAttrib.h" @@ -92,17 +91,11 @@ public: virtual void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr, - const RenderBuffer &rb); + virtual void framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb); - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb); - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr); - - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb); + virtual bool framebuffer_copy_to_ram(Texture *pb, const DisplayRegion *dr, + const RenderBuffer &rb); virtual void apply_material(const Material *material); virtual void apply_fog(Fog *fog); @@ -158,9 +151,6 @@ protected: void free_pointers(); // free local internal buffers void free_dxgsg_objects(void); // free the DirectX objects we create - virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - virtual void restore_frame_buffer(SavedFrameBuffer *frame_buffer); void set_draw_buffer(const RenderBuffer &rb); void set_read_buffer(const RenderBuffer &rb); diff --git a/panda/src/dxgsg7/dxSavedFrameBuffer7.I b/panda/src/dxgsg7/dxSavedFrameBuffer7.I deleted file mode 100644 index e483db2114..0000000000 --- a/panda/src/dxgsg7/dxSavedFrameBuffer7.I +++ /dev/null @@ -1,39 +0,0 @@ -// Filename: dxSavedFrameBuffer7.I -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: DXSavedFrameBuffer7::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXSavedFrameBuffer7:: -DXSavedFrameBuffer7(const RenderBuffer &buffer, CPT(DisplayRegion) dr) : - SavedFrameBuffer(buffer, dr) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: DXSavedFrameBuffer7::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXSavedFrameBuffer7:: -~DXSavedFrameBuffer7() { -} - diff --git a/panda/src/dxgsg7/dxSavedFrameBuffer7.cxx b/panda/src/dxgsg7/dxSavedFrameBuffer7.cxx deleted file mode 100644 index 989c572bc9..0000000000 --- a/panda/src/dxgsg7/dxSavedFrameBuffer7.cxx +++ /dev/null @@ -1,21 +0,0 @@ -// Filename: dxSavedFrameBuffer7.cxx -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 "dxSavedFrameBuffer7.h" - -TypeHandle DXSavedFrameBuffer7::_type_handle; diff --git a/panda/src/dxgsg7/dxSavedFrameBuffer7.h b/panda/src/dxgsg7/dxSavedFrameBuffer7.h deleted file mode 100644 index 881971e1ee..0000000000 --- a/panda/src/dxgsg7/dxSavedFrameBuffer7.h +++ /dev/null @@ -1,64 +0,0 @@ -// Filename: dxSavedFrameBuffer7.h -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 DXSAVEDFRAMEBUFFER7_H -#define DXSAVEDFRAMEBUFFER7_H - -#include "pandabase.h" - -#include "savedFrameBuffer.h" -#include "texture.h" -#include "textureContext.h" -#include "pixelBuffer.h" - - -//////////////////////////////////////////////////////////////////// -// Class : DXSavedFrameBuffer7 -// Description : -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXSavedFrameBuffer7 : public SavedFrameBuffer { -public: - INLINE DXSavedFrameBuffer7(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - INLINE ~DXSavedFrameBuffer7(); - - PT(Texture) _back_rgba; - PT(PixelBuffer) _depth; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - SavedFrameBuffer::init_type(); - register_type(_type_handle, "DXSavedFrameBuffer7", - SavedFrameBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "dxSavedFrameBuffer7.I" - -#endif - diff --git a/panda/src/dxgsg7/dxTextureContext7.cxx b/panda/src/dxgsg7/dxTextureContext7.cxx index 375c3bc743..50b00c27b7 100644 --- a/panda/src/dxgsg7/dxTextureContext7.cxx +++ b/panda/src/dxgsg7/dxTextureContext7.cxx @@ -31,7 +31,7 @@ static const DWORD g_LowByteMask = 0x000000FF; #ifdef PANDA_BGRA_ORDER // assume Panda uses byte-order BGRA/LA to store pixels, which when read into little-endian word is ARGB/AL -// these macros GET from PixelBuffer, (wont work from DDSurface) +// these macros GET from Texture, (wont work from DDSurface) #define GET_RED_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask)) #define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD) & g_LowByteMask)) #else @@ -150,54 +150,54 @@ enum Format { //////////////////////////////////////////////////////////////////// // Function: DXTextureContext7::get_bits_per_pixel // Access: Protected -// Description: Maps from the PixelBuffer's Format symbols +// Description: Maps from the Texture's Format symbols // to bpp. returns # of alpha bits -// Note: PixelBuffer's format indicates REQUESTED final format, +// Note: Texture's format indicates REQUESTED final format, // not the stored format, which is indicated by pixelbuffer type //////////////////////////////////////////////////////////////////// unsigned int DXTextureContext7:: -get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { +get_bits_per_pixel(Texture::Format format, int *alphbits) { *alphbits = 0; // assume no alpha bits switch(format) { - case PixelBuffer::F_alpha: + case Texture::F_alpha: *alphbits = 8; return 8; - case PixelBuffer::F_color_index: - case PixelBuffer::F_red: - case PixelBuffer::F_green: - case PixelBuffer::F_blue: - case PixelBuffer::F_rgb332: - case PixelBuffer::F_luminance_alphamask: + case Texture::F_color_index: + case Texture::F_red: + case Texture::F_green: + case Texture::F_blue: + case Texture::F_rgb332: + case Texture::F_luminance_alphamask: *alphbits = 1; return 16; - case PixelBuffer::F_luminance_alpha: + case Texture::F_luminance_alpha: *alphbits = 8; return 16; - case PixelBuffer::F_luminance: + case Texture::F_luminance: return 8; - case PixelBuffer::F_rgba4: + case Texture::F_rgba4: *alphbits = 4; return 16; - case PixelBuffer::F_rgba5: + case Texture::F_rgba5: *alphbits = 1; return 16; - case PixelBuffer::F_depth_component: - case PixelBuffer::F_rgb5: + case Texture::F_depth_component: + case Texture::F_rgb5: return 16; - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgb: + case Texture::F_rgb8: + case Texture::F_rgb: return 24; - case PixelBuffer::F_rgba8: - case PixelBuffer::F_rgba: + case Texture::F_rgba8: + case Texture::F_rgba: *alphbits = 8; return 32; - case PixelBuffer::F_rgbm: + case Texture::F_rgbm: *alphbits = 1; return 32; - case PixelBuffer::F_rgb12: + case Texture::F_rgb12: return 36; - case PixelBuffer::F_rgba12: + case Texture::F_rgba12: *alphbits = 12; return 48; } @@ -218,7 +218,7 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS return hr; } - //pbuf contains raw ARGB in PixelBuffer byteorder + //pbuf contains raw ARGB in Texture byteorder DWORD lPitch = ddsd.lPitch; BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; @@ -672,7 +672,7 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS return S_OK; } -HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { +HRESULT ConvertDDSurftoPixBuf(Texture *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { HRESULT hr; DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); @@ -681,7 +681,7 @@ HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) assert((dwNumComponents==3) || (dwNumComponents==4)); // cant handle anything else now - BYTE *pbuf=pixbuf->_image.p(); + BYTE *pbuf=pixbuf->modify_ram_image().p(); if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) { dxgsg7_cat.error() << "ConvertDDSurftoPixBuf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n"; @@ -732,7 +732,7 @@ HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) //make sure there's enough space in the pixbuf, its size must match (especially xsize) // or scanlines will be too long - if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) { + if(!((dwCopyWidth==pixbuf->get_x_size()) && (dwCopyHeight<=(DWORD)pixbuf->get_y_size()))) { pDDSurf->Unlock(NULL); assert(0); dxgsg7_cat.error() << "ConvertDDSurftoPixBuf, PixBuf incorrect size to hold display surface!\n"; @@ -742,7 +742,7 @@ HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) // others not handled yet assert((ddsd.ddpfPixelFormat.dwRGBBitCount==32)||(ddsd.ddpfPixelFormat.dwRGBBitCount==16)||(ddsd.ddpfPixelFormat.dwRGBBitCount==24)); - //pbuf contains raw ARGB in PixelBuffer byteorder + //pbuf contains raw ARGB in Texture byteorder DWORD lPitch = ddsd.lPitch; BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; @@ -751,7 +751,7 @@ HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) if(dxgsg7_cat.is_debug()) dxgsg7_cat.debug() << "ConvertDDSurftoPixBuf converting " << ddsd.ddpfPixelFormat.dwRGBBitCount << "bpp DDSurf to " - << dwNumComponents << "-channel panda PixelBuffer\n"; + << dwNumComponents << "-channel panda Texture\n"; if(dwNumComponents==4) { @@ -1017,8 +1017,6 @@ LPDIRECTDRAWSURFACE7 DXTextureContext7::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevi assert(_texture!=NULL); - PixelBuffer *pbuf = _texture->_pbuffer; - #ifdef USE_TEXFMTVEC int cNumTexPixFmts=TexturePixelFormats.size(); #endif @@ -1035,12 +1033,12 @@ LPDIRECTDRAWSURFACE7 DXTextureContext7::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevi #endif // bpp indicates requested fmt, not pixbuf fmt - DWORD bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); - PixelBuffer::Type pixbuf_type = pbuf->get_image_type(); - DWORD cNumColorChannels = pbuf->get_num_components(); + DWORD bpp = get_bits_per_pixel(_texture->get_format(), &cNumAlphaBits); + Texture::ComponentType pixbuf_type = _texture->get_component_type(); + DWORD cNumColorChannels = _texture->get_num_components(); - DWORD dwOrigWidth = (DWORD)pbuf->get_xsize(); - DWORD dwOrigHeight = (DWORD)pbuf->get_ysize(); + DWORD dwOrigWidth = (DWORD)_texture->get_x_size(); + DWORD dwOrigHeight = (DWORD)_texture->get_y_size(); // Use the device caps so we can check if the device has any constraints // when using textures. @@ -1061,9 +1059,9 @@ LPDIRECTDRAWSURFACE7 DXTextureContext7::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevi ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)|| - (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) || - (pbuf->get_format() == PixelBuffer::F_luminance)) { + if((_texture->get_format() == Texture::F_luminance_alpha)|| + (_texture->get_format() == Texture::F_luminance_alphamask) || + (_texture->get_format() == Texture::F_luminance)) { ddsd.ddpfPixelFormat.dwFlags = DDPF_LUMINANCE; } @@ -1132,13 +1130,13 @@ LPDIRECTDRAWSURFACE7 DXTextureContext7::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevi // need 2 add checks for errors PNMImage pnmi_src; PNMImage *pnmi = new PNMImage(ddsd.dwWidth, ddsd.dwHeight, cNumColorChannels); - pbuf->store(pnmi_src); + _texture->store(pnmi_src); pnmi->quick_filter_from(pnmi_src,0,0); - pbuf->load(*pnmi); // violates device independence of pixbufs + _texture->load(*pnmi); // violates device independence of pixbufs - dwOrigWidth = (DWORD)pbuf->get_xsize(); - dwOrigHeight = (DWORD)pbuf->get_ysize(); + dwOrigWidth = (DWORD)_texture->get_x_size(); + dwOrigHeight = (DWORD)_texture->get_y_size(); delete pnmi; } @@ -1661,18 +1659,18 @@ downsample_image(uchar *source, int num_pixels, int component_width) { HRESULT DXTextureContext7:: FillDDSurfTexturePixels(void) { - PixelBuffer *pbuf = _texture->get_ram_image(); - if (pbuf == (PixelBuffer *)NULL) { + CPTA_uchar orig_image = _texture->get_ram_image(); + if (orig_image.empty()) { dxgsg7_cat.fatal() << "CreateTexture: get_ram_image() failed\n"; // The texture doesn't have an image to load. return E_FAIL; } - PTA_uchar image = pbuf->_image; - if (pbuf->get_component_width() != 1) { + PTA_uchar image = (PTA_uchar &)orig_image; + if (_texture->get_component_width() != 1) { image = downsample_image(image, - pbuf->get_xsize() * pbuf->get_ysize() * pbuf->get_num_components(), - pbuf->get_component_width()); + _texture->get_x_size() * _texture->get_y_size() * _texture->get_num_components(), + _texture->get_component_width()); } HRESULT hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,image.p(),_surface); @@ -1688,7 +1686,7 @@ FillDDSurfTexturePixels(void) { DWORD i,oldcurxsize,oldcurysize,curxsize,curysize,cMipMapCount=ddsd.dwMipMapCount; assert(ddsd.dwMipMapCount<20); - DWORD cNumColorChannels = pbuf->get_num_components(); + DWORD cNumColorChannels = _texture->get_num_components(); curxsize=ddsd.dwWidth; curysize=ddsd.dwHeight; diff --git a/panda/src/dxgsg7/dxTextureContext7.h b/panda/src/dxgsg7/dxTextureContext7.h index 2524cfe38b..11ddf0b1f4 100644 --- a/panda/src/dxgsg7/dxTextureContext7.h +++ b/panda/src/dxgsg7/dxTextureContext7.h @@ -55,7 +55,7 @@ public: HRESULT FillDDSurfTexturePixels(void); protected: - unsigned int get_bits_per_pixel(PixelBuffer::Format format, int *alphbits); + unsigned int get_bits_per_pixel(Texture::Format format, int *alphbits); public: static TypeHandle get_class_type() { diff --git a/panda/src/dxgsg7/dxgsg7_composite1.cxx b/panda/src/dxgsg7/dxgsg7_composite1.cxx index f387e370cd..8805be0ff2 100644 --- a/panda/src/dxgsg7/dxgsg7_composite1.cxx +++ b/panda/src/dxgsg7/dxgsg7_composite1.cxx @@ -1,7 +1,6 @@ #include "dxgsg7base.h" #include "dxgsg7base.cxx" #include "config_dxgsg7.cxx" -#include "dxSavedFrameBuffer7.cxx" #include "dxTextureContext7.cxx" #include "wdxGraphicsPipe7.cxx" #include "wdxGraphicsWindow7.cxx" diff --git a/panda/src/dxgsg8/Sources.pp b/panda/src/dxgsg8/Sources.pp index 235abee804..96eddfee2d 100644 --- a/panda/src/dxgsg8/Sources.pp +++ b/panda/src/dxgsg8/Sources.pp @@ -26,7 +26,7 @@ // build dxGraphicsStateGuardian separately since its so big #define SOURCES \ - dxGraphicsStateGuardian8.cxx dxSavedFrameBuffer8.I dxSavedFrameBuffer8.h \ + dxGraphicsStateGuardian8.cxx \ dxGraphicsDevice8.h \ wdxGraphicsPipe8.I wdxGraphicsPipe8.h \ wdxGraphicsWindow8.I wdxGraphicsWindow8.h \ @@ -34,7 +34,7 @@ #define INCLUDED_SOURCES \ config_dxgsg8.cxx \ - dxSavedFrameBuffer8.cxx dxTextureContext8.cxx \ + dxTextureContext8.cxx \ d3dfont8.cxx \ dxGraphicsDevice8.cxx \ wdxGraphicsPipe8.cxx wdxGraphicsWindow8.cxx diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index 02f893929c..4e579d500c 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -18,7 +18,6 @@ #include "config_dxgsg8.h" #include "dxGraphicsStateGuardian8.h" -#include "dxSavedFrameBuffer8.h" #include "dxTextureContext8.h" #include "graphicsPipeSelection.h" #include "wdxGraphicsWindow8.h" @@ -143,7 +142,6 @@ init_libdxgsg8() { initialized = true; DXGraphicsStateGuardian8::init_type(); - DXSavedFrameBuffer8::init_type(); DXTextureContext8::init_type(); wdxGraphicsPipe8::init_type(); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 9a7eca55f9..38babf6888 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -1549,8 +1549,8 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { modify_state(RenderState::make (TextureAttrib::make(tex), TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); - tex_xsize = tex->_pbuffer->get_xsize(); - tex_ysize = tex->_pbuffer->get_ysize(); + tex_xsize = tex->get_x_size(); + tex_ysize = tex->get_y_size(); } // save the modelview matrix @@ -2657,8 +2657,8 @@ apply_texture(TextureContext *tc) { Texture *tex = tc->_texture; Texture::WrapMode wrapU,wrapV; - wrapU=tex->get_wrapu(); - wrapV=tex->get_wrapv(); + wrapU=tex->get_wrap_u(); + wrapV=tex->get_wrap_v(); if (wrapU!=_CurTexWrapModeU) { _pD3DDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,get_texture_wrap_mode(wrapU)); @@ -2783,15 +2783,15 @@ release_texture(TextureContext *tc) { // copies current display region in framebuffer to the texture // usually its more efficient to do SetRenderTgt void DXGraphicsStateGuardian8:: -copy_texture(Texture *tex, const DisplayRegion *dr) { +framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { + set_read_buffer(rb); HRESULT hr; int xo, yo, w, h; dr->get_region_pixels_i(xo, yo, w, h); - PixelBuffer *pb = tex->_pbuffer; - pb->set_xsize(w); - pb->set_ysize(h); + tex->set_x_size(w); + tex->set_y_size(h); TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { @@ -2833,151 +2833,93 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { //////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::copy_texture -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { - set_read_buffer(rb); - copy_texture(tex, dr); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { - // This code is now invalidated by the new design; perhaps the - // interface is not needed anyway. - dxgsg8_cat.error() << "texture_to_pixel_buffer unimplemented for DX!\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr) { - dxgsg8_cat.error() - << "texture_to_pixel_buffer unimplemented!\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::copy_pixel_buffer +// Function: DXGraphicsStateGuardian9::framebuffer_copy_to_ram // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian8:: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { +framebuffer_copy_to_ram(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { + set_read_buffer(rb); - RECT SrcCopyRect; - nassertr(pb != NULL && dr != NULL, false); + RECT SrcCopyRect; + nassertr(tex != NULL && dr != NULL, false); + + int xo, yo, w, h; + dr->get_region_pixels_i(xo, yo, w, h); - int xo, yo, w, h; - dr->get_region_pixels_i(xo, yo, w, h); + tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgb); - // only handled simple case - nassertr(xo == 0 && yo==0 && w == pb->get_xsize() && h == pb->get_ysize(), false); + SrcCopyRect.top = yo; + SrcCopyRect.left = xo; + SrcCopyRect.right = xo + w; + SrcCopyRect.bottom = yo + h; + + IDirect3DSurface8 *pD3DSurf; + HRESULT hr; + + if(_cur_read_pixel_buffer & RenderBuffer::T_back) { + hr=_pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); + + if(FAILED(hr)) { + dxgsg8_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); + return false; + } + + // note if you try to grab the backbuffer and full-screen anti-aliasing is on, + // the backbuffer might be larger than the window size. for screenshots its safer to get the front buffer. + + } else if(_cur_read_pixel_buffer & RenderBuffer::T_front) { + // must create a A8R8G8B8 sysmem surface for GetFrontBuffer to copy to + + DWORD TmpSurfXsize,TmpSurfYsize; + + if(_pScrn->PresParams.Windowed) { + // GetFrontBuffer retrieves the entire desktop for a monitor, so + // need space for that + + MONITORINFO minfo; + minfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(_pScrn->hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor + + TmpSurfXsize = RECT_XSIZE(minfo.rcMonitor); + TmpSurfYsize = RECT_YSIZE(minfo.rcMonitor); - IDirect3DSurface8 *pD3DSurf; - HRESULT hr; + // set SrcCopyRect to client area of window in scrn coords + ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.left ); + ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.right ); - RECT WindRect; - GetWindowRect(_pScrn->hWnd,&WindRect); - - // just handling front and backbuf for now, not textures yet - if(_cur_read_pixel_buffer & RenderBuffer::T_back) { - hr=_pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); - - if(FAILED(hr)) { - dxgsg8_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); - return false; - } - - D3DSURFACE_DESC SurfDesc; - hr = pD3DSurf->GetDesc(&SurfDesc); - - SrcCopyRect.top=SrcCopyRect.left=0; - SrcCopyRect.right=SurfDesc.Width; - SrcCopyRect.bottom=SurfDesc.Height; - - // note if you try to grab the backbuffer and full-screen anti-aliasing is on, - // the backbuffer might be larger than the window size. for screenshots its safer to get the front buffer. - - } else if(_cur_read_pixel_buffer & RenderBuffer::T_front) { - // must create a A8R8G8B8 sysmem surface for GetFrontBuffer to copy to - - DWORD TmpSurfXsize,TmpSurfYsize; - - if(_pScrn->PresParams.Windowed) { - // GetFrontBuffer retrieves the entire desktop for a monitor, so need space for that - - MONITORINFO minfo; - minfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(_pScrn->hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor - - TmpSurfXsize=RECT_XSIZE(minfo.rcMonitor); - TmpSurfYsize=RECT_YSIZE(minfo.rcMonitor); - - // set SrcCopyRect to client area of window in scrn coords - GetClientRect( _pScrn->hWnd, &SrcCopyRect); - ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.left ); - ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.right ); - } else { - TmpSurfXsize=RECT_XSIZE(WindRect); - TmpSurfYsize=RECT_YSIZE(WindRect); - - SrcCopyRect.top=SrcCopyRect.left=0; - SrcCopyRect.right=TmpSurfXsize; - SrcCopyRect.bottom=TmpSurfYsize; - } - - hr=_pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf); - if(FAILED(hr)) { - dxgsg8_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); - return false; - } - - hr=_pD3DDevice->GetFrontBuffer(pD3DSurf); - - if(hr==D3DERR_DEVICELOST) { - pD3DSurf->Release(); - dxgsg8_cat.error() << "copy_pixel_buffer failed: device lost\n"; - return false; - } } else { - dxgsg8_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; - return false; + RECT WindRect; + GetWindowRect(_pScrn->hWnd,&WindRect); + TmpSurfXsize = RECT_XSIZE(WindRect); + TmpSurfYsize = RECT_YSIZE(WindRect); + } + + hr=_pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf); + if(FAILED(hr)) { + dxgsg8_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); + return false; + } + + hr=_pD3DDevice->GetFrontBuffer(pD3DSurf); + + if(hr==D3DERR_DEVICELOST) { + pD3DSurf->Release(); + dxgsg8_cat.error() << "copy_pixel_buffer failed: device lost\n"; + return false; } - if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) { - dxgsg8_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n"; - return false; - } - - (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb); - - RELEASE(pD3DSurf,dxgsg8,"pD3DSurf",RELEASE_ONCE); - - nassertr(!pb->_image.empty(), false); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::copy_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian8:: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb) { - set_read_buffer(rb); - return copy_pixel_buffer(pb, dr); + } else { + dxgsg8_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; + return false; + } + + (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,tex); + + RELEASE(pD3DSurf,dxgsg8,"pD3DSurf",RELEASE_ONCE); + + nassertr(tex->has_ram_image(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -3997,55 +3939,6 @@ set_blend_mode() { enable_blend(false); } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::save_frame_buffer -// Access: Public -// Description: Saves the indicated planes of the frame buffer -// (within the indicated display region) and returns it -// in some meaningful form that can be restored later -// via restore_frame_buffer(). This is a helper -// function for push_frame_buffer() and -// pop_frame_buffer(). -//////////////////////////////////////////////////////////////////// -PT(SavedFrameBuffer) DXGraphicsStateGuardian8:: -save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr) { - - dxgsg8_cat.error() << "save_frame_buffer unimplemented!!\n"; - return NULL; - -#if 0 - DXSavedFrameBuffer *sfb = new DXSavedFrameBuffer(buffer, dr); - - if (buffer._buffer_type & RenderBuffer::T_depth) { - // Save the depth buffer. - sfb->_depth = - new PixelBuffer(PixelBuffer::depth_buffer(dr->get_pixel_width(), - dr->get_pixel_height())); - copy_pixel_buffer(sfb->_depth, dr, buffer); - } - - if (buffer._buffer_type & RenderBuffer::T_back) { - // Save the color buffer. - sfb->_back_rgba = new Texture; - copy_texture(sfb->_back_rgba, dr, buffer); - } - - return sfb; -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::restore_frame_buffer -// Access: Public -// Description: Restores the frame buffer that was previously saved. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -restore_frame_buffer(SavedFrameBuffer *frame_buffer) { - dxgsg8_cat.error() << "restore_frame_buffer unimplemented!!\n"; - return; -} - TypeHandle DXGraphicsStateGuardian8::get_type(void) const { return get_class_type(); } @@ -4655,4 +4548,3 @@ POS_TEX_VERTEX junk11; POS_COLOR_TEX_VERTEX junk22; POS_NORM_COLOR_TEX_VERTEX junk33; #endif - diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 6386ad9728..e9414ba463 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -29,7 +29,6 @@ #include "graphicsStateGuardian.h" #include "geomprimitives.h" #include "texture.h" -#include "pixelBuffer.h" #include "displayRegion.h" #include "material.h" #include "depthTestAttrib.h" @@ -94,17 +93,10 @@ public: virtual void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr, - const RenderBuffer &rb); - - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb); - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr); - - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb); + virtual void framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb); + virtual bool framebuffer_copy_to_ram(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb); virtual void apply_material(const Material *material); virtual void apply_fog(Fog *fog); @@ -159,9 +151,6 @@ protected: void free_nondx_resources(); // free local internal buffers void free_d3d_device(void); - virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - virtual void restore_frame_buffer(SavedFrameBuffer *frame_buffer); void set_draw_buffer(const RenderBuffer &rb); void set_read_buffer(const RenderBuffer &rb); diff --git a/panda/src/dxgsg8/dxSavedFrameBuffer8.I b/panda/src/dxgsg8/dxSavedFrameBuffer8.I deleted file mode 100644 index 10ce94ed36..0000000000 --- a/panda/src/dxgsg8/dxSavedFrameBuffer8.I +++ /dev/null @@ -1,39 +0,0 @@ -// Filename: dxSavedFrameBuffer8.I -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: DXSavedFrameBuffer8::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXSavedFrameBuffer8:: -DXSavedFrameBuffer8(const RenderBuffer &buffer, CPT(DisplayRegion) dr) : - SavedFrameBuffer(buffer, dr) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: DXSavedFrameBuffer8::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXSavedFrameBuffer8:: -~DXSavedFrameBuffer8() { -} - diff --git a/panda/src/dxgsg8/dxSavedFrameBuffer8.cxx b/panda/src/dxgsg8/dxSavedFrameBuffer8.cxx deleted file mode 100644 index 10e46002aa..0000000000 --- a/panda/src/dxgsg8/dxSavedFrameBuffer8.cxx +++ /dev/null @@ -1,21 +0,0 @@ -// Filename: dxSavedFrameBuffer8.cxx -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 "dxSavedFrameBuffer8.h" - -TypeHandle DXSavedFrameBuffer8::_type_handle; diff --git a/panda/src/dxgsg8/dxSavedFrameBuffer8.h b/panda/src/dxgsg8/dxSavedFrameBuffer8.h deleted file mode 100644 index b471114576..0000000000 --- a/panda/src/dxgsg8/dxSavedFrameBuffer8.h +++ /dev/null @@ -1,64 +0,0 @@ -// Filename: dxSavedFrameBuffer8.h -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 DXSAVEDFRAMEBUFFER8_H -#define DXSAVEDFRAMEBUFFER8_H - -#include "pandabase.h" - -#include "savedFrameBuffer.h" -#include "texture.h" -#include "textureContext.h" -#include "pixelBuffer.h" - - -//////////////////////////////////////////////////////////////////// -// Class : DXSavedFrameBuffer8 -// Description : -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXSavedFrameBuffer8 : public SavedFrameBuffer { -public: - INLINE DXSavedFrameBuffer8(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - INLINE ~DXSavedFrameBuffer8(); - - PT(Texture) _back_rgba; - PT(PixelBuffer) _depth; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - SavedFrameBuffer::init_type(); - register_type(_type_handle, "DXSavedFrameBuffer8", - SavedFrameBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "DXSavedFrameBuffer8.I" - -#endif - diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index bd0719632c..1964e1fd8e 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -31,7 +31,7 @@ static const DWORD g_LowByteMask = 0x000000FF; #ifdef PANDA_BGRA_ORDER // assume Panda uses byte-order BGRA/LA to store pixels, which when read into little-endian word is ARGB/AL -// these macros GET from PixelBuffer, (wont work from DDSurface) +// these macros GET from Texture, (wont work from DDSurface) #define GET_RED_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask)) #define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD) & g_LowByteMask)) #else @@ -135,54 +135,54 @@ enum Format { //////////////////////////////////////////////////////////////////// // Function: DXTextureContext8::get_bits_per_pixel // Access: Protected -// Description: Maps from the PixelBuffer's Format symbols +// Description: Maps from the Texture's Format symbols // to bpp. returns # of alpha bits -// Note: PixelBuffer's format indicates REQUESTED final format, +// Note: Texture's format indicates REQUESTED final format, // not the stored format, which is indicated by pixelbuffer type //////////////////////////////////////////////////////////////////// unsigned int DXTextureContext8:: -get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { +get_bits_per_pixel(Texture::Format format, int *alphbits) { *alphbits = 0; // assume no alpha bits switch(format) { - case PixelBuffer::F_alpha: + case Texture::F_alpha: *alphbits = 8; - case PixelBuffer::F_color_index: - case PixelBuffer::F_red: - case PixelBuffer::F_green: - case PixelBuffer::F_blue: - case PixelBuffer::F_rgb332: + case Texture::F_color_index: + case Texture::F_red: + case Texture::F_green: + case Texture::F_blue: + case Texture::F_rgb332: return 8; - case PixelBuffer::F_luminance_alphamask: + case Texture::F_luminance_alphamask: *alphbits = 1; return 16; - case PixelBuffer::F_luminance_alpha: + case Texture::F_luminance_alpha: *alphbits = 8; return 16; - case PixelBuffer::F_luminance: + case Texture::F_luminance: return 8; - case PixelBuffer::F_rgba4: + case Texture::F_rgba4: *alphbits = 4; return 16; - case PixelBuffer::F_rgba5: + case Texture::F_rgba5: *alphbits = 1; return 16; - case PixelBuffer::F_depth_component: - case PixelBuffer::F_rgb5: + case Texture::F_depth_component: + case Texture::F_rgb5: return 16; - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgb: + case Texture::F_rgb8: + case Texture::F_rgb: return 24; - case PixelBuffer::F_rgba8: - case PixelBuffer::F_rgba: - case PixelBuffer::F_rgbm: - if(format==PixelBuffer::F_rgbm) // does this make any sense? + case Texture::F_rgba8: + case Texture::F_rgba: + case Texture::F_rgbm: + if(format==Texture::F_rgbm) // does this make any sense? *alphbits = 1; else *alphbits = 8; return 32; - case PixelBuffer::F_rgb12: + case Texture::F_rgb12: return 36; - case PixelBuffer::F_rgba12: + case Texture::F_rgba12: *alphbits = 12; return 48; } @@ -190,20 +190,20 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { } // still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer -HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf) { -// copies SrcRect in pD3DSurf to upper left of pixbuf +HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,Texture *texture) { +// copies SrcRect in pD3DSurf to upper left of texture HRESULT hr; - DWORD dwNumComponents=pixbuf->get_num_components(); + DWORD dwNumComponents=texture->get_num_components(); - assert(pixbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now - assert(pixbuf->get_image_type()==PixelBuffer::T_unsigned_byte); // cant handle anything else now + assert(texture->get_component_width()==sizeof(BYTE)); // cant handle anything else now + assert(texture->get_component_type()==Texture::T_unsigned_byte); // cant handle anything else now assert((dwNumComponents==3) || (dwNumComponents==4)); // cant handle anything else now assert(IS_VALID_PTR(pD3DSurf8)); - BYTE *pbuf=pixbuf->_image.p(); + BYTE *pbuf=texture->modify_ram_image().p(); if(IsBadWritePtr(pD3DSurf8,sizeof(DWORD))) { - dxgsg8_cat.error() << "ConvertDDSurftoPixBuf failed: bad pD3DSurf ptr value (" << ((void*)pD3DSurf8) << ")\n"; + dxgsg8_cat.error() << "ConvertDDSurftoTexture failed: bad pD3DSurf ptr value (" << ((void*)pD3DSurf8) << ")\n"; exit(1); } @@ -219,11 +219,11 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelB dwCopyWidth=RECT_XSIZE(SrcRect); dwCopyHeight=RECT_YSIZE(SrcRect); - //make sure there's enough space in the pixbuf, its size must match (especially xsize) + //make sure there's enough space in the texture, its size must match (especially xsize) // or scanlines will be too long - if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) { - dxgsg8_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size too small to hold display surface!\n"; + if(!((dwCopyWidth==texture->get_x_size()) && (dwCopyHeight<=(DWORD)texture->get_y_size()))) { + dxgsg8_cat.error() << "ConvertDDSurftoPixBuf, Texture size too small to hold display surface!\n"; assert(0); return E_FAIL; } @@ -239,7 +239,7 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelB (SurfDesc.Format==D3DFMT_R5G6B5)||(SurfDesc.Format==D3DFMT_X1R5G5B5)||(SurfDesc.Format==D3DFMT_A1R5G5B5)|| (SurfDesc.Format==D3DFMT_A4R4G4B4)); - //pbuf contains raw ARGB in PixelBuffer byteorder + //pbuf contains raw ARGB in Texture byteorder DWORD BytePitch = LockedRect.Pitch; BYTE* pSurfBytes = (BYTE*)LockedRect.pBits; @@ -249,7 +249,7 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelB if(dxgsg8_cat.is_debug()) { dxgsg8_cat.debug() << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " - << dwNumComponents << "-channel panda PixelBuffer\n"; + << dwNumComponents << "-channel panda Texture\n"; } DWORD *pDstWord = (DWORD *) pbuf; @@ -285,7 +285,7 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelB #endif } } else { - // 24bpp pixbuf case (numComponents==3) + // 24bpp texture case (numComponents==3) DWORD *pSrcWord; pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1); for(DWORD y=0; y_pbuffer; - // bpp indicates requested fmt, not pixbuf fmt - DWORD target_bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); - PixelBuffer::Type pixbuf_type = pbuf->get_image_type(); - DWORD cNumColorChannels = pbuf->get_num_components(); + // bpp indicates requested fmt, not texture fmt + DWORD target_bpp = get_bits_per_pixel(_texture->get_format(), &cNumAlphaBits); + DWORD cNumColorChannels = _texture->get_num_components(); //PRINT_REFCNT(dxgsg8,scrn.pD3D8); - DWORD dwOrigWidth = (DWORD)pbuf->get_xsize(); - DWORD dwOrigHeight = (DWORD)pbuf->get_ysize(); + DWORD dwOrigWidth = (DWORD)_texture->get_x_size(); + DWORD dwOrigHeight = (DWORD)_texture->get_y_size(); - if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)|| - (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) || - (pbuf->get_format() == PixelBuffer::F_luminance)) { + if((_texture->get_format() == Texture::F_luminance_alpha)|| + (_texture->get_format() == Texture::F_luminance_alphamask) || + (_texture->get_format() == Texture::F_luminance)) { bNeedLuminance = true; } @@ -496,7 +494,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { _PixBufD3DFmt=D3DFMT_UNKNOWN; - // figure out what 'D3DFMT' the PixelBuffer is in, so D3DXLoadSurfFromMem knows how to perform copy + // figure out what 'D3DFMT' the Texture is in, so D3DXLoadSurfFromMem knows how to perform copy switch(cNumColorChannels) { case 1: @@ -567,13 +565,13 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { // need 2 add checks for errors PNMImage pnmi_src; PNMImage *pnmi = new PNMImage(TargetWidth, TargetHeight, cNumColorChannels); - pbuf->store(pnmi_src); + _texture->store(pnmi_src); pnmi->quick_filter_from(pnmi_src,0,0); - pbuf->load(*pnmi); // violates device independence of pixbufs + _texture->load(*pnmi); // violates device independence of pixbufs - dwOrigWidth = (DWORD)pbuf->get_xsize(); - dwOrigHeight = (DWORD)pbuf->get_ysize(); + dwOrigWidth = (DWORD)_texture->get_x_size(); + dwOrigHeight = (DWORD)_texture->get_y_size(); delete pnmi; } */ @@ -601,7 +599,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { switch(target_bpp) { // IMPORTANT NOTE: - // target_bpp is REQUESTED bpp, not what exists in the pixbuf array (the pixbuf array contains cNumColorChannels*8bits) + // target_bpp is REQUESTED bpp, not what exists in the texture array (the texture array contains cNumColorChannels*8bits) case 32: if(!((cNumColorChannels==3) || (cNumColorChannels==4))) @@ -772,7 +770,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { /////////////////////////////////////////////////////////// found_matching_format: - // We found a suitable format that matches the pbuffer's format. + // We found a suitable format that matches the texture's format. if (_texture->get_match_framebuffer_format()) { // Instead of creating a texture with the found format, we will @@ -936,8 +934,8 @@ FillDDSurfTexturePixels(void) { HRESULT hr=E_FAIL; assert(IS_VALID_PTR(_texture)); - PixelBuffer *pbuf = _texture->get_ram_image(); - if (pbuf == (PixelBuffer *)NULL) { + CPTA_uchar image = _texture->get_ram_image(); + if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it // might be a texture we've rendered to by frame buffer // operations or something. @@ -946,12 +944,12 @@ FillDDSurfTexturePixels(void) { assert(IS_VALID_PTR(_pD3DTexture8)); - DWORD OrigWidth = (DWORD) pbuf->get_xsize(); - DWORD OrigHeight = (DWORD) pbuf->get_ysize(); - DWORD cNumColorChannels = pbuf->get_num_components(); + DWORD OrigWidth = (DWORD) _texture->get_x_size(); + DWORD OrigHeight = (DWORD) _texture->get_y_size(); + DWORD cNumColorChannels = _texture->get_num_components(); D3DFORMAT SrcFormat=_PixBufD3DFmt; - BYTE *pPixels=(BYTE*)pbuf->_image.p(); - int component_width = pbuf->get_component_width(); + BYTE *pPixels=(BYTE*)image.p(); + int component_width = _texture->get_component_width(); assert(IS_VALID_PTR(pPixels)); @@ -1009,7 +1007,7 @@ FillDDSurfTexturePixels(void) { // original image, but dx8 doesn't support high-precision images // anyway. - int num_components = pbuf->get_num_components(); + int num_components = _texture->get_num_components(); int num_pixels = OrigWidth * OrigHeight * num_components; BYTE *pTempPixBuf = new BYTE[num_pixels]; if(!IS_VALID_PTR(pTempPixBuf)) { diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h index 38270d8e02..e57cd3282d 100644 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ b/panda/src/dxgsg8/dxTextureContext8.h @@ -41,7 +41,7 @@ public: Texture *_tex; // ptr to parent, primarily for access to namestr IDirect3DTexture8 *CreateTexture(DXScreenData &scrn); - D3DFORMAT _PixBufD3DFmt; // the 'D3DFORMAT' the Panda PixelBuffer fmt corresponds to + D3DFORMAT _PixBufD3DFmt; // the 'D3DFORMAT' the Panda TextureBuffer fmt corresponds to bool _bHasMipMaps; @@ -54,7 +54,7 @@ public: HRESULT FillDDSurfTexturePixels(void); protected: - unsigned int get_bits_per_pixel(PixelBuffer::Format format, int *alphbits); + unsigned int get_bits_per_pixel(Texture::Format format, int *alphbits); public: static TypeHandle get_class_type() { @@ -74,7 +74,7 @@ private: static TypeHandle _type_handle; }; -extern HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf); +extern HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,Texture *pixbuf); #endif diff --git a/panda/src/dxgsg8/dxgsg8_composite1.cxx b/panda/src/dxgsg8/dxgsg8_composite1.cxx index b6c2566c50..8b9b5d9b18 100644 --- a/panda/src/dxgsg8/dxgsg8_composite1.cxx +++ b/panda/src/dxgsg8/dxgsg8_composite1.cxx @@ -1,6 +1,5 @@ #include "dxgsg8base.h" #include "config_dxgsg8.cxx" -#include "dxSavedFrameBuffer8.cxx" #include "dxTextureContext8.cxx" #include "d3dfont8.cxx" #include "wdxGraphicsPipe8.cxx" diff --git a/panda/src/dxgsg9/Sources.pp b/panda/src/dxgsg9/Sources.pp index 7f77653fe9..561a02c811 100755 --- a/panda/src/dxgsg9/Sources.pp +++ b/panda/src/dxgsg9/Sources.pp @@ -24,7 +24,7 @@ // build dxGraphicsStateGuardian separately since its so big #define SOURCES \ - dxGraphicsStateGuardian9.cxx dxSavedFrameBuffer9.I dxSavedFrameBuffer9.h \ + dxGraphicsStateGuardian9.cxx \ dxGraphicsDevice9.h \ wdxGraphicsPipe9.I wdxGraphicsPipe9.h \ wdxGraphicsWindow9.I wdxGraphicsWindow9.h \ @@ -32,7 +32,7 @@ #define INCLUDED_SOURCES \ config_dxgsg9.cxx \ - dxSavedFrameBuffer9.cxx dxTextureContext9.cxx \ + dxTextureContext9.cxx \ d3dfont9.cxx \ dxGraphicsDevice9.cxx \ wdxGraphicsPipe9.cxx wdxGraphicsWindow9.cxx diff --git a/panda/src/dxgsg9/config_dxgsg9.cxx b/panda/src/dxgsg9/config_dxgsg9.cxx index ca8b98961b..dfaa1b3963 100755 --- a/panda/src/dxgsg9/config_dxgsg9.cxx +++ b/panda/src/dxgsg9/config_dxgsg9.cxx @@ -18,7 +18,6 @@ #include "config_dxgsg9.h" #include "dxGraphicsStateGuardian9.h" -#include "dxSavedFrameBuffer9.h" #include "dxTextureContext9.h" #include "graphicsPipeSelection.h" #include "wdxGraphicsWindow9.h" @@ -143,7 +142,6 @@ init_libdxgsg9() { initialized = true; DXGraphicsStateGuardian9::init_type(); - DXSavedFrameBuffer9::init_type(); DXTextureContext9::init_type(); wdxGraphicsPipe9::init_type(); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index f94a03170f..1334541f04 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -1530,8 +1530,8 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { modify_state(RenderState::make (TextureAttrib::make(tex), TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); - tex_xsize = tex->_pbuffer->get_xsize(); - tex_ysize = tex->_pbuffer->get_ysize(); + tex_xsize = tex->get_x_size(); + tex_ysize = tex->get_y_size(); } // save the modelview matrix @@ -2640,8 +2640,8 @@ apply_texture(TextureContext *tc) { Texture *tex = tc->_texture; Texture::WrapMode wrapU,wrapV; - wrapU=tex->get_wrapu(); - wrapV=tex->get_wrapv(); + wrapU=tex->get_wrap_u(); + wrapV=tex->get_wrap_v(); if (wrapU!=_CurTexWrapModeU) { _pD3DDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,get_texture_wrap_mode(wrapU)); @@ -2766,15 +2766,15 @@ release_texture(TextureContext *tc) { // copies current display region in framebuffer to the texture // usually its more efficient to do SetRenderTgt void DXGraphicsStateGuardian9:: -copy_texture(Texture *tex, const DisplayRegion *dr) { +framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { + set_read_buffer(rb); HRESULT hr; int xo, yo, w, h; dr->get_region_pixels_i(xo, yo, w, h); - PixelBuffer *pb = tex->_pbuffer; - pb->set_xsize(w); - pb->set_ysize(h); + tex->set_x_size(w); + tex->set_y_size(h); TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { @@ -2819,153 +2819,94 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { SAFE_RELEASE(pTexSurfaceLev0); } - //////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::copy_texture -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: -copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { - set_read_buffer(rb); - copy_texture(tex, dr); -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { - // This code is now invalidated by the new design; perhaps the - // interface is not needed anyway. - dxgsg9_cat.error() << "texture_to_pixel_buffer unimplemented for DX!\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr) { - dxgsg9_cat.error() - << "texture_to_pixel_buffer unimplemented!\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::copy_pixel_buffer +// Function: DXGraphicsStateGuardian9::framebuffer_copy_to_ram // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian9:: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { +framebuffer_copy_to_ram(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { + set_read_buffer(rb); - RECT SrcCopyRect; - nassertr(pb != NULL && dr != NULL, false); + RECT SrcCopyRect; + nassertr(tex != NULL && dr != NULL, false); + + int xo, yo, w, h; + dr->get_region_pixels_i(xo, yo, w, h); - int xo, yo, w, h; - dr->get_region_pixels_i(xo, yo, w, h); + tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgb); - // only handled simple case - nassertr(xo == 0 && yo==0 && w == pb->get_xsize() && h == pb->get_ysize(), false); + SrcCopyRect.top = yo; + SrcCopyRect.left = xo; + SrcCopyRect.right = xo + w; + SrcCopyRect.bottom = yo + h; + + IDirect3DSurface9 *pD3DSurf; + HRESULT hr; + + if(_cur_read_pixel_buffer & RenderBuffer::T_back) { + hr=_pD3DDevice->GetBackBuffer(0, 0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); + + if(FAILED(hr)) { + dxgsg9_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); + return false; + } + + // note if you try to grab the backbuffer and full-screen anti-aliasing is on, + // the backbuffer might be larger than the window size. for screenshots its safer to get the front buffer. + + } else if(_cur_read_pixel_buffer & RenderBuffer::T_front) { + // must create a A8R8G8B8 sysmem surface for GetFrontBuffer to copy to + + DWORD TmpSurfXsize,TmpSurfYsize; + + if(_pScrn->PresParams.Windowed) { + // GetFrontBuffer retrieves the entire desktop for a monitor, so + // need space for that + + MONITORINFO minfo; + minfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(_pScrn->hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor + + TmpSurfXsize = RECT_XSIZE(minfo.rcMonitor); + TmpSurfYsize = RECT_YSIZE(minfo.rcMonitor); - IDirect3DSurface9 *pD3DSurf; - HRESULT hr; + // set SrcCopyRect to client area of window in scrn coords + ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.left ); + ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.right ); - RECT WindRect; - GetWindowRect(_pScrn->hWnd,&WindRect); - - // just handling front and backbuf for now, not textures yet - if(_cur_read_pixel_buffer & RenderBuffer::T_back) { - hr=_pD3DDevice->GetBackBuffer(0, 0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); - - if(FAILED(hr)) { - dxgsg9_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); - return false; - } - - D3DSURFACE_DESC SurfDesc; - hr = pD3DSurf->GetDesc(&SurfDesc); - - SrcCopyRect.top=SrcCopyRect.left=0; - SrcCopyRect.right=SurfDesc.Width; - SrcCopyRect.bottom=SurfDesc.Height; - - // note if you try to grab the backbuffer and full-screen anti-aliasing is on, - // the backbuffer might be larger than the window size. for screenshots its safer to get the front buffer. - - } else if(_cur_read_pixel_buffer & RenderBuffer::T_front) { - // must create a A8R8G8B8 sysmem surface for GetFrontBuffer to copy to - - DWORD TmpSurfXsize,TmpSurfYsize; - - if(_pScrn->PresParams.Windowed) { - // GetFrontBuffer retrieves the entire desktop for a monitor, so need space for that - - MONITORINFO minfo; - minfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(_pScrn->hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor - - TmpSurfXsize=RECT_XSIZE(minfo.rcMonitor); - TmpSurfYsize=RECT_YSIZE(minfo.rcMonitor); - - // set SrcCopyRect to client area of window in scrn coords - GetClientRect( _pScrn->hWnd, &SrcCopyRect); - ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.left ); - ClientToScreen( _pScrn->hWnd, (POINT*)&SrcCopyRect.right ); - } else { - TmpSurfXsize=RECT_XSIZE(WindRect); - TmpSurfYsize=RECT_YSIZE(WindRect); - - SrcCopyRect.top=SrcCopyRect.left=0; - SrcCopyRect.right=TmpSurfXsize; - SrcCopyRect.bottom=TmpSurfYsize; - } - - hr=_pD3DDevice->CreateOffscreenPlainSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM, &pD3DSurf, NULL); - if(FAILED(hr)) { - dxgsg9_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); - return false; - } - - hr=_pD3DDevice->GetFrontBufferData(0, pD3DSurf); - - if(hr==D3DERR_DEVICELOST) { - pD3DSurf->Release(); - dxgsg9_cat.error() << "copy_pixel_buffer failed: device lost\n"; - return false; - } } else { - dxgsg9_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; - return false; + RECT WindRect; + GetWindowRect(_pScrn->hWnd,&WindRect); + TmpSurfXsize = RECT_XSIZE(WindRect); + TmpSurfYsize = RECT_YSIZE(WindRect); + } + + hr=_pD3DDevice->CreateOffscreenPlainSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM, &pD3DSurf, NULL); + if(FAILED(hr)) { + dxgsg9_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); + return false; + } + + hr=_pD3DDevice->GetFrontBufferData(0, pD3DSurf); + + if(hr==D3DERR_DEVICELOST) { + pD3DSurf->Release(); + dxgsg9_cat.error() << "copy_pixel_buffer failed: device lost\n"; + return false; } - if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) { - dxgsg9_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n"; - return false; - } - - (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb); - - RELEASE(pD3DSurf,dxgsg9,"pD3DSurf",RELEASE_ONCE); - - nassertr(!pb->_image.empty(), false); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::copy_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool DXGraphicsStateGuardian9:: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb) { - set_read_buffer(rb); - return copy_pixel_buffer(pb, dr); + } else { + dxgsg9_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; + return false; + } + + (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,tex); + + RELEASE(pD3DSurf,dxgsg9,"pD3DSurf",RELEASE_ONCE); + + nassertr(tex->has_ram_image(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -3986,55 +3927,6 @@ set_blend_mode() { enable_blend(false); } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::save_frame_buffer -// Access: Public -// Description: Saves the indicated planes of the frame buffer -// (within the indicated display region) and returns it -// in some meaningful form that can be restored later -// via restore_frame_buffer(). This is a helper -// function for push_frame_buffer() and -// pop_frame_buffer(). -//////////////////////////////////////////////////////////////////// -PT(SavedFrameBuffer) DXGraphicsStateGuardian9:: -save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr) { - - dxgsg9_cat.error() << "save_frame_buffer unimplemented!!\n"; - return NULL; - -#if 0 - DXSavedFrameBuffer *sfb = new DXSavedFrameBuffer(buffer, dr); - - if (buffer._buffer_type & RenderBuffer::T_depth) { - // Save the depth buffer. - sfb->_depth = - new PixelBuffer(PixelBuffer::depth_buffer(dr->get_pixel_width(), - dr->get_pixel_height())); - copy_pixel_buffer(sfb->_depth, dr, buffer); - } - - if (buffer._buffer_type & RenderBuffer::T_back) { - // Save the color buffer. - sfb->_back_rgba = new Texture; - copy_texture(sfb->_back_rgba, dr, buffer); - } - - return sfb; -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::restore_frame_buffer -// Access: Public -// Description: Restores the frame buffer that was previously saved. -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: -restore_frame_buffer(SavedFrameBuffer *frame_buffer) { - dxgsg9_cat.error() << "restore_frame_buffer unimplemented!!\n"; - return; -} - TypeHandle DXGraphicsStateGuardian9::get_type(void) const { return get_class_type(); } diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index 623396bfd5..af2ec51fb5 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -30,7 +30,6 @@ #include "geomprimitives.h" #include "texture.h" #include "texGenAttrib.h" -#include "pixelBuffer.h" #include "displayRegion.h" #include "material.h" #include "depthTestAttrib.h" @@ -95,17 +94,10 @@ public: virtual void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr, - const RenderBuffer &rb); - - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb); - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr); - - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb); + virtual void framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb); + virtual bool framebuffer_copy_to_ram(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb); virtual void apply_material(const Material *material); virtual void apply_fog(Fog *fog); @@ -160,9 +152,6 @@ protected: void free_nondx_resources(); // free local internal buffers void free_d3d_device(void); - virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - virtual void restore_frame_buffer(SavedFrameBuffer *frame_buffer); void set_draw_buffer(const RenderBuffer &rb); void set_read_buffer(const RenderBuffer &rb); diff --git a/panda/src/dxgsg9/dxSavedFrameBuffer9.I b/panda/src/dxgsg9/dxSavedFrameBuffer9.I deleted file mode 100755 index 785c6f17ca..0000000000 --- a/panda/src/dxgsg9/dxSavedFrameBuffer9.I +++ /dev/null @@ -1,39 +0,0 @@ -// Filename: dxSavedFrameBuffer8.I -// Created by: masad (02Jan04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: DXSavedFrameBuffer9::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXSavedFrameBuffer9:: -DXSavedFrameBuffer9(const RenderBuffer &buffer, CPT(DisplayRegion) dr) : - SavedFrameBuffer(buffer, dr) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: DXSavedFrameBuffer9::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE DXSavedFrameBuffer9:: -~DXSavedFrameBuffer9() { -} - diff --git a/panda/src/dxgsg9/dxSavedFrameBuffer9.cxx b/panda/src/dxgsg9/dxSavedFrameBuffer9.cxx deleted file mode 100755 index ea9d7fe086..0000000000 --- a/panda/src/dxgsg9/dxSavedFrameBuffer9.cxx +++ /dev/null @@ -1,21 +0,0 @@ -// Filename: dxSavedFrameBuffer8.cxx -// Created by: masad (02Jan04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2004, 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 "dxSavedFrameBuffer9.h" - -TypeHandle DXSavedFrameBuffer9::_type_handle; diff --git a/panda/src/dxgsg9/dxSavedFrameBuffer9.h b/panda/src/dxgsg9/dxSavedFrameBuffer9.h deleted file mode 100755 index 2829555780..0000000000 --- a/panda/src/dxgsg9/dxSavedFrameBuffer9.h +++ /dev/null @@ -1,64 +0,0 @@ -// Filename: dxSavedFrameBuffer8.h -// Created by: masad (02Jan04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2004, 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 DXSAVEDFRAMEBUFFER9_H -#define DXSAVEDFRAMEBUFFER9_H - -#include "pandabase.h" - -#include "savedFrameBuffer.h" -#include "texture.h" -#include "textureContext.h" -#include "pixelBuffer.h" - - -//////////////////////////////////////////////////////////////////// -// Class : DXSavedFrameBuffer9 -// Description : -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXSavedFrameBuffer9 : public SavedFrameBuffer { -public: - INLINE DXSavedFrameBuffer9(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - INLINE ~DXSavedFrameBuffer9(); - - PT(Texture) _back_rgba; - PT(PixelBuffer) _depth; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - SavedFrameBuffer::init_type(); - register_type(_type_handle, "DXSavedFrameBuffer9", - SavedFrameBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "DXSavedFrameBuffer9.I" - -#endif - diff --git a/panda/src/dxgsg9/dxTextureContext9.cxx b/panda/src/dxgsg9/dxTextureContext9.cxx index bd47e11e13..51c7abb882 100755 --- a/panda/src/dxgsg9/dxTextureContext9.cxx +++ b/panda/src/dxgsg9/dxTextureContext9.cxx @@ -31,7 +31,7 @@ static const DWORD g_LowByteMask = 0x000000FF; #ifdef PANDA_BGRA_ORDER // assume Panda uses byte-order BGRA/LA to store pixels, which when read into little-endian word is ARGB/AL -// these macros GET from PixelBuffer, (wont work from DDSurface) +// these macros GET from Texture, (wont work from DDSurface) #define GET_RED_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask)) #define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD) & g_LowByteMask)) #else @@ -135,54 +135,54 @@ enum Format { //////////////////////////////////////////////////////////////////// // Function: DXTextureContext9::get_bits_per_pixel // Access: Protected -// Description: Maps from the PixelBuffer's Format symbols +// Description: Maps from the Texture's Format symbols // to bpp. returns # of alpha bits -// Note: PixelBuffer's format indicates REQUESTED final format, +// Note: Texture's format indicates REQUESTED final format, // not the stored format, which is indicated by pixelbuffer type //////////////////////////////////////////////////////////////////// unsigned int DXTextureContext9:: -get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { +get_bits_per_pixel(Texture::Format format, int *alphbits) { *alphbits = 0; // assume no alpha bits switch(format) { - case PixelBuffer::F_alpha: + case Texture::F_alpha: *alphbits = 8; - case PixelBuffer::F_color_index: - case PixelBuffer::F_red: - case PixelBuffer::F_green: - case PixelBuffer::F_blue: - case PixelBuffer::F_rgb332: + case Texture::F_color_index: + case Texture::F_red: + case Texture::F_green: + case Texture::F_blue: + case Texture::F_rgb332: return 8; - case PixelBuffer::F_luminance_alphamask: + case Texture::F_luminance_alphamask: *alphbits = 1; return 16; - case PixelBuffer::F_luminance_alpha: + case Texture::F_luminance_alpha: *alphbits = 8; return 16; - case PixelBuffer::F_luminance: + case Texture::F_luminance: return 8; - case PixelBuffer::F_rgba4: + case Texture::F_rgba4: *alphbits = 4; return 16; - case PixelBuffer::F_rgba5: + case Texture::F_rgba5: *alphbits = 1; return 16; - case PixelBuffer::F_depth_component: - case PixelBuffer::F_rgb5: + case Texture::F_depth_component: + case Texture::F_rgb5: return 16; - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgb: + case Texture::F_rgb8: + case Texture::F_rgb: return 24; - case PixelBuffer::F_rgba8: - case PixelBuffer::F_rgba: - case PixelBuffer::F_rgbm: - if(format==PixelBuffer::F_rgbm) // does this make any sense? + case Texture::F_rgba8: + case Texture::F_rgba: + case Texture::F_rgbm: + if(format==Texture::F_rgbm) // does this make any sense? *alphbits = 1; else *alphbits = 8; return 32; - case PixelBuffer::F_rgb12: + case Texture::F_rgb12: return 36; - case PixelBuffer::F_rgba12: + case Texture::F_rgba12: *alphbits = 12; return 48; } @@ -190,20 +190,20 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { } // still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer -HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelBuffer *pixbuf) { -// copies SrcRect in pD3DSurf to upper left of pixbuf +HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,Texture *texture) { +// copies SrcRect in pD3DSurf to upper left of texture HRESULT hr; - DWORD dwNumComponents=pixbuf->get_num_components(); + DWORD dwNumComponents=texture->get_num_components(); - assert(pixbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now - assert(pixbuf->get_image_type()==PixelBuffer::T_unsigned_byte); // cant handle anything else now + assert(texture->get_component_width()==sizeof(BYTE)); // cant handle anything else now + assert(texture->get_component_type()==Texture::T_unsigned_byte); // cant handle anything else now assert((dwNumComponents==3) || (dwNumComponents==4)); // cant handle anything else now assert(IS_VALID_PTR(pD3DSurf9)); - BYTE *pbuf=pixbuf->_image.p(); + BYTE *pbuf=texture->modify_ram_image().p(); if(IsBadWritePtr(pD3DSurf9,sizeof(DWORD))) { - dxgsg9_cat.error() << "ConvertDDSurftoPixBuf failed: bad pD3DSurf ptr value (" << ((void*)pD3DSurf9) << ")\n"; + dxgsg9_cat.error() << "ConvertDDSurftoTexture failed: bad pD3DSurf ptr value (" << ((void*)pD3DSurf9) << ")\n"; exit(1); } @@ -219,11 +219,11 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelB dwCopyWidth=RECT_XSIZE(SrcRect); dwCopyHeight=RECT_YSIZE(SrcRect); - //make sure there's enough space in the pixbuf, its size must match (especially xsize) + //make sure there's enough space in the texture, its size must match (especially xsize) // or scanlines will be too long - if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) { - dxgsg9_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size too small to hold display surface!\n"; + if(!((dwCopyWidth==texture->get_x_size()) && (dwCopyHeight<=(DWORD)texture->get_y_size()))) { + dxgsg9_cat.error() << "ConvertDDSurftoPixBuf, Texture size too small to hold display surface!\n"; assert(0); return E_FAIL; } @@ -239,7 +239,7 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelB (SurfDesc.Format==D3DFMT_R5G6B5)||(SurfDesc.Format==D3DFMT_X1R5G5B5)||(SurfDesc.Format==D3DFMT_A1R5G5B5)|| (SurfDesc.Format==D3DFMT_A4R4G4B4)); - //pbuf contains raw ARGB in PixelBuffer byteorder + //pbuf contains raw ARGB in Texture byteorder DWORD BytePitch = LockedRect.Pitch; BYTE* pSurfBytes = (BYTE*)LockedRect.pBits; @@ -249,7 +249,7 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelB if(dxgsg9_cat.is_debug()) { dxgsg9_cat.debug() << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " - << dwNumComponents << "-channel panda PixelBuffer\n"; + << dwNumComponents << "-channel panda Texture\n"; } DWORD *pDstWord = (DWORD *) pbuf; @@ -285,7 +285,7 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelB #endif } } else { - // 24bpp pixbuf case (numComponents==3) + // 24bpp texture case (numComponents==3) DWORD *pSrcWord; pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1); for(DWORD y=0; y_pbuffer; - // bpp indicates requested fmt, not pixbuf fmt - DWORD target_bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); - PixelBuffer::Type pixbuf_type = pbuf->get_image_type(); - DWORD cNumColorChannels = pbuf->get_num_components(); + // bpp indicates requested fmt, not texture fmt + DWORD target_bpp = get_bits_per_pixel(_texture->get_format(), &cNumAlphaBits); + DWORD cNumColorChannels = _texture->get_num_components(); //PRINT_REFCNT(dxgsg9,scrn.pD3D9); - DWORD dwOrigWidth = (DWORD)pbuf->get_xsize(); - DWORD dwOrigHeight = (DWORD)pbuf->get_ysize(); + DWORD dwOrigWidth = (DWORD)_texture->get_x_size(); + DWORD dwOrigHeight = (DWORD)_texture->get_y_size(); - if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)|| - (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) || - (pbuf->get_format() == PixelBuffer::F_luminance)) { + if((_texture->get_format() == Texture::F_luminance_alpha)|| + (_texture->get_format() == Texture::F_luminance_alphamask) || + (_texture->get_format() == Texture::F_luminance)) { bNeedLuminance = true; } @@ -496,7 +494,7 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { _PixBufD3DFmt=D3DFMT_UNKNOWN; - // figure out what 'D3DFMT' the PixelBuffer is in, so D3DXLoadSurfFromMem knows how to perform copy + // figure out what 'D3DFMT' the Texture is in, so D3DXLoadSurfFromMem knows how to perform copy switch(cNumColorChannels) { case 1: @@ -567,13 +565,13 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { // need 2 add checks for errors PNMImage pnmi_src; PNMImage *pnmi = new PNMImage(TargetWidth, TargetHeight, cNumColorChannels); - pbuf->store(pnmi_src); + _texture->store(pnmi_src); pnmi->quick_filter_from(pnmi_src,0,0); - pbuf->load(*pnmi); // violates device independence of pixbufs + _texture->load(*pnmi); // violates device independence of pixbufs - dwOrigWidth = (DWORD)pbuf->get_xsize(); - dwOrigHeight = (DWORD)pbuf->get_ysize(); + dwOrigWidth = (DWORD)_texture->get_x_size(); + dwOrigHeight = (DWORD)_texture->get_y_size(); delete pnmi; } */ @@ -601,7 +599,7 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { switch(target_bpp) { // IMPORTANT NOTE: - // target_bpp is REQUESTED bpp, not what exists in the pixbuf array (the pixbuf array contains cNumColorChannels*8bits) + // target_bpp is REQUESTED bpp, not what exists in the texture array (the texture array contains cNumColorChannels*8bits) case 32: if(!((cNumColorChannels==3) || (cNumColorChannels==4))) @@ -772,7 +770,7 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { /////////////////////////////////////////////////////////// found_matching_format: - // We found a suitable format that matches the pbuffer's format. + // We found a suitable format that matches the texture's format. if (_texture->get_match_framebuffer_format()) { // Instead of creating a texture with the found format, we will @@ -936,8 +934,8 @@ FillDDSurfTexturePixels(void) { HRESULT hr=E_FAIL; assert(IS_VALID_PTR(_texture)); - PixelBuffer *pbuf = _texture->get_ram_image(); - if (pbuf == (PixelBuffer *)NULL) { + CPTA_uchar image = _texture->get_ram_image(); + if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it // might be a texture we've rendered to by frame buffer // operations or something. @@ -946,12 +944,12 @@ FillDDSurfTexturePixels(void) { assert(IS_VALID_PTR(_pD3DTexture9)); - DWORD OrigWidth = (DWORD) pbuf->get_xsize(); - DWORD OrigHeight = (DWORD) pbuf->get_ysize(); - DWORD cNumColorChannels = pbuf->get_num_components(); + DWORD OrigWidth = (DWORD) _texture->get_x_size(); + DWORD OrigHeight = (DWORD) _texture->get_y_size(); + DWORD cNumColorChannels = _texture->get_num_components(); D3DFORMAT SrcFormat=_PixBufD3DFmt; - BYTE *pPixels=(BYTE*)pbuf->_image.p(); - int component_width = pbuf->get_component_width(); + BYTE *pPixels=(BYTE*)image.p(); + int component_width = _texture->get_component_width(); assert(IS_VALID_PTR(pPixels)); @@ -1009,7 +1007,7 @@ FillDDSurfTexturePixels(void) { // original image. dx9 does support some of these // high-precision formats, but we don't right now. - int num_components = pbuf->get_num_components(); + int num_components = _texture->get_num_components(); int num_pixels = OrigWidth * OrigHeight * num_components; BYTE *pTempPixBuf = new BYTE[num_pixels]; if(!IS_VALID_PTR(pTempPixBuf)) { diff --git a/panda/src/dxgsg9/dxTextureContext9.h b/panda/src/dxgsg9/dxTextureContext9.h index 346c65a2f1..e1b7fab65e 100755 --- a/panda/src/dxgsg9/dxTextureContext9.h +++ b/panda/src/dxgsg9/dxTextureContext9.h @@ -41,7 +41,7 @@ public: Texture *_tex; // ptr to parent, primarily for access to namestr IDirect3DTexture9 *CreateTexture(DXScreenData &scrn); - D3DFORMAT _PixBufD3DFmt; // the 'D3DFORMAT' the Panda PixelBuffer fmt corresponds to + D3DFORMAT _PixBufD3DFmt; // the 'D3DFORMAT' the Panda TextureBuffer fmt corresponds to bool _bHasMipMaps; @@ -54,7 +54,7 @@ public: HRESULT FillDDSurfTexturePixels(void); protected: - unsigned int get_bits_per_pixel(PixelBuffer::Format format, int *alphbits); + unsigned int get_bits_per_pixel(Texture::Format format, int *alphbits); public: static TypeHandle get_class_type() { @@ -74,7 +74,7 @@ private: static TypeHandle _type_handle; }; -extern HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelBuffer *pixbuf); +extern HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,Texture *pixbuf); #endif diff --git a/panda/src/dxgsg9/dxgsg9_composite1.cxx b/panda/src/dxgsg9/dxgsg9_composite1.cxx index d70e7ed831..3a35ad3a0c 100755 --- a/panda/src/dxgsg9/dxgsg9_composite1.cxx +++ b/panda/src/dxgsg9/dxgsg9_composite1.cxx @@ -1,6 +1,5 @@ #include "dxgsg9base.h" #include "config_dxgsg9.cxx" -#include "dxSavedFrameBuffer9.cxx" #include "dxTextureContext9.cxx" #include "d3dfont9.cxx" #include "wdxGraphicsPipe9.cxx" diff --git a/panda/src/egg/eggTexture.cxx b/panda/src/egg/eggTexture.cxx index 03e2f953d5..0df30c071d 100644 --- a/panda/src/egg/eggTexture.cxx +++ b/panda/src/egg/eggTexture.cxx @@ -816,6 +816,9 @@ string_tex_gen(const string &string) { } else if (cmp_nocase_uh(string, "eye_position") == 0) { return TG_eye_position; + } else if (cmp_nocase_uh(string, "object_normal") == 0) { + return TG_object_normal; + } else { return TG_unspecified; } @@ -1125,6 +1128,9 @@ operator << (ostream &out, EggTexture::TexGen tex_gen) { case EggTexture::TG_eye_position: return out << "eye_position"; + + case EggTexture::TG_object_normal: + return out << "object_normal"; } return out << "**invalid TexGen(" << (int)tex_gen << ")**"; diff --git a/panda/src/egg/eggTexture.h b/panda/src/egg/eggTexture.h index 92dfa4c67e..65fcb9a863 100644 --- a/panda/src/egg/eggTexture.h +++ b/panda/src/egg/eggTexture.h @@ -134,6 +134,7 @@ PUBLISHED: TG_world_position, TG_object_position, TG_eye_position, + TG_object_normal, }; INLINE void set_format(Format format); diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 18dd1b582a..6e5f69dd3e 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -860,16 +860,16 @@ void EggLoader:: apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { switch (egg_tex->determine_wrap_u()) { case EggTexture::WM_repeat: - tex->set_wrapu(Texture::WM_repeat); + tex->set_wrap_u(Texture::WM_repeat); break; case EggTexture::WM_clamp: if (egg_ignore_clamp) { egg2pg_cat.warning() << "Ignoring clamp request\n"; - tex->set_wrapu(Texture::WM_repeat); + tex->set_wrap_u(Texture::WM_repeat); } else { - tex->set_wrapu(Texture::WM_clamp); + tex->set_wrap_u(Texture::WM_clamp); } break; @@ -884,16 +884,16 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { switch (egg_tex->determine_wrap_v()) { case EggTexture::WM_repeat: - tex->set_wrapv(Texture::WM_repeat); + tex->set_wrap_v(Texture::WM_repeat); break; case EggTexture::WM_clamp: if (egg_ignore_clamp) { egg2pg_cat.warning() << "Ignoring clamp request\n"; - tex->set_wrapv(Texture::WM_repeat); + tex->set_wrap_v(Texture::WM_repeat); } else { - tex->set_wrapv(Texture::WM_clamp); + tex->set_wrap_v(Texture::WM_clamp); } break; @@ -1018,22 +1018,22 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { tex->set_anisotropic_degree(egg_tex->get_anisotropic_degree()); } - if (tex->_pbuffer->get_num_components() == 1) { + if (tex->get_num_components() == 1) { switch (egg_tex->get_format()) { case EggTexture::F_red: - tex->_pbuffer->set_format(PixelBuffer::F_red); + tex->set_format(Texture::F_red); break; case EggTexture::F_green: - tex->_pbuffer->set_format(PixelBuffer::F_green); + tex->set_format(Texture::F_green); break; case EggTexture::F_blue: - tex->_pbuffer->set_format(PixelBuffer::F_blue); + tex->set_format(Texture::F_blue); break; case EggTexture::F_alpha: - tex->_pbuffer->set_format(PixelBuffer::F_alpha); + tex->set_format(Texture::F_alpha); break; case EggTexture::F_luminance: - tex->_pbuffer->set_format(PixelBuffer::F_luminance); + tex->set_format(Texture::F_luminance); break; case EggTexture::F_unspecified: @@ -1045,14 +1045,14 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { << " for 1-component texture " << egg_tex->get_name() << "\n"; } - } else if (tex->_pbuffer->get_num_components() == 2) { + } else if (tex->get_num_components() == 2) { switch (egg_tex->get_format()) { case EggTexture::F_luminance_alpha: - tex->_pbuffer->set_format(PixelBuffer::F_luminance_alpha); + tex->set_format(Texture::F_luminance_alpha); break; case EggTexture::F_luminance_alphamask: - tex->_pbuffer->set_format(PixelBuffer::F_luminance_alphamask); + tex->set_format(Texture::F_luminance_alphamask); break; case EggTexture::F_unspecified: @@ -1064,15 +1064,15 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { << " for 2-component texture " << egg_tex->get_name() << "\n"; } - } else if (tex->_pbuffer->get_num_components() == 3) { + } else if (tex->get_num_components() == 3) { switch (egg_tex->get_format()) { case EggTexture::F_rgb: - tex->_pbuffer->set_format(PixelBuffer::F_rgb); + tex->set_format(Texture::F_rgb); break; case EggTexture::F_rgb12: - if (tex->_pbuffer->get_component_width() >= 2) { + if (tex->get_component_width() >= 2) { // Only do this if the component width supports it. - tex->_pbuffer->set_format(PixelBuffer::F_rgb12); + tex->set_format(Texture::F_rgb12); } else { egg2pg_cat.warning() << "Ignoring inappropriate format " << egg_tex->get_format() @@ -1084,13 +1084,13 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { // We'll quietly accept RGBA8 for a 3-component texture, since // flt2egg generates these for 3-component as well as for // 4-component textures. - tex->_pbuffer->set_format(PixelBuffer::F_rgb8); + tex->set_format(Texture::F_rgb8); break; case EggTexture::F_rgb5: - tex->_pbuffer->set_format(PixelBuffer::F_rgb5); + tex->set_format(Texture::F_rgb5); break; case EggTexture::F_rgb332: - tex->_pbuffer->set_format(PixelBuffer::F_rgb332); + tex->set_format(Texture::F_rgb332); break; case EggTexture::F_unspecified: @@ -1102,18 +1102,18 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { << " for 3-component texture " << egg_tex->get_name() << "\n"; } - } else if (tex->_pbuffer->get_num_components() == 4) { + } else if (tex->get_num_components() == 4) { switch (egg_tex->get_format()) { case EggTexture::F_rgba: - tex->_pbuffer->set_format(PixelBuffer::F_rgba); + tex->set_format(Texture::F_rgba); break; case EggTexture::F_rgbm: - tex->_pbuffer->set_format(PixelBuffer::F_rgbm); + tex->set_format(Texture::F_rgbm); break; case EggTexture::F_rgba12: - if (tex->_pbuffer->get_component_width() >= 2) { + if (tex->get_component_width() >= 2) { // Only do this if the component width supports it. - tex->_pbuffer->set_format(PixelBuffer::F_rgba12); + tex->set_format(Texture::F_rgba12); } else { egg2pg_cat.warning() << "Ignoring inappropriate format " << egg_tex->get_format() @@ -1121,13 +1121,13 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) { } break; case EggTexture::F_rgba8: - tex->_pbuffer->set_format(PixelBuffer::F_rgba8); + tex->set_format(Texture::F_rgba8); break; case EggTexture::F_rgba4: - tex->_pbuffer->set_format(PixelBuffer::F_rgba4); + tex->set_format(Texture::F_rgba4); break; case EggTexture::F_rgba5: - tex->_pbuffer->set_format(PixelBuffer::F_rgba5); + tex->set_format(Texture::F_rgba5); break; case EggTexture::F_unspecified: @@ -1451,7 +1451,7 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs, const TextureAttrib *tex_attrib = DCAST(TextureAttrib, def._texture); Texture *tex = tex_attrib->get_texture(); nassertv(tex != (Texture *)NULL); - int num_components = tex->_pbuffer->get_num_components(); + int num_components = tex->get_num_components(); if (egg_tex->has_alpha_channel(num_components)) { switch (egg_tex->get_env_type()) { case EggTexture::ET_decal: @@ -3129,6 +3129,9 @@ get_tex_gen(const EggTexture *egg_tex) { case EggTexture::TG_eye_position: return TexGenAttrib::M_eye_position; + + case EggTexture::TG_object_normal: + return TexGenAttrib::M_object_normal; }; return TexGenAttrib::M_off; diff --git a/panda/src/glstuff/Sources.pp b/panda/src/glstuff/Sources.pp index 118a749ddd..6a37fdd24e 100644 --- a/panda/src/glstuff/Sources.pp +++ b/panda/src/glstuff/Sources.pp @@ -25,9 +25,6 @@ glGraphicsStateGuardian_src.cxx \ glGraphicsStateGuardian_src.I \ glGraphicsStateGuardian_src.h \ - glSavedFrameBuffer_src.cxx \ - glSavedFrameBuffer_src.I \ - glSavedFrameBuffer_src.h \ glTextureContext_src.cxx \ glTextureContext_src.I \ glTextureContext_src.h \ diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 7b6e473d68..07703c99d4 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -51,6 +51,7 @@ #include "pvector.h" #include "vector_string.h" #include "string_utils.h" +#include "pnmImage.h" #ifdef DO_PSTATS #include "pStatTimer.h" #endif @@ -212,30 +213,62 @@ ushort_bgra_to_rgba(unsigned short *dest, const unsigned short *source, } } +//////////////////////////////////////////////////////////////////// +// Function: reduce_image +// Description: Reduces an image to an acceptable size by sampling +// pixels. This is just a cheap and dirty trick to load +// an image that the GL says is too large. +// +// The implementation copies byte_chunk bytes every +// byte_chunk * stride bytes. +//////////////////////////////////////////////////////////////////// +static PTA_uchar +reduce_image(CPTA_uchar orig_image, int byte_chunk, int stride) { + size_t orig_image_size = orig_image.size(); + size_t new_image_size = orig_image_size / stride; + PTA_uchar new_image = PTA_uchar::empty_array(new_image_size); + const unsigned char *from = orig_image.p(); + unsigned char *to = new_image.p(); + + const unsigned char *from_end = from + orig_image_size; + const unsigned char *to_end = to + new_image_size; + + while (from + byte_chunk <= from_end) { + nassertr(to + byte_chunk <= to_end, new_image); + memcpy(to, from, byte_chunk); + from += stride * byte_chunk; + to += byte_chunk; + } + + return new_image; +} + //////////////////////////////////////////////////////////////////// // Function: fix_component_ordering // Description: Reverses the order of the components within the // image, to convert (for instance) GL_BGR to GL_RGB. -// Returns the PTA_uchar representing the converted +// Returns the CPTA_uchar representing the converted // image, or the original image if it is unchanged. //////////////////////////////////////////////////////////////////// static PTA_uchar -fix_component_ordering(GLenum external_format, PixelBuffer *pb) { - PTA_uchar new_image = pb->_image; +fix_component_ordering(CPTA_uchar orig_image, GLenum external_format, + Texture *tex) { + size_t orig_image_size = orig_image.size(); + PTA_uchar new_image = (PTA_uchar &)orig_image; switch (external_format) { case GL_RGB: - switch (pb->get_image_type()) { - case PixelBuffer::T_unsigned_byte: - new_image = PTA_uchar::empty_array(pb->_image.size()); - uchar_bgr_to_rgb(new_image, pb->_image, pb->_image.size() / 3); + switch (tex->get_component_type()) { + case Texture::T_unsigned_byte: + new_image = PTA_uchar::empty_array(orig_image_size); + uchar_bgr_to_rgb(new_image, orig_image, orig_image_size / 3); break; - case PixelBuffer::T_unsigned_short: - new_image = PTA_uchar::empty_array(pb->_image.size()); + case Texture::T_unsigned_short: + new_image = PTA_uchar::empty_array(orig_image_size); ushort_bgr_to_rgb((unsigned short *)new_image.p(), - (unsigned short *)pb->_image.p(), - pb->_image.size() / 6); + (const unsigned short *)orig_image.p(), + orig_image_size / 6); break; default: @@ -244,17 +277,17 @@ fix_component_ordering(GLenum external_format, PixelBuffer *pb) { break; case GL_RGBA: - switch (pb->get_image_type()) { - case PixelBuffer::T_unsigned_byte: - new_image = PTA_uchar::empty_array(pb->_image.size()); - uchar_bgra_to_rgba(new_image, pb->_image, pb->_image.size() / 4); + switch (tex->get_component_type()) { + case Texture::T_unsigned_byte: + new_image = PTA_uchar::empty_array(orig_image_size); + uchar_bgra_to_rgba(new_image, orig_image, orig_image_size / 4); break; - case PixelBuffer::T_unsigned_short: - new_image = PTA_uchar::empty_array(pb->_image.size()); + case Texture::T_unsigned_short: + new_image = PTA_uchar::empty_array(orig_image_size); ushort_bgra_to_rgba((unsigned short *)new_image.p(), - (unsigned short *)pb->_image.p(), - pb->_image.size() / 8); + (const unsigned short *)orig_image.p(), + orig_image_size / 8); break; default: @@ -420,6 +453,17 @@ reset() { _supports_multisample = false; } } + + GLP(GetIntegerv)(GL_MAX_TEXTURE_SIZE, &_max_texture_size); + GLP(GetIntegerv)(GL_MAX_3D_TEXTURE_SIZE, &_max_3d_texture_size); + GLP(GetIntegerv)(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &_max_cube_map_size); + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "max texture size = " << _max_texture_size + << ", max 3d texture = " << _max_3d_texture_size + << ", max cube map = " << _max_cube_map_size << "\n"; + } report_my_gl_errors(); @@ -479,11 +523,21 @@ reset() { GLP(GetIntegerv)(GL_MAX_LIGHTS, &max_lights); _max_lights = max_lights; + if (GLCAT.is_debug()) { + GLCAT.debug() + << "max lights = " << _max_lights << "\n"; + } + // Count the max number of clipping planes GLint max_clip_planes; GLP(GetIntegerv)(GL_MAX_CLIP_PLANES, &max_clip_planes); _max_clip_planes = max_clip_planes; + if (GLCAT.is_debug()) { + GLCAT.debug() + << "max clip planes = " << _max_clip_planes << "\n"; + } + _current_projection_mat = LMatrix4f::ident_mat(); _projection_mat_stack_count = 0; @@ -491,6 +545,11 @@ reset() { GLint max_texture_stages; GLP(GetIntegerv)(GL_MAX_TEXTURE_UNITS, &max_texture_stages); _max_texture_stages = max_texture_stages; + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "max texture stages = " << _max_texture_stages << "\n"; + } } _current_texture = DCAST(TextureAttrib, TextureAttrib::make_all_off()); _current_tex_mat = DCAST(TexMatrixAttrib, TexMatrixAttrib::make()); @@ -1071,8 +1130,8 @@ draw_sprite(GeomSprite *geom, GeomContext *) { Geom::ColorIterator ci = geom->make_color_iterator(); // need some interface so user can set 2d dimensions if no texture specified - float tex_xsize = 1.0f; - float tex_ysize = 1.0f; + float tex_x_size = 1.0f; + float tex_y_size = 1.0f; Texture *tex = geom->get_texture(); if(tex != NULL) { @@ -1080,8 +1139,8 @@ draw_sprite(GeomSprite *geom, GeomContext *) { modify_state(RenderState::make (TextureAttrib::make(tex), TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); - tex_xsize = tex->_pbuffer->get_xsize(); - tex_ysize = tex->_pbuffer->get_ysize(); + tex_x_size = tex->get_x_size(); + tex_y_size = tex->get_y_size(); } // save the modelview matrix @@ -1101,8 +1160,8 @@ draw_sprite(GeomSprite *geom, GeomContext *) { float tex_bottom = geom->get_ll_uv()[1]; float tex_top = geom->get_ur_uv()[1]; - float half_width = 0.5f * tex_xsize * fabs(tex_right - tex_left); - float half_height = 0.5f * tex_ysize * fabs(tex_top - tex_bottom); + float half_width = 0.5f * tex_x_size * fabs(tex_right - tex_left); + float half_height = 0.5f * tex_y_size * fabs(tex_top - tex_bottom); float scaled_width = 0.0f; float scaled_height = 0.0f; @@ -2053,90 +2112,48 @@ static int binary_log_cap(const int x) { #endif //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::copy_texture +// Function: CLP(GraphicsStateGuardian)::framebuffer_copy_to_texture // Access: Public, Virtual -// Description: Copy the pixel region indicated by the display +// Description: Copy the pixels within the indicated display // region from the framebuffer into texture memory //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: -copy_texture(Texture *tex, const DisplayRegion *dr) { - nassertv(tex != NULL && dr != NULL); +framebuffer_copy_to_texture(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb) { + nassertv(tex != NULL && dr != NULL && + tex->get_texture_type() == Texture::TT_2d_texture); + set_read_buffer(rb); int xo, yo, w, h; dr->get_region_pixels(xo, yo, w, h); - PixelBuffer *pb = tex->_pbuffer; - pb->set_xsize(w); - pb->set_ysize(h); + tex->set_x_size(w); + tex->set_y_size(h); TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); nassertv(tc != (TextureContext *)NULL); bind_texture(tc); GLP(CopyTexImage2D)(GL_TEXTURE_2D, 0, - get_internal_image_format(pb->get_format()), - xo, yo, w, h, tex->get_border_width()); + get_internal_image_format(tex->get_format()), + xo, yo, w, h, 0); // Clear the internal texture state, since we've just monkeyed with it. modify_state(get_untextured_state()); } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::copy_texture +// Function: CLP(GraphicsStateGuardian)::framebuffer_copy_to_ram // Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -copy_texture(Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb) { - set_read_buffer(rb); - copy_texture(tex, dr); -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { - // This code is now invalidated by the new design; perhaps the - // interface is not needed anyway. -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::texture_to_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr) { - nassertv(tc != NULL && pb != NULL && dr != NULL); - Texture *tex = tc->_texture; - - // Do a deep copy to initialize the pixel buffer - pb->copy(tex->_pbuffer); - - // If the image was empty, we need to render the texture into the frame - // buffer and then copy the results into the pixel buffer's image - if (pb->_image.empty()) { - int w = pb->get_xsize(); - int h = pb->get_ysize(); - draw_texture(tc, dr); - pb->_image = PTA_uchar::empty_array(w * h * pb->get_num_components()); - copy_pixel_buffer(pb, dr); - } - report_my_gl_errors(); -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::copy_pixel_buffer -// Access: Public, Virtual -// Description: +// Description: Copy the pixels within the indicated display region +// from the framebuffer into system memory, not texture +// memory. Returns true on success, false on failure. //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { - nassertr(pb != NULL && dr != NULL, false); +framebuffer_copy_to_ram(Texture *tex, const DisplayRegion *dr, + const RenderBuffer &rb) { + nassertr(tex != NULL && dr != NULL, false); + set_read_buffer(rb); GLP(PixelStorei)(GL_PACK_ALIGNMENT, 1); // Bug fix for RE, RE2, and VTX - need to disable texturing in order @@ -2148,13 +2165,28 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { int xo, yo, w, h; dr->get_region_pixels(xo, yo, w, h); - GLenum external_format = get_external_image_format(pb->get_format()); + const FrameBufferProperties &properties = get_properties(); + + Texture::ComponentType component_type; + if (properties.get_color_bits() <= 24) { + component_type = Texture::T_unsigned_byte; + } else { + component_type = Texture::T_unsigned_short; + } + + Texture::Format format; + if (properties.get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) { + format = Texture::F_rgba; + } else { + format = Texture::F_rgb; + } + + tex->setup_2d_texture(w, h, component_type, format); + GLenum external_format = get_external_image_format(format); #ifdef GSG_VERBOSE GLCAT.debug() - << "glReadPixels(" << xo << ", " << yo - << ", " << pb->get_xsize() << ", " << pb->get_ysize() - << ", "; + << "glReadPixels(" << xo << ", " << yo << ", " << w << ", " << h << ", "; switch (external_format) { case GL_DEPTH_COMPONENT: GLCAT.debug(false) << "GL_DEPTH_COMPONENT, "; @@ -2175,10 +2207,13 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { GLCAT.debug(false) << "unknown, "; break; } - switch (get_image_type(pb->get_image_type())) { + switch (get_component_type(component_type)) { case GL_UNSIGNED_BYTE: GLCAT.debug(false) << "GL_UNSIGNED_BYTE, "; break; + case GL_UNSIGNED_SHORT: + GLCAT.debug(false) << "GL_UNSIGNED_SHORT, "; + break; case GL_FLOAT: GLCAT.debug(false) << "GL_FLOAT, "; break; @@ -2187,38 +2222,24 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { break; } GLCAT.debug(false) - << (void *)pb->_image.p() << ")" << endl; + << ")" << endl; #endif - // pixelbuffer "origin" represents upper left screen point at which - // pixelbuffer should be drawn using draw_pixel_buffer - nassertr(!pb->_image.empty(), false); - GLP(ReadPixels)(xo, yo, - pb->get_xsize(), pb->get_ysize(), - external_format, - get_image_type(pb->get_image_type()), - pb->_image.p()); + GLP(ReadPixels)(xo, yo, w, h, + external_format, get_component_type(component_type), + tex->make_ram_image()); // We may have to reverse the byte ordering of the image if GL // didn't do it for us. - pb->_image = fix_component_ordering(external_format, pb); + if (!_supports_bgr) { + tex->set_ram_image(fix_component_ordering(tex->get_ram_image(), + external_format, tex)); + } report_my_gl_errors(); return true; } -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::copy_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool CLP(GraphicsStateGuardian):: -copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb) { - set_read_buffer(rb); - return copy_pixel_buffer(pb, dr); -} - //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::apply_material // Access: Public, Virtual @@ -3166,7 +3187,10 @@ bind_texture(TextureContext *tc) { << "glBindTexture(): " << tex->get_name() << "(" << (int)gtc->_index << ")" << endl; #endif - GLP(BindTexture)(GL_TEXTURE_2D, gtc->_index); + + GLP(BindTexture)(get_texture_target(tc->_texture->get_texture_type()), + gtc->_index); + report_my_gl_errors(); } @@ -3177,13 +3201,21 @@ bind_texture(TextureContext *tc) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: specify_texture(Texture *tex) { - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - get_texture_wrap_mode(tex->get_wrapu())); - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - get_texture_wrap_mode(tex->get_wrapv())); + GLenum target = get_texture_target(tex->get_texture_type()); + + GLP(TexParameteri)(target, GL_TEXTURE_WRAP_S, + get_texture_wrap_mode(tex->get_wrap_u())); + if (target != GL_TEXTURE_1D) { + GLP(TexParameteri)(target, GL_TEXTURE_WRAP_T, + get_texture_wrap_mode(tex->get_wrap_v())); + } + if (target == GL_TEXTURE_3D) { + GLP(TexParameteri)(target, GL_TEXTURE_WRAP_R, + get_texture_wrap_mode(tex->get_wrap_w())); + } Colorf border_color = tex->get_border_color(); - GLP(TexParameterfv)(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, + GLP(TexParameterfv)(target, GL_TEXTURE_BORDER_COLOR, border_color.get_data()); Texture::FilterType minfilter = tex->get_minfilter(); @@ -3202,7 +3234,7 @@ specify_texture(Texture *tex) { (auto_generate_mipmaps || !tex->might_have_ram_image())) { // If the hardware can automatically generate mipmaps, ask it to // do so now, but only if the texture requires them. - GLP(TexParameteri)(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, uses_mipmaps); + GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, uses_mipmaps); } else if (!tex->might_have_ram_image()) { // If the hardware can't automatically generate mipmaps, but it's @@ -3213,9 +3245,9 @@ specify_texture(Texture *tex) { uses_mipmaps = false; } - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, get_texture_filter_type(minfilter, !uses_mipmaps)); - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER, get_texture_filter_type(magfilter, true)); report_my_gl_errors(); @@ -3230,7 +3262,8 @@ specify_texture(Texture *tex) { // debugging. //////////////////////////////////////////////////////////////////// static int -compute_gl_image_size(int xsize, int ysize, int external_format, int type) { +compute_gl_image_size(int x_size, int y_size, int z_size, + int external_format, int type) { int num_components = 0; switch (external_format) { case GL_COLOR_INDEX: @@ -3279,7 +3312,7 @@ compute_gl_image_size(int xsize, int ysize, int external_format, int type) { break; } - return xsize * ysize * pixel_width; + return x_size * y_size * z_size * pixel_width; } #endif // NDEBUG @@ -3295,44 +3328,102 @@ compute_gl_image_size(int xsize, int ysize, int external_format, int type) { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex) { - PixelBuffer *pb = tex->get_ram_image(); - if (pb == (PixelBuffer *)NULL) { + CPTA_uchar image = tex->get_ram_image(); + if (image.is_null()) { return false; } - int width = pb->get_xsize(); - int height = pb->get_ysize(); + int width = tex->get_x_size(); + int height = tex->get_y_size(); + int depth = tex->get_z_size(); - GLint internal_format = get_internal_image_format(pb->get_format()); - GLint external_format = get_external_image_format(pb->get_format()); - GLenum type = get_image_type(pb->get_image_type()); + GLint internal_format = get_internal_image_format(tex->get_format()); + GLint external_format = get_external_image_format(tex->get_format()); + GLenum component_type = get_component_type(tex->get_component_type()); - PTA_uchar image = pb->_image; - nassertr(!image.empty(), false); + // Ensure that the texture fits within the GL's specified limits. + int max_dimension; + switch (tex->get_texture_type()) { + case Texture::TT_3d_texture: + max_dimension = _max_3d_texture_size; + break; + + case Texture::TT_cube_map: + max_dimension = _max_cube_map_size; + break; + + default: + max_dimension = _max_texture_size; + } + + if (max_dimension == 0) { + // Guess this GL doesn't support cube mapping/3d textures. + return false; + } + + int texel_size = tex->get_num_components() * tex->get_component_width(); + + // If it doesn't fit, we have to reduce it on-the-fly. This is kind + // of expensive and it doesn't look great; it would have been better + // if the user had specified max-texture-dimension to reduce the + // texture at load time instead. + if (width > max_dimension) { + int byte_chunk = texel_size; + int stride = 1; + int new_width = width; + while (new_width > max_dimension) { + stride <<= 1; + new_width >>= 1; + } + GLCAT.info() + << "Reducing width of " << tex->get_name() + << " from " << width << " to " << new_width << "\n"; + image = reduce_image(image, byte_chunk, stride); + width = new_width; + } + if (height > max_dimension) { + int byte_chunk = width * texel_size; + int stride = 1; + int new_height = height; + while (new_height > max_dimension) { + stride <<= 1; + new_height >>= 1; + } + GLCAT.info() + << "Reducing height of " << tex->get_name() + << " from " << height << " to " << new_height << "\n"; + image = reduce_image(image, byte_chunk, stride); + height = new_height; + } + if (depth > max_dimension) { + int byte_chunk = height * width * texel_size; + int stride = 1; + int new_depth = depth; + while (new_depth > max_dimension) { + stride <<= 1; + new_depth >>= 1; + } + GLCAT.info() + << "Reducing depth of " << tex->get_name() + << " from " << depth << " to " << new_depth << "\n"; + image = reduce_image(image, byte_chunk, stride); + depth = new_depth; + } if (!_supports_bgr) { // If the GL doesn't claim to support BGR, we may have to reverse // the component ordering of the image. - image = fix_component_ordering(external_format, pb); + image = fix_component_ordering(image, external_format, tex); } #ifndef NDEBUG int wanted_size = - compute_gl_image_size(width, height, external_format, type); - nassertr(wanted_size == (int)pb->_image.size(), false); + compute_gl_image_size(width, height, depth, external_format, component_type); + nassertr(wanted_size == (int)image.size(), false); #endif // NDEBUG GLP(PixelStorei)(GL_UNPACK_ALIGNMENT, 1); -#ifdef GSG_VERBOSE - GLCAT.debug() - << "glTexImage2D(GL_TEXTURE_2D, " - << (int)internal_format << ", " - << width << ", " << height << ", " - << tex->get_border_width() << ", " << (int)external_format << ", " - << (int)type << ", " << tex->get_name() << ")\n"; -#endif - bool uses_mipmaps = (tex->uses_mipmaps() && !CLP(ignore_mipmaps)) || CLP(force_mipmaps); #ifndef NDEBUG @@ -3341,10 +3432,96 @@ apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex) { } #endif + bool success = true; + + if (tex->get_texture_type() == Texture::TT_cube_map) { + // A cube map must load six different 2-d images (which are stored + // as the six pages of the system ram image). + size_t page_size = height * width * texel_size; + const unsigned char *image_base = image; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_X, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + nassertr((size_t)(image_base - image) == image.size(), false); + + } else { + // Any other kind of texture can be loaded all at once. + success = upload_texture_image + (gtc, uses_mipmaps, get_texture_target(tex->get_texture_type()), + internal_format, width, height, depth, external_format, component_type, + image); + } + + if (success) { + gtc->_already_applied = true; + gtc->_internal_format = internal_format; + gtc->_width = width; + gtc->_height = height; + gtc->_depth = depth; + +#ifndef NDEBUG + if (uses_mipmaps && CLP(save_mipmaps)) { + save_mipmap_images(tex); + } +#endif + + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::upload_texture_image +// Access: Protected +// Description: Loads a texture image, or one page of a cube map +// image, from system RAM to texture memory. +//////////////////////////////////////////////////////////////////// +bool CLP(GraphicsStateGuardian):: +upload_texture_image(CLP(TextureContext) *gtc, + bool uses_mipmaps, + GLenum target, GLint internal_format, + int width, int height, int depth, + GLint external_format, GLenum component_type, + const unsigned char *image) { if (uses_mipmaps) { #ifndef NDEBUG - if (CLP(show_mipmaps)) { - build_phony_mipmaps(tex); + if (CLP(show_mipmaps) && target == GL_TEXTURE_2D) { + build_phony_mipmaps(gtc->_texture); report_my_gl_errors(); return true; @@ -3353,57 +3530,82 @@ apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex) { if (!_supports_generate_mipmap || !auto_generate_mipmaps) { // We only need to build the mipmaps by hand if the GL // doesn't support generating them automatically. - GLUP(Build2DMipmaps)(GL_TEXTURE_2D, internal_format, - width, height, - external_format, type, image); - - gtc->_already_applied = false; - gtc->_internal_format = internal_format; - gtc->_width = width; - gtc->_height = height; - gtc->_border_width = 0; - -#ifndef NDEBUG - if (CLP(save_mipmaps)) { - save_mipmap_images(tex); + switch (target) { + case GL_TEXTURE_1D: + GLUP(Build1DMipmaps)(target, internal_format, width, + external_format, component_type, image); + break; + + case GL_TEXTURE_3D: + GLUP(Build3DMipmaps)(target, internal_format, + width, height, depth, + external_format, component_type, image); + break; + + default: + GLUP(Build2DMipmaps)(target, internal_format, + width, height, + external_format, component_type, image); } -#endif + report_my_gl_errors(); return true; } } - GLint border_width = tex->get_border_width(); - if (!gtc->_already_applied || gtc->_internal_format != internal_format || gtc->_width != width || gtc->_height != height || - gtc->_border_width != border_width) { + gtc->_depth != depth) { // We need to reload a new image. - GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format, - width, height, border_width, - external_format, type, image); - gtc->_already_applied = true; - gtc->_internal_format = internal_format; - gtc->_width = width; - gtc->_height = height; - gtc->_border_width = border_width; + switch (target) { + case GL_TEXTURE_1D: + GLP(TexImage1D)(target, 0, internal_format, + width, 0, + external_format, component_type, image); + break; + + case GL_TEXTURE_3D: + GLP(TexImage3D)(target, 0, internal_format, + width, height, depth, 0, + external_format, component_type, image); + break; + + default: + GLP(TexImage2D)(target, 0, internal_format, + width, height, 0, + external_format, component_type, image); + } } else { - // We can reload the image over the previous image, saving on - // texture memory fragmentation. - GLP(TexSubImage2D)(GL_TEXTURE_2D, 0, 0, 0, width, height, - external_format, type, image); + // We can reload the image over the previous image, possibly + // saving on texture memory fragmentation. + switch (target) { + case GL_TEXTURE_1D: + GLP(TexSubImage1D)(target, 0, 0, width, + external_format, component_type, image); + break; + + case GL_TEXTURE_3D: + GLP(TexSubImage3D)(target, 0, 0, 0, 0, width, height, depth, + external_format, component_type, image); + break; + + default: + GLP(TexSubImage2D)(target, 0, 0, 0, width, height, + external_format, component_type, image); + break; + } } - //report_my_gl_errors(); - // want to give explict error for texture creation failure + // Report the error message explicitly if the GL texture creation + // failed. GLenum error_code = GLP(GetError)(); if (error_code != GL_NO_ERROR) { const GLubyte *error_string = GLUP(ErrorString)(error_code); GLCAT.error() - << "GL texture creation failed for " << tex->get_name(); + << "GL texture creation failed for " << gtc->_texture->get_name(); if (error_string != (const GLubyte *)NULL) { GLCAT.error(false) << " : " << error_string; @@ -3415,234 +3617,41 @@ apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex) { return true; } + //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::draw_texture -// Access: Protected -// Description: Copies the texture image directly onto the frame -// buffer within the indicated display region. +// Function: CLP(GraphicsStateGuardian)::get_texture_target +// Access: Protected, Static +// Description: Maps from the Texture's texture type symbols to +// GL's. //////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -draw_texture(TextureContext *tc, const DisplayRegion *dr) { - nassertv(tc != NULL && dr != NULL); - Texture *tex = tc->_texture; +GLenum CLP(GraphicsStateGuardian):: +get_texture_target(Texture::TextureType texture_type) { + switch (texture_type) { + case Texture::TT_1d_texture: + return GL_TEXTURE_1D; - DisplayRegionStack old_dr = push_display_region(dr); - prepare_display_region(); + case Texture::TT_2d_texture: + return GL_TEXTURE_2D; - static CPT(RenderState) basic_state; - if (basic_state == (RenderState *)NULL) { - // Create a State object for rendering textures in general. Lots - // of things get turned off. - const RenderAttrib *attribs[] = { - CullFaceAttrib::make(CullFaceAttrib::M_cull_none), - DepthTestAttrib::make(DepthTestAttrib::M_none), - DepthWriteAttrib::make(DepthWriteAttrib::M_off), - TextureApplyAttrib::make(TextureApplyAttrib::M_decal), - ColorWriteAttrib::make(ColorWriteAttrib::M_on), - RenderModeAttrib::make(RenderModeAttrib::M_filled), - //TexMatrixAttrib::make(LMatrix4f::ident_mat()), - ColorBlendAttrib::make_off(), - TransparencyAttrib::make(TransparencyAttrib::M_none), - }; - basic_state = - RenderState::make(attribs, sizeof(attribs) / sizeof(void *)); - } - CPT(RenderState) state = basic_state->compose - (RenderState::make(TextureAttrib::make(tex))); - modify_state(state); - set_transform(TransformState::make_identity()); + case Texture::TT_3d_texture: + return GL_TEXTURE_3D; - // We set up an orthographic projection that defines our entire - // viewport to the range [0..1] in both dimensions. Then, when we - // create a unit square polygon below, it will exactly fill the - // viewport (and thus exactly fill the display region). - GLP(MatrixMode)(GL_PROJECTION); - GLP(PushMatrix)(); - GLP(LoadIdentity)(); - GLUP(Ortho2D)(0, 1, 0, 1); - - float txl, txr, tyt, tyb; - txl = tyb = 0.0f; -#if 0 - // remove this auto-scaling stuff for now - // has_requested_size is only used here for draw_texture() - if (tex->_has_requested_size) { - txr = ((float)(tex->_requested_w)) / ((float)(tex->_pbuffer->get_xsize())); - tyt = ((float)(tex->_requested_h)) / ((float)(tex->_pbuffer->get_ysize())); - } else -#endif - { - txr = tyt = 1.0f; + case Texture::TT_cube_map: + return GL_TEXTURE_CUBE_MAP; } - // This two-triangle strip is actually a quad. But it's usually - // better to render quads as tristrips anyway. - GLP(Begin)(GL_TRIANGLE_STRIP); - GLP(TexCoord2f)(txl, tyb); GLP(Vertex2i)(0, 0); - GLP(TexCoord2f)(txr, tyb); GLP(Vertex2i)(1, 0); - GLP(TexCoord2f)(txl, tyt); GLP(Vertex2i)(0, 1); - GLP(TexCoord2f)(txr, tyt); GLP(Vertex2i)(1, 1); - GLP(End)(); - - GLP(MatrixMode)(GL_PROJECTION); - GLP(PopMatrix)(); - - pop_display_region(old_dr); -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::draw_texture -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -draw_texture(TextureContext *tc, const DisplayRegion *dr, - const RenderBuffer &rb) { - set_draw_buffer(rb); - draw_texture(tc, dr); -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::draw_pixel_buffer -// Access: Protected -// Description: Copies the indicated pixel buffer into the frame -// buffer in the given display region. -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { - // This code is now invalidated by the new design; perhaps the - // interface is not needed anyway. -#if 0 - nassertv(pb != NULL && dr != NULL); - nassertv(!pb->_image.empty()); - DisplayRegionStack old_dr = push_display_region(dr); - prepare_display_region(); - - static CPT(RenderState) depth_state; - static CPT(RenderState) color_state; - if (depth_state == (RenderState *)NULL) { - // Create a State object for rendering depth-mask pixel buffers. - depth_state = - RenderState::make(TextureAttrib::make_off(), - ColorWriteAttrib::make(ColorWriteAttrib::M_off), - DepthTestAttrib::make(DepthTestAttrib::M_always), - DepthWriteAttrib::make(DepthWriteAttrib::M_on)); - - // And one for rendering color buffers. - color_state = - RenderState::make(TextureAttrib::make_off(), - ColorWriteAttrib::make(ColorWriteAttrib::M_on), - DepthTestAttrib::make(DepthTestAttrib::M_none), - DepthWriteAttrib::make(DepthWriteAttrib::M_off)); - } - - switch (pb->get_format()) { - case PixelBuffer::F_depth_component: - modify_state(depth_state); - break; - - case PixelBuffer::F_rgb: - case PixelBuffer::F_rgb5: - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgb12: - case PixelBuffer::F_rgba: - case PixelBuffer::F_rgbm: - case PixelBuffer::F_rgba4: - case PixelBuffer::F_rgba5: - case PixelBuffer::F_rgba8: - case PixelBuffer::F_rgba12: - modify_state(color_state); - break; - - default: - GLCAT.error() - << "draw_pixel_buffer(): unknown buffer format" << endl; - } - set_transform(TransformState::make_identity()); - - GLP(PixelStorei)(GL_UNPACK_ALIGNMENT, 1); - - WindowProperties props = _win->get_properties(); - - GLP(MatrixMode)( GL_PROJECTION ); - GLP(PushMatrix)(); - GLP(LoadIdentity)(); - GLUP(Ortho2D)(0, props.get_x_size(), - 0, props.get_y_size()); - -#ifdef GSG_VERBOSE - GLCAT.debug() - << "glDrawPixels(" << pb->get_xsize() << ", " << pb->get_ysize() - << ", "; - switch (get_external_image_format(pb->get_format())) { - case GL_DEPTH_COMPONENT: - GLCAT.debug(false) << "GL_DEPTH_COMPONENT, "; - break; - case GL_RGB: - GLCAT.debug(false) << "GL_RGB, "; - break; - case GL_RGBA: - GLCAT.debug(false) << "GL_RGBA, "; - break; - case GL_BGR: - GLCAT.debug(false) << "GL_BGR, "; - break; - case GL_BGRA: - GLCAT.debug(false) << "GL_BGRA, "; - break; - default: - GLCAT.debug(false) << "unknown, "; - break; - } - switch (get_image_type(pb->get_image_type())) { - case GL_UNSIGNED_BYTE: - GLCAT.debug(false) << "GL_UNSIGNED_BYTE, "; - break; - case GL_FLOAT: - GLCAT.debug(false) << "GL_FLOAT, "; - break; - default: - GLCAT.debug(false) << "unknown, "; - break; - } - GLCAT.debug(false) - << (void *)pb->_image.p() << ")" << endl; -#endif - - GLP(RasterPos2i)(0, 0); - GLP(DrawPixels)(pb->get_xsize(), pb->get_ysize(), - get_external_image_format(pb->get_format()), - get_image_type(pb->get_image_type()), - pb->_image.p() ); - - GLP(MatrixMode)( GL_PROJECTION ); - GLP(PopMatrix)(); - - pop_display_region(old_dr); - report_my_gl_errors(); -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::draw_pixel_buffer -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb) { - set_draw_buffer(rb); - draw_pixel_buffer(pb, dr); + GLCAT.error() << "Invalid Texture::TextureType value!\n"; + return GL_TEXTURE_2D; } //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_wrap_mode -// Access: Protected +// Access: Protected, Static // Description: Maps from the Texture's internal wrap mode symbols to // GL's. //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: -get_texture_wrap_mode(Texture::WrapMode wm) const { +get_texture_wrap_mode(Texture::WrapMode wm) { if (CLP(ignore_clamp)) { return GL_REPEAT; } @@ -3717,25 +3726,23 @@ get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_image_type +// Function: CLP(GraphicsStateGuardian)::get_component_type // Access: Protected, Static -// Description: Maps from the PixelBuffer's internal Type symbols +// Description: Maps from the Texture's internal ComponentType symbols // to GL's. //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: -get_image_type(PixelBuffer::Type type) { - switch (type) { - case PixelBuffer::T_unsigned_byte: +get_component_type(Texture::ComponentType component_type) { + switch (component_type) { + case Texture::T_unsigned_byte: return GL_UNSIGNED_BYTE; - case PixelBuffer::T_unsigned_short: + case Texture::T_unsigned_short: return GL_UNSIGNED_SHORT; - case PixelBuffer::T_unsigned_byte_332: - return GL_UNSIGNED_BYTE_3_3_2; - case PixelBuffer::T_float: + case Texture::T_float: return GL_FLOAT; default: - GLCAT.error() << "Invalid PixelBuffer::Type value!\n"; + GLCAT.error() << "Invalid Texture::Type value!\n"; return GL_UNSIGNED_BYTE; } } @@ -3743,47 +3750,47 @@ get_image_type(PixelBuffer::Type type) { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_external_image_format // Access: Protected -// Description: Maps from the PixelBuffer's Format symbols +// Description: Maps from the Texture's Format symbols // to GL's. //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_external_image_format(PixelBuffer::Format format) const { +get_external_image_format(Texture::Format format) const { switch (format) { - case PixelBuffer::F_color_index: + case Texture::F_color_index: return GL_COLOR_INDEX; - case PixelBuffer::F_stencil_index: + case Texture::F_stencil_index: return GL_STENCIL_INDEX; - case PixelBuffer::F_depth_component: + case Texture::F_depth_component: return GL_DEPTH_COMPONENT; - case PixelBuffer::F_red: + case Texture::F_red: return GL_RED; - case PixelBuffer::F_green: + case Texture::F_green: return GL_GREEN; - case PixelBuffer::F_blue: + case Texture::F_blue: return GL_BLUE; - case PixelBuffer::F_alpha: + case Texture::F_alpha: return GL_ALPHA; - case PixelBuffer::F_rgb: - case PixelBuffer::F_rgb5: - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgb12: - case PixelBuffer::F_rgb332: + case Texture::F_rgb: + case Texture::F_rgb5: + case Texture::F_rgb8: + case Texture::F_rgb12: + case Texture::F_rgb332: return _supports_bgr ? GL_BGR : GL_RGB; - case PixelBuffer::F_rgba: - case PixelBuffer::F_rgbm: - case PixelBuffer::F_rgba4: - case PixelBuffer::F_rgba5: - case PixelBuffer::F_rgba8: - case PixelBuffer::F_rgba12: + case Texture::F_rgba: + case Texture::F_rgbm: + case Texture::F_rgba4: + case Texture::F_rgba5: + case Texture::F_rgba8: + case Texture::F_rgba12: return _supports_bgr ? GL_BGRA : GL_RGBA; - case PixelBuffer::F_luminance: + case Texture::F_luminance: return GL_LUMINANCE; - case PixelBuffer::F_luminance_alphamask: - case PixelBuffer::F_luminance_alpha: + case Texture::F_luminance_alphamask: + case Texture::F_luminance_alpha: return GL_LUMINANCE_ALPHA; } GLCAT.error() - << "Invalid PixelBuffer::Format value in get_external_image_format(): " + << "Invalid Texture::Format value in get_external_image_format(): " << (int)format << "\n"; return GL_RGB; } @@ -3791,45 +3798,45 @@ get_external_image_format(PixelBuffer::Format format) const { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_internal_image_format // Access: Protected, Static -// Description: Maps from the PixelBuffer's Format symbols to a +// Description: Maps from the Texture's Format symbols to a // suitable internal format for GL textures. //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_internal_image_format(PixelBuffer::Format format) { +get_internal_image_format(Texture::Format format) { switch (format) { - case PixelBuffer::F_rgba: - case PixelBuffer::F_rgbm: + case Texture::F_rgba: + case Texture::F_rgbm: return GL_RGBA; - case PixelBuffer::F_rgba4: + case Texture::F_rgba4: return GL_RGBA4; - case PixelBuffer::F_rgba8: + case Texture::F_rgba8: return GL_RGBA8; - case PixelBuffer::F_rgba12: + case Texture::F_rgba12: return GL_RGBA12; - case PixelBuffer::F_rgb: + case Texture::F_rgb: return GL_RGB; - case PixelBuffer::F_rgb5: + case Texture::F_rgb5: return GL_RGB5; - case PixelBuffer::F_rgba5: + case Texture::F_rgba5: return GL_RGB5_A1; - case PixelBuffer::F_rgb8: + case Texture::F_rgb8: return GL_RGB8; - case PixelBuffer::F_rgb12: + case Texture::F_rgb12: return GL_RGB12; - case PixelBuffer::F_rgb332: + case Texture::F_rgb332: return GL_R3_G3_B2; - case PixelBuffer::F_alpha: + case Texture::F_alpha: return GL_ALPHA; - case PixelBuffer::F_red: - case PixelBuffer::F_green: - case PixelBuffer::F_blue: - case PixelBuffer::F_luminance: + case Texture::F_red: + case Texture::F_green: + case Texture::F_blue: + case Texture::F_luminance: return GL_LUMINANCE; - case PixelBuffer::F_luminance_alpha: - case PixelBuffer::F_luminance_alphamask: + case Texture::F_luminance_alpha: + case Texture::F_luminance_alphamask: return GL_LUMINANCE_ALPHA; default: @@ -4491,7 +4498,6 @@ finish_modify_state() { switch (_current_tex_gen->get_mode(stage)) { case TexGenAttrib::M_off: - case TexGenAttrib::M_cube_map: GLP(Disable)(GL_TEXTURE_GEN_S); GLP(Disable)(GL_TEXTURE_GEN_T); GLP(Disable)(GL_TEXTURE_GEN_R); @@ -4507,6 +4513,17 @@ finish_modify_state() { GLP(Disable)(GL_TEXTURE_GEN_Q); force_normal = true; break; + + case TexGenAttrib::M_cube_map: + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + GLP(Disable)(GL_TEXTURE_GEN_Q); + force_normal = true; + break; case TexGenAttrib::M_object_position: GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -4555,27 +4572,40 @@ finish_modify_state() { // We achieve world position coordinates by using the eye // position mode, and loading the transform of the root // node--thus putting the "eye" at the root. - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); - CPT(TransformState) root_transform = _scene_setup->get_render_transform(); - GLP(LoadMatrixf)(root_transform->get_mat().get_data()); - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + { + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PushMatrix)(); + CPT(TransformState) root_transform = _scene_setup->get_render_transform(); + GLP(LoadMatrixf)(root_transform->get_mat().get_data()); + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data); - GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data); - GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data); - GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data); + GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data); + GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data); + GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data); + GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data); + + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + GLP(Enable)(GL_TEXTURE_GEN_Q); + + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PopMatrix)(); + } + break; + case TexGenAttrib::M_object_normal: + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); GLP(Enable)(GL_TEXTURE_GEN_S); GLP(Enable)(GL_TEXTURE_GEN_T); GLP(Enable)(GL_TEXTURE_GEN_R); - GLP(Enable)(GL_TEXTURE_GEN_Q); - - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); + GLP(Disable)(GL_TEXTURE_GEN_Q); + force_normal = true; break; } } @@ -4605,61 +4635,6 @@ void CLP(GraphicsStateGuardian):: free_pointers() { } -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::save_frame_buffer -// Access: Public -// Description: Saves the indicated planes of the frame buffer -// (within the indicated display region) and returns it -// in some meaningful form that can be restored later -// via restore_frame_buffer(). This is a helper -// function for push_frame_buffer() and -// pop_frame_buffer(). -//////////////////////////////////////////////////////////////////// -PT(SavedFrameBuffer) CLP(GraphicsStateGuardian):: -save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr) { - CLP(SavedFrameBuffer) *sfb = new CLP(SavedFrameBuffer)(buffer, dr); - - if (buffer._buffer_type & RenderBuffer::T_depth) { - // Save the depth buffer. - sfb->_depth = - new PixelBuffer(PixelBuffer::depth_buffer(dr->get_pixel_width(), - dr->get_pixel_height())); - copy_pixel_buffer(sfb->_depth, dr, buffer); - } - - if (buffer._buffer_type & RenderBuffer::T_back) { - // Save the color buffer. - sfb->_back_rgba = new Texture; - copy_texture(sfb->_back_rgba, dr, buffer); - } - - return sfb; -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::restore_frame_buffer -// Access: Public -// Description: Restores the frame buffer that was previously saved. -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -restore_frame_buffer(SavedFrameBuffer *frame_buffer) { - CLP(SavedFrameBuffer) *sfb = DCAST(CLP(SavedFrameBuffer), frame_buffer); - - if (sfb->_back_rgba != (Texture *)NULL && - (sfb->_buffer._buffer_type & RenderBuffer::T_back) != 0) { - // Restore the color buffer. - TextureContext *tc = sfb->_back_rgba->prepare_now(_prepared_objects, this); - draw_texture(tc, sfb->_display_region, sfb->_buffer); - } - - if (sfb->_depth != (PixelBuffer *)NULL && - (sfb->_buffer._buffer_type & RenderBuffer::T_depth) != 0) { - // Restore the depth buffer. - draw_pixel_buffer(sfb->_depth, sfb->_display_region, sfb->_buffer); - } -} - //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_untextured_state // Access: Protected, Static @@ -4744,7 +4719,7 @@ do_issue_texture() { // Stage i has changed. Issue the texture on this stage. _glActiveTexture(GL_TEXTURE0 + i); - GLP(Enable)(GL_TEXTURE_2D); + GLP(Enable)(get_texture_target(texture->get_texture_type())); TextureContext *tc = texture->prepare_now(_prepared_objects, this); apply_texture(tc); @@ -4762,8 +4737,7 @@ do_issue_texture() { } if (stage->get_mode() == TextureStage::M_decal) { - if (texture->_pbuffer != (PixelBuffer *)NULL && - texture->_pbuffer->get_num_components() < 3) { + if (texture->get_num_components() < 3) { // Make a special case for 1- and 2-channel decal textures. // OpenGL does not define their use with GL_DECAL for some // reason, so implement them using the combiner instead. @@ -4862,7 +4836,10 @@ do_issue_texture() { // Disable the texture stages that are no longer used. for (i = num_stages; i < num_old_stages; i++) { _glActiveTexture(GL_TEXTURE0 + i); + GLP(Disable)(GL_TEXTURE_1D); GLP(Disable)(GL_TEXTURE_2D); + GLP(Disable)(GL_TEXTURE_3D); + GLP(Disable)(GL_TEXTURE_CUBE_MAP); } _current_texture = new_texture; @@ -4885,38 +4862,37 @@ do_issue_texture() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: build_phony_mipmaps(Texture *tex) { - PixelBuffer *pb = tex->_pbuffer; - int xsize = pb->get_xsize(); - int ysize = pb->get_ysize(); + int x_size = tex->get_x_size(); + int y_size = tex->get_y_size(); GLCAT.info() << "Building phony mipmap levels for " << tex->get_name() << "\n"; int level = 0; - while (xsize > 0 && ysize > 0) { + while (x_size > 0 && y_size > 0) { GLCAT.info(false) - << " level " << level << " is " << xsize << " by " << ysize << "\n"; - build_phony_mipmap_level(level, xsize, ysize); + << " level " << level << " is " << x_size << " by " << y_size << "\n"; + build_phony_mipmap_level(level, x_size, y_size); - xsize >>= 1; - ysize >>= 1; + x_size >>= 1; + y_size >>= 1; level++; } - while (xsize > 0) { + while (x_size > 0) { GLCAT.info(false) - << " level " << level << " is " << xsize << " by 1\n"; - build_phony_mipmap_level(level, xsize, 1); + << " level " << level << " is " << x_size << " by 1\n"; + build_phony_mipmap_level(level, x_size, 1); - xsize >>= 1; + x_size >>= 1; level++; } - while (ysize > 0) { + while (y_size > 0) { GLCAT.info(false) - << " level " << level << " is 1 by " << ysize << "\n"; - build_phony_mipmap_level(level, 1, ysize); + << " level " << level << " is 1 by " << y_size << "\n"; + build_phony_mipmap_level(level, 1, y_size); - ysize >>= 1; + y_size >>= 1; level++; } } @@ -4927,7 +4903,7 @@ build_phony_mipmaps(Texture *tex) { // Description: Generates a single colored mipmap level. //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: -build_phony_mipmap_level(int level, int xsize, int ysize) { +build_phony_mipmap_level(int level, int x_size, int y_size) { static const int num_levels = 10; static const char *level_filenames[num_levels] = { "mipmap_level_0.rgb", @@ -4957,7 +4933,7 @@ build_phony_mipmap_level(int level, int xsize, int ysize) { level = level % num_levels; Filename filename(level_filenames[level]); - PNMImage image_sized(xsize, ysize); + PNMImage image_sized(x_size, y_size); PNMImage image_source; if (filename.resolve_filename(get_texture_path()) || filename.resolve_filename(get_model_path())) { @@ -4975,18 +4951,19 @@ build_phony_mipmap_level(int level, int xsize, int ysize) { level_colors[level][2]); } - PixelBuffer *pb = new PixelBuffer; - pb->load(image_sized); - - GLenum internal_format = get_internal_image_format(pb->get_format()); - GLenum external_format = get_external_image_format(pb->get_format()); - GLenum type = get_image_type(pb->get_image_type()); - - GLP(TexImage2D)(GL_TEXTURE_2D, level, internal_format, - pb->get_xsize(), pb->get_ysize(), 0, - external_format, type, pb->_image ); - - delete pb; + PT(Texture) tex = new Texture; + if (!tex->load(image_sized)) { + GLCAT.warning() + << "Unable to load phony mipmap image.\n"; + } else { + GLenum internal_format = get_internal_image_format(tex->get_format()); + GLenum external_format = get_external_image_format(tex->get_format()); + GLenum type = get_component_type(tex->get_component_type()); + + GLP(TexImage2D)(GL_TEXTURE_2D, level, internal_format, + tex->get_x_size(), tex->get_y_size(), 0, + external_format, type, tex->get_ram_image()); + } } //////////////////////////////////////////////////////////////////// @@ -4998,6 +4975,11 @@ build_phony_mipmap_level(int level, int xsize, int ysize) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: save_mipmap_images(Texture *tex) { + if (tex->get_texture_type() != Texture::TT_2d_texture) { + // Never mind on unusual texture formats. + return; + } + Filename filename = tex->get_name(); string name; if (filename.empty()) { @@ -5008,39 +4990,35 @@ save_mipmap_images(Texture *tex) { name = filename.get_basename_wo_extension(); } - PixelBuffer *pb = tex->get_ram_image(); - nassertv(pb != (PixelBuffer *)NULL); + GLenum external_format = get_external_image_format(tex->get_format()); + GLenum type = get_component_type(tex->get_component_type()); - GLenum external_format = get_external_image_format(pb->get_format()); - GLenum type = get_image_type(pb->get_image_type()); - - int xsize = pb->get_xsize(); - int ysize = pb->get_ysize(); + int x_size = tex->get_x_size(); + int y_size = tex->get_y_size(); // Specify byte-alignment for the pixels on output. GLP(PixelStorei)(GL_PACK_ALIGNMENT, 1); int mipmap_level = 0; do { - xsize = max(xsize, 1); - ysize = max(ysize, 1); + x_size = max(x_size, 1); + y_size = max(y_size, 1); - PT(PixelBuffer) mpb = - new PixelBuffer(xsize, ysize, pb->get_num_components(), - pb->get_component_width(), pb->get_image_type(), - pb->get_format()); + PT(Texture) mtex = new Texture; + mtex->setup_2d_texture(x_size, y_size, tex->get_component_type(), + tex->get_format()); GLP(GetTexImage)(GL_TEXTURE_2D, mipmap_level, external_format, - type, mpb->_image); + type, mtex->make_ram_image()); Filename mipmap_filename = name + "_" + format_string(mipmap_level) + ".rgb"; nout << "Writing mipmap level " << mipmap_level - << " (" << xsize << " by " << ysize << ") " + << " (" << x_size << " by " << y_size << ") " << mipmap_filename << "\n"; - mpb->write(mipmap_filename); + mtex->write(mipmap_filename); - xsize >>= 1; - ysize >>= 1; + x_size >>= 1; + y_size >>= 1; mipmap_level++; - } while (xsize > 0 && ysize > 0); + } while (x_size > 0 || y_size > 0); } #endif // NDEBUG diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index c3220d8f5e..36ebcdcf87 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -21,7 +21,6 @@ #include "graphicsStateGuardian.h" #include "geomprimitives.h" #include "texture.h" -#include "pixelBuffer.h" #include "displayRegion.h" #include "material.h" #include "depthTestAttrib.h" @@ -95,17 +94,10 @@ public: virtual GeomContext *prepare_geom(Geom *geom); virtual void release_geom(GeomContext *gc); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr); - virtual void copy_texture(Texture *tex, const DisplayRegion *dr, - const RenderBuffer &rb); - - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb); - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr); - - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb); + virtual void framebuffer_copy_to_texture + (Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb); + virtual bool framebuffer_copy_to_ram + (Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb); virtual void apply_material(const Material *material); void apply_fog(Fog *fog); @@ -182,9 +174,6 @@ protected: virtual void finish_modify_state(); virtual void free_pointers(); - virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - virtual void restore_frame_buffer(SavedFrameBuffer *frame_buffer); INLINE void enable_multisample_antialias(bool val); INLINE void enable_multisample_alpha_one(bool val); @@ -215,19 +204,18 @@ protected: void bind_texture(TextureContext *tc); void specify_texture(Texture *tex); bool apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex); + bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, + GLenum target, GLint internal_format, + int width, int height, int depth, + GLint external_format, GLenum component_type, + const unsigned char *image); - void draw_texture(TextureContext *tc, const DisplayRegion *dr); - void draw_texture(TextureContext *tc, const DisplayRegion *dr, - const RenderBuffer &rb); - void draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - void draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb); - - GLenum get_texture_wrap_mode(Texture::WrapMode wm) const; + static GLenum get_texture_target(Texture::TextureType texture_type); + GLenum get_texture_wrap_mode(Texture::WrapMode wm); static GLenum get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps); - static GLenum get_image_type(PixelBuffer::Type type); - GLint get_external_image_format(PixelBuffer::Format format) const; - static GLint get_internal_image_format(PixelBuffer::Format format); + static GLenum get_component_type(Texture::ComponentType component_type); + GLint get_external_image_format(Texture::Format format) const; + static GLint get_internal_image_format(Texture::Format format); static GLint get_texture_apply_mode_type(TextureStage::Mode am); static GLint get_texture_combine_type(TextureStage::CombineMode cm); static GLint get_texture_src_type(TextureStage::CombineSource cs); @@ -243,7 +231,7 @@ protected: #ifndef NDEBUG void build_phony_mipmaps(Texture *tex); - void build_phony_mipmap_level(int level, int xsize, int ysize); + void build_phony_mipmap_level(int level, int x_size, int y_size); void save_mipmap_images(Texture *tex); #endif @@ -305,6 +293,10 @@ protected: pset _extensions; public: + GLint _max_texture_size; + GLint _max_3d_texture_size; + GLint _max_cube_map_size; + bool _supports_bgr; bool _supports_rescale_normal; diff --git a/panda/src/glstuff/glSavedFrameBuffer_src.I b/panda/src/glstuff/glSavedFrameBuffer_src.I deleted file mode 100644 index 56dd4d3a48..0000000000 --- a/panda/src/glstuff/glSavedFrameBuffer_src.I +++ /dev/null @@ -1,39 +0,0 @@ -// Filename: glSavedFrameBuffer_src.I -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: CLP(SavedFrameBuffer)::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE CLP(SavedFrameBuffer):: -CLP(SavedFrameBuffer)(const RenderBuffer &buffer, CPT(DisplayRegion) dr) : - SavedFrameBuffer(buffer, dr) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: CLP(SavedFrameBuffer)::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE CLP(SavedFrameBuffer):: -~CLP(SavedFrameBuffer)() { -} - diff --git a/panda/src/glstuff/glSavedFrameBuffer_src.cxx b/panda/src/glstuff/glSavedFrameBuffer_src.cxx deleted file mode 100644 index 59a15f5fd5..0000000000 --- a/panda/src/glstuff/glSavedFrameBuffer_src.cxx +++ /dev/null @@ -1,19 +0,0 @@ -// Filename: glSavedFrameBuffer.cxx -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - -TypeHandle CLP(SavedFrameBuffer)::_type_handle; diff --git a/panda/src/glstuff/glSavedFrameBuffer_src.h b/panda/src/glstuff/glSavedFrameBuffer_src.h deleted file mode 100644 index 07af3e91f7..0000000000 --- a/panda/src/glstuff/glSavedFrameBuffer_src.h +++ /dev/null @@ -1,58 +0,0 @@ -// Filename: glSavedFrameBuffer_src.h -// Created by: drose (06Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 "pandabase.h" - -#include "savedFrameBuffer.h" -#include "texture.h" -#include "pixelBuffer.h" - - -//////////////////////////////////////////////////////////////////// -// Class : GLSavedFrameBuffer -// Description : -//////////////////////////////////////////////////////////////////// -class EXPCL_GL CLP(SavedFrameBuffer) : public SavedFrameBuffer { -public: - INLINE CLP(SavedFrameBuffer)(const RenderBuffer &buffer, - CPT(DisplayRegion) dr); - INLINE ~CLP(SavedFrameBuffer)(); - - PT(Texture) _back_rgba; - PT(PixelBuffer) _depth; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - SavedFrameBuffer::init_type(); - register_type(_type_handle, CLASSPREFIX_QUOTED "SavedFrameBuffer", - SavedFrameBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "glSavedFrameBuffer_src.I" - diff --git a/panda/src/glstuff/glTextureContext_src.h b/panda/src/glstuff/glTextureContext_src.h index 682dfe311b..c403e0a236 100644 --- a/panda/src/glstuff/glTextureContext_src.h +++ b/panda/src/glstuff/glTextureContext_src.h @@ -40,7 +40,7 @@ public: GLint _internal_format; GLsizei _width; GLsizei _height; - GLint _border_width; + GLsizei _depth; public: static TypeHandle get_class_type() { diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index be8e406464..2e1fc4af92 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -61,7 +61,6 @@ ConfigVariableBool CLP(color_mask) void CLP(init_classes)() { CLP(GraphicsStateGuardian)::init_type(); - CLP(SavedFrameBuffer)::init_type(); CLP(TextureContext)::init_type(); CLP(GeomContext)::init_type(); diff --git a/panda/src/glstuff/glstuff_src.cxx b/panda/src/glstuff/glstuff_src.cxx index bbade49d1a..e99a634d66 100644 --- a/panda/src/glstuff/glstuff_src.cxx +++ b/panda/src/glstuff/glstuff_src.cxx @@ -24,7 +24,6 @@ #include "glmisc_src.cxx" #include "glTextureContext_src.cxx" #include "glGeomContext_src.cxx" -#include "glSavedFrameBuffer_src.cxx" #include "glCgShaderContext_src.cxx" #include "glGraphicsStateGuardian_src.cxx" diff --git a/panda/src/glstuff/glstuff_src.h b/panda/src/glstuff/glstuff_src.h index fc40f82d73..2c311d500a 100644 --- a/panda/src/glstuff/glstuff_src.h +++ b/panda/src/glstuff/glstuff_src.h @@ -42,7 +42,6 @@ #include "glmisc_src.h" #include "glTextureContext_src.h" #include "glGeomContext_src.h" -#include "glSavedFrameBuffer_src.h" #include "glCgShaderContext_src.h" #include "glGraphicsStateGuardian_src.h" diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index b3a1666bc6..da214ebe53 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -16,12 +16,11 @@ geomContext.I geomContext.h \ geomLine.h geomLinestrip.h geomPoint.h geomPolygon.h \ geomQuad.h geomSphere.h geomSprite.I geomSprite.h geomTri.h \ - geomTrifan.h geomTristrip.h imageBuffer.I imageBuffer.h \ + geomTrifan.h geomTristrip.h \ material.I material.h materialPool.I materialPool.h \ matrixLens.I matrixLens.h \ orthographicLens.I orthographicLens.h perspectiveLens.I \ - perspectiveLens.h pixelBuffer.I \ - pixelBuffer.h \ + perspectiveLens.h \ preparedGraphicsObjects.I preparedGraphicsObjects.h \ lens.h lens.I \ savedContext.I savedContext.h \ @@ -37,9 +36,9 @@ geomContext.cxx \ geomLine.cxx geomLinestrip.cxx geomPoint.cxx geomPolygon.cxx \ geomQuad.cxx geomSphere.cxx geomSprite.cxx geomTri.cxx \ - geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx \ + geomTrifan.cxx geomTristrip.cxx material.cxx \ materialPool.cxx matrixLens.cxx orthographicLens.cxx \ - perspectiveLens.cxx pixelBuffer.cxx \ + perspectiveLens.cxx \ preparedGraphicsObjects.cxx \ lens.cxx \ savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \ @@ -53,10 +52,10 @@ geomLine.h \ geomLinestrip.h geomPoint.h geomPolygon.h geomQuad.h geomSphere.h \ geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \ - geomprimitives.h imageBuffer.I imageBuffer.h material.I material.h \ + geomprimitives.h material.I material.h \ materialPool.I materialPool.h matrixLens.I matrixLens.h \ orthographicLens.I orthographicLens.h perspectiveLens.I \ - perspectiveLens.h pixelBuffer.I pixelBuffer.h \ + perspectiveLens.h \ preparedGraphicsObjects.I preparedGraphicsObjects.h \ lens.h lens.I \ savedContext.I savedContext.h \ diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 4ba5c23c4c..daad368bd3 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -22,12 +22,10 @@ #include "drawable.h" #include "geom.h" #include "geomprimitives.h" -#include "imageBuffer.h" #include "material.h" #include "orthographicLens.h" #include "matrixLens.h" #include "perspectiveLens.h" -#include "pixelBuffer.h" #include "lens.h" #include "texture.h" #include "textureStage.h" @@ -52,7 +50,7 @@ ConfigVariableBool keep_texture_ram ("keep-texture-ram", false, PRC_DESC("Set this to true to retain the ram image for each texture after it " "has been prepared with the GSG. This will allow the texture to be " - "prepared with multiple GSG, or to be re-prepared later after it is " + "prepared with multiple GSG's, or to be re-prepared later after it is " "explicitly released from the GSG, without having to reread the " "texture image from disk; but it will consume memory somewhat " "wastefully.")); @@ -135,12 +133,10 @@ ConfigureFn(config_gobj) { GeomTri::init_type(); GeomTrifan::init_type(); GeomTristrip::init_type(); - ImageBuffer::init_type(); Material::init_type(); OrthographicLens::init_type(); MatrixLens::init_type(); PerspectiveLens::init_type(); - PixelBuffer::init_type(); Lens::init_type(); Texture::init_type(); dDrawable::init_type(); diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 884462eae5..5315e38495 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -2,13 +2,11 @@ #include "config_gobj.cxx" #include "drawable.cxx" #include "geomContext.cxx" -#include "imageBuffer.cxx" #include "material.cxx" #include "materialPool.cxx" #include "orthographicLens.cxx" #include "matrixLens.cxx" #include "perspectiveLens.cxx" -#include "pixelBuffer.cxx" #include "preparedGraphicsObjects.cxx" #include "lens.cxx" #include "savedContext.cxx" diff --git a/panda/src/gobj/imageBuffer.I b/panda/src/gobj/imageBuffer.I deleted file mode 100644 index 78593338af..0000000000 --- a/panda/src/gobj/imageBuffer.I +++ /dev/null @@ -1,224 +0,0 @@ -// Filename: imageBuffer.I -// Created by: drose (21Nov00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::has_filename -// Access: Published -// Description: Returns true if the filename has been set and -// is available. See set_filename(). -//////////////////////////////////////////////////////////////////// -INLINE bool ImageBuffer:: -has_filename() const { - return !_filename.empty(); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::get_filename -// Access: Published -// Description: Returns the filename that has been set. This is the -// name of the file as it was requested. Also see -// get_fullpath(). -//////////////////////////////////////////////////////////////////// -INLINE const Filename &ImageBuffer:: -get_filename() const { - return _filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::has_alpha_filename -// Access: Published -// Description: Returns true if the alpha_filename has been set and -// is available. See set_alpha_filename(). -//////////////////////////////////////////////////////////////////// -INLINE bool ImageBuffer:: -has_alpha_filename() const { - return !_alpha_filename.empty(); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::get_alpha_filename -// Access: Published -// Description: Returns the alpha_filename that has been set. If -// this is set, it represents the name of the alpha -// component, which is stored in a separate file. See -// also get_filename(), and get_alpha_fullpath(). -//////////////////////////////////////////////////////////////////// -INLINE const Filename &ImageBuffer:: -get_alpha_filename() const { - return _alpha_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::has_fullpath -// Access: Published -// Description: Returns true if the fullpath has been set and -// is available. See set_fullpath(). -//////////////////////////////////////////////////////////////////// -INLINE bool ImageBuffer:: -has_fullpath() const { - return !_fullpath.empty(); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::get_fullpath -// Access: Published -// Description: Returns the fullpath that has been set. This is the -// full path to the file as it was found along the -// texture search path. -//////////////////////////////////////////////////////////////////// -INLINE const Filename &ImageBuffer:: -get_fullpath() const { - return _fullpath; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::has_alpha_fullpath -// Access: Published -// Description: Returns true if the alpha_fullpath has been set and -// is available. See set_alpha_fullpath(). -//////////////////////////////////////////////////////////////////// -INLINE bool ImageBuffer:: -has_alpha_fullpath() const { - return !_alpha_fullpath.empty(); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::get_alpha_fullpath -// Access: Published -// Description: -// Returns the alpha_fullpath that has been set. This -// is the full path to the alpha part of the image file -// as it was found along the texture search path. -//////////////////////////////////////////////////////////////////// -INLINE const Filename &ImageBuffer:: -get_alpha_fullpath() const { - return _alpha_fullpath; -} - - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::set_filename -// Access: Public -// Description: Sets the name of the file that contains the image's -// contents. Normally, this is set automatically when -// the image is loaded, for instance via -// Texture::read(). -// -// The ImageBuffer's get_name() function used to return -// the filename, but now returns just the basename -// (without the extension), which is a more useful name -// for identifying an image in show code. -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -set_filename(const Filename &filename) { - _filename = filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::clear_filename -// Access: Public -// Description: Removes the alpha filename, if it was previously set. -// See set_filename(). -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -clear_filename() { - _filename = Filename(); -} - - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::set_alpha_filename -// Access: Public -// Description: Sets the name of the file that contains the image's -// alpha channel contents. Normally, this is set -// automatically when the image is loaded, for instance -// via Texture::read(). -// -// The ImageBuffer's get_filename() function returns the -// name of the image file that was loaded into the -// buffer. In the case where a texture specified two -// separate files to load, a 1- or 3-channel color image -// and a 1-channel alpha image, this Filename is update -// to contain the name of the image file that was loaded -// into the buffer's alpha channel. -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -set_alpha_filename(const Filename &alpha_filename) { - _alpha_filename = alpha_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::clear_alpha_filename -// Access: Public -// Description: Removes the alpha filename, if it was previously set. -// See set_alpha_filename(). -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -clear_alpha_filename() { - _alpha_filename = Filename(); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::set_fullpath -// Access: Public -// Description: Sets the full pathname to the file that contains the -// image's contents, as found along the search path. -// Normally, this is set automatically when the image is -// loaded, for instance via Texture::read(). -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -set_fullpath(const Filename &fullpath) { - _fullpath = fullpath; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::clear_fullpath -// Access: Public -// Description: Removes the alpha fullpath, if it was previously set. -// See set_fullpath(). -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -clear_fullpath() { - _fullpath = Filename(); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::set_alpha_fullpath -// Access: Public -// Description: Sets the full pathname to the file that contains the -// image's alpha channel contents, as found along the -// search path. Normally, this is set automatically -// when the image is loaded, for instance via -// Texture::read(). -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -set_alpha_fullpath(const Filename &alpha_fullpath) { - _alpha_fullpath = alpha_fullpath; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::clear_alpha_fullpath -// Access: Public -// Description: Removes the alpha fullpath, if it was previously set. -// See set_alpha_fullpath(). -//////////////////////////////////////////////////////////////////// -INLINE void ImageBuffer:: -clear_alpha_fullpath() { - _alpha_fullpath = Filename(); -} diff --git a/panda/src/gobj/imageBuffer.cxx b/panda/src/gobj/imageBuffer.cxx deleted file mode 100644 index 81b0ddf591..0000000000 --- a/panda/src/gobj/imageBuffer.cxx +++ /dev/null @@ -1,128 +0,0 @@ -// Filename: imageBuffer.cxx -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 "pandabase.h" - -#include "imageBuffer.h" -#include "config_gobj.h" -#include "config_util.h" - -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" - -TypeHandle ImageBuffer::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -ImageBuffer:: -ImageBuffer() { - _primary_file_num_channels = 0; - _alpha_file_channel = 0; -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -ImageBuffer:: -~ImageBuffer() { -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::write_datagram -// Access: Public -// Description: Function to write the important information in -// the particular object to a Datagram -//////////////////////////////////////////////////////////////////// -void ImageBuffer:: -write_datagram(BamWriter *, Datagram &me) -{ - Filename filename = get_filename(); - Filename alpha_filename = get_alpha_filename(); - - switch (bam_texture_mode) { - case BTM_unchanged: - case BTM_rawdata: - break; - - case BTM_fullpath: - filename = get_fullpath(); - alpha_filename = get_alpha_fullpath(); - break; - - case BTM_relative: - filename = get_fullpath(); - alpha_filename = get_alpha_fullpath(); - filename.find_on_searchpath(get_texture_path()) || - filename.find_on_searchpath(get_model_path()); - if (gobj_cat.is_debug()) { - gobj_cat.debug() - << "Texture file " << get_filename() << " found as " << filename << "\n"; - } - alpha_filename.find_on_searchpath(get_texture_path()) || - alpha_filename.find_on_searchpath(get_model_path()); - if (gobj_cat.is_debug()) { - gobj_cat.debug() - << "Alpha image " << get_alpha_filename() << " found as " << alpha_filename << "\n"; - } - break; - - case BTM_basename: - filename = filename.get_basename(); - alpha_filename = alpha_filename.get_basename(); - break; - - default: - gobj_cat.error() - << "Unsupported bam-texture-mode: " << (int)bam_texture_mode << "\n"; - } - - me.add_string(get_name()); - me.add_string(filename); - me.add_string(alpha_filename); - me.add_uint8(_primary_file_num_channels); - me.add_uint8(_alpha_file_channel); -} - -//////////////////////////////////////////////////////////////////// -// Function: ImageBuffer::fillin -// Access: Protected -// Description: Function that reads out of the datagram (or asks -// manager to read) all of the data that is needed to -// re-create this object and stores it in the appropiate -// place -//////////////////////////////////////////////////////////////////// -void ImageBuffer:: -fillin(DatagramIterator &scan, BamReader *manager) { - set_name(scan.get_string()); - set_filename(scan.get_string()); - set_alpha_filename(scan.get_string()); - - if (manager->get_file_minor_ver() < 3) { - _primary_file_num_channels = 0; - _alpha_file_channel = 0; - } else { - _primary_file_num_channels = scan.get_uint8(); - _alpha_file_channel = scan.get_uint8(); - } -} diff --git a/panda/src/gobj/imageBuffer.h b/panda/src/gobj/imageBuffer.h deleted file mode 100644 index c36d467fb5..0000000000 --- a/panda/src/gobj/imageBuffer.h +++ /dev/null @@ -1,121 +0,0 @@ -// Filename: imageBuffer.h -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 IMAGEBUFFER_H -#define IMAGEBUFFER_H - -#include "pandabase.h" - -#include "drawable.h" -#include "pointerToArray.h" -#include "typedef.h" -#include "filename.h" -#include "namable.h" - -class RenderBuffer; -class DisplayRegion; - -//////////////////////////////////////////////////////////////////// -// Class : ImageBuffer -// Description : -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA ImageBuffer : public ReferenceCount, - public WritableConfigurable, public Namable { -PUBLISHED: - ImageBuffer(); - virtual ~ImageBuffer(); - -public: - virtual void config( void ) { WritableConfigurable::config(); } - -PUBLISHED: - INLINE bool has_filename() const; - INLINE const Filename &get_filename() const; - INLINE bool has_alpha_filename() const; - INLINE const Filename &get_alpha_filename() const; - - INLINE bool has_fullpath() const; - INLINE const Filename &get_fullpath() const; - INLINE bool has_alpha_fullpath() const; - INLINE const Filename &get_alpha_fullpath() const; - -public: - INLINE void set_filename(const Filename &filename); - INLINE void clear_filename(); - INLINE void set_alpha_filename(const Filename &alpha_filename); - INLINE void clear_alpha_filename(); - - INLINE void set_fullpath(const Filename &fullpath); - INLINE void clear_fullpath(); - INLINE void set_alpha_fullpath(const Filename &alpha_fullpath); - INLINE void clear_alpha_fullpath(); - -private: - Filename _filename; - Filename _alpha_filename; - Filename _fullpath; - Filename _alpha_fullpath; - -protected: - // These are set by (and read by) the derived Texture class. - - // The number of channels of the primary file we use. 1, 2, 3, or 4. - int _primary_file_num_channels; - - // If we have a separate alpha file, this designates which channel - // in the alpha file provides the alpha channel. 0 indicates the - // combined grayscale value of rgb; otherwise, 1, 2, 3, or 4 are - // valid. - int _alpha_file_channel; - -public: - // Abstract class, so no factory methods for Reading and Writing - virtual void write_datagram(BamWriter *manager, Datagram &me); - -protected: - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ReferenceCount::init_type(); - WritableConfigurable::init_type(); - Namable::init_type(); - register_type(_type_handle, "ImageBuffer", - ReferenceCount::get_class_type(), - WritableConfigurable::get_class_type(), - Namable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - - static TypeHandle _type_handle; -}; - -#include "imageBuffer.I" - -#endif - - diff --git a/panda/src/gobj/pixelBuffer.I b/panda/src/gobj/pixelBuffer.I deleted file mode 100644 index a566774c8f..0000000000 --- a/panda/src/gobj/pixelBuffer.I +++ /dev/null @@ -1,331 +0,0 @@ -// Filename: pixelBuffer.I -// Created by: drose (05Feb99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: rgb_buffer -// Access: Public -// Description: Constructs a PixelBuffer suitable for RGB -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer PixelBuffer:: -rgb_buffer(int xsize, int ysize) { - return PixelBuffer(xsize, ysize, 3, sizeof(uchar), T_unsigned_byte, - F_rgb); -} - -//////////////////////////////////////////////////////////////////// -// Function: rgba_buffer -// Access: Public -// Description: Constructs a PixelBuffer suitable for RGBA -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer PixelBuffer:: -rgba_buffer(int xsize, int ysize) { - return PixelBuffer(xsize, ysize, 4, sizeof(uchar), T_unsigned_byte, - F_rgba); -} - -//////////////////////////////////////////////////////////////////// -// Function: depth_buffer -// Access: Public -// Description: Constructs a PixelBuffer suitable for depth maps -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer PixelBuffer:: -depth_buffer(int xsize, int ysize) { - return PixelBuffer(xsize, ysize, 1, sizeof(float), T_float, - F_depth_component); -} - -//////////////////////////////////////////////////////////////////// -// Function: stencil_buffer -// Access: Public -// Description: Constructs a PixelBuffer suitable for stencil buffers -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer PixelBuffer:: -stencil_buffer(int xsize, int ysize) { - return PixelBuffer(xsize, ysize, 1, sizeof(uchar), T_unsigned_byte, - F_stencil_index); -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer:: -~PixelBuffer(void) { -} - - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_xsize -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer::set_xsize(int size) -{ - if (_xsize != size) { - _xsize = size; - make_dirty(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_ysize -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer::set_ysize(int size) -{ - if (_ysize != size) { - _ysize = size; - make_dirty(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_num_components -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -set_num_components(int num_components) { - if (_num_components != num_components) { - _num_components = num_components; - make_dirty(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_component_width -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -set_component_width(int component_width) { - if (_component_width != component_width) { - _component_width = component_width; - make_dirty(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_format -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -set_format(PixelBuffer::Format format) { - if (_format != format) { - _format = format; - make_dirty(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_image_type -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -set_image_type(PixelBuffer::Type type) { - if (_type != type) { - _type = type; - make_dirty(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_loaded -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -set_loaded() { - _loaded = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_xsize -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int PixelBuffer:: -get_xsize() const { - return _xsize; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_ysize -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int PixelBuffer:: -get_ysize() const { - return _ysize; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_num_components -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int PixelBuffer:: -get_num_components() const { - return _num_components; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_component_width -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int PixelBuffer:: -get_component_width() const { - return _component_width; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_format -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer::Format PixelBuffer:: -get_format() const { - return _format; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_image_type -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE PixelBuffer::Type PixelBuffer:: -get_image_type() const { - return _type; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::set_uchar_rgb_texel -// Access: Public -// Description: This is only valid when the PixelBuffer is an RGB -// buffer with uchar components. -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -set_uchar_rgb_texel(const uchar color[3], int x, int y, int width) -{ - int i = y * 3 * width + x * 3; - _image[i] = color[0]; - _image[i+1] = color[1]; - _image[i+2] = color[2]; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::store_unscaled_byte -// Access: Private -// Description: This is used by load() to store the next consecutive -// component value into the indicated element of the -// array, which is taken to be an array of unsigned -// bytes. The value is assumed to be in the range -// 0-255. -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -store_unscaled_byte(int &index, int value) { - _image[index++] = (uchar)value; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::store_unscaled_short -// Access: Private -// Description: This is used by load() to store the next consecutive -// component value into the indicated element of the -// array, which is taken to be an array of unsigned -// shorts. The value is assumed to be in the range -// 0-65535. -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -store_unscaled_short(int &index, int value) { - union { - ushort us; - uchar uc[2]; - } v; - v.us = (ushort)value; - _image[index++] = v.uc[0]; - _image[index++] = v.uc[1]; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::store_scaled_byte -// Access: Private -// Description: This is used by load() to store the next consecutive -// component value into the indicated element of the -// array, which is taken to be an array of unsigned -// bytes. The value will be scaled by the indicated -// factor before storing it. -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -store_scaled_byte(int &index, int value, double scale) { - store_unscaled_byte(index, (int)(value * scale)); -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::store_scaled_short -// Access: Private -// Description: This is used by load() to store the next consecutive -// component value into the indicated element of the -// array, which is taken to be an array of unsigned -// shorts. The value will be scaled by the indicated -// factor before storing it. -//////////////////////////////////////////////////////////////////// -INLINE void PixelBuffer:: -store_scaled_short(int &index, int value, double scale) { - store_unscaled_short(index, (int)(value * scale)); -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_unsigned_byte -// Access: Private -// Description: This is used by store() to retieve the next -// consecutive component value from the indicated -// element of the array, which is taken to be an array -// of unsigned bytes. -//////////////////////////////////////////////////////////////////// -INLINE double PixelBuffer:: -get_unsigned_byte(int &index) const { - nassertr(index >= 0 && index < (int)_image.size(), 0.0); - return (double)_image[index++] / 255.0; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::get_unsigned_short -// Access: Private -// Description: This is used by store() to retieve the next -// consecutive component value from the indicated -// element of the array, which is taken to be an array -// of unsigned shorts. -//////////////////////////////////////////////////////////////////// -INLINE double PixelBuffer:: -get_unsigned_short(int &index) const { - nassertr(index >= 0 && index+1 < (int)_image.size(), 0.0); - union { - ushort us; - uchar uc[2]; - } v; - v.uc[0] = _image[index++]; - v.uc[1] = _image[index++]; - return (double)v.us / 65535.0; -} diff --git a/panda/src/gobj/pixelBuffer.cxx b/panda/src/gobj/pixelBuffer.cxx deleted file mode 100644 index 93c163ba23..0000000000 --- a/panda/src/gobj/pixelBuffer.cxx +++ /dev/null @@ -1,390 +0,0 @@ -// Filename: pixelBuffer.cxx -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 "pixelBuffer.h" -#include "config_gobj.h" - -//////////////////////////////////////////////////////////////////// -// Static variables -//////////////////////////////////////////////////////////////////// -TypeHandle PixelBuffer::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PixelBuffer:: -PixelBuffer() { - _xsize = 0; - _ysize = 0; - _format = F_rgb; - _type = T_unsigned_byte; - _num_components = 3; - _component_width = 1; - _image = PTA_uchar(); - - _loaded = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PixelBuffer:: -PixelBuffer(int xsize, int ysize, int components, int component_width, - Type type, Format format, bool allocate_ram) { - _xsize = xsize; - _ysize = ysize; - _num_components = components; - _component_width = component_width; - _type = type; - _format = format; - - if (allocate_ram) { - int num_pixels = _xsize * _ysize * _num_components * _component_width; - _image = PTA_uchar::empty_array((size_t)num_pixels); - } - _loaded = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PixelBuffer:: -PixelBuffer(const PixelBuffer ©) : - _xsize(copy._xsize), - _ysize(copy._ysize), - _num_components(copy._num_components), - _component_width(copy._component_width), - _format(copy._format), - _type(copy._type), - _loaded(copy._loaded), - _image(copy._image) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void PixelBuffer:: -operator = (const PixelBuffer ©) { - _xsize = copy._xsize; - _ysize = copy._ysize; - _num_components = copy._num_components; - _component_width = copy._component_width; - _format = copy._format; - _type = copy._type; - _loaded = copy._loaded; - _image = copy._image; -} - -//////////////////////////////////////////////////////////////////// -// Function: config -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -void PixelBuffer::config(void) -{ - ImageBuffer::config(); -} - -//////////////////////////////////////////////////////////////////// -// Function: read -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -bool PixelBuffer:: -read(const Filename &name) { - PNMImage pnmimage; - - if (!pnmimage.read(name)) { - gobj_cat.error() - << "PixelBuffer::read() - couldn't read: " << name << endl; - return false; - } - - set_name(name.get_basename_wo_extension()); - set_filename(name); - clear_alpha_filename(); - return load(pnmimage); -} - -//////////////////////////////////////////////////////////////////// -// Function: write -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -bool PixelBuffer:: -write(const Filename &name) const { - PNMImage pnmimage; - if (!store(pnmimage)) { - return false; - } - - Filename tname; - if (name.empty()) { - tname = get_filename(); - } else { - tname = name; - } - - if (!pnmimage.write(tname)) { - gobj_cat.error() - << "PixelBuffer::write() - couldn't write: " << name << endl; - return false; - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: load -// Access: Public -// Description: Extracts the image data from the given PNMImage and -// stores it in the _image member, as an unadorned array -// of pixel values. Note that we now store pixel -// components in the order B, G, R, A. -//////////////////////////////////////////////////////////////////// -bool PixelBuffer::load(const PNMImage& pnmimage) -{ - int num_components = pnmimage.get_num_channels(); - - if (!_loaded || num_components != _num_components) { - // Come up with a default format based on the number of channels. - // But only do this the first time the file is loaded, or if the - // number of channels in the image changes on subsequent loads. - - switch (pnmimage.get_color_type()) { - case PNMImage::CT_grayscale: - _format = F_luminance; - break; - - case PNMImage::CT_two_channel: - _format = F_luminance_alpha; - break; - - case PNMImage::CT_color: - _format = F_rgb; - break; - - case PNMImage::CT_four_channel: - _format = F_rgba; - break; - - default: - // Eh? - nassertr(false, false); - _format = F_rgb; - }; - } - - _xsize = pnmimage.get_x_size(); - _ysize = pnmimage.get_y_size(); - _num_components = num_components; - _component_width = 1; - _loaded = true; - - // Now copy the pixel data from the PNMImage into our internal - // _image component. - bool has_alpha = pnmimage.has_alpha(); - bool is_grayscale = pnmimage.is_grayscale(); - xelval maxval = pnmimage.get_maxval(); - - if (maxval == 255) { - // Most common case: one byte per pixel, and the source image - // shows a maxval of 255. No scaling is necessary. - _type = T_unsigned_byte; - _image = PTA_uchar::empty_array((int)(_xsize * _ysize * _num_components)); - int idx = 0; - - for (int j = _ysize-1; j >= 0; j--) { - for (int i = 0; i < _xsize; i++) { - if (is_grayscale) { - store_unscaled_byte(idx, pnmimage.get_gray_val(i, j)); - } else { - store_unscaled_byte(idx, pnmimage.get_blue_val(i, j)); - store_unscaled_byte(idx, pnmimage.get_green_val(i, j)); - store_unscaled_byte(idx, pnmimage.get_red_val(i, j)); - } - if (has_alpha) { - store_unscaled_byte(idx, pnmimage.get_alpha_val(i, j)); - } - } - } - - } else if (maxval == 65535) { - // Another possible case: two bytes per pixel, and the source - // image shows a maxval of 65535. Again, no scaling is necessary. - _type = T_unsigned_short; - _image = PTA_uchar::empty_array(_xsize * _ysize * _num_components * 2); - _component_width = 2; - int idx = 0; - - for (int j = _ysize-1; j >= 0; j--) { - for (int i = 0; i < _xsize; i++) { - if (is_grayscale) { - store_unscaled_short(idx, pnmimage.get_gray_val(i, j)); - } else { - store_unscaled_short(idx, pnmimage.get_blue_val(i, j)); - store_unscaled_short(idx, pnmimage.get_green_val(i, j)); - store_unscaled_short(idx, pnmimage.get_red_val(i, j)); - } - if (has_alpha) { - store_unscaled_short(idx, pnmimage.get_alpha_val(i, j)); - } - } - } - - } else if (maxval <= 255) { - // A less common case: one byte per pixel, but the maxval is - // something other than 255. In this case, we should scale the - // pixel values up to the appropriate amount. - _type = T_unsigned_byte; - _image = PTA_uchar::empty_array(_xsize * _ysize * _num_components); - int idx = 0; - double scale = 255.0 / (double)maxval; - - for (int j = _ysize-1; j >= 0; j--) { - for (int i = 0; i < _xsize; i++) { - if (is_grayscale) { - store_scaled_byte(idx, pnmimage.get_gray_val(i, j), scale); - } else { - store_scaled_byte(idx, pnmimage.get_blue_val(i, j), scale); - store_scaled_byte(idx, pnmimage.get_green_val(i, j), scale); - store_scaled_byte(idx, pnmimage.get_red_val(i, j), scale); - } - if (has_alpha) { - store_scaled_byte(idx, pnmimage.get_alpha_val(i, j), scale); - } - } - } - - } else { - // Another uncommon case: two bytes per pixel, and the maxval is - // something other than 65535. Again, we must scale the pixel - // values. - _type = T_unsigned_short; - _image = PTA_uchar::empty_array(_xsize * _ysize * _num_components * 2); - _component_width = 2; - int idx = 0; - double scale = 65535.0 / (double)maxval; - - for (int j = _ysize-1; j >= 0; j--) { - for (int i = 0; i < _xsize; i++) { - if (is_grayscale) { - store_scaled_short(idx, pnmimage.get_gray_val(i, j), scale); - } else { - store_scaled_short(idx, pnmimage.get_blue_val(i, j), scale); - store_scaled_short(idx, pnmimage.get_green_val(i, j), scale); - store_scaled_short(idx, pnmimage.get_red_val(i, j), scale); - } - if (has_alpha) { - store_scaled_short(idx, pnmimage.get_alpha_val(i, j), scale); - } - } - } - } - - config(); - return true; -} - - -//////////////////////////////////////////////////////////////////// -// Function: store -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -bool PixelBuffer:: -store(PNMImage &pnmimage) const { - if (_type == T_unsigned_byte) { - pnmimage.clear(_xsize, _ysize, _num_components); - bool has_alpha = pnmimage.has_alpha(); - bool is_grayscale = pnmimage.is_grayscale(); - - int idx = 0; - for (int j = _ysize-1; j >= 0; j--) { - for (int i = 0; i < _xsize; i++) { - if (is_grayscale) { - pnmimage.set_gray(i, j, get_unsigned_byte(idx)); - } else { - pnmimage.set_blue(i, j, get_unsigned_byte(idx)); - pnmimage.set_green(i, j, get_unsigned_byte(idx)); - pnmimage.set_red(i, j, get_unsigned_byte(idx)); - } - if (has_alpha) - pnmimage.set_alpha(i, j, get_unsigned_byte(idx)); - } - } - return true; - - } else if (_type == T_unsigned_short) { - pnmimage.clear(_xsize, _ysize, _num_components, 65535); - bool has_alpha = pnmimage.has_alpha(); - bool is_grayscale = pnmimage.is_grayscale(); - - int idx = 0; - for (int j = _ysize-1; j >= 0; j--) { - for (int i = 0; i < _xsize; i++) { - if (is_grayscale) { - pnmimage.set_gray(i, j, get_unsigned_short(idx)); - } else { - pnmimage.set_blue(i, j, get_unsigned_short(idx)); - pnmimage.set_green(i, j, get_unsigned_short(idx)); - pnmimage.set_red(i, j, get_unsigned_short(idx)); - } - if (has_alpha) - pnmimage.set_alpha(i, j, get_unsigned_short(idx)); - } - } - return true; - } - - gobj_cat.error() - << "Couldn't write image for " << get_name() - << "; inappropriate type " << (int)_type << ".\n"; - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: copy -// Access: -// Description: Deep copy of pixel buffer -//////////////////////////////////////////////////////////////////// -void PixelBuffer:: -copy(const PixelBuffer *pb) { - nassertv(pb != NULL); - _xsize = pb->_xsize; - _ysize = pb->_ysize; - _num_components = pb->_num_components; - _component_width = pb->_component_width; - _format = pb->_format; - - if (!pb->_image.is_null()) { - _image = PTA_uchar::empty_array(0); - _image.v() = pb->_image.v(); - } else { - _image = PTA_uchar(); - } - -} diff --git a/panda/src/gobj/pixelBuffer.h b/panda/src/gobj/pixelBuffer.h deleted file mode 100644 index 8b6feb4830..0000000000 --- a/panda/src/gobj/pixelBuffer.h +++ /dev/null @@ -1,172 +0,0 @@ -// Filename: pixelBuffer.h -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, 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 PIXELBUFFER_H -#define PIXELBUFFER_H - -#include "pandabase.h" - -#include "imageBuffer.h" - -#include "pnmImage.h" -#include "graphicsStateGuardianBase.h" -#include "pta_uchar.h" - -class RenderBuffer; -class Filename; - -//////////////////////////////////////////////////////////////////// -// Class : PixelBuffer -// Description : Maintains an array of pixel data corresponding to an -// image, e.g. copied from the frame buffer, or as part -// of a Texture. -// -// Pixel data is stored in a generic, uncompressed -// format. Each row of pixels is laid out horizontally, -// from the top to the bottom, with no padding between -// rows. Each pixel consumes one or more bytes, -// according to get_component_width(). If the Format -// indicates multiple components are present, they are -// stored in the order B, G, R, A. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA PixelBuffer : public ImageBuffer { -public: - enum Type { - T_unsigned_byte, - T_unsigned_short, - T_unsigned_byte_332, - T_float, - }; - - enum Format { - F_color_index, - F_stencil_index, - F_depth_component, - F_red, - F_green, - F_blue, - F_alpha, - F_rgb, // any suitable RGB mode, whatever the hardware prefers - F_rgb5, // specifically, 5 bits per R,G,B channel. - // this is paired with T_unsigned_byte. really T_unsigned_byte - // should not be specified for this one, it should use - // T_unsigned_5bits or something - F_rgb8, // 8 bits per R,G,B channel - F_rgb12, // 12 bits per R,G,B channel - F_rgb332, // 3 bits per R & G, 2 bits for B - F_rgba, // any suitable RGBA mode, whatever the hardware prefers - F_rgbm, // as above, but only requires 1 bit for alpha (i.e. mask) - F_rgba4, // 4 bits per R,G,B,A channel - F_rgba5, // 5 bits per R,G,B channel, 1 bit alpha - F_rgba8, // 8 bits per R,G,B,A channel - F_rgba12, // 12 bits per R,G,B,A channel - F_luminance, - F_luminance_alpha, // 8 bits luminance, 8 bits alpha - F_luminance_alphamask // 8 bits luminance, only needs 1 bit of alpha - }; - - PixelBuffer(void); - PixelBuffer(int xsize, int ysize, int components, - int component_width, Type type, Format format, - bool allocate_ram = true); - PixelBuffer(const PixelBuffer ©); - void operator = (const PixelBuffer ©); - - // Some named constructors for common PixelBuffer types. - INLINE static PixelBuffer rgb_buffer(int xsize, int ysize); - INLINE static PixelBuffer rgba_buffer(int xsize, int ysize); - INLINE static PixelBuffer depth_buffer(int xsize, int ysize); - INLINE static PixelBuffer stencil_buffer(int xsize, int ysize); - - INLINE ~PixelBuffer(void); - - virtual void config( void ); - - bool read(const Filename &name); - bool write(const Filename &name) const; - - bool load( const PNMImage& pnmimage ); - bool store( PNMImage& pnmimage ) const; - - void copy(const PixelBuffer *pb); - - INLINE void set_xsize(int size); - INLINE void set_ysize(int size); - INLINE void set_num_components(int num_components); - INLINE void set_component_width(int component_width); - INLINE void set_format(Format format); - INLINE void set_image_type(Type type); - INLINE void set_loaded(); - - INLINE int get_xsize() const; - INLINE int get_ysize() const; - INLINE int get_num_components() const; - INLINE int get_component_width() const; - INLINE Format get_format() const; - INLINE Type get_image_type() const; - - INLINE void set_uchar_rgb_texel(const uchar color[3], - int x, int y, int width); - -private: - INLINE void store_unscaled_byte(int &index, int value); - INLINE void store_unscaled_short(int &index, int value); - INLINE void store_scaled_byte(int &index, int value, double scale); - INLINE void store_scaled_short(int &index, int value, double scale); - INLINE double get_unsigned_byte(int &index) const; - INLINE double get_unsigned_short(int &index) const; - -public: - - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ImageBuffer::init_type(); - register_type(_type_handle, "PixelBuffer", - ImageBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - - static TypeHandle _type_handle; - - //////////////////////////////////////////////////////////////////// - -protected: - int _xsize; - int _ysize; - int _num_components; - int _component_width; - Format _format; - Type _type; - - bool _loaded; - -public: - // This is public to allow direct manipulation of the image data. - // Know what you are doing! - PTA_uchar _image; -}; - -#include "pixelBuffer.I" - -#endif diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 5046fbe604..e5688b38aa 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -18,29 +18,336 @@ //////////////////////////////////////////////////////////////////// -// Function: Texture::get_wrapu +// Function: Texture::setup_1d_texture // Access: Published -// Description: +// Description: Sets the texture as an empty 1-d texture with no +// dimensions. Follow up with read() or load() to fill +// the texture properties and image data. //////////////////////////////////////////////////////////////////// -INLINE Texture::WrapMode Texture:: -get_wrapu() const { - return _wrapu; +INLINE void Texture:: +setup_1d_texture() { + setup_1d_texture(0, T_unsigned_byte, F_rgb); } //////////////////////////////////////////////////////////////////// -// Function: Texture::get_wrapv +// Function: Texture::setup_1d_texture // Access: Published -// Description: +// Description: Sets the texture as an empty 1-d texture with the +// specified dimensions and properties. Follow up with +// set_ram_image() or modify_ram_image() to fill the +// image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_1d_texture(int x_size, ComponentType component_type, Format format) { + setup_texture(TT_1d_texture, x_size, 1, 1, component_type, format); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_2d_texture +// Access: Published +// Description: Sets the texture as an empty 2-d texture with no +// dimensions. Follow up with read() or load() to fill +// the texture properties and image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_2d_texture() { + setup_2d_texture(0, 1, T_unsigned_byte, F_rgb); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_2d_texture +// Access: Published +// Description: Sets the texture as an empty 2-d texture with the +// specified dimensions and properties. Follow up with +// set_ram_image() or modify_ram_image() to fill the +// image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_2d_texture(int x_size, int y_size, ComponentType component_type, + Format format) { + setup_texture(TT_2d_texture, x_size, y_size, 1, component_type, format); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_3d_texture +// Access: Published +// Description: Sets the texture as an empty 3-d texture with no +// dimensions (though if you know the depth ahead +// of time, it saves a bit of reallocation later). +// Follow up with read() or load() to fill the texture +// properties and image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_3d_texture(int z_size) { + setup_3d_texture(0, 1, z_size, T_unsigned_byte, F_rgb); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_3d_texture +// Access: Published +// Description: Sets the texture as an empty 3-d texture with the +// specified dimensions and properties. Follow up with +// set_ram_image() or modify_ram_image() to fill the +// image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_3d_texture(int x_size, int y_size, int z_size, + ComponentType component_type, Format format) { + setup_texture(TT_3d_texture, x_size, y_size, z_size, component_type, format); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_cube_map +// Access: Published +// Description: Sets the texture as an empty cube map texture with no +// dimensions. Follow up with read() or load() to fill +// the texture properties and image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_cube_map() { + setup_cube_map(0, 1, T_unsigned_byte, F_rgb); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_cube_map +// Access: Published +// Description: Sets the texture as an empty cube map texture with +// the specified dimensions and properties. Follow up +// with set_ram_image() or modify_ram_image() to fill +// the image data. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +setup_cube_map(int x_size, int y_size, ComponentType component_type, + Format format) { + setup_texture(TT_cube_map, x_size, y_size, 6, component_type, format); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_filename +// Access: Published +// Description: Returns true if the filename has been set and +// is available. See set_filename(). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +has_filename() const { + return !_filename.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_filename +// Access: Published +// Description: Returns the filename that has been set. This is the +// name of the file as it was requested. Also see +// get_fullpath(). +//////////////////////////////////////////////////////////////////// +INLINE const Filename &Texture:: +get_filename() const { + return _filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_alpha_filename +// Access: Published +// Description: Returns true if the alpha_filename has been set and +// is available. See set_alpha_filename(). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +has_alpha_filename() const { + return !_alpha_filename.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_alpha_filename +// Access: Published +// Description: Returns the alpha_filename that has been set. If +// this is set, it represents the name of the alpha +// component, which is stored in a separate file. See +// also get_filename(), and get_alpha_fullpath(). +//////////////////////////////////////////////////////////////////// +INLINE const Filename &Texture:: +get_alpha_filename() const { + return _alpha_filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_fullpath +// Access: Published +// Description: Returns true if the fullpath has been set and +// is available. See set_fullpath(). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +has_fullpath() const { + return !_fullpath.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_fullpath +// Access: Published +// Description: Returns the fullpath that has been set. This is the +// full path to the file as it was found along the +// texture search path. +//////////////////////////////////////////////////////////////////// +INLINE const Filename &Texture:: +get_fullpath() const { + return _fullpath; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_alpha_fullpath +// Access: Published +// Description: Returns true if the alpha_fullpath has been set and +// is available. See set_alpha_fullpath(). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +has_alpha_fullpath() const { + return !_alpha_fullpath.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_alpha_fullpath +// Access: Published +// Description: +// Returns the alpha_fullpath that has been set. This +// is the full path to the alpha part of the image file +// as it was found along the texture search path. +//////////////////////////////////////////////////////////////////// +INLINE const Filename &Texture:: +get_alpha_fullpath() const { + return _alpha_fullpath; +} + + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_x_size +// Access: Published +// Description: Returns the width of the texture image in texels. +//////////////////////////////////////////////////////////////////// +INLINE int Texture:: +get_x_size() const { + return _x_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_y_size +// Access: Published +// Description: Returns the height of the texture image in texels. +// For a 1-d texture, this will be 1. +//////////////////////////////////////////////////////////////////// +INLINE int Texture:: +get_y_size() const { + return _y_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_z_size +// Access: Published +// Description: Returns the depth of the texture image in texels. +// For a 1-d texture or 2-d texture, this will be 1. +// For a cube map texture, this will be 6. +//////////////////////////////////////////////////////////////////// +INLINE int Texture:: +get_z_size() const { + return _z_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_num_components +// Access: Published +// Description: Returns the number of color components for each texel +// of the texture image. This is 3 for an rgb texture +// or 4 for an rgba texture; it may also be 1 or 2 for a +// grayscale texture. +//////////////////////////////////////////////////////////////////// +INLINE int Texture:: +get_num_components() const { + return _num_components; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_component_width +// Access: Published +// Description: Returns the number of bytes stored for each color +// component of a texel. Typically this is 1, but it +// may be 2 for 16-bit texels. +//////////////////////////////////////////////////////////////////// +INLINE int Texture:: +get_component_width() const { + return _component_width; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_texture_type +// Access: Published +// Description: Returns the overall interpretation of the texture. +//////////////////////////////////////////////////////////////////// +INLINE Texture::TextureType Texture:: +get_texture_type() const { + return _texture_type; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_format +// Access: Published +// Description: Returns the format of the texture, which represents +// both the semantic meaning of the texels and, to some +// extent, their storage information. +//////////////////////////////////////////////////////////////////// +INLINE Texture::Format Texture:: +get_format() const { + return _format; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_component_type +// Access: Published +// Description: Returns the numeric interpretation of each component +// of the texture. +//////////////////////////////////////////////////////////////////// +INLINE Texture::ComponentType Texture:: +get_component_type() const { + return _component_type; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_wrap_u +// Access: Published +// Description: Returns the wrap mode of the texture in the U +// direction. //////////////////////////////////////////////////////////////////// INLINE Texture::WrapMode Texture:: -get_wrapv() const { - return _wrapv; +get_wrap_u() const { + return _wrap_u; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_wrap_v +// Access: Published +// Description: Returns the wrap mode of the texture in the V +// direction. +//////////////////////////////////////////////////////////////////// +INLINE Texture::WrapMode Texture:: +get_wrap_v() const { + return _wrap_v; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_wrap_w +// Access: Published +// Description: Returns the wrap mode of the texture in the W +// direction. This is the depth direction of 3-d +// textures. +//////////////////////////////////////////////////////////////////// +INLINE Texture::WrapMode Texture:: +get_wrap_w() const { + return _wrap_w; } //////////////////////////////////////////////////////////////////// // Function: Texture::get_minfilter // Access: Published -// Description: +// Description: Returns the filter mode of the texture for +// minification. If this is one of the mipmap +// constants, then the texture requires mipmaps. //////////////////////////////////////////////////////////////////// INLINE Texture::FilterType Texture:: get_minfilter() const { @@ -50,7 +357,9 @@ get_minfilter() const { //////////////////////////////////////////////////////////////////// // Function: Texture::get_magfilter // Access: Published -// Description: +// Description: Returns the filter mode of the texture for +// magnification. The mipmap constants are invalid +// here. //////////////////////////////////////////////////////////////////// INLINE Texture::FilterType Texture:: get_magfilter() const { @@ -75,28 +384,21 @@ get_anisotropic_degree() const { //////////////////////////////////////////////////////////////////// // Function: Texture::get_border_color // Access: Published -// Description: +// Description: Returns the solid color of the texture's border. +// Some OpenGL implementations use a border for tiling +// textures; in Panda, it is only used for specifying +// the clamp color. //////////////////////////////////////////////////////////////////// INLINE Colorf Texture:: get_border_color() const { return _border_color; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::get_border_width -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int Texture:: -get_border_width() const { - return _border_width; -} - //////////////////////////////////////////////////////////////////// // Function: Texture::uses_mipmaps // Access: Public // Description: Returns true if the minfilter settings on this -// texture require the use of mipmapping, false +// texture indicate the use of mipmapping, false // otherwise. //////////////////////////////////////////////////////////////////// INLINE bool Texture:: @@ -104,24 +406,9 @@ uses_mipmaps() const { return is_mipmap(get_minfilter()); } -//////////////////////////////////////////////////////////////////// -// Function: Texture::get_match_framebuffer_format -// Access: Published -// Description: Returns true if the Texture was created with a -// special flag that indicates to the GSG that the -// Texture's format should be chosen to exactly match -// the framebuffer's format, presumably because the -// application intends to copy image data from the -// framebuffer into the Texture (or vice-versa). -//////////////////////////////////////////////////////////////////// -INLINE bool Texture:: -get_match_framebuffer_format() const { - return _match_framebuffer_format; -} - //////////////////////////////////////////////////////////////////// // Function: Texture::has_ram_image -// Access: Public +// Access: Published // Description: Returns true if the Texture has its image contents // available in main RAM, false if it exists only in // texture memory or in the prepared GSG context. @@ -149,12 +436,48 @@ get_match_framebuffer_format() const { //////////////////////////////////////////////////////////////////// INLINE bool Texture:: has_ram_image() const { - return !_pbuffer->_image.empty(); + return !_image.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_ram_image_size +// Access: Published +// Description: Returns the number of bytes used by the in-memory +// image, or 0 if there is no in-memory image. +//////////////////////////////////////////////////////////////////// +INLINE size_t Texture:: +get_ram_image_size() const { + return _image.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_expected_ram_image_size +// Access: Published +// Description: Returns the number of bytes that *ought* to be used +// by the in-memory image, based on the texture +// parameters. +//////////////////////////////////////////////////////////////////// +INLINE size_t Texture:: +get_expected_ram_image_size() const { + return get_expected_ram_page_size() * (size_t)_z_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_expected_ram_page_size +// Access: Published +// Description: Returns the number of bytes that should be used per +// each Z page of the 3-d texture. For a 2-d or 1-d +// texture, this is the same as +// get_expected_ram_image_size(). +//////////////////////////////////////////////////////////////////// +INLINE size_t Texture:: +get_expected_ram_page_size() const { + return (size_t)(_x_size * _y_size * _num_components * _component_width); } //////////////////////////////////////////////////////////////////// // Function: Texture::might_have_ram_image -// Access: Public +// Access: Published // Description: Returns true if the texture's image contents are // currently available in main RAM, or there is reason // to believe it can be loaded on demand. That is, this @@ -169,7 +492,7 @@ might_have_ram_image() const { //////////////////////////////////////////////////////////////////// // Function: Texture::set_keep_ram_image -// Access: Public +// Access: Published // Description: Sets the flag that indicates whether this Texture is // eligible to have its main RAM copy of the texture // memory dumped when the texture is prepared for @@ -179,8 +502,8 @@ might_have_ram_image() const { // their images if needed by rereading the input file. // However, textures that were generated dynamically and // cannot be easily reloaded will want to set this flag -// to true, so that the _pbuffer member will always keep -// its image copy around. +// to true, so that the texture will always keep its +// image copy around. //////////////////////////////////////////////////////////////////// INLINE void Texture:: set_keep_ram_image(bool keep_ram_image) { @@ -189,7 +512,7 @@ set_keep_ram_image(bool keep_ram_image) { //////////////////////////////////////////////////////////////////// // Function: Texture::get_keep_ram_image -// Access: Public +// Access: Published // Description: Returns the flag that indicates whether this Texture // is eligible to have its main RAM copy of the texture // memory dumped when the texture is prepared for @@ -200,4 +523,305 @@ get_keep_ram_image() const { return _keep_ram_image; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_filename +// Access: Public +// Description: Sets the name of the file that contains the image's +// contents. Normally, this is set automatically when +// the image is loaded, for instance via +// Texture::read(). +// +// The Texture's get_name() function used to return +// the filename, but now returns just the basename +// (without the extension), which is a more useful name +// for identifying an image in show code. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_filename(const Filename &filename) { + _filename = filename; +} +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_filename +// Access: Public +// Description: Removes the alpha filename, if it was previously set. +// See set_filename(). +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +clear_filename() { + _filename = Filename(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_alpha_filename +// Access: Public +// Description: Sets the name of the file that contains the image's +// alpha channel contents. Normally, this is set +// automatically when the image is loaded, for instance +// via Texture::read(). +// +// The Texture's get_filename() function returns the +// name of the image file that was loaded into the +// buffer. In the case where a texture specified two +// separate files to load, a 1- or 3-channel color image +// and a 1-channel alpha image, this Filename is update +// to contain the name of the image file that was loaded +// into the buffer's alpha channel. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_alpha_filename(const Filename &alpha_filename) { + _alpha_filename = alpha_filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_alpha_filename +// Access: Public +// Description: Removes the alpha filename, if it was previously set. +// See set_alpha_filename(). +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +clear_alpha_filename() { + _alpha_filename = Filename(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_fullpath +// Access: Public +// Description: Sets the full pathname to the file that contains the +// image's contents, as found along the search path. +// Normally, this is set automatically when the image is +// loaded, for instance via Texture::read(). +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_fullpath(const Filename &fullpath) { + _fullpath = fullpath; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_fullpath +// Access: Public +// Description: Removes the alpha fullpath, if it was previously set. +// See set_fullpath(). +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +clear_fullpath() { + _fullpath = Filename(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_alpha_fullpath +// Access: Public +// Description: Sets the full pathname to the file that contains the +// image's alpha channel contents, as found along the +// search path. Normally, this is set automatically +// when the image is loaded, for instance via +// Texture::read(). +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_alpha_fullpath(const Filename &alpha_fullpath) { + _alpha_fullpath = alpha_fullpath; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_alpha_fullpath +// Access: Public +// Description: Removes the alpha fullpath, if it was previously set. +// See set_alpha_fullpath(). +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +clear_alpha_fullpath() { + _alpha_fullpath = Filename(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_x_size +// Access: Public +// Description: Changes the x size indicated for the texture. This +// also implicitly unloads the texture if it has already +// been loaded. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_x_size(int x_size) { + if (_x_size != x_size) { + _x_size = x_size; + clear_ram_image(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_y_size +// Access: Public +// Description: Changes the y size indicated for the texture. This +// also implicitly unloads the texture if it has already +// been loaded. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_y_size(int y_size) { + if (_y_size != y_size) { + nassertv(_texture_type != Texture::TT_1d_texture); + _y_size = y_size; + clear_ram_image(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_z_size +// Access: Public +// Description: Changes the z size indicated for the texture. This +// also implicitly unloads the texture if it has already +// been loaded. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_z_size(int z_size) { + if (_z_size != z_size) { + nassertv(_texture_type == Texture::TT_3d_texture); + _z_size = z_size; + clear_ram_image(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_loaded_from_disk +// Access: Public +// Description: Sets the flag that indicates the texture has been +// loaded from a disk file. You should also ensure the +// filename has been set correctly. When this flag is +// true, the texture may be automatically reloaded when +// its ram image needs to be replaced. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_loaded_from_disk() { + _loaded_from_disk = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_match_framebuffer_format +// Access: Public +// Description: Returns true if the special flag was set that +// indicates to the GSG that the Texture's format should +// be chosen to exactly match the framebuffer's format, +// presumably because the application intends to copy +// image data from the framebuffer into the Texture (or +// vice-versa). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +get_match_framebuffer_format() const { + return _match_framebuffer_format; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_match_framebuffer_format +// Access: Public +// Description: Sets the special flag that, if true, indicates to the +// GSG that the Texture's format should be chosen to +// exactly match the framebuffer's format, presumably +// because the application intends to copy image data +// from the framebuffer into the Texture (or +// vice-versa). +// +// This sets only the graphics card's idea of the +// texture format; it is not related to the +// system-memory format. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +set_match_framebuffer_format(bool flag) { + _match_framebuffer_format = flag; +} + + + +//////////////////////////////////////////////////////////////////// +// Function: Texture::store_unscaled_byte +// Access: Private +// Description: This is used by load() to store the next consecutive +// component value into the indicated element of the +// array, which is taken to be an array of unsigned +// bytes. The value is assumed to be in the range +// 0-255. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +store_unscaled_byte(int &index, int value) { + _image[index++] = (uchar)value; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::store_unscaled_short +// Access: Private +// Description: This is used by load() to store the next consecutive +// component value into the indicated element of the +// array, which is taken to be an array of unsigned +// shorts. The value is assumed to be in the range +// 0-65535. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +store_unscaled_short(int &index, int value) { + union { + ushort us; + uchar uc[2]; + } v; + v.us = (ushort)value; + _image[index++] = v.uc[0]; + _image[index++] = v.uc[1]; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::store_scaled_byte +// Access: Private +// Description: This is used by load() to store the next consecutive +// component value into the indicated element of the +// array, which is taken to be an array of unsigned +// bytes. The value will be scaled by the indicated +// factor before storing it. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +store_scaled_byte(int &index, int value, double scale) { + store_unscaled_byte(index, (int)(value * scale)); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::store_scaled_short +// Access: Private +// Description: This is used by load() to store the next consecutive +// component value into the indicated element of the +// array, which is taken to be an array of unsigned +// shorts. The value will be scaled by the indicated +// factor before storing it. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +store_scaled_short(int &index, int value, double scale) { + store_unscaled_short(index, (int)(value * scale)); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_unsigned_byte +// Access: Private +// Description: This is used by store() to retieve the next +// consecutive component value from the indicated +// element of the array, which is taken to be an array +// of unsigned bytes. +//////////////////////////////////////////////////////////////////// +INLINE double Texture:: +get_unsigned_byte(int &index) const { + nassertr(index >= 0 && index < (int)_image.size(), 0.0); + return (double)_image[index++] / 255.0; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_unsigned_short +// Access: Private +// Description: This is used by store() to retieve the next +// consecutive component value from the indicated +// element of the array, which is taken to be an array +// of unsigned shorts. +//////////////////////////////////////////////////////////////////// +INLINE double Texture:: +get_unsigned_short(int &index) const { + nassertr(index >= 0 && index+1 < (int)_image.size(), 0.0); + union { + ushort us; + uchar uc[2]; + } v; + v.uc[0] = _image[index++]; + v.uc[1] = _image[index++]; + return (double)v.us / 65535.0; +} diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 8ce0994533..1b34c53662 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -27,173 +27,46 @@ #include "bamWriter.h" #include "string_utils.h" #include "preparedGraphicsObjects.h" +#include "pnmImage.h" #include TypeHandle Texture::_type_handle; -//////////////////////////////////////////////////////////////////// -// Function: up_to_power_2 -// Description: Returns the smallest power of 2 greater than or equal -// to value. -//////////////////////////////////////////////////////////////////// -static int -up_to_power_2(int value) { - int x = 1; - while (x < value) { - x = (x << 1); - } - return x; -} - -//////////////////////////////////////////////////////////////////// -// Function: down_to_power_2 -// Description: Returns the largest power of 2 less than or equal -// to value. -//////////////////////////////////////////////////////////////////// -static int -down_to_power_2(int value) { - int x = 1; - while ((x << 1) <= value) { - x = (x << 1); - } - return x; -} - -//////////////////////////////////////////////////////////////////// -// Function: consider_rescale -// Description: Scales the PNMImage according to the whims of the -// Configrc file. -//////////////////////////////////////////////////////////////////// -static void -consider_rescale(PNMImage &pnmimage, const string &name) { - int new_x_size = pnmimage.get_x_size(); - int new_y_size = pnmimage.get_y_size(); - - switch (textures_power_2) { - case ATS_down: - new_x_size = down_to_power_2(new_x_size); - new_y_size = down_to_power_2(new_y_size); - break; - - case ATS_up: - new_x_size = up_to_power_2(new_x_size); - new_y_size = up_to_power_2(new_y_size); - break; - - case ATS_none: - break; - } - - switch (textures_square) { - case ATS_down: - new_x_size = new_y_size = min(new_x_size, new_y_size); - break; - - case ATS_up: - new_x_size = new_y_size = max(new_x_size, new_y_size); - break; - - case ATS_none: - break; - } - - if (max_texture_dimension > 0) { - new_x_size = min(new_x_size, (int)max_texture_dimension); - new_y_size = min(new_y_size, (int)max_texture_dimension); - } - - if (pnmimage.get_x_size() != new_x_size || - pnmimage.get_y_size() != new_y_size) { - gobj_cat.info() - << "Automatically rescaling " << name << " from " - << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << " to " - << new_x_size << " by " << new_y_size << "\n"; - - PNMImage scaled(new_x_size, new_y_size, pnmimage.get_num_channels(), - pnmimage.get_maxval(), pnmimage.get_type()); - scaled.quick_filter_from(pnmimage); - pnmimage = scaled; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: consider_downgrade -// Description: Reduces the number of channels in the texture, if -// necessary, according to num_channels. -//////////////////////////////////////////////////////////////////// -static void -consider_downgrade(PNMImage &pnmimage, int num_channels, - const string &name) { - if (num_channels != 0 && num_channels < pnmimage.get_num_channels()) { - // One special case: we can't reduce from 3 to 2 components, since - // that would require adding an alpha channel. - if (pnmimage.get_num_channels() == 3 && num_channels == 2) { - return; - } - - gobj_cat.info() - << "Downgrading " << name << " from " << pnmimage.get_num_channels() - << " components to " << num_channels << ".\n"; - pnmimage.set_num_channels(num_channels); - } -} - //////////////////////////////////////////////////////////////////// // Function: Texture::Constructor // Access: Published -// Description: +// Description: Constructs an empty texture. The default is to set +// up the texture as an empty 2-d texture; follow up +// with one of the variants of setup_texture() if this +// is not what you want. //////////////////////////////////////////////////////////////////// Texture:: -Texture(bool match_framebuffer_format) { +Texture(const string &name) : + Namable(name) +{ + _primary_file_num_channels = 0; + _alpha_file_channel = 0; _magfilter = FT_linear; _minfilter = FT_linear; - _wrapu = WM_repeat; - _wrapv = WM_repeat; + _wrap_u = WM_repeat; + _wrap_v = WM_repeat; + _wrap_w = WM_repeat; _anisotropic_degree = 1; - _keep_ram_image = false; - _pbuffer = new PixelBuffer; + _keep_ram_image = true; _all_dirty_flags = 0; _border_color.set(0.0f, 0.0f, 0.0f, 1.0f); - _border_width = 0; - _match_framebuffer_format = match_framebuffer_format; - - if (_match_framebuffer_format) { - // If this flag is true, it indicates to the GSG that the texture - // will be created in a format consistent with the framebuffer - // (presumably to allow copying from the framebuffer), regardless - // of the pbuffer format. - - // Make up a default format for the pbuffer. - _pbuffer->set_format(PixelBuffer::F_rgba8); - _pbuffer->set_num_components(4); - _pbuffer->set_component_width(1); - _pbuffer->set_image_type(PixelBuffer::T_unsigned_byte); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: Texture::Constructor -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -Texture:: -Texture(int xsize, int ysize, int components, int component_width, - PixelBuffer::Type type, PixelBuffer::Format format, - bool allocate_ram) { - _magfilter = FT_linear; - _minfilter = FT_linear; - _wrapu = WM_repeat; - _wrapv = WM_repeat; - _anisotropic_degree = 1; - _keep_ram_image = allocate_ram; - _pbuffer = new PixelBuffer(xsize, ysize, components, component_width, - type, format, allocate_ram); - _all_dirty_flags = 0; - _border_color.set(0.0f, 0.0f, 0.0f, 1.0f); - _border_width = 0; _match_framebuffer_format = false; + + _texture_type = TT_2d_texture; + _x_size = 0; + _y_size = 1; + _z_size = 1; + set_format(F_rgb); + set_component_type(T_unsigned_byte); + + _loaded_from_disk = false; } //////////////////////////////////////////////////////////////////// @@ -206,6 +79,32 @@ Texture:: release_all(); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::setup_texture +// Access: Published +// Description: Sets the texture to the indicated type and +// dimensions, presumably in preparation for calling +// read() or load(), or set_ram_image() or +// modify_ram_image(). +//////////////////////////////////////////////////////////////////// +void Texture:: +setup_texture(Texture::TextureType texture_type, int x_size, int y_size, + int z_size, Texture::ComponentType component_type, + Texture::Format format) { + _texture_type = texture_type; + _x_size = x_size; + _y_size = y_size; + _z_size = z_size; + if (_texture_type == TT_cube_map) { + _z_size = 6; + } + set_component_type(component_type); + set_format(format); + + clear_ram_image(); + _loaded_from_disk = false; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::read // Access: Published @@ -213,9 +112,11 @@ Texture:: // num_channels is not 0, it specifies the number of // components to downgrade the image to if it is greater // than this number. +// +// This also implicitly sets keep_ram_image to false. //////////////////////////////////////////////////////////////////// bool Texture:: -read(const Filename &fullpath, int primary_file_num_channels) { +read(const Filename &fullpath, int z, int primary_file_num_channels) { PNMImage image; if (!image.read(fullpath)) { @@ -236,13 +137,13 @@ read(const Filename &fullpath, int primary_file_num_channels) { clear_alpha_fullpath(); // Check to see if we need to scale it. - consider_rescale(image, get_name()); - consider_downgrade(image, primary_file_num_channels, get_name()); + consider_rescale(image); + consider_downgrade(image, primary_file_num_channels); _primary_file_num_channels = image.get_num_channels(); _alpha_file_channel = 0; - return load(image); + return load(image, z); } //////////////////////////////////////////////////////////////////// @@ -250,10 +151,12 @@ read(const Filename &fullpath, int primary_file_num_channels) { // Access: Published // Description: Combine a 3-component image with a grayscale image // to get a 4-component image +// +// This also implicitly sets keep_ram_image to false. //////////////////////////////////////////////////////////////////// bool Texture:: read(const Filename &fullpath, const Filename &alpha_fullpath, - int primary_file_num_channels, int alpha_file_channel) { + int z, int primary_file_num_channels, int alpha_file_channel) { PNMImage image; if (!image.read(fullpath)) { gobj_cat.error() @@ -279,7 +182,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath, set_fullpath(fullpath); set_alpha_fullpath(alpha_fullpath); - consider_rescale(image, get_name()); + consider_rescale(image); // The grayscale (alpha channel) image must be the same size as the // main image. @@ -298,7 +201,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath, alpha_image = scaled; } - consider_downgrade(image, primary_file_num_channels, get_name()); + consider_downgrade(image, primary_file_num_channels); _primary_file_num_channels = image.get_num_channels(); @@ -336,7 +239,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath, _alpha_file_channel = 0; } - return load(image); + return load(image, z); } //////////////////////////////////////////////////////////////////// @@ -345,10 +248,10 @@ read(const Filename &fullpath, const Filename &alpha_fullpath, // Description: Writes the texture to the indicated filename. //////////////////////////////////////////////////////////////////// bool Texture:: -write(const Filename &name) const { +write(const Filename &name, int z) const { nassertr(has_ram_image(), false); PNMImage pnmimage; - if (!_pbuffer->store(pnmimage)) { + if (!store(pnmimage, z)) { return false; } @@ -363,12 +266,202 @@ write(const Filename &name) const { //////////////////////////////////////////////////////////////////// // Function: Texture::load // Access: Published -// Description: Creates the texture from the already-read PNMImage. +// Description: Fills the texture system RAM data from the +// already-read PNMImage. +// +// For a 3-d texture or a cube map, this must be called +// multiple times, one for each page (z value). Cube +// maps have exactly 6 pages, while 3-d textures can +// have any number and can dynamically grow as each page +// is loaded. For the first page loaded (or when +// reloading z == 0), this also sets the texture +// parameters; for subsequent pages, the texture +// parameters must match those which were loaded +// previously. +// +// This also implicitly sets keep_ram_image to false if +// a filename has been set, or true if one has not been +// set. //////////////////////////////////////////////////////////////////// bool Texture:: -load(const PNMImage &pnmimage) { - if (!_pbuffer->load(pnmimage)) - return false; +load(const PNMImage &pnmimage, int z) { + if (z >= _z_size) { + // If we're loading a page past _z_size, treat it as an implicit + // request to enlarge _z_size. However, this is only legal if + // this is, in fact, a 3-d texture (cube maps always have z_size + // 6, and other types have z_size 1). + nassertr(_texture_type == Texture::TT_3d_texture, false); + + _z_size = z + 1; + // Increase the size of the data buffer to make room for the new + // texture level. + size_t new_size = get_expected_ram_image_size(); + if (!_image.is_null() && new_size > _image.size()) { + _image.insert(_image.end(), new_size - _image.size(), 0); + nassertr(_image.size() == new_size, false); + } + } + + nassertr(z >= 0 && z < _z_size, false); + + int num_components = pnmimage.get_num_channels(); + ComponentType component_type = T_unsigned_byte; + + xelval maxval = pnmimage.get_maxval(); + if (maxval > 255) { + component_type = T_unsigned_short; + } + + if (!_loaded_from_disk || num_components != _num_components) { + // Come up with a default format based on the number of channels. + // But only do this the first time the file is loaded, or if the + // number of channels in the image changes on subsequent loads. + + switch (pnmimage.get_color_type()) { + case PNMImage::CT_grayscale: + _format = F_luminance; + break; + + case PNMImage::CT_two_channel: + _format = F_luminance_alpha; + break; + + case PNMImage::CT_color: + _format = F_rgb; + break; + + case PNMImage::CT_four_channel: + _format = F_rgba; + break; + + default: + // Eh? + nassertr(false, false); + _format = F_rgb; + }; + } + + if (!_loaded_from_disk || z == 0) { + if (_texture_type == TT_1d_texture) { + nassertr(pnmimage.get_y_size() == 1, false); + } + _x_size = pnmimage.get_x_size(); + _y_size = pnmimage.get_y_size(); + _num_components = num_components; + set_component_type(component_type); + + } else { + if (_x_size != pnmimage.get_x_size() || + _y_size != pnmimage.get_y_size() || + _component_type != component_type) { + gobj_cat.error() + << "Texture properties have changed for texture " << get_name() + << " level " << z << ".\n"; + return false; + } + } + + _loaded_from_disk = true; + modify_ram_image(); + _keep_ram_image = !has_filename(); + + // Now copy the pixel data from the PNMImage into our internal + // _image component. + bool has_alpha = pnmimage.has_alpha(); + bool is_grayscale = pnmimage.is_grayscale(); + + if (maxval == 255) { + // Most common case: one byte per pixel, and the source image + // shows a maxval of 255. No scaling is necessary. + int idx = get_expected_ram_page_size() * z; + + for (int j = _y_size-1; j >= 0; j--) { + for (int i = 0; i < _x_size; i++) { + if (is_grayscale) { + store_unscaled_byte(idx, pnmimage.get_gray_val(i, j)); + } else { + store_unscaled_byte(idx, pnmimage.get_blue_val(i, j)); + store_unscaled_byte(idx, pnmimage.get_green_val(i, j)); + store_unscaled_byte(idx, pnmimage.get_red_val(i, j)); + } + if (has_alpha) { + store_unscaled_byte(idx, pnmimage.get_alpha_val(i, j)); + } + } + } + + nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false); + + } else if (maxval == 65535) { + // Another possible case: two bytes per pixel, and the source + // image shows a maxval of 65535. Again, no scaling is necessary. + int idx = get_expected_ram_page_size() * z; + + for (int j = _y_size-1; j >= 0; j--) { + for (int i = 0; i < _x_size; i++) { + if (is_grayscale) { + store_unscaled_short(idx, pnmimage.get_gray_val(i, j)); + } else { + store_unscaled_short(idx, pnmimage.get_blue_val(i, j)); + store_unscaled_short(idx, pnmimage.get_green_val(i, j)); + store_unscaled_short(idx, pnmimage.get_red_val(i, j)); + } + if (has_alpha) { + store_unscaled_short(idx, pnmimage.get_alpha_val(i, j)); + } + } + } + + nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false); + + } else if (maxval <= 255) { + // A less common case: one byte per pixel, but the maxval is + // something other than 255. In this case, we should scale the + // pixel values up to the appropriate amount. + int idx = get_expected_ram_page_size() * z; + double scale = 255.0 / (double)maxval; + + for (int j = _y_size-1; j >= 0; j--) { + for (int i = 0; i < _x_size; i++) { + if (is_grayscale) { + store_scaled_byte(idx, pnmimage.get_gray_val(i, j), scale); + } else { + store_scaled_byte(idx, pnmimage.get_blue_val(i, j), scale); + store_scaled_byte(idx, pnmimage.get_green_val(i, j), scale); + store_scaled_byte(idx, pnmimage.get_red_val(i, j), scale); + } + if (has_alpha) { + store_scaled_byte(idx, pnmimage.get_alpha_val(i, j), scale); + } + } + } + + nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false); + + } else { + // Another uncommon case: two bytes per pixel, and the maxval is + // something other than 65535. Again, we must scale the pixel + // values. + int idx = get_expected_ram_page_size() * z; + double scale = 65535.0 / (double)maxval; + + for (int j = _y_size-1; j >= 0; j--) { + for (int i = 0; i < _x_size; i++) { + if (is_grayscale) { + store_scaled_short(idx, pnmimage.get_gray_val(i, j), scale); + } else { + store_scaled_short(idx, pnmimage.get_blue_val(i, j), scale); + store_scaled_short(idx, pnmimage.get_green_val(i, j), scale); + store_scaled_short(idx, pnmimage.get_red_val(i, j), scale); + } + if (has_alpha) { + store_scaled_short(idx, pnmimage.get_alpha_val(i, j), scale); + } + } + } + + nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false); + } mark_dirty(DF_image); @@ -378,37 +471,108 @@ load(const PNMImage &pnmimage) { //////////////////////////////////////////////////////////////////// // Function: Texture::store // Access: Published -// Description: Saves the texture to the indicated PNMImage, but does -// not write it to disk. +// Description: Saves the zth level of the texture to the indicated +// PNMImage, but does not write it to disk. //////////////////////////////////////////////////////////////////// bool Texture:: -store(PNMImage &pnmimage) const { - return _pbuffer->store( pnmimage ); +store(PNMImage &pnmimage, int z) const { + nassertr(z >= 0 && z < _z_size, false); + + if (_component_type == T_unsigned_byte) { + pnmimage.clear(_x_size, _y_size, _num_components); + bool has_alpha = pnmimage.has_alpha(); + bool is_grayscale = pnmimage.is_grayscale(); + + int idx = get_expected_ram_page_size() * z; + + for (int j = _y_size-1; j >= 0; j--) { + for (int i = 0; i < _x_size; i++) { + if (is_grayscale) { + pnmimage.set_gray(i, j, get_unsigned_byte(idx)); + } else { + pnmimage.set_blue(i, j, get_unsigned_byte(idx)); + pnmimage.set_green(i, j, get_unsigned_byte(idx)); + pnmimage.set_red(i, j, get_unsigned_byte(idx)); + } + if (has_alpha) { + pnmimage.set_alpha(i, j, get_unsigned_byte(idx)); + } + } + } + + nassertr(idx == (int)get_expected_ram_image_size(), false); + + return true; + + } else if (_component_type == T_unsigned_short) { + pnmimage.clear(_x_size, _y_size, _num_components, 65535); + bool has_alpha = pnmimage.has_alpha(); + bool is_grayscale = pnmimage.is_grayscale(); + + int idx = get_expected_ram_page_size() * z; + + for (int j = _y_size-1; j >= 0; j--) { + for (int i = 0; i < _x_size; i++) { + if (is_grayscale) { + pnmimage.set_gray(i, j, get_unsigned_short(idx)); + } else { + pnmimage.set_blue(i, j, get_unsigned_short(idx)); + pnmimage.set_green(i, j, get_unsigned_short(idx)); + pnmimage.set_red(i, j, get_unsigned_short(idx)); + } + if (has_alpha) { + pnmimage.set_alpha(i, j, get_unsigned_short(idx)); + } + } + } + + nassertr(idx == (int)get_expected_ram_image_size(), false); + + return true; + } + + gobj_cat.error() + << "Couldn't write image for " << get_name() + << "; inappropriate data type " << (int)_component_type << ".\n"; + return false; } //////////////////////////////////////////////////////////////////// -// Function: Texture::set_wrapu +// Function: Texture::set_wrap_u // Access: Published // Description: //////////////////////////////////////////////////////////////////// void Texture:: -set_wrapu(Texture::WrapMode wrap) { - if (_wrapu != wrap) { +set_wrap_u(Texture::WrapMode wrap) { + if (_wrap_u != wrap) { mark_dirty(DF_wrap); - _wrapu = wrap; + _wrap_u = wrap; } } //////////////////////////////////////////////////////////////////// -// Function: Texture::set_wrapv +// Function: Texture::set_wrap_v // Access: Published // Description: //////////////////////////////////////////////////////////////////// void Texture:: -set_wrapv(Texture::WrapMode wrap) { - if (_wrapv != wrap) { +set_wrap_v(Texture::WrapMode wrap) { + if (_wrap_v != wrap) { mark_dirty(DF_wrap); - _wrapv = wrap; + _wrap_v = wrap; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_wrap_w +// Access: Published +// Description: The W wrap direction is only used for 3-d textures. +//////////////////////////////////////////////////////////////////// +void Texture:: +set_wrap_w(Texture::WrapMode wrap) { + if (_wrap_w != wrap) { + mark_dirty(DF_wrap); + _wrap_w = wrap; } } @@ -462,9 +626,10 @@ set_anisotropic_degree(int anisotropic_degree) { //////////////////////////////////////////////////////////////////// // Function: Texture::set_border_color // Access: Published -// Description: Specifies the uniform color of the texture border, if -// it has one (see set_border_width()), and if the -// border color is not part of the image. +// Description: Specifies the solid color of the texture's border. +// Some OpenGL implementations use a border for tiling +// textures; in Panda, it is only used for specifying +// the clamp color. //////////////////////////////////////////////////////////////////// void Texture:: set_border_color(const Colorf &color) { @@ -475,20 +640,114 @@ set_border_color(const Colorf &color) { } //////////////////////////////////////////////////////////////////// -// Function: Texture::set_border_width +// Function: Texture::get_ram_image // Access: Published -// Description: Specifies the width of the texture border, in pixels. -// Generally, this can be either 0 or 1, and the default -// is 0. This is intended to be used for tiling large -// textures, although it has one or two other -// applications. +// Description: Returns the system-RAM image data associated with the +// texture. If the texture does not currently have an +// associated RAM image, and the texture was generated +// by loading an image from a disk file (the most common +// case), this forces the reload of the same texture. +// This can happen if keep_texture_ram is configured to +// false, and we have previously prepared this texture +// with a GSG. +// +// Note that it is not correct to call has_ram_image() +// first to test whether this function will fail. A +// false return value from has_ram_image() indicates +// only that get_ram_image() may need to reload the +// texture from disk, which it will do automatically. +// However, you can call might_have_ram_image(), which +// will return true if the ram image exists, or there is +// a reasonable reason to believe it can be loaded. +// +// On the other hand, it is possible that the texture +// cannot be found on disk or is otherwise unavailable. +// If that happens, this function will return NULL. +// There is no way to predict with 100% accuracy whether +// get_ram_image() will return NULL without calling it +// first; might_have_ram_image() is the closest. +//////////////////////////////////////////////////////////////////// +CPTA_uchar Texture:: +get_ram_image() { + if (_loaded_from_disk && !has_ram_image() && has_filename() && + (_texture_type == TT_1d_texture || _texture_type == TT_2d_texture)) { + // Now we have to reload the texture image. + gobj_cat.info() + << "Reloading texture " << get_name() << "\n"; + + make_ram_image(); + if (has_alpha_fullpath()) { + read(get_fullpath(), get_alpha_fullpath()); + } else { + read(get_fullpath()); + } + } + + return _image; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::modify_ram_image +// Access: Published +// Description: Returns a modifiable pointer to the system-RAM image. +// If the RAM image has been dumped, creates a new one. +// +// This also implicitly sets keep_ram_image to true. +//////////////////////////////////////////////////////////////////// +PTA_uchar Texture:: +modify_ram_image() { + if (!has_ram_image()) { + make_ram_image(); + } + + mark_dirty(DF_image); + _keep_ram_image = true; + return _image; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::make_ram_image +// Access: Published +// Description: Discards the current system-RAM image for the +// texture, if any, and allocates a new buffer of the +// appropriate size. Returns the new buffer. +// +// This also implicitly sets keep_ram_image to true. +//////////////////////////////////////////////////////////////////// +PTA_uchar Texture:: +make_ram_image() { + _image = PTA_uchar::empty_array(get_expected_ram_image_size()); + mark_dirty(DF_image); + _keep_ram_image = true; + return _image; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_ram_image +// Access: Published +// Description: Replaces the current system-RAM image with the new +// data. +// +// This also implicitly sets keep_ram_image to true. //////////////////////////////////////////////////////////////////// void Texture:: -set_border_width(int width) { - if (_border_width != width) { - mark_dirty(DF_border); - _border_width = width; +set_ram_image(PTA_uchar image) { + nassertv(image.size() == get_expected_ram_image_size()); + if (_image != image) { + _image = image; + mark_dirty(DF_image); } + _keep_ram_image = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_ram_image +// Access: Published +// Description: Discards the current system-RAM image. +//////////////////////////////////////////////////////////////////// +void Texture:: +clear_ram_image() { + _image.clear(); } //////////////////////////////////////////////////////////////////// @@ -508,6 +767,128 @@ prepare(PreparedGraphicsObjects *prepared_objects) { prepared_objects->enqueue_texture(this); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::release +// Access: Published +// Description: Frees the texture context only on the indicated object, +// if it exists there. Returns true if it was released, +// false if it had not been prepared. +//////////////////////////////////////////////////////////////////// +bool Texture:: +release(PreparedGraphicsObjects *prepared_objects) { + Contexts::iterator ci; + ci = _contexts.find(prepared_objects); + if (ci != _contexts.end()) { + TextureContext *tc = (*ci).second; + prepared_objects->release_texture(tc); + return true; + } + + // Maybe it wasn't prepared yet, but it's about to be. + return prepared_objects->dequeue_texture(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::release_all +// Access: Published +// Description: Frees the context allocated on all objects for which +// the texture has been declared. Returns the number of +// contexts which have been freed. +//////////////////////////////////////////////////////////////////// +int Texture:: +release_all() { + // We have to traverse a copy of the _contexts list, because the + // PreparedGraphicsObjects object will call clear_prepared() in response + // to each release_texture(), and we don't want to be modifying the + // _contexts list while we're traversing it. + Contexts temp = _contexts; + int num_freed = (int)_contexts.size(); + + Contexts::const_iterator ci; + for (ci = temp.begin(); ci != temp.end(); ++ci) { + PreparedGraphicsObjects *prepared_objects = (*ci).first; + TextureContext *tc = (*ci).second; + prepared_objects->release_texture(tc); + } + + // Now that we've called release_texture() on every known context, + // the _contexts list should have completely emptied itself. + nassertr(_contexts.empty(), num_freed); + + return num_freed; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_format +// Access: Public +// Description: Changes the format value for the texture components. +// This implicitly sets num_components as well. +//////////////////////////////////////////////////////////////////// +void Texture:: +set_format(Texture::Format format) { + _format = format; + + switch (_format) { + case F_color_index: + case F_stencil_index: + case F_depth_component: + case F_red: + case F_green: + case F_blue: + case F_alpha: + case F_luminance: + _num_components = 1; + break; + + case F_luminance_alpha: + case F_luminance_alphamask: + _num_components = 2; + break; + + case F_rgb: + case F_rgb5: + case F_rgb8: + case F_rgb12: + case F_rgb332: + _num_components = 3; + break; + + case F_rgba: + case F_rgbm: + case F_rgba4: + case F_rgba5: + case F_rgba8: + case F_rgba12: + _num_components = 4; + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::set_component_type +// Access: Public +// Description: Changes the data value for the texture components. +// This implicitly sets component_width as well. +//////////////////////////////////////////////////////////////////// +void Texture:: +set_component_type(Texture::ComponentType component_type) { + _component_type = component_type; + + switch (component_type) { + case T_unsigned_byte: + _component_width = 1; + break; + + case T_unsigned_short: + _component_width = 2; + break; + + case T_float: + _component_width = 4; + break; + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::is_mipmap // Access: Public, Static @@ -515,8 +896,8 @@ prepare(PreparedGraphicsObjects *prepared_objects) { // the use of mipmaps, or false if it does not. //////////////////////////////////////////////////////////////////// bool Texture:: -is_mipmap(FilterType type) { - switch (type) { +is_mipmap(FilterType filter_type) { + switch (filter_type) { case FT_nearest_mipmap_nearest: case FT_linear_mipmap_nearest: case FT_nearest_mipmap_linear: @@ -572,112 +953,12 @@ prepare_now(PreparedGraphicsObjects *prepared_objects, gobj_cat.debug() << "Dumping RAM for texture " << get_name() << "\n"; } - _pbuffer->_image.clear(); + _image.clear(); } } return tc; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::release -// Access: Public -// Description: Frees the texture context only on the indicated object, -// if it exists there. Returns true if it was released, -// false if it had not been prepared. -//////////////////////////////////////////////////////////////////// -bool Texture:: -release(PreparedGraphicsObjects *prepared_objects) { - Contexts::iterator ci; - ci = _contexts.find(prepared_objects); - if (ci != _contexts.end()) { - TextureContext *tc = (*ci).second; - prepared_objects->release_texture(tc); - return true; - } - - // Maybe it wasn't prepared yet, but it's about to be. - return prepared_objects->dequeue_texture(this); -} - -//////////////////////////////////////////////////////////////////// -// Function: Texture::release_all -// Access: Public -// Description: Frees the context allocated on all objects for which -// the texture has been declared. Returns the number of -// contexts which have been freed. -//////////////////////////////////////////////////////////////////// -int Texture:: -release_all() { - // We have to traverse a copy of the _contexts list, because the - // PreparedGraphicsObjects object will call clear_prepared() in response - // to each release_texture(), and we don't want to be modifying the - // _contexts list while we're traversing it. - Contexts temp = _contexts; - int num_freed = (int)_contexts.size(); - - Contexts::const_iterator ci; - for (ci = temp.begin(); ci != temp.end(); ++ci) { - PreparedGraphicsObjects *prepared_objects = (*ci).first; - TextureContext *tc = (*ci).second; - prepared_objects->release_texture(tc); - } - - // Now that we've called release_texture() on every known context, - // the _contexts list should have completely emptied itself. - nassertr(_contexts.empty(), num_freed); - - return num_freed; -} - -//////////////////////////////////////////////////////////////////// -// Function: Texture::get_ram_image -// Access: Public -// Description: Returns the PixelBuffer associated with the texture. -// If the PixelBuffer does not currently have an -// associated RAM image, and the texture was generated -// by loading an image from a disk file (the most common -// case), this forces the reload of the same texture. -// This can happen if keep_texture_ram is configured to -// false, and we have previously prepared this texture -// with a GSG. -// -// Note that it is not correct to call has_ram_image() -// first to test whether this function will fail. A -// false return value from has_ram_image() indicates -// only that get_ram_image() may need to reload the -// texture from disk, which it will do automatically. -// However, you can call might_have_ram_image(), which -// will return true if the ram image exists, or there is -// a reasonable reason to believe it can be loaded. -// -// On the other hand, it is possible that the texture -// cannot be found on disk or is otherwise unavailable. -// If that happens, this function will return NULL. -// There is no way to predict with 100% accuracy whether -// get_ram_image() will return NULL without calling it -// first; might_have_ram_image() is the closest. -//////////////////////////////////////////////////////////////////// -PixelBuffer *Texture:: -get_ram_image() { - if (!has_ram_image() && has_filename()) { - // Now we have to reload the texture image. - gobj_cat.info() - << "Reloading texture " << get_name() << "\n"; - - if (has_alpha_fullpath()) { - read(get_fullpath(), get_alpha_fullpath()); - } else { - read(get_fullpath()); - } - } - - if (has_ram_image()) { - return _pbuffer; - } else { - return (PixelBuffer *)NULL; - } -} - //////////////////////////////////////////////////////////////////// // Function: Texture::mark_dirty // Access: Public @@ -690,9 +971,8 @@ get_ram_image() { // Normally, this does not need to be called directly; // changing the properties on the texture will // automatically call this. However, if you fiddle with -// the texture image directly, for instance by meddling -// with the _pbuffer member, you may need to explicitly -// call mark_dirty(Texture::DF_image). +// the texture image directly, you may need to +// explicitly call mark_dirty(Texture::DF_image). //////////////////////////////////////////////////////////////////// void Texture:: mark_dirty(int flags_to_set) { @@ -711,28 +991,6 @@ mark_dirty(int flags_to_set) { _all_dirty_flags |= flags_to_set; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::clear_prepared -// Access: Private -// Description: Removes the indicated PreparedGraphicsObjects table -// from the Texture's table, without actually releasing -// the texture. This is intended to be called only from -// PreparedGraphicsObjects::release_texture(); it should -// never be called by user code. -//////////////////////////////////////////////////////////////////// -void Texture:: -clear_prepared(PreparedGraphicsObjects *prepared_objects) { - Contexts::iterator ci; - ci = _contexts.find(prepared_objects); - if (ci != _contexts.end()) { - _contexts.erase(ci); - } else { - // If this assertion fails, clear_prepared() was given a - // prepared_objects which the texture didn't know about. - nassertv(false); - } -} - //////////////////////////////////////////////////////////////////// // Function: Texture::string_wrap_mode // Access: Public @@ -786,6 +1044,139 @@ string_filter_type(const string &string) { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::clear_prepared +// Access: Private +// Description: Removes the indicated PreparedGraphicsObjects table +// from the Texture's table, without actually releasing +// the texture. This is intended to be called only from +// PreparedGraphicsObjects::release_texture(); it should +// never be called by user code. +//////////////////////////////////////////////////////////////////// +void Texture:: +clear_prepared(PreparedGraphicsObjects *prepared_objects) { + Contexts::iterator ci; + ci = _contexts.find(prepared_objects); + if (ci != _contexts.end()) { + _contexts.erase(ci); + } else { + // If this assertion fails, clear_prepared() was given a + // prepared_objects which the texture didn't know about. + nassertv(false); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::up_to_power_2 +// Access: Private, Static +// Description: Returns the smallest power of 2 greater than or equal +// to value. +//////////////////////////////////////////////////////////////////// +int Texture:: +up_to_power_2(int value) { + int x = 1; + while (x < value) { + x = (x << 1); + } + return x; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::down_to_power_2 +// Access: Private, Static +// Description: Returns the largest power of 2 less than or equal +// to value. +//////////////////////////////////////////////////////////////////// +int Texture:: +down_to_power_2(int value) { + int x = 1; + while ((x << 1) <= value) { + x = (x << 1); + } + return x; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::consider_rescale +// Access: Private +// Description: Scales the PNMImage according to the whims of the +// Config.prc file. +//////////////////////////////////////////////////////////////////// +void Texture:: +consider_rescale(PNMImage &pnmimage) { + int new_x_size = pnmimage.get_x_size(); + int new_y_size = pnmimage.get_y_size(); + + switch (textures_power_2) { + case ATS_down: + new_x_size = down_to_power_2(new_x_size); + new_y_size = down_to_power_2(new_y_size); + break; + + case ATS_up: + new_x_size = up_to_power_2(new_x_size); + new_y_size = up_to_power_2(new_y_size); + break; + + case ATS_none: + break; + } + + switch (textures_square) { + case ATS_down: + new_x_size = new_y_size = min(new_x_size, new_y_size); + break; + + case ATS_up: + new_x_size = new_y_size = max(new_x_size, new_y_size); + break; + + case ATS_none: + break; + } + + if (max_texture_dimension > 0) { + new_x_size = min(new_x_size, (int)max_texture_dimension); + new_y_size = min(new_y_size, (int)max_texture_dimension); + } + + if (pnmimage.get_x_size() != new_x_size || + pnmimage.get_y_size() != new_y_size) { + gobj_cat.info() + << "Automatically rescaling " << get_name() << " from " + << pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << " to " + << new_x_size << " by " << new_y_size << "\n"; + + PNMImage scaled(new_x_size, new_y_size, pnmimage.get_num_channels(), + pnmimage.get_maxval(), pnmimage.get_type()); + scaled.quick_filter_from(pnmimage); + pnmimage = scaled; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::consider_downgrade +// Access: Private +// Description: Reduces the number of channels in the texture, if +// necessary, according to num_channels. +//////////////////////////////////////////////////////////////////// +void Texture:: +consider_downgrade(PNMImage &pnmimage, int num_channels) { + if (num_channels != 0 && num_channels < pnmimage.get_num_channels()) { + // One special case: we can't reduce from 3 to 2 components, since + // that would require adding an alpha channel. + if (pnmimage.get_num_channels() == 3 && num_channels == 2) { + return; + } + + gobj_cat.info() + << "Downgrading " << get_name() << " from " + << pnmimage.get_num_channels() << " components to " + << num_channels << ".\n"; + pnmimage.set_num_channels(num_channels); + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::register_with_read_factory // Access: Public, Static @@ -801,7 +1192,7 @@ register_with_read_factory() { // Access: Protected // Description: Factory method to generate a Texture object //////////////////////////////////////////////////////////////////// -TypedWritable* Texture:: +TypedWritable *Texture:: make_Texture(const FactoryParams ¶ms) { //The process of making a texture is slightly //different than making other Writable objects. @@ -815,7 +1206,7 @@ make_Texture(const FactoryParams ¶ms) { parse_params(params, scan, manager); - // Get the properties written by ImageBuffer::write_datagram(). + // Get the filenames so we can look up the file on disk first. string name = scan.get_string(); Filename filename = scan.get_string(); Filename alpha_filename = scan.get_string(); @@ -834,8 +1225,9 @@ make_Texture(const FactoryParams ¶ms) { } // from minor version 5, read the rawdata mode, else carry on - if (manager->get_file_minor_ver() >= 5) + if (manager->get_file_minor_ver() >= 5) { has_rawdata = scan.get_bool(); + } Texture *me = NULL; if (has_rawdata) { @@ -870,14 +1262,6 @@ make_Texture(const FactoryParams ¶ms) { } else { me->set_name(name); me->fillin(scan, manager, has_rawdata); - - /* - cerr << "_xsize = " << me->_pbuffer->get_xsize() << "\n"; - cerr << "_ysize = " << me->_pbuffer->get_ysize() << "\n"; - cerr << "_xorg = " << me->_pbuffer->get_xorg() << "\n"; - cerr << "_yorg = " << me->_pbuffer->get_xorg() << "\n"; - cerr << "_components = " << me->_pbuffer->get_num_components() << "\n"; - */ } return me; } @@ -892,53 +1276,64 @@ make_Texture(const FactoryParams ¶ms) { //////////////////////////////////////////////////////////////////// void Texture:: fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) { - //We don't want to call ImageBuffer::fillin, like we - //would normally, since due to needing to know the name - //of the Texture before creating it, we have already read - //that name in. This is something of a problem as it forces - //Texture to know how the parent write_datagram works. And - //makes the assumption that the only data being written is - //the name + // We have already read in the filenames; don't read them again. - _wrapu = (enum WrapMode) scan.get_uint8(); - _wrapv = (enum WrapMode) scan.get_uint8(); - _minfilter = (enum FilterType) scan.get_uint8(); - _magfilter = (enum FilterType) scan.get_uint8(); + if (manager->get_file_minor_ver() < 17) { + _texture_type = TT_2d_texture; + } else { + _texture_type = (TextureType)scan.get_uint8(); + } + + _wrap_u = (WrapMode)scan.get_uint8(); + _wrap_v = (WrapMode)scan.get_uint8(); + if (manager->get_file_minor_ver() < 17) { + _wrap_w = WM_repeat; + } else { + _wrap_w = (WrapMode)scan.get_uint8(); + } + _minfilter = (FilterType)scan.get_uint8(); + _magfilter = (FilterType)scan.get_uint8(); _anisotropic_degree = scan.get_int16(); - bool has_pbuffer = scan.get_bool(); + bool has_pbuffer = true; + if (manager->get_file_minor_ver() < 17) { + has_pbuffer = scan.get_bool(); + } if (has_pbuffer) { - PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8(); + Format format = (Format)scan.get_uint8(); int num_channels = -1; num_channels = scan.get_uint8(); - if (_pbuffer != (PixelBuffer *)NULL) { - if (num_channels == _pbuffer->get_num_components()) { - // Only reset the format if the number of components hasn't - // changed, since if the number of components has changed our - // texture no longer matches what it was when the bam was - // written. - _pbuffer->set_format(format); + if (num_channels == get_num_components()) { + // Only reset the format if the number of components hasn't + // changed, since if the number of components has changed our + // texture no longer matches what it was when the bam was + // written. + set_format(format); + } + + if (has_rawdata) { + // In the rawdata case, we must always set the format. + _format = format; + _x_size = scan.get_uint32(); + _y_size = scan.get_uint32(); + if (manager->get_file_minor_ver() < 17) { + _z_size = 1; + } else { + _z_size = scan.get_uint32(); } + _component_type = (ComponentType)scan.get_uint8(); + _num_components = scan.get_uint8(); + _component_width = scan.get_uint8(); + _loaded_from_disk = false; - if (has_rawdata) { - // In the rawdata case, we must always set the format. - _pbuffer->set_format(format); - _pbuffer->set_xsize(scan.get_int32()); - _pbuffer->set_ysize(scan.get_int32()); - _pbuffer->set_image_type((PixelBuffer::Type)scan.get_uint8()); - _pbuffer->set_num_components(scan.get_uint8()); - _pbuffer->set_component_width(scan.get_uint8()); - - _pbuffer->set_loaded(); - PN_uint32 u_size = scan.get_uint32(); - - // fill the _image buffer with image data - string temp_buff = scan.extract_bytes(u_size); - _pbuffer->_image = PTA_uchar::empty_array((int) u_size); - for (PN_uint32 u_idx=0; u_idx < u_size; ++u_idx) { - _pbuffer->_image[(int)u_idx] = (uchar) temp_buff[u_idx]; - } + PN_uint32 u_size = scan.get_uint32(); + + // fill the _image buffer with image data + string temp_buff = scan.extract_bytes(u_size); + _image = PTA_uchar::empty_array((int) u_size); + for (PN_uint32 u_idx=0; u_idx < u_size; ++u_idx) { + _image[(int)u_idx] = (uchar) temp_buff[u_idx]; } } } @@ -952,40 +1347,79 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) { //////////////////////////////////////////////////////////////////// void Texture:: write_datagram(BamWriter *manager, Datagram &me) { - // We also need to write out the pixel buffer's format, even though - // that's not stored as part of the texture structure. - bool has_pbuffer = (_pbuffer != (PixelBuffer *)NULL); bool has_rawdata = (bam_texture_mode == BTM_rawdata); - // These properties are read in again by make_Texture(), above. - ImageBuffer::write_datagram(manager, me); + Filename filename = get_filename(); + Filename alpha_filename = get_alpha_filename(); - // from minor version 5, you add this byte to support rawdata mode + switch (bam_texture_mode) { + case BTM_unchanged: + case BTM_rawdata: + break; + + case BTM_fullpath: + filename = get_fullpath(); + alpha_filename = get_alpha_fullpath(); + break; + + case BTM_relative: + filename = get_fullpath(); + alpha_filename = get_alpha_fullpath(); + filename.find_on_searchpath(get_texture_path()) || + filename.find_on_searchpath(get_model_path()); + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Texture file " << get_filename() << " found as " << filename << "\n"; + } + alpha_filename.find_on_searchpath(get_texture_path()) || + alpha_filename.find_on_searchpath(get_model_path()); + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Alpha image " << get_alpha_filename() << " found as " << alpha_filename << "\n"; + } + break; + + case BTM_basename: + filename = filename.get_basename(); + alpha_filename = alpha_filename.get_basename(); + break; + + default: + gobj_cat.error() + << "Unsupported bam-texture-mode: " << (int)bam_texture_mode << "\n"; + } + + me.add_string(get_name()); + me.add_string(filename); + me.add_string(alpha_filename); + me.add_uint8(_primary_file_num_channels); + me.add_uint8(_alpha_file_channel); me.add_bool(has_rawdata); - // These properties are read in again by fillin(), above. - me.add_uint8(_wrapu); - me.add_uint8(_wrapv); + // The data beginning at this point is handled by fillin(). + me.add_uint8(_texture_type); + me.add_uint8(_wrap_u); + me.add_uint8(_wrap_v); + me.add_uint8(_wrap_w); me.add_uint8(_minfilter); me.add_uint8(_magfilter); me.add_int16(_anisotropic_degree); - me.add_bool(has_pbuffer); - if (has_pbuffer) { - me.add_uint8(_pbuffer->get_format()); - me.add_uint8(_pbuffer->get_num_components()); - } + me.add_uint8(_format); + me.add_uint8(_num_components); - // if it has rawdata, then stuff them here along with the header information + // If we are also including the texture's image data, then stuff it + // in here. if (has_rawdata) { - me.add_int32(_pbuffer->get_xsize()); - me.add_int32(_pbuffer->get_ysize()); - me.add_uint8(_pbuffer->get_image_type()); - me.add_uint8(_pbuffer->get_num_components()); - me.add_uint8(_pbuffer->get_component_width()); + me.add_uint32(_x_size); + me.add_uint32(_y_size); + me.add_uint32(_z_size); + me.add_uint8(_component_type); + me.add_uint8(_num_components); + me.add_uint8(_component_width); - me.add_uint32(_pbuffer->_image.size()); - me.append_data(_pbuffer->_image, _pbuffer->_image.size()); + me.add_uint32(_image.size()); + me.append_data(_image, _image.size()); } } diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index d4dc18a243..af496d4605 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -15,13 +15,14 @@ // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// + #ifndef TEXTURE_H #define TEXTURE_H #include "pandabase.h" -#include "imageBuffer.h" -#include "pixelBuffer.h" +#include "typedWritableReferenceCount.h" +#include "namable.h" #include "graphicsStateGuardianBase.h" #include "pmap.h" @@ -32,10 +33,64 @@ class PreparedGraphicsObjects; //////////////////////////////////////////////////////////////////// // Class : Texture -// Description : 2D texture class +// Description : Represents a texture object, which is typically a +// single 2-d image but may also represent a 1-d or 3-d +// texture image, or the six 2-d faces of a cube map +// texture. +// +// A texture's image data might be stored in system RAM +// (see get_ram_image()) or its image may be represented +// in texture memory on one or more +// GraphicsStateGuardians (see prepare()), or both. The +// typical usage pattern is that a texture is loaded +// from an image file on disk, which copies its image +// data into system RAM; then the first time the texture +// is rendered its image data is copied to texture +// memory (actually, to the graphics API), and the +// system RAM image is automatically freed. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Texture : public ImageBuffer { +class EXPCL_PANDA Texture : public TypedWritableReferenceCount, public Namable { PUBLISHED: + enum TextureType { + TT_1d_texture, + TT_2d_texture, + TT_3d_texture, + TT_cube_map, + }; + + enum ComponentType { + T_unsigned_byte, + T_unsigned_short, + T_float, + }; + + enum Format { + F_color_index, + F_stencil_index, + F_depth_component, + F_red, + F_green, + F_blue, + F_alpha, + F_rgb, // any suitable RGB mode, whatever the hardware prefers + F_rgb5, // specifically, 5 bits per R,G,B channel. + // this is paired with T_unsigned_byte. really T_unsigned_byte + // should not be specified for this one, it should use + // T_unsigned_5bits or something + F_rgb8, // 8 bits per R,G,B channel + F_rgb12, // 12 bits per R,G,B channel + F_rgb332, // 3 bits per R & G, 2 bits for B + F_rgba, // any suitable RGBA mode, whatever the hardware prefers + F_rgbm, // as above, but only requires 1 bit for alpha (i.e. mask) + F_rgba4, // 4 bits per R,G,B,A channel + F_rgba5, // 5 bits per R,G,B channel, 1 bit alpha + F_rgba8, // 8 bits per R,G,B,A channel + F_rgba12, // 12 bits per R,G,B,A channel + F_luminance, + F_luminance_alpha, // 8 bits luminance, 8 bits alpha + F_luminance_alphamask // 8 bits luminance, only needs 1 bit of alpha + }; + enum FilterType { // Mag Filter and Min Filter @@ -75,54 +130,118 @@ PUBLISHED: }; PUBLISHED: - Texture(bool match_framebuffer_format = false); - Texture(int xsize, int ysize, int components, int component_width, - PixelBuffer::Type type, PixelBuffer::Format format, - bool allocate_ram); + Texture(const string &name = string()); ~Texture(); - bool read(const Filename &fullpath, int primary_file_num_channels = 0); - bool read(const Filename &fullpath, const Filename &alpha_fullpath, + void setup_texture(TextureType texture_type, + int x_size, int y_size, int z_size, + ComponentType component_type, Format format); + + INLINE void setup_1d_texture(); + INLINE void setup_1d_texture(int x_size, + ComponentType component_type, Format format); + INLINE void setup_2d_texture(); + INLINE void setup_2d_texture(int x_size, int y_size, + ComponentType component_type, Format format); + INLINE void setup_3d_texture(int z_size = 1); + INLINE void setup_3d_texture(int x_size, int y_size, int z_size, + ComponentType component_type, Format format); + INLINE void setup_cube_map(); + INLINE void setup_cube_map(int x_size, int y_size, + ComponentType component_type, Format format); + + bool read(const Filename &fullpath, int z = 0, + int primary_file_num_channels = 0); + bool read(const Filename &fullpath, const Filename &alpha_fullpath, + int z = 0, int primary_file_num_channels = 0, int alpha_file_channel = 0); - bool write(const Filename &fullpath = "") const; + bool write(const Filename &fullpath, int z = 0) const; - bool load(const PNMImage &pnmimage); - bool store(PNMImage &pnmimage) const; + bool load(const PNMImage &pnmimage, int z = 0); + bool store(PNMImage &pnmimage, int z = 0) const; - void set_wrapu(WrapMode wrap); - void set_wrapv(WrapMode wrap); + INLINE bool has_filename() const; + INLINE const Filename &get_filename() const; + INLINE bool has_alpha_filename() const; + INLINE const Filename &get_alpha_filename() const; + + INLINE bool has_fullpath() const; + INLINE const Filename &get_fullpath() const; + INLINE bool has_alpha_fullpath() const; + INLINE const Filename &get_alpha_fullpath() const; + + INLINE int get_x_size() const; + INLINE int get_y_size() const; + INLINE int get_z_size() const; + INLINE int get_num_components() const; + INLINE int get_component_width() const; + INLINE TextureType get_texture_type() const; + INLINE Format get_format() const; + INLINE ComponentType get_component_type() const; + + void set_wrap_u(WrapMode wrap); + void set_wrap_v(WrapMode wrap); + void set_wrap_w(WrapMode wrap); void set_minfilter(FilterType filter); void set_magfilter(FilterType filter); void set_anisotropic_degree(int anisotropic_degree); void set_border_color(const Colorf &color); - void set_border_width(int border_width); - INLINE WrapMode get_wrapu() const; - INLINE WrapMode get_wrapv() const; + INLINE WrapMode get_wrap_u() const; + INLINE WrapMode get_wrap_v() const; + INLINE WrapMode get_wrap_w() const; INLINE FilterType get_minfilter() const; INLINE FilterType get_magfilter() const; INLINE int get_anisotropic_degree() const; INLINE Colorf get_border_color() const; - INLINE int get_border_width() const; INLINE bool uses_mipmaps() const; - INLINE bool get_match_framebuffer_format() const; + INLINE bool has_ram_image() const; + INLINE bool might_have_ram_image() const; + INLINE size_t get_ram_image_size() const; + INLINE size_t get_expected_ram_image_size() const; + INLINE size_t get_expected_ram_page_size() const; + CPTA_uchar get_ram_image(); + PTA_uchar modify_ram_image(); + PTA_uchar make_ram_image(); + void set_ram_image(PTA_uchar image); + void clear_ram_image(); + INLINE void set_keep_ram_image(bool keep_ram_image); + INLINE bool get_keep_ram_image() const; void prepare(PreparedGraphicsObjects *prepared_objects); + bool release(PreparedGraphicsObjects *prepared_objects); + int release_all(); public: + // These are public, but in general, you shouldn't be mucking with + // these values; they are set automatically when a texture is + // loaded. + INLINE void set_filename(const Filename &filename); + INLINE void clear_filename(); + INLINE void set_alpha_filename(const Filename &alpha_filename); + INLINE void clear_alpha_filename(); + + INLINE void set_fullpath(const Filename &fullpath); + INLINE void clear_fullpath(); + INLINE void set_alpha_fullpath(const Filename &alpha_fullpath); + INLINE void clear_alpha_fullpath(); + + INLINE void set_x_size(int x_size); + INLINE void set_y_size(int y_size); + INLINE void set_z_size(int z_size); + void set_format(Format format); + void set_component_type(ComponentType component_type); + INLINE void set_loaded_from_disk(); + +public: + INLINE bool get_match_framebuffer_format() const; + INLINE void set_match_framebuffer_format(bool flag); + static bool is_mipmap(FilterType type); TextureContext *prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg); - bool release(PreparedGraphicsObjects *prepared_objects); - int release_all(); - - INLINE bool has_ram_image() const; - INLINE bool might_have_ram_image() const; - PixelBuffer *get_ram_image(); - INLINE void set_keep_ram_image(bool keep_ram_image); - INLINE bool get_keep_ram_image() const; // These bits are used as parameters to Texture::mark_dirty() and // also TextureContext::mark_dirty() (and related functions in @@ -143,14 +262,53 @@ public: private: void clear_prepared(PreparedGraphicsObjects *prepared_objects); - WrapMode _wrapu; - WrapMode _wrapv; + static int up_to_power_2(int value); + static int down_to_power_2(int value); + + void consider_rescale(PNMImage &pnmimage); + void consider_downgrade(PNMImage &pnmimage, int num_channels); + + INLINE void store_unscaled_byte(int &index, int value); + INLINE void store_unscaled_short(int &index, int value); + INLINE void store_scaled_byte(int &index, int value, double scale); + INLINE void store_scaled_short(int &index, int value, double scale); + INLINE double get_unsigned_byte(int &index) const; + INLINE double get_unsigned_short(int &index) const; + +private: + Filename _filename; + Filename _alpha_filename; + Filename _fullpath; + Filename _alpha_fullpath; + + // The number of channels of the primary file we use. 1, 2, 3, or 4. + int _primary_file_num_channels; + + // If we have a separate alpha file, this designates which channel + // in the alpha file provides the alpha channel. 0 indicates the + // combined grayscale value of rgb; otherwise, 1, 2, 3, or 4 are + // valid. + int _alpha_file_channel; + + int _x_size; + int _y_size; + int _z_size; + int _num_components; + int _component_width; + TextureType _texture_type; + Format _format; + ComponentType _component_type; + + bool _loaded_from_disk; + + WrapMode _wrap_u; + WrapMode _wrap_v; + WrapMode _wrap_w; FilterType _minfilter; FilterType _magfilter; int _anisotropic_degree; bool _keep_ram_image; Colorf _border_color; - int _border_width; bool _match_framebuffer_format; // A Texture keeps a list (actually, a map) of all the @@ -166,10 +324,8 @@ private: // texture. int _all_dirty_flags; -public: - // These are public to allow direct manipulation of the underlying - // pixel buffer when needed. Know what you are doing! - PT(PixelBuffer) _pbuffer; + PTA_uchar _image; + // Datagram stuff public: @@ -186,9 +342,9 @@ public: return _type_handle; } static void init_type() { - ImageBuffer::init_type(); + TypedWritableReferenceCount::init_type(); register_type(_type_handle, "Texture", - ImageBuffer::get_class_type()); + TypedWritableReferenceCount::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/gobj/textureContext.cxx b/panda/src/gobj/textureContext.cxx index 0c0f74afea..df92f6f033 100644 --- a/panda/src/gobj/textureContext.cxx +++ b/panda/src/gobj/textureContext.cxx @@ -18,7 +18,6 @@ #include "textureContext.h" -#include "pixelBuffer.h" #include "texture.h" TypeHandle TextureContext::_type_handle; @@ -34,45 +33,43 @@ TypeHandle TextureContext::_type_handle; //////////////////////////////////////////////////////////////////// size_t TextureContext:: estimate_texture_memory() { - PixelBuffer *pb = _texture->_pbuffer; - - size_t pixels = pb->get_xsize() * pb->get_ysize(); + size_t pixels = _texture->get_x_size() * _texture->get_y_size(); size_t bpp = 4; /* size_t bpp = 1; - switch (pb->get_format()) { - case PixelBuffer::F_rgb332: - case PixelBuffer::F_alpha: - case PixelBuffer::F_red: - case PixelBuffer::F_green: - case PixelBuffer::F_blue: - case PixelBuffer::F_luminance: - case PixelBuffer::F_luminance_alpha: - case PixelBuffer::F_luminance_alphamask: - case PixelBuffer::F_color_index: - case PixelBuffer::F_stencil_index: - case PixelBuffer::F_depth_component: + switch (_texture->get_format()) { + case Texture::F_rgb332: + case Texture::F_alpha: + case Texture::F_red: + case Texture::F_green: + case Texture::F_blue: + case Texture::F_luminance: + case Texture::F_luminance_alpha: + case Texture::F_luminance_alphamask: + case Texture::F_color_index: + case Texture::F_stencil_index: + case Texture::F_depth_component: bpp = 1; break; - case PixelBuffer::F_rgba: - case PixelBuffer::F_rgba4: - case PixelBuffer::F_rgbm: - case PixelBuffer::F_rgb: - case PixelBuffer::F_rgb5: - case PixelBuffer::F_rgba5: + case Texture::F_rgba: + case Texture::F_rgba4: + case Texture::F_rgbm: + case Texture::F_rgb: + case Texture::F_rgb5: + case Texture::F_rgba5: bpp = 2; break; - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgba8: + case Texture::F_rgb8: + case Texture::F_rgba8: bpp = 4; break; - case PixelBuffer::F_rgba12: - case PixelBuffer::F_rgb12: + case Texture::F_rgba12: + case Texture::F_rgb12: bpp = 6; break; } diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index 5aaf6b548e..1678631cdc 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -51,14 +51,9 @@ ns_has_texture(const Filename &orig_filename) { filename = _fake_texture_image; } - if (use_vfs) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->resolve_filename(filename, get_texture_path()); - vfs->resolve_filename(filename, get_model_path()); - } else { - filename.resolve_filename(get_texture_path()); - filename.resolve_filename(get_model_path()); - } + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + vfs->resolve_filename(filename, get_texture_path()); + vfs->resolve_filename(filename, get_model_path()); Textures::const_iterator ti; ti = _textures.find(filename); @@ -83,14 +78,9 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels) { filename = _fake_texture_image; } - if (use_vfs) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->resolve_filename(filename, get_texture_path()) || - vfs->resolve_filename(filename, get_model_path()); - } else { - filename.resolve_filename(get_texture_path()) || - filename.resolve_filename(get_model_path()); - } + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + vfs->resolve_filename(filename, get_texture_path()) || + vfs->resolve_filename(filename, get_model_path()); Textures::const_iterator ti; ti = _textures.find(filename); @@ -102,11 +92,10 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels) { gobj_cat.info() << "Loading texture " << filename << "\n"; PT(Texture) tex = new Texture; - if (!tex->read(filename, primary_file_num_channels)) { + if (!tex->read(filename, 0, primary_file_num_channels)) { // This texture was not found. gobj_cat.error() << "Unable to read texture \"" << filename << "\"" - << (use_vfs ? " (using vfs) ": "") << " on texture_path " << texture_path << " or model_path " << model_path <<"\n"; return NULL; @@ -136,21 +125,12 @@ ns_load_texture(const Filename &orig_filename, return ns_load_texture(_fake_texture_image, primary_file_num_channels); } - if (use_vfs) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->resolve_filename(filename, get_texture_path()) || - vfs->resolve_filename(filename, get_model_path()); - - vfs->resolve_filename(alpha_filename, get_texture_path()) || - vfs->resolve_filename(alpha_filename, get_model_path()); - - } else { - filename.resolve_filename(get_texture_path()) || - filename.resolve_filename(get_model_path()); - - alpha_filename.resolve_filename(get_texture_path()) || - alpha_filename.resolve_filename(get_model_path()); - } + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + vfs->resolve_filename(filename, get_texture_path()) || + vfs->resolve_filename(filename, get_model_path()); + + vfs->resolve_filename(alpha_filename, get_texture_path()) || + vfs->resolve_filename(alpha_filename, get_model_path()); Textures::const_iterator ti; ti = _textures.find(filename); @@ -163,7 +143,7 @@ ns_load_texture(const Filename &orig_filename, << "Loading texture " << filename << " and alpha component " << alpha_filename << endl; PT(Texture) tex = new Texture; - if (!tex->read(filename, alpha_filename, primary_file_num_channels, + if (!tex->read(filename, alpha_filename, 0, primary_file_num_channels, alpha_file_channel)) { // This texture was not found. gobj_cat.error() << "Unable to read texture " << filename << "\n"; @@ -260,7 +240,7 @@ ns_list_contents(ostream &out) const { Texture *texture = (*ti).second; out << " " << (*ti).first << " (count = " << texture->get_ref_count() << ", ram = " - << texture->_pbuffer->_image.size() / 1024 << " Kb)\n"; + << texture->get_ram_image_size() / 1024 << " Kb)\n"; } } diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index c6a8f2b5dc..c5596d8f8e 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -471,10 +471,7 @@ scan_geom_node(GeomNode *node, const RenderState *state, for (int si = 0; si < num_stages; si++) { TextureStage *stage = ta->get_on_stage(si); Texture *tex = ta->get_on_texture(stage); - PixelBuffer *tex_pbuffer = tex->_pbuffer; - if (tex_pbuffer != (PixelBuffer *)NULL && - tex_pbuffer->get_xsize() != 0 && - tex_pbuffer->get_ysize() != 0) { + if (tex->get_x_size() != 0 && tex->get_y_size() != 0) { stage_list.push_back(StageInfo(stage, ta, tma)); } else { @@ -633,11 +630,10 @@ choose_texture_size(int &x_size, int &y_size, const LVecBase2f &uv_scale, GraphicsOutput *window) const { Texture *model_tex = model_stage._tex; - PixelBuffer *model_pbuffer = model_tex->_pbuffer; // Start with the same size as the model texture. - x_size = model_pbuffer->get_xsize(); - y_size = model_pbuffer->get_ysize(); + x_size = model_tex->get_x_size(); + y_size = model_tex->get_y_size(); // But we might be looking at just a subset of that texture (scale < // 1) or a superset of the texture (scale > 1). In this case, we diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 6f0f242c01..3c106557fa 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -48,7 +48,6 @@ class PreparedGraphicsObjects; class GraphicsOutput; class TextureContext; class Texture; -class PixelBuffer; class RenderState; class TransformState; @@ -166,21 +165,14 @@ public: virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0; virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0; - virtual void copy_texture(Texture *tex, const DisplayRegion *dr)=0; - virtual void copy_texture(Texture *tex, const DisplayRegion *dr, - const RenderBuffer &rb)=0; + virtual void framebuffer_copy_to_texture + (Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb)=0; + virtual bool framebuffer_copy_to_ram + (Texture *tex, const DisplayRegion *dr, const RenderBuffer &rb)=0; virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex)=0; virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex)=0; - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb)=0; - virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, - const DisplayRegion *dr)=0; - - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr)=0; - virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, - const RenderBuffer &rb)=0; - virtual void apply_material(const Material *material)=0; virtual void issue_transform(const TransformState *) { } diff --git a/panda/src/helix/HxSiteSupplier.cxx b/panda/src/helix/HxSiteSupplier.cxx index 23c3b806c4..ae5bb18ea9 100644 --- a/panda/src/helix/HxSiteSupplier.cxx +++ b/panda/src/helix/HxSiteSupplier.cxx @@ -197,26 +197,9 @@ STDMETHODIMP HxSiteSupplier::SitesNeeded(UINT32 request_id, IHXValues* pProps) style = WS_OVERLAPPED | WS_VISIBLE | WS_CLIPCHILDREN; #endif - // Determine if there is a valid Panda buffer available - // so that it may be sent down into the sites video - // surface object. - if( _texture->has_ram_image() ) { - pSiteWindowed->SetDstBuffer(_texture->_pbuffer->_image, - _texture->_pbuffer->get_xsize(), - _texture->_pbuffer->get_ysize()); - } - else { - cout << "--- {{ HxSiteSupplier.cxx, RELOADED RAM IMAGE!!! }}---" << endl; - PixelBuffer* fake = _texture->get_ram_image(); - if( fake ) { - pSiteWindowed->SetDstBuffer(fake->_image, - _texture->_pbuffer->get_xsize(), - _texture->_pbuffer->get_ysize()); - } - else { - cout << "--- {{ HxSiteSupplier.cxx, NO RAM IMAGE PRESENT!!! }} ---" << endl; - } - } + pSiteWindowed->SetDstBuffer(_texture->modify_ram_image(), + _texture->get_x_size(), + _texture->get_y_size()); // Create the window. Not necessary later on. hres = pSiteWindowed->Create(NULL, style); diff --git a/panda/src/pgraph/sceneGraphAnalyzer.cxx b/panda/src/pgraph/sceneGraphAnalyzer.cxx index cd6b06363d..0d457411bf 100644 --- a/panda/src/pgraph/sceneGraphAnalyzer.cxx +++ b/panda/src/pgraph/sceneGraphAnalyzer.cxx @@ -366,18 +366,15 @@ collect_statistics(Texture *texture) { // Attempt to guess how many bytes of texture memory this one // requires. - PixelBuffer *pb = texture->_pbuffer; - if (pb != (PixelBuffer *)NULL) { - int bytes = - pb->get_xsize() * pb->get_ysize() * pb->get_num_components() * - pb->get_component_width(); - - if (texture->uses_mipmaps()) { - bytes *= 4/3; - } - - _texture_bytes += bytes; + int bytes = + texture->get_x_size() * texture->get_y_size() * + texture->get_num_components() * texture->get_component_width(); + + if (texture->uses_mipmaps()) { + bytes *= 4/3; } + + _texture_bytes += bytes; } else { // This texture has been encountered before; don't count it again. diff --git a/panda/src/pgraph/spotlight.cxx b/panda/src/pgraph/spotlight.cxx index 46bc09fe69..e85f705de6 100644 --- a/panda/src/pgraph/spotlight.cxx +++ b/panda/src/pgraph/spotlight.cxx @@ -25,6 +25,7 @@ #include "colorAttrib.h" #include "texture.h" #include "config_pgraph.h" +#include "pnmImage.h" TypeHandle Spotlight::_type_handle; @@ -171,26 +172,20 @@ make_image(Texture *texture, float radius) { << "Spotlight::make_image() - NULL texture" << endl; return false; } - PixelBuffer *pb = texture->_pbuffer; - int size = pb->get_xsize(); + int size = min(texture->get_x_size(), texture->get_y_size()); if (size == 0) { - pgraph_cat.error() - << "Spotlight::make_image() - pixel buffer has size == 0" << endl; - return false; + size = 64; } - const Colorf &color = get_color(); + PNMImage image(size, size, 1); - RGBColorf scaled_color; - scaled_color[0] = (color[0] * 255.0f); - scaled_color[1] = (color[1] * 255.0f); - scaled_color[2] = (color[2] * 255.0f); + const Colorf &c4 = get_color(); + const RGBColord color(c4[0], c4[1], c4[2]); int half_width = (size - 2) / 2; float dXY = 1 / (float)half_width; float Y = dXY + dXY; float X, YY, dist_from_center, intensity; - uchar C[3]; int tx, ty, tx2, ty2; for (int y = 0; y < half_width; y++, Y += dXY) { @@ -209,28 +204,23 @@ make_image(Texture *texture, float radius) { else intensity = 0; - C[0] = (uchar)(intensity * scaled_color[0]); - C[1] = (uchar)(intensity * scaled_color[1]); - C[2] = (uchar)(intensity * scaled_color[2]); - tx = x + half_width; - pb->set_uchar_rgb_texel(C, tx, ty, size); - pb->set_uchar_rgb_texel(C, tx, size - ty - 1, size); - pb->set_uchar_rgb_texel(C, size - tx - 1, ty, size); - pb->set_uchar_rgb_texel(C, size - tx - 1, size - ty - 1, size); + image.set_xel(tx, ty, color * intensity); + image.set_xel(tx, size - ty - 1, color * intensity); + image.set_xel(size - tx - 1, ty, color * intensity); + image.set_xel(size - tx - 1, size - ty - 1, color * intensity); tx2 = ty; ty2 = tx; - pb->set_uchar_rgb_texel(C, tx2, ty2, size); - pb->set_uchar_rgb_texel(C, tx2, size - ty2 - 1, size); - pb->set_uchar_rgb_texel(C, size - tx2 - 1, ty2, size); - pb->set_uchar_rgb_texel(C, size - tx2 - 1, size - ty2 - 1, size); + image.set_xel(tx2, ty2, color * intensity); + image.set_xel(tx2, size - ty2 - 1, color * intensity); + image.set_xel(size - tx2 - 1, ty2, color * intensity); + image.set_xel(size - tx2 - 1, size - ty2 - 1, color * intensity); } } - // Force the texture to be reloaded into texture memory. - texture->mark_dirty(Texture::DF_image); + texture->load(image); return true; } diff --git a/panda/src/pgraph/texGenAttrib.cxx b/panda/src/pgraph/texGenAttrib.cxx index aa805832d9..d2656e0e11 100755 --- a/panda/src/pgraph/texGenAttrib.cxx +++ b/panda/src/pgraph/texGenAttrib.cxx @@ -172,6 +172,9 @@ output(ostream &out) const { case M_eye_position: out << "eye_position"; break; + case M_object_normal: + out << "object_normal"; + break; } out << ")"; } diff --git a/panda/src/pgraph/texGenAttrib.h b/panda/src/pgraph/texGenAttrib.h index 5e33068659..a0b047aac1 100755 --- a/panda/src/pgraph/texGenAttrib.h +++ b/panda/src/pgraph/texGenAttrib.h @@ -45,6 +45,7 @@ PUBLISHED: M_world_position, M_object_position, M_eye_position, + M_object_normal, }; protected: diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 39e5993974..863b2ac3b3 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -52,6 +52,7 @@ static const unsigned short _bam_minor_ver = 16; // Bumped to minor version 14 on 11/18/04 to differentiate old_hpr from new_hpr in compressed anim channels. // Bumped to minor version 15 on 1/16/05 to remove width from GeomLine, etc. // Bumped to minor version 16 on 2/24/05 to add TextureStage::rgb_scale, etc. +// Bumped to minor version 17 on 3/03/05 to add 3-d textures, etc. #endif diff --git a/panda/src/text/dynamicTextGlyph.cxx b/panda/src/text/dynamicTextGlyph.cxx index fc88e0dd0f..e4e908a106 100644 --- a/panda/src/text/dynamicTextGlyph.cxx +++ b/panda/src/text/dynamicTextGlyph.cxx @@ -47,7 +47,6 @@ unsigned char *DynamicTextGlyph:: get_row(int y) { nassertr(y >= 0 && y < _y_size - _margin * 2, (unsigned char *)NULL); nassertr(_page != (DynamicTextPage *)NULL, (unsigned char *)NULL); - nassertr(_page->_pbuffer != (PixelBuffer *)NULL, (unsigned char *)NULL); // First, offset y by the glyph's start. y += _y + _margin; @@ -55,10 +54,10 @@ get_row(int y) { int x = _x + _margin; // Invert y. - y = _page->_pbuffer->get_ysize() - 1 - y; + y = _page->get_y_size() - 1 - y; - int offset = (y * _page->_pbuffer->get_xsize()) + x; - return _page->_pbuffer->_image + offset; + int offset = (y * _page->get_x_size()) + x; + return _page->modify_ram_image() + offset; } //////////////////////////////////////////////////////////////////// @@ -69,14 +68,14 @@ get_row(int y) { void DynamicTextGlyph:: erase() { nassertv(_page != (DynamicTextPage *)NULL); - nassertv(_page->_pbuffer != (PixelBuffer *)NULL); + nassertv(_page->has_ram_image()); - int ysizetop = _page->_pbuffer->get_ysize() - 1; - int xsize = _page->_pbuffer->get_xsize(); - unsigned char *buffer = _page->_pbuffer->_image; + int ysizetop = _page->get_y_size() - 1; + int width = _page->get_x_size(); + unsigned char *buffer = _page->modify_ram_image(); for (int y = _y; y < _y + _y_size; y++) { - int offset = (ysizetop - y) * xsize + _x; + int offset = (ysizetop - y) * width + _x; memset(buffer + offset, 0, _x_size); } } diff --git a/panda/src/text/dynamicTextPage.cxx b/panda/src/text/dynamicTextPage.cxx index 488069be3f..95dd47d632 100644 --- a/panda/src/text/dynamicTextPage.cxx +++ b/panda/src/text/dynamicTextPage.cxx @@ -36,18 +36,13 @@ DynamicTextPage(DynamicTextFont *font, int page_number) : _x_size = _font->get_page_x_size(); _y_size = _font->get_page_y_size(); + setup_2d_texture(_x_size, _y_size, T_unsigned_byte, F_alpha); + // Assign a name to the Texture. ostringstream strm; strm << font->get_name() << "_" << page_number; set_name(strm.str()); - // Initialize the Texture to an empty, black (transparent) image of - // the appropriate size. - _pbuffer = new PixelBuffer(_x_size, _y_size, 1, 1, - PixelBuffer::T_unsigned_byte, - PixelBuffer::F_alpha); - mark_dirty(DF_image); - // We'd better never free this image. set_keep_ram_image(true); @@ -58,8 +53,8 @@ DynamicTextPage(DynamicTextFont *font, int page_number) : // It's slightly better to let the texture clamp, rather than // wrapping, so we're less likely to get bleeding at the edges. - set_wrapu(WM_clamp); - set_wrapv(WM_clamp); + set_wrap_u(WM_clamp); + set_wrap_v(WM_clamp); } ////////////////////////////////////////////////////////////////////