1 /*
2   -----------------------------------------------------------------------------
3   This source file is part of OGRE
4   (Object-oriented Graphics Rendering Engine)
5   For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2014 Torus Knot Software Ltd
8 
9   Permission is hereby granted, free of charge, to any person obtaining a copy
10   of this software and associated documentation files (the "Software"), to deal
11   in the Software without restriction, including without limitation the rights
12   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13   copies of the Software, and to permit persons to whom the Software is
14   furnished to do so, subject to the following conditions:
15 
16   The above copyright notice and this permission notice shall be included in
17   all copies or substantial portions of the Software.
18 
19   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25   THE SOFTWARE.
26   -----------------------------------------------------------------------------
27 */
28 #include "OgreGLVertexArrayObject.h"
29 #include "OgreRoot.h"
30 #include "OgreLogManager.h"
31 #include "OgreGLSLProgramCommon.h"
32 #include "OgreGLRenderSystemCommon.h"
33 
34 namespace Ogre {
GLVertexArrayObject()35     GLVertexArrayObject::GLVertexArrayObject() : mCreatorContext(0), mVAO(0), mNeedsUpdate(true), mVertexStart(0) {
36     }
37 
~GLVertexArrayObject()38     GLVertexArrayObject::~GLVertexArrayObject()
39     {
40         if(mVAO != 0)
41         {
42             GLRenderSystemCommon* rs = static_cast<GLRenderSystemCommon*>(Root::getSingleton().getRenderSystem());
43             rs->_destroyVao(mCreatorContext, mVAO);
44         }
45     }
46 
bind(GLRenderSystemCommon * rs)47     void GLVertexArrayObject::bind(GLRenderSystemCommon* rs)
48     {
49         if(mCreatorContext && mCreatorContext != rs->_getCurrentContext()) // VAO is unusable with current context, destroy it
50         {
51             if(mVAO != 0)
52                 rs->_destroyVao(mCreatorContext, mVAO);
53             mCreatorContext = 0;
54             mVAO = 0;
55             mNeedsUpdate = true;
56         }
57         if(!mCreatorContext && rs->getCapabilities()->hasCapability(RSC_VAO)) // create VAO lazy or recreate after destruction
58         {
59             mCreatorContext = rs->_getCurrentContext();
60             mVAO = rs->_createVao();
61             mNeedsUpdate = true;
62         }
63         rs->_bindVao(mCreatorContext, mVAO);
64     }
65 
needsUpdate(VertexBufferBinding * vertexBufferBinding,size_t vertexStart)66     bool GLVertexArrayObject::needsUpdate(VertexBufferBinding* vertexBufferBinding,
67                                           size_t vertexStart)
68     {
69         if(mNeedsUpdate)
70             return true;
71 
72         VertexDeclaration::VertexElementList::const_iterator elemIter, elemEnd;
73         elemEnd = mElementList.end();
74 
75         for (elemIter = mElementList.begin(); elemIter != elemEnd; ++elemIter)
76         {
77             const VertexElement & elem = *elemIter;
78 
79             uint16 source = elem.getSource();
80 
81             if (!vertexBufferBinding->isBufferBound(source))
82                 continue; // Skip unbound elements
83 
84             VertexElementSemantic sem = elem.getSemantic();
85             unsigned short elemIndex = elem.getIndex();
86 
87             uint32 attrib = (uint32)GLSLProgramCommon::getFixedAttributeIndex(sem, elemIndex);
88 
89             const HardwareVertexBufferSharedPtr& vertexBuffer = vertexBufferBinding->getBuffer(source);
90             if (std::find(mAttribsBound.begin(), mAttribsBound.end(),
91                           std::make_pair(attrib, vertexBuffer.get())) == mAttribsBound.end())
92                 return true;
93 
94             if (vertexBuffer->isInstanceData() &&
95                 std::find(mInstanceAttribsBound.begin(), mInstanceAttribsBound.end(), attrib) ==
96                     mInstanceAttribsBound.end())
97                 return true;
98         }
99 
100         if(vertexStart != mVertexStart) {
101             return true;
102         }
103 
104         return false;
105     }
106 
bindToGpu(GLRenderSystemCommon * rs,VertexBufferBinding * vertexBufferBinding,size_t vertexStart)107     void GLVertexArrayObject::bindToGpu(GLRenderSystemCommon* rs,
108                                         VertexBufferBinding* vertexBufferBinding,
109                                         size_t vertexStart)
110     {
111         mAttribsBound.clear();
112         mInstanceAttribsBound.clear();
113 
114         VertexDeclaration::VertexElementList::const_iterator elemIter, elemEnd;
115         elemEnd = mElementList.end();
116 
117         for (elemIter = mElementList.begin(); elemIter != elemEnd; ++elemIter)
118         {
119             const VertexElement& elem = *elemIter;
120 
121             uint16 source = elem.getSource();
122 
123             if (!vertexBufferBinding->isBufferBound(source))
124                 continue; // Skip unbound elements
125 
126             VertexElementSemantic sem = elem.getSemantic();
127             unsigned short elemIndex = elem.getIndex();
128 
129             uint32 attrib = (uint32)GLSLProgramCommon::getFixedAttributeIndex(sem, elemIndex);
130 
131             const HardwareVertexBufferSharedPtr& vertexBuffer = vertexBufferBinding->getBuffer(source);
132 
133             mAttribsBound.push_back(std::make_pair(attrib, vertexBuffer.get()));
134 
135             rs->bindVertexElementToGpu(elem, vertexBuffer, vertexStart);
136 
137             if (vertexBuffer->isInstanceData())
138                 mInstanceAttribsBound.push_back(attrib);
139         }
140 
141         mVertexStart = vertexStart;
142         mNeedsUpdate = false;
143     }
144 }
145