comparison Framework/Scene2D/Internals/OpenGLLinesProgram.cpp @ 947:1091b2adeb5a toa2019081001

Fixed animation frame stopping when returning false + big work on the OpenGL objects to make them lost context-safe + debug code to forcefully tag a context as lost + debug macros
author Benjamin Golinvaux <bgo@osimis.io>
date Sat, 10 Aug 2019 13:07:31 +0200
parents 61ba4b504e9a
children a7351ad54960
comparison
equal deleted inserted replaced
946:dbe3e1e47019 947:1091b2adeb5a
261 const PolylineSceneLayer& layer) : 261 const PolylineSceneLayer& layer) :
262 context_(context), 262 context_(context),
263 verticesCount_(0), 263 verticesCount_(0),
264 thickness_(static_cast<float>(layer.GetThickness())) 264 thickness_(static_cast<float>(layer.GetThickness()))
265 { 265 {
266 // High-level reference: 266 if (!context_.IsContextLost())
267 // https://mattdesl.svbtle.com/drawing-lines-is-hard 267 {
268 // https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader 268 // High-level reference:
269 269 // https://mattdesl.svbtle.com/drawing-lines-is-hard
270 size_t countVertices = 0; 270 // https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
271 for (size_t i = 0; i < layer.GetChainsCount(); i++) 271
272 { 272 size_t countVertices = 0;
273 size_t countSegments = layer.GetChain(i).size() - 1; 273 for (size_t i = 0; i < layer.GetChainsCount(); i++)
274 274 {
275 if (layer.IsClosedChain(i)) 275 size_t countSegments = layer.GetChain(i).size() - 1;
276 {
277 countSegments++;
278 }
279
280 // Each segment is made of 2 triangles. One triangle is
281 // defined by 3 points in 2D => 6 vertices per segment.
282 countVertices += countSegments * 2 * 3;
283 }
284
285 std::vector<float> coords, colors, miterDirections;
286 coords.reserve(countVertices * COMPONENTS_POSITION);
287 colors.reserve(countVertices * COMPONENTS_COLOR);
288 miterDirections.reserve(countVertices * COMPONENTS_MITER);
289
290 for (size_t i = 0; i < layer.GetChainsCount(); i++)
291 {
292 const PolylineSceneLayer::Chain& chain = layer.GetChain(i);
293
294 if (chain.size() > 1)
295 {
296 std::vector<Segment> segments;
297 for (size_t j = 1; j < chain.size(); j++)
298 {
299 segments.push_back(Segment(chain, j - 1, j));
300 }
301 276
302 if (layer.IsClosedChain(i)) 277 if (layer.IsClosedChain(i))
303 { 278 {
304 segments.push_back(Segment(chain, chain.size() - 1, 0)); 279 countSegments++;
305 } 280 }
306 281
307 // Try and create nice miters 282 // Each segment is made of 2 triangles. One triangle is
308 for (size_t j = 1; j < segments.size(); j++) 283 // defined by 3 points in 2D => 6 vertices per segment.
309 { 284 countVertices += countSegments * 2 * 3;
310 Segment::CreateMiter(segments[j - 1], segments[j]); 285 }
311 } 286
312 287 std::vector<float> coords, colors, miterDirections;
313 if (layer.IsClosedChain(i)) 288 coords.reserve(countVertices * COMPONENTS_POSITION);
314 { 289 colors.reserve(countVertices * COMPONENTS_COLOR);
315 Segment::CreateMiter(segments.back(), segments.front()); 290 miterDirections.reserve(countVertices * COMPONENTS_MITER);
316 } 291
317 292 for (size_t i = 0; i < layer.GetChainsCount(); i++)
318 for (size_t j = 0; j < segments.size(); j++) 293 {
319 { 294 const PolylineSceneLayer::Chain& chain = layer.GetChain(i);
320 if (!segments[j].IsEmpty()) 295
296 if (chain.size() > 1)
297 {
298 std::vector<Segment> segments;
299 for (size_t j = 1; j < chain.size(); j++)
321 { 300 {
322 segments[j].AddTriangles(coords, miterDirections, colors, layer.GetColor(i)); 301 segments.push_back(Segment(chain, j - 1, j));
323 } 302 }
324 } 303
325 } 304 if (layer.IsClosedChain(i))
326 } 305 {
327 306 segments.push_back(Segment(chain, chain.size() - 1, 0));
328 assert(coords.size() == colors.size()); 307 }
329 308
330 if (!coords.empty()) 309 // Try and create nice miters
331 { 310 for (size_t j = 1; j < segments.size(); j++)
332 verticesCount_ = coords.size() / COMPONENTS_POSITION; 311 {
333 312 Segment::CreateMiter(segments[j - 1], segments[j]);
334 context_.MakeCurrent(); 313 }
335 glGenBuffers(3, buffers_); 314
336 315 if (layer.IsClosedChain(i))
337 glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]); 316 {
338 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW); 317 Segment::CreateMiter(segments.back(), segments.front());
339 318 }
340 glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]); 319
341 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW); 320 for (size_t j = 0; j < segments.size(); j++)
342 321 {
343 glBindBuffer(GL_ARRAY_BUFFER, buffers_[2]); 322 if (!segments[j].IsEmpty())
344 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size(), &colors[0], GL_STATIC_DRAW); 323 {
324 segments[j].AddTriangles(coords, miterDirections, colors, layer.GetColor(i));
325 }
326 }
327 }
328 }
329
330 assert(coords.size() == colors.size());
331
332 if (!coords.empty())
333 {
334 verticesCount_ = coords.size() / COMPONENTS_POSITION;
335
336 context_.MakeCurrent();
337 glGenBuffers(3, buffers_);
338
339 glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]);
340 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW);
341
342 glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]);
343 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW);
344
345 glBindBuffer(GL_ARRAY_BUFFER, buffers_[2]);
346 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size(), &colors[0], GL_STATIC_DRAW);
347 }
345 } 348 }
346 } 349 }
347 350
348 351
349 OpenGLLinesProgram::Data::~Data() 352 OpenGLLinesProgram::Data::~Data()
350 { 353 {
351 if (!IsEmpty()) 354 if (!context_.IsContextLost() && !IsEmpty())
352 { 355 {
353 context_.MakeCurrent(); 356 context_.MakeCurrent();
357 ORTHANC_OPENGL_TRACE_CURRENT_CONTEXT("About to call glDeleteBuffers");
354 glDeleteBuffers(3, buffers_); 358 glDeleteBuffers(3, buffers_);
355 } 359 }
356 } 360 }
357
358 361
359 GLuint OpenGLLinesProgram::Data::GetVerticesBuffer() const 362 GLuint OpenGLLinesProgram::Data::GetVerticesBuffer() const
360 { 363 {
361 if (IsEmpty()) 364 if (IsEmpty())
362 { 365 {
396 399
397 400
398 OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext& context) : 401 OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext& context) :
399 context_(context) 402 context_(context)
400 { 403 {
401 context_.MakeCurrent(); 404 if (!context_.IsContextLost())
402 405 {
403 program_.reset(new OpenGL::OpenGLProgram); 406 context_.MakeCurrent();
404 program_->CompileShaders(VERTEX_SHADER, FRAGMENT_SHADER); 407 program_.reset(new OpenGL::OpenGLProgram(context_));
405 } 408 program_->CompileShaders(VERTEX_SHADER, FRAGMENT_SHADER);
406 409 }
410 }
407 411
408 void OpenGLLinesProgram::Apply(const Data& data, 412 void OpenGLLinesProgram::Apply(const Data& data,
409 const AffineTransform2D& transform, 413 const AffineTransform2D& transform,
410 bool antialiasing, 414 bool antialiasing,
411 bool scaleIndependantThickness) 415 bool scaleIndependantThickness)
412 { 416 {
413 if (!data.IsEmpty()) 417 if (!context_.IsContextLost() && !data.IsEmpty())
414 { 418 {
415 context_.MakeCurrent(); 419 context_.MakeCurrent();
416 program_->Use(); 420 program_->Use();
417 421
418 GLint locationPosition = program_->GetAttributeLocation("a_position"); 422 GLint locationPosition = program_->GetAttributeLocation("a_position");