2525#include " pxr/pxr.h"
2626#include " pxr/base/tf/pxrCLI11/CLI11.h"
2727#include " pxr/base/tf/exception.h"
28+ #include " pxr/base/tf/scoped.h"
2829#include " pxr/base/tf/stringUtils.h"
2930#include " pxr/usd/sdf/layer.h"
3031#include " pxr/usd/sdf/fileFormat.h"
5051
5152PXR_NAMESPACE_USING_DIRECTIVE
5253
54+ #if PXR_USE_GLFW
55+ class GLFWOpenGLContext ;
56+ using GLFWOpenGLContextPtr = std::unique_ptr<GLFWOpenGLContext>;
57+
58+ // RAII wrapper around the GLFW resources. Not currently safe for multiple uses in other tools
59+ // would need to be a singleton wrapper around the init/terminate, with a call to serve up
60+ // managed windows/contexts.
61+ class GLFWOpenGLContext
62+ {
63+ GLFWOpenGLContext () {};
64+
65+ GLFWOpenGLContext (const GLFWOpenGLContext&) = delete ;
66+ GLFWOpenGLContext &operator =(const GLFWOpenGLContext&) = delete ;
67+
68+ public:
69+ ~GLFWOpenGLContext () {
70+ glfwTerminate ();
71+ };
72+
73+ static GLFWOpenGLContextPtr create (unsigned int imageWidth, unsigned int imageHeight) {
74+ if (!glfwInit ())
75+ return nullptr ;
76+
77+ GLFWOpenGLContextPtr contextPtr = std::unique_ptr<GLFWOpenGLContext>(new GLFWOpenGLContext ());
78+
79+ glfwWindowHint (GLFW_VISIBLE, GLFW_FALSE);
80+
81+ // Create a windowed mode window and its OpenGL context
82+ GLFWwindow* window = glfwCreateWindow (imageWidth, imageWidth, " no title" , NULL , NULL );
83+ if (!window) {
84+ return nullptr ;
85+ }
86+
87+ // Make the window's context current
88+ glfwMakeContextCurrent (window);
89+
90+ return contextPtr;
91+ }
92+ };
93+ #endif
94+
95+
5396using namespace pxr_CLI ;
5497
5598struct Args {
@@ -611,30 +654,11 @@ static int32_t UsdRecord(const Args &args) {
611654 // NOTE - this isn't required when we use Metal, but if we want to pass this code back to pixar we may need to reintroduce this
612655 // and test on other platforms.
613656#if PXR_USE_GLFW
657+ GLFWOpenGLContextPtr glContext = nullptr ;
614658 if (gpuEnabled) {
615- // UsdAppUtilsFrameRecorder will expect that an OpenGL context has
616- // been created and made current if the GPU is enabled.
617- //
618- // Frame-independent initialization.
619- // Note that the size of the widget doesn't actually affect the size of
620- // the output image. We just pass it along for cleanliness.
621-
622- // Initialize the library
623- if (!glfwInit ())
624- return -1 ;
625-
626- glfwWindowHint (GLFW_VISIBLE, GLFW_FALSE);
627-
628- // Create a windowed mode window and its OpenGL context
629- GLFWwindow* window = glfwCreateWindow (args.imageWidth , args.imageWidth , " usdrecord" , NULL , NULL );
630- if (!window)
631- {
632- glfwTerminate ();
659+ glContext = GLFWOpenGLContext::create (args.imageWidth , args.imageWidth );
660+ if (!glContext)
633661 return -1 ;
634- }
635-
636- // Make the window's context current
637- glfwMakeContextCurrent (window);
638662 }
639663#endif
640664
@@ -681,7 +705,7 @@ static int32_t UsdRecord(const Args &args) {
681705
682706 try {
683707 frameRecorder->Record (usdStage, usdCamera, timeCode, outputImagePath);
684- } catch (TfBaseException e) {
708+ } catch (const TfBaseException& e) {
685709 std::cerr << " Recording aborted due to the following failure at time code " << timeCode << " : "
686710 << e.what () << std::endl;
687711 return 1 ;
@@ -691,10 +715,6 @@ static int32_t UsdRecord(const Args &args) {
691715 // Release our reference to the frame recorder so it can be deleted before other resources are freed
692716 frameRecorder = nullptr ;
693717
694- #if PXR_USE_GLFW
695- glfwTerminate ();
696- #endif
697-
698718 return 0 ;
699719}
700720
0 commit comments