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 28DEFINE_bool2(fullscreen, f, true, "Run fullscreen."); 29DEFINE_string(mode, "classic", "one of: classic interactive debugger"); 30DEFINE_bool2(dif, d, false, "Use device-independent fonts."); 31 32VisualBench::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 69VisualBench::~VisualBench() { 70 this->tearDownContext(); 71} 72 73void VisualBench::setTitle() { 74 SkString title("VisualBench"); 75 INHERITED::setTitle(title.c_str()); 76} 77 78SkSurface* 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 88bool 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 102void VisualBench::resetContext() { 103 this->tearDownContext(); 104 this->setupContext(); 105} 106 107void 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 135void 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 146void VisualBench::setupRenderTarget() { 147 if (fContext) { 148 fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fContext)); 149 } 150} 151 152void 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 159void 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 168void VisualBench::onSizeChange() { 169 this->setupRenderTarget(); 170} 171 172bool 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 183void application_init() { 184 SkGraphics::Init(); 185 SkEvent::Init(); 186} 187 188void application_term() { 189 SkEvent::Term(); 190} 191 192SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 193 return new VisualBench(hwnd, argc, argv); 194} 195 196