Panda3D
dxIndexBufferContext9.cxx
1 // Filename: dxIndexBufferContext9.cxx
2 // Created by: drose (18Mar05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "dxIndexBufferContext9.h"
16 #include "geomPrimitive.h"
17 #include "config_dxgsg9.h"
18 #include "graphicsStateGuardian.h"
19 #include "pStatTimer.h"
20 
21 #define DEBUG_INDEX_BUFFER false
22 
23 TypeHandle DXIndexBufferContext9::_type_handle;
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: DXIndexBufferContext9::Constructor
27 // Access: Public
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 DXIndexBufferContext9::
31 DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
32  IndexBufferContext(pgo, data),
33  _ibuffer(NULL),
34  _managed(-1) {
35 }
36 
37 ////////////////////////////////////////////////////////////////////
38 // Function: DXIndexBufferContext9::Destructor
39 // Access: Public
40 // Description:
41 ////////////////////////////////////////////////////////////////////
42 DXIndexBufferContext9::
43 ~DXIndexBufferContext9() {
44  free_ibuffer();
45 }
46 
47 ////////////////////////////////////////////////////////////////////
48 // Function: DXIndexBufferContext9::evict_lru
49 // Access: Public, Virtual
50 // Description: Evicts the page from the LRU. Called internally when
51 // the LRU determines that it is full. May also be
52 // called externally when necessary to explicitly evict
53 // the page.
54 //
55 // It is legal for this method to either evict the page
56 // as requested, do nothing (in which case the eviction
57 // will be requested again at the next epoch), or
58 // requeue itself on the tail of the queue (in which
59 // case the eviction will be requested again much
60 // later).
61 ////////////////////////////////////////////////////////////////////
64  dequeue_lru();
65  free_ibuffer();
67  mark_unloaded();
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: DXIndexBufferContext9::free_ibuffer
72 // Access: Public
73 // Description: Free index buffer.
74 ////////////////////////////////////////////////////////////////////
76 free_ibuffer(void) {
77  if (_ibuffer != NULL) {
78  if (DEBUG_INDEX_BUFFER && dxgsg9_cat.is_debug()) {
79  dxgsg9_cat.debug()
80  << "deleting index buffer " << _ibuffer << "\n";
81  }
82 
83  if (DEBUG_INDEX_BUFFER) {
84  RELEASE(_ibuffer, dxgsg9, "index buffer", RELEASE_ONCE);
85  } else {
86  _ibuffer->Release();
87  }
88 
89  _ibuffer = NULL;
90  }
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: DXIndexBufferContext9::allocate_ibuffer
95 // Access: Public
96 // Description: Allocates index buffer memory.
97 ////////////////////////////////////////////////////////////////////
100  const GeomPrimitivePipelineReader *reader) {
101 
102  D3DFORMAT index_type =
103  DXGraphicsStateGuardian9::get_index_type(reader->get_index_type());
104 
105  int data_size;
106  DWORD usage;
107  D3DPOOL pool;
108 
109  data_size = reader->get_data_size_bytes();
110 
111  if (reader->get_index_type() == GeomEnums::NT_uint8) {
112  // We widen 8-bits indices to 16-bits.
113  data_size *= 2;
114  }
115 
116  _managed = scrn._managed_index_buffers;
117  if (_managed)
118  {
119  usage = D3DUSAGE_WRITEONLY;
120  pool = D3DPOOL_MANAGED;
121  }
122  else
123  {
124  usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
125  pool = D3DPOOL_DEFAULT;
126  }
127 
128  int attempts;
129  HRESULT hr;
130 
131  attempts = 0;
132  do
133  {
134  hr = scrn._d3d_device->CreateIndexBuffer
135  (data_size, usage, index_type, pool, &_ibuffer, NULL);
136  attempts++;
137  }
138  while (scrn._dxgsg9 -> check_dx_allocation (hr, data_size, attempts));
139 
140  if (FAILED(hr)) {
141  dxgsg9_cat.warning()
142  << "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
143  _ibuffer = NULL;
144  } else {
145  if (DEBUG_INDEX_BUFFER && dxgsg9_cat.is_debug()) {
146  dxgsg9_cat.debug()
147  << "creating index buffer " << _ibuffer << ": "
148  << reader->get_num_vertices() << " indices ("
149  << reader->get_vertices_reader()->get_array_format()->get_column(0)->get_numeric_type()
150  << ")\n";
151  }
152  }
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: DXIndexBufferContext9::create_ibuffer
157 // Access: Public
158 // Description: Creates a new index buffer (but does not upload data
159 // to it).
160 ////////////////////////////////////////////////////////////////////
163  const GeomPrimitivePipelineReader *reader) {
164  nassertv(reader->get_object() == get_data());
165  Thread *current_thread = reader->get_current_thread();
166 
167  free_ibuffer();
168 
169  PStatTimer timer(GraphicsStateGuardian::_create_index_buffer_pcollector,
170  current_thread);
171 
172  allocate_ibuffer(scrn, reader);
173 }
174 
175 ////////////////////////////////////////////////////////////////////
176 // Function: DXIndexBufferContext9::upload_data
177 // Access: Public
178 // Description: Copies the latest data from the client store to
179 // DirectX.
180 ////////////////////////////////////////////////////////////////////
182 upload_data(const GeomPrimitivePipelineReader *reader, bool force) {
183  nassertr(reader->get_object() == get_data(), false);
184  Thread *current_thread = reader->get_current_thread();
185 
186  nassertr(_ibuffer != NULL, false);
187 
188  const unsigned char *data_pointer = reader->get_read_pointer(force);
189  if (data_pointer == NULL) {
190  return false;
191  }
192  int data_size = reader->get_data_size_bytes();
193 
194  if (reader->get_index_type() == GeomEnums::NT_uint8) {
195  // We widen 8-bits indices to 16-bits.
196  data_size *= 2;
197  }
198 
199  if (dxgsg9_cat.is_spam()) {
200  dxgsg9_cat.spam()
201  << "copying " << data_size
202  << " bytes into index buffer " << _ibuffer << "\n";
203  }
204  PStatTimer timer(GraphicsStateGuardian::_load_index_buffer_pcollector,
205  current_thread);
206 
207  HRESULT hr;
208  BYTE *local_pointer;
209 
210  if (_managed) {
211  hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, 0);
212  } else {
213  hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
214  }
215  if (FAILED(hr)) {
216  dxgsg9_cat.error()
217  << "IndexBuffer::Lock failed" << D3DERRORSTRING(hr);
218  return false;
219  }
220 
221  GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
222 
223  if (reader->get_index_type() == GeomEnums::NT_uint8) {
224  // Widen to 16-bits, as DirectX doesn't support 8-bits indices.
225  PN_uint16 *ptr = (PN_uint16 *)local_pointer;
226  for (size_t i = 0; i < data_size; i += 2) {
227  *ptr++ = (PN_uint16)*data_pointer++;
228  }
229  } else {
230  memcpy(local_pointer, data_pointer, data_size);
231  }
232 
233  _ibuffer->Unlock();
234  return true;
235 }
This is a special class object that holds all the information returned by a particular GSG to indicat...
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:63
static D3DFORMAT get_index_type(Geom::NumericType numeric_type)
Maps from the Geom&#39;s internal numeric type symbols to DirectX&#39;s.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
A table of objects that are saved within the graphics context for reference by handle later...
void dequeue_lru()
Removes the page from its AdaptiveLru.
Definition: adaptiveLru.I:171
void allocate_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader)
Allocates index buffer memory.
void mark_unloaded()
Should be called after the buffer has been forced out of graphics memory.
bool upload_data(const GeomPrimitivePipelineReader *reader, bool force)
Copies the latest data from the client store to DirectX.
A thread; that is, a lightweight process.
Definition: thread.h:51
virtual void evict_lru()
Evicts the page from the LRU.
GeomPrimitive * get_data() const
Returns the pointer to the client-side array data object.
void free_ibuffer()
Free index buffer.
void create_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader)
Creates a new index buffer (but does not upload data to it).
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
int get_data_size_bytes() const
Returns the number of bytes stored in the vertices array.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
void update_data_size_bytes(size_t new_data_size_bytes)
Should be called (usually by a derived class) when the on-card size of this object has changed...