1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 * 7 */ 8 9 #include "VisualBench.h" 10 11 #include "GrContext.h" 12 #include "ProcStats.h" 13 #include "SkApplication.h" 14 #include "SkCanvas.h" 15 #include "SkCommandLineFlags.h" 16 #include "SkGraphics.h" 17 #include "SkGr.h" 18 #include "SkOSFile.h" 19 #include "SkStream.h" 20 #include "Stats.h" 21 #include "VisualDebugModule.h" 22 #include "VisualLightweightBenchModule.h" 23 #include "VisualInteractiveModule.h" 24 #include "gl/GrGLInterface.h" 25 26 #include <stdlib.h> 27 28 DEFINE_bool2(fullscreen, f, true, "Run fullscreen."); 29 DEFINE_string(mode, "classic", "one of: classic interactive debugger"); 30 DEFINE_bool2(dif, d, false, "Use device-independent fonts."); 31 32 VisualBench::VisualBench(void* hwnd, int argc, char** argv) 33 : INHERITED(hwnd) { 34 SkDebugf("Command line arguments: "); 35 for (int i = 1; i < argc; ++i) { 36 SkDebugf("%s ", argv[i]); 37 } 38 SkDebugf("\n"); 39 40 SkCommandLineFlags::Parse(argc, argv); 41 42 if (FLAGS_nvpr && !FLAGS_msaa) { 43 SkDebugf("Got nvpr without msaa. Exiting.\n"); 44 exit(-1); 45 } 46 47 // these have to happen after commandline parsing 48 if (FLAGS_dif) { 49 const SkSurfaceProps& props(INHERITED::getSurfaceProps()); 50 uint32_t flags = SkSurfaceProps::kUseDeviceIndependentFonts_Flag | props.flags(); 51 INHERITED::setSurfaceProps(SkSurfaceProps(flags, props.pixelGeometry())); 52 } 53 fModule.reset(new VisualLightweightBenchModule(this)); 54 55 if (FLAGS_mode.count()) { 56 SkASSERT(FLAGS_mode.count() == 1); 57 SkString mode(FLAGS_mode[0]); 58 if (mode == SkString("interactive")) { 59 fModule.reset(new VisualInteractiveModule(this)); 60 } else if (mode == SkString("debugger")) { 61 fModule.reset(new VisualDebugModule(this)); 62 } 63 } 64 65 this->setTitle(); 66 this->setupBackend(); 67 } 68 69 VisualBench::~VisualBench() { 70 this->tearDownContext(); 71 } 72 73 void VisualBench::setTitle() { 74 SkString title("VisualBench"); 75 INHERITED::setTitle(title.c_str()); 76 } 77 78 SkSurface* VisualBench::createSurface() { 79 if (!fSurface) { 80 SkSurfaceProps props(INHERITED::getSurfaceProps()); 81 fSurface.reset(SkSurface::NewRenderTargetDirect(fRenderTarget, &props)); 82 } 83 84 // The caller will wrap the SkSurface in an SkAutoTUnref 85 return SkRef(fSurface.get()); 86 } 87 88 bool VisualBench::setupBackend() { 89 this->setVisibleP(true); 90 this->setClipToBounds(false); 91 92 if (FLAGS_fullscreen) { 93 if (!this->makeFullscreen()) { 94 SkDebugf("Could not go fullscreen!"); 95 } 96 } 97 98 this->resetContext(); 99 return true; 100 } 101 102 void VisualBench::resetContext() { 103 this->tearDownContext(); 104 this->setupContext(); 105 } 106 107 void VisualBench::setupContext() { 108 int screenSamples = FLAGS_offscreen ? 0 : FLAGS_msaa; 109 if (!this->attach(kNativeGL_BackEndType, screenSamples, &fAttachmentInfo)) { 110 SkDebugf("Not possible to create backend.\n"); 111 INHERITED::detach(); 112 SkFAIL("Could not create backend\n"); 113 } 114 115 this->setVsync(false); 116 117 fSurface.reset(nullptr); 118 119 fInterface.reset(GrGLCreateNativeInterface()); 120 121 // TODO use the GLContext creation factories and also set this all up in configs 122 if (!FLAGS_nvpr) { 123 fInterface.reset(GrGLInterfaceRemoveNVPR(fInterface)); 124 } 125 SkASSERT(fInterface); 126 127 // setup contexts 128 fContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface.get())); 129 SkASSERT(fContext); 130 131 // setup rendertargets 132 this->setupRenderTarget(); 133 } 134 135 void VisualBench::tearDownContext() { 136 if (fContext) { 137 // We abandon the context in case SkWindow has kept a ref to the surface 138 fContext->abandonContext(); 139 fContext.reset(); 140 fSurface.reset(); 141 fInterface.reset(); 142 this->detach(); 143 } 144 } 145 146 void VisualBench::setupRenderTarget() { 147 if (fContext) { 148 fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fContext)); 149 } 150 } 151 152 void VisualBench::draw(SkCanvas* canvas) { 153 fModule->draw(canvas); 154 155 // Invalidate the window to force a redraw. Poor man's animation mechanism. 156 this->inval(nullptr); 157 } 158 159 void VisualBench::clear(SkCanvas* canvas, SkColor color, int frames) { 160 canvas->clear(color); 161 for (int i = 0; i < frames - 1; ++i) { 162 canvas->flush(); 163 this->present(); 164 canvas->clear(color); 165 } 166 } 167 168 void VisualBench::onSizeChange() { 169 this->setupRenderTarget(); 170 } 171 172 bool VisualBench::onHandleChar(SkUnichar unichar) { 173 static const auto kEscKey = 27; 174 if (kEscKey == unichar) { 175 this->closeWindow(); 176 return true; 177 } 178 179 return fModule->onHandleChar(unichar); 180 } 181 182 // Externally declared entry points 183 void application_init() { 184 SkGraphics::Init(); 185 SkEvent::Init(); 186 } 187 188 void application_term() { 189 SkEvent::Term(); 190 } 191 192 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 193 return new VisualBench(hwnd, argc, argv); 194 } 195 196