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
error_callback(int error,const char * description)23 static void error_callback(int error, const char* description) {
24 fputs(description, stderr);
25 }
26
key_callback(GLFWwindow * window,int key,int scancode,int action,int mods)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
init_skia(int w,int h)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::MakeFromBackendRenderTarget(sContext, desc, nullptr, nullptr).release();
46 }
47
cleanup_skia()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
main(void)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 sk_sp<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 sk_sp<SkData> imageData(SkData::MakeFromFileName("ship.png"));
87 atlas.reset(SkImage::NewFromEncoded(imageData.get()));
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