Skip to content

Commit

Permalink
Add initial OpenGL support for Windows, macOS, and Linux
Browse files Browse the repository at this point in the history
* We've added a new "shader" example to show the capabilities of SkSL
shading language (it works on CPU without acceleration, and with GPU
shaders). More info: https://skia.org/docs/user/sksl/

* The macOS port still need some work as live resizing is not
working/refreshing the window properly.

* The API needs some refactor to support different GPU
backends (Raster, OpenGL, Direct3D, Metal, etc.)

* We still need a way to specify the GPU acceleration by
window (instead of system-wide) and when we change the option the
window/OpenGL context should be updated/created/destroyed
immediately (right now a resize events must be generated to update the
backend).

Related to:
aseprite/aseprite#960
#11
  • Loading branch information
dacap committed May 13, 2022
1 parent 48e7a25 commit 8a03881
Show file tree
Hide file tree
Showing 26 changed files with 815 additions and 895 deletions.
7 changes: 3 additions & 4 deletions cmake/FindSkia.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ target_compile_definitions(skia INTERFACE
SK_GAMMA_APPLY_TO_A8
SK_SCALAR_TO_FLOAT_EXCLUDED
SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1
SK_SUPPORT_OPENCL=0
SK_FORCE_DISTANCE_FIELD_TEXT=0
GR_GL_FUNCTION_TYPE=__stdcall
SK_SUPPORT_GPU=0) # TODO change this to 1
SK_SUPPORT_GPU=1
SK_ENABLE_SKSL=1
SK_GL=1)

if(WIN32)
target_compile_definitions(skia INTERFACE
Expand Down
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LAF OS
# Copyright (C) 2019-2021 Igara Studio S.A.
# Copyright (C) 2019-2022 Igara Studio S.A.

if(LAF_BACKEND STREQUAL "skia")
function(laf_add_example name console="")
Expand All @@ -21,4 +21,5 @@ if(LAF_BACKEND STREQUAL "skia")
laf_add_example(listscreens CONSOLE)
laf_add_example(multiple_windows GUI)
laf_add_example(panviewport GUI)
laf_add_example(shader GUI)
endif()
16 changes: 15 additions & 1 deletion examples/helloworld.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF Library
// Copyright (c) 2019-2021 Igara Studio S.A.
// Copyright (c) 2019-2022 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
Expand All @@ -24,17 +24,24 @@ void draw_window(os::Window* window)
os::draw_text(surface, nullptr, "Hello World", rc.center(),
&p, os::TextAlign::Center);

if (window->isGpuAccelerated())
os::draw_text(surface, nullptr, "(GPU)", rc.center()+gfx::Point(0, 24),
&p, os::TextAlign::Center);

// Invalidates the whole window to show it on the screen.
if (window->isVisible())
window->invalidateRegion(gfx::Region(rc));
else
window->setVisible(true);

window->swapBuffers();
}

int app_main(int argc, char* argv[])
{
os::SystemRef system = os::make_system();
system->setAppMode(os::AppMode::GUI);
system->setGpuAcceleration(true);

os::WindowRef window = system->makeWindow(400, 300);

Expand Down Expand Up @@ -88,6 +95,13 @@ int app_main(int argc, char* argv[])
case os::kKeyEsc:
running = false;
break;

case os::kKeyG:
system->setGpuAcceleration(!system->gpuAcceleration());
// TODO change window backend immediately
redraw = true;
break;

case os::kKey1:
case os::kKey2:
case os::kKey3:
Expand Down
10 changes: 8 additions & 2 deletions examples/panviewport.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF Library
// Copyright (C) 2020-2021 Igara Studio S.A.
// Copyright (C) 2020-2022 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
Expand Down Expand Up @@ -114,7 +114,6 @@ class PanWindow {
return true;
}

private:
void repaint() {
os::Surface* surface = m_window->surface();
os::SurfaceLock lock(surface);
Expand Down Expand Up @@ -154,8 +153,10 @@ class PanWindow {
}

m_window->invalidate();
m_window->swapBuffers();
}

private:
void setZoom(const gfx::PointF& mousePos, double newZoom) {
double oldZoom = m_zoom;
m_zoom = base::clamp(newZoom, 0.01, 10.0);
Expand Down Expand Up @@ -195,9 +196,14 @@ int app_main(int argc, char* argv[])
{
os::SystemRef system = os::make_system();
system->setAppMode(os::AppMode::GUI);
system->setGpuAcceleration(true);

PanWindow window(system.get());

system->handleWindowResize = [&window](os::Window* win){
window.repaint();
};

system->finishLaunching();
system->activateApp();

Expand Down
169 changes: 169 additions & 0 deletions examples/shader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// LAF Library
// Copyright (C) 2022 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#include "os/os.h"

#ifndef LAF_SKIA
#error You need Skia library to compile this example
#endif

#if !SK_SUPPORT_GPU
#error You need Skia with GPU support to compile this example
#endif

#include "base/time.h"
#include "os/skia/skia_surface.h"

#include "include/effects/SkRuntimeEffect.h"

#include <cstdio>

base::tick_t startTick;

// Shader from:
// https://shaders.skia.org/
// https://twitter.com/notargs/status/1250468645030858753
const char* shaderCode = R"(
uniform float3 iResolution;
uniform float iTime;
float f(vec3 p) {
p.z -= iTime * 10.0;
float a = p.z * .1;
p.xy *= mat2(cos(a), sin(a), -sin(a), cos(a));
return .1 - length(cos(p.xy) + sin(p.yz));
}
half4 main(vec2 fragcoord) {
vec3 d = .5 - fragcoord.xy1 / iResolution.y;
vec3 p = vec3(0);
for (int i = 0; i < 32; i++) {
p += f(p) * d;
}
return ((sin(p) + vec3(2, 5, 9)) / length(p)).xyz1;
}
)";

class ShaderWindow {
public:
ShaderWindow(os::System* system)
: m_builder(SkRuntimeEffect::MakeForShader(SkString(shaderCode)).effect) {
m_window = system->makeWindow(256, 256);
m_window->setCursor(os::NativeCursor::Arrow);
m_window->setTitle("Shader");
repaint();
m_window->setVisible(true);
}

bool processEvent(const os::Event& ev) {
switch (ev.type()) {

case os::Event::CloseWindow:
return false;

case os::Event::ResizeWindow:
repaint();
break;

case os::Event::KeyDown:
if (ev.scancode() == os::kKeyEsc)
return false;
else if (ev.scancode() == os::kKeyG) {
os::instance()->setGpuAcceleration(
!os::instance()->gpuAcceleration());
}
break;

default:
// Do nothing
break;
}
return true;
}

void repaint() {
os::Surface* surface = m_window->surface();
os::SurfaceLock lock(surface);

SkCanvas* canvas = &static_cast<os::SkiaSurface*>(surface)->canvas();
skiaPaint(canvas);

if (m_window->isGpuAccelerated()) {
os::Paint p;
p.color(gfx::rgba(0, 0, 0));
os::draw_text(surface, nullptr, "GPU", gfx::Point(12, 12),
&p, os::TextAlign::Center);
}

m_window->invalidate();
m_window->swapBuffers();
}

private:

void skiaPaint(SkCanvas* canvas) {
SkImageInfo ii = canvas->imageInfo();
m_builder.uniform("iResolution") = SkV3{float(ii.width()),
float(ii.height()), 0.0f};
m_builder.uniform("iTime") =
float((base::current_tick() - startTick) / 1000.0f);

SkPaint p;
p.setShader(m_builder.makeShader());
canvas->drawPaint(p);
}

os::WindowRef m_window;
SkRuntimeShaderBuilder m_builder;
};

int app_main(int argc, char* argv[])
{
os::SystemRef system = os::make_system();
system->setAppMode(os::AppMode::GUI);
system->setGpuAcceleration(true);

ShaderWindow window(system.get());

system->handleWindowResize = [&window](os::Window* win){
window.repaint();
};

system->finishLaunching();
system->activateApp();

startTick = base::current_tick();

os::EventQueue* queue = system->eventQueue();
auto t = startTick;
double paintDelay = 0.0;

while (true) {
os::Event ev;

ASSERT(paintDelay >= 0.0);
const double waitSecs =
(base::current_tick() - t) / 1000.0 * 60.0 + paintDelay;

queue->getEvent(ev, waitSecs);
if (!window.processEvent(ev))
break;

auto now = base::current_tick();
paintDelay -= (now - t) / 1000.0;
if (paintDelay < 0.0) {
auto paintStart = now;

window.repaint();

now = base::current_tick();
paintDelay = (now - paintStart) / 1000.0;
}
t = now;
}

return 0;
}
7 changes: 6 additions & 1 deletion gfx/color_space.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF Gfx Library
// Copyright (c) 2018-2020 Igara Studio S.A.
// Copyright (c) 2018-2022 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
Expand All @@ -15,6 +15,9 @@
#include <string>
#include <vector>

#pragma push_macro("None")
#undef None // Undefine the X11 None macro

namespace gfx {

class ColorSpace;
Expand Down Expand Up @@ -129,4 +132,6 @@ namespace gfx {

} // namespace gfx

#pragma pop_macro("None")

#endif
6 changes: 4 additions & 2 deletions os/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LAF OS
# Copyright (C) 2018-2021 Igara Studio S.A.
# Copyright (C) 2018-2022 Igara Studio S.A.
# Copyright (C) 2012-2018 David Capello

######################################################################
Expand Down Expand Up @@ -36,7 +36,8 @@ elseif(APPLE)
osx/native_dialogs.mm
osx/system.mm
osx/view.mm
osx/window.mm)
osx/window.mm
gl/gl_context_nsgl.mm)
endif()
else()
list(APPEND LAF_OS_SOURCES
Expand Down Expand Up @@ -64,6 +65,7 @@ if(LAF_BACKEND STREQUAL "skia")
skia/skia_color_space.cpp
skia/skia_draw_text.cpp
skia/skia_draw_text_with_shaper.cpp
skia/skia_gl.cpp
skia/skia_surface.cpp
skia/skia_window.cpp)
if(WIN32)
Expand Down
7 changes: 4 additions & 3 deletions os/gl/gl_context.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// LAF OS Library
// Copyright (C) 2022 Igara Studio S.A.
// Copyright (C) 2015-2016 David Capello
//
// This file is released under the terms of the MIT license.
Expand All @@ -13,11 +14,11 @@ namespace os {
class GLContext {
public:
virtual ~GLContext() { }
virtual bool isValid() = 0;
virtual bool createGLContext() = 0;
virtual void destroyGLContext() = 0;
virtual int getStencilBits() = 0;
virtual int getSampleCount() = 0;
virtual void swapBuffers() { }
virtual void makeCurrent() = 0;
virtual void swapBuffers() = 0;
};

} // namespace os
Expand Down
Loading

0 comments on commit 8a03881

Please sign in to comment.