blob: 77c80da671adc272bd2a77cf4a95ae636954e71f [file] [log] [blame]
/*
* Copyright 2022 Rive
*/
// Makes ure gl3w is included before glfw3
#include "GL/gl3w.h"
#define SK_GL
#include "GLFW/glfw3.h"
#include "GrBackendSurface.h"
#include "GrDirectContext.h"
#include "SkCanvas.h"
#include "SkColorSpace.h"
#include "SkSurface.h"
#include "gl/GrGLInterface.h"
#include "imgui/backends/imgui_impl_glfw.h"
#include "imgui/backends/imgui_impl_opengl3.h"
#include "../src/render_counter.hpp"
#include <cmath>
#include <stdio.h>
#include "viewer_content.hpp"
int lastScreenWidth = 0, lastScreenHeight = 0;
std::unique_ptr<ViewerContent> gContent;
std::vector<uint8_t> ViewerContent::LoadFile(const char filename[]) {
std::vector<uint8_t> bytes;
FILE* fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Can't find file: %s\n", filename);
return bytes;
}
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
bytes.resize(size);
size_t bytesRead = fread(bytes.data(), 1, size, fp);
fclose(fp);
if (bytesRead != size) {
fprintf(stderr, "Failed to read all of %s\n", filename);
bytes.resize(0);
}
return bytes;
}
static void glfwCursorPosCallback(GLFWwindow* window, double x, double y) {
if (gContent) {
float xscale, yscale;
glfwGetWindowContentScale(window, &xscale, &yscale);
gContent->handlePointerMove(x * xscale, y * yscale);
}
}
void glfwMouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
if (gContent) {
switch (action) {
case GLFW_PRESS:
gContent->handlePointerDown();
break;
case GLFW_RELEASE:
gContent->handlePointerUp();
break;
}
}
}
void glfwErrorCallback(int error, const char* description) { puts(description); }
void glfwDropCallback(GLFWwindow* window, int count, const char** paths) {
// Just get the last dropped file for now...
const char* filename = paths[count - 1];
auto newContent = ViewerContent::FindHandler(filename);
if (newContent) {
gContent = std::move(newContent);
gContent->handleResize(lastScreenWidth, lastScreenHeight);
} else {
fprintf(stderr, "No handler found for %s\n", filename);
}
}
int main() {
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize glfw.\n");
return 1;
}
glfwSetErrorCallback(glfwErrorCallback);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Rive Viewer", NULL, NULL);
if (window == nullptr) {
fprintf(stderr, "Failed to make window or GL.\n");
glfwTerminate();
return 1;
}
glfwSetDropCallback(window, glfwDropCallback);
glfwSetCursorPosCallback(window, glfwCursorPosCallback);
glfwSetMouseButtonCallback(window, glfwMouseButtonCallback);
glfwMakeContextCurrent(window);
if (gl3wInit() != 0) {
fprintf(stderr, "Failed to make initialize gl3w.\n");
glfwTerminate();
return 1;
}
// Enable VSYNC.
glfwSwapInterval(1);
// Setup ImGui
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
(void)io;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 150");
io.Fonts->AddFontDefault();
// Setup Skia
GrContextOptions options;
sk_sp<GrDirectContext> context = GrDirectContext::MakeGL(nullptr, options);
GrGLFramebufferInfo framebufferInfo;
framebufferInfo.fFBOID = 0;
framebufferInfo.fFormat = GL_RGBA8;
sk_sp<SkSurface> surface;
SkCanvas* canvas = nullptr;
// Render loop.
int width = 0, height = 0;
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
glfwGetFramebufferSize(window, &width, &height);
// Update surface.
if (!surface || width != lastScreenWidth || height != lastScreenHeight) {
lastScreenWidth = width;
lastScreenHeight = height;
if (gContent) {
gContent->handleResize(width, height);
}
SkColorType colorType =
kRGBA_8888_SkColorType; // GrColorTypeToSkColorType(GrPixelConfigToColorType(kRGBA_8888_GrPixelConfig));
//
// if (kRGBA_8888_GrPixelConfig == kSkia8888_GrPixelConfig)
// {
// colorType = kRGBA_8888_SkColorType;
// }
// else
// {
// colorType = kBGRA_8888_SkColorType;
// }
GrBackendRenderTarget backendRenderTarget(width,
height,
0, // sample count
0, // stencil bits
framebufferInfo);
surface = SkSurface::MakeFromBackendRenderTarget(context.get(),
backendRenderTarget,
kBottomLeft_GrSurfaceOrigin,
colorType,
nullptr,
nullptr);
if (!surface) {
fprintf(stderr, "Failed to create Skia surface\n");
return 1;
}
canvas = surface->getCanvas();
}
double time = glfwGetTime();
float elapsed = (float)(time - lastTime);
lastTime = time;
// Clear screen.
SkPaint paint;
paint.setColor(SK_ColorDKGRAY);
canvas->drawPaint(paint);
if (gContent) {
SkAutoCanvasRestore acr(canvas, true);
gContent->handleDraw(canvas, elapsed);
}
context->flush();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
if (gContent) {
gContent->handleImgui();
}
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
glfwPollEvents();
}
gContent = nullptr; // force delete now, so we can clean up
// Cleanup Skia.
surface = nullptr;
context = nullptr;
ImGui_ImplGlfw_Shutdown();
// Cleanup GLFW.
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}