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 #include "GLFW/glfw3.h" 9 #include <stdlib.h> 10 #include <stdio.h> 11 12 #include "GrContext.h" 13 14 #include "SkCanvas.h" 15 #include "SkImage.h" 16 #include "SkRSXform.h" 17 #include "SkSurface.h" 18 #include "Timer.h" 19 20 GrContext* sContext = nullptr; 21 SkSurface* sSurface = nullptr; 22 23 static void error_callback(int error, const char* description) { 24 fputs(description, stderr); 25 } 26 27 static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { 28 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 29 glfwSetWindowShouldClose(window, GL_TRUE); 30 } 31 32 33 static void init_skia(int w, int h) { 34 sContext = GrContext::Create(kOpenGL_GrBackend, 0); 35 36 GrBackendRenderTargetDesc desc; 37 desc.fWidth = w; 38 desc.fHeight = h; 39 desc.fConfig = kSkia8888_GrPixelConfig; 40 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 41 desc.fSampleCnt = 1; 42 desc.fStencilBits = 0; 43 desc.fRenderTargetHandle = 0; // assume default framebuffer 44 45 sSurface = SkSurface::NewFromBackendRenderTarget(sContext, desc, NULL); 46 } 47 48 static void cleanup_skia() { 49 delete sSurface; 50 delete sContext; 51 } 52 53 const int kGrid = 100; 54 const int kWidth = 960; 55 const int kHeight = 640; 56 57 int main(void) { 58 GLFWwindow* window; 59 glfwSetErrorCallback(error_callback); 60 if (!glfwInit()) { 61 exit(EXIT_FAILURE); 62 } 63 64 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 65 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); 66 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 67 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 68 glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE); 69 70 window = glfwCreateWindow(kWidth, kHeight, "Simple example", NULL, NULL); 71 if (!window) { 72 glfwTerminate(); 73 exit(EXIT_FAILURE); 74 } 75 glfwMakeContextCurrent(window); 76 77 init_skia(kWidth, kHeight); 78 79 SkAutoTUnref<SkImage> atlas; 80 SkRSXform xform[kGrid*kGrid+1]; 81 SkRect tex[kGrid*kGrid+1]; 82 WallTimer timer; 83 float times[32]; 84 int currentTime; 85 86 SkAutoTUnref<SkData> imageData(SkData::NewFromFileName("ship.png")); 87 atlas.reset(SkImage::NewFromEncoded(imageData)); 88 if (!atlas) { 89 SkDebugf("\nCould not decode file ship.png\n"); 90 91 cleanup_skia(); 92 glfwDestroyWindow(window); 93 glfwTerminate(); 94 exit(EXIT_FAILURE); 95 } 96 97 SkScalar anchorX = atlas->width()*0.5f; 98 SkScalar anchorY = atlas->height()*0.5f; 99 int currIndex = 0; 100 for (int x = 0; x < kGrid; x++) { 101 for (int y = 0; y < kGrid; y++) { 102 float xPos = (x / (kGrid - 1.0)) * kWidth; 103 float yPos = (y / (kGrid - 1.0)) * kWidth; 104 105 tex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f, atlas->width(), atlas->height()); 106 xform[currIndex] = SkRSXform::MakeFromRadians(2.0f, SK_ScalarPI*0.5f, 107 xPos, yPos, anchorX, anchorY); 108 currIndex++; 109 } 110 } 111 tex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f, atlas->width(), atlas->height()); 112 xform[currIndex] = SkRSXform::MakeFromRadians(2.0f, SK_ScalarPI*0.5f, 113 kWidth*0.5f, kHeight*0.5f, anchorX, anchorY); 114 115 currentTime = 0; 116 117 glfwSwapInterval(1); 118 glfwSetKeyCallback(window, key_callback); 119 120 // Draw to the surface via its SkCanvas. 121 SkCanvas* canvas = sSurface->getCanvas(); // We don't manage this pointer's lifetime. 122 SkPaint paint; 123 paint.setFilterQuality(kLow_SkFilterQuality); 124 paint.setColor(SK_ColorWHITE); 125 paint.setTextSize(15.0f); 126 127 while (!glfwWindowShouldClose(window)) { 128 const float kCosDiff = 0.99984769515f; 129 const float kSinDiff = 0.01745240643f; 130 131 timer.start(); 132 133 glfwPollEvents(); 134 135 float meanTime = 0.0f; 136 for (int i = 0; i < 32; ++i) { 137 meanTime += times[i]; 138 } 139 meanTime /= 32.f; 140 char outString[64]; 141 float fps = 1000.f/meanTime; 142 sprintf(outString, "fps: %f ms: %f", fps, meanTime); 143 144 for (int i = 0; i < kGrid*kGrid+1; ++i) { 145 SkScalar c = xform[i].fSCos; 146 SkScalar s = xform[i].fSSin; 147 148 SkScalar dx = c*anchorX - s*anchorY; 149 SkScalar dy = s*anchorX + c*anchorY; 150 151 xform[i].fSCos = kCosDiff*c - kSinDiff*s; 152 xform[i].fSSin = kSinDiff*c + kCosDiff*s; 153 154 dx -= xform[i].fSCos*anchorX - xform[i].fSSin*anchorY; 155 dy -= xform[i].fSSin*anchorX + xform[i].fSCos*anchorY; 156 xform[i].fTx += dx; 157 xform[i].fTy += dy; 158 } 159 160 canvas->clear(SK_ColorBLACK); 161 canvas->drawAtlas(atlas, xform, tex, nullptr, kGrid*kGrid+1, SkXfermode::kSrcOver_Mode, 162 nullptr, &paint); 163 canvas->drawText(outString, strlen(outString), 100.f, 100.f, paint); 164 165 canvas->flush(); 166 167 timer.end(); 168 times[currentTime] = (float)(timer.fWall); 169 currentTime = (currentTime + 1) & 0x1f; 170 171 glfwSwapBuffers(window); 172 } 173 174 cleanup_skia(); 175 176 glfwDestroyWindow(window); 177 glfwTerminate(); 178 exit(EXIT_SUCCESS); 179 } 180