feat(webgl): Add WEBGL_GAL implementation (compiles, not yet rendering)
Copy and adapt OpenGL GAL to WebGL: - Copy all OpenGL GAL source files to tests/gal-regression/wasm/webgl/ - Rename classes from OPENGL_* to WEBGL_* - Add kiglew.h with WebGL2/GLES3 headers and GLEW stubs - Add webgl_antialiasing.h/cpp adapted for WEBGL_COMPOSITOR - Add shader generator (generate_shaders.py) for WASM build - Update Makefile with all KiCad dependencies (C++20, GLM, clipper2, etc.) Build produces 544KB JS + 4.9MB WASM. Tests run but render blank (expected - GL context initialization needs WebGL adaptation). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a4f444fea8
commit
c381fdb85c
60 changed files with 27839 additions and 16 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# Makefile for GAL WebGL Test (WASM)
|
||||
#
|
||||
# Uses direct em++ calls like tests/apps/Makefile.wasm
|
||||
# Avoids emcmake/cmake which require Python 3.10+
|
||||
# Builds WEBGL_GAL (ported from OPENGL_GAL) using wxWidgets WASM build.
|
||||
# Uses LEGACY_GL_EMULATION for legacy OpenGL compatibility.
|
||||
#
|
||||
# Usage:
|
||||
# make # Build
|
||||
|
|
@ -10,32 +10,104 @@
|
|||
|
||||
CXX = em++
|
||||
|
||||
# Paths relative to this Makefile
|
||||
PROJECT_ROOT = ../../..
|
||||
KICAD_ROOT = $(PROJECT_ROOT)/kicad
|
||||
WX_BUILD = $(PROJECT_ROOT)/build-wasm/wxwidgets-universal
|
||||
TOOLS_ROOT = $(PROJECT_ROOT)/wxwidgets/build/wasm
|
||||
|
||||
# Output directory
|
||||
OUTPUT_DIR = ../../apps/gal-webgl
|
||||
|
||||
# wx-config for wxWidgets WASM
|
||||
WXCONFIG = $(WX_BUILD)/wx-config
|
||||
WX_CXXFLAGS := $(shell $(WXCONFIG) --cxxflags)
|
||||
WX_LDFLAGS := $(shell $(WXCONFIG) --libs base,core,gl)
|
||||
|
||||
# Sysroot (contains boost, etc.)
|
||||
SYSROOT = $(PROJECT_ROOT)/build-wasm/sysroot
|
||||
|
||||
# KiCad include paths
|
||||
# Note: -I../native provides stub files (config.h, kicad_stubs.h, etc.)
|
||||
KICAD_INCLUDES = -I../native \
|
||||
-Igenerated \
|
||||
-I$(KICAD_ROOT)/include \
|
||||
-I$(KICAD_ROOT)/include/gal \
|
||||
-I$(KICAD_ROOT)/include/gal/opengl \
|
||||
-I$(KICAD_ROOT)/common \
|
||||
-I$(KICAD_ROOT)/libs/kimath/include \
|
||||
-I$(KICAD_ROOT)/libs/kiplatform/include \
|
||||
-I$(KICAD_ROOT)/libs/core/include \
|
||||
-I$(KICAD_ROOT)/thirdparty/glm \
|
||||
-I$(KICAD_ROOT)/thirdparty/nlohmann_json \
|
||||
-I$(KICAD_ROOT)/thirdparty/thread-pool \
|
||||
-I$(KICAD_ROOT)/thirdparty/clipper2/Clipper2Lib/include \
|
||||
-I$(SYSROOT)/include \
|
||||
-Iwebgl
|
||||
|
||||
# Debug or Release build
|
||||
ifdef DEBUG
|
||||
CXXFLAGS = -g -O0
|
||||
OPT_FLAGS = -g -O0
|
||||
DEBUG_LDFLAGS = -g -gsource-map
|
||||
else
|
||||
CXXFLAGS = -O2
|
||||
OPT_FLAGS = -O2
|
||||
DEBUG_LDFLAGS =
|
||||
endif
|
||||
|
||||
# Emscripten flags for WebGL 2.0
|
||||
EM_FLAGS = -sUSE_WEBGL2=1 \
|
||||
-sFULL_ES3=1 \
|
||||
-sALLOW_MEMORY_GROWTH=1 \
|
||||
-sEXPORTED_FUNCTIONS=['_main','_runScenario','_getTotalScenarios','_getCurrentScenario','_getCanvasWidth','_getCanvasHeight'] \
|
||||
-sEXPORTED_RUNTIME_METHODS=['ccall','cwrap'] \
|
||||
-sMODULARIZE=1 \
|
||||
-sEXPORT_NAME='createGALTest' \
|
||||
-sENVIRONMENT=web
|
||||
CXXFLAGS = $(OPT_FLAGS) $(WX_CXXFLAGS) $(KICAD_INCLUDES) -std=c++20
|
||||
|
||||
LDFLAGS = $(DEBUG_LDFLAGS) $(EM_FLAGS)
|
||||
# Emscripten flags
|
||||
BASE_LDFLAGS = -sALLOW_MEMORY_GROWTH=1 \
|
||||
-sERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||
-sEXPORTED_FUNCTIONS=['_main','_runScenario','_getTotalScenarios','_getCurrentScenario','_getCanvasWidth','_getCanvasHeight'] \
|
||||
-sEXPORTED_RUNTIME_METHODS=['ccall','cwrap','HEAPU8'] \
|
||||
-sMODULARIZE=1 \
|
||||
-sEXPORT_NAME='createGALTest' \
|
||||
-sENVIRONMENT=web
|
||||
|
||||
# GL-specific flags - LEGACY_GL_EMULATION handles legacy GL calls
|
||||
EM_GL_FLAGS = -sLEGACY_GL_EMULATION=1 -sMAX_WEBGL_VERSION=2
|
||||
GL_SHIM = $(PROJECT_ROOT)/wasm/shims/gl_immediate_shim.js
|
||||
|
||||
LDFLAGS = $(DEBUG_LDFLAGS) $(BASE_LDFLAGS) $(EM_GL_FLAGS) --js-library=$(GL_SHIM) $(WX_LDFLAGS)
|
||||
|
||||
# Templates
|
||||
JS = $(TOOLS_ROOT)/wx.js
|
||||
HTML_TEMPLATE = $(TOOLS_ROOT)/template.html
|
||||
|
||||
# Source files
|
||||
SRCS = gal_webgl_test.cpp
|
||||
MAIN_SRCS = gal_webgl_test.cpp
|
||||
|
||||
# Generated shader sources (from generate_shaders.py)
|
||||
SHADER_SRCS = generated/glsl_kicad_frag.cpp \
|
||||
generated/glsl_kicad_vert.cpp \
|
||||
generated/glsl_smaa_base.cpp \
|
||||
generated/glsl_smaa_pass_1_frag_color.cpp \
|
||||
generated/glsl_smaa_pass_1_frag_luma.cpp \
|
||||
generated/glsl_smaa_pass_1_vert.cpp \
|
||||
generated/glsl_smaa_pass_2_frag.cpp \
|
||||
generated/glsl_smaa_pass_2_vert.cpp \
|
||||
generated/glsl_smaa_pass_3_frag.cpp \
|
||||
generated/glsl_smaa_pass_3_vert.cpp
|
||||
|
||||
# WebGL GAL sources (ported from OpenGL GAL)
|
||||
WEBGL_SRCS = webgl/webgl_gal.cpp \
|
||||
webgl/vertex_manager.cpp \
|
||||
webgl/vertex_container.cpp \
|
||||
webgl/vertex_item.cpp \
|
||||
webgl/gpu_manager.cpp \
|
||||
webgl/noncached_container.cpp \
|
||||
webgl/cached_container.cpp \
|
||||
webgl/cached_container_gpu.cpp \
|
||||
webgl/cached_container_ram.cpp \
|
||||
webgl/shader.cpp \
|
||||
webgl/webgl_compositor.cpp \
|
||||
webgl/utils.cpp \
|
||||
webgl/gl_context_mgr.cpp \
|
||||
webgl/gl_resources.cpp \
|
||||
webgl/webgl_antialiasing.cpp
|
||||
|
||||
SRCS = $(MAIN_SRCS) $(SHADER_SRCS) $(WEBGL_SRCS)
|
||||
OBJS = $(SRCS:.cpp=.o)
|
||||
|
||||
# Target
|
||||
|
|
@ -50,7 +122,7 @@ $(OUTPUT_DIR):
|
|||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CXX) $(OBJS) $(LDFLAGS) -o $@
|
||||
$(CXX) $(OBJS) $(LDFLAGS) --pre-js $(JS) -o $@
|
||||
cp gal_webgl_test.html $(OUTPUT_DIR)/
|
||||
|
||||
clean:
|
||||
|
|
|
|||
102
tests/gal-regression/wasm/generate_shaders.py
Normal file
102
tests/gal-regression/wasm/generate_shaders.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate C++ shader headers from KiCad GLSL files.
|
||||
|
||||
This script converts GLSL shader files to C++ headers compatible with
|
||||
KiCad's BUILTIN_SHADERS namespace.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
def convert_shader_to_cpp(source_path, var_name):
|
||||
"""Convert a shader file to C++ header content."""
|
||||
with open(source_path, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
# Convert to hex array
|
||||
hex_values = ', '.join(f'0x{b:02x}' for b in data)
|
||||
hex_values += ', 0x00' # Null terminate
|
||||
|
||||
array_size = len(data)
|
||||
|
||||
header_content = f"""// Auto-generated shader header from {os.path.basename(source_path)}
|
||||
#ifndef {var_name.upper()}_H
|
||||
#define {var_name.upper()}_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {{
|
||||
namespace BUILTIN_SHADERS {{
|
||||
extern std::string {var_name};
|
||||
}}
|
||||
}}
|
||||
|
||||
#endif // {var_name.upper()}_H
|
||||
"""
|
||||
|
||||
cpp_content = f"""// Auto-generated from {os.path.basename(source_path)}
|
||||
#include <string>
|
||||
#include "{var_name}.h"
|
||||
|
||||
namespace KIGFX {{
|
||||
namespace BUILTIN_SHADERS {{
|
||||
|
||||
static unsigned char {var_name}_bytes[] = {{ {hex_values} }};
|
||||
|
||||
std::string {var_name} = std::string(reinterpret_cast<char const*>({var_name}_bytes), {array_size});
|
||||
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
|
||||
return header_content, cpp_content
|
||||
|
||||
def main():
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
kicad_root = os.path.abspath(os.path.join(script_dir, '..', '..', '..', 'kicad'))
|
||||
shaders_dir = os.path.join(kicad_root, 'common', 'gal', 'shaders')
|
||||
|
||||
output_dir = os.path.join(script_dir, 'generated')
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
shaders = [
|
||||
('kicad_frag.glsl', 'glsl_kicad_frag'),
|
||||
('kicad_vert.glsl', 'glsl_kicad_vert'),
|
||||
('smaa_base.glsl', 'glsl_smaa_base'),
|
||||
('smaa_pass_1_frag_color.glsl', 'glsl_smaa_pass_1_frag_color'),
|
||||
('smaa_pass_1_frag_luma.glsl', 'glsl_smaa_pass_1_frag_luma'),
|
||||
('smaa_pass_1_vert.glsl', 'glsl_smaa_pass_1_vert'),
|
||||
('smaa_pass_2_frag.glsl', 'glsl_smaa_pass_2_frag'),
|
||||
('smaa_pass_2_vert.glsl', 'glsl_smaa_pass_2_vert'),
|
||||
('smaa_pass_3_frag.glsl', 'glsl_smaa_pass_3_frag'),
|
||||
('smaa_pass_3_vert.glsl', 'glsl_smaa_pass_3_vert'),
|
||||
]
|
||||
|
||||
generated_cpp_files = []
|
||||
|
||||
for shader_file, var_name in shaders:
|
||||
source_path = os.path.join(shaders_dir, shader_file)
|
||||
|
||||
if not os.path.exists(source_path):
|
||||
print(f"Warning: {source_path} not found, skipping")
|
||||
continue
|
||||
|
||||
header_content, cpp_content = convert_shader_to_cpp(source_path, var_name)
|
||||
|
||||
header_path = os.path.join(output_dir, f'{var_name}.h')
|
||||
cpp_path = os.path.join(output_dir, f'{var_name}.cpp')
|
||||
|
||||
with open(header_path, 'w') as f:
|
||||
f.write(header_content)
|
||||
|
||||
with open(cpp_path, 'w') as f:
|
||||
f.write(cpp_content)
|
||||
|
||||
generated_cpp_files.append(cpp_path)
|
||||
print(f"Generated {var_name}.h and {var_name}.cpp")
|
||||
|
||||
print(f"\nGenerated {len(generated_cpp_files)} shader files in {output_dir}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
13
tests/gal-regression/wasm/generated/glsl_kicad_frag.cpp
Normal file
13
tests/gal-regression/wasm/generated/glsl_kicad_frag.cpp
Normal file
File diff suppressed because one or more lines are too long
13
tests/gal-regression/wasm/generated/glsl_kicad_frag.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_kicad_frag.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from kicad_frag.glsl
|
||||
#ifndef GLSL_KICAD_FRAG_H
|
||||
#define GLSL_KICAD_FRAG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_kicad_frag;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_KICAD_FRAG_H
|
||||
13
tests/gal-regression/wasm/generated/glsl_kicad_vert.cpp
Normal file
13
tests/gal-regression/wasm/generated/glsl_kicad_vert.cpp
Normal file
File diff suppressed because one or more lines are too long
13
tests/gal-regression/wasm/generated/glsl_kicad_vert.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_kicad_vert.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from kicad_vert.glsl
|
||||
#ifndef GLSL_KICAD_VERT_H
|
||||
#define GLSL_KICAD_VERT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_kicad_vert;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_KICAD_VERT_H
|
||||
13
tests/gal-regression/wasm/generated/glsl_smaa_base.cpp
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_base.cpp
Normal file
File diff suppressed because one or more lines are too long
13
tests/gal-regression/wasm/generated/glsl_smaa_base.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_base.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_base.glsl
|
||||
#ifndef GLSL_SMAA_BASE_H
|
||||
#define GLSL_SMAA_BASE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_base;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_BASE_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_1_frag_color.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_1_frag_color.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_1_frag_color_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x33, 0x5d, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x79, 0x20, 0x3d, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x45, 0x64, 0x67, 0x65, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x53, 0x28, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x29, 0x2e, 0x78, 0x79, 0x3b, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_1_frag_color = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_1_frag_color_bytes), 170);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_1_frag_color.glsl
|
||||
#ifndef GLSL_SMAA_PASS_1_FRAG_COLOR_H
|
||||
#define GLSL_SMAA_PASS_1_FRAG_COLOR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_1_frag_color;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_1_FRAG_COLOR_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_1_frag_luma.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_1_frag_luma.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_1_frag_luma_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x33, 0x5d, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x79, 0x20, 0x3d, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x4c, 0x75, 0x6d, 0x61, 0x45, 0x64, 0x67, 0x65, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x53, 0x28, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x29, 0x2e, 0x78, 0x79, 0x3b, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_1_frag_luma = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_1_frag_luma_bytes), 169);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_1_frag_luma.glsl
|
||||
#ifndef GLSL_SMAA_PASS_1_FRAG_LUMA_H
|
||||
#define GLSL_SMAA_PASS_1_FRAG_LUMA_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_1_frag_luma;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_1_FRAG_LUMA_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_1_vert.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_1_vert.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_1_vert_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x33, 0x5d, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x2e, 0x73, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x45, 0x64, 0x67, 0x65, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x53, 0x28, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x66, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x28, 0x29, 0x3b, 0x0a, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_1_vert = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_1_vert_bytes), 179);
|
||||
|
||||
}
|
||||
}
|
||||
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_1_vert.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_1_vert.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_1_vert.glsl
|
||||
#ifndef GLSL_SMAA_PASS_1_VERT_H
|
||||
#define GLSL_SMAA_PASS_1_VERT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_1_vert;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_1_VERT_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_2_frag.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_2_frag.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_2_frag_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x70, 0x69, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x33, 0x5d, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x65, 0x64, 0x67, 0x65, 0x73, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x61, 0x72, 0x65, 0x61, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x42, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x53, 0x28, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x65, 0x64, 0x67, 0x65, 0x73, 0x54, 0x65, 0x78, 0x2c, 0x20, 0x61, 0x72, 0x65, 0x61, 0x54, 0x65, 0x78, 0x2c, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54, 0x65, 0x78, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x30, 0x2e, 0x2c, 0x30, 0x2e, 0x2c, 0x30, 0x2e, 0x2c, 0x30, 0x2e, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_2_frag = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_2_frag_bytes), 299);
|
||||
|
||||
}
|
||||
}
|
||||
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_2_frag.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_2_frag.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_2_frag.glsl
|
||||
#ifndef GLSL_SMAA_PASS_2_FRAG_H
|
||||
#define GLSL_SMAA_PASS_2_FRAG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_2_frag;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_2_FRAG_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_2_vert.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_2_vert.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_2_vert_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5b, 0x33, 0x5d, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x70, 0x69, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x2e, 0x73, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x42, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x53, 0x28, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x28, 0x29, 0x3b, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_2_vert = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_2_vert_bytes), 222);
|
||||
|
||||
}
|
||||
}
|
||||
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_2_vert.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_2_vert.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_2_vert.glsl
|
||||
#ifndef GLSL_SMAA_PASS_2_VERT_H
|
||||
#define GLSL_SMAA_PASS_2_VERT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_2_vert;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_2_VERT_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_3_frag.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_3_frag.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_3_frag_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x62, 0x6c, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x78, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x68, 0x6f, 0x6f, 0x64, 0x42, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x53, 0x28, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x2c, 0x20, 0x62, 0x6c, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x78, 0x29, 0x3b, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_3_frag = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_3_frag_bytes), 201);
|
||||
|
||||
}
|
||||
}
|
||||
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_3_frag.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_3_frag.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_3_frag.glsl
|
||||
#ifndef GLSL_SMAA_PASS_3_FRAG_H
|
||||
#define GLSL_SMAA_PASS_3_FRAG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_3_frag;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_3_FRAG_H
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated from smaa_pass_3_vert.glsl
|
||||
#include <string>
|
||||
#include "glsl_smaa_pass_3_vert.h"
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
|
||||
static unsigned char glsl_smaa_pass_3_vert_bytes[] = { 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x2e, 0x73, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4d, 0x41, 0x41, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x68, 0x6f, 0x6f, 0x64, 0x42, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x56, 0x53, 0x28, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x28, 0x29, 0x3b, 0x0a, 0x7d, 0x00 };
|
||||
|
||||
std::string glsl_smaa_pass_3_vert = std::string(reinterpret_cast<char const*>(glsl_smaa_pass_3_vert_bytes), 181);
|
||||
|
||||
}
|
||||
}
|
||||
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_3_vert.h
Normal file
13
tests/gal-regression/wasm/generated/glsl_smaa_pass_3_vert.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated shader header from smaa_pass_3_vert.glsl
|
||||
#ifndef GLSL_SMAA_PASS_3_VERT_H
|
||||
#define GLSL_SMAA_PASS_3_VERT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_SHADERS {
|
||||
extern std::string glsl_smaa_pass_3_vert;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLSL_SMAA_PASS_3_VERT_H
|
||||
14980
tests/gal-regression/wasm/webgl/SmaaAreaTex.h
Normal file
14980
tests/gal-regression/wasm/webgl/SmaaAreaTex.h
Normal file
File diff suppressed because it is too large
Load diff
132
tests/gal-regression/wasm/webgl/SmaaSearchTex.h
Normal file
132
tests/gal-regression/wasm/webgl/SmaaSearchTex.h
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com)
|
||||
* Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
||||
* Copyright (C) 2013 Belen Masia (bmasia@unizar.es)
|
||||
* Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com)
|
||||
* Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to
|
||||
* do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software. As clarification, there
|
||||
* is no requirement that the copyright notice and permission be included in
|
||||
* binary distributions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SEARCHTEX_H
|
||||
#define SEARCHTEX_H
|
||||
|
||||
#define SEARCHTEX_WIDTH 64
|
||||
#define SEARCHTEX_HEIGHT 16
|
||||
#define SEARCHTEX_PITCH SEARCHTEX_WIDTH
|
||||
#define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH)
|
||||
|
||||
/**
|
||||
* Stored in R8 format. Load it in the following format:
|
||||
* - DX9: D3DFMT_L8
|
||||
* - DX10: DXGI_FORMAT_R8_UNORM
|
||||
*/
|
||||
static const unsigned char searchTexBytes[] = {
|
||||
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
|
||||
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
|
||||
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#endif
|
||||
143
tests/gal-regression/wasm/webgl/antialiasing.h
Normal file
143
tests/gal-regression/wasm/webgl/antialiasing.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef OPENGL_ANTIALIASING_H__
|
||||
#define OPENGL_ANTIALIASING_H__
|
||||
|
||||
#include <memory>
|
||||
#include "shader.h"
|
||||
#include <math/vector2d.h>
|
||||
|
||||
namespace KIGFX {
|
||||
|
||||
class WEBGL_COMPOSITOR;
|
||||
|
||||
class OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
virtual ~OPENGL_PRESENTOR()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Init() = 0;
|
||||
virtual unsigned int CreateBuffer() = 0;
|
||||
|
||||
virtual VECTOR2I GetInternalBufferSize() = 0;
|
||||
virtual void OnLostBuffers() = 0;
|
||||
|
||||
virtual void Begin() = 0;
|
||||
virtual void DrawBuffer( GLuint aBuffer ) = 0;
|
||||
virtual void Present() = 0;
|
||||
};
|
||||
|
||||
|
||||
class ANTIALIASING_NONE : public OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
ANTIALIASING_NONE( WEBGL_COMPOSITOR* aCompositor );
|
||||
|
||||
bool Init() override;
|
||||
unsigned int CreateBuffer() override;
|
||||
|
||||
VECTOR2I GetInternalBufferSize() override;
|
||||
void OnLostBuffers() override;
|
||||
|
||||
void Begin() override;
|
||||
void DrawBuffer( GLuint aBuffer ) override;
|
||||
void Present() override;
|
||||
|
||||
private:
|
||||
WEBGL_COMPOSITOR* compositor;
|
||||
};
|
||||
|
||||
|
||||
class ANTIALIASING_SUPERSAMPLING : public OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
ANTIALIASING_SUPERSAMPLING( WEBGL_COMPOSITOR* aCompositor );
|
||||
|
||||
bool Init() override;
|
||||
unsigned int CreateBuffer() override;
|
||||
|
||||
VECTOR2I GetInternalBufferSize() override;
|
||||
void OnLostBuffers() override;
|
||||
|
||||
void Begin() override;
|
||||
void DrawBuffer( GLuint ) override;
|
||||
void Present() override;
|
||||
|
||||
private:
|
||||
WEBGL_COMPOSITOR* compositor;
|
||||
|
||||
unsigned int ssaaMainBuffer;
|
||||
bool areBuffersCreated;
|
||||
|
||||
bool areShadersCreated;
|
||||
};
|
||||
|
||||
class ANTIALIASING_SMAA : public OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
ANTIALIASING_SMAA( WEBGL_COMPOSITOR* aCompositor );
|
||||
|
||||
bool Init() override;
|
||||
unsigned int CreateBuffer () override;
|
||||
|
||||
VECTOR2I GetInternalBufferSize() override;
|
||||
void OnLostBuffers() override;
|
||||
|
||||
void Begin() override;
|
||||
void DrawBuffer( GLuint buffer ) override;
|
||||
void Present() override;
|
||||
|
||||
private:
|
||||
void loadShaders();
|
||||
void updateUniforms();
|
||||
|
||||
bool areBuffersInitialized;
|
||||
|
||||
unsigned int smaaBaseBuffer; // base + overlay temporary
|
||||
unsigned int smaaEdgesBuffer;
|
||||
unsigned int smaaBlendBuffer;
|
||||
|
||||
// smaa shader lookup textures
|
||||
unsigned int smaaAreaTex;
|
||||
unsigned int smaaSearchTex;
|
||||
|
||||
bool shadersLoaded;
|
||||
|
||||
std::unique_ptr<SHADER> pass_1_shader;
|
||||
GLint pass_1_metrics;
|
||||
|
||||
std::unique_ptr<SHADER> pass_2_shader;
|
||||
GLint pass_2_metrics;
|
||||
|
||||
std::unique_ptr<SHADER> pass_3_shader;
|
||||
GLint pass_3_metrics;
|
||||
|
||||
WEBGL_COMPOSITOR* compositor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1319
tests/gal-regression/wasm/webgl/bitmap_font_desc.c
Normal file
1319
tests/gal-regression/wasm/webgl/bitmap_font_desc.c
Normal file
File diff suppressed because it is too large
Load diff
1029
tests/gal-regression/wasm/webgl/bitmap_font_img.c
Normal file
1029
tests/gal-regression/wasm/webgl/bitmap_font_img.c
Normal file
File diff suppressed because one or more lines are too long
442
tests/gal-regression/wasm/webgl/cached_container.cpp
Normal file
442
tests/gal-regression/wasm/webgl/cached_container.cpp
Normal file
|
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cached_container.cpp
|
||||
* @brief Class to store instances of VERTEX with caching. It allows storing VERTEX objects and
|
||||
* associates them with VERTEX_ITEMs. This leads to a possibility of caching vertices data in the
|
||||
* GPU memory and a fast reuse of that data.
|
||||
*/
|
||||
|
||||
#include "cached_container.h"
|
||||
#include "vertex_manager.h"
|
||||
#include "vertex_item.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <excpt.h>
|
||||
#endif
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
#include <wx/log.h>
|
||||
#include <core/profile.h>
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
|
||||
VERTEX_CONTAINER( aSize ),
|
||||
m_item( nullptr ),
|
||||
m_chunkSize( 0 ),
|
||||
m_chunkOffset( 0 ),
|
||||
m_maxIndex( 0 )
|
||||
{
|
||||
// In the beginning there is only free space
|
||||
m_freeChunks.insert( std::make_pair( aSize, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||
{
|
||||
assert( aItem != nullptr );
|
||||
|
||||
unsigned int itemSize = aItem->GetSize();
|
||||
m_item = aItem;
|
||||
m_chunkSize = itemSize;
|
||||
|
||||
// Get the previously set offset if the item was stored previously
|
||||
m_chunkOffset = itemSize > 0 ? aItem->GetOffset() : -1;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::FinishItem()
|
||||
{
|
||||
assert( m_item != nullptr );
|
||||
|
||||
unsigned int itemSize = m_item->GetSize();
|
||||
|
||||
// Finishing the previously edited item
|
||||
if( itemSize < m_chunkSize )
|
||||
{
|
||||
// There is some not used but reserved memory left, so we should return it to the pool
|
||||
int itemOffset = m_item->GetOffset();
|
||||
|
||||
// Add the not used memory back to the pool
|
||||
addFreeChunk( itemOffset + itemSize, m_chunkSize - itemSize );
|
||||
|
||||
// mergeFreeChunks(); // veery slow and buggy
|
||||
|
||||
m_maxIndex = std::max( itemOffset + itemSize, m_maxIndex );
|
||||
}
|
||||
|
||||
if( itemSize > 0 )
|
||||
m_items.insert( m_item );
|
||||
|
||||
m_item = nullptr;
|
||||
m_chunkSize = 0;
|
||||
m_chunkOffset = 0;
|
||||
|
||||
#if CACHED_CONTAINER_TEST > 1
|
||||
test();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
|
||||
{
|
||||
assert( m_item != nullptr );
|
||||
assert( IsMapped() );
|
||||
|
||||
if( m_failed )
|
||||
return nullptr;
|
||||
|
||||
unsigned int itemSize = m_item->GetSize();
|
||||
unsigned int newSize = itemSize + aSize;
|
||||
|
||||
if( newSize > m_chunkSize )
|
||||
{
|
||||
// There is not enough space in the currently reserved chunk, so we have to resize it
|
||||
if( !reallocate( newSize ) )
|
||||
{
|
||||
m_failed = true;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VERTEX* reserved = &m_vertices[m_chunkOffset + itemSize];
|
||||
|
||||
// Now the item officially possesses the memory chunk
|
||||
m_item->setSize( newSize );
|
||||
|
||||
// The content has to be updated
|
||||
m_dirty = true;
|
||||
|
||||
#if CACHED_CONTAINER_TEST > 0
|
||||
test();
|
||||
#endif
|
||||
#if CACHED_CONTAINER_TEST > 2
|
||||
showFreeChunks();
|
||||
showUsedChunks();
|
||||
#endif
|
||||
|
||||
return reserved;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::Delete( VERTEX_ITEM* aItem )
|
||||
{
|
||||
assert( aItem != nullptr );
|
||||
assert( m_items.find( aItem ) != m_items.end() || aItem->GetSize() == 0 );
|
||||
|
||||
int size = aItem->GetSize();
|
||||
|
||||
if( size == 0 )
|
||||
return; // Item is not stored here
|
||||
|
||||
int offset = aItem->GetOffset();
|
||||
|
||||
// Insert a free memory chunk entry in the place where item was stored
|
||||
addFreeChunk( offset, size );
|
||||
|
||||
// Indicate that the item is not stored in the container anymore
|
||||
aItem->setSize( 0 );
|
||||
|
||||
m_items.erase( aItem );
|
||||
|
||||
#if CACHED_CONTAINER_TEST > 0
|
||||
test();
|
||||
#endif
|
||||
|
||||
// This dynamic memory freeing optimize memory usage, but in fact can create
|
||||
// out of memory issues because freeing and reallocation large chunks of memory
|
||||
// can create memory fragmentation and no room to reallocate large chunks
|
||||
// after many free/reallocate cycles during a session using the same complex board
|
||||
// So it can be disable.
|
||||
// Currently: it is disable to avoid "out of memory" issues
|
||||
#if 0
|
||||
// Dynamic memory freeing, there is no point in holding
|
||||
// a large amount of memory when there is no use for it
|
||||
if( m_freeSpace > ( 0.75 * m_currentSize ) && m_currentSize > m_initialSize )
|
||||
{
|
||||
defragmentResize( 0.5 * m_currentSize );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::Clear()
|
||||
{
|
||||
m_freeSpace = m_currentSize;
|
||||
m_maxIndex = 0;
|
||||
m_failed = false;
|
||||
|
||||
// Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
|
||||
// in the container anymore
|
||||
for( ITEMS::iterator it = m_items.begin(); it != m_items.end(); ++it )
|
||||
( *it )->setSize( 0 );
|
||||
|
||||
m_items.clear();
|
||||
|
||||
// Now there is only free space left
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER::reallocate( unsigned int aSize )
|
||||
{
|
||||
assert( aSize > 0 );
|
||||
assert( IsMapped() );
|
||||
|
||||
unsigned int itemSize = m_item->GetSize();
|
||||
|
||||
// Find a free space chunk >= aSize
|
||||
FREE_CHUNK_MAP::iterator newChunk = m_freeChunks.lower_bound( aSize );
|
||||
|
||||
// Is there enough space to store vertices?
|
||||
if( newChunk == m_freeChunks.end() )
|
||||
{
|
||||
bool result;
|
||||
|
||||
// Would it be enough to double the current space?
|
||||
if( aSize < m_freeSpace + m_currentSize )
|
||||
{
|
||||
// Yes: exponential growing
|
||||
result = defragmentResize( m_currentSize * 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No: grow to the nearest greater power of 2
|
||||
result = defragmentResize( pow( 2, ceil( log2( m_currentSize * 2 + aSize ) ) ) );
|
||||
}
|
||||
|
||||
if( !result )
|
||||
return false;
|
||||
|
||||
newChunk = m_freeChunks.lower_bound( aSize );
|
||||
assert( newChunk != m_freeChunks.end() );
|
||||
}
|
||||
|
||||
// Parameters of the allocated chunk
|
||||
unsigned int newChunkSize = getChunkSize( *newChunk );
|
||||
unsigned int newChunkOffset = getChunkOffset( *newChunk );
|
||||
|
||||
assert( newChunkSize >= aSize );
|
||||
assert( newChunkOffset < m_currentSize );
|
||||
|
||||
// Check if the item was previously stored in the container
|
||||
if( itemSize > 0 )
|
||||
{
|
||||
// The item was reallocated, so we have to copy all the old data to the new place
|
||||
memcpy( &m_vertices[newChunkOffset], &m_vertices[m_chunkOffset], itemSize * VERTEX_SIZE );
|
||||
|
||||
// Free the space used by the previous chunk
|
||||
addFreeChunk( m_chunkOffset, m_chunkSize );
|
||||
}
|
||||
|
||||
// Remove the new allocated chunk from the free space pool
|
||||
m_freeChunks.erase( newChunk );
|
||||
m_freeSpace -= newChunkSize;
|
||||
|
||||
m_chunkSize = newChunkSize;
|
||||
m_chunkOffset = newChunkOffset;
|
||||
|
||||
m_item->setOffset( m_chunkOffset );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::defragment( VERTEX* aTarget )
|
||||
{
|
||||
// Defragmentation
|
||||
ITEMS::iterator it, it_end;
|
||||
int newOffset = 0;
|
||||
|
||||
[&]()
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
#ifdef __MINGW32__
|
||||
// currently, because SEH (Structured Exception Handling) is not documented on msys
|
||||
// (for instance __try or __try1 exists without doc) or is not supported, do nothing
|
||||
#else
|
||||
__try
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
for( VERTEX_ITEM* item : m_items )
|
||||
{
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VERTEX_SIZE );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Move the current item and place it at the end
|
||||
if( m_item->GetSize() > 0 )
|
||||
{
|
||||
memcpy( &aTarget[newOffset], &m_vertices[m_item->GetOffset()],
|
||||
m_item->GetSize() * VERTEX_SIZE );
|
||||
m_item->setOffset( newOffset );
|
||||
m_chunkOffset = newOffset;
|
||||
}
|
||||
}
|
||||
#ifdef __WIN32__
|
||||
#ifdef __MINGW32__
|
||||
// currently, because SEH (Structured Exception Handling) is not documented on msys
|
||||
// (for instance __except1 exists without doc) or is not supported, do nothing
|
||||
#else
|
||||
__except( GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER
|
||||
: EXCEPTION_CONTINUE_SEARCH )
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Access violation in defragment. This is usually an indicator of "
|
||||
"system or GPU memory running low." );
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
}();
|
||||
|
||||
m_maxIndex = usedSpace();
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::mergeFreeChunks()
|
||||
{
|
||||
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
|
||||
return;
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
PROF_TIMER totalTime;
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
// Reversed free chunks map - this one stores chunk size with its offset as the key
|
||||
std::list<CHUNK> freeChunks;
|
||||
|
||||
FREE_CHUNK_MAP::const_iterator it, it_end;
|
||||
|
||||
for( it = m_freeChunks.begin(), it_end = m_freeChunks.end(); it != it_end; ++it )
|
||||
{
|
||||
freeChunks.emplace_back( it->second, it->first );
|
||||
}
|
||||
|
||||
m_freeChunks.clear();
|
||||
freeChunks.sort();
|
||||
|
||||
std::list<CHUNK>::const_iterator itf, itf_end;
|
||||
unsigned int offset = freeChunks.front().first;
|
||||
unsigned int size = freeChunks.front().second;
|
||||
freeChunks.pop_front();
|
||||
|
||||
for( itf = freeChunks.begin(), itf_end = freeChunks.end(); itf != itf_end; ++itf )
|
||||
{
|
||||
if( itf->first == offset + size )
|
||||
{
|
||||
// These chunks can be merged, so just increase the current chunk size and go on
|
||||
size += itf->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// These chunks cannot be merged
|
||||
// So store the previous one
|
||||
m_freeChunks.insert( std::make_pair( size, offset ) );
|
||||
|
||||
// and let's check the next chunk
|
||||
offset = itf->first;
|
||||
size = itf->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last one
|
||||
m_freeChunks.insert( std::make_pair( size, offset ) );
|
||||
|
||||
#if CACHED_CONTAINER_TEST > 0
|
||||
test();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::addFreeChunk( unsigned int aOffset, unsigned int aSize )
|
||||
{
|
||||
assert( aOffset + aSize <= m_currentSize );
|
||||
assert( aSize > 0 );
|
||||
|
||||
m_freeChunks.insert( std::make_pair( aSize, aOffset ) );
|
||||
m_freeSpace += aSize;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::showFreeChunks()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::showUsedChunks()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::test()
|
||||
{
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
// Free space check
|
||||
unsigned int freeSpace = 0;
|
||||
FREE_CHUNK_MAP::iterator itf;
|
||||
|
||||
for( itf = m_freeChunks.begin(); itf != m_freeChunks.end(); ++itf )
|
||||
freeSpace += getChunkSize( *itf );
|
||||
|
||||
assert( freeSpace == m_freeSpace );
|
||||
|
||||
// Used space check
|
||||
unsigned int used_space = 0;
|
||||
ITEMS::iterator itr;
|
||||
|
||||
for( itr = m_items.begin(); itr != m_items.end(); ++itr )
|
||||
used_space += ( *itr )->GetSize();
|
||||
|
||||
// If we have a chunk assigned, then there must be an item edited
|
||||
assert( m_chunkSize == 0 || m_item );
|
||||
|
||||
// Currently reserved chunk is also counted as used
|
||||
used_space += m_chunkSize;
|
||||
|
||||
assert( ( m_freeSpace + used_space ) == m_currentSize );
|
||||
|
||||
// Overlapping check TODO
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
}
|
||||
191
tests/gal-regression/wasm/webgl/cached_container.h
Normal file
191
tests/gal-regression/wasm/webgl/cached_container.h
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHED_CONTAINER_H_
|
||||
#define CACHED_CONTAINER_H_
|
||||
|
||||
#include "vertex_container.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
/**
|
||||
* Class to store VERTEX instances with caching.
|
||||
*
|
||||
* It associates VERTEX objects and with VERTEX_ITEMs. Caching vertices data in the memory and a
|
||||
* enables fast reuse of that data.
|
||||
*/
|
||||
|
||||
class CACHED_CONTAINER : public VERTEX_CONTAINER
|
||||
{
|
||||
public:
|
||||
CACHED_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
|
||||
virtual ~CACHED_CONTAINER() {}
|
||||
|
||||
bool IsCached() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void SetItem( VERTEX_ITEM* aItem ) override;
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::FinishItem()
|
||||
virtual void FinishItem() override;
|
||||
|
||||
/**
|
||||
* Return allocated space for the requested number of vertices associated with the
|
||||
* current item (set with SetItem()).
|
||||
*
|
||||
* The allocated space is added at the end of the chunk used by the current item and
|
||||
* may serve to store new vertices.
|
||||
*
|
||||
* @param aSize is the number of vertices to be allocated.
|
||||
* @return Pointer to the allocated space.
|
||||
* @throw bad_alloc exception if allocation fails.
|
||||
*/
|
||||
virtual VERTEX* Allocate( unsigned int aSize ) override;
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Delete()
|
||||
virtual void Delete( VERTEX_ITEM* aItem ) override;
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Clear()
|
||||
virtual void Clear() override;
|
||||
|
||||
/**
|
||||
* Return handle to the vertex buffer. It might be negative if the buffer is not initialized.
|
||||
*/
|
||||
virtual unsigned int GetBufferHandle() const = 0;
|
||||
|
||||
/**
|
||||
* Return true if vertex buffer is currently mapped.
|
||||
*/
|
||||
virtual bool IsMapped() const = 0;
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Map()
|
||||
virtual void Map() override = 0;
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Unmap()
|
||||
virtual void Unmap() override = 0;
|
||||
|
||||
virtual unsigned int AllItemsSize() const { return 0; }
|
||||
|
||||
protected:
|
||||
///< Maps size of free memory chunks to their offsets
|
||||
typedef std::pair<unsigned int, unsigned int> CHUNK;
|
||||
typedef std::multimap<unsigned int, unsigned int> FREE_CHUNK_MAP;
|
||||
|
||||
/// List of all the stored items
|
||||
typedef std::set<VERTEX_ITEM*> ITEMS;
|
||||
|
||||
/**
|
||||
* Resize the chunk that stores the current item to the given size. The current item has
|
||||
* its offset adjusted after the call, and the new chunk parameters are stored
|
||||
* in m_chunkOffset and m_chunkSize.
|
||||
*
|
||||
* @param aSize is the requested chunk size.
|
||||
* @return true in case of success, false otherwise.
|
||||
*/
|
||||
bool reallocate( unsigned int aSize );
|
||||
|
||||
/**
|
||||
* Remove empty spaces between chunks and optionally resizes the container.
|
||||
*
|
||||
* After the operation there is continuous space for storing vertices at the end of the
|
||||
* container.
|
||||
*
|
||||
* @param aNewSize is the new size of container, expressed in number of vertices.
|
||||
* @return false in case of failure (e.g. memory shortage).
|
||||
*/
|
||||
virtual bool defragmentResize( unsigned int aNewSize ) = 0;
|
||||
|
||||
/**
|
||||
* Transfer all stored data to a new buffer, removing empty spaces between the data chunks
|
||||
* in the container.
|
||||
*
|
||||
* @param aTarget is the destination for the defragmented data.
|
||||
*/
|
||||
void defragment( VERTEX* aTarget );
|
||||
|
||||
/**
|
||||
* Look for consecutive free memory chunks and merges them, decreasing fragmentation of
|
||||
* memory.
|
||||
*/
|
||||
void mergeFreeChunks();
|
||||
|
||||
/**
|
||||
* Return the size of a chunk.
|
||||
*
|
||||
* @param aChunk is the chunk.
|
||||
*/
|
||||
inline int getChunkSize( const CHUNK& aChunk ) const
|
||||
{
|
||||
return aChunk.first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the offset of a chunk.
|
||||
*
|
||||
* @param aChunk is the chunk.
|
||||
*/
|
||||
inline unsigned int getChunkOffset( const CHUNK& aChunk ) const
|
||||
{
|
||||
return aChunk.second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a chunk marked as a free space.
|
||||
*/
|
||||
void addFreeChunk( unsigned int aOffset, unsigned int aSize );
|
||||
|
||||
///< Store size & offset of free chunks.
|
||||
FREE_CHUNK_MAP m_freeChunks;
|
||||
|
||||
///< Stored VERTEX_ITEMs
|
||||
ITEMS m_items;
|
||||
|
||||
///< Currently modified item
|
||||
VERTEX_ITEM* m_item;
|
||||
|
||||
///< Properties of currently modified chunk & item
|
||||
unsigned int m_chunkSize;
|
||||
unsigned int m_chunkOffset;
|
||||
|
||||
///< Maximal vertex index number stored in the container
|
||||
unsigned int m_maxIndex;
|
||||
|
||||
private:
|
||||
/// Debug & test functions
|
||||
void showFreeChunks();
|
||||
void showUsedChunks();
|
||||
void test();
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* CACHED_CONTAINER_H_ */
|
||||
312
tests/gal-regression/wasm/webgl/cached_container_gpu.cpp
Normal file
312
tests/gal-regression/wasm/webgl/cached_container_gpu.cpp
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "cached_container_gpu.h"
|
||||
#include "vertex_manager.h"
|
||||
#include "vertex_item.h"
|
||||
#include "shader.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <wx/log.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <core/profile.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
/**
|
||||
* Flag to enable debug output of the GAL OpenGL GPU cached container.
|
||||
*
|
||||
* Use "KICAD_GAL_CACHED_CONTAINER_GPU" to enable GAL OpenGL GPU cached container tracing.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar* const traceGalCachedContainerGpu = wxT( "KICAD_GAL_CACHED_CONTAINER_GPU" );
|
||||
|
||||
|
||||
CACHED_CONTAINER_GPU::CACHED_CONTAINER_GPU( unsigned int aSize ) :
|
||||
CACHED_CONTAINER( aSize ),
|
||||
m_isMapped( false ),
|
||||
m_glBufferHandle( -1 )
|
||||
{
|
||||
m_useCopyBuffer = GLEW_ARB_copy_buffer;
|
||||
|
||||
wxString vendor( glGetString( GL_VENDOR ) );
|
||||
|
||||
// workaround for intel GPU drivers:
|
||||
// disable glCopyBuffer, causes crashes/freezes on certain driver versions
|
||||
// Note, Intel's GL_VENDOR string varies depending on GPU/driver generation
|
||||
// But generally always starts with Intel at least
|
||||
if( vendor.StartsWith( "Intel" ) || vendor.Contains( "etnaviv" ) )
|
||||
{
|
||||
m_useCopyBuffer = false;
|
||||
}
|
||||
|
||||
KI_TRACE( traceGalProfile, "VBO initial size: %d\n", m_currentSize );
|
||||
|
||||
glGenBuffers( 1, &m_glBufferHandle );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
|
||||
glBufferData( GL_ARRAY_BUFFER, m_currentSize * VERTEX_SIZE, nullptr, GL_DYNAMIC_DRAW );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
checkGlError( "allocating video memory for cached container", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
|
||||
CACHED_CONTAINER_GPU::~CACHED_CONTAINER_GPU()
|
||||
{
|
||||
if( m_isMapped )
|
||||
Unmap();
|
||||
|
||||
if( glDeleteBuffers )
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_GPU::Map()
|
||||
{
|
||||
wxCHECK( !IsMapped(), /*void*/ );
|
||||
|
||||
// OpenGL version might suddenly stop being available in Windows when an RDP session is started
|
||||
if( !glBindBuffer )
|
||||
throw std::runtime_error( "OpenGL no longer available!" );
|
||||
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
|
||||
m_vertices = static_cast<VERTEX*>( glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ) );
|
||||
|
||||
if( checkGlError( "mapping vertices buffer", __FILE__, __LINE__ ) == GL_NO_ERROR )
|
||||
m_isMapped = true;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_GPU::Unmap()
|
||||
{
|
||||
wxCHECK( IsMapped(), /*void*/ );
|
||||
|
||||
// This gets called from ~CACHED_CONTAINER_GPU. To avoid throwing an exception from
|
||||
// the dtor, catch it here instead.
|
||||
try
|
||||
{
|
||||
glUnmapBuffer( GL_ARRAY_BUFFER );
|
||||
checkGlError( "unmapping vertices buffer", __FILE__, __LINE__ );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
m_vertices = nullptr;
|
||||
checkGlError( "unbinding vertices buffer", __FILE__, __LINE__ );
|
||||
}
|
||||
catch( const std::runtime_error& err )
|
||||
{
|
||||
wxLogError( wxT( "OpenGL did not shut down properly.\n\n%s" ), err.what() );
|
||||
}
|
||||
|
||||
m_isMapped = false;
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER_GPU::defragmentResize( unsigned int aNewSize )
|
||||
{
|
||||
if( !m_useCopyBuffer )
|
||||
return defragmentResizeMemcpy( aNewSize );
|
||||
|
||||
wxCHECK( IsMapped(), false );
|
||||
|
||||
wxLogTrace( traceGalCachedContainerGpu,
|
||||
wxT( "Resizing & defragmenting container from %d to %d" ), m_currentSize,
|
||||
aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
PROF_TIMER totalTime;
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
GLuint newBuffer;
|
||||
|
||||
// glCopyBufferSubData requires a buffer to be unmapped
|
||||
glUnmapBuffer( GL_ARRAY_BUFFER );
|
||||
|
||||
// Create a new destination buffer
|
||||
glGenBuffers( 1, &newBuffer );
|
||||
|
||||
// It would be best to use GL_COPY_WRITE_BUFFER here,
|
||||
// but it is not available everywhere
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
GLint eaBuffer = -1;
|
||||
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
|
||||
wxASSERT( eaBuffer == 0 );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VERTEX_SIZE, nullptr, GL_DYNAMIC_DRAW );
|
||||
checkGlError( "creating buffer during defragmentation", __FILE__, __LINE__ );
|
||||
|
||||
ITEMS::iterator it, it_end;
|
||||
int newOffset = 0;
|
||||
|
||||
// Defragmentation
|
||||
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||
{
|
||||
VERTEX_ITEM* item = *it;
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, itemOffset * VERTEX_SIZE,
|
||||
newOffset * VERTEX_SIZE, itemSize * VERTEX_SIZE );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Move the current item and place it at the end
|
||||
if( m_item->GetSize() > 0 )
|
||||
{
|
||||
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
||||
m_item->GetOffset() * VERTEX_SIZE, newOffset * VERTEX_SIZE,
|
||||
m_item->GetSize() * VERTEX_SIZE );
|
||||
|
||||
m_item->setOffset( newOffset );
|
||||
m_chunkOffset = newOffset;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
|
||||
// Previously we have unmapped the array buffer, now when it is also
|
||||
// unbound, it may be officially marked as unmapped
|
||||
m_isMapped = false;
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
m_glBufferHandle = newBuffer;
|
||||
Map();
|
||||
checkGlError( "switching buffers during defragmentation", __FILE__, __LINE__ );
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( traceGalCachedContainerGpu, "Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
KI_TRACE( traceGalProfile, "VBO size %d used %d\n", m_currentSize, AllItemsSize() );
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER_GPU::defragmentResizeMemcpy( unsigned int aNewSize )
|
||||
{
|
||||
wxCHECK( IsMapped(), false );
|
||||
|
||||
wxLogTrace( traceGalCachedContainerGpu,
|
||||
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ), m_currentSize,
|
||||
aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
PROF_TIMER totalTime;
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
GLuint newBuffer;
|
||||
VERTEX* newBufferMem;
|
||||
|
||||
// Create the destination buffer
|
||||
glGenBuffers( 1, &newBuffer );
|
||||
|
||||
// It would be best to use GL_COPY_WRITE_BUFFER here,
|
||||
// but it is not available everywhere
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
GLint eaBuffer = -1;
|
||||
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
|
||||
wxASSERT( eaBuffer == 0 );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VERTEX_SIZE, nullptr, GL_DYNAMIC_DRAW );
|
||||
newBufferMem = static_cast<VERTEX*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
|
||||
checkGlError( "creating buffer during defragmentation", __FILE__, __LINE__ );
|
||||
|
||||
defragment( newBufferMem );
|
||||
|
||||
// Cleanup
|
||||
glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
Unmap();
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
m_glBufferHandle = newBuffer;
|
||||
Map();
|
||||
checkGlError( "switching buffers during defragmentation", __FILE__, __LINE__ );
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( traceGalCachedContainerGpu, "Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
KI_TRACE( traceGalProfile, "VBO size %d used: %d \n", m_currentSize, AllItemsSize() );
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CACHED_CONTAINER_GPU::AllItemsSize() const
|
||||
{
|
||||
unsigned int size = 0;
|
||||
|
||||
for( const auto& item : m_items )
|
||||
{
|
||||
size += item->GetSize();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
87
tests/gal-regression/wasm/webgl/cached_container_gpu.h
Normal file
87
tests/gal-regression/wasm/webgl/cached_container_gpu.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHED_CONTAINER_GPU_H_
|
||||
#define CACHED_CONTAINER_GPU_H_
|
||||
|
||||
#include "cached_container.h"
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
|
||||
/**
|
||||
* Specialization of CACHED_CONTAINER that stores data in video memory via memory mapping.
|
||||
*/
|
||||
class CACHED_CONTAINER_GPU : public CACHED_CONTAINER
|
||||
{
|
||||
public:
|
||||
CACHED_CONTAINER_GPU( unsigned int aSize = DEFAULT_SIZE );
|
||||
~CACHED_CONTAINER_GPU();
|
||||
|
||||
unsigned int GetBufferHandle() const override
|
||||
{
|
||||
return m_glBufferHandle;
|
||||
}
|
||||
|
||||
bool IsMapped() const override
|
||||
{
|
||||
return m_isMapped;
|
||||
}
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Map()
|
||||
void Map() override;
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Unmap() override;
|
||||
|
||||
virtual unsigned int AllItemsSize() const override;
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Remove empty spaces between chunks and optionally resizes the container.
|
||||
*
|
||||
* After the operation there is continuous space for storing vertices at the end of
|
||||
* the container.
|
||||
*
|
||||
* @param aNewSize is the new size of container, expressed in number of vertices.
|
||||
* @return false in case of failure (e.g. memory shortage).
|
||||
*/
|
||||
bool defragmentResize( unsigned int aNewSize ) override;
|
||||
bool defragmentResizeMemcpy( unsigned int aNewSize );
|
||||
|
||||
///< Flag saying if vertex buffer is currently mapped
|
||||
bool m_isMapped;
|
||||
|
||||
///< Vertex buffer handle
|
||||
unsigned int m_glBufferHandle;
|
||||
|
||||
///< Flag saying whether it is safe to use glCopyBufferSubData
|
||||
bool m_useCopyBuffer;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* CACHED_CONTAINER_GPU_H_ */
|
||||
134
tests/gal-regression/wasm/webgl/cached_container_ram.cpp
Normal file
134
tests/gal-regression/wasm/webgl/cached_container_ram.cpp
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "cached_container_ram.h"
|
||||
#include "vertex_manager.h"
|
||||
#include "vertex_item.h"
|
||||
#include "shader.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <confirm.h>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
|
||||
#include <wx/log.h>
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
#include <core/profile.h>
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable debug output of the GAL OpenGL cached container.
|
||||
*
|
||||
* Use "KICAD_GAL_CACHED_CONTAINER" to enable GAL OpenGL cached container tracing.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar* const traceGalCachedContainer = wxT( "KICAD_GAL_CACHED_CONTAINER" );
|
||||
|
||||
|
||||
CACHED_CONTAINER_RAM::CACHED_CONTAINER_RAM( unsigned int aSize ) :
|
||||
CACHED_CONTAINER( aSize ),
|
||||
m_verticesBuffer( 0 )
|
||||
{
|
||||
glGenBuffers( 1, &m_verticesBuffer );
|
||||
checkGlError( "generating vertices buffer", __FILE__, __LINE__ );
|
||||
|
||||
m_vertices = static_cast<VERTEX*>( malloc( aSize * VERTEX_SIZE ) );
|
||||
|
||||
if( !m_vertices )
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
|
||||
CACHED_CONTAINER_RAM::~CACHED_CONTAINER_RAM()
|
||||
{
|
||||
if( glDeleteBuffers )
|
||||
glDeleteBuffers( 1, &m_verticesBuffer );
|
||||
|
||||
free( m_vertices );
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_RAM::Unmap()
|
||||
{
|
||||
if( !m_dirty )
|
||||
return;
|
||||
|
||||
// Upload vertices coordinates and shader types to GPU memory
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
|
||||
checkGlError( "binding vertices buffer", __FILE__, __LINE__ );
|
||||
glBufferData( GL_ARRAY_BUFFER, m_maxIndex * VERTEX_SIZE, m_vertices, GL_STREAM_DRAW );
|
||||
checkGlError( "transferring vertices", __FILE__, __LINE__ );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
checkGlError( "unbinding vertices buffer", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER_RAM::defragmentResize( unsigned int aNewSize )
|
||||
{
|
||||
wxLogTrace( traceGalCachedContainer,
|
||||
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ), m_currentSize,
|
||||
aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
PROF_TIMER totalTime;
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
VERTEX* newBufferMem = static_cast<VERTEX*>( malloc( aNewSize * VERTEX_SIZE ) );
|
||||
|
||||
if( !newBufferMem )
|
||||
throw std::bad_alloc();
|
||||
|
||||
defragment( newBufferMem );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
free( m_vertices );
|
||||
m_vertices = newBufferMem;
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( traceGalCachedContainer, "Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
m_dirty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
86
tests/gal-regression/wasm/webgl/cached_container_ram.h
Normal file
86
tests/gal-regression/wasm/webgl/cached_container_ram.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHED_CONTAINER_RAM_H_
|
||||
#define CACHED_CONTAINER_RAM_H_
|
||||
|
||||
#include "cached_container.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
/**
|
||||
* Specialization of CACHED_CONTAINER that stores data in RAM.
|
||||
*
|
||||
* This is mainly for video cards/drivers that do not cope well with video memory mapping.
|
||||
*/
|
||||
|
||||
class CACHED_CONTAINER_RAM : public CACHED_CONTAINER
|
||||
{
|
||||
public:
|
||||
CACHED_CONTAINER_RAM( unsigned int aSize = DEFAULT_SIZE );
|
||||
~CACHED_CONTAINER_RAM();
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Map() override {}
|
||||
|
||||
///< @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Unmap() override;
|
||||
|
||||
bool IsMapped() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return handle to the vertex buffer.
|
||||
*
|
||||
* It might be negative if the buffer is not initialized.
|
||||
*/
|
||||
unsigned int GetBufferHandle() const override
|
||||
{
|
||||
return m_verticesBuffer; // make common with CACHED_CONTAINER_RAM
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Defragment the currently stored data and resizes the buffer.
|
||||
*
|
||||
* @param aNewSize is the new buffer vertex buffer size, expressed as the number of vertices.
|
||||
* @return true on success.
|
||||
*/
|
||||
bool defragmentResize( unsigned int aNewSize ) override;
|
||||
|
||||
///< Handle to vertices buffer
|
||||
GLuint m_verticesBuffer;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* CACHED_CONTAINER_RAM_H_ */
|
||||
118
tests/gal-regression/wasm/webgl/gl_context_mgr.cpp
Normal file
118
tests/gal-regression/wasm/webgl/gl_context_mgr.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "gl_context_mgr.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
wxGLContext* GL_CONTEXT_MANAGER::CreateCtx( wxGLCanvas* aCanvas, const wxGLContext* aOther )
|
||||
{
|
||||
wxGLContext* context = new wxGLContext( aCanvas, aOther );
|
||||
wxCHECK( context, nullptr );
|
||||
|
||||
if( !context->IsOK() )
|
||||
{
|
||||
delete context;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_glContexts.insert( std::make_pair( context, aCanvas ) );
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::DestroyCtx( wxGLContext* aContext )
|
||||
{
|
||||
if( m_glContexts.count( aContext ) )
|
||||
{
|
||||
m_glContexts.erase( aContext );
|
||||
delete aContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not delete unknown GL contexts
|
||||
wxFAIL;
|
||||
}
|
||||
|
||||
if( m_glCtx == aContext )
|
||||
m_glCtx = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::DeleteAll()
|
||||
{
|
||||
m_glCtxMutex.lock();
|
||||
|
||||
for( auto& ctx : m_glContexts )
|
||||
delete ctx.first;
|
||||
|
||||
m_glContexts.clear();
|
||||
m_glCtx = nullptr;
|
||||
m_glCtxMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas )
|
||||
{
|
||||
wxCHECK( aContext && m_glContexts.count( aContext ) > 0, /* void */ );
|
||||
|
||||
m_glCtxMutex.lock();
|
||||
wxGLCanvas* canvas = aCanvas ? aCanvas : m_glContexts.at( aContext );
|
||||
|
||||
// Prevent assertion failure in wxGLContext::SetCurrent during GAL teardown
|
||||
#ifdef __WXGTK__
|
||||
|
||||
#ifdef KICAD_USE_EGL
|
||||
if( canvas->GTKGetDrawingWindow() )
|
||||
#else
|
||||
if( canvas->GetXWindow() )
|
||||
#endif // KICAD_USE_EGL
|
||||
|
||||
#endif // __WXGTK__
|
||||
{
|
||||
canvas->SetCurrent( *aContext );
|
||||
}
|
||||
|
||||
m_glCtx = aContext;
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::UnlockCtx( wxGLContext* aContext )
|
||||
{
|
||||
wxCHECK( aContext && m_glContexts.count( aContext ) > 0, /* void */ );
|
||||
|
||||
if( m_glCtx == aContext )
|
||||
{
|
||||
m_glCtxMutex.unlock();
|
||||
m_glCtx = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG( wxString::Format( wxS( "Trying to unlock GL context mutex from "
|
||||
"a wrong context: aContext %p m_glCtx %p" ), aContext, m_glCtx ) );
|
||||
}
|
||||
}
|
||||
|
||||
147
tests/gal-regression/wasm/webgl/gl_context_mgr.h
Normal file
147
tests/gal-regression/wasm/webgl/gl_context_mgr.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef GL_CONTEXT_MANAGER_H
|
||||
#define GL_CONTEXT_MANAGER_H
|
||||
|
||||
#include <kicommon.h>
|
||||
#include <gal/gal.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
|
||||
class KICOMMON_API GL_CONTEXT_MANAGER
|
||||
{
|
||||
public:
|
||||
|
||||
GL_CONTEXT_MANAGER() : m_glCtx( nullptr ) {}
|
||||
|
||||
/**
|
||||
* Create a managed OpenGL context.
|
||||
*
|
||||
* It is assured that the created context is freed upon exit. See wxGLContext
|
||||
* documentation for the parameters description.
|
||||
*
|
||||
* @return Created OpenGL context.
|
||||
*/
|
||||
wxGLContext* CreateCtx( wxGLCanvas* aCanvas, const wxGLContext* aOther = nullptr );
|
||||
|
||||
/**
|
||||
* Destroy a managed OpenGL context.
|
||||
*
|
||||
* The context to be removed has to be created using GL_CONTEXT_MANAGER::CreateCtx() first.
|
||||
*
|
||||
* @param aContext is the OpenGL context to be destroyed. It will not be managed anymore.
|
||||
*/
|
||||
void DestroyCtx( wxGLContext* aContext );
|
||||
|
||||
/**
|
||||
* Destroy all managed OpenGL contexts.
|
||||
*
|
||||
* This method should be called in the final deinitialization routine.
|
||||
*/
|
||||
void DeleteAll();
|
||||
|
||||
/**
|
||||
* Set a context as current and prevents other canvases from switching it.
|
||||
*
|
||||
* Requires calling UnlockCtx() when there are no more GL calls for the context. If
|
||||
* another canvas has already locked a GL context, then the calling process is blocked.
|
||||
*
|
||||
* @param aContext is the GL context to be bound.
|
||||
* @param aCanvas (optional) allows caller to bind the context to a non-parent canvas
|
||||
* (e.g. when a few canvases share a single GL context).
|
||||
*/
|
||||
void LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas );
|
||||
|
||||
/**
|
||||
* Allow other canvases to bind an OpenGL context.
|
||||
*
|
||||
* @param aContext is the currently bound context. It is only a check to assure the right
|
||||
* canvas wants to unlock GL context.
|
||||
*/
|
||||
void UnlockCtx( wxGLContext* aContext );
|
||||
|
||||
/**
|
||||
* Get the currently bound GL context.
|
||||
*
|
||||
* @return the currently bound GL context.
|
||||
*/
|
||||
wxGLContext* GetCurrentCtx() const
|
||||
{
|
||||
return m_glCtx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently bound GL canvas.
|
||||
*
|
||||
* @return the currently bound GL canvas.
|
||||
*/
|
||||
wxGLCanvas* GetCurrentCanvas() const
|
||||
{
|
||||
auto it = m_glContexts.find( m_glCtx );
|
||||
return it != m_glContexts.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given function first releasing the GL context lock, then restoring it.
|
||||
*
|
||||
* @param aFunction is the function to be executed.
|
||||
*/
|
||||
template<typename Func, typename... Args>
|
||||
auto RunWithoutCtxLock( Func&& aFunction, Args&&... args )
|
||||
{
|
||||
wxGLContext* currentCtx = GetCurrentCtx();
|
||||
wxGLCanvas* currentCanvas = GetCurrentCanvas();
|
||||
UnlockCtx( currentCtx );
|
||||
|
||||
if constexpr (std::is_void_v<decltype(aFunction(std::forward<Args>(args)...))>)
|
||||
{
|
||||
std::forward<Func>(aFunction)(std::forward<Args>(args)...);
|
||||
LockCtx( currentCtx, currentCanvas );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = std::forward<Func>(aFunction)(std::forward<Args>(args)...);
|
||||
LockCtx( currentCtx, currentCanvas );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
///< Map of GL contexts & their parent canvases.
|
||||
std::map<wxGLContext*, wxGLCanvas*> m_glContexts;
|
||||
|
||||
///< Currently bound GL context.
|
||||
wxGLContext* m_glCtx;
|
||||
|
||||
///< Lock to prevent unexpected GL context switching.
|
||||
std::mutex m_glCtxMutex;
|
||||
};
|
||||
|
||||
#endif /* GL_CONTEXT_MANAGER_H */
|
||||
|
||||
63
tests/gal-regression/wasm/webgl/gl_resources.cpp
Normal file
63
tests/gal-regression/wasm/webgl/gl_resources.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
// The current font is "Ubuntu Mono" available under Ubuntu Font Licence 1.0
|
||||
// (see ubuntu-font-licence-1.0.txt for details)
|
||||
#include <algorithm>
|
||||
#include "gl_resources.h"
|
||||
|
||||
#define BITMAP_FONT_USE_SPANS
|
||||
|
||||
namespace KIGFX {
|
||||
namespace BUILTIN_FONT {
|
||||
|
||||
#include "bitmap_font_img.c"
|
||||
#include "bitmap_font_desc.c"
|
||||
|
||||
const FONT_GLYPH_TYPE* LookupGlyph( unsigned int aCodepoint )
|
||||
{
|
||||
#ifdef BITMAP_FONT_USE_SPANS
|
||||
auto *end = font_codepoint_spans + sizeof( font_codepoint_spans ) / sizeof(FONT_SPAN_TYPE);
|
||||
|
||||
auto ptr = std::upper_bound( font_codepoint_spans, end, aCodepoint,
|
||||
[]( unsigned int codepoint, const FONT_SPAN_TYPE& span )
|
||||
{
|
||||
return codepoint < span.end;
|
||||
} );
|
||||
|
||||
if( ptr != end && ptr->start <= aCodepoint )
|
||||
{
|
||||
unsigned int index = aCodepoint - ptr->start + ptr->cumulative;
|
||||
return &font_codepoint_infos[ index ];
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
return &bitmap_chars[codepoint];
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
73
tests/gal-regression/wasm/webgl/gl_resources.h
Normal file
73
tests/gal-regression/wasm/webgl/gl_resources.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef GAL_OPENGL_RESOURCES_H___
|
||||
#define GAL_OPENGL_RESOURCES_H___
|
||||
|
||||
#define BITMAP_FONT_USE_SPANS
|
||||
|
||||
namespace KIGFX {
|
||||
|
||||
namespace BUILTIN_FONT {
|
||||
|
||||
struct FONT_IMAGE_TYPE
|
||||
{
|
||||
unsigned int width, height;
|
||||
unsigned int char_border;
|
||||
unsigned int spacing;
|
||||
unsigned char pixels[1024 * 1024 * 3];
|
||||
};
|
||||
|
||||
struct FONT_INFO_TYPE
|
||||
{
|
||||
unsigned int smooth_pixels;
|
||||
float min_y;
|
||||
float max_y;
|
||||
};
|
||||
|
||||
struct FONT_SPAN_TYPE
|
||||
{
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
unsigned int cumulative;
|
||||
};
|
||||
|
||||
struct FONT_GLYPH_TYPE
|
||||
{
|
||||
unsigned int atlas_x, atlas_y;
|
||||
unsigned int atlas_w, atlas_h;
|
||||
float minx, maxx;
|
||||
float miny, maxy;
|
||||
float advance;
|
||||
};
|
||||
|
||||
extern FONT_IMAGE_TYPE font_image;
|
||||
extern FONT_INFO_TYPE font_information;
|
||||
|
||||
const FONT_GLYPH_TYPE* LookupGlyph( unsigned int aCodePoint );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
172
tests/gal-regression/wasm/webgl/gl_utils.h
Normal file
172
tests/gal-regression/wasm/webgl/gl_utils.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef GL_UTILS_H
|
||||
#define GL_UTILS_H
|
||||
|
||||
#include "kiglew.h" // Must be included first
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef __MINGW32__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize( "O0" )
|
||||
#else
|
||||
#pragma optimize( "", off )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class GL_UTILS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Attempt to set the OpenGL swap interval.
|
||||
*
|
||||
* @param aVal if -1 = try to set adaptive swapping, 0 = sync off, 1 = sync with VSYNC rate.
|
||||
* @return actual value set
|
||||
*/
|
||||
static int SetSwapInterval( int aVal )
|
||||
{
|
||||
#if defined( __linux__ ) && !defined( KICAD_USE_EGL )
|
||||
|
||||
if( Display* dpy = glXGetCurrentDisplay() )
|
||||
{
|
||||
GLXDrawable drawable = glXGetCurrentDrawable();
|
||||
|
||||
std::string exts( glXQueryExtensionsString( dpy, DefaultScreen( dpy ) ) );
|
||||
|
||||
if( glXSwapIntervalEXT && glXQueryDrawable && drawable
|
||||
&& exts.find( "GLX_EXT_swap_control" ) != std::string::npos )
|
||||
{
|
||||
if( aVal == -1 )
|
||||
{
|
||||
if( exts.find( "GLX_EXT_swap_control_tear" ) == std::string::npos )
|
||||
{
|
||||
aVal = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Even though the extensions might be available,
|
||||
// we need to be sure that late/adaptive swaps are
|
||||
// enabled on the drawable.
|
||||
|
||||
unsigned lateSwapsEnabled = 0;
|
||||
glXQueryDrawable( dpy, drawable, GLX_LATE_SWAPS_TEAR_EXT,
|
||||
&lateSwapsEnabled );
|
||||
|
||||
if( !lateSwapsEnabled )
|
||||
{
|
||||
aVal = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned clampedInterval;
|
||||
glXSwapIntervalEXT( dpy, drawable, aVal );
|
||||
glXQueryDrawable( dpy, drawable, GLX_SWAP_INTERVAL_EXT, &clampedInterval );
|
||||
|
||||
return clampedInterval;
|
||||
}
|
||||
|
||||
if( glXSwapIntervalMESA && glXGetSwapIntervalMESA
|
||||
&& exts.find( "GLX_MESA_swap_control" ) != std::string::npos )
|
||||
{
|
||||
if( aVal == -1 )
|
||||
aVal = 1;
|
||||
|
||||
if( !glXSwapIntervalMESA( aVal ) )
|
||||
return aVal;
|
||||
}
|
||||
|
||||
if( glXSwapIntervalSGI && exts.find( "GLX_SGI_swap_control" ) != std::string::npos )
|
||||
{
|
||||
if( aVal == -1 )
|
||||
aVal = 1;
|
||||
|
||||
if( !glXSwapIntervalSGI( aVal ) )
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined( _WIN32 )
|
||||
|
||||
const GLubyte* vendor = glGetString( GL_VENDOR );
|
||||
const GLubyte* version = glGetString( GL_VERSION );
|
||||
|
||||
if( wglSwapIntervalEXT && wxGLCanvas::IsExtensionSupported( "WGL_EXT_swap_control" ) )
|
||||
{
|
||||
wxString vendorStr = vendor;
|
||||
wxString versionStr = version;
|
||||
|
||||
if( aVal == -1 && ( !wxGLCanvas::IsExtensionSupported( "WGL_EXT_swap_control_tear" ) ) )
|
||||
aVal = 1;
|
||||
|
||||
// Trying to enable adaptive swapping on AMD drivers from 2017 or older leads to crash
|
||||
if( aVal == -1 && vendorStr == wxS( "ATI Technologies Inc." ) )
|
||||
{
|
||||
wxArrayString parts = wxSplit( versionStr.AfterLast( ' ' ), '.', 0 );
|
||||
|
||||
if( parts.size() == 4 )
|
||||
{
|
||||
long majorVer = 0;
|
||||
|
||||
if( parts[0].ToLong( &majorVer ) )
|
||||
{
|
||||
if( majorVer <= 22 )
|
||||
aVal = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HDC hdc = wglGetCurrentDC();
|
||||
HGLRC hglrc = wglGetCurrentContext();
|
||||
|
||||
if( hdc && hglrc )
|
||||
{
|
||||
int currentInterval = wglGetSwapIntervalEXT();
|
||||
|
||||
if( currentInterval != aVal )
|
||||
{
|
||||
wglSwapIntervalEXT( aVal );
|
||||
currentInterval = wglGetSwapIntervalEXT();
|
||||
}
|
||||
|
||||
return currentInterval;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef __MINGW32__
|
||||
#pragma GCC pop_options
|
||||
#else
|
||||
#pragma optimize( "", on )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* GL_CONTEXT_MANAGER_H */
|
||||
340
tests/gal-regression/wasm/webgl/gpu_manager.cpp
Normal file
340
tests/gal-regression/wasm/webgl/gpu_manager.cpp
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "gpu_manager.h"
|
||||
#include "cached_container_gpu.h"
|
||||
#include "cached_container_ram.h"
|
||||
#include "noncached_container.h"
|
||||
#include "shader.h"
|
||||
#include "utils.h"
|
||||
#include "vertex_item.h"
|
||||
|
||||
#include <core/profile.h>
|
||||
|
||||
#include <typeinfo>
|
||||
#include <confirm.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
#include <core/profile.h>
|
||||
#include <wx/log.h>
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
|
||||
{
|
||||
if( aContainer->IsCached() )
|
||||
return new GPU_CACHED_MANAGER( aContainer );
|
||||
else
|
||||
return new GPU_NONCACHED_MANAGER( aContainer );
|
||||
}
|
||||
|
||||
|
||||
GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||
m_isDrawing( false ),
|
||||
m_container( aContainer ),
|
||||
m_shader( nullptr ),
|
||||
m_shaderAttrib( 0 ),
|
||||
m_enableDepthTest( true )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GPU_MANAGER::~GPU_MANAGER()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GPU_MANAGER::SetShader( SHADER& aShader )
|
||||
{
|
||||
m_shader = &aShader;
|
||||
m_shaderAttrib = m_shader->GetAttribute( "a_shaderParams" );
|
||||
|
||||
if( m_shaderAttrib == -1 )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "Could not get the shader attribute location" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Cached manager
|
||||
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||
GPU_MANAGER( aContainer ),
|
||||
m_buffersInitialized( false ),
|
||||
m_indicesCapacity( 0 ),
|
||||
m_totalHuge( 0 ),
|
||||
m_totalNormal( 0 ),
|
||||
m_indexBufSize( 0 ),
|
||||
m_indexBufMaxSize( 0 ),
|
||||
m_curVrangeSize( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GPU_CACHED_MANAGER::~GPU_CACHED_MANAGER()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GPU_CACHED_MANAGER::BeginDrawing()
|
||||
{
|
||||
wxASSERT( !m_isDrawing );
|
||||
|
||||
m_curVrangeSize = 0;
|
||||
m_indexBufMaxSize = 0;
|
||||
m_indexBufSize = 0;
|
||||
m_vranges.clear();
|
||||
|
||||
m_isDrawing = true;
|
||||
}
|
||||
|
||||
|
||||
void GPU_CACHED_MANAGER::DrawIndices( const VERTEX_ITEM* aItem )
|
||||
{
|
||||
// Hot path: don't use wxASSERT
|
||||
assert( m_isDrawing );
|
||||
|
||||
unsigned int offset = aItem->GetOffset();
|
||||
unsigned int size = aItem->GetSize();
|
||||
|
||||
if( size == 0 )
|
||||
return;
|
||||
|
||||
if( size <= 1000 )
|
||||
{
|
||||
m_totalNormal += size;
|
||||
m_vranges.emplace_back( offset, offset + size - 1, false );
|
||||
m_curVrangeSize += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_totalHuge += size;
|
||||
m_vranges.emplace_back( offset, offset + size - 1, true );
|
||||
m_indexBufSize = std::max( m_curVrangeSize, m_indexBufSize );
|
||||
m_curVrangeSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GPU_CACHED_MANAGER::EndDrawing()
|
||||
{
|
||||
wxASSERT( m_isDrawing );
|
||||
|
||||
CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
|
||||
|
||||
if( cached->IsMapped() )
|
||||
cached->Unmap();
|
||||
|
||||
m_indexBufSize = std::max( m_curVrangeSize, m_indexBufSize );
|
||||
m_indexBufMaxSize = std::max( 2*m_indexBufSize, m_indexBufMaxSize );
|
||||
|
||||
resizeIndices( m_indexBufMaxSize );
|
||||
|
||||
if( m_enableDepthTest )
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
else
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
|
||||
// Prepare buffers
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
// Bind vertices data buffers
|
||||
glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
|
||||
glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, (GLvoid*) COORD_OFFSET );
|
||||
glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, (GLvoid*) COLOR_OFFSET );
|
||||
|
||||
if( m_shader != nullptr ) // Use shader if applicable
|
||||
{
|
||||
m_shader->Use();
|
||||
glEnableVertexAttribArray( m_shaderAttrib );
|
||||
glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
|
||||
(GLvoid*) SHADER_OFFSET );
|
||||
}
|
||||
|
||||
PROF_TIMER cntDraw( "gl-draw-elements" );
|
||||
|
||||
int n_ranges = m_vranges.size();
|
||||
int n = 0;
|
||||
GLuint* iptr = m_indices.get();
|
||||
GLuint icnt = 0;
|
||||
|
||||
int drawCalls = 0;
|
||||
|
||||
while( n < n_ranges )
|
||||
{
|
||||
VRANGE* cur = &m_vranges[n];
|
||||
|
||||
if( cur->m_isContinuous )
|
||||
{
|
||||
if( icnt > 0 )
|
||||
{
|
||||
glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
|
||||
drawCalls++;
|
||||
}
|
||||
|
||||
icnt = 0;
|
||||
iptr = m_indices.get();
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, cur->m_start, cur->m_end - cur->m_start + 1 );
|
||||
drawCalls++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( GLuint i = cur->m_start; i <= cur->m_end; i++ )
|
||||
{
|
||||
*iptr++ = i;
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
if( icnt > 0 )
|
||||
{
|
||||
glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
|
||||
drawCalls++;
|
||||
}
|
||||
|
||||
cntDraw.Stop();
|
||||
|
||||
KI_TRACE( traceGalProfile,
|
||||
"Cached manager size: VBO size %u iranges %zu max elt size %u drawcalls %u\n",
|
||||
cached->AllItemsSize(), m_vranges.size(), m_indexBufMaxSize, drawCalls );
|
||||
KI_TRACE( traceGalProfile, "Timing: %s\n", cntDraw.to_string() );
|
||||
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
cached->ClearDirty();
|
||||
|
||||
// Deactivate vertex array
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
if( m_shader != nullptr )
|
||||
{
|
||||
glDisableVertexAttribArray( m_shaderAttrib );
|
||||
m_shader->Deactivate();
|
||||
}
|
||||
|
||||
m_isDrawing = false;
|
||||
}
|
||||
|
||||
|
||||
void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
|
||||
{
|
||||
if( aNewSize > m_indicesCapacity )
|
||||
{
|
||||
m_indicesCapacity = aNewSize;
|
||||
m_indices.reset( new GLuint[m_indicesCapacity] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Noncached manager
|
||||
GPU_NONCACHED_MANAGER::GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||
GPU_MANAGER( aContainer )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GPU_NONCACHED_MANAGER::BeginDrawing()
|
||||
{
|
||||
// Nothing has to be prepared
|
||||
}
|
||||
|
||||
|
||||
void GPU_NONCACHED_MANAGER::DrawIndices( const VERTEX_ITEM* aItem )
|
||||
{
|
||||
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
|
||||
}
|
||||
|
||||
|
||||
void GPU_NONCACHED_MANAGER::EndDrawing()
|
||||
{
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
PROF_TIMER totalRealTime;
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
if( m_container->GetSize() == 0 )
|
||||
return;
|
||||
|
||||
VERTEX* vertices = m_container->GetAllVertices();
|
||||
GLfloat* coordinates = (GLfloat*) ( vertices );
|
||||
GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
|
||||
|
||||
if( m_enableDepthTest )
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
else
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
|
||||
// Prepare buffers
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
|
||||
glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
|
||||
|
||||
if( m_shader != nullptr ) // Use shader if applicable
|
||||
{
|
||||
GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof( GLfloat );
|
||||
|
||||
m_shader->Use();
|
||||
glEnableVertexAttribArray( m_shaderAttrib );
|
||||
glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
|
||||
shaders );
|
||||
}
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
wxLogTrace( traceGalProfile, wxT( "Noncached manager size: %d" ), m_container->GetSize() );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
|
||||
// Deactivate vertex array
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
if( m_shader != nullptr )
|
||||
{
|
||||
glDisableVertexAttribArray( m_shaderAttrib );
|
||||
m_shader->Deactivate();
|
||||
}
|
||||
|
||||
m_container->Clear();
|
||||
|
||||
#ifdef KICAD_GAL_PROFILE
|
||||
totalRealTime.Stop();
|
||||
wxLogTrace( traceGalProfile, wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
|
||||
totalRealTime.msecs() );
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
}
|
||||
|
||||
void GPU_MANAGER::EnableDepthTest( bool aEnabled )
|
||||
{
|
||||
m_enableDepthTest = aEnabled;
|
||||
}
|
||||
188
tests/gal-regression/wasm/webgl/gpu_manager.h
Normal file
188
tests/gal-regression/wasm/webgl/gpu_manager.h
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef GPU_MANAGER_H_
|
||||
#define GPU_MANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
#include "vertex_common.h"
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class SHADER;
|
||||
class VERTEX_CONTAINER;
|
||||
class VERTEX_ITEM;
|
||||
class CACHED_CONTAINER;
|
||||
class NONCACHED_CONTAINER;
|
||||
|
||||
/**
|
||||
* Class to handle uploading vertices and indices to GPU in drawing purposes.
|
||||
*/
|
||||
class GPU_MANAGER
|
||||
{
|
||||
public:
|
||||
static GPU_MANAGER* MakeManager( VERTEX_CONTAINER* aContainer );
|
||||
|
||||
virtual ~GPU_MANAGER();
|
||||
|
||||
/**
|
||||
* Prepare the stored data to be drawn.
|
||||
*/
|
||||
virtual void BeginDrawing() = 0;
|
||||
|
||||
/**
|
||||
* Make the GPU draw given range of vertices.
|
||||
*
|
||||
* @param aOffset is the beginning of the range.
|
||||
* @param aSize is the number of vertices to be drawn.
|
||||
*/
|
||||
virtual void DrawIndices( const VERTEX_ITEM* aItem ) = 0;
|
||||
|
||||
/**
|
||||
* Clear the container after drawing routines.
|
||||
*/
|
||||
virtual void EndDrawing() = 0;
|
||||
|
||||
/**
|
||||
* Allow using shaders with the stored data.
|
||||
*
|
||||
* @param aShader is the object that allows using shaders.
|
||||
*/
|
||||
virtual void SetShader( SHADER& aShader );
|
||||
|
||||
/**
|
||||
* Enable/disable Z buffer depth test.
|
||||
*/
|
||||
void EnableDepthTest( bool aEnabled );
|
||||
|
||||
protected:
|
||||
GPU_MANAGER( VERTEX_CONTAINER* aContainer );
|
||||
|
||||
///< Drawing status flag.
|
||||
bool m_isDrawing;
|
||||
|
||||
///< Container that stores vertices data.
|
||||
VERTEX_CONTAINER* m_container;
|
||||
|
||||
///< Shader handling
|
||||
SHADER* m_shader;
|
||||
|
||||
///< Location of shader attributes (for glVertexAttribPointer)
|
||||
int m_shaderAttrib;
|
||||
|
||||
///< true: enable Z test when drawing
|
||||
bool m_enableDepthTest;
|
||||
};
|
||||
|
||||
|
||||
class GPU_CACHED_MANAGER : public GPU_MANAGER
|
||||
{
|
||||
public:
|
||||
|
||||
struct VRANGE
|
||||
{
|
||||
VRANGE( int aStart, int aEnd, bool aContinuous ) :
|
||||
m_start( aStart ),
|
||||
m_end( aEnd ),
|
||||
m_isContinuous( aContinuous )
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int m_start, m_end;
|
||||
bool m_isContinuous;
|
||||
};
|
||||
|
||||
|
||||
GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer );
|
||||
~GPU_CACHED_MANAGER();
|
||||
|
||||
///< @copydoc GPU_MANAGER::BeginDrawing()
|
||||
virtual void BeginDrawing() override;
|
||||
|
||||
///< @copydoc GPU_MANAGER::DrawIndices()
|
||||
virtual void DrawIndices( const VERTEX_ITEM* aItem ) override;
|
||||
|
||||
///< @copydoc GPU_MANAGER::EndDrawing()
|
||||
virtual void EndDrawing() override;
|
||||
|
||||
///< Map vertex buffer stored in GPU memory.
|
||||
void Map();
|
||||
|
||||
///< Unmap vertex buffer.
|
||||
void Unmap();
|
||||
|
||||
protected:
|
||||
///< Resizes the indices buffer to aNewSize if necessary
|
||||
void resizeIndices( unsigned int aNewSize );
|
||||
|
||||
///< Buffers initialization flag
|
||||
bool m_buffersInitialized;
|
||||
|
||||
///< Pointer to the current indices buffer
|
||||
boost::scoped_array<GLuint> m_indices;
|
||||
|
||||
///< Current indices buffer size
|
||||
unsigned int m_indicesCapacity;
|
||||
|
||||
///< Ranges of visible vertex indices to render
|
||||
std::vector<VRANGE> m_vranges;
|
||||
|
||||
///< Number of huge VRANGEs (i.e. large zones) with separate draw calls
|
||||
int m_totalHuge;
|
||||
|
||||
///< Number of regular VRANGEs (small items) pooled into single draw call
|
||||
int m_totalNormal;
|
||||
|
||||
///< Current size of index buffer
|
||||
unsigned int m_indexBufSize;
|
||||
|
||||
///< Maximum size taken by the index buffer for all frames rendered so far
|
||||
unsigned int m_indexBufMaxSize;
|
||||
|
||||
///< Size of the current VRANGE
|
||||
unsigned int m_curVrangeSize;
|
||||
};
|
||||
|
||||
|
||||
class GPU_NONCACHED_MANAGER : public GPU_MANAGER
|
||||
{
|
||||
public:
|
||||
GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer );
|
||||
|
||||
///< @copydoc GPU_MANAGER::BeginDrawing()
|
||||
virtual void BeginDrawing() override;
|
||||
|
||||
///< @copydoc GPU_MANAGER::DrawIndices()
|
||||
virtual void DrawIndices( const VERTEX_ITEM* aItem ) override;
|
||||
|
||||
///< @copydoc GPU_MANAGER::EndDrawing()
|
||||
virtual void EndDrawing() override;
|
||||
};
|
||||
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* GPU_MANAGER_H_ */
|
||||
258
tests/gal-regression/wasm/webgl/kiglew.h
Normal file
258
tests/gal-regression/wasm/webgl/kiglew.h
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is used for including the proper GLEW header for the platform.
|
||||
*/
|
||||
|
||||
#ifndef KIGLEW_H_
|
||||
#define KIGLEW_H_
|
||||
|
||||
// Pull in the configuration options for wxWidgets
|
||||
#include <wx/platform.h>
|
||||
|
||||
#if defined( __EMSCRIPTEN__ )
|
||||
// WebGL2/GLES3: Modern shader functions (glUseProgram, etc.)
|
||||
#include <GLES3/gl3.h>
|
||||
// Legacy GL emulation: glMatrixMode, glColor4d, glBegin/glEnd, etc.
|
||||
#include <GL/gl.h>
|
||||
// GLU tesselator - provided by wasm/stubs/glu_wasm_impl.cpp
|
||||
#include <GL/glu.h>
|
||||
|
||||
// GLEW compatibility stubs for WebGL
|
||||
#define GLEW_OK 0
|
||||
#define GLEW_VERSION 1
|
||||
#define GLEW_VERSION_1_2 1
|
||||
#define GLEW_VERSION_1_3 1
|
||||
#define GLEW_VERSION_1_4 1
|
||||
#define GLEW_VERSION_1_5 1
|
||||
#define GLEW_VERSION_2_0 1
|
||||
#define GLEW_VERSION_2_1 1
|
||||
#define GLEW_ARB_vertex_array_object 1
|
||||
#define GLEW_ARB_vertex_buffer_object 1
|
||||
#define GLEW_ARB_framebuffer_object 1
|
||||
#define GLEW_EXT_framebuffer_object 1
|
||||
#define GLEW_ARB_texture_non_power_of_two 1
|
||||
#define GLEW_ARB_copy_buffer 0 // Not available in WebGL 1.0
|
||||
#define GLEW_EXT_framebuffer_multisample 0 // Limited in WebGL
|
||||
|
||||
inline int glewInit() { return GLEW_OK; }
|
||||
inline const unsigned char* glewGetString(int) { return (const unsigned char*)"WebGL"; }
|
||||
inline const char* glewGetErrorString(int) { return ""; }
|
||||
inline int glewIsSupported(const char*) { return 1; }
|
||||
|
||||
// VAO functions - available in WebGL2 / OpenGL ES 3.0
|
||||
#ifndef GL_VERTEX_ARRAY_BINDING
|
||||
#define GL_VERTEX_ARRAY_BINDING 0x85B5
|
||||
#endif
|
||||
|
||||
// Geometry shader extensions - not supported in WebGL
|
||||
#ifndef GL_GEOMETRY_VERTICES_OUT_EXT
|
||||
#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
|
||||
#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
|
||||
#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
|
||||
#endif
|
||||
|
||||
// Geometry shader function stub (not supported in WebGL)
|
||||
inline void glProgramParameteriEXT(GLuint program, GLenum pname, GLint value) {
|
||||
(void)program; (void)pname; (void)value;
|
||||
}
|
||||
|
||||
// glMapBuffer family - not available in WebGL 1.0
|
||||
// Return nullptr to signal failure, KiCad has RAM-based fallback
|
||||
inline void* glMapBuffer(GLenum target, GLenum access) {
|
||||
(void)target; (void)access;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline GLboolean glUnmapBuffer(GLenum target) {
|
||||
(void)target;
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// Buffer copy - not available in WebGL 1.0, no-op stub
|
||||
inline void glCopyBufferSubData(GLenum readTarget, GLenum writeTarget,
|
||||
GLintptr readOffset, GLintptr writeOffset,
|
||||
GLsizeiptr size) {
|
||||
(void)readTarget; (void)writeTarget;
|
||||
(void)readOffset; (void)writeOffset; (void)size;
|
||||
}
|
||||
|
||||
// EXT framebuffer functions - alias to standard GL ES 2.0 functions
|
||||
#ifndef GL_FRAMEBUFFER_EXT
|
||||
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER
|
||||
#endif
|
||||
#ifndef GL_RENDERBUFFER_EXT
|
||||
#define GL_RENDERBUFFER_EXT GL_RENDERBUFFER
|
||||
#endif
|
||||
#ifndef GL_FRAMEBUFFER_COMPLETE_EXT
|
||||
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
||||
#endif
|
||||
|
||||
#define glGenFramebuffersEXT glGenFramebuffers
|
||||
#define glDeleteFramebuffersEXT glDeleteFramebuffers
|
||||
#define glBindFramebufferEXT glBindFramebuffer
|
||||
#define glCheckFramebufferStatusEXT glCheckFramebufferStatus
|
||||
#define glFramebufferTexture2DEXT glFramebufferTexture2D
|
||||
#define glFramebufferRenderbufferEXT glFramebufferRenderbuffer
|
||||
|
||||
#define glGenRenderbuffersEXT glGenRenderbuffers
|
||||
#define glDeleteRenderbuffersEXT glDeleteRenderbuffers
|
||||
#define glBindRenderbufferEXT glBindRenderbuffer
|
||||
#define glRenderbufferStorageEXT glRenderbufferStorage
|
||||
|
||||
// GL_DEPTH24_STENCIL8 - map to GLES2/WebGL constant
|
||||
#ifndef GL_DEPTH24_STENCIL8
|
||||
#define GL_DEPTH24_STENCIL8 0x88F0
|
||||
#endif
|
||||
|
||||
// GL_DEPTH_STENCIL_ATTACHMENT - WebGL uses separate depth/stencil, but this constant exists
|
||||
#ifndef GL_DEPTH_STENCIL_ATTACHMENT
|
||||
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
|
||||
#endif
|
||||
|
||||
// Debug output - not available in WebGL, no-op stubs
|
||||
#ifndef GL_DEBUG_OUTPUT
|
||||
#define GL_DEBUG_OUTPUT 0x92E0
|
||||
#endif
|
||||
|
||||
#ifndef GLchar
|
||||
typedef char GLchar;
|
||||
#endif
|
||||
|
||||
typedef void (*GLDEBUGPROC)(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity, GLsizei length,
|
||||
const GLchar* message, const void* userParam);
|
||||
|
||||
inline void glDebugMessageCallback(GLDEBUGPROC callback, const void* userParam) {
|
||||
(void)callback; (void)userParam;
|
||||
}
|
||||
|
||||
// GLdouble type for double-precision functions
|
||||
#ifndef GLdouble
|
||||
typedef double GLdouble;
|
||||
#endif
|
||||
|
||||
// Double-precision GL function wrappers - LEGACY_GL_EMULATION only provides float versions
|
||||
// These convert double arguments to float and call the float variants
|
||||
inline void glVertex2d(GLdouble x, GLdouble y) {
|
||||
glVertex2f((GLfloat)x, (GLfloat)y);
|
||||
}
|
||||
inline void glVertex3d(GLdouble x, GLdouble y, GLdouble z) {
|
||||
glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
inline void glColor4d(GLdouble r, GLdouble g, GLdouble b, GLdouble a) {
|
||||
glColor4f((GLfloat)r, (GLfloat)g, (GLfloat)b, (GLfloat)a);
|
||||
}
|
||||
inline void glColor3d(GLdouble r, GLdouble g, GLdouble b) {
|
||||
glColor3f((GLfloat)r, (GLfloat)g, (GLfloat)b);
|
||||
}
|
||||
inline void glTranslated(GLdouble x, GLdouble y, GLdouble z) {
|
||||
glTranslatef((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
inline void glScaled(GLdouble x, GLdouble y, GLdouble z) {
|
||||
glScalef((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
inline void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) {
|
||||
glRotatef((GLfloat)angle, (GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
inline void glNormal3d(GLdouble x, GLdouble y, GLdouble z) {
|
||||
glNormal3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
inline void glTexCoord2d(GLdouble s, GLdouble t) {
|
||||
glTexCoord2f((GLfloat)s, (GLfloat)t);
|
||||
}
|
||||
inline void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) {
|
||||
glRectf((GLfloat)x1, (GLfloat)y1, (GLfloat)x2, (GLfloat)y2);
|
||||
}
|
||||
inline void glLoadMatrixd(const GLdouble* m) {
|
||||
GLfloat fm[16];
|
||||
for(int i = 0; i < 16; i++) fm[i] = (GLfloat)m[i];
|
||||
glLoadMatrixf(fm);
|
||||
}
|
||||
inline void glMultMatrixd(const GLdouble* m) {
|
||||
GLfloat fm[16];
|
||||
for(int i = 0; i < 16; i++) fm[i] = (GLfloat)m[i];
|
||||
glMultMatrixf(fm);
|
||||
}
|
||||
|
||||
// Display lists - not supported in WebGL, stub implementations
|
||||
inline GLuint glGenLists(GLsizei range) { (void)range; return 0; }
|
||||
inline GLboolean glIsList(GLuint list) { (void)list; return GL_FALSE; }
|
||||
inline void glNewList(GLuint list, GLenum mode) { (void)list; (void)mode; }
|
||||
inline void glEndList(void) {}
|
||||
inline void glCallList(GLuint list) { (void)list; }
|
||||
inline void glDeleteLists(GLuint list, GLsizei range) { (void)list; (void)range; }
|
||||
|
||||
// Lighting and material functions - stubs (lighting not fully supported in WebGL)
|
||||
inline void glLightModeli(GLenum pname, GLint param) { (void)pname; (void)param; }
|
||||
inline void glColorMaterial(GLenum face, GLenum mode) { (void)face; (void)mode; }
|
||||
inline void glMaterialf(GLenum face, GLenum pname, GLfloat param) {
|
||||
(void)face; (void)pname; (void)param;
|
||||
}
|
||||
inline void glMaterialfv(GLenum face, GLenum pname, const GLfloat* params) {
|
||||
(void)face; (void)pname; (void)params;
|
||||
}
|
||||
inline void glLightfv(GLenum light, GLenum pname, const GLfloat* params) {
|
||||
(void)light; (void)pname; (void)params;
|
||||
}
|
||||
inline void glLightf(GLenum light, GLenum pname, GLfloat param) {
|
||||
(void)light; (void)pname; (void)param;
|
||||
}
|
||||
|
||||
#elif defined( __unix__ ) and not defined( __APPLE__ )
|
||||
|
||||
#ifdef KICAD_USE_EGL
|
||||
|
||||
#if wxUSE_GLCANVAS_EGL
|
||||
// wxWidgets was compiled with the EGL canvas, so use the EGL header for GLEW
|
||||
#include <GL/eglew.h>
|
||||
#else
|
||||
#error "KICAD_USE_EGL can only be used when wxWidgets is compiled with the EGL canvas"
|
||||
#endif
|
||||
|
||||
#else // KICAD_USE_EGL
|
||||
|
||||
#if wxUSE_GLCANVAS_EGL
|
||||
#error "KICAD_USE_EGL must be defined since wxWidgets has been compiled with the EGL canvas"
|
||||
#else
|
||||
// wxWidgets wasn't compiled with the EGL canvas, so use the X11 GLEW
|
||||
#include <GL/glxew.h>
|
||||
#endif
|
||||
|
||||
#endif // KICAD_USE_EGL
|
||||
|
||||
#else // defined( __unix__ ) and not defined( __APPLE__ )
|
||||
|
||||
// Non-GTK platforms only need the normal GLEW include
|
||||
#include <GL/glew.h>
|
||||
|
||||
#endif // defined( __unix__ ) and not defined( __APPLE__ )
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <GL/wglew.h>
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // KIGLEW_H_
|
||||
102
tests/gal-regression/wasm/webgl/noncached_container.cpp
Normal file
102
tests/gal-regression/wasm/webgl/noncached_container.cpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file noncached_container.cpp
|
||||
* @brief Class to store instances of VERTEX without caching. It allows a fast one-frame drawing
|
||||
* and then clearing the buffer and starting from scratch.
|
||||
*/
|
||||
|
||||
#include "noncached_container.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
|
||||
VERTEX_CONTAINER( aSize ),
|
||||
m_freePtr( 0 )
|
||||
{
|
||||
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
|
||||
|
||||
// Unfortunately we cannot remove the use of malloc here because realloc is used in
|
||||
// the Allocate method below. The new operator behavior is mimicked here so that a
|
||||
// malloc failure can be caught in the OpenGL initialization code further up the stack.
|
||||
if( !m_vertices )
|
||||
throw std::bad_alloc();
|
||||
|
||||
memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) );
|
||||
}
|
||||
|
||||
|
||||
NONCACHED_CONTAINER::~NONCACHED_CONTAINER()
|
||||
{
|
||||
free( m_vertices );
|
||||
}
|
||||
|
||||
|
||||
void NONCACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||
{
|
||||
// Nothing has to be done, as the noncached container
|
||||
// does not care about VERTEX_ITEMs ownership
|
||||
}
|
||||
|
||||
|
||||
VERTEX* NONCACHED_CONTAINER::Allocate( unsigned int aSize )
|
||||
{
|
||||
if( m_freeSpace < aSize )
|
||||
{
|
||||
// Double the space
|
||||
VERTEX* newVertices =
|
||||
static_cast<VERTEX*>( realloc( m_vertices, m_currentSize * 2 * sizeof( VERTEX ) ) );
|
||||
|
||||
if( newVertices != nullptr )
|
||||
{
|
||||
m_vertices = newVertices;
|
||||
m_freeSpace += m_currentSize;
|
||||
m_currentSize *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
VERTEX* freeVertex = &m_vertices[m_freePtr];
|
||||
|
||||
// Move to the next free chunk
|
||||
m_freePtr += aSize;
|
||||
m_freeSpace -= aSize;
|
||||
|
||||
return freeVertex;
|
||||
}
|
||||
|
||||
|
||||
void NONCACHED_CONTAINER::Clear()
|
||||
{
|
||||
m_freePtr = 0;
|
||||
m_freeSpace = m_currentSize;
|
||||
}
|
||||
85
tests/gal-regression/wasm/webgl/noncached_container.h
Normal file
85
tests/gal-regression/wasm/webgl/noncached_container.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file noncached_container.h
|
||||
* @brief Class to store instances of VERTEX without caching. It allows a fast one-frame drawing
|
||||
* and then clearing the buffer and starting from scratch.
|
||||
*/
|
||||
|
||||
#ifndef NONCACHED_CONTAINER_H_
|
||||
#define NONCACHED_CONTAINER_H_
|
||||
|
||||
#include "vertex_container.h"
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
class NONCACHED_CONTAINER : public VERTEX_CONTAINER
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a non-cached container object.
|
||||
*
|
||||
* @param aSize is the size of the cache.
|
||||
* @throw bad_alloc exception if memory allocation fails.
|
||||
*/
|
||||
NONCACHED_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
|
||||
virtual ~NONCACHED_CONTAINER();
|
||||
|
||||
bool IsCached() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @copydoc VERTEX_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||
virtual void SetItem( VERTEX_ITEM* aItem ) override;
|
||||
|
||||
/// @copydoc VERTEX_CONTAINER::Allocate( unsigned int aSize )
|
||||
virtual VERTEX* Allocate( unsigned int aSize ) override;
|
||||
|
||||
/// @copydoc VERTEX_CONTAINER::Delete( VERTEX_ITEM* aItem )
|
||||
void Delete( VERTEX_ITEM* aItem ) override {}
|
||||
|
||||
/// @copydoc VERTEX_CONTAINER::Clear()
|
||||
virtual void Clear() override;
|
||||
|
||||
/// @copydoc VERTEX_CONTAINER::GetSize()
|
||||
virtual unsigned int GetSize() const override
|
||||
{
|
||||
// As the m_freePtr points to the first free space, we can safely assume
|
||||
// that this is the number of vertices stored inside
|
||||
return m_freePtr;
|
||||
}
|
||||
|
||||
protected:
|
||||
///< Index of the free first space where a vertex can be stored
|
||||
unsigned int m_freePtr;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* NONCACHED_CONTAINER_H_ */
|
||||
298
tests/gal-regression/wasm/webgl/shader.cpp
Normal file
298
tests/gal-regression/wasm/webgl/shader.cpp
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Graphics Abstraction Layer (GAL) for OpenGL
|
||||
*
|
||||
* Shader class
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include "shader.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
SHADER::SHADER() :
|
||||
isProgramCreated( false ),
|
||||
isShaderLinked( false ),
|
||||
active( false ),
|
||||
maximumVertices( 4 ),
|
||||
geomInputType( GL_LINES ),
|
||||
geomOutputType( GL_LINES )
|
||||
|
||||
{
|
||||
// Do not have uninitialized members:
|
||||
programNumber = 0;
|
||||
}
|
||||
|
||||
|
||||
SHADER::~SHADER()
|
||||
{
|
||||
if( active )
|
||||
Deactivate();
|
||||
|
||||
if( isProgramCreated )
|
||||
{
|
||||
if( glIsShader )
|
||||
{
|
||||
// Delete the shaders and the program
|
||||
for( std::deque<GLuint>::iterator it = shaderNumbers.begin(); it != shaderNumbers.end();
|
||||
++it )
|
||||
{
|
||||
GLuint shader = *it;
|
||||
|
||||
if( glIsShader( shader ) )
|
||||
{
|
||||
glDetachShader( programNumber, shader );
|
||||
glDeleteShader( shader );
|
||||
}
|
||||
}
|
||||
|
||||
glDeleteProgram( programNumber );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SHADER::LoadShaderFromFile( SHADER_TYPE aShaderType, const std::string& aShaderSourceName )
|
||||
{
|
||||
// Load shader sources
|
||||
const std::string shaderSource = ReadSource( aShaderSourceName );
|
||||
|
||||
return LoadShaderFromStrings( aShaderType, shaderSource );
|
||||
}
|
||||
|
||||
|
||||
void SHADER::ConfigureGeometryShader( GLuint maxVertices, GLuint geometryInputType,
|
||||
GLuint geometryOutputType )
|
||||
{
|
||||
maximumVertices = maxVertices;
|
||||
geomInputType = geometryInputType;
|
||||
geomOutputType = geometryOutputType;
|
||||
}
|
||||
|
||||
|
||||
bool SHADER::Link()
|
||||
{
|
||||
// Shader linking
|
||||
glLinkProgram( programNumber );
|
||||
programInfo( programNumber );
|
||||
|
||||
// Check the Link state
|
||||
GLint tmp;
|
||||
glGetProgramiv( programNumber, GL_LINK_STATUS, &tmp );
|
||||
isShaderLinked = !!tmp;
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !isShaderLinked )
|
||||
{
|
||||
int maxLength;
|
||||
glGetProgramiv( programNumber, GL_INFO_LOG_LENGTH, &maxLength );
|
||||
maxLength = maxLength + 1;
|
||||
char* linkInfoLog = new char[maxLength];
|
||||
glGetProgramInfoLog( programNumber, maxLength, &maxLength, linkInfoLog );
|
||||
std::cerr << "Shader linking error:" << std::endl;
|
||||
std::cerr << linkInfoLog;
|
||||
delete[] linkInfoLog;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
return isShaderLinked;
|
||||
}
|
||||
|
||||
|
||||
int SHADER::AddParameter( const std::string& aParameterName )
|
||||
{
|
||||
GLint location = glGetUniformLocation( programNumber, aParameterName.c_str() );
|
||||
|
||||
if( location >= 0 )
|
||||
parameterLocation.push_back( location );
|
||||
else
|
||||
throw std::runtime_error( "Could not find shader uniform: " + aParameterName );
|
||||
|
||||
return static_cast<int>( parameterLocation.size() ) - 1;
|
||||
}
|
||||
|
||||
|
||||
void SHADER::SetParameter( int parameterNumber, float value ) const
|
||||
{
|
||||
assert( (unsigned) parameterNumber < parameterLocation.size() );
|
||||
|
||||
glUniform1f( parameterLocation[parameterNumber], value );
|
||||
}
|
||||
|
||||
|
||||
void SHADER::SetParameter( int parameterNumber, int value ) const
|
||||
{
|
||||
assert( (unsigned) parameterNumber < parameterLocation.size() );
|
||||
|
||||
glUniform1i( parameterLocation[parameterNumber], value );
|
||||
}
|
||||
|
||||
|
||||
void SHADER::SetParameter( int parameterNumber, float f0, float f1, float f2, float f3 ) const
|
||||
{
|
||||
assert( (unsigned) parameterNumber < parameterLocation.size() );
|
||||
float arr[4] = { f0, f1, f2, f3 };
|
||||
glUniform4fv( parameterLocation[parameterNumber], 1, arr );
|
||||
}
|
||||
|
||||
|
||||
void SHADER::SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const
|
||||
{
|
||||
assert( (unsigned) aParameterNumber < parameterLocation.size() );
|
||||
glUniform2f( parameterLocation[aParameterNumber], static_cast<GLfloat>( aValue.x ),
|
||||
static_cast<GLfloat>( aValue.y ) );
|
||||
}
|
||||
|
||||
|
||||
int SHADER::GetAttribute( const std::string& aAttributeName ) const
|
||||
{
|
||||
return glGetAttribLocation( programNumber, aAttributeName.c_str() );
|
||||
}
|
||||
|
||||
|
||||
void SHADER::programInfo( GLuint aProgram )
|
||||
{
|
||||
GLint glInfoLogLength = 0;
|
||||
GLint writtenChars = 0;
|
||||
|
||||
// Get the length of the info string
|
||||
glGetProgramiv( aProgram, GL_INFO_LOG_LENGTH, &glInfoLogLength );
|
||||
|
||||
// Print the information
|
||||
if( glInfoLogLength > 2 )
|
||||
{
|
||||
GLchar* glInfoLog = new GLchar[glInfoLogLength];
|
||||
glGetProgramInfoLog( aProgram, glInfoLogLength, &writtenChars, glInfoLog );
|
||||
|
||||
delete[] glInfoLog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SHADER::shaderInfo( GLuint aShader )
|
||||
{
|
||||
GLint glInfoLogLength = 0;
|
||||
GLint writtenChars = 0;
|
||||
|
||||
// Get the length of the info string
|
||||
glGetShaderiv( aShader, GL_INFO_LOG_LENGTH, &glInfoLogLength );
|
||||
|
||||
// Print the information
|
||||
if( glInfoLogLength > 2 )
|
||||
{
|
||||
GLchar* glInfoLog = new GLchar[glInfoLogLength];
|
||||
glGetShaderInfoLog( aShader, glInfoLogLength, &writtenChars, glInfoLog );
|
||||
|
||||
delete[] glInfoLog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string SHADER::ReadSource( const std::string& aShaderSourceName )
|
||||
{
|
||||
// Open the shader source for reading
|
||||
std::ifstream inputFile( aShaderSourceName.c_str(), std::ifstream::in );
|
||||
std::string shaderSource;
|
||||
|
||||
if( !inputFile )
|
||||
throw std::runtime_error( "Can't read the shader source: " + aShaderSourceName );
|
||||
|
||||
std::string shaderSourceLine;
|
||||
|
||||
// Read all lines from the text file
|
||||
while( getline( inputFile, shaderSourceLine ) )
|
||||
{
|
||||
shaderSource += shaderSourceLine;
|
||||
shaderSource += "\n";
|
||||
}
|
||||
|
||||
return shaderSource;
|
||||
}
|
||||
|
||||
|
||||
bool SHADER::loadShaderFromStringArray( SHADER_TYPE aShaderType, const char** aArray, size_t aSize )
|
||||
{
|
||||
assert( !isShaderLinked );
|
||||
|
||||
// Create the program
|
||||
if( !isProgramCreated )
|
||||
{
|
||||
programNumber = glCreateProgram();
|
||||
isProgramCreated = true;
|
||||
}
|
||||
|
||||
// Create a shader
|
||||
GLuint shaderNumber = glCreateShader( aShaderType );
|
||||
shaderNumbers.push_back( shaderNumber );
|
||||
|
||||
// Get the program info
|
||||
programInfo( programNumber );
|
||||
|
||||
// Attach the sources
|
||||
glShaderSource( shaderNumber, static_cast<GLsizei>( aSize ), (const GLchar**) aArray, nullptr );
|
||||
programInfo( programNumber );
|
||||
|
||||
// Compile and attach shader to the program
|
||||
glCompileShader( shaderNumber );
|
||||
GLint status;
|
||||
glGetShaderiv( shaderNumber, GL_COMPILE_STATUS, &status );
|
||||
|
||||
if( status != GL_TRUE )
|
||||
{
|
||||
shaderInfo( shaderNumber );
|
||||
|
||||
GLint maxLength = 0;
|
||||
glGetShaderiv( shaderNumber, GL_INFO_LOG_LENGTH, &maxLength );
|
||||
|
||||
// The maxLength includes the NULL character
|
||||
std::vector<GLchar> errorLog( (size_t) maxLength );
|
||||
glGetShaderInfoLog( shaderNumber, maxLength, &maxLength, &errorLog[0] );
|
||||
|
||||
// Provide the infolog in whatever manor you deem best.
|
||||
// Exit with failure.
|
||||
glDeleteShader( shaderNumber ); // Don't leak the shader.
|
||||
|
||||
throw std::runtime_error( &errorLog[0] );
|
||||
}
|
||||
|
||||
glAttachShader( programNumber, shaderNumber );
|
||||
programInfo( programNumber );
|
||||
|
||||
// Special handling for the geometry shader
|
||||
if( aShaderType == SHADER_TYPE_GEOMETRY )
|
||||
{
|
||||
glProgramParameteriEXT( programNumber, GL_GEOMETRY_VERTICES_OUT_EXT, maximumVertices );
|
||||
glProgramParameteriEXT( programNumber, GL_GEOMETRY_INPUT_TYPE_EXT, geomInputType );
|
||||
glProgramParameteriEXT( programNumber, GL_GEOMETRY_OUTPUT_TYPE_EXT, geomOutputType );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
236
tests/gal-regression/wasm/webgl/shader.h
Normal file
236
tests/gal-regression/wasm/webgl/shader.h
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Graphics Abstraction Layer (GAL) for OpenGL
|
||||
*
|
||||
* Shader class
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef SHADER_H_
|
||||
#define SHADER_H_
|
||||
|
||||
#include "kiglew.h" // Must be included first
|
||||
|
||||
#include <math/vector2d.h>
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class WEBGL_GAL;
|
||||
|
||||
/// Type definition for the shader
|
||||
enum SHADER_TYPE
|
||||
{
|
||||
SHADER_TYPE_VERTEX = GL_VERTEX_SHADER, ///< Vertex shader
|
||||
SHADER_TYPE_FRAGMENT = GL_FRAGMENT_SHADER, ///< Fragment shader
|
||||
SHADER_TYPE_GEOMETRY = GL_GEOMETRY_SHADER ///< Geometry shader
|
||||
};
|
||||
|
||||
namespace DETAIL {
|
||||
|
||||
inline const char* translateStringArg( const std::string& str )
|
||||
{
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
inline const char* translateStringArg( const char* str )
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide the access to the OpenGL shaders.
|
||||
*
|
||||
* The purpose of this class is advanced drawing with OpenGL. One example is using the pixel
|
||||
* shader for drawing exact circles or for anti-aliasing. This class supports vertex, geometry
|
||||
* and fragment shaders.
|
||||
*
|
||||
* Make sure that the hardware supports these features. This can be identified with the "GLEW"
|
||||
* library.
|
||||
*/
|
||||
class SHADER
|
||||
{
|
||||
public:
|
||||
|
||||
SHADER();
|
||||
|
||||
virtual ~SHADER();
|
||||
|
||||
/**
|
||||
* Add a shader and compile the shader sources.
|
||||
*
|
||||
* @param aArgs is the list of strings (std::string or convertible to const char*) which
|
||||
* are concatenated and compiled as a single shader source code.
|
||||
* @param aShaderType is the type of the shader.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
template< typename... Args >
|
||||
bool LoadShaderFromStrings( SHADER_TYPE aShaderType, Args&&... aArgs )
|
||||
{
|
||||
const char* arr[] = { DETAIL::translateStringArg( aArgs )... };
|
||||
return loadShaderFromStringArray( aShaderType, arr, sizeof...(Args) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load one of the built-in shaders and compiles it.
|
||||
*
|
||||
* @param aShaderSourceName is the shader source file name.
|
||||
* @param aShaderType is the type of the shader.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
bool LoadShaderFromFile( SHADER_TYPE aShaderType, const std::string& aShaderSourceName );
|
||||
|
||||
/**
|
||||
* Link the shaders.
|
||||
*
|
||||
* @return true in case of success, false otherwise.
|
||||
*/
|
||||
bool Link();
|
||||
|
||||
/**
|
||||
* Return true if shaders are linked correctly.
|
||||
*/
|
||||
bool IsLinked() const
|
||||
{
|
||||
return isShaderLinked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the shader.
|
||||
*/
|
||||
inline void Use()
|
||||
{
|
||||
glUseProgram( programNumber );
|
||||
active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate the shader and use the default OpenGL program.
|
||||
*/
|
||||
inline void Deactivate()
|
||||
{
|
||||
glUseProgram( 0 );
|
||||
active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current state of the shader.
|
||||
*
|
||||
* @return True if any of shaders is enabled.
|
||||
*/
|
||||
inline bool IsActive() const
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the geometry shader - has to be done before linking!
|
||||
*
|
||||
* @param maxVertices is the maximum of vertices to be generated.
|
||||
* @param geometryInputType is the input type [e.g. GL_LINES, GL_TRIANGLES, GL_QUADS etc.]
|
||||
* @param geometryOutputType is the output type [e.g. GL_LINES, GL_TRIANGLES, GL_QUADS etc.]
|
||||
*/
|
||||
void ConfigureGeometryShader( GLuint maxVertices, GLuint geometryInputType,
|
||||
GLuint geometryOutputType );
|
||||
|
||||
/**
|
||||
* Add a parameter to the parameter queue.
|
||||
*
|
||||
* To communicate with the shader use this function to set up the names for the uniform
|
||||
* variables. These are queued in a list and can be assigned with the SetParameter(..)
|
||||
* method using the queue position.
|
||||
*
|
||||
* @param aParameterName is the name of the parameter.
|
||||
* @return the added parameter location.
|
||||
*/
|
||||
int AddParameter( const std::string& aParameterName );
|
||||
|
||||
/**
|
||||
* Set a parameter of the shader.
|
||||
*
|
||||
* @param aParameterNumber is the number of the parameter.
|
||||
* @param aValue is the value of the parameter.
|
||||
*/
|
||||
void SetParameter( int aParameterNumber, float aValue ) const;
|
||||
void SetParameter( int aParameterNumber, int aValue ) const;
|
||||
void SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const;
|
||||
void SetParameter( int aParameterNumber, float f0, float f1, float f2, float f3 ) const;
|
||||
|
||||
/**
|
||||
* Get an attribute location.
|
||||
*
|
||||
* @param aAttributeName is the name of the attribute.
|
||||
* @return the location.
|
||||
*/
|
||||
int GetAttribute( const std::string& aAttributeName ) const;
|
||||
|
||||
/**
|
||||
* Read the shader source file
|
||||
*
|
||||
* @param aShaderSourceName is the shader source file name.
|
||||
* @return the source as string
|
||||
*/
|
||||
static std::string ReadSource( const std::string& aShaderSourceName );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compile vertex of fragment shader source code into the program.
|
||||
*/
|
||||
bool loadShaderFromStringArray( SHADER_TYPE aShaderType, const char** aArray, size_t aSize );
|
||||
|
||||
/**
|
||||
* Get the shader program information.
|
||||
*
|
||||
* @param aProgram is the program number.
|
||||
*/
|
||||
void programInfo( GLuint aProgram );
|
||||
|
||||
/**
|
||||
* Get the shader information.
|
||||
*
|
||||
* @param aShader is the shader number.
|
||||
*/
|
||||
void shaderInfo( GLuint aShader );
|
||||
|
||||
std::deque<GLuint> shaderNumbers; ///< Shader number list
|
||||
GLuint programNumber; ///< Shader program number
|
||||
bool isProgramCreated; ///< Flag for program creation
|
||||
bool isShaderLinked; ///< Is the shader linked?
|
||||
bool active; ///< Is any of shaders used?
|
||||
GLuint maximumVertices; ///< The maximum of vertices to be generated
|
||||
|
||||
///< Input type [e.g. GL_LINES, GL_TRIANGLES, GL_QUADS etc.]
|
||||
GLuint geomInputType;
|
||||
|
||||
///< Output type [e.g. GL_LINES, GL_TRIANGLES, GL_QUADS etc.]
|
||||
GLuint geomOutputType;
|
||||
std::deque<GLint> parameterLocation; ///< Location of the parameter
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* SHADER_H_ */
|
||||
199
tests/gal-regression/wasm/webgl/utils.cpp
Normal file
199
tests/gal-regression/wasm/webgl/utils.cpp
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <confirm.h> // DisplayError
|
||||
|
||||
#include "kiglew.h" // Must be included first
|
||||
|
||||
#include <stdexcept>
|
||||
#include <wx/log.h> // wxLogDebug
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable debug output of the GAL OpenGL error checking.
|
||||
*
|
||||
* Use "KICAD_GAL_OPENGL_ERROR" to enable GAL OpenGL error tracing.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar* const traceGalOpenGlError = wxT( "KICAD_GAL_OPENGL_ERROR" );
|
||||
|
||||
|
||||
int checkGlError( const std::string& aInfo, const char* aFile, int aLine, bool aThrow )
|
||||
{
|
||||
int result = glGetError();
|
||||
wxString errorMsg;
|
||||
|
||||
switch( result )
|
||||
{
|
||||
case GL_NO_ERROR:
|
||||
// all good
|
||||
break;
|
||||
|
||||
case GL_INVALID_ENUM:
|
||||
errorMsg = wxString::Format( "Error: %s: invalid enum", aInfo );
|
||||
break;
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
errorMsg = wxString::Format( "Error: %s: invalid value", aInfo );
|
||||
break;
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
errorMsg = wxString::Format( "Error: %s: invalid operation", aInfo );
|
||||
break;
|
||||
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
{
|
||||
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
|
||||
|
||||
if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
|
||||
{
|
||||
switch( status )
|
||||
{
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
errorMsg = "The framebuffer attachment points are incomplete.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
errorMsg = "No images attached to the framebuffer.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
errorMsg = "The framebuffer does not have at least one image attached to it.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
errorMsg = "The framebuffer read buffer is incomplete.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
errorMsg = "The combination of internal formats of the attached images violates "
|
||||
"an implementation dependent set of restrictions.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
|
||||
errorMsg = "GL_RENDERBUFFER_SAMPLES is not the same for all attached render "
|
||||
"buffers.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT:
|
||||
errorMsg = "Framebuffer incomplete layer targets errors.";
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
errorMsg = "Framebuffer attachments have different dimensions";
|
||||
break;
|
||||
|
||||
default:
|
||||
errorMsg.Printf( "Unknown incomplete framebuffer error id %X", status );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMsg = wxString::Format( "Error: %s: invalid framebuffer operation", aInfo );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
errorMsg = wxString::Format( "Error: %s: out of memory", aInfo );
|
||||
break;
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
errorMsg = wxString::Format( "Error: %s: stack underflow", aInfo );
|
||||
break;
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
errorMsg = wxString::Format( "Error: %s: stack overflow", aInfo );
|
||||
break;
|
||||
|
||||
default:
|
||||
errorMsg = wxString::Format( "Error: %s: unknown error", aInfo );
|
||||
break;
|
||||
}
|
||||
|
||||
if( result != GL_NO_ERROR )
|
||||
{
|
||||
if( aThrow )
|
||||
{
|
||||
wxLogTrace( traceGalOpenGlError, wxT( "Throwing exception for glGetError() '%s' "
|
||||
"in file '%s' on line %d." ),
|
||||
errorMsg,
|
||||
aFile,
|
||||
aLine );
|
||||
|
||||
throw std::runtime_error( (const char*) errorMsg.char_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString msg = wxString::Format( wxT( "glGetError() '%s' in file '%s' on line %d." ),
|
||||
errorMsg,
|
||||
aFile,
|
||||
aLine );
|
||||
|
||||
DisplayErrorMessage( nullptr, "OpenGL Error", errorMsg );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// debugMsgCallback is a callback function for glDebugMessageCallback.
|
||||
// It must have the right type ( GLAPIENTRY )
|
||||
static void GLAPIENTRY debugMsgCallback( GLenum aSource, GLenum aType, GLuint aId, GLenum aSeverity,
|
||||
GLsizei aLength, const GLchar* aMessage,
|
||||
const void* aUserParam )
|
||||
{
|
||||
switch( aSeverity )
|
||||
{
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
wxLogTrace( traceGalOpenGlError, wxS( "OpenGL ERROR: %s" ), aMessage );
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
wxLogTrace( traceGalOpenGlError, wxS( "OpenGL WARNING: %s" ), aMessage );
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
wxLogTrace( traceGalOpenGlError, wxS( "OpenGL INFO: %s" ), aMessage );
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void enableGlDebug( bool aEnable )
|
||||
{
|
||||
if( aEnable )
|
||||
{
|
||||
glEnable( GL_DEBUG_OUTPUT );
|
||||
glDebugMessageCallback( (GLDEBUGPROC) debugMsgCallback, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable( GL_DEBUG_OUTPUT );
|
||||
}
|
||||
}
|
||||
51
tests/gal-regression/wasm/webgl/utils.h
Normal file
51
tests/gal-regression/wasm/webgl/utils.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __OPENGL_UTILS_H
|
||||
#define __OPENGL_UTILS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Check if a recent OpenGL operation has failed. If so, display the appropriate message
|
||||
* starting with \a aInfo string to give more details.
|
||||
*
|
||||
* @param aInfo is the beginning of the error message.
|
||||
* @param aFile is the file where the error occurred defined by the C __FILE__ variable.
|
||||
* @param aLine is the line in \a aFile where the error occurred defined by the C __LINE__
|
||||
* variable.
|
||||
* @param aThrow an exception is thrown when true, otherwise only an error message is displayed.
|
||||
* @return GL_NO_ERROR in case of no errors or one of GL_ constants returned by glGetError().
|
||||
*/
|
||||
int checkGlError( const std::string& aInfo, const char* aFile, int aLine, bool aThrow = true );
|
||||
|
||||
/**
|
||||
* Enable or disable OpenGL driver messages output.
|
||||
*
|
||||
* @param aEnable decides whether the message should be shown.
|
||||
*/
|
||||
void enableGlDebug( bool aEnable );
|
||||
|
||||
#endif /* __OPENGL_ERROR_H */
|
||||
90
tests/gal-regression/wasm/webgl/vertex_common.h
Normal file
90
tests/gal-regression/wasm/webgl/vertex_common.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_common.h
|
||||
* @brief Common defines and consts used in vertex related classes.
|
||||
*/
|
||||
|
||||
#ifndef VERTEX_COMMON_H_
|
||||
#define VERTEX_COMMON_H_
|
||||
|
||||
#include "kiglew.h" // Must be included first
|
||||
|
||||
#include <math/vector2d.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
///< Possible types of shaders (keep consistent with the actual shader source in
|
||||
///< kicad_vert.glsl and kicad_frag.glsl).
|
||||
enum SHADER_MODE
|
||||
{
|
||||
SHADER_NONE = 0,
|
||||
SHADER_FILLED_CIRCLE = 2,
|
||||
SHADER_STROKED_CIRCLE = 3,
|
||||
SHADER_FONT = 4,
|
||||
SHADER_LINE_A = 5,
|
||||
SHADER_LINE_B = 6,
|
||||
SHADER_LINE_C = 7,
|
||||
SHADER_LINE_D = 8,
|
||||
SHADER_LINE_E = 9,
|
||||
SHADER_LINE_F = 10,
|
||||
SHADER_HOLE_WALL = 11
|
||||
};
|
||||
|
||||
///< Data structure for vertices {X,Y,Z,R,G,B,A,shader¶m}
|
||||
struct VERTEX
|
||||
{
|
||||
GLfloat x, y, z; // Coordinates
|
||||
GLubyte r, g, b, a; // Color
|
||||
GLfloat shader[4]; // Shader type & params
|
||||
};
|
||||
|
||||
static constexpr size_t VERTEX_SIZE = sizeof( VERTEX );
|
||||
static constexpr size_t VERTEX_STRIDE = VERTEX_SIZE / sizeof( GLfloat );
|
||||
|
||||
static constexpr size_t COORD_OFFSET = offsetof( VERTEX, x );
|
||||
static constexpr size_t COORD_SIZE = sizeof( VERTEX::x ) + sizeof( VERTEX::y ) +
|
||||
sizeof( VERTEX::z );
|
||||
static constexpr size_t COORD_STRIDE = COORD_SIZE / sizeof( GLfloat );
|
||||
|
||||
static constexpr size_t COLOR_OFFSET = offsetof( VERTEX, r );
|
||||
static constexpr size_t COLOR_SIZE = sizeof( VERTEX::r ) + sizeof( VERTEX::g ) +
|
||||
sizeof( VERTEX::b ) + sizeof( VERTEX::a );
|
||||
static constexpr size_t COLOR_STRIDE = COLOR_SIZE / sizeof( GLubyte );
|
||||
|
||||
// Shader attributes
|
||||
static constexpr size_t SHADER_OFFSET = offsetof( VERTEX, shader );
|
||||
static constexpr size_t SHADER_SIZE = sizeof( VERTEX::shader );
|
||||
static constexpr size_t SHADER_STRIDE = SHADER_SIZE / sizeof( GLfloat );
|
||||
|
||||
static constexpr size_t INDEX_SIZE = sizeof( GLuint );
|
||||
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* VERTEX_COMMON_H_ */
|
||||
73
tests/gal-regression/wasm/webgl/vertex_container.cpp
Normal file
73
tests/gal-regression/wasm/webgl/vertex_container.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_container.cpp
|
||||
* @brief Class to store vertices and handle transfers between system memory and GPU memory.
|
||||
*/
|
||||
|
||||
#include "vertex_container.h"
|
||||
#include "cached_container_ram.h"
|
||||
#include "cached_container_gpu.h"
|
||||
#include "noncached_container.h"
|
||||
#include "shader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
|
||||
{
|
||||
if( aCached )
|
||||
{
|
||||
const char* vendor = (const char*) glGetString( GL_VENDOR );
|
||||
|
||||
// Open source drivers do not cope well with GPU memory mapping,
|
||||
// so the vertex data has to be kept in RAM
|
||||
if( strstr( vendor, "X.Org" ) || strstr( vendor, "nouveau" ) )
|
||||
return new CACHED_CONTAINER_RAM;
|
||||
else
|
||||
return new CACHED_CONTAINER_GPU;
|
||||
}
|
||||
|
||||
return new NONCACHED_CONTAINER;
|
||||
}
|
||||
|
||||
|
||||
VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) :
|
||||
m_freeSpace( aSize ),
|
||||
m_currentSize( aSize ),
|
||||
m_initialSize( aSize ),
|
||||
m_vertices( nullptr ),
|
||||
m_failed( false ),
|
||||
m_dirty( true )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
VERTEX_CONTAINER::~VERTEX_CONTAINER()
|
||||
{
|
||||
}
|
||||
191
tests/gal-regression/wasm/webgl/vertex_container.h
Normal file
191
tests/gal-regression/wasm/webgl/vertex_container.h
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_container.h
|
||||
* Class to store vertices and handle transfers between system memory and GPU memory.
|
||||
*/
|
||||
|
||||
#ifndef VERTEX_CONTAINER_H_
|
||||
#define VERTEX_CONTAINER_H_
|
||||
|
||||
#include "vertex_common.h"
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
class VERTEX_CONTAINER
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Return a pointer to a new container of an appropriate type.
|
||||
*/
|
||||
static VERTEX_CONTAINER* MakeContainer( bool aCached );
|
||||
|
||||
virtual ~VERTEX_CONTAINER();
|
||||
|
||||
/**
|
||||
* Return true if the container caches vertex data in RAM or video memory.
|
||||
* Otherwise it is a single batch draw which is later discarded.
|
||||
*/
|
||||
virtual bool IsCached() const = 0;
|
||||
|
||||
/**
|
||||
* Prepare the container for vertices updates.
|
||||
*/
|
||||
virtual void Map() {}
|
||||
|
||||
/**
|
||||
* Finish the vertices updates stage.
|
||||
*/
|
||||
virtual void Unmap() {}
|
||||
|
||||
/**
|
||||
* Set the item for the further actions.
|
||||
*
|
||||
* @param aItem is the item or NULL in case of finishing the item.
|
||||
*/
|
||||
virtual void SetItem( VERTEX_ITEM* aItem ) = 0;
|
||||
|
||||
/**
|
||||
* Clean up after adding an item.
|
||||
*/
|
||||
virtual void FinishItem() {};
|
||||
|
||||
/**
|
||||
* Return allocated space for the requested number of vertices associated with the
|
||||
* current item (set with SetItem()).
|
||||
*
|
||||
* The allocated space is added at the end of the chunk used by the current item and
|
||||
* may serve to store new vertices.
|
||||
*
|
||||
* @param aSize is the number of vertices to be allocated.
|
||||
* @return Pointer to the allocated space or NULL in case of failure.
|
||||
*/
|
||||
virtual VERTEX* Allocate( unsigned int aSize ) = 0;
|
||||
|
||||
/**
|
||||
* Erase the data related to an item.
|
||||
*
|
||||
* @param aItem is the item to be erased.
|
||||
*/
|
||||
virtual void Delete( VERTEX_ITEM* aItem ) = 0;
|
||||
|
||||
/**
|
||||
* Remove all data stored in the container and restores its original state.
|
||||
*/
|
||||
virtual void Clear() = 0;
|
||||
|
||||
/**
|
||||
* Return pointer to the vertices stored in the container.
|
||||
*/
|
||||
VERTEX* GetAllVertices() const
|
||||
{
|
||||
return m_vertices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return vertices stored at the specific offset.
|
||||
*
|
||||
* @param aOffset is the offset.
|
||||
*/
|
||||
virtual VERTEX* GetVertices( unsigned int aOffset ) const
|
||||
{
|
||||
return &m_vertices[aOffset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return amount of vertices currently stored in the container.
|
||||
*/
|
||||
virtual unsigned int GetSize() const
|
||||
{
|
||||
return m_currentSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information about the container cache state.
|
||||
*
|
||||
* @return True in case the vertices have to be reuploaded.
|
||||
*/
|
||||
bool IsDirty() const
|
||||
{
|
||||
return m_dirty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dirty flag, so vertices in the container are going to be reuploaded to the GPU on
|
||||
* the next frame.
|
||||
*/
|
||||
void SetDirty()
|
||||
{
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the dirty flag to prevent reuploading vertices to the GPU memory.
|
||||
*/
|
||||
void ClearDirty()
|
||||
{
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
VERTEX_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
|
||||
|
||||
/**
|
||||
* Return size of the used memory space.
|
||||
*
|
||||
* @return Size of the used memory space (expressed as a number of vertices).
|
||||
*/
|
||||
unsigned int usedSpace() const
|
||||
{
|
||||
return m_currentSize - m_freeSpace;
|
||||
}
|
||||
|
||||
///< Free space left in the container, expressed in vertices
|
||||
unsigned int m_freeSpace;
|
||||
|
||||
///< Current container size, expressed in vertices
|
||||
unsigned int m_currentSize;
|
||||
|
||||
///< Store the initial size, so it can be resized to this on Clear()
|
||||
unsigned int m_initialSize;
|
||||
|
||||
///< Actual storage memory
|
||||
VERTEX* m_vertices;
|
||||
|
||||
// Status flags
|
||||
bool m_failed;
|
||||
bool m_dirty;
|
||||
|
||||
///< Default initial size of a container (expressed in vertices)
|
||||
static constexpr unsigned int DEFAULT_SIZE = 1048576;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* VERTEX_CONTAINER_H_ */
|
||||
57
tests/gal-regression/wasm/webgl/vertex_item.cpp
Normal file
57
tests/gal-regression/wasm/webgl/vertex_item.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_item.cpp
|
||||
* @brief Class to handle an item held in a container.
|
||||
*/
|
||||
|
||||
#include "vertex_item.h"
|
||||
#include "vertex_manager.h"
|
||||
#include <cstring>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
VERTEX_ITEM::VERTEX_ITEM( const VERTEX_MANAGER& aManager ) :
|
||||
m_manager( aManager ),
|
||||
m_offset( 0 ),
|
||||
m_size( 0 )
|
||||
{
|
||||
// As the item is created, we are going to modify it, so call to SetItem() is needed
|
||||
m_manager.SetItem( *this );
|
||||
}
|
||||
|
||||
|
||||
VERTEX_ITEM::~VERTEX_ITEM()
|
||||
{
|
||||
m_manager.FreeItem( *this );
|
||||
}
|
||||
|
||||
|
||||
VERTEX* VERTEX_ITEM::GetVertices() const
|
||||
{
|
||||
return m_manager.GetVertices( *this );
|
||||
}
|
||||
105
tests/gal-regression/wasm/webgl/vertex_item.h
Normal file
105
tests/gal-regression/wasm/webgl/vertex_item.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_item.h
|
||||
* Class to handle an item held in a container.
|
||||
*/
|
||||
|
||||
#ifndef VERTEX_ITEM_H_
|
||||
#define VERTEX_ITEM_H_
|
||||
|
||||
#include "vertex_common.h"
|
||||
#include <gal/color4d.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VERTEX_MANAGER;
|
||||
|
||||
class VERTEX_ITEM
|
||||
{
|
||||
public:
|
||||
friend class CACHED_CONTAINER;
|
||||
friend class CACHED_CONTAINER_GPU;
|
||||
friend class VERTEX_MANAGER;
|
||||
|
||||
explicit VERTEX_ITEM( const VERTEX_MANAGER& aManager );
|
||||
~VERTEX_ITEM();
|
||||
|
||||
/**
|
||||
* Return information about number of vertices stored.
|
||||
*
|
||||
* @return Number of vertices.
|
||||
*/
|
||||
inline unsigned int GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return data offset in the container.
|
||||
*
|
||||
* @return Data offset expressed as a number of vertices.
|
||||
*/
|
||||
inline unsigned int GetOffset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pointer to the data used by the VERTEX_ITEM.
|
||||
*/
|
||||
VERTEX* GetVertices() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set data offset in the container.
|
||||
*
|
||||
* @param aOffset is the offset expressed as a number of vertices.
|
||||
*/
|
||||
inline void setOffset( unsigned int aOffset )
|
||||
{
|
||||
m_offset = aOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data size in the container.
|
||||
*
|
||||
* @param aSize is the size expressed as a number of vertices.
|
||||
*/
|
||||
inline void setSize( unsigned int aSize )
|
||||
{
|
||||
m_size = aSize;
|
||||
}
|
||||
|
||||
const VERTEX_MANAGER& m_manager;
|
||||
unsigned int m_offset;
|
||||
unsigned int m_size;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* VERTEX_ITEM_H_ */
|
||||
318
tests/gal-regression/wasm/webgl/vertex_manager.cpp
Normal file
318
tests/gal-regression/wasm/webgl/vertex_manager.cpp
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_manager.cpp
|
||||
* @brief Class to control vertex container and GPU with possibility of emulating old-style OpenGL
|
||||
* 1.0 state machine using modern OpenGL methods.
|
||||
*/
|
||||
|
||||
#include "vertex_manager.h"
|
||||
#include "cached_container.h"
|
||||
#include "noncached_container.h"
|
||||
#include "gpu_manager.h"
|
||||
#include "vertex_item.h"
|
||||
#include <confirm.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable #VERTEX_MANAGER debugging output.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar traceVertexManager[] = wxT( "KICAD_VERTEX_MANAGER" );
|
||||
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
|
||||
m_noTransform( true ),
|
||||
m_transform( 1.0f ),
|
||||
m_reserved( nullptr ),
|
||||
m_reservedSpace( 0 )
|
||||
{
|
||||
m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) );
|
||||
m_gpu.reset( GPU_MANAGER::MakeManager( m_container.get() ) );
|
||||
|
||||
// There is no shader used by default
|
||||
for( unsigned int i = 0; i < SHADER_STRIDE; ++i )
|
||||
m_shader[i] = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::Map()
|
||||
{
|
||||
m_container->Map();
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::Unmap()
|
||||
{
|
||||
m_container->Unmap();
|
||||
}
|
||||
|
||||
|
||||
bool VERTEX_MANAGER::Reserve( unsigned int aSize )
|
||||
{
|
||||
if( !aSize )
|
||||
return true;
|
||||
|
||||
// flags to avoid hanging by calling DisplayError too many times:
|
||||
static bool show_err_reserve = true;
|
||||
static bool show_err_alloc = true;
|
||||
|
||||
if( m_reservedSpace != 0 || m_reserved )
|
||||
{
|
||||
if( show_err_reserve )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Reserve: Did not use all previous vertices allocated" ) );
|
||||
show_err_reserve = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_reserved = m_container->Allocate( aSize );
|
||||
|
||||
if( m_reserved == nullptr )
|
||||
{
|
||||
if( show_err_alloc )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Reserve: Vertex allocation error" ) );
|
||||
show_err_alloc = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_reservedSpace = aSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ )
|
||||
{
|
||||
// flag to avoid hanging by calling DisplayError too many times:
|
||||
static bool show_err = true;
|
||||
|
||||
// Obtain the pointer to the vertex in the currently used container
|
||||
VERTEX* newVertex;
|
||||
|
||||
if( m_reservedSpace > 0 )
|
||||
{
|
||||
newVertex = m_reserved++;
|
||||
--m_reservedSpace;
|
||||
|
||||
if( m_reservedSpace == 0 )
|
||||
m_reserved = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newVertex = m_container->Allocate( 1 );
|
||||
|
||||
if( newVertex == nullptr )
|
||||
{
|
||||
if( show_err )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
|
||||
show_err = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
putVertex( *newVertex, aX, aY, aZ );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize )
|
||||
{
|
||||
// flag to avoid hanging by calling DisplayError too many times:
|
||||
static bool show_err = true;
|
||||
|
||||
// Obtain pointer to the vertex in currently used container
|
||||
VERTEX* newVertex = m_container->Allocate( aSize );
|
||||
|
||||
if( newVertex == nullptr )
|
||||
{
|
||||
if( show_err )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertices: Vertex allocation error" ) );
|
||||
show_err = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put vertices in already allocated memory chunk
|
||||
for( unsigned int i = 0; i < aSize; ++i )
|
||||
{
|
||||
putVertex( newVertex[i], aVertices[i].x, aVertices[i].y, aVertices[i].z );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::SetItem( VERTEX_ITEM& aItem ) const
|
||||
{
|
||||
m_container->SetItem( &aItem );
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::FinishItem() const
|
||||
{
|
||||
if( m_reservedSpace != 0 || m_reserved )
|
||||
wxLogTrace( traceVertexManager, wxS( "Did not use all previous vertices allocated" ) );
|
||||
|
||||
m_container->FinishItem();
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::FreeItem( VERTEX_ITEM& aItem ) const
|
||||
{
|
||||
m_container->Delete( &aItem );
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const
|
||||
{
|
||||
unsigned int size = aItem.GetSize();
|
||||
unsigned int offset = aItem.GetOffset();
|
||||
|
||||
VERTEX* vertex = m_container->GetVertices( offset );
|
||||
|
||||
for( unsigned int i = 0; i < size; ++i )
|
||||
{
|
||||
vertex->r = aColor.r * 255.0;
|
||||
vertex->g = aColor.g * 255.0;
|
||||
vertex->b = aColor.b * 255.0;
|
||||
vertex->a = aColor.a * 255.0;
|
||||
vertex++;
|
||||
}
|
||||
|
||||
m_container->SetDirty();
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const
|
||||
{
|
||||
unsigned int size = aItem.GetSize();
|
||||
unsigned int offset = aItem.GetOffset();
|
||||
|
||||
VERTEX* vertex = m_container->GetVertices( offset );
|
||||
|
||||
for( unsigned int i = 0; i < size; ++i )
|
||||
{
|
||||
vertex->z = aDepth;
|
||||
vertex++;
|
||||
}
|
||||
|
||||
m_container->SetDirty();
|
||||
}
|
||||
|
||||
|
||||
VERTEX* VERTEX_MANAGER::GetVertices( const VERTEX_ITEM& aItem ) const
|
||||
{
|
||||
if( aItem.GetSize() == 0 )
|
||||
return nullptr; // The item is not stored in the container
|
||||
|
||||
return m_container->GetVertices( aItem.GetOffset() );
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::SetShader( SHADER& aShader ) const
|
||||
{
|
||||
m_gpu->SetShader( aShader );
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::Clear() const
|
||||
{
|
||||
m_container->Clear();
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::BeginDrawing() const
|
||||
{
|
||||
m_gpu->BeginDrawing();
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::DrawItem( const VERTEX_ITEM& aItem ) const
|
||||
{
|
||||
m_gpu->DrawIndices( &aItem );
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::EndDrawing() const
|
||||
{
|
||||
m_gpu->EndDrawing();
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat aZ ) const
|
||||
{
|
||||
// Modify the vertex according to the currently used transformations
|
||||
if( m_noTransform )
|
||||
{
|
||||
// Simply copy coordinates, when the transform matrix is the identity matrix
|
||||
aTarget.x = aX;
|
||||
aTarget.y = aY;
|
||||
aTarget.z = aZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply transformations
|
||||
glm::vec4 transVertex( aX, aY, aZ, 1.0f );
|
||||
transVertex = m_transform * transVertex;
|
||||
|
||||
aTarget.x = transVertex.x;
|
||||
aTarget.y = transVertex.y;
|
||||
aTarget.z = transVertex.z;
|
||||
}
|
||||
|
||||
// Apply currently used color
|
||||
aTarget.r = m_color[0];
|
||||
aTarget.g = m_color[1];
|
||||
aTarget.b = m_color[2];
|
||||
aTarget.a = m_color[3];
|
||||
|
||||
// Apply currently used shader
|
||||
for( unsigned int j = 0; j < SHADER_STRIDE; ++j )
|
||||
{
|
||||
aTarget.shader[j] = m_shader[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_MANAGER::EnableDepthTest( bool aEnabled )
|
||||
{
|
||||
m_gpu->EnableDepthTest( aEnabled );
|
||||
}
|
||||
393
tests/gal-regression/wasm/webgl/vertex_manager.h
Normal file
393
tests/gal-regression/wasm/webgl/vertex_manager.h
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vertex_manager.h
|
||||
*/
|
||||
|
||||
#ifndef VERTEX_MANAGER_H_
|
||||
#define VERTEX_MANAGER_H_
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include "vertex_common.h"
|
||||
#include <gal/color4d.h>
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class SHADER;
|
||||
class VERTEX_ITEM;
|
||||
class VERTEX_CONTAINER;
|
||||
class GPU_MANAGER;
|
||||
|
||||
/**
|
||||
* Class to control vertex container and GPU with possibility of emulating old-style OpenGL
|
||||
* 1.0 state machine using modern OpenGL methods.
|
||||
*/
|
||||
class VERTEX_MANAGER
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param aCached says if vertices should be cached in GPU or system memory. For data that
|
||||
* does not change every frame, it is better to store vertices in GPU memory.
|
||||
*/
|
||||
VERTEX_MANAGER( bool aCached );
|
||||
|
||||
/**
|
||||
* Map vertex buffer.
|
||||
*/
|
||||
void Map();
|
||||
|
||||
/**
|
||||
* Unmap vertex buffer.
|
||||
*/
|
||||
void Unmap();
|
||||
|
||||
/**
|
||||
* Allocate space for vertices, so it will be used with subsequent Vertex() calls.
|
||||
*
|
||||
* @param aSize is the number of vertices that should be available in the reserved space.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool Reserve( unsigned int aSize );
|
||||
|
||||
/**
|
||||
* Add a vertex with the given coordinates to the currently set item.
|
||||
*
|
||||
* Color & shader parameters stored in aVertex are ignored, instead color & shader set
|
||||
* by Color() and Shader() functions are used. Vertex coordinates will have the current
|
||||
* transformation matrix applied.
|
||||
*
|
||||
* @param aVertex contains vertex coordinates.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
inline bool Vertex( const VERTEX& aVertex )
|
||||
{
|
||||
return Vertex( aVertex.x, aVertex.y, aVertex.z );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a vertex with the given coordinates to the currently set item.
|
||||
*
|
||||
* Vertex coordinates will have the current transformation matrix applied.
|
||||
*
|
||||
* @param aX is the X coordinate of the new vertex.
|
||||
* @param aY is the Y coordinate of the new vertex.
|
||||
* @param aZ is the Z coordinate of the new vertex.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool Vertex( GLfloat aX, GLfloat aY, GLfloat aZ );
|
||||
|
||||
/**
|
||||
* Add a vertex with the given coordinates to the currently set item.
|
||||
*
|
||||
* Vertex coordinates will have the current transformation matrix applied.
|
||||
*
|
||||
* @param aXY are the XY coordinates of the new vertex.
|
||||
* @param aZ is the Z coordinate of the new vertex.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool Vertex( const VECTOR2D& aXY, GLfloat aZ )
|
||||
{
|
||||
return Vertex( aXY.x, aXY.y, aZ );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or more vertices to the currently set item.
|
||||
*
|
||||
* It takes advantage of allocating memory in advance, so should be faster than
|
||||
* adding vertices one by one. Color & shader parameters stored in aVertices are
|
||||
* ignored, instead color & shader set by Color() and Shader() functions are used.
|
||||
* All the vertex coordinates will have the current transformation matrix applied.
|
||||
*
|
||||
* @param aVertices contains vertices to be added.
|
||||
* @param aSize is the number of vertices to be added.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool Vertices( const VERTEX aVertices[], unsigned int aSize );
|
||||
|
||||
/**
|
||||
* Change currently used color that will be applied to newly added vertices.
|
||||
*
|
||||
* @param aColor is the new color.
|
||||
*/
|
||||
inline void Color( const COLOR4D& aColor )
|
||||
{
|
||||
m_color[0] = aColor.r * 255.0;
|
||||
m_color[1] = aColor.g * 255.0;
|
||||
m_color[2] = aColor.b * 255.0;
|
||||
m_color[3] = aColor.a * 255.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change currently used color that will be applied to newly added vertices.
|
||||
*
|
||||
* It is the equivalent of glColor4f() function.
|
||||
*
|
||||
* @param aRed is the red component of the new color.
|
||||
* @param aGreen is the green component of the new color.
|
||||
* @param aBlue is the blue component of the new color.
|
||||
* @param aAlpha is the alpha component of the new color.
|
||||
*/
|
||||
inline void Color( GLfloat aRed, GLfloat aGreen, GLfloat aBlue, GLfloat aAlpha )
|
||||
{
|
||||
m_color[0] = aRed * 255.0;
|
||||
m_color[1] = aGreen * 255.0;
|
||||
m_color[2] = aBlue * 255.0;
|
||||
m_color[3] = aAlpha * 255.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change currently used shader and its parameters that will be applied to newly added
|
||||
* vertices.
|
||||
*
|
||||
* Parameters depend on shader, for more information have a look at shaders source code.
|
||||
*
|
||||
* @see SHADER_TYPE
|
||||
*
|
||||
* @param aShaderType is the a shader type to be applied.
|
||||
* @param aParam1 is the optional parameter for a shader.
|
||||
* @param aParam2 is the optional parameter for a shader.
|
||||
* @param aParam3 is the optional parameter for a shader.
|
||||
*/
|
||||
inline void Shader( GLfloat aShaderType, GLfloat aParam1 = 0.0f, GLfloat aParam2 = 0.0f,
|
||||
GLfloat aParam3 = 0.0f )
|
||||
{
|
||||
m_shader[0] = aShaderType;
|
||||
m_shader[1] = aParam1;
|
||||
m_shader[2] = aParam2;
|
||||
m_shader[3] = aParam3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply the current matrix by a translation matrix, so newly vertices will be
|
||||
* translated by the given vector.
|
||||
*
|
||||
* It is the equivalent of the glTranslatef() function.
|
||||
*
|
||||
* @param aX is the X coordinate of a translation vector.
|
||||
* @param aY is the X coordinate of a translation vector.
|
||||
* @param aZ is the X coordinate of a translation vector.
|
||||
*/
|
||||
inline void Translate( GLfloat aX, GLfloat aY, GLfloat aZ )
|
||||
{
|
||||
m_transform = glm::translate( m_transform, glm::vec3( aX, aY, aZ ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply the current matrix by a rotation matrix, so the newly vertices will be
|
||||
* rotated by the given angles.
|
||||
*
|
||||
* It is the equivalent of the glRotatef() function.
|
||||
*
|
||||
* @param aAngle is the angle of rotation, in radians.
|
||||
* @param aX is a multiplier for the X axis
|
||||
* @param aY is a multiplier for the Y axis
|
||||
* @param aZ is a multiplier for the Z axis.
|
||||
*/
|
||||
inline void Rotate( GLfloat aAngle, GLfloat aX, GLfloat aY, GLfloat aZ )
|
||||
{
|
||||
m_transform = glm::rotate( m_transform, aAngle, glm::vec3( aX, aY, aZ ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply the current matrix by a scaling matrix, so the newly vertices will be
|
||||
* scaled by the given factors.
|
||||
*
|
||||
* It is the equivalent of the glScalef() function.
|
||||
*
|
||||
* @param aX is the X axis scaling factor.
|
||||
* @param aY is the Y axis scaling factor.
|
||||
* @param aZ is the Z axis scaling factor.
|
||||
*/
|
||||
inline void Scale( GLfloat aX, GLfloat aY, GLfloat aZ )
|
||||
{
|
||||
m_transform = glm::scale( m_transform, glm::vec3( aX, aY, aZ ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the current transformation matrix stack.
|
||||
*
|
||||
* It is the equivalent of the glPushMatrix() function.
|
||||
*/
|
||||
inline void PushMatrix()
|
||||
{
|
||||
m_transformStack.push( m_transform );
|
||||
|
||||
// Every transformation starts with PushMatrix
|
||||
m_noTransform = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop the current transformation matrix stack.
|
||||
*
|
||||
* It is the equivalent of the glPopMatrix() function.
|
||||
*/
|
||||
void PopMatrix()
|
||||
{
|
||||
wxASSERT( !m_transformStack.empty() );
|
||||
|
||||
m_transform = m_transformStack.top();
|
||||
m_transformStack.pop();
|
||||
|
||||
if( m_transformStack.empty() )
|
||||
{
|
||||
// We return back to the identity matrix, thus no vertex transformation is needed
|
||||
m_noTransform = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an item to start its modifications.
|
||||
*
|
||||
* After calling the function it is possible to add vertices using function Add().
|
||||
*
|
||||
* @param aItem is the item that is going to store vertices in the container.
|
||||
*/
|
||||
void SetItem( VERTEX_ITEM& aItem ) const;
|
||||
|
||||
/**
|
||||
* Clean after adding an item.
|
||||
*/
|
||||
void FinishItem() const;
|
||||
|
||||
/**
|
||||
* Free the memory occupied by the item, so it is no longer stored in the container.
|
||||
*
|
||||
* @param aItem is the item to be freed
|
||||
*/
|
||||
void FreeItem( VERTEX_ITEM& aItem ) const;
|
||||
|
||||
/**
|
||||
* Change the color of all vertices owned by an item.
|
||||
*
|
||||
* @param aItem is the item to change.
|
||||
* @param aColor is the new color to be applied.
|
||||
*/
|
||||
void ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const;
|
||||
|
||||
/**
|
||||
* Change the depth of all vertices owned by an item.
|
||||
*
|
||||
* @param aItem is the item to change.
|
||||
* @param aDepth is the new color to be applied.
|
||||
*/
|
||||
void ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const;
|
||||
|
||||
/**
|
||||
* Return a pointer to the vertices owned by an item.
|
||||
*
|
||||
* @param aItem is the owner of vertices that are going to be returned.
|
||||
* @return Pointer to the vertices or NULL if the item is not stored at the container.
|
||||
*/
|
||||
VERTEX* GetVertices( const VERTEX_ITEM& aItem ) const;
|
||||
|
||||
const glm::mat4& GetTransformation() const
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a shader program that is going to be used during rendering.
|
||||
*
|
||||
* @param aShader is the object containing compiled and linked shader program.
|
||||
*/
|
||||
void SetShader( SHADER& aShader ) const;
|
||||
|
||||
/**
|
||||
* Remove all the stored vertices from the container.
|
||||
*/
|
||||
void Clear() const;
|
||||
|
||||
/**
|
||||
* Prepare buffers and items to start drawing.
|
||||
*/
|
||||
void BeginDrawing() const;
|
||||
|
||||
/**
|
||||
* Draw an item to the buffer.
|
||||
*
|
||||
* @param aItem is the item to be drawn.
|
||||
*/
|
||||
void DrawItem( const VERTEX_ITEM& aItem ) const;
|
||||
|
||||
/**
|
||||
* Finish drawing operations.
|
||||
*/
|
||||
void EndDrawing() const;
|
||||
|
||||
/**
|
||||
* Enable/disable Z buffer depth test.
|
||||
*/
|
||||
void EnableDepthTest( bool aEnabled );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Apply all transformation to the given coordinates and store them at the specified target.
|
||||
*
|
||||
* @param aTarget is the place where the new vertex is going to be stored (it has to be
|
||||
* allocated first).
|
||||
* @param aX is the X coordinate of the new vertex.
|
||||
* @param aY is the Y coordinate of the new vertex.
|
||||
* @param aZ is the Z coordinate of the new vertex.
|
||||
*/
|
||||
void putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat aZ ) const;
|
||||
|
||||
/// Container for vertices, may be cached or noncached
|
||||
std::shared_ptr<VERTEX_CONTAINER> m_container;
|
||||
|
||||
/// GPU manager for data transfers and drawing operations
|
||||
std::shared_ptr<GPU_MANAGER> m_gpu;
|
||||
|
||||
/// State machine variables
|
||||
/// True in case there is no need to transform vertices
|
||||
bool m_noTransform;
|
||||
|
||||
/// Currently used transform matrix
|
||||
glm::mat4 m_transform;
|
||||
|
||||
/// Stack of transformation matrices, used for Push/PopMatrix
|
||||
std::stack<glm::mat4> m_transformStack;
|
||||
|
||||
/// Currently used color
|
||||
GLubyte m_color[COLOR_STRIDE];
|
||||
|
||||
/// Currently used shader and its parameters
|
||||
GLfloat m_shader[SHADER_STRIDE];
|
||||
|
||||
/// Currently reserved chunk to store vertices
|
||||
VERTEX* m_reserved;
|
||||
|
||||
/// Currently available reserved space
|
||||
unsigned int m_reservedSpace;
|
||||
};
|
||||
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* VERTEX_MANAGER_H_ */
|
||||
562
tests/gal-regression/wasm/webgl/webgl_antialiasing.cpp
Normal file
562
tests/gal-regression/wasm/webgl/webgl_antialiasing.cpp
Normal file
|
|
@ -0,0 +1,562 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "webgl_antialiasing.h"
|
||||
#include "webgl_compositor.h"
|
||||
#include "utils.h"
|
||||
#include <gal/color4d.h>
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include <glsl_smaa_base.h>
|
||||
#include <glsl_smaa_pass_1_frag_color.h>
|
||||
#include <glsl_smaa_pass_1_frag_luma.h>
|
||||
#include <glsl_smaa_pass_1_vert.h>
|
||||
#include <glsl_smaa_pass_2_frag.h>
|
||||
#include <glsl_smaa_pass_2_vert.h>
|
||||
#include <glsl_smaa_pass_3_frag.h>
|
||||
#include <glsl_smaa_pass_3_vert.h>
|
||||
#include "SmaaAreaTex.h"
|
||||
#include "SmaaSearchTex.h"
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
// =========================
|
||||
// ANTIALIASING_NONE
|
||||
// =========================
|
||||
|
||||
ANTIALIASING_NONE::ANTIALIASING_NONE( WEBGL_COMPOSITOR* aCompositor ) :
|
||||
compositor( aCompositor )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool ANTIALIASING_NONE::Init()
|
||||
{
|
||||
// Nothing to initialize
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I ANTIALIASING_NONE::GetInternalBufferSize()
|
||||
{
|
||||
return compositor->GetScreenSize();
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_NONE::DrawBuffer( GLuint buffer )
|
||||
{
|
||||
compositor->DrawBuffer( buffer, WEBGL_COMPOSITOR::DIRECT_RENDERING );
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_NONE::Present()
|
||||
{
|
||||
// Nothing to present, draw_buffer already drew to the screen
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_NONE::OnLostBuffers()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_NONE::Begin()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
unsigned int ANTIALIASING_NONE::CreateBuffer()
|
||||
{
|
||||
return compositor->CreateBuffer( compositor->GetScreenSize() );
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
void draw_fullscreen_primitive()
|
||||
{
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
glBegin( GL_TRIANGLES );
|
||||
glTexCoord2f( 0.0f, 1.0f );
|
||||
glVertex2f( -1.0f, 1.0f );
|
||||
glTexCoord2f( 0.0f, 0.0f );
|
||||
glVertex2f( -1.0f, -1.0f );
|
||||
glTexCoord2f( 1.0f, 1.0f );
|
||||
glVertex2f( 1.0f, 1.0f );
|
||||
|
||||
glTexCoord2f( 1.0f, 1.0f );
|
||||
glVertex2f( 1.0f, 1.0f );
|
||||
glTexCoord2f( 0.0f, 0.0f );
|
||||
glVertex2f( -1.0f, -1.0f );
|
||||
glTexCoord2f( 1.0f, 0.0f );
|
||||
glVertex2f( 1.0f, -1.0f );
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// =========================
|
||||
// ANTIALIASING_SUPERSAMPLING
|
||||
// =========================
|
||||
|
||||
ANTIALIASING_SUPERSAMPLING::ANTIALIASING_SUPERSAMPLING( WEBGL_COMPOSITOR* aCompositor ) :
|
||||
compositor( aCompositor ),
|
||||
ssaaMainBuffer( 0 ), areBuffersCreated( false ), areShadersCreated( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool ANTIALIASING_SUPERSAMPLING::Init()
|
||||
{
|
||||
areShadersCreated = false;
|
||||
|
||||
if( !areBuffersCreated )
|
||||
{
|
||||
ssaaMainBuffer = compositor->CreateBuffer();
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
|
||||
areBuffersCreated = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I ANTIALIASING_SUPERSAMPLING::GetInternalBufferSize()
|
||||
{
|
||||
return compositor->GetScreenSize() * 2;
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SUPERSAMPLING::Begin()
|
||||
{
|
||||
compositor->SetBuffer( ssaaMainBuffer );
|
||||
compositor->ClearBuffer( COLOR4D::BLACK );
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SUPERSAMPLING::DrawBuffer( GLuint aBuffer )
|
||||
{
|
||||
compositor->DrawBuffer( aBuffer, ssaaMainBuffer );
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SUPERSAMPLING::Present()
|
||||
{
|
||||
glDisable( GL_BLEND );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
glBindTexture( GL_TEXTURE_2D, compositor->GetBufferTexture( ssaaMainBuffer ) );
|
||||
compositor->SetBuffer( WEBGL_COMPOSITOR::DIRECT_RENDERING );
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE );
|
||||
|
||||
draw_fullscreen_primitive();
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SUPERSAMPLING::OnLostBuffers()
|
||||
{
|
||||
areBuffersCreated = false;
|
||||
}
|
||||
|
||||
|
||||
unsigned int ANTIALIASING_SUPERSAMPLING::CreateBuffer()
|
||||
{
|
||||
return compositor->CreateBuffer( GetInternalBufferSize() );
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// ANTIALIASING_SMAA
|
||||
// ===============================
|
||||
|
||||
ANTIALIASING_SMAA::ANTIALIASING_SMAA( WEBGL_COMPOSITOR* aCompositor ) :
|
||||
areBuffersInitialized( false ),
|
||||
shadersLoaded( false ),
|
||||
compositor( aCompositor )
|
||||
{
|
||||
smaaBaseBuffer = 0;
|
||||
smaaEdgesBuffer = 0;
|
||||
smaaBlendBuffer = 0;
|
||||
smaaAreaTex = 0;
|
||||
smaaSearchTex = 0;
|
||||
|
||||
pass_1_metrics = 0;
|
||||
pass_2_metrics = 0;
|
||||
pass_3_metrics = 0;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I ANTIALIASING_SMAA::GetInternalBufferSize()
|
||||
{
|
||||
return compositor->GetScreenSize();
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SMAA::loadShaders()
|
||||
{
|
||||
// Load constant textures
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
|
||||
glGenTextures( 1, &smaaAreaTex );
|
||||
glBindTexture( GL_TEXTURE_2D, smaaAreaTex );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, 0, GL_RG,
|
||||
GL_UNSIGNED_BYTE, areaTexBytes );
|
||||
checkGlError( "loading smaa area tex", __FILE__, __LINE__ );
|
||||
|
||||
glGenTextures( 1, &smaaSearchTex );
|
||||
glBindTexture( GL_TEXTURE_2D, smaaSearchTex );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 0, GL_RED,
|
||||
GL_UNSIGNED_BYTE, searchTexBytes );
|
||||
checkGlError( "loading smaa search tex", __FILE__, __LINE__ );
|
||||
|
||||
// Quality settings:
|
||||
// THRESHOLD: intended to exclude spurious edges in photorealistic game graphics
|
||||
// but in a high-contrast CAD application, all edges are intentional
|
||||
// should be set fairly low, so user color choices do not affect antialiasing
|
||||
// MAX_SEARCH_STEPS: steps of 2px, searched in H/V direction to discover true angle of edges
|
||||
// improves AA for lines close H/V but creates fuzzyness at junctions
|
||||
// MAX_SEARCH_STEPS_DIAG: steps of 1px, searched in diagonal direction
|
||||
// improves lines close to 45deg but turns small circles into octagons
|
||||
// CORNER_ROUNDING: SMAA can distinguish actual corners from aliasing jaggies,
|
||||
// we want to preserve those as much as possible
|
||||
// Edge Detection: In Eeschema, when a single pixel line changes color, edge detection using
|
||||
// color is too aggressive and leads to a white spot at the transition point
|
||||
std::string quality_string;
|
||||
std::string edge_detect_shader;
|
||||
|
||||
// trades imperfect AA of shallow angles for a near artifact-free reproduction of fine features
|
||||
// jaggies are smoothed over max 5px (original step + 2px in both directions)
|
||||
quality_string = "#define SMAA_THRESHOLD 0.005\n"
|
||||
"#define SMAA_MAX_SEARCH_STEPS 1\n"
|
||||
"#define SMAA_MAX_SEARCH_STEPS_DIAG 2\n"
|
||||
"#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 1.5\n"
|
||||
"#define SMAA_CORNER_ROUNDING 0\n";
|
||||
edge_detect_shader = BUILTIN_SHADERS::glsl_smaa_pass_1_frag_luma;
|
||||
|
||||
// set up shaders
|
||||
std::string vert_preamble( R"SHADER(
|
||||
#version 120
|
||||
#define SMAA_GLSL_2_1
|
||||
#define SMAA_INCLUDE_VS 1
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
uniform vec4 SMAA_RT_METRICS;
|
||||
)SHADER" );
|
||||
|
||||
std::string frag_preamble( R"SHADER(
|
||||
#version 120
|
||||
#define SMAA_GLSL_2_1
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
#define SMAA_INCLUDE_PS 1
|
||||
uniform vec4 SMAA_RT_METRICS;
|
||||
)SHADER" );
|
||||
|
||||
//
|
||||
// Set up pass 1 Shader
|
||||
//
|
||||
pass_1_shader = std::make_unique<SHADER>();
|
||||
pass_1_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, quality_string,
|
||||
BUILTIN_SHADERS::glsl_smaa_base,
|
||||
BUILTIN_SHADERS::glsl_smaa_pass_1_vert );
|
||||
pass_1_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble,
|
||||
quality_string, BUILTIN_SHADERS::glsl_smaa_base,
|
||||
edge_detect_shader );
|
||||
pass_1_shader->Link();
|
||||
checkGlError( "linking pass 1 shader", __FILE__, __LINE__ );
|
||||
|
||||
GLint smaaColorTexParameter = pass_1_shader->AddParameter( "colorTex" );
|
||||
checkGlError( "pass1: getting colorTex uniform", __FILE__, __LINE__ );
|
||||
pass_1_metrics = pass_1_shader->AddParameter( "SMAA_RT_METRICS" );
|
||||
checkGlError( "pass1: getting metrics uniform", __FILE__, __LINE__ );
|
||||
|
||||
pass_1_shader->Use();
|
||||
checkGlError( "pass1: using shader", __FILE__, __LINE__ );
|
||||
pass_1_shader->SetParameter( smaaColorTexParameter, 0 );
|
||||
checkGlError( "pass1: setting colorTex uniform", __FILE__, __LINE__ );
|
||||
pass_1_shader->Deactivate();
|
||||
checkGlError( "pass1: deactivating shader", __FILE__, __LINE__ );
|
||||
|
||||
//
|
||||
// set up pass 2 shader
|
||||
//
|
||||
pass_2_shader = std::make_unique<SHADER>();
|
||||
pass_2_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, quality_string,
|
||||
BUILTIN_SHADERS::glsl_smaa_base,
|
||||
BUILTIN_SHADERS::glsl_smaa_pass_2_vert );
|
||||
pass_2_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble,
|
||||
quality_string, BUILTIN_SHADERS::glsl_smaa_base,
|
||||
BUILTIN_SHADERS::glsl_smaa_pass_2_frag );
|
||||
pass_2_shader->Link();
|
||||
checkGlError( "linking pass 2 shader", __FILE__, __LINE__ );
|
||||
|
||||
GLint smaaEdgesTexParameter = pass_2_shader->AddParameter( "edgesTex" );
|
||||
checkGlError( "pass2: getting colorTex uniform", __FILE__, __LINE__ );
|
||||
GLint smaaAreaTexParameter = pass_2_shader->AddParameter( "areaTex" );
|
||||
checkGlError( "pass2: getting areaTex uniform", __FILE__, __LINE__ );
|
||||
GLint smaaSearchTexParameter = pass_2_shader->AddParameter( "searchTex" );
|
||||
checkGlError( "pass2: getting searchTex uniform", __FILE__, __LINE__ );
|
||||
pass_2_metrics = pass_2_shader->AddParameter( "SMAA_RT_METRICS" );
|
||||
checkGlError( "pass2: getting metrics uniform", __FILE__, __LINE__ );
|
||||
|
||||
pass_2_shader->Use();
|
||||
checkGlError( "pass2: using shader", __FILE__, __LINE__ );
|
||||
pass_2_shader->SetParameter( smaaEdgesTexParameter, 0 );
|
||||
checkGlError( "pass2: setting colorTex uniform", __FILE__, __LINE__ );
|
||||
pass_2_shader->SetParameter( smaaAreaTexParameter, 1 );
|
||||
checkGlError( "pass2: setting areaTex uniform", __FILE__, __LINE__ );
|
||||
pass_2_shader->SetParameter( smaaSearchTexParameter, 3 );
|
||||
checkGlError( "pass2: setting searchTex uniform", __FILE__, __LINE__ );
|
||||
pass_2_shader->Deactivate();
|
||||
checkGlError( "pass2: deactivating shader", __FILE__, __LINE__ );
|
||||
|
||||
//
|
||||
// set up pass 3 shader
|
||||
//
|
||||
pass_3_shader = std::make_unique<SHADER>();
|
||||
pass_3_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, quality_string,
|
||||
BUILTIN_SHADERS::glsl_smaa_base,
|
||||
BUILTIN_SHADERS::glsl_smaa_pass_3_vert );
|
||||
pass_3_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble,
|
||||
quality_string, BUILTIN_SHADERS::glsl_smaa_base,
|
||||
BUILTIN_SHADERS::glsl_smaa_pass_3_frag );
|
||||
pass_3_shader->Link();
|
||||
|
||||
GLint smaaP3ColorTexParameter = pass_3_shader->AddParameter( "colorTex" );
|
||||
checkGlError( "pass3: getting colorTex uniform", __FILE__, __LINE__ );
|
||||
GLint smaaBlendTexParameter = pass_3_shader->AddParameter( "blendTex" );
|
||||
checkGlError( "pass3: getting blendTex uniform", __FILE__, __LINE__ );
|
||||
pass_3_metrics = pass_3_shader->AddParameter( "SMAA_RT_METRICS" );
|
||||
checkGlError( "pass3: getting metrics uniform", __FILE__, __LINE__ );
|
||||
|
||||
pass_3_shader->Use();
|
||||
checkGlError( "pass3: using shader", __FILE__, __LINE__ );
|
||||
pass_3_shader->SetParameter( smaaP3ColorTexParameter, 0 );
|
||||
checkGlError( "pass3: setting colorTex uniform", __FILE__, __LINE__ );
|
||||
pass_3_shader->SetParameter( smaaBlendTexParameter, 1 );
|
||||
checkGlError( "pass3: setting blendTex uniform", __FILE__, __LINE__ );
|
||||
pass_3_shader->Deactivate();
|
||||
checkGlError( "pass3: deactivating shader", __FILE__, __LINE__ );
|
||||
|
||||
shadersLoaded = true;
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SMAA::updateUniforms()
|
||||
{
|
||||
auto dims = compositor->GetScreenSize();
|
||||
|
||||
pass_1_shader->Use();
|
||||
checkGlError( "pass1: using shader", __FILE__, __LINE__ );
|
||||
pass_1_shader->SetParameter( pass_1_metrics, 1.f / float( dims.x ), 1.f / float( dims.y ),
|
||||
float( dims.x ), float( dims.y ) );
|
||||
checkGlError( "pass1: setting metrics uniform", __FILE__, __LINE__ );
|
||||
pass_1_shader->Deactivate();
|
||||
checkGlError( "pass1: deactivating shader", __FILE__, __LINE__ );
|
||||
|
||||
pass_2_shader->Use();
|
||||
checkGlError( "pass2: using shader", __FILE__, __LINE__ );
|
||||
pass_2_shader->SetParameter( pass_2_metrics, 1.f / float( dims.x ), 1.f / float( dims.y ),
|
||||
float( dims.x ), float( dims.y ) );
|
||||
checkGlError( "pass2: setting metrics uniform", __FILE__, __LINE__ );
|
||||
pass_2_shader->Deactivate();
|
||||
checkGlError( "pass2: deactivating shader", __FILE__, __LINE__ );
|
||||
|
||||
pass_3_shader->Use();
|
||||
checkGlError( "pass3: using shader", __FILE__, __LINE__ );
|
||||
pass_3_shader->SetParameter( pass_3_metrics, 1.f / float( dims.x ), 1.f / float( dims.y ),
|
||||
float( dims.x ), float( dims.y ) );
|
||||
checkGlError( "pass3: setting metrics uniform", __FILE__, __LINE__ );
|
||||
pass_3_shader->Deactivate();
|
||||
checkGlError( "pass3: deactivating shader", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
|
||||
bool ANTIALIASING_SMAA::Init()
|
||||
{
|
||||
if( !shadersLoaded )
|
||||
loadShaders();
|
||||
|
||||
if( !areBuffersInitialized )
|
||||
{
|
||||
smaaBaseBuffer = compositor->CreateBuffer();
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
|
||||
smaaEdgesBuffer = compositor->CreateBuffer();
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
|
||||
smaaBlendBuffer = compositor->CreateBuffer();
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
|
||||
updateUniforms();
|
||||
areBuffersInitialized = true;
|
||||
}
|
||||
|
||||
// Nothing to initialize
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SMAA::OnLostBuffers()
|
||||
{
|
||||
areBuffersInitialized = false;
|
||||
}
|
||||
|
||||
|
||||
unsigned int ANTIALIASING_SMAA::CreateBuffer()
|
||||
{
|
||||
return compositor->CreateBuffer( compositor->GetScreenSize() );
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SMAA::DrawBuffer( GLuint buffer )
|
||||
{
|
||||
// draw to internal buffer
|
||||
compositor->DrawBuffer( buffer, smaaBaseBuffer );
|
||||
}
|
||||
|
||||
|
||||
void ANTIALIASING_SMAA::Begin()
|
||||
{
|
||||
compositor->SetBuffer( smaaBaseBuffer );
|
||||
compositor->ClearBuffer( COLOR4D::BLACK );
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
void draw_fullscreen_triangle()
|
||||
{
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glBegin( GL_TRIANGLES );
|
||||
glTexCoord2f( 0.0f, 1.0f );
|
||||
glVertex2f( -1.0f, 1.0f );
|
||||
glTexCoord2f( 0.0f, -1.0f );
|
||||
glVertex2f( -1.0f, -3.0f );
|
||||
glTexCoord2f( 2.0f, 1.0f );
|
||||
glVertex2f( 3.0f, 1.0f );
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPopMatrix();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
void ANTIALIASING_SMAA::Present()
|
||||
{
|
||||
auto sourceTexture = compositor->GetBufferTexture( smaaBaseBuffer );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
|
||||
//
|
||||
// pass 1: main-buffer -> smaaEdgesBuffer
|
||||
//
|
||||
compositor->SetBuffer( smaaEdgesBuffer );
|
||||
compositor->ClearBuffer( COLOR4D::BLACK );
|
||||
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
glBindTexture( GL_TEXTURE_2D, sourceTexture );
|
||||
checkGlError( "binding colorTex", __FILE__, __LINE__ );
|
||||
pass_1_shader->Use();
|
||||
checkGlError( "using smaa pass 1 shader", __FILE__, __LINE__ );
|
||||
draw_fullscreen_triangle();
|
||||
pass_1_shader->Deactivate();
|
||||
|
||||
//
|
||||
// pass 2: smaaEdgesBuffer -> smaaBlendBuffer
|
||||
//
|
||||
compositor->SetBuffer( smaaBlendBuffer );
|
||||
compositor->ClearBuffer( COLOR4D::BLACK );
|
||||
|
||||
auto edgesTex = compositor->GetBufferTexture( smaaEdgesBuffer );
|
||||
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
glBindTexture( GL_TEXTURE_2D, edgesTex );
|
||||
glActiveTexture( GL_TEXTURE1 );
|
||||
glBindTexture( GL_TEXTURE_2D, smaaAreaTex );
|
||||
glActiveTexture( GL_TEXTURE3 );
|
||||
glBindTexture( GL_TEXTURE_2D, smaaSearchTex );
|
||||
|
||||
pass_2_shader->Use();
|
||||
draw_fullscreen_triangle();
|
||||
pass_2_shader->Deactivate();
|
||||
|
||||
//
|
||||
// pass 3: colorTex + BlendBuffer -> output
|
||||
//
|
||||
compositor->SetBuffer( WEBGL_COMPOSITOR::DIRECT_RENDERING );
|
||||
compositor->ClearBuffer( COLOR4D::BLACK );
|
||||
auto blendTex = compositor->GetBufferTexture( smaaBlendBuffer );
|
||||
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
glBindTexture( GL_TEXTURE_2D, sourceTexture );
|
||||
glActiveTexture( GL_TEXTURE1 );
|
||||
glBindTexture( GL_TEXTURE_2D, blendTex );
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE );
|
||||
|
||||
pass_3_shader->Use();
|
||||
draw_fullscreen_triangle();
|
||||
pass_3_shader->Deactivate();
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
}
|
||||
143
tests/gal-regression/wasm/webgl/webgl_antialiasing.h
Normal file
143
tests/gal-regression/wasm/webgl/webgl_antialiasing.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef OPENGL_ANTIALIASING_H__
|
||||
#define OPENGL_ANTIALIASING_H__
|
||||
|
||||
#include <memory>
|
||||
#include "shader.h"
|
||||
#include <math/vector2d.h>
|
||||
|
||||
namespace KIGFX {
|
||||
|
||||
class WEBGL_COMPOSITOR;
|
||||
|
||||
class OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
virtual ~OPENGL_PRESENTOR()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Init() = 0;
|
||||
virtual unsigned int CreateBuffer() = 0;
|
||||
|
||||
virtual VECTOR2I GetInternalBufferSize() = 0;
|
||||
virtual void OnLostBuffers() = 0;
|
||||
|
||||
virtual void Begin() = 0;
|
||||
virtual void DrawBuffer( GLuint aBuffer ) = 0;
|
||||
virtual void Present() = 0;
|
||||
};
|
||||
|
||||
|
||||
class ANTIALIASING_NONE : public OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
ANTIALIASING_NONE( WEBGL_COMPOSITOR* aCompositor );
|
||||
|
||||
bool Init() override;
|
||||
unsigned int CreateBuffer() override;
|
||||
|
||||
VECTOR2I GetInternalBufferSize() override;
|
||||
void OnLostBuffers() override;
|
||||
|
||||
void Begin() override;
|
||||
void DrawBuffer( GLuint aBuffer ) override;
|
||||
void Present() override;
|
||||
|
||||
private:
|
||||
WEBGL_COMPOSITOR* compositor;
|
||||
};
|
||||
|
||||
|
||||
class ANTIALIASING_SUPERSAMPLING : public OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
ANTIALIASING_SUPERSAMPLING( WEBGL_COMPOSITOR* aCompositor );
|
||||
|
||||
bool Init() override;
|
||||
unsigned int CreateBuffer() override;
|
||||
|
||||
VECTOR2I GetInternalBufferSize() override;
|
||||
void OnLostBuffers() override;
|
||||
|
||||
void Begin() override;
|
||||
void DrawBuffer( GLuint ) override;
|
||||
void Present() override;
|
||||
|
||||
private:
|
||||
WEBGL_COMPOSITOR* compositor;
|
||||
|
||||
unsigned int ssaaMainBuffer;
|
||||
bool areBuffersCreated;
|
||||
|
||||
bool areShadersCreated;
|
||||
};
|
||||
|
||||
class ANTIALIASING_SMAA : public OPENGL_PRESENTOR
|
||||
{
|
||||
public:
|
||||
ANTIALIASING_SMAA( WEBGL_COMPOSITOR* aCompositor );
|
||||
|
||||
bool Init() override;
|
||||
unsigned int CreateBuffer () override;
|
||||
|
||||
VECTOR2I GetInternalBufferSize() override;
|
||||
void OnLostBuffers() override;
|
||||
|
||||
void Begin() override;
|
||||
void DrawBuffer( GLuint buffer ) override;
|
||||
void Present() override;
|
||||
|
||||
private:
|
||||
void loadShaders();
|
||||
void updateUniforms();
|
||||
|
||||
bool areBuffersInitialized;
|
||||
|
||||
unsigned int smaaBaseBuffer; // base + overlay temporary
|
||||
unsigned int smaaEdgesBuffer;
|
||||
unsigned int smaaBlendBuffer;
|
||||
|
||||
// smaa shader lookup textures
|
||||
unsigned int smaaAreaTex;
|
||||
unsigned int smaaSearchTex;
|
||||
|
||||
bool shadersLoaded;
|
||||
|
||||
std::unique_ptr<SHADER> pass_1_shader;
|
||||
GLint pass_1_metrics;
|
||||
|
||||
std::unique_ptr<SHADER> pass_2_shader;
|
||||
GLint pass_2_metrics;
|
||||
|
||||
std::unique_ptr<SHADER> pass_3_shader;
|
||||
GLint pass_3_metrics;
|
||||
|
||||
WEBGL_COMPOSITOR* compositor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
421
tests/gal-regression/wasm/webgl/webgl_compositor.cpp
Normal file
421
tests/gal-regression/wasm/webgl/webgl_compositor.cpp
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2017 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opengl_compositor.cpp
|
||||
* @brief Class that handles multitarget rendering (i.e. to different textures/surfaces) and
|
||||
* later compositing into a single image (OpenGL flavour).
|
||||
*/
|
||||
|
||||
#include "webgl_compositor.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <gal/color4d.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <wx/log.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
WEBGL_COMPOSITOR::WEBGL_COMPOSITOR() :
|
||||
m_initialized( false ),
|
||||
m_curBuffer( 0 ),
|
||||
m_mainFbo( 0 ),
|
||||
m_depthBuffer( 0 ),
|
||||
m_curFbo( DIRECT_RENDERING ),
|
||||
m_currentAntialiasingMode( GAL_ANTIALIASING_MODE::AA_NONE )
|
||||
{
|
||||
m_antialiasing = std::make_unique<ANTIALIASING_NONE>( this );
|
||||
}
|
||||
|
||||
|
||||
WEBGL_COMPOSITOR::~WEBGL_COMPOSITOR()
|
||||
{
|
||||
if( m_initialized )
|
||||
{
|
||||
try
|
||||
{
|
||||
clean();
|
||||
}
|
||||
catch( const std::runtime_error& exc )
|
||||
{
|
||||
wxLogError( wxT( "Run time exception `%s` occurred in WEBGL_COMPOSITOR destructor." ),
|
||||
exc.what() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::SetAntialiasingMode( GAL_ANTIALIASING_MODE aMode )
|
||||
{
|
||||
m_currentAntialiasingMode = aMode;
|
||||
|
||||
if( m_initialized )
|
||||
clean();
|
||||
}
|
||||
|
||||
|
||||
GAL_ANTIALIASING_MODE WEBGL_COMPOSITOR::GetAntialiasingMode() const
|
||||
{
|
||||
return m_currentAntialiasingMode;
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::Initialize()
|
||||
{
|
||||
if( m_initialized )
|
||||
return;
|
||||
|
||||
switch( m_currentAntialiasingMode )
|
||||
{
|
||||
case GAL_ANTIALIASING_MODE::AA_FAST:
|
||||
m_antialiasing = std::make_unique<ANTIALIASING_SMAA>( this );
|
||||
break;
|
||||
case GAL_ANTIALIASING_MODE::AA_HIGHQUALITY:
|
||||
m_antialiasing = std::make_unique<ANTIALIASING_SUPERSAMPLING>( this );
|
||||
break;
|
||||
default:
|
||||
m_antialiasing = std::make_unique<ANTIALIASING_NONE>( this );
|
||||
break;
|
||||
}
|
||||
|
||||
VECTOR2I dims = m_antialiasing->GetInternalBufferSize();
|
||||
assert( dims.x != 0 && dims.y != 0 );
|
||||
|
||||
GLint maxBufSize;
|
||||
glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxBufSize );
|
||||
|
||||
if( dims.x < 0 || dims.y < 0 || dims.x > maxBufSize || dims.y >= maxBufSize )
|
||||
throw std::runtime_error( "Requested render buffer size is not supported" );
|
||||
|
||||
// We need framebuffer objects for drawing the screen contents
|
||||
// Generate framebuffer and a depth buffer
|
||||
glGenFramebuffersEXT( 1, &m_mainFbo );
|
||||
checkGlError( "generating framebuffer", __FILE__, __LINE__ );
|
||||
bindFb( m_mainFbo );
|
||||
|
||||
// Allocate memory for the depth buffer
|
||||
// Attach the depth buffer to the framebuffer
|
||||
glGenRenderbuffersEXT( 1, &m_depthBuffer );
|
||||
checkGlError( "generating renderbuffer", __FILE__, __LINE__ );
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||
checkGlError( "binding renderbuffer", __FILE__, __LINE__ );
|
||||
|
||||
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, dims.x, dims.y );
|
||||
checkGlError( "creating renderbuffer storage", __FILE__, __LINE__ );
|
||||
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||
checkGlError( "attaching renderbuffer", __FILE__, __LINE__ );
|
||||
|
||||
// Unbind the framebuffer, so by default all the rendering goes directly to the display
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
m_initialized = true;
|
||||
|
||||
m_antialiasing->Init();
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
|
||||
{
|
||||
if( m_initialized )
|
||||
clean();
|
||||
|
||||
m_antialiasing->OnLostBuffers();
|
||||
|
||||
m_width = aWidth;
|
||||
m_height = aHeight;
|
||||
}
|
||||
|
||||
|
||||
unsigned int WEBGL_COMPOSITOR::CreateBuffer()
|
||||
{
|
||||
return m_antialiasing->CreateBuffer();
|
||||
}
|
||||
|
||||
|
||||
unsigned int WEBGL_COMPOSITOR::CreateBuffer( VECTOR2I aDimensions )
|
||||
{
|
||||
assert( m_initialized );
|
||||
|
||||
int maxBuffers, maxTextureSize;
|
||||
|
||||
// Get the maximum number of buffers
|
||||
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
|
||||
|
||||
if( (int) usedBuffers() >= maxBuffers )
|
||||
{
|
||||
throw std::runtime_error( "Cannot create more framebuffers. OpenGL rendering backend requires at "
|
||||
"least 3 framebuffers. You may try to update/change your graphic drivers." );
|
||||
}
|
||||
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*) &maxTextureSize );
|
||||
|
||||
if( maxTextureSize < (int) aDimensions.x || maxTextureSize < (int) aDimensions.y )
|
||||
{
|
||||
throw std::runtime_error( "Requested texture size is not supported. Could not create a buffer." );
|
||||
}
|
||||
|
||||
// GL_COLOR_ATTACHMENTn are consecutive integers
|
||||
GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers();
|
||||
GLuint textureTarget;
|
||||
|
||||
// Generate the texture for the pixel storage
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
glGenTextures( 1, &textureTarget );
|
||||
checkGlError( "generating framebuffer texture target", __FILE__, __LINE__ );
|
||||
glBindTexture( GL_TEXTURE_2D, textureTarget );
|
||||
checkGlError( "binding framebuffer texture target", __FILE__, __LINE__ );
|
||||
|
||||
// Set texture parameters
|
||||
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, aDimensions.x, aDimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
|
||||
checkGlError( "creating framebuffer texture", __FILE__, __LINE__ );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
|
||||
// Bind the texture to the specific attachment point, clear and rebind the screen
|
||||
bindFb( m_mainFbo );
|
||||
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 );
|
||||
|
||||
// Check the status, exit if the framebuffer can't be created
|
||||
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
|
||||
|
||||
if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
|
||||
{
|
||||
switch( status )
|
||||
{
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
throw std::runtime_error( "The framebuffer attachment points are incomplete." );
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
throw std::runtime_error( "No images attached to the framebuffer." );
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
throw std::runtime_error( "The framebuffer does not have at least one image attached to it." );
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
throw std::runtime_error( "The framebuffer read buffer is incomplete." );
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
throw std::runtime_error( "The combination of internal formats of the attached images violates "
|
||||
"an implementation-dependent set of restrictions." );
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
|
||||
throw std::runtime_error( "GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers" );
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT:
|
||||
throw std::runtime_error( "Framebuffer incomplete layer targets errors." );
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
throw std::runtime_error( "Framebuffer attachments have different dimensions" );
|
||||
|
||||
default:
|
||||
throw std::runtime_error( "Unknown error occurred when creating the framebuffer." );
|
||||
}
|
||||
}
|
||||
|
||||
ClearBuffer( COLOR4D::BLACK );
|
||||
|
||||
// Return to direct rendering (we were asked only to create a buffer, not switch to one)
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
// Store the new buffer
|
||||
OPENGL_BUFFER buffer = { aDimensions, textureTarget, attachmentPoint };
|
||||
m_buffers.push_back( buffer );
|
||||
|
||||
return usedBuffers();
|
||||
}
|
||||
|
||||
|
||||
GLenum WEBGL_COMPOSITOR::GetBufferTexture( unsigned int aBufferHandle )
|
||||
{
|
||||
wxCHECK( aBufferHandle > 0 && aBufferHandle <= usedBuffers(), 0 );
|
||||
return m_buffers[aBufferHandle - 1].textureTarget;
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
|
||||
{
|
||||
wxCHECK( m_initialized && aBufferHandle <= usedBuffers(), /* void */ );
|
||||
|
||||
// Either unbind the FBO for direct rendering, or bind the one with target textures
|
||||
bindFb( aBufferHandle == DIRECT_RENDERING ? DIRECT_RENDERING : m_mainFbo );
|
||||
|
||||
// Switch the target texture
|
||||
if( m_curFbo != DIRECT_RENDERING )
|
||||
{
|
||||
m_curBuffer = aBufferHandle - 1;
|
||||
glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint );
|
||||
checkGlError( "setting draw buffer", __FILE__, __LINE__ );
|
||||
|
||||
glViewport( 0, 0, m_buffers[m_curBuffer].dimensions.x, m_buffers[m_curBuffer].dimensions.y );
|
||||
}
|
||||
else
|
||||
{
|
||||
glViewport( 0, 0, GetScreenSize().x, GetScreenSize().y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::ClearBuffer( const COLOR4D& aColor )
|
||||
{
|
||||
wxCHECK( m_initialized, /* void */ );
|
||||
|
||||
glClearColor( aColor.r, aColor.g, aColor.b, m_curFbo == DIRECT_RENDERING ? 1.0f : 0.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I WEBGL_COMPOSITOR::GetScreenSize() const
|
||||
{
|
||||
typedef VECTOR2I::coord_type coord_t;
|
||||
wxASSERT( m_width <= static_cast<unsigned int>( std::numeric_limits<coord_t>::max() ) );
|
||||
wxASSERT( m_height <= static_cast<unsigned int>( std::numeric_limits<coord_t>::max() ) );
|
||||
|
||||
return { static_cast<coord_t>( m_width ), static_cast<coord_t>( m_height ) };
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::Begin()
|
||||
{
|
||||
m_antialiasing->Begin();
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
|
||||
{
|
||||
m_antialiasing->DrawBuffer( aBufferHandle );
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle )
|
||||
{
|
||||
wxCHECK( m_initialized && aSourceHandle != 0 && aSourceHandle <= usedBuffers(), /* void */ );
|
||||
wxCHECK( aDestHandle <= usedBuffers(), /* void */ );
|
||||
|
||||
// Switch to the destination buffer and blit the scene
|
||||
SetBuffer( aDestHandle );
|
||||
|
||||
// Depth test has to be disabled to make transparency working
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// Enable texturing and bind the main texture
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glBindTexture( GL_TEXTURE_2D, m_buffers[aSourceHandle - 1].textureTarget );
|
||||
|
||||
// Draw a full screen quad with the texture
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glBegin( GL_TRIANGLES );
|
||||
glTexCoord2f( 0.0f, 1.0f );
|
||||
glVertex2f( -1.0f, 1.0f );
|
||||
glTexCoord2f( 0.0f, 0.0f );
|
||||
glVertex2f( -1.0f, -1.0f );
|
||||
glTexCoord2f( 1.0f, 1.0f );
|
||||
glVertex2f( 1.0f, 1.0f );
|
||||
|
||||
glTexCoord2f( 1.0f, 1.0f );
|
||||
glVertex2f( 1.0f, 1.0f );
|
||||
glTexCoord2f( 0.0f, 0.0f );
|
||||
glVertex2f( -1.0f, -1.0f );
|
||||
glTexCoord2f( 1.0f, 0.0f );
|
||||
glVertex2f( 1.0f, -1.0f );
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::Present()
|
||||
{
|
||||
m_antialiasing->Present();
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::bindFb( unsigned int aFb )
|
||||
{
|
||||
// Currently there are only 2 valid FBOs
|
||||
wxASSERT( aFb == DIRECT_RENDERING || aFb == m_mainFbo );
|
||||
|
||||
if( m_curFbo != aFb )
|
||||
{
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER, aFb );
|
||||
checkGlError( "switching framebuffer", __FILE__, __LINE__ );
|
||||
m_curFbo = aFb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WEBGL_COMPOSITOR::clean()
|
||||
{
|
||||
wxCHECK( m_initialized, /* void */ );
|
||||
|
||||
bindFb( DIRECT_RENDERING );
|
||||
|
||||
for( const OPENGL_BUFFER& buffer : m_buffers )
|
||||
glDeleteTextures( 1, &buffer.textureTarget );
|
||||
|
||||
m_buffers.clear();
|
||||
|
||||
if( glDeleteFramebuffersEXT )
|
||||
glDeleteFramebuffersEXT( 1, &m_mainFbo );
|
||||
|
||||
if( glDeleteRenderbuffersEXT )
|
||||
glDeleteRenderbuffersEXT( 1, &m_depthBuffer );
|
||||
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
|
||||
int WEBGL_COMPOSITOR::GetAntialiasSupersamplingFactor() const
|
||||
{
|
||||
switch ( m_currentAntialiasingMode )
|
||||
{
|
||||
case GAL_ANTIALIASING_MODE::AA_HIGHQUALITY: return 2;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
VECTOR2D WEBGL_COMPOSITOR::GetAntialiasRenderingOffset() const
|
||||
{
|
||||
switch( m_currentAntialiasingMode )
|
||||
{
|
||||
case GAL_ANTIALIASING_MODE::AA_HIGHQUALITY: return VECTOR2D( 0.5, -0.5 );
|
||||
default: return VECTOR2D( 0, 0 );
|
||||
}
|
||||
}
|
||||
139
tests/gal-regression/wasm/webgl/webgl_compositor.h
Normal file
139
tests/gal-regression/wasm/webgl/webgl_compositor.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opengl_compositor.h
|
||||
* Handle multitarget rendering (ie. to different textures/surfaces) and later compositing
|
||||
* into a single image (OpenGL flavor).
|
||||
*/
|
||||
|
||||
#ifndef WEBGL_COMPOSITOR_H_
|
||||
#define WEBGL_COMPOSITOR_H_
|
||||
|
||||
#include "kiglew.h" // Must be included first
|
||||
|
||||
#include <gal/compositor.h>
|
||||
#include "webgl_antialiasing.h"
|
||||
#include <gal/gal_display_options.h>
|
||||
#include <deque>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
|
||||
class WEBGL_COMPOSITOR : public COMPOSITOR
|
||||
{
|
||||
public:
|
||||
WEBGL_COMPOSITOR();
|
||||
virtual ~WEBGL_COMPOSITOR();
|
||||
|
||||
/// @copydoc COMPOSITOR::Initialize()
|
||||
virtual void Initialize() override;
|
||||
|
||||
/// @copydoc COMPOSITOR::Resize()
|
||||
virtual void Resize( unsigned int aWidth, unsigned int aHeight ) override;
|
||||
|
||||
/// @copydoc COMPOSITOR::CreateBuffer()
|
||||
virtual unsigned int CreateBuffer() override;
|
||||
|
||||
/// @copydoc COMPOSITOR::SetBuffer()
|
||||
virtual void SetBuffer( unsigned int aBufferHandle ) override;
|
||||
|
||||
/// @copydoc COMPOSITOR::GetBuffer()
|
||||
inline virtual unsigned int GetBuffer() const override
|
||||
{
|
||||
if( m_curFbo == DIRECT_RENDERING )
|
||||
return DIRECT_RENDERING;
|
||||
|
||||
return m_curBuffer + 1;
|
||||
}
|
||||
|
||||
/// @copydoc COMPOSITOR::ClearBuffer()
|
||||
virtual void ClearBuffer( const COLOR4D& aColor ) override;
|
||||
|
||||
/// @copydoc COMPOSITOR::DrawBuffer()
|
||||
virtual void DrawBuffer( unsigned int aBufferHandle ) override;
|
||||
|
||||
/// @copydoc COMPOSITOR::Begin()
|
||||
virtual void Begin() override;
|
||||
|
||||
// @copydoc COMPOSITOR::Present()
|
||||
virtual void Present() override;
|
||||
|
||||
// Constant used by glBindFramebuffer to turn off rendering to framebuffers
|
||||
static const unsigned int DIRECT_RENDERING = 0;
|
||||
|
||||
VECTOR2I GetScreenSize() const;
|
||||
GLenum GetBufferTexture( unsigned int aBufferHandle );
|
||||
void DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle );
|
||||
unsigned int CreateBuffer( VECTOR2I aDimensions );
|
||||
|
||||
void SetAntialiasingMode( GAL_ANTIALIASING_MODE aMode ); // clears all buffers
|
||||
GAL_ANTIALIASING_MODE GetAntialiasingMode() const;
|
||||
|
||||
int GetAntialiasSupersamplingFactor() const;
|
||||
VECTOR2D GetAntialiasRenderingOffset() const;
|
||||
|
||||
protected:
|
||||
/// Binds a specific Framebuffer Object.
|
||||
void bindFb( unsigned int aFb );
|
||||
|
||||
/**
|
||||
* Perform freeing of resources.
|
||||
*/
|
||||
void clean();
|
||||
|
||||
/// Returns number of used buffers
|
||||
inline unsigned int usedBuffers()
|
||||
{
|
||||
return m_buffers.size();
|
||||
}
|
||||
|
||||
// Buffers are simply textures storing a result of certain target rendering.
|
||||
struct OPENGL_BUFFER
|
||||
{
|
||||
VECTOR2I dimensions;
|
||||
GLuint textureTarget; ///< Main texture handle
|
||||
GLuint attachmentPoint; ///< Point to which an image from texture is attached
|
||||
};
|
||||
|
||||
bool m_initialized; ///< Initialization status flag
|
||||
unsigned int m_curBuffer; ///< Currently used buffer handle
|
||||
GLuint m_mainFbo; ///< Main FBO handle (storing all target textures)
|
||||
GLuint m_depthBuffer; ///< Depth buffer handle
|
||||
typedef std::deque<OPENGL_BUFFER> OPENGL_BUFFERS;
|
||||
|
||||
/// Stores information about initialized buffers
|
||||
OPENGL_BUFFERS m_buffers;
|
||||
|
||||
/// Store the used FBO name in case there was more than one compositor used
|
||||
GLuint m_curFbo;
|
||||
|
||||
GAL_ANTIALIASING_MODE m_currentAntialiasingMode;
|
||||
std::unique_ptr<OPENGL_PRESENTOR> m_antialiasing;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* COMPOSITOR_H_ */
|
||||
3098
tests/gal-regression/wasm/webgl/webgl_gal.cpp
Normal file
3098
tests/gal-regression/wasm/webgl/webgl_gal.cpp
Normal file
File diff suppressed because it is too large
Load diff
614
tests/gal-regression/wasm/webgl/webgl_gal.h
Normal file
614
tests/gal-regression/wasm/webgl/webgl_gal.h
Normal file
|
|
@ -0,0 +1,614 @@
|
|||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2013-2017 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* Graphics Abstraction Layer (GAL) for OpenGL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef OPENGLGAL_H_
|
||||
#define OPENGLGAL_H_
|
||||
|
||||
// GAL imports
|
||||
#include <gal/gal.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <gal/gal_display_options.h>
|
||||
#include "shader.h"
|
||||
#include "vertex_manager.h"
|
||||
#include "vertex_item.h"
|
||||
#include "cached_container.h"
|
||||
#include "noncached_container.h"
|
||||
#include "webgl_compositor.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <wx/event.h>
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
///< The default number of points for circle approximation
|
||||
#define SEG_PER_CIRCLE_COUNT 64
|
||||
|
||||
struct bitmap_glyph;
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class SHADER;
|
||||
class GL_BITMAP_CACHE;
|
||||
|
||||
|
||||
/**
|
||||
* OpenGL implementation of the Graphics Abstraction Layer.
|
||||
*
|
||||
* This is a direct OpenGL-implementation and uses low-level graphics primitives like triangles
|
||||
* and quads. The purpose is to provide a fast graphics interface, that takes advantage of modern
|
||||
* graphics card GPUs. All methods here benefit thus from the hardware acceleration.
|
||||
*/
|
||||
class GAL_API WEBGL_GAL : public GAL, public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param aParent is the wxWidgets immediate wxWindow parent of this object.
|
||||
*
|
||||
* @param aMouseListener is the wxEvtHandler that should receive the mouse events,
|
||||
* this can be can be any wxWindow, but is often a wxFrame container.
|
||||
*
|
||||
* @param aPaintListener is the wxEvtHandler that should receive the paint
|
||||
* event. This can be any wxWindow, but is often a derived instance
|
||||
* of this class or a containing wxFrame. The "paint event" here is
|
||||
* a wxCommandEvent holding EVT_GAL_REDRAW, as sent by PostPaint().
|
||||
*
|
||||
* @param aName is the name of this window for use by wxWindow::FindWindowByName()
|
||||
*/
|
||||
WEBGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIONS& aDisplayOptions,
|
||||
wxWindow* aParent,
|
||||
wxEvtHandler* aMouseListener = nullptr, wxEvtHandler* aPaintListener = nullptr,
|
||||
const wxString& aName = wxT( "GLCanvas" ) );
|
||||
|
||||
~WEBGL_GAL();
|
||||
|
||||
/**
|
||||
* Checks OpenGL features.
|
||||
*
|
||||
* @param aOptions
|
||||
* @return wxEmptyString if OpenGL 2.1 or greater is available, otherwise returns error message
|
||||
*/
|
||||
static wxString CheckFeatures( GAL_DISPLAY_OPTIONS& aOptions );
|
||||
|
||||
bool IsOpenGlEngine() override { return true; }
|
||||
|
||||
/// @copydoc GAL::IsInitialized()
|
||||
bool IsInitialized() const override
|
||||
{
|
||||
// is*Initialized flags, but it is enough for OpenGL to show up
|
||||
return IsShownOnScreen() && !GetClientRect().IsEmpty();
|
||||
}
|
||||
|
||||
///< @copydoc GAL::IsVisible()
|
||||
bool IsVisible() const override
|
||||
{
|
||||
return IsShownOnScreen() && !GetClientRect().IsEmpty();
|
||||
}
|
||||
|
||||
void SetMinLineWidth( float aLineWidth ) override;
|
||||
|
||||
// ---------------
|
||||
// Drawing methods
|
||||
// ---------------
|
||||
|
||||
/// @copydoc GAL::DrawLine()
|
||||
void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
||||
|
||||
/// @copydoc GAL::DrawSegment()
|
||||
void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||
double aWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawSegmentChain()
|
||||
void DrawSegmentChain( const std::vector<VECTOR2D>& aPointList, double aWidth ) override;
|
||||
void DrawSegmentChain( const SHAPE_LINE_CHAIN& aLineChain, double aWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawCircle()
|
||||
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
|
||||
|
||||
/// @copydoc GAL::DrawHoleWall()
|
||||
void DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
|
||||
double aWallWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawArc()
|
||||
void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aAngle ) override;
|
||||
|
||||
/// @copydoc GAL::DrawArcSegment()
|
||||
void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aAngle, double aWidth, double aMaxError ) override;
|
||||
|
||||
/// @copydoc GAL::DrawRectangle()
|
||||
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
||||
|
||||
/// @copydoc GAL::DrawPolyline()
|
||||
void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override;
|
||||
void DrawPolyline( const std::vector<VECTOR2D>& aPointList ) override;
|
||||
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override;
|
||||
void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override;
|
||||
|
||||
/// @copydoc GAL::DrawPolylines()
|
||||
void DrawPolylines( const std::vector<std::vector<VECTOR2D>>& aPointLists ) override;
|
||||
|
||||
/// @copydoc GAL::DrawPolygon()
|
||||
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override;
|
||||
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override;
|
||||
void DrawPolygon( const SHAPE_POLY_SET& aPolySet, bool aStrokeTriangulation = false ) override;
|
||||
void DrawPolygon( const SHAPE_LINE_CHAIN& aPolySet ) override;
|
||||
|
||||
/// @copydoc GAL::DrawGlyph()
|
||||
virtual void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal ) override;
|
||||
|
||||
/// @copydoc GAL::DrawGlyphs()
|
||||
virtual void DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>& aGlyphs ) override;
|
||||
|
||||
/// @copydoc GAL::DrawCurve()
|
||||
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
||||
double aFilterValue = 0.0 ) override;
|
||||
|
||||
/// @copydoc GAL::DrawBitmap()
|
||||
void DrawBitmap( const BITMAP_BASE& aBitmap, double alphaBlend = 1.0 ) override;
|
||||
|
||||
/// @copydoc GAL::BitmapText()
|
||||
void BitmapText( const wxString& aText, const VECTOR2I& aPosition,
|
||||
const EDA_ANGLE& aAngle ) override;
|
||||
|
||||
/// @copydoc GAL::DrawGrid()
|
||||
void DrawGrid() override;
|
||||
|
||||
// --------------
|
||||
// Screen methods
|
||||
// --------------
|
||||
|
||||
/// @brief Resizes the canvas.
|
||||
void ResizeScreen( int aWidth, int aHeight ) override;
|
||||
|
||||
/// @brief Shows/hides the GAL canvas
|
||||
bool Show( bool aShow ) override;
|
||||
|
||||
/// @copydoc GAL::GetSwapInterval()
|
||||
int GetSwapInterval() const override { return m_swapInterval; };
|
||||
|
||||
/// @copydoc GAL::Flush()
|
||||
void Flush() override;
|
||||
|
||||
/// @copydoc GAL::ClearScreen()
|
||||
void ClearScreen( ) override;
|
||||
|
||||
// --------------
|
||||
// Transformation
|
||||
// --------------
|
||||
|
||||
/// @copydoc GAL::Transform()
|
||||
void Transform( const MATRIX3x3D& aTransformation ) override;
|
||||
|
||||
/// @copydoc GAL::Rotate()
|
||||
void Rotate( double aAngle ) override;
|
||||
|
||||
/// @copydoc GAL::Translate()
|
||||
void Translate( const VECTOR2D& aTranslation ) override;
|
||||
|
||||
/// @copydoc GAL::Scale()
|
||||
void Scale( const VECTOR2D& aScale ) override;
|
||||
|
||||
/// @copydoc GAL::Save()
|
||||
void Save() override;
|
||||
|
||||
/// @copydoc GAL::Restore()
|
||||
void Restore() override;
|
||||
|
||||
// --------------------------------------------
|
||||
// Group methods
|
||||
// ---------------------------------------------
|
||||
|
||||
/// @copydoc GAL::BeginGroup()
|
||||
int BeginGroup() override;
|
||||
|
||||
/// @copydoc GAL::EndGroup()
|
||||
void EndGroup() override;
|
||||
|
||||
/// @copydoc GAL::DrawGroup()
|
||||
void DrawGroup( int aGroupNumber ) override;
|
||||
|
||||
/// @copydoc GAL::ChangeGroupColor()
|
||||
void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor ) override;
|
||||
|
||||
/// @copydoc GAL::ChangeGroupDepth()
|
||||
void ChangeGroupDepth( int aGroupNumber, int aDepth ) override;
|
||||
|
||||
/// @copydoc GAL::DeleteGroup()
|
||||
void DeleteGroup( int aGroupNumber ) override;
|
||||
|
||||
/// @copydoc GAL::ClearCache()
|
||||
void ClearCache() override;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Handling the world <-> screen transformation
|
||||
// --------------------------------------------------------
|
||||
|
||||
/// @copydoc GAL::SetTarget()
|
||||
void SetTarget( RENDER_TARGET aTarget ) override;
|
||||
|
||||
/// @copydoc GAL::GetTarget()
|
||||
RENDER_TARGET GetTarget() const override;
|
||||
|
||||
/// @copydoc GAL::ClearTarget()
|
||||
void ClearTarget( RENDER_TARGET aTarget ) override;
|
||||
|
||||
/// @copydoc GAL::HasTarget()
|
||||
virtual bool HasTarget( RENDER_TARGET aTarget ) override;
|
||||
|
||||
/// @copydoc GAL::SetNegativeDrawMode()
|
||||
void SetNegativeDrawMode( bool aSetting ) override {}
|
||||
|
||||
/// @copydoc GAL::StartDiffLayer()
|
||||
void StartDiffLayer() override;
|
||||
//
|
||||
/// @copydoc GAL::EndDiffLayer()
|
||||
void EndDiffLayer() override;
|
||||
|
||||
void ComputeWorldScreenMatrix() override;
|
||||
|
||||
// -------
|
||||
// Cursor
|
||||
// -------
|
||||
|
||||
/// @copydoc GAL::SetNativeCursorStyle()
|
||||
bool SetNativeCursorStyle( KICURSOR aCursor, bool aHiDPI ) override;
|
||||
|
||||
/// @copydoc GAL::DrawCursor()
|
||||
void DrawCursor( const VECTOR2D& aCursorPosition ) override;
|
||||
|
||||
/**
|
||||
* Post an event to #m_paint_listener.
|
||||
*
|
||||
* A post is used so that the actual drawing function can use a device context type that
|
||||
* is not specific to the wxEVT_PAINT event, just by changing the PostPaint code.
|
||||
*/
|
||||
void PostPaint( wxPaintEvent& aEvent );
|
||||
|
||||
void SetMouseListener( wxEvtHandler* aMouseListener )
|
||||
{
|
||||
m_mouseListener = aMouseListener;
|
||||
}
|
||||
|
||||
void SetPaintListener( wxEvtHandler* aPaintListener )
|
||||
{
|
||||
m_paintListener = aPaintListener;
|
||||
}
|
||||
|
||||
void EnableDepthTest( bool aEnabled = false ) override;
|
||||
|
||||
bool IsContextLocked() override
|
||||
{
|
||||
return m_isContextLocked;
|
||||
}
|
||||
|
||||
void LockContext( int aClientCookie ) override;
|
||||
|
||||
void UnlockContext( int aClientCookie ) override;
|
||||
|
||||
/// @copydoc GAL::BeginDrawing()
|
||||
void BeginDrawing() override;
|
||||
|
||||
/// @copydoc GAL::EndDrawing()
|
||||
void EndDrawing() override;
|
||||
|
||||
///< Parameters passed to the GLU tesselator
|
||||
struct TessParams
|
||||
{
|
||||
/// Manager used for storing new vertices
|
||||
VERTEX_MANAGER* vboManager;
|
||||
|
||||
/// Intersect points, that have to be freed after tessellation
|
||||
std::deque<std::shared_ptr<GLdouble>>& intersectPoints;
|
||||
};
|
||||
|
||||
private:
|
||||
/// Super class definition
|
||||
typedef GAL super;
|
||||
|
||||
static wxGLContext* m_glMainContext; ///< Parent OpenGL context
|
||||
wxGLContext* m_glPrivContext; ///< Canvas-specific OpenGL context
|
||||
int m_swapInterval; ///< Used to store swap interval information
|
||||
static int m_instanceCounter; ///< GL GAL instance counter
|
||||
wxEvtHandler* m_mouseListener;
|
||||
wxEvtHandler* m_paintListener;
|
||||
|
||||
static GLuint g_fontTexture; ///< Bitmap font texture handle (shared)
|
||||
|
||||
// Vertex buffer objects related fields
|
||||
typedef std::unordered_map< unsigned int, std::shared_ptr<VERTEX_ITEM> > GROUPS_MAP;
|
||||
|
||||
GROUPS_MAP m_groups; ///< Stores information about VBO objects (groups)
|
||||
unsigned int m_groupCounter; ///< Counter used for generating keys for groups
|
||||
VERTEX_MANAGER* m_currentManager; ///< Currently used VERTEX_MANAGER (for storing
|
||||
///< VERTEX_ITEMs).
|
||||
VERTEX_MANAGER* m_cachedManager; ///< Container for storing cached VERTEX_ITEMs
|
||||
VERTEX_MANAGER* m_nonCachedManager; ///< Container for storing non-cached VERTEX_ITEMs
|
||||
VERTEX_MANAGER* m_overlayManager; ///< Container for storing overlaid VERTEX_ITEMs
|
||||
|
||||
/// Container for storing temp (diff mode) VERTEX_ITEMs
|
||||
VERTEX_MANAGER* m_tempManager;
|
||||
|
||||
// Framebuffer & compositing
|
||||
WEBGL_COMPOSITOR* m_compositor; ///< Handles multiple rendering targets
|
||||
unsigned int m_mainBuffer; ///< Main rendering target
|
||||
unsigned int m_overlayBuffer; ///< Auxiliary rendering target (for menus etc.)
|
||||
unsigned int m_tempBuffer; ///< Temporary rendering target (for diffing etc.)
|
||||
RENDER_TARGET m_currentTarget; ///< Current rendering target
|
||||
|
||||
// Shader
|
||||
/// There is only one shader used for different objects.
|
||||
SHADER* m_shader;
|
||||
|
||||
// Internal flags
|
||||
bool m_isFramebufferInitialized; ///< Are the framebuffers initialized?
|
||||
static bool m_isBitmapFontLoaded; ///< Is the bitmap font texture loaded?
|
||||
bool m_isBitmapFontInitialized; ///< Is the shader set to use bitmap fonts?
|
||||
bool m_isInitialized; ///< Basic initialization flag, has to be
|
||||
///< done when the window is visible
|
||||
bool m_isGrouping; ///< Was a group started?
|
||||
bool m_isContextLocked; ///< Used for assertion checking
|
||||
int m_lockClientCookie;
|
||||
GLint ufm_worldPixelSize;
|
||||
GLint ufm_screenPixelSize;
|
||||
GLint ufm_pixelSizeMultiplier;
|
||||
GLint ufm_antialiasingOffset;
|
||||
GLint ufm_minLinePixelWidth;
|
||||
GLint ufm_fontTexture;
|
||||
GLint ufm_fontTextureWidth;
|
||||
|
||||
/// wx cursor showing the current native cursor.
|
||||
WX_CURSOR_TYPE m_currentwxCursor;
|
||||
|
||||
std::unique_ptr<GL_BITMAP_CACHE> m_bitmapCache;
|
||||
|
||||
// Polygon tesselation
|
||||
GLUtesselator* m_tesselator;
|
||||
std::deque<std::shared_ptr<GLdouble>> m_tessIntersects;
|
||||
|
||||
/// @copydoc GAL::BeginUpdate()
|
||||
void beginUpdate() override;
|
||||
|
||||
/// @copydoc GAL::EndUpdate()
|
||||
void endUpdate() override;
|
||||
|
||||
///< Update handler for OpenGL settings
|
||||
bool updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions ) override;
|
||||
|
||||
/**
|
||||
* Draw a quad for the line.
|
||||
*
|
||||
* @param aStartPoint is the start point of the line.
|
||||
* @param aEndPoint is the end point of the line.
|
||||
* @param aReserve if set to false, call reserveLineQuads beforehand
|
||||
* to reserve the right amount of vertices.
|
||||
*/
|
||||
void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||
bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Reserve specified number of line quads.
|
||||
*
|
||||
* @param aLineCount the number of line quads to reserve.
|
||||
*/
|
||||
void reserveLineQuads( const int aLineCount );
|
||||
|
||||
/**
|
||||
* Draw a semicircle.
|
||||
*
|
||||
* Depending on settings (m_isStrokeEnabled & isFilledEnabled) it runs the proper function
|
||||
* (drawStrokedSemiCircle or drawFilledSemiCircle).
|
||||
*
|
||||
* @param aCenterPoint is the center point.
|
||||
* @param aRadius is the radius of the semicircle.
|
||||
* @param aAngle is the angle of the semicircle.
|
||||
*
|
||||
*/
|
||||
void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
|
||||
|
||||
/**
|
||||
*Draw a filled semicircle.
|
||||
*
|
||||
* @param aCenterPoint is the center point.
|
||||
* @param aRadius is the radius of the semicircle.
|
||||
* @param aAngle is the angle of the semicircle.
|
||||
*
|
||||
*/
|
||||
void drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
|
||||
|
||||
/**
|
||||
* Draw a stroked semicircle.
|
||||
*
|
||||
* @param aCenterPoint is the center point.
|
||||
* @param aRadius is the radius of the semicircle.
|
||||
* @param aAngle is the angle of the semicircle.
|
||||
* @param aReserve if set to false, reserve 3 vertices for each semicircle.
|
||||
*
|
||||
*/
|
||||
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle,
|
||||
bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Internal method for circle drawing.
|
||||
*
|
||||
* @param aReserve if set to false, reserve 3 vertices for each circle.
|
||||
*/
|
||||
void drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Generic way of drawing a polyline stored in different containers.
|
||||
*
|
||||
* @param aPointGetter is a function to obtain coordinates of n-th vertex.
|
||||
* @param aPointCount is the number of points to be drawn.
|
||||
* @param aReserve if set to false, reserve aPointCount - 1 line quads.
|
||||
*/
|
||||
void drawPolyline( const std::function<VECTOR2D( int )>& aPointGetter, int aPointCount,
|
||||
bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Generic way of drawing a chain of segments stored in different containers.
|
||||
*
|
||||
* @param aPointGetter is a function to obtain coordinates of n-th vertex.
|
||||
* @param aPointCount is the number of points to be drawn.
|
||||
* @param aReserve if set to false, do not reserve vertices internally.
|
||||
*/
|
||||
void drawSegmentChain( const std::function<VECTOR2D( int )>& aPointGetter, int aPointCount,
|
||||
double aWidth, bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Internal method for segment drawing
|
||||
*/
|
||||
void drawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth,
|
||||
bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Draw a filled polygon. It does not need the last point to have the same coordinates
|
||||
* as the first one.
|
||||
*
|
||||
* @param aPoints is the vertices data (3 coordinates: x, y, z).
|
||||
* @param aPointCount is the number of points.
|
||||
*/
|
||||
void drawPolygon( GLdouble* aPoints, int aPointCount );
|
||||
|
||||
/**
|
||||
* Draw a set of polygons with a cached triangulation. Way faster than drawPolygon.
|
||||
*
|
||||
* @param aStrokeTriangulation indicates the triangulation should be stroked rather than
|
||||
* filled. Used for debugging.
|
||||
*/
|
||||
void drawTriangulatedPolyset( const SHAPE_POLY_SET& aPoly, bool aStrokeTriangulation );
|
||||
|
||||
/**
|
||||
* Draw a single character using bitmap font.
|
||||
*
|
||||
* Its main purpose is to be used in BitmapText() function.
|
||||
*
|
||||
* @param aChar is the character to be drawn.
|
||||
* @return Width of the drawn glyph.
|
||||
* @param aReserve if set to false, reserve 6 vertices for each character.
|
||||
*/
|
||||
int drawBitmapChar( unsigned long aChar, bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Draw an overbar over the currently drawn text.
|
||||
*
|
||||
* Its main purpose is to be used in BitmapText() function.
|
||||
* This method requires appropriate scaling to be applied (as is done in BitmapText() function).
|
||||
* The current X coordinate will be the overbar ending.
|
||||
*
|
||||
* @param aLength is the width of the overbar.
|
||||
* @param aHeight is the height for the overbar.
|
||||
* @param aReserve if set to false, reserve 6 vertices for each overbar.
|
||||
*/
|
||||
void drawBitmapOverbar( double aLength, double aHeight, bool aReserve = true );
|
||||
|
||||
/**
|
||||
* Compute a size of text drawn using bitmap font with current text setting applied.
|
||||
*
|
||||
* @param aText is the text to be drawn.
|
||||
* @return Pair containing text bounding box and common Y axis offset. The values are expressed
|
||||
* as a number of pixels on the bitmap font texture and need to be scaled before drawing.
|
||||
*/
|
||||
std::pair<VECTOR2D, float> computeBitmapTextSize( const UTF8& aText ) const;
|
||||
|
||||
// Event handling
|
||||
/**
|
||||
* This is the OnPaint event handler.
|
||||
*
|
||||
* @param aEvent is the OnPaint event.
|
||||
*/
|
||||
void onPaint( wxPaintEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Skip the mouse event to the parent.
|
||||
*
|
||||
* @param aEvent is the mouse event.
|
||||
*/
|
||||
void skipMouseEvent( wxMouseEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Skip the gesture event to the parent.
|
||||
*
|
||||
* @param aEvent is the gesture event.
|
||||
*/
|
||||
void skipGestureEvent( wxGestureEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Give the correct cursor image when the native widget asks for it.
|
||||
*
|
||||
* @param aEvent is the cursor event to plac the cursor into.
|
||||
*/
|
||||
void onSetNativeCursor( wxSetCursorEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Blit cursor into the current screen.
|
||||
*/
|
||||
void blitCursor();
|
||||
|
||||
/**
|
||||
* Return a valid key that can be used as a new group number.
|
||||
*
|
||||
* @return An unique group number that is not used by any other group.
|
||||
*/
|
||||
unsigned int getNewGroupNumber();
|
||||
|
||||
/**
|
||||
* Compute the angle step when drawing arcs/circles approximated with lines.
|
||||
*/
|
||||
double calcAngleStep( double aRadius ) const
|
||||
{
|
||||
// Bigger arcs need smaller alpha increment to make them look smooth
|
||||
return std::min( 1e6 / aRadius, 2.0 * M_PI / SEG_PER_CIRCLE_COUNT );
|
||||
}
|
||||
|
||||
double getWorldPixelSize() const;
|
||||
|
||||
VECTOR2D getScreenPixelSize() const;
|
||||
|
||||
/**
|
||||
* Set up the shader parameters for OpenGL rendering.
|
||||
* This method initializes all the uniform parameter locations
|
||||
* after the shader has been linked.
|
||||
*/
|
||||
void setupShaderParameters();
|
||||
|
||||
/**
|
||||
* Basic OpenGL initialization and feature checks.
|
||||
*
|
||||
* @throw std::runtime_error if any of the OpenGL feature checks failed
|
||||
*/
|
||||
void init();
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif // OPENGLGAL_H_
|
||||
Loading…
Reference in a new issue