diff options
author | Emmanuel Gil Peyrot <emmanuel.peyrot@collabora.com> | 2015-11-19 17:18:55 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2015-11-19 19:21:48 +0200 |
commit | e18da092ef9a81202c9ec941bcb9876f257eed5b (patch) | |
tree | 1ed88646902ff93afcc7c8cd475e183e9e220226 /slideshow | |
parent | 04e2caeba5e346fb5d415d633b1956ef24c41037 (diff) |
slideshow: Batch primitive display as much as possible
We now set the state and upload all vertices data at once, before each
batch, in order to minimize GL calls during drawing.
The next step will be to move to shaders, in order to use per-primitive
uniforms instead of changing the global modelview matrix and issuing
another draw call.
Change-Id: I8c7cf29047047b9cad575cc6264485ae77d6ba10
Diffstat (limited to 'slideshow')
-rw-r--r-- | slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx | 120 | ||||
-rw-r--r-- | slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx | 39 |
2 files changed, 100 insertions, 59 deletions
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx index 11e6c4e92093..a7fa892decd1 100644 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx +++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx @@ -192,6 +192,58 @@ void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthS rOverallOperations[i]->interpolate(nTime,SlideWidthScale,SlideHeightScale); } +static void display_primitives(const Primitives_t& primitives, double nTime, double WidthScale, double HeightScale) +{ + CHECK_GL_ERROR(); + GLuint buffer; + glGenBuffers(1, &buffer); + CHECK_GL_ERROR(); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + + int size = 0; + for (const Primitive& primitive: primitives) + size += primitive.getVerticesSize(); + + CHECK_GL_ERROR(); + glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STREAM_DRAW); + CHECK_GL_ERROR(); + Vertex *buf = reinterpret_cast<Vertex*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)); + + std::vector<int> first_elements; + int last_pos = 0; + for (const Primitive& primitive: primitives) { + first_elements.push_back(last_pos); + int num = primitive.writeVertices(buf); + buf += num; + last_pos += num; + } + auto first = first_elements.begin(); + + CHECK_GL_ERROR(); + glUnmapBuffer(GL_ARRAY_BUFFER); + + // State initialization + // TODO: move that elsewhere. + CHECK_GL_ERROR(); + glEnableClientState( GL_VERTEX_ARRAY ); + CHECK_GL_ERROR(); + glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) ); + CHECK_GL_ERROR(); + glEnableClientState( GL_NORMAL_ARRAY ); + CHECK_GL_ERROR(); + glNormalPointer( GL_FLOAT , sizeof(Vertex) , reinterpret_cast<void*>(offsetof(Vertex, normal)) ); + CHECK_GL_ERROR(); + glEnableClientState( GL_TEXTURE_COORD_ARRAY ); + CHECK_GL_ERROR(); + glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) ); + + for (const Primitive& primitive: primitives) + primitive.display(nTime, WidthScale, HeightScale, *first++); + + CHECK_GL_ERROR(); + glDeleteBuffers(1, &buffer); +} + void OGLTransitionImpl::displaySlide( const double nTime, @@ -216,8 +268,7 @@ OGLTransitionImpl::displaySlide( glTranslated( 0, 2 - surfaceLevel, 0 ); glCullFace(GL_FRONT); - for(size_t i(0); i < primitives.size(); ++i) - primitives[i].display(nTime, SlideWidthScale, SlideHeightScale); + display_primitives(primitives, nTime, SlideWidthScale, SlideHeightScale); glCullFace(GL_BACK); slideShadow( nTime, primitives[0], SlideWidthScale, SlideHeightScale ); @@ -225,8 +276,7 @@ OGLTransitionImpl::displaySlide( glPopMatrix(); } - for(size_t i(0); i < primitives.size(); ++i) - primitives[i].display(nTime, SlideWidthScale, SlideHeightScale); + display_primitives(primitives, nTime, SlideWidthScale, SlideHeightScale); CHECK_GL_ERROR(); } @@ -240,7 +290,7 @@ void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double Sl CHECK_GL_ERROR(); } -void Primitive::display(double nTime, double WidthScale, double HeightScale) const +void Primitive::display(double nTime, double WidthScale, double HeightScale, int first) const { CHECK_GL_ERROR(); glPushMatrix(); @@ -249,19 +299,8 @@ void Primitive::display(double nTime, double WidthScale, double HeightScale) con applyOperations( nTime, WidthScale, HeightScale ); CHECK_GL_ERROR(); - glEnableClientState( GL_VERTEX_ARRAY ); - CHECK_GL_ERROR(); - glNormalPointer( GL_FLOAT , 0 , &Normals[0] ); - CHECK_GL_ERROR(); - glEnableClientState( GL_NORMAL_ARRAY ); - CHECK_GL_ERROR(); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - CHECK_GL_ERROR(); - glTexCoordPointer( 2, GL_FLOAT, 0, &TexCoords[0] ); - CHECK_GL_ERROR(); - glVertexPointer( 3, GL_FLOAT, 0, &Vertices[0] ); - CHECK_GL_ERROR(); - glDrawArrays( GL_TRIANGLES, 0, Vertices.size() ); + glDrawArrays( GL_TRIANGLES, first, Vertices.size() ); + CHECK_GL_ERROR(); glPopMatrix(); CHECK_GL_ERROR(); @@ -278,22 +317,19 @@ void Primitive::applyOperations(double nTime, double WidthScale, double HeightSc void SceneObject::display(double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight ) const { + // fixme: allow various model spaces, now we make it so that + // it is regular -1,-1 to 1,1, where the whole display fits in CHECK_GL_ERROR(); - for(size_t i(0); i < maPrimitives.size(); ++i) { - // fixme: allow various model spaces, now we make it so that - // it is regular -1,-1 to 1,1, where the whole display fits in - CHECK_GL_ERROR(); - glPushMatrix(); - CHECK_GL_ERROR(); - if (DispHeight > DispWidth) - glScaled(DispHeight/DispWidth, 1, 1); - else - glScaled(1, DispWidth/DispHeight, 1); - maPrimitives[i].display(nTime, 1, 1); - CHECK_GL_ERROR(); - glPopMatrix(); - CHECK_GL_ERROR(); - } + glPushMatrix(); + CHECK_GL_ERROR(); + if (DispHeight > DispWidth) + glScaled(DispHeight/DispWidth, 1, 1); + else + glScaled(1, DispWidth/DispHeight, 1); + CHECK_GL_ERROR(); + display_primitives(maPrimitives, nTime, 1, 1); + CHECK_GL_ERROR(); + glPopMatrix(); CHECK_GL_ERROR(); } @@ -1063,8 +1099,6 @@ Primitive& Primitive::operator=(const Primitive& rvalue) Primitive::Primitive(const Primitive& rvalue) : Operations(rvalue.Operations) , Vertices(rvalue.Vertices) - , Normals(rvalue.Normals) - , TexCoords(rvalue.TexCoords) { } @@ -1074,8 +1108,6 @@ void Primitive::swap(Primitive& rOther) swap(Operations, rOther.Operations); swap(Vertices, rOther.Vertices); - swap(Normals, rOther.Normals); - swap(TexCoords, rOther.TexCoords); } void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2) @@ -1108,17 +1140,9 @@ void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& Sl Verts.push_back(glm::vec3( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 )); } - Vertices.push_back(Verts[0]); - Vertices.push_back(Verts[1]); - Vertices.push_back(Verts[2]); - - TexCoords.push_back(Texs[0]); - TexCoords.push_back(Texs[1]); - TexCoords.push_back(Texs[2]); - - Normals.push_back(glm::vec3(0,0,1));//all normals always face the screen when untransformed. - Normals.push_back(glm::vec3(0,0,1));//all normals always face the screen when untransformed. - Normals.push_back(glm::vec3(0,0,1));//all normals always face the screen when untransformed. + Vertices.push_back({Verts[0], glm::vec3(0, 0, 1), Texs[0]}); //all normals always face the screen when untransformed. + Vertices.push_back({Verts[1], glm::vec3(0, 0, 1), Texs[1]}); //all normals always face the screen when untransformed. + Vertices.push_back({Verts[2], glm::vec3(0, 0, 1), Texs[2]}); //all normals always face the screen when untransformed. } namespace diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx index 37df57e86e56..972cb83a61e5 100644 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx +++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx @@ -277,6 +277,14 @@ private: GLuint maTexture; }; +struct Vertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 texcoord; +}; +static_assert(sizeof(Vertex) == (3 + 3 + 2) * 4, "Vertex struct has wrong size/alignment"); + /** This class is a list of Triangles that will share Operations, and could possibly share */ class Primitive @@ -290,7 +298,7 @@ public: void swap(Primitive& rOther); void applyOperations(double nTime, double SlideWidthScale, double SlideHeightScale) const; - void display(double nTime, double SlideWidthScale, double SlideHeightScale) const; + void display(double nTime, double SlideWidthScale, double SlideHeightScale, int first) const; /** PushBack a vertex,normal, and tex coord. Each SlideLocation is where on the slide is mapped to this location ( from (0,0) to (1,1) ). This will make sure the correct aspect ratio is used, and helps to make slides begin and end at the correct position. (0,0) is the top left of the slide, and (1,1) is the bottom right. @@ -311,7 +319,24 @@ public: @return the list of vertices */ - const glm::vec3& getVertex(int n) const {return Vertices[n];} + const glm::vec3& getVertex(int n) const {return Vertices[n].position;} + + /** accessor for the size of the vertices data + + @return + the size in bytes of the Vertices data + */ + int getVerticesSize() const {return Vertices.size() * sizeof(Vertex);} + + /** copies all vertices to the C array passed + + @return + the number of written vertices + */ + int writeVertices(Vertex *location) const { + std::copy(Vertices.begin(), Vertices.end(), location); + return Vertices.size(); + } /** list of Operations to be performed on this primitive.These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back. @@ -324,15 +349,7 @@ public: private: /** list of vertices */ - std::vector<glm::vec3> Vertices; - - /** list of Normals - */ - std::vector<glm::vec3> Normals; - - /** list of Texture Coordinates - */ - std::vector<glm::vec2> TexCoords; + std::vector<Vertex> Vertices; }; /** This class is to be derived to make any operation (transform) you may need in order to construct your transitions |