1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12 *
13 * osg/PrimitiveSetIndirect.cpp
14 * Author: Julien Valentin 2016-2017
15 */
16
17 #include <osg/PrimitiveSetIndirect>
18 #include <osg/BufferObject>
19 #include <osg/State>
20 #include <osg/Notify>
21
22 /// TODO: add base vertex feature to PrimitiveFunctor and PrimitiveIndexFunctor
23 //#define PRIMFUNCTORBASEVERTEX 1
24
25 using namespace osg;
26 ////////////////////////////////////////////////////////////////////////////////////////////////////////
27 //
28 // DrawElementsIndirect
29 //
30 template<class T>
getNumPrimitivesDI(const T & _this)31 inline unsigned int getNumPrimitivesDI( const T&_this )
32 {
33 unsigned int offset= _this.getFirstCommandToDraw();
34 IndirectCommandDrawElements *cmd=const_cast<IndirectCommandDrawElements *>(_this.getIndirectCommandArray());
35 unsigned int total=0;
36 switch(_this.getMode())
37 {
38 case(PrimitiveSet::POINTS):
39 return cmd->count(offset);
40 case(PrimitiveSet::LINES):
41 return cmd->count(offset)/2;
42 case(PrimitiveSet::TRIANGLES):
43 return cmd->count(offset)/3;
44 case(PrimitiveSet::QUADS):
45 return cmd->count(offset)/4;
46 case(PrimitiveSet::LINE_STRIP):
47 case(PrimitiveSet::LINE_LOOP):
48 case(PrimitiveSet::TRIANGLE_STRIP):
49 case(PrimitiveSet::TRIANGLE_FAN):
50 case(PrimitiveSet::QUAD_STRIP):
51 case(PrimitiveSet::PATCHES):
52 case(PrimitiveSet::POLYGON):
53 {
54 return 1;
55 }
56 }
57 return total;
58 }
59
getNumPrimitives() const60 unsigned int DrawElementsIndirectUInt::getNumPrimitives() const { return getNumPrimitivesDI<DrawElementsIndirectUInt>(*this); }
getNumPrimitives() const61 unsigned int DrawElementsIndirectUByte::getNumPrimitives() const { return getNumPrimitivesDI<DrawElementsIndirectUByte>(*this); }
getNumPrimitives() const62 unsigned int DrawElementsIndirectUShort::getNumPrimitives() const { return getNumPrimitivesDI<DrawElementsIndirectUShort>(*this); }
63
draw(State & state,bool) const64 void DrawElementsIndirectUInt::draw(State& state, bool /*useVertexBufferObjects*/) const
65 {
66 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
67 state.bindDrawIndirectBufferObject(dibo);
68
69 GLenum mode = _mode;
70 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
71 if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
72 if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
73 #endif
74
75 GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
76
77 state.bindElementBufferObject(ebo);
78
79 state.get<GLExtensions>()-> glDrawElementsIndirect(mode, GL_UNSIGNED_INT,
80 (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex()) //command array address
81 +_firstCommand* _indirectCommandArray->getElementSize())// runtime offset computaion can be sizeof(*_indirectCommandArray->begin())
82 );
83 }
84
~DrawElementsIndirectUInt()85 DrawElementsIndirectUInt::~DrawElementsIndirectUInt()
86 {
87 releaseGLObjects();
88 }
89
offsetIndices(int offset)90 void DrawElementsIndirectUInt::offsetIndices(int offset)
91 {
92 for(iterator itr=begin();
93 itr!=end();
94 ++itr)
95 {
96 *itr += offset;
97 }
98 }
99
100 #ifndef PRIMFUNCTORBASEVERTEX
accept(PrimitiveFunctor &) const101 void DrawElementsIndirectUInt::accept(PrimitiveFunctor&) const {}
accept(PrimitiveIndexFunctor &) const102 void DrawElementsIndirectUInt::accept(PrimitiveIndexFunctor&) const {}
103 #else
accept(PrimitiveFunctor & functor) const104 void DrawElementsIndirectUInt::accept(PrimitiveFunctor& functor) const
105 {
106 // TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
107 if (!empty())
108 functor.drawElements(_mode,_indirectCommandArray->count(_firstCommand),
109 &(*this)[_indirectCommandArray->firstIndex(_firstCommand)],
110 _indirectCommandArray->baseVertex(_firstCommand));
111 }
112
accept(PrimitiveIndexFunctor & functor) const113 void DrawElementsIndirectUInt::accept(PrimitiveIndexFunctor& functor) const
114 {
115 // TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
116 if (!empty())
117 functor.drawElements(_mode,_indirectCommandArray->count(_firstCommand),
118 &(*this)[_indirectCommandArray->firstIndex(_firstCommand)],
119 _indirectCommandArray->baseVertex(_firstCommand));
120 }
121 #endif
122
draw(State & state,bool) const123 void DrawElementsIndirectUByte::draw(State& state, bool /*useVertexBufferObjects*/) const
124 {
125 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
126 state.bindDrawIndirectBufferObject(dibo);
127
128 GLenum mode = _mode;
129 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
130 if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
131 if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
132 #endif
133
134 GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
135
136 state.bindElementBufferObject(ebo);
137
138 state.get<GLExtensions>()-> glDrawElementsIndirect(mode, GL_UNSIGNED_BYTE,
139 (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())+_firstCommand* _indirectCommandArray->getElementSize()));
140 }
141
~DrawElementsIndirectUByte()142 DrawElementsIndirectUByte::~DrawElementsIndirectUByte()
143 {
144 releaseGLObjects();
145 }
146
offsetIndices(int offset)147 void DrawElementsIndirectUByte::offsetIndices(int offset)
148 {
149 for(iterator itr=begin();
150 itr!=end();
151 ++itr)
152 {
153 *itr += offset;
154 }
155 }
156
157 #ifndef PRIMFUNCTORBASEVERTEX
accept(PrimitiveFunctor &) const158 void DrawElementsIndirectUByte::accept(PrimitiveFunctor&) const {}
accept(PrimitiveIndexFunctor &) const159 void DrawElementsIndirectUByte::accept(PrimitiveIndexFunctor&) const {}
160 #else
accept(PrimitiveFunctor & functor) const161 void DrawElementsIndirectUByte::accept(PrimitiveFunctor& functor) const
162 {
163 // TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
164 if (!empty())
165 functor.drawElements(_mode,_indirectCommandArray->count(_firstCommand),
166 &(*this)[_indirectCommandArray->firstIndex(_firstCommand)],
167 _indirectCommandArray->baseVertex(_firstCommand));
168 }
169
accept(PrimitiveIndexFunctor & functor) const170 void DrawElementsIndirectUByte::accept(PrimitiveIndexFunctor& functor) const
171 {
172 // TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
173 if (!empty())
174 functor.drawElements(_mode,_indirectCommandArray->count(_firstCommand),
175 &(*this)[_indirectCommandArray->firstIndex(_firstCommand)],
176 _indirectCommandArray->baseVertex(_firstCommand));
177 }
178 #endif
179
draw(State & state,bool) const180 void DrawElementsIndirectUShort::draw(State& state, bool /*useVertexBufferObjects*/) const
181 {
182 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
183 state.bindDrawIndirectBufferObject(dibo);
184
185 GLenum mode = _mode;
186 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
187 if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
188 if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
189 #endif
190
191 GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
192
193 state.bindElementBufferObject(ebo);
194
195 state.get<GLExtensions>()-> glDrawElementsIndirect(mode, GL_UNSIGNED_SHORT,
196 (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())+_firstCommand* _indirectCommandArray->getElementSize()));
197 }
198
~DrawElementsIndirectUShort()199 DrawElementsIndirectUShort::~DrawElementsIndirectUShort()
200 {
201 releaseGLObjects();
202 }
203
offsetIndices(int offset)204 void DrawElementsIndirectUShort::offsetIndices(int offset)
205 {
206 for(iterator itr=begin();
207 itr!=end();
208 ++itr)
209 {
210 *itr += offset;
211 }
212 }
213
214 #ifndef PRIMFUNCTORBASEVERTEX
accept(PrimitiveFunctor &) const215 void DrawElementsIndirectUShort::accept(PrimitiveFunctor&) const {}
accept(PrimitiveIndexFunctor &) const216 void DrawElementsIndirectUShort::accept(PrimitiveIndexFunctor&) const {}
217 #else
accept(PrimitiveFunctor & functor) const218 void DrawElementsIndirectUShort::accept(PrimitiveFunctor& functor) const
219 {
220 // TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
221 if (!empty())
222 functor.drawElements(_mode,_indirectCommandArray->count(_firstCommand),
223 &(*this)[_indirectCommandArray->firstIndex(_firstCommand)],
224 _indirectCommandArray->baseVertex(_firstCommand));
225 }
226
accept(PrimitiveIndexFunctor & functor) const227 void DrawElementsIndirectUShort::accept(PrimitiveIndexFunctor& functor) const
228 {
229 // TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
230 if (!empty())
231 functor.drawElements(_mode,_indirectCommandArray->count(_firstCommand),
232 &(*this)[_indirectCommandArray->firstIndex(_firstCommand)],
233 _indirectCommandArray->baseVertex(_firstCommand));
234 }
235 #endif
236
237 ////////////////////////////////////////////////////////////////////////////////////////////////////////
238 //
239 // MultiDrawElementsIndirect
240 //
241 template<class T> inline
getNumPrimitivesMDI(const T & _this)242 unsigned int getNumPrimitivesMDI( const T&_this)
243 {
244 IndirectCommandDrawElements *_indirectCommandArray=const_cast<IndirectCommandDrawElements *>(_this.getIndirectCommandArray());
245 unsigned int total=0;
246 switch(_this.getMode())
247 {
248 case(PrimitiveSet::POINTS):
249 for(unsigned int i=0;i<_indirectCommandArray->getNumElements();++i)
250 total+=_indirectCommandArray->count(i);
251 break;
252 case(PrimitiveSet::LINES):
253 for(unsigned int i=0;i<_indirectCommandArray->getNumElements();++i)
254 total+=_indirectCommandArray->count(i)/2;
255 break;
256 case(PrimitiveSet::TRIANGLES):
257 for(unsigned int i=0;i<_indirectCommandArray->getNumElements();++i)
258 total+=_indirectCommandArray->count(i)/3;
259 break;
260 case(PrimitiveSet::QUADS):
261 for(unsigned int i=0;i<_indirectCommandArray->getNumElements();++i)
262 total+=_indirectCommandArray->count(i)/4;
263 break;
264 case(PrimitiveSet::LINE_STRIP):
265 case(PrimitiveSet::LINE_LOOP):
266 case(PrimitiveSet::TRIANGLE_STRIP):
267 case(PrimitiveSet::TRIANGLE_FAN):
268 case(PrimitiveSet::QUAD_STRIP):
269 case(PrimitiveSet::PATCHES):
270 case(PrimitiveSet::POLYGON):
271 {
272 unsigned int primcount = _indirectCommandArray->getNumElements();
273 return primcount;
274 }
275 }
276 return total;
277 }
278
getNumPrimitives() const279 unsigned int MultiDrawElementsIndirectUInt::getNumPrimitives() const { return getNumPrimitivesMDI<MultiDrawElementsIndirectUInt>(*this); }
getNumPrimitives() const280 unsigned int MultiDrawElementsIndirectUByte::getNumPrimitives() const { return getNumPrimitivesMDI<MultiDrawElementsIndirectUByte>(*this); }
getNumPrimitives() const281 unsigned int MultiDrawElementsIndirectUShort::getNumPrimitives() const { return getNumPrimitivesMDI<MultiDrawElementsIndirectUShort>(*this); }
282
283 ////////////////////////////////////////////////////////////////////////////////////////////////////////
284 //
285 // MultiDrawElementsIndirectUByte
286 //
~MultiDrawElementsIndirectUByte()287 MultiDrawElementsIndirectUByte::~MultiDrawElementsIndirectUByte()
288 {
289 releaseGLObjects();
290 }
291
draw(State & state,bool) const292 void MultiDrawElementsIndirectUByte::draw(State& state, bool /*useVertexBufferObjects*/) const
293 {
294 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
295
296 state.bindDrawIndirectBufferObject(dibo);
297 GLenum mode = _mode;
298 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
299 if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
300 if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
301 #endif
302
303 GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
304
305 state.bindElementBufferObject(ebo);
306
307 state.get<GLExtensions>()-> glMultiDrawElementsIndirect(mode, GL_UNSIGNED_BYTE,
308 (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())),_indirectCommandArray->getNumElements(), _stride);
309 }
310
311 #ifndef PRIMFUNCTORBASEVERTEX
accept(PrimitiveFunctor &) const312 void MultiDrawElementsIndirectUByte::accept(PrimitiveFunctor&) const {}
accept(PrimitiveIndexFunctor &) const313 void MultiDrawElementsIndirectUByte::accept(PrimitiveIndexFunctor&) const {}
314 #else
accept(PrimitiveFunctor & functor) const315 void MultiDrawElementsIndirectUByte::accept(PrimitiveFunctor& functor) const
316 {
317 //TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
318 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
319 if (!empty() )
320 for(unsigned int i = _firstCommand; i<maxindex; ++i)
321 functor.drawElements(_mode,_indirectCommandArray->count(i),
322 &(*this)[_indirectCommandArray->firstIndex(i)],
323 _indirectCommandArray->baseVertex(i));
324 }
325
accept(PrimitiveIndexFunctor & functor) const326 void MultiDrawElementsIndirectUByte::accept(PrimitiveIndexFunctor& functor) const
327 {
328 //TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
329 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
330 if (!empty() )
331 for(unsigned int i = _firstCommand; i<maxindex; ++i)
332 functor.drawElements(_mode,_indirectCommandArray->count(i),
333 &(*this)[_indirectCommandArray->firstIndex(i)],
334 _indirectCommandArray->baseVertex(i));
335 }
336 #endif
337
338
339
340
341 ////////////////////////////////////////////////////////////////////////////////////////////////////////
342 //
343 // MultiDrawElementsIndirectUShort
344 //
~MultiDrawElementsIndirectUShort()345 MultiDrawElementsIndirectUShort::~MultiDrawElementsIndirectUShort()
346 {
347 releaseGLObjects();
348 }
349
draw(State & state,bool) const350 void MultiDrawElementsIndirectUShort::draw(State& state, bool /*useVertexBufferObjects*/) const
351 { GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
352 state.bindDrawIndirectBufferObject(dibo);
353
354 GLenum mode = _mode;
355 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
356 if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
357 if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
358 #endif
359
360 GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
361
362 state.bindElementBufferObject(ebo);
363
364 state.get<GLExtensions>()-> glMultiDrawElementsIndirect(mode, GL_UNSIGNED_SHORT, (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())),
365 (_count>0) ?_count:_indirectCommandArray->getNumElements(),_stride);
366 }
367
368 #ifndef PRIMFUNCTORBASEVERTEX
accept(PrimitiveFunctor &) const369 void MultiDrawElementsIndirectUShort::accept(PrimitiveFunctor&) const {}
accept(PrimitiveIndexFunctor &) const370 void MultiDrawElementsIndirectUShort::accept(PrimitiveIndexFunctor&) const {}
371 #else
accept(PrimitiveFunctor & functor) const372 void MultiDrawElementsIndirectUShort::accept(PrimitiveFunctor& functor) const
373 {
374 //TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
375 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
376 if (!empty() )
377 for(unsigned int i = _firstCommand; i<maxindex; ++i)
378 functor.drawElements(_mode,_indirectCommandArray->count(i),
379 &(*this)[_indirectCommandArray->firstIndex(i)],
380 _indirectCommandArray->baseVertex(i));
381 }
382
accept(PrimitiveIndexFunctor & functor) const383 void MultiDrawElementsIndirectUShort::accept(PrimitiveIndexFunctor& functor) const
384 {
385 //TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
386 unsigned int maxindex = (_count>0) ?_firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
387 if (!empty() )
388 for(unsigned int i = _firstCommand; i<maxindex; ++i)
389 functor.drawElements(_mode,_indirectCommandArray->count(i),
390 &(*this)[_indirectCommandArray->firstIndex(i)],
391 _indirectCommandArray->baseVertex(i));
392 }
393 #endif
394
395 ////////////////////////////////////////////////////////////////////////////////////////////////////////
396 //
397 // MultiDrawElementsIndirectUInt
398 //
~MultiDrawElementsIndirectUInt()399 MultiDrawElementsIndirectUInt::~MultiDrawElementsIndirectUInt()
400 {
401 releaseGLObjects();
402 }
403
draw(State & state,bool) const404 void MultiDrawElementsIndirectUInt::draw(State& state, bool /*useVertexBufferObjects*/) const
405 {
406 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
407 state.bindDrawIndirectBufferObject(dibo);
408 GLenum mode = _mode;
409 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
410 if (mode==GL_POLYGON) mode = GL_TRIANGLE_FAN;
411 if (mode==GL_QUAD_STRIP) mode = GL_TRIANGLE_STRIP;
412 #endif
413
414 GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID());
415
416 state.bindElementBufferObject(ebo);
417
418 state.get<GLExtensions>()-> glMultiDrawElementsIndirect(mode, GL_UNSIGNED_INT, (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())),
419 (_count>0) ? _count:_indirectCommandArray->getNumElements(), _stride);
420 }
421
422 #ifndef PRIMFUNCTORBASEVERTEX
accept(PrimitiveFunctor &) const423 void MultiDrawElementsIndirectUInt::accept(PrimitiveFunctor&) const {}
accept(PrimitiveIndexFunctor &) const424 void MultiDrawElementsIndirectUInt::accept(PrimitiveIndexFunctor&) const {}
425 #else
accept(PrimitiveFunctor & functor) const426 void MultiDrawElementsIndirectUInt::accept(PrimitiveFunctor& functor) const
427 {
428 //TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
429 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
430 if (!empty() )
431 for(unsigned int i = _firstCommand; i<maxindex; ++i)
432 functor.drawElements(_mode,_indirectCommandArray->count(i),
433 &(*this)[_indirectCommandArray->firstIndex(i)],
434 _indirectCommandArray->baseVertex(i));
435 }
436
accept(PrimitiveIndexFunctor & functor) const437 void MultiDrawElementsIndirectUInt::accept(PrimitiveIndexFunctor& functor) const
438 {
439 //TODO: add base vertex parameter in PrimitiveFunctor and PrimitiveIndexFunctor drawelements method
440 unsigned int maxindex = (_count>0) ?_firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
441 if (!empty() )
442 for(unsigned int i = _firstCommand; i<maxindex; ++i)
443 functor.drawElements(_mode,_indirectCommandArray->count(i),
444 &(*this)[_indirectCommandArray->firstIndex(i)],
445 _indirectCommandArray->baseVertex(i));
446 }
447 #endif
448
449
450 ////////////////////////////////////////////////////////////////////////////////////////////////////////
451 //
452 // MultiDrawArrays
453 //
draw(osg::State & state,bool) const454 void DrawArraysIndirect::draw(osg::State& state, bool) const
455 {
456 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
457 state.bindDrawIndirectBufferObject(dibo);
458
459 GLExtensions* ext = state.get<GLExtensions>();
460
461 ext->glDrawArraysIndirect(_mode, (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())+_firstCommand* _indirectCommandArray->getElementSize()));
462 }
463
accept(PrimitiveFunctor & functor) const464 void DrawArraysIndirect::accept(PrimitiveFunctor& functor) const
465 {
466 functor.drawArrays(_mode, _indirectCommandArray->first(_firstCommand), _indirectCommandArray->count(_firstCommand));
467 }
468
accept(PrimitiveIndexFunctor & functor) const469 void DrawArraysIndirect::accept(PrimitiveIndexFunctor& functor) const
470 {
471 functor.drawArrays(_mode, _indirectCommandArray->first(_firstCommand), _indirectCommandArray->count(_firstCommand));
472 }
473
getNumIndices() const474 unsigned int DrawArraysIndirect::getNumIndices() const
475 {
476 return _indirectCommandArray->count(_firstCommand);
477 }
478
index(unsigned int pos) const479 unsigned int DrawArraysIndirect::index(unsigned int pos) const
480 {
481 return _indirectCommandArray->first(_firstCommand)+ pos;
482 }
483
offsetIndices(int offset)484 void DrawArraysIndirect::offsetIndices(int offset)
485 {
486 _indirectCommandArray->first(_firstCommand)+= offset;
487 }
488
getNumPrimitives() const489 unsigned int DrawArraysIndirect::getNumPrimitives() const
490 {
491 switch(_mode)
492 {
493 case(POINTS):
494 return _indirectCommandArray->count(_firstCommand);
495 case(LINES):
496 return _indirectCommandArray->count(_firstCommand)/2;
497 case(TRIANGLES):
498 return _indirectCommandArray->count(_firstCommand)/3;
499 case(QUADS):
500 return _indirectCommandArray->count(_firstCommand)/4;
501 case(LINE_STRIP):
502 case(LINE_LOOP):
503 case(TRIANGLE_STRIP):
504 case(TRIANGLE_FAN):
505 case(QUAD_STRIP):
506 case(PATCHES):
507 case(POLYGON):
508 {
509 return 1;
510 }
511 }
512 return 0;
513 }
514
515 ////////////////////////////////////////////////////////////////////////////////////////////////////////
516 //
517 // MultiDrawArrays
518 //
draw(osg::State & state,bool) const519 void MultiDrawArraysIndirect::draw(osg::State& state, bool) const
520 {
521 GLBufferObject* dibo = _indirectCommandArray->getBufferObject()->getOrCreateGLBufferObject( state.getContextID() );
522 state.bindDrawIndirectBufferObject(dibo);
523
524 GLExtensions* ext = state.get<GLExtensions>();
525
526 ext->glMultiDrawArraysIndirect(_mode, (const GLvoid *)(dibo->getOffset(_indirectCommandArray->getBufferIndex())+_firstCommand*_indirectCommandArray->getElementSize()),
527 (_count>0) ?_count:_indirectCommandArray->getNumElements(), _stride);
528
529 }
530
accept(PrimitiveFunctor & functor) const531 void MultiDrawArraysIndirect::accept(PrimitiveFunctor& functor) const
532 {
533 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
534 for(unsigned int i = _firstCommand; i<maxindex; ++i)
535 {
536 functor.drawArrays(_mode, _indirectCommandArray->first(i), _indirectCommandArray->count(i));
537 }
538 }
539
accept(PrimitiveIndexFunctor & functor) const540 void MultiDrawArraysIndirect::accept(PrimitiveIndexFunctor& functor) const
541 {
542 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
543 for(unsigned int i = _firstCommand; i<maxindex; ++i)
544 {
545 functor.drawArrays(_mode, _indirectCommandArray->first(i), _indirectCommandArray->count(i));
546 }
547 }
548
getNumIndices() const549 unsigned int MultiDrawArraysIndirect::getNumIndices() const
550 {
551 unsigned int total=0;
552 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
553 for(unsigned int i = _firstCommand; i<maxindex; ++i)
554 total+= _indirectCommandArray->count(i);
555
556 return total;
557 }
558
index(unsigned int pos) const559 unsigned int MultiDrawArraysIndirect::index(unsigned int pos) const
560 {
561 unsigned int i = 0, maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
562 for(i=_firstCommand; i<maxindex;++i)
563 {
564 unsigned int count = _indirectCommandArray->count(i);
565 if (pos<count) break;
566 pos -= count;
567 }
568 if (i>=maxindex) return 0;
569 return _indirectCommandArray->first(maxindex-1) + pos;
570
571 }
572
offsetIndices(int offset)573 void MultiDrawArraysIndirect::offsetIndices(int offset)
574 {
575 unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
576 for(unsigned int i = _firstCommand; i<maxindex; ++i)
577 _indirectCommandArray->first(i) += offset;
578 }
579
getNumPrimitives() const580 unsigned int MultiDrawArraysIndirect::getNumPrimitives() const
581 {
582 unsigned int total=0;unsigned int maxindex= (_count>0) ? _firstCommand + _count : _indirectCommandArray->getNumElements() - _firstCommand;
583
584 switch(_mode)
585 {
586 case(POINTS):
587 for(unsigned int i = _firstCommand; i<maxindex; ++i)
588 total+=_indirectCommandArray->count(i);
589 break;
590 case(LINES):
591 for(unsigned int i = _firstCommand; i<maxindex; ++i)
592 total+=_indirectCommandArray->count(i)/2;
593 break;
594 case(TRIANGLES):
595 for(unsigned int i = _firstCommand; i<maxindex; ++i)
596 total+=_indirectCommandArray->count(i)/3;
597 break;
598 case(QUADS):
599 for(unsigned int i = _firstCommand; i<maxindex; ++i)
600 total+=_indirectCommandArray->count(i)/4;
601 break;
602 case(LINE_STRIP):
603 case(LINE_LOOP):
604 case(TRIANGLE_STRIP):
605 case(TRIANGLE_FAN):
606 case(QUAD_STRIP):
607 case(PATCHES):
608 case(POLYGON):
609 {
610 unsigned int primcount = _indirectCommandArray->getNumElements();
611 return primcount;
612 }
613 }
614 return total;
615 }
616