1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/pxr.h"
25 
26 #include "pxr/imaging/garch/glApi.h"
27 
28 #include "pxr/usdImaging/usdImagingGL/unitTestGLDrawing.h"
29 #include "pxr/imaging/glf/contextCaps.h"
30 #include "pxr/imaging/glf/diagnostic.h"
31 #include "pxr/imaging/glf/drawTarget.h"
32 #include "pxr/imaging/garch/glDebugWindow.h"
33 
34 #include "pxr/base/arch/attributes.h"
35 #include "pxr/base/gf/vec2i.h"
36 #include "pxr/base/trace/collector.h"
37 #include "pxr/base/trace/reporter.h"
38 
39 #include "pxr/base/plug/registry.h"
40 #include "pxr/base/arch/systemInfo.h"
41 
42 #include <stdio.h>
43 #include <stdarg.h>
44 
45 #include <fstream>
46 
47 PXR_NAMESPACE_OPEN_SCOPE
48 
49 
UsdImagingGL_UnitTestHelper_InitPlugins()50 static void UsdImagingGL_UnitTestHelper_InitPlugins()
51 {
52     // Unfortunately, in order to properly find plugins in our test setup, we
53     // need to know where the test is running.
54     std::string testDir = TfGetPathName(ArchGetExecutablePath());
55     std::string pluginDir = TfStringCatPaths(testDir,
56             "UsdImagingPlugins/lib/UsdImagingTest.framework/Resources");
57     printf("registering plugins in: %s\n", pluginDir.c_str());
58 
59     PlugRegistry::GetInstance().RegisterPlugins(pluginDir);
60 }
61 
62 ////////////////////////////////////////////////////////////
63 
64 class UsdImagingGL_UnitTestWindow : public GarchGLDebugWindow {
65 public:
66     typedef UsdImagingGL_UnitTestWindow This;
67 
68 public:
69     UsdImagingGL_UnitTestWindow(UsdImagingGL_UnitTestGLDrawing * unitTest,
70                                 int w, int h);
71     virtual ~UsdImagingGL_UnitTestWindow();
72 
73     void DrawOffscreen();
74 
75     bool WriteToFile(std::string const & attachment,
76                      std::string const & filename);
77 
78     // GarchGLDebugWIndow overrides;
79     virtual void OnInitializeGL();
80     virtual void OnUninitializeGL();
81     virtual void OnPaintGL();
82     virtual void OnKeyRelease(int key);
83     virtual void OnMousePress(int button, int x, int y, int modKeys);
84     virtual void OnMouseRelease(int button, int x, int y, int modKeys);
85     virtual void OnMouseMove(int x, int y, int modKeys);
86 
87 private:
88     UsdImagingGL_UnitTestGLDrawing *_unitTest;
89     GlfDrawTargetRefPtr _drawTarget;
90 };
91 
UsdImagingGL_UnitTestWindow(UsdImagingGL_UnitTestGLDrawing * unitTest,int w,int h)92 UsdImagingGL_UnitTestWindow::UsdImagingGL_UnitTestWindow(
93     UsdImagingGL_UnitTestGLDrawing * unitTest, int w, int h)
94     : GarchGLDebugWindow("UsdImagingGL Test", w, h)
95     , _unitTest(unitTest)
96 {
97 }
98 
~UsdImagingGL_UnitTestWindow()99 UsdImagingGL_UnitTestWindow::~UsdImagingGL_UnitTestWindow()
100 {
101 }
102 
103 /* virtual */
104 void
OnInitializeGL()105 UsdImagingGL_UnitTestWindow::OnInitializeGL()
106 {
107     GarchGLApiLoad();
108     GlfRegisterDefaultDebugOutputMessageCallback();
109     GlfContextCaps::InitInstance();
110 
111 
112     //
113     // Create an offscreen draw target which is the same size as this
114     // widget and initialize the unit test with the draw target bound.
115     //
116     _drawTarget = GlfDrawTarget::New(GfVec2i(GetWidth(), GetHeight()));
117     _drawTarget->Bind();
118     _drawTarget->AddAttachment("color", GL_RGBA, GL_FLOAT, GL_RGBA);
119     _drawTarget->AddAttachment("depth", GL_DEPTH_COMPONENT, GL_FLOAT,
120                                         GL_DEPTH_COMPONENT);
121 
122     _unitTest->InitTest();
123 
124     _drawTarget->Unbind();
125 }
126 
127 /* virtual */
128 void
OnUninitializeGL()129 UsdImagingGL_UnitTestWindow::OnUninitializeGL()
130 {
131     _drawTarget = GlfDrawTargetRefPtr();
132 
133     _unitTest->ShutdownTest();
134 }
135 
136 /* virtual */
137 void
OnPaintGL()138 UsdImagingGL_UnitTestWindow::OnPaintGL()
139 {
140     //
141     // Update the draw target's size and execute the unit test with
142     // the draw target bound.
143     //
144     int width = GetWidth();
145     int height = GetHeight();
146     _drawTarget->Bind();
147     _drawTarget->SetSize(GfVec2i(width, height));
148 
149     _unitTest->DrawTest(false);
150 
151     _drawTarget->Unbind();
152 
153     //
154     // Blit the resulting color buffer to the window (this is a noop
155     // if we're drawing offscreen).
156     //
157     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
158     glBindFramebuffer(GL_READ_FRAMEBUFFER, _drawTarget->GetFramebufferId());
159 
160     glBlitFramebuffer(0, 0, width, height,
161                       0, 0, width, height,
162                       GL_COLOR_BUFFER_BIT,
163                       GL_NEAREST);
164 
165     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
166     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
167 }
168 
169 void
DrawOffscreen()170 UsdImagingGL_UnitTestWindow::DrawOffscreen()
171 {
172     _drawTarget->Bind();
173     _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight()));
174 
175     _unitTest->DrawTest(true);
176 
177     _drawTarget->Unbind();
178 }
179 
180 bool
WriteToFile(std::string const & attachment,std::string const & filename)181 UsdImagingGL_UnitTestWindow::WriteToFile(std::string const & attachment,
182         std::string const & filename)
183 {
184     // We need to unbind the draw target before writing to file to be sure the
185     // attachment is in a good state.
186     bool isBound = _drawTarget->IsBound();
187     if (isBound)
188         _drawTarget->Unbind();
189 
190     bool result = _drawTarget->WriteToFile(attachment, filename);
191 
192     if (isBound)
193         _drawTarget->Bind();
194     return result;
195 }
196 
197 /* virtual */
198 void
OnKeyRelease(int key)199 UsdImagingGL_UnitTestWindow::OnKeyRelease(int key)
200 {
201     switch (key) {
202     case 'q':
203         ExitApp();
204         return;
205     }
206     _unitTest->KeyRelease(key);
207 }
208 
209 /* virtual */
210 void
OnMousePress(int button,int x,int y,int modKeys)211 UsdImagingGL_UnitTestWindow::OnMousePress(int button,
212                                           int x, int y, int modKeys)
213 {
214     _unitTest->MousePress(button, x, y, modKeys);
215 }
216 
217 /* virtual */
218 void
OnMouseRelease(int button,int x,int y,int modKeys)219 UsdImagingGL_UnitTestWindow::OnMouseRelease(int button,
220                                             int x, int y, int modKeys)
221 {
222     _unitTest->MouseRelease(button, x, y, modKeys);
223 }
224 
225 /* virtual */
226 void
OnMouseMove(int x,int y,int modKeys)227 UsdImagingGL_UnitTestWindow::OnMouseMove(int x, int y, int modKeys)
228 {
229     _unitTest->MouseMove(x, y, modKeys);
230 }
231 
232 ////////////////////////////////////////////////////////////
233 
UsdImagingGL_UnitTestGLDrawing()234 UsdImagingGL_UnitTestGLDrawing::UsdImagingGL_UnitTestGLDrawing()
235     : _widget(NULL)
236     , _testLighting(false)
237     , _sceneLights(false)
238     , _cameraLight(false)
239     , _testIdRender(false)
240     , _enableSceneMaterials(true)
241     , _complexity(1.0f)
242     , _drawMode(UsdImagingGLDrawMode::DRAW_SHADED_SMOOTH)
243     , _shouldFrameAll(false)
244     , _cullStyle(UsdImagingGLCullStyle::CULL_STYLE_NOTHING)
245     , _showGuides(UsdImagingGLRenderParams().showGuides)
246     , _showRender(UsdImagingGLRenderParams().showRender)
247     , _showProxy(UsdImagingGLRenderParams().showProxy)
248     , _clearOnce(false)
249     , _presentDisabled(false)
250 {
251 }
252 
~UsdImagingGL_UnitTestGLDrawing()253 UsdImagingGL_UnitTestGLDrawing::~UsdImagingGL_UnitTestGLDrawing()
254 {
255 }
256 
257 int
GetWidth() const258 UsdImagingGL_UnitTestGLDrawing::GetWidth() const
259 {
260     return _widget->GetWidth();
261 }
262 
263 int
GetHeight() const264 UsdImagingGL_UnitTestGLDrawing::GetHeight() const
265 {
266     return _widget->GetHeight();
267 }
268 
269 bool
WriteToFile(std::string const & attachment,std::string const & filename) const270 UsdImagingGL_UnitTestGLDrawing::WriteToFile(std::string const & attachment,
271         std::string const & filename) const
272 {
273     return _widget->WriteToFile(attachment, filename);
274 }
275 
276 struct UsdImagingGL_UnitTestGLDrawing::_Args {
_ArgsUsdImagingGL_UnitTestGLDrawing::_Args277     _Args()
278       : offscreen(false)
279       , clearColor{1.0f, 0.5f, 0.1f, 1.0f}
280       , translate{0.0f, -1000.0f, -2500.0f}
281       , widgetSize{640, 480}
282       , pixelAspectRatio(1.0f)
283       , dataWindow{0, 0, 0, 0}
284       , displayWindow{0.0f, 0.0f, 0.0f, 0.0f}
285     {
286     }
287 
288     std::string unresolvedStageFilePath;
289     bool offscreen;
290     std::string shading;
291     std::string cullStyle;
292     std::vector<double> clipPlaneCoords;
293     std::vector<double> complexities;
294     float clearColor[4];
295     float translate[3];
296     int widgetSize[2];
297     float pixelAspectRatio;
298     int dataWindow[4];
299     float displayWindow[4];
300 };
301 
302 static void Die(const char* fmt, ...) ARCH_PRINTF_FUNCTION(1, 2);
Die(const char * fmt,...)303 static void Die(const char* fmt, ...)
304 {
305     va_list ap;
306     va_start(ap, fmt);
307     vfprintf(stderr, fmt, ap);
308     va_end(ap);
309     fflush(stderr);
310     exit(1);
311 }
312 
313 static void
314 ParseError(const char* pname, const char* fmt, ...) ARCH_PRINTF_FUNCTION(2, 3);
315 static void
ParseError(const char * pname,const char * fmt,...)316 ParseError(const char* pname, const char* fmt, ...)
317 {
318     fprintf(stderr, "%s: ", TfGetBaseName(pname).c_str());
319     va_list ap;
320     va_start(ap, fmt);
321     vfprintf(stderr, fmt, ap);
322     va_end(ap);
323     fprintf(stderr, ".  Try '%s -' for help.\n", TfGetBaseName(pname).c_str());
324     fflush(stderr);
325     exit(1);
326 }
327 
Usage(int argc,char * argv[])328 static void Usage(int argc, char *argv[])
329 {
330     static const char usage[] =
331 "%s [-stage filePath] [-write filePath]\n"
332 "                           [-offscreen] [-lighting] [-idRender]\n"
333 "                           [-disableSceneMaterials]\n"
334 "                           [-camera pathToCamera]\n"
335 "                           [-complexity complexity]\n"
336 "                           [-renderer rendererName]\n"
337 "                           [-shading [flat|smooth|wire|wireOnSurface|points]]\n"
338 "                           [-frameAll]\n"
339 "                           [-clipPlane clipPlane1 ... clipPlane4]\n"
340 "                           [-complexities complexities1 complexities2 ...]\n"
341 "                           [-times times1 times2 ...] [-cullStyle cullStyle]\n"
342 "                           [-clear r g b a] [-clearOnce] [-translate x y z]\n"
343 "                           [-renderSetting name type value]\n"
344 "                           [-rendererAov name]\n"
345 "                           [-perfStatsFile path]\n"
346 "                           [-traceFile path] [...]\n"
347 "\n"
348 "  usdImaging basic drawing test\n"
349 "\n"
350 "options:\n"
351 "  -stage filePath     name of usd stage to open []\n"
352 "  -write filePath     name of image file to write (suffix determines type) []\n"
353 "  -offscreen          execute without mapping a window\n"
354 "  -lighting           use simple lighting override shader\n"
355 "  -sceneLights        use in combination with -lighting to utilize the lights \n"
356 "                      defined in the scene\n"
357 "  -camLight           use a single camera light\n"
358 "  -idRender           ID rendering\n"
359 "  -disableSceneMaterials\n"
360 "                      Disable scene materials\n"
361 "  -complexity complexity\n"
362 "                      Set the fallback complexity [1]\n"
363 "  -renderer rendererName\n"
364 "                      use the specified renderer plugin []\n"
365 "  -shading [flat|smooth|wire|wireOnSurface]\n"
366 "                      force specific type of shading\n"
367 "                      [flat|smooth|wire|wireOnSurface|points] []\n"
368 "  -frameAll           set the view to frame all root prims on the stage\n"
369 "  -clipPlane clipPlane1 ... clipPlane4\n"
370 "                      set an additional camera clipping plane [()]\n"
371 "  -complexities complexities1 complexities2 ...\n"
372 "                      One or more complexities, each complexity will\n"
373 "                      produce an image [()]\n"
374 "  -times times1 times2 ...\n"
375 "                      One or more time samples, each time will produce\n"
376 "                      an image [()]\n"
377 "  -cullStyle          Set face cull style\n"
378 "  -clear r g b a      clear color\n"
379 "  -clearOnce          Clear the framebuffer only once at the start \n"
380 "                      instead of before each render.\n"
381 "  -translate x y z    default camera translation\n"
382 "  -rendererAov name   Name of AOV to display or write out\n"
383 "  -perfStatsFile path Path to file performance stats are written to\n"
384 "  -traceFile path     Path to trace file to write\n"
385 "  -renderSetting name type value\n"
386 "                      Specifies a setting with given name, type (such as\n"
387 "                      float) and value passed to renderer. -renderSetting\n"
388 "                      can be given multiple times to specify different\n"
389 "                      settings\n"
390 "  -guidesPurpose [show|hide]\n"
391 "                      force prims of purpose 'guide' to be shown or hidden\n"
392 "  -renderPurpose [show|hide]\n"
393 "                      force prims of purpose 'render' to be shown or hidden\n"
394 "  -proxyPurpose [show|hide]\n"
395 "                      force prims of purpose 'proxy' to be shown or hidden\n"
396 "  -widgetSize w h     width and height of widget and render buffers\n"
397 "  -pixelAspectRatio a\n"
398 "                      width of pixel divided by height of pixel\n"
399 "  -dataWindow x y width height\n"
400 "                      Specifies data window for rendering\n"
401 "  -displayWindow x y width height\n"
402 "                      Specifies display window for rendering\n"
403 ;
404 
405     Die(usage, TfGetBaseName(argv[0]).c_str());
406 }
407 
CheckForMissingArguments(int i,int n,int argc,char * argv[])408 static void CheckForMissingArguments(int i, int n, int argc, char *argv[])
409 {
410     if (i + n >= argc) {
411         if (n == 1) {
412             ParseError(argv[0], "missing parameter for '%s'", argv[i]);
413         }
414         else {
415             ParseError(argv[0], "argument '%s' requires %d values", argv[i], n);
416         }
417     }
418 }
419 
ParseDouble(int & i,int argc,char * argv[],bool * invalid=nullptr)420 static double ParseDouble(int& i, int argc, char *argv[],
421                           bool* invalid = nullptr)
422 {
423     if (i + 1 == argc) {
424         if (invalid) {
425             *invalid = true;
426             return 0.0;
427         }
428         ParseError(argv[0], "missing parameter for '%s'", argv[i]);
429     }
430     char* end;
431     double result = strtod(argv[i + 1], &end);
432     if (end == argv[i + 1] || *end != '\0') {
433         if (invalid) {
434             *invalid = true;
435             return 0.0;
436         }
437         ParseError(argv[0], "invalid parameter for '%s': %s",
438                    argv[i], argv[i + 1]);
439     }
440     ++i;
441     if (invalid) {
442         *invalid = false;
443     }
444     return result;
445 }
446 
ParseShowHide(int & i,int argc,char * argv[],bool * result)447 static bool ParseShowHide(int& i, int argc, char *argv[],
448                           bool* result)
449 {
450     if (i + 1 == argc) {
451         ParseError(argv[0], "missing parameter for '%s'", argv[i]);
452         return false;
453     }
454     if (strcmp(argv[i + 1], "show") == 0) {
455         *result = true;
456     } else if (strcmp(argv[i + 1], "hide") == 0) {
457         *result = false;
458     } else {
459         ParseError(argv[0], "invalid parameter for '%s': %s. Must be either "
460                             "'show' or 'hide'",
461                    argv[i], argv[i + 1]);
462         return false;
463     }
464 
465     ++i;
466     return true;
467 }
468 
ParseString(int & i,int argc,char * argv[],bool * invalid=nullptr)469 static const char * ParseString(int &i, int argc, char *argv[],
470                                 bool* invalid = nullptr)
471 {
472     if (i + 1 == argc) {
473         if (invalid) {
474             *invalid = true;
475             return nullptr;
476         }
477         ParseError(argv[0], "missing parameter for '%s'", argv[i]);
478     }
479     const char * const result = argv[i + 1];
480     ++i;
481     if (invalid) {
482         *invalid = false;
483     }
484     return result;
485 }
486 
487 static void
ParseDoubleVector(int & i,int argc,char * argv[],std::vector<double> * result)488 ParseDoubleVector(
489     int& i, int argc, char *argv[],
490     std::vector<double>* result)
491 {
492     bool invalid = false;
493     while (i != argc) {
494         const double value = ParseDouble(i, argc, argv, &invalid);
495         if (invalid) {
496             break;
497         }
498         result->push_back(value);
499     }
500 }
501 
ParseVtValue(int & i,int argc,char * argv[])502 static VtValue ParseVtValue(int &i, int argc, char *argv[])
503 {
504     const char * const typeString = ParseString(i, argc, argv);
505 
506     if (strcmp(typeString, "float") == 0) {
507         CheckForMissingArguments(i, 1, argc, argv);
508         return VtValue(float(ParseDouble(i, argc, argv)));
509     } else {
510         ParseError(argv[0], "unknown type '%s'", typeString);
511         return VtValue();
512     }
513 }
514 
515 void
_Parse(int argc,char * argv[],_Args * args)516 UsdImagingGL_UnitTestGLDrawing::_Parse(int argc, char *argv[], _Args* args)
517 {
518     for (int i = 1; i != argc; ++i) {
519         if (strcmp(argv[i], "-") == 0) {
520             Usage(argc, argv);
521         }
522         else if (strcmp(argv[i], "-frameAll") == 0) {
523             _shouldFrameAll = true;
524         }
525         else if (strcmp(argv[i], "-cullStyle") == 0) {
526             CheckForMissingArguments(i, 1, argc, argv);
527             args->cullStyle = argv[++i];
528         }
529         else if (strcmp(argv[i], "-offscreen") == 0) {
530             args->offscreen = true;
531         }
532         else if (strcmp(argv[i], "-lighting") == 0) {
533             _testLighting = true;
534         }
535         else if (strcmp(argv[i], "-sceneLights") == 0) {
536             _sceneLights = true;
537         }
538         else if (strcmp(argv[i], "-camlight") == 0) {
539             _cameraLight = true;
540         }
541         else if (strcmp(argv[i], "-camera") == 0) {
542             CheckForMissingArguments(i, 1, argc, argv);
543             _cameraPath = argv[++i];
544         }
545         else if (strcmp(argv[i], "-idRender") == 0) {
546             _testIdRender = true;
547         }
548         else if (strcmp(argv[i], "-disableSceneMaterials") == 0) {
549             _enableSceneMaterials = false;
550         }
551         else if (strcmp(argv[i], "-stage") == 0) {
552             CheckForMissingArguments(i, 1, argc, argv);
553             args->unresolvedStageFilePath = argv[++i];
554         }
555         else if (strcmp(argv[i], "-write") == 0) {
556             CheckForMissingArguments(i, 1, argc, argv);
557             _outputFilePath = argv[++i];
558         }
559         else if (strcmp(argv[i], "-shading") == 0) {
560             CheckForMissingArguments(i, 1, argc, argv);
561             args->shading = argv[++i];
562         }
563         else if (strcmp(argv[i], "-complexity") == 0) {
564             CheckForMissingArguments(i, 1, argc, argv);
565             _complexity = ParseDouble(i, argc, argv);
566         }
567         else if (strcmp(argv[i], "-renderer") == 0) {
568             CheckForMissingArguments(i, 1, argc, argv);
569             _renderer = TfToken(argv[++i]);
570         }
571         else if (strcmp(argv[i], "-rendererAov") == 0) {
572             CheckForMissingArguments(i, 1, argc, argv);
573             _rendererAov = TfToken(argv[++i]);
574         }
575         else if (strcmp(argv[i], "-perfStatsFile") == 0) {
576             CheckForMissingArguments(i, 1, argc, argv);
577             _perfStatsFile = argv[++i];
578         }
579         else if (strcmp(argv[i], "-traceFile") == 0) {
580             CheckForMissingArguments(i, 1, argc, argv);
581             _traceFile = argv[++i];
582         }
583         else if (strcmp(argv[i], "-clipPlane") == 0) {
584             CheckForMissingArguments(i, 4, argc, argv);
585             args->clipPlaneCoords.push_back(ParseDouble(i, argc, argv));
586             args->clipPlaneCoords.push_back(ParseDouble(i, argc, argv));
587             args->clipPlaneCoords.push_back(ParseDouble(i, argc, argv));
588             args->clipPlaneCoords.push_back(ParseDouble(i, argc, argv));
589         }
590         else if (strcmp(argv[i], "-complexities") == 0) {
591             ParseDoubleVector(i, argc, argv, &args->complexities);
592         }
593         else if (strcmp(argv[i], "-times") == 0) {
594             ParseDoubleVector(i, argc, argv, &_times);
595         }
596         else if (strcmp(argv[i], "-clear") == 0) {
597             CheckForMissingArguments(i, 4, argc, argv);
598             args->clearColor[0] = (float)ParseDouble(i, argc, argv);
599             args->clearColor[1] = (float)ParseDouble(i, argc, argv);
600             args->clearColor[2] = (float)ParseDouble(i, argc, argv);
601             args->clearColor[3] = (float)ParseDouble(i, argc, argv);
602         }
603         else if (strcmp(argv[i], "-translate") == 0) {
604             CheckForMissingArguments(i, 3, argc, argv);
605             args->translate[0] = (float)ParseDouble(i, argc, argv);
606             args->translate[1] = (float)ParseDouble(i, argc, argv);
607             args->translate[2] = (float)ParseDouble(i, argc, argv);
608         }
609         else if (strcmp(argv[i], "-widgetSize") == 0) {
610             CheckForMissingArguments(i, 2, argc, argv);
611             args->widgetSize[0] = (int)ParseDouble(i, argc, argv);
612             args->widgetSize[1] = (int)ParseDouble(i, argc, argv);
613         }
614         else if (strcmp(argv[i], "-pixelAspectRatio") == 0) {
615             CheckForMissingArguments(i, 1, argc, argv);
616             args->pixelAspectRatio = (float)ParseDouble(i, argc, argv);
617         }
618         else if (strcmp(argv[i], "-dataWindow") == 0) {
619             CheckForMissingArguments(i, 4, argc, argv);
620             args->dataWindow[0] = (int)ParseDouble(i, argc, argv);
621             args->dataWindow[1] = (int)ParseDouble(i, argc, argv);
622             args->dataWindow[2] = (int)ParseDouble(i, argc, argv);
623             args->dataWindow[3] = (int)ParseDouble(i, argc, argv);
624         }
625         else if (strcmp(argv[i], "-displayWindow") == 0) {
626             CheckForMissingArguments(i, 4, argc, argv);
627             args->displayWindow[0] = (float)ParseDouble(i, argc, argv);
628             args->displayWindow[1] = (float)ParseDouble(i, argc, argv);
629             args->displayWindow[2] = (float)ParseDouble(i, argc, argv);
630             args->displayWindow[3] = (float)ParseDouble(i, argc, argv);
631         }
632         else if (strcmp(argv[i], "-renderSetting") == 0) {
633             CheckForMissingArguments(i, 2, argc, argv);
634             const char * const key = ParseString(i, argc, argv);
635             _renderSettings[key] = ParseVtValue(i, argc, argv);
636         }
637         else if (strcmp(argv[i], "-guidesPurpose") == 0) {
638             ParseShowHide(i, argc, argv, &_showGuides);
639         }
640         else if (strcmp(argv[i], "-renderPurpose") == 0) {
641             ParseShowHide(i, argc, argv, &_showRender);
642         }
643         else if (strcmp(argv[i], "-proxyPurpose") == 0) {
644             ParseShowHide(i, argc, argv, &_showProxy);
645         }
646         else if (strcmp(argv[i], "-clearOnce") == 0) {
647             _clearOnce = true;
648         }
649         else if (strcmp(argv[i], "-presentDisabled") == 0) {
650             _presentDisabled = true;
651         }
652         else {
653             ParseError(argv[0], "unknown argument %s", argv[i]);
654         }
655     }
656 }
657 
658 /* virtual */
659 void
MousePress(int button,int x,int y,int modKeys)660 UsdImagingGL_UnitTestGLDrawing::MousePress(int button, int x, int y,
661                                            int modKeys)
662 {
663 }
664 /* virtual */
665 void
MouseRelease(int button,int x,int y,int modKeys)666 UsdImagingGL_UnitTestGLDrawing::MouseRelease(int button, int x, int y,
667                                              int modKeys)
668 {
669 }
670 /* virtual */
671 void
MouseMove(int x,int y,int modKeys)672 UsdImagingGL_UnitTestGLDrawing::MouseMove(int x, int y, int modKeys)
673 {
674 }
675 /* virtual */
676 void
KeyRelease(int key)677 UsdImagingGL_UnitTestGLDrawing::KeyRelease(int key)
678 {
679 }
680 
681 void
RunTest(int argc,char * argv[])682 UsdImagingGL_UnitTestGLDrawing::RunTest(int argc, char *argv[])
683 {
684     _Args args;
685     _Parse(argc, argv, &args);
686 
687     if (!_traceFile.empty()) {
688         TraceCollector::GetInstance().SetEnabled(true);
689     }
690 
691     UsdImagingGL_UnitTestHelper_InitPlugins();
692 
693     for (size_t i=0; i<args.clipPlaneCoords.size()/4; ++i) {
694         _clipPlanes.push_back(GfVec4d(&args.clipPlaneCoords[i*4]));
695     }
696     _clearColor = GfVec4f(args.clearColor);
697     _translate = GfVec3f(args.translate);
698     _pixelAspectRatio = args.pixelAspectRatio;
699     _displayWindow = GfRange2f(
700         GfVec2f(args.displayWindow[0],
701                 args.displayWindow[1]),
702         GfVec2f(args.displayWindow[0] + args.displayWindow[2],
703                 args.displayWindow[1] + args.displayWindow[3]));
704     _dataWindow = GfRect2i(
705         GfVec2i(args.dataWindow[0], args.dataWindow[1]),
706         args.dataWindow[2], args.dataWindow[3]);
707 
708     _drawMode = UsdImagingGLDrawMode::DRAW_SHADED_SMOOTH;
709 
710     if (args.shading.compare("wireOnSurface") == 0) {
711         _drawMode = UsdImagingGLDrawMode::DRAW_WIREFRAME_ON_SURFACE;
712     } else if (args.shading.compare("flat") == 0 ) {
713         _drawMode = UsdImagingGLDrawMode::DRAW_SHADED_FLAT;
714     } else if (args.shading.compare("wire") == 0 ) {
715         _drawMode = UsdImagingGLDrawMode::DRAW_WIREFRAME;
716     } else if (args.shading.compare("points") == 0 ) {
717         _drawMode = UsdImagingGLDrawMode::DRAW_POINTS;
718     } else {
719         TF_WARN("Draw mode %s not supported!", args.shading.c_str());
720     }
721 
722     _cullStyle = UsdImagingGLCullStyle::CULL_STYLE_NOTHING;
723 
724     if (args.cullStyle.compare("back") == 0) {
725         _cullStyle = UsdImagingGLCullStyle::CULL_STYLE_BACK;
726     } else if (args.cullStyle.compare("backUnlessDoubleSided") == 0 ) {
727         _cullStyle = UsdImagingGLCullStyle::CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED;
728     } else if (args.cullStyle.compare("front") == 0 ) {
729         _cullStyle = UsdImagingGLCullStyle::CULL_STYLE_FRONT;
730     } else {
731         TF_WARN("Cull style %s not supported!", args.cullStyle.c_str());
732     }
733 
734     if (!args.unresolvedStageFilePath.empty()) {
735         _stageFilePath = args.unresolvedStageFilePath;
736     }
737 
738     _widget = new UsdImagingGL_UnitTestWindow(
739         this, args.widgetSize[0], args.widgetSize[1]);
740     _widget->Init();
741 
742     if (_times.empty()) {
743         _times.push_back(-999);
744     }
745 
746     if (args.complexities.size() > 0) {
747         std::string imageFilePath = GetOutputFilePath();
748 
749         TF_FOR_ALL(compIt, args.complexities) {
750             _complexity = *compIt;
751             if (!imageFilePath.empty()) {
752                 std::stringstream suffix;
753                 suffix << "_" << _complexity << ".png";
754                 _outputFilePath = TfStringReplace(imageFilePath, ".png", suffix.str());
755             }
756 
757             _widget->DrawOffscreen();
758         }
759 
760     } else if (args.offscreen) {
761         _widget->DrawOffscreen();
762     } else {
763         _widget->Run();
764     }
765 
766     if(!_traceFile.empty()) {
767         TraceCollector::GetInstance().SetEnabled(false);
768 
769         {
770             std::ofstream traceOutFile(_traceFile);
771             if (TF_VERIFY(traceOutFile)) {
772                 TraceReporter::GetGlobalReporter()->Report(traceOutFile);
773             }
774         }
775 
776         TraceCollector::GetInstance().Clear();
777         TraceReporter::GetGlobalReporter()->ClearTree();
778     }
779 }
780 
781 PXR_NAMESPACE_CLOSE_SCOPE
782 
783