glfw_main.cpp revision cda8ec2b030c6fcb58d2d11f4983a14c0f355235
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
20GrContext* sContext = nullptr;
21SkSurface* sSurface = nullptr;
22
23static void error_callback(int error, const char* description) {
24    fputs(description, stderr);
25}
26
27static 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
33static 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
48static void cleanup_skia() {
49    delete sSurface;
50    delete sContext;
51}
52
53const int kGrid = 100;
54const int kWidth = 960;
55const int kHeight = 640;
56
57int 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