Re-re-land sksl fragment processor support

This reverts commit 5ce3972055.

Bug: skia:
Change-Id: I88260c90004610a1cf8ad1a87c2b4b222525bbb6
Reviewed-on: https://skia-review.googlesource.com/21108
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2017-06-29 10:03:38 -04:00 committed by Skia Commit-Bot
parent e78c8ed9cb
commit 762466e9fe
58 changed files with 3413 additions and 1110 deletions

View File

@ -41,6 +41,7 @@ declare_args() {
skia_enable_tools = is_skia_dev_build
skia_enable_vulkan_debug_layers = is_skia_dev_build && is_debug
skia_vulkan_sdk = getenv("VULKAN_SDK")
skia_compile_processors = false
skia_jumper_clang = ""
skia_jumper_objdump = ""
@ -349,6 +350,9 @@ template("optional") {
optional("effects") {
enabled = skia_enable_effects
deps = [
":compile_processors",
]
sources =
skia_effects_sources + [ "src/ports/SkGlobalInitialization_default.cpp" ]
sources_when_disabled = [ "src/ports/SkGlobalInitialization_none.cpp" ]
@ -414,12 +418,70 @@ optional("fontmgr_fuchsia") {
]
}
if (skia_compile_processors) {
executable("skslc") {
defines = [ "SKSL_STANDALONE" ]
sources = [
"src/sksl/SkSLMain.cpp",
]
sources += skia_sksl_sources
include_dirs = [
"src/gpu",
"src/sksl",
]
deps = [
"//third_party/spirv-tools",
]
}
skia_gpu_processor_outputs = []
foreach(src, skia_gpu_processor_sources) {
dir = get_path_info(src, "dir")
name = get_path_info(src, "name")
# GN insists its outputs should go somewhere underneath target_out_dir, so we trick it with a
# path that starts with target_out_dir and then uses ".." to back up into the src dir.
skia_gpu_processor_outputs += [
"$target_out_dir/" + rebase_path("$dir/$name.h", target_out_dir),
# the script also modifies the corresponding .cpp file, but if we tell GN that it gets
# confused due to the same file being named by two different paths
]
}
action("compile_processors") {
script = "gn/compile_processors.py"
deps = [
":skslc(//gn/toolchain:$host_toolchain)",
]
sources = skia_gpu_processor_sources
outputs = skia_gpu_processor_outputs
skslc_path = "$root_out_dir/"
if (host_toolchain != default_toolchain_name) {
skslc_path += "$host_toolchain/"
}
skslc_path += "skslc"
if (host_os == "win") {
skslc_path += ".exe"
}
args = [ rebase_path(skslc_path) ]
args += rebase_path(skia_gpu_processor_sources)
}
} else {
skia_gpu_processor_outputs = []
group("compile_processors") {
}
}
optional("gpu") {
enabled = skia_enable_gpu
deps = [
":compile_processors",
]
public_defines = []
sources = skia_gpu_sources + skia_sksl_sources +
[ "src/gpu/gl/GrGLDefaultInterface_native.cpp" ]
[ "src/gpu/gl/GrGLDefaultInterface_native.cpp" ] +
skia_gpu_processor_outputs
# These paths need to be absolute to match the ones produced by shared_sources.gni.
sources -= get_path_info([
@ -463,9 +525,7 @@ optional("gpu") {
}
}
if (skia_enable_spirv_validation) {
deps = [
"//third_party/spirv-tools",
]
deps += [ "//third_party/spirv-tools" ]
public_defines += [ "SK_ENABLE_SPIRV_VALIDATION" ]
}
}
@ -1534,17 +1594,6 @@ if (skia_enable_tools) {
]
}
}
if (skia_enable_gpu) {
test_app("skslc") {
defines = [ "SKSL_STANDALONE" ]
sources = [
"src/sksl/SkSLMain.cpp",
]
sources += skia_sksl_sources
include_dirs = [ "src/sksl" ]
}
}
}
if (skia_jumper_clang != "") {

View File

@ -4,48 +4,14 @@
# found in the LICENSE file.
declare_args() {
ar = "ar"
cc = "cc"
cxx = "c++"
if (is_android) {
if (host_os == "win") {
ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar.exe"
cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang.exe"
cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++.exe"
} else {
ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar"
cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang"
cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++"
}
}
msvc = 2015
extra_asmflags = []
extra_cflags = []
extra_cflags_c = []
extra_cflags_cc = []
extra_ldflags = []
cc_wrapper = ""
malloc = ""
}
declare_args() {
if (msvc == 2015) {
windk = "C:/Program Files (x86)/Microsoft Visual Studio 14.0"
} else {
windk = "C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional"
}
}
if (host_os == "win") {
python = "python.bat"
stamp = "cmd.exe /c echo >"
} else {
python = "python"
stamp = "touch"
}
is_clang = is_android || is_ios || is_mac || (cc == "clang" && cxx == "clang++")
if (!is_clang && !is_win) {
@ -473,247 +439,3 @@ config("executable") {
]
}
}
toolchain("msvc") {
lib_dir_switch = "/LIBPATH:"
if (msvc == 2015) {
bin = "$windk/VC/bin/amd64"
env_setup = ""
if (target_cpu == "x86") {
bin += "_x86"
env_setup = "cmd /c $windk/win_sdk/bin/SetEnv.cmd /x86 && "
}
} else {
bin = "$windk/VC/Tools/MSVC/14.10.25017/bin/HostX64/$target_cpu"
env_setup = ""
if (target_cpu == "x86") {
print("Be sure to run")
print("$windk/VC/Auxiliary/Build/vcvarsall.bat amd64_x86")
print("to set up your environment before running ninja.")
}
}
tool("asm") {
_ml = "ml"
if (target_cpu == "x64") {
_ml += "64"
}
command = "$env_setup$bin/$_ml.exe /nologo /c /Fo {{output}} {{source}}"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
description = "assemble {{source}}"
}
tool("cc") {
rspfile = "{{output}}.rsp"
precompiled_header_type = "msvc"
pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
# Label names may have spaces so pdbname must be quoted.
command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
depsformat = "msvc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
description = "compile {{source}}"
}
tool("cxx") {
rspfile = "{{output}}.rsp"
precompiled_header_type = "msvc"
pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
# Label names may have spaces so pdbname must be quoted.
command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
depsformat = "msvc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
description = "compile {{source}}"
}
tool("alink") {
rspfile = "{{output}}.rsp"
command = "$env_setup$bin/lib.exe /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile"
outputs = [
# Ignore {{output_extension}} and always use .lib, there's no reason to
# allow targets to override this extension on Windows.
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
]
default_output_extension = ".lib"
default_output_dir = "{{target_out_dir}}"
# inputs_newline works around a fixed per-line buffer size in the linker.
rspfile_content = "{{inputs_newline}}"
description = "link {{output}}"
}
tool("solink") {
dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
libname = "${dllname}.lib"
pdbname = "${dllname}.pdb"
rspfile = "${dllname}.rsp"
command = "$env_setup$bin/link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
outputs = [
dllname,
libname,
pdbname,
]
default_output_extension = ".dll"
default_output_dir = "{{root_out_dir}}"
link_output = libname
depend_output = libname
runtime_outputs = [
dllname,
pdbname,
]
# I don't quite understand this. Aping Chrome's toolchain/win/BUILD.gn.
restat = true
# inputs_newline works around a fixed per-line buffer size in the linker.
rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
description = "link {{output}}"
}
tool("link") {
exename = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
pdbname = "$exename.pdb"
rspfile = "$exename.rsp"
command =
"$env_setup$bin/link.exe /nologo /OUT:$exename /PDB:$pdbname @$rspfile"
default_output_extension = ".exe"
default_output_dir = "{{root_out_dir}}"
outputs = [
exename,
]
# inputs_newline works around a fixed per-line buffer size in the linker.
rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
description = "link {{output}}"
}
tool("stamp") {
command = "$stamp {{output}}"
description = "stamp {{output}}"
}
tool("copy") {
cp_py = rebase_path("cp.py")
command = "$python $cp_py {{source}} {{output}}"
description = "copy {{source}} {{output}}"
}
}
toolchain("gcc_like") {
lib_switch = "-l"
lib_dir_switch = "-L"
tool("cc") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("cxx") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("objc") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("objcxx") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{cflags_objc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("asm") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "assemble {{source}}"
}
tool("alink") {
rspfile = "{{output}}.rsp"
rspfile_content = "{{inputs}}"
ar_py = rebase_path("ar.py")
command = "$python $ar_py $ar {{output}} $rspfile"
outputs = [
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
]
default_output_extension = ".a"
output_prefix = "lib"
description = "link {{output}}"
}
tool("solink") {
soname = "{{target_output_name}}{{output_extension}}"
rpath = "-Wl,-soname,$soname"
if (is_mac) {
rpath = "-Wl,-install_name,@rpath/$soname"
}
command = "$cc_wrapper $cxx -shared {{ldflags}} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
outputs = [
"{{root_out_dir}}/$soname",
]
output_prefix = "lib"
default_output_extension = ".so"
description = "link {{output}}"
}
tool("link") {
command = "$cc_wrapper $cxx {{ldflags}} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
outputs = [
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
]
description = "link {{output}}"
}
tool("stamp") {
command = "$stamp {{output}}"
description = "stamp {{output}}"
}
tool("copy") {
cp_py = rebase_path("cp.py")
command = "$python $cp_py {{source}} {{output}}"
description = "copy {{source}} {{output}}"
}
}

View File

@ -17,9 +17,21 @@ declare_args() {
ndk_api = 21
}
sanitize = ""
ar = "ar"
cc = "cc"
cxx = "c++"
msvc = 2015
}
declare_args() {
is_debug = !is_official_build
if (msvc == 2015) {
windk = "C:/Program Files (x86)/Microsoft Visual Studio 14.0"
} else {
windk = "C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional"
}
}
assert(!(is_debug && is_official_build))
@ -164,8 +176,12 @@ set_defaults("component") {
if (is_win) {
# Windows tool chain
set_default_toolchain("//gn:msvc")
set_default_toolchain("//gn/toolchain:msvc")
default_toolchain_name = "msvc"
host_toolchain = "msvc"
} else {
# GCC-like toolchains, including Clang.
set_default_toolchain("//gn:gcc_like")
set_default_toolchain("//gn/toolchain:gcc_like")
default_toolchain_name = "gcc_like"
host_toolchain = "gcc_like_host"
}

17
gn/compile_processors.py Executable file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env python
#
# Copyright 2017 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import subprocess
import sys
skslc = sys.argv[1]
processors = sys.argv[2:]
for p in processors:
path, _ = os.path.splitext(p)
subprocess.check_call([skslc, p, path + ".h"])
subprocess.check_call([skslc, p, path + ".cpp"])

View File

@ -11,11 +11,16 @@ skia_sksl_sources = [
"$_src/sksl/SkSLCompiler.cpp",
"$_src/sksl/SkSLIRGenerator.cpp",
"$_src/sksl/SkSLParser.cpp",
"$_src/sksl/SkSLCPPCodeGenerator.cpp",
"$_src/sksl/SkSLHCodeGenerator.cpp",
"$_src/sksl/SkSLGLSLCodeGenerator.cpp",
"$_src/sksl/SkSLSPIRVCodeGenerator.cpp",
"$_src/sksl/SkSLString.cpp",
"$_src/sksl/SkSLUtil.cpp",
"$_src/sksl/lex.layout.cpp",
"$_src/sksl/ir/SkSLSymbolTable.cpp",
"$_src/sksl/ir/SkSLSetting.cpp",
"$_src/sksl/ir/SkSLType.cpp",
]
skia_gpu_processor_sources = [ "$_src/gpu/effects/GrDitherEffect.fp" ]

View File

@ -216,6 +216,7 @@ tests_sources = [
"$_tests/SkResourceCacheTest.cpp",
"$_tests/SkSharedMutexTest.cpp",
"$_tests/SkSLErrorTest.cpp",
"$_tests/SkSLFPTest.cpp",
"$_tests/SkSLGLSLTest.cpp",
"$_tests/SkSLMemoryLayoutTest.cpp",
"$_tests/SkSLSPIRVTest.cpp",

301
gn/toolchain/BUILD.gn Normal file
View File

@ -0,0 +1,301 @@
declare_args() {
host_ar = ar
host_cc = cc
host_cxx = cxx
if (is_android) {
if (host_os == "win") {
target_ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar.exe"
target_cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang.exe"
target_cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++.exe"
} else {
target_ar = "$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin/ar"
target_cc = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang"
target_cxx = "$ndk/toolchains/llvm/prebuilt/$ndk_host/bin/clang++"
}
} else {
target_ar = ar
target_cc = cc
target_cxx = cxx
}
cc_wrapper = ""
}
if (host_os == "win") {
python = "python.bat"
stamp = "cmd.exe /c echo >"
} else {
python = "python"
stamp = "touch"
}
toolchain("msvc") {
lib_dir_switch = "/LIBPATH:"
if (msvc == 2015) {
bin = "$windk/VC/bin/amd64"
env_setup = ""
if (target_cpu == "x86") {
bin += "_x86"
env_setup = "cmd /c $windk/win_sdk/bin/SetEnv.cmd /x86 && "
}
} else {
bin = "$windk/VC/Tools/MSVC/14.10.25017/bin/HostX64/$target_cpu"
env_setup = ""
if (target_cpu == "x86") {
print("Be sure to run")
print("$windk/VC/Auxiliary/Build/vcvarsall.bat amd64_x86")
print("to set up your environment before running ninja.")
}
}
tool("asm") {
_ml = "ml"
if (target_cpu == "x64") {
_ml += "64"
}
command = "$env_setup$bin/$_ml.exe /nologo /c /Fo {{output}} {{source}}"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
description = "assemble {{source}}"
}
tool("cc") {
rspfile = "{{output}}.rsp"
precompiled_header_type = "msvc"
pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
# Label names may have spaces so pdbname must be quoted.
command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
depsformat = "msvc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
description = "compile {{source}}"
}
tool("cxx") {
rspfile = "{{output}}.rsp"
precompiled_header_type = "msvc"
pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
# Label names may have spaces so pdbname must be quoted.
command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
depsformat = "msvc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
description = "compile {{source}}"
}
tool("alink") {
rspfile = "{{output}}.rsp"
command = "$env_setup$bin/lib.exe /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile"
outputs = [
# Ignore {{output_extension}} and always use .lib, there's no reason to
# allow targets to override this extension on Windows.
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
]
default_output_extension = ".lib"
default_output_dir = "{{target_out_dir}}"
# inputs_newline works around a fixed per-line buffer size in the linker.
rspfile_content = "{{inputs_newline}}"
description = "link {{output}}"
}
tool("solink") {
dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
libname = "${dllname}.lib"
pdbname = "${dllname}.pdb"
rspfile = "${dllname}.rsp"
command = "$env_setup$bin/link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
outputs = [
dllname,
libname,
pdbname,
]
default_output_extension = ".dll"
default_output_dir = "{{root_out_dir}}"
link_output = libname
depend_output = libname
runtime_outputs = [
dllname,
pdbname,
]
# I don't quite understand this. Aping Chrome's toolchain/win/BUILD.gn.
restat = true
# inputs_newline works around a fixed per-line buffer size in the linker.
rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
description = "link {{output}}"
}
tool("link") {
exename = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
pdbname = "$exename.pdb"
rspfile = "$exename.rsp"
command =
"$env_setup$bin/link.exe /nologo /OUT:$exename /PDB:$pdbname @$rspfile"
default_output_extension = ".exe"
default_output_dir = "{{root_out_dir}}"
outputs = [
exename,
]
# inputs_newline works around a fixed per-line buffer size in the linker.
rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
description = "link {{output}}"
}
tool("stamp") {
command = "$stamp {{output}}"
description = "stamp {{output}}"
}
tool("copy") {
cp_py = rebase_path("../cp.py")
command = "$python $cp_py {{source}} {{output}}"
description = "copy {{source}} {{output}}"
}
}
template("gcc_like_toolchain") {
toolchain(target_name) {
ar = invoker.ar
cc = invoker.cc
cxx = invoker.cxx
lib_switch = "-l"
lib_dir_switch = "-L"
tool("cc") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("cxx") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("objc") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("objcxx") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} {{cflags_objc}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "compile {{source}}"
}
tool("asm") {
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
depsformat = "gcc"
outputs = [
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
description = "assemble {{source}}"
}
tool("alink") {
rspfile = "{{output}}.rsp"
rspfile_content = "{{inputs}}"
ar_py = rebase_path("../ar.py")
command = "$python $ar_py $ar {{output}} $rspfile"
outputs = [
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
]
default_output_extension = ".a"
output_prefix = "lib"
description = "link {{output}}"
}
tool("solink") {
soname = "{{target_output_name}}{{output_extension}}"
rpath = "-Wl,-soname,$soname"
if (is_mac) {
rpath = "-Wl,-install_name,@rpath/$soname"
}
command = "$cc_wrapper $cxx -shared {{ldflags}} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
outputs = [
"{{root_out_dir}}/$soname",
]
output_prefix = "lib"
default_output_extension = ".so"
description = "link {{output}}"
}
tool("link") {
command = "$cc_wrapper $cxx {{ldflags}} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
outputs = [
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
]
description = "link {{output}}"
}
tool("stamp") {
command = "$stamp {{output}}"
description = "stamp {{output}}"
}
tool("copy") {
cp_py = rebase_path("../cp.py")
command = "$python $cp_py {{source}} {{output}}"
description = "copy {{source}} {{output}}"
}
toolchain_args = {
current_cpu = invoker.cpu
current_os = invoker.os
}
}
}
gcc_like_toolchain("gcc_like") {
cpu = current_cpu
os = current_os
ar = target_ar
cc = target_cc
cxx = target_cxx
}
gcc_like_toolchain("gcc_like_host") {
cpu = host_cpu
os = host_os
ar = host_ar
cc = host_cc
cxx = host_cxx
}

View File

@ -1,91 +1,48 @@
/*
* Copyright 2014 Google Inc.
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This file was autogenerated from GrDitherEffect.fp; do not modify.
*/
#include "GrDitherEffect.h"
#include "GrFragmentProcessor.h"
#include "SkRect.h"
#include "glsl/GrGLSLColorSpaceXformHelper.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "../private/GrGLSL.h"
//////////////////////////////////////////////////////////////////////////////
class DitherEffect : public GrFragmentProcessor {
#include "glsl/GrGLSLProgramBuilder.h"
#include "GrResourceProvider.h"
#include "SkSLCPP.h"
#include "SkSLUtil.h"
class GrGLSLDitherEffect : public GrGLSLFragmentProcessor {
public:
static sk_sp<GrFragmentProcessor> Make() {
return sk_sp<GrFragmentProcessor>(new DitherEffect);
GrGLSLDitherEffect() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
(void) _outer;
fragBuilder->codeAppendf("float r = fract(sin(dot(sk_FragCoord.xy, vec2(12.989800000000001, 78.233000000000004))) * 43758.545299999998);\n%s = clamp(0.0039215686274509803 * vec4(r) + %s, 0.0, 1.0);\n", args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)");
}
~DitherEffect() override {}
const char* name() const override { return "Dither"; }
private:
DitherEffect() : INHERITED(kNone_OptimizationFlags) { this->initClassID<DitherEffect>(); }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
// All dither effects are equal
bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrFragmentProcessor INHERITED;
void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override {
}
};
//////////////////////////////////////////////////////////////////////////////
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
GrGLSLFragmentProcessor* GrDitherEffect::onCreateGLSLInstance() const {
return new GrGLSLDitherEffect();
}
void GrDitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
}
bool GrDitherEffect::onIsEqual(const GrFragmentProcessor& other) const {
const GrDitherEffect& that = other.cast<GrDitherEffect>();
(void) that;
return true;
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDitherEffect);
#if GR_TEST_UTILS
sk_sp<GrFragmentProcessor> DitherEffect::TestCreate(GrProcessorTestData*) {
return DitherEffect::Make();
sk_sp<GrFragmentProcessor> GrDitherEffect::TestCreate(GrProcessorTestData* testData) {
return GrDitherEffect::Make();
}
#endif
//////////////////////////////////////////////////////////////////////////////
class GLDitherEffect : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs& args) override;
private:
typedef GrGLSLFragmentProcessor INHERITED;
};
void GLDitherEffect::emitCode(EmitArgs& args) {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
// Generate a random number based on the fragment position. For this
// random number generator, we use the "GLSL rand" function
// that seems to be floating around on the internet. It works under
// the assumption that sin(<big number>) oscillates with high frequency
// and sampling it will generate "randomness". Since we're using this
// for rendering and not cryptography it should be OK.
// For each channel c, add the random offset to the pixel to either bump
// it up or let it remain constant during quantization.
fragBuilder->codeAppendf("\t\tfloat r = "
"fract(sin(dot(sk_FragCoord.xy, vec2(12.9898,78.233))) * "
"43758.5453);\n");
fragBuilder->codeAppendf("\t\t%s = clamp((1.0/255.0) * vec4(r, r, r, r) + %s, 0, 1);\n",
args.fOutputColor, args.fInputColor);
}
//////////////////////////////////////////////////////////////////////////////
void DitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
GLDitherEffect::GenKey(*this, caps, b);
}
GrGLSLFragmentProcessor* DitherEffect::onCreateGLSLInstance() const {
return new GLDitherEffect;
}
sk_sp<GrFragmentProcessor> GrDitherEffect::Make() { return DitherEffect::Make(); }

View File

@ -0,0 +1,17 @@
void main() {
// Generate a random number based on the fragment position. For this
// random number generator, we use the "GLSL rand" function
// that seems to be floating around on the internet. It works under
// the assumption that sin(<big number>) oscillates with high frequency
// and sampling it will generate "randomness". Since we're using this
// for rendering and not cryptography it should be OK.
// For each channel c, add the random offset to the pixel to either bump
// it up or let it remain constant during quantization.
float r = fract(sin(dot(sk_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453);
sk_OutColor = clamp(1.0 / 255.0 * vec4(r) + sk_InColor, 0, 1);
}
@test(testData) {
return GrDitherEffect::Make();
}

View File

@ -1,24 +1,33 @@
/*
* Copyright 2014 Google Inc.
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This file was autogenerated from GrDitherEffect.fp; do not modify.
*/
#ifndef GrDitherEffect_DEFINED
#define GrDitherEffect_DEFINED
#include "GrTypes.h"
#include "GrTypesPriv.h"
#include "SkRefCnt.h"
class GrFragmentProcessor;
namespace GrDitherEffect {
/**
* Creates an effect that dithers the resulting color to an RGBA8 framebuffer
*/
sk_sp<GrFragmentProcessor> Make();
#include "GrFragmentProcessor.h"
#include "GrCoordTransform.h"
#include "effects/GrProxyMove.h"
class GrDitherEffect : public GrFragmentProcessor {
public:
static sk_sp<GrFragmentProcessor> Make() {
return sk_sp<GrFragmentProcessor>(new GrDitherEffect());
}
const char* name() const override { return "DitherEffect"; }
private:
GrDitherEffect()
: INHERITED(kNone_OptimizationFlags) {
this->initClassID<GrDitherEffect>();
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
typedef GrFragmentProcessor INHERITED;
};
#endif

View File

@ -9,6 +9,7 @@ in GLSL "in the wild", but it does bring a few of its own changes to the table.
Skia uses the SkSL compiler to convert SkSL code to GLSL, GLSL ES, or SPIR-V
before handing it over to the graphics driver.
Differences from GLSL
=====================
@ -56,3 +57,58 @@ following differences between SkSL and GLSL:
SkSL is still under development, and is expected to diverge further from GLSL
over time.
SkSL Fragment Processors
========================
An extension of SkSL allows for the creation of fragment processors in pure
SkSL. The program defines its inputs similarly to a normal SkSL program (with
'in' and 'uniform' variables), but the 'main()' function represents only this
fragment processor's portion of the overall fragment shader.
Within an '.fp' fragment processor file:
* C++ code can be embedded in sections of the form:
@section_name { <arbitrary C++ code> }
Supported section are:
@header (in the .h file, outside the class declaration)
@class (in the .h file, inside the class declaration)
@cpp (in the .cpp file)
@constructorParams (extra parameters to the constructor, comma-separated)
@constructor (replaces the default constructor)
@initializers (constructor initializer list, comma-separated)
@emitCode (extra code for the emitCode function)
@fields (extra private fields, each terminated with a semicolon)
@make (replaces the default Make function)
@setData(<pdman>) (extra code for the setData function, where <pdman> is
the name of the GrGLSLProgramDataManager)
@test(<testData>) (the body of the TestCreate function, where <testData> is
the name of the GrProcessorTestData* parameter)
* global 'in' variables represent data passed to the fragment processor at
construction time. These variables become constructor parameters and are
stored in fragment processor fields. vec2s map to SkPoints, and vec4s map to
SkRects (in x, y, width, height) order.
* 'uniform' variables become, as one would expect, top-level uniforms. By
default they do not have any data provided to them; you will need to provide
them with data via the @setData section.
* 'in uniform' variables are uniforms that are automatically wired up to
fragment processor constructor parameters
* the 'sk_TransformedCoords2D' array provides access to 2D transformed
coordinates. sk_TransformedCoords2D[0] is equivalent to calling
fragBuilder->ensureCoords2D(args.fTransformedCoords[0]) (and the result is
cached, so you need not worry about using the value repeatedly).
* 'colorSpaceXform' is a supported type. It is reflected within SkSL as a mat4,
and on the C++ side as sk_sp<GrColorSpaceXform>.
* the texture() function can be passed a colorSpaceXform as an additional
parameter
* Uniform variables support an additional 'when' layout key.
'layout(when=foo) uniform int x;' means that this uniform will only be
emitted when the 'foo' expression is true.
* 'in' variables support an additional 'key' layout key.
'layout(key) uniform int x;' means that this uniform should be included in
the program's key. Matrix variables additionally support 'key=identity',
which causes the key to consider only whether or not the matrix is an
identity matrix.

View File

@ -231,6 +231,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
case Expression::kBoolLiteral_Kind: // fall through
case Expression::kFloatLiteral_Kind: // fall through
case Expression::kIntLiteral_Kind: // fall through
case Expression::kSetting_Kind: // fall through
case Expression::kVariableReference_Kind:
*iter = fNodes.erase(*iter);
return true;
@ -380,6 +381,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
case Expression::kBoolLiteral_Kind: // fall through
case Expression::kFloatLiteral_Kind: // fall through
case Expression::kIntLiteral_Kind: // fall through
case Expression::kSetting_Kind: // fall through
case Expression::kVariableReference_Kind:
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });

25
src/sksl/SkSLCPP.h Normal file
View File

@ -0,0 +1,25 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_CPP
#define SKSL_CPP
// functions used by CPP programs created by skslc
#include "SkPoint.h"
// macros to make sk_Caps.<cap name> work from C++ code
#define sk_Caps (*args.fShaderCaps)
#define floatPrecisionVaries floatPrecisionVaries()
// functions to make GLSL constructors work from C++ code
inline SkPoint vec2(float xy) { return SkPoint::Make(xy, xy); }
inline SkPoint vec2(float x, float y) { return SkPoint::Make(x, y); }
#endif

View File

@ -0,0 +1,598 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLCPPCodeGenerator.h"
#include "SkSLCompiler.h"
#include "SkSLHCodeGenerator.h"
namespace SkSL {
static bool needs_uniform_var(const Variable& var) {
return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
strcmp(var.fType.fName.c_str(), "colorSpaceXform");
}
CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
ErrorReporter* errors, String name, OutputStream* out)
: INHERITED(context, program, errors, out)
, fName(std::move(name))
, fFullName(String::printf("Gr%s", fName.c_str()))
, fSectionAndParameterHelper(*program, *errors) {
fLineEnding = "\\n";
}
void CPPCodeGenerator::writef(const char* s, va_list va) {
static constexpr int BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
if (length < BUFFER_SIZE) {
fOut->write(buffer, length);
} else {
std::unique_ptr<char[]> heap(new char[length + 1]);
vsprintf(heap.get(), s, va);
fOut->write(heap.get(), length);
}
}
void CPPCodeGenerator::writef(const char* s, ...) {
va_list va;
va_start(va, s);
this->writef(s, va);
va_end(va);
}
void CPPCodeGenerator::writeHeader() {
}
void CPPCodeGenerator::writePrecisionModifier() {
}
void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
if (b.fOperator == Token::PERCENT) {
// need to use "%%" instead of "%" b/c the code will be inside of a printf
Precedence precedence = GetBinaryPrecedence(b.fOperator);
if (precedence >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*b.fLeft, precedence);
this->write(" %% ");
this->writeExpression(*b.fRight, precedence);
if (precedence >= parentPrecedence) {
this->write(")");
}
} else {
INHERITED::writeBinaryExpression(b, parentPrecedence);
}
}
void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
const Expression& base = *i.fBase;
if (base.fKind == Expression::kVariableReference_Kind) {
int builtin = ((VariableReference&) base).fVariable.fModifiers.fLayout.fBuiltin;
if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
this->write("%s");
if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
fErrors.error(i.fIndex->fPosition,
"index into sk_TransformedCoords2D must be an integer literal");
return;
}
int64_t index = ((IntLiteral&) *i.fIndex).fValue;
String name = "sk_TransformedCoords2D_" + to_string(index);
fFormatArgs.push_back(name + ".c_str()");
if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
fExtraEmitCodeCode += " SkSL::String " + name +
" = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
to_string(index) + "]);\n";
fWrittenTransformedCoords.insert(index);
}
return;
} else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
this->write("%s");
if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
fErrors.error(i.fIndex->fPosition,
"index into sk_TextureSamplers must be an integer literal");
return;
}
int64_t index = ((IntLiteral&) *i.fIndex).fValue;
fFormatArgs.push_back(" fragBuilder->getProgramBuilder()->samplerVariable("
"args.fTexSamplers[" + to_string(index) + "]).c_str()");
return;
}
}
INHERITED::writeIndexExpression(i);
}
static const char* default_value(const Type& type) {
const char* name = type.name().c_str();
if (!strcmp(name, "float")) {
return "0.0";
} else if (!strcmp(name, "vec2")) {
return "vec2(0.0)";
} else if (!strcmp(name, "vec3")) {
return "vec3(0.0)";
} else if (!strcmp(name, "vec4")) {
return "vec4(0.0)";
} else if (!strcmp(name, "mat4") || !strcmp(name, "colorSpaceXform")) {
return "mat4(1.0)";
}
ABORT("unsupported default_value type\n");
}
static bool is_private(const Variable& var) {
return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
!(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
var.fStorage == Variable::kGlobal_Storage &&
var.fModifiers.fLayout.fBuiltin == -1;
}
void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
if (type == *fContext.fFloat_Type) {
this->write("%f");
fFormatArgs.push_back(cppCode);
} else if (type == *fContext.fInt_Type) {
this->write("%d");
fFormatArgs.push_back(cppCode);
} else if (type == *fContext.fBool_Type) {
this->write("%s");
fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
} else if (type == *fContext.fVec2_Type) {
this->write("vec2(%f, %f)");
fFormatArgs.push_back(cppCode + ".fX");
fFormatArgs.push_back(cppCode + ".fY");
} else {
printf("%s\n", type.name().c_str());
ABORT("unsupported runtime value type\n");
}
}
void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
if (is_private(var)) {
this->writeRuntimeValue(var.fType, var.fName);
} else {
this->writeExpression(value, kTopLevel_Precedence);
}
}
void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
case SK_INCOLOR_BUILTIN:
this->write("%s");
fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"vec4(1)\""));
break;
case SK_OUTCOLOR_BUILTIN:
this->write("%s");
fFormatArgs.push_back(String("args.fOutputColor"));
break;
default:
if (ref.fVariable.fType.kind() == Type::kSampler_Kind) {
int samplerCount = 0;
for (const auto param : fSectionAndParameterHelper.fParameters) {
if (&ref.fVariable == param) {
this->write("%s");
fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable("
"args.fTexSamplers[" + to_string(samplerCount) +
"]).c_str()");
return;
}
if (param->fType.kind() == Type::kSampler_Kind) {
++samplerCount;
}
}
ABORT("should have found sampler in parameters\n");
}
if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
this->write("%s");
String name = ref.fVariable.fName;
String var;
if (ref.fVariable.fType == *fContext.fColorSpaceXform_Type) {
ASSERT(fNeedColorSpaceHelper);
var = String::printf("fColorSpaceHelper.isValid() ? "
"args.fUniformHandler->getUniformCStr("
"fColorSpaceHelper.gamutXformUniform()) : \"%s\"",
default_value(ref.fVariable.fType));
} else {
var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
HCodeGenerator::FieldName(name.c_str()).c_str());
}
String code;
if (ref.fVariable.fModifiers.fLayout.fWhen.size()) {
code = String::printf("%sVar.isValid() ? %s : \"%s\"",
HCodeGenerator::FieldName(name.c_str()).c_str(),
var.c_str(),
default_value(ref.fVariable.fType));
} else {
code = var;
}
fFormatArgs.push_back(code);
} else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
const char* name = ref.fVariable.fName.c_str();
this->writeRuntimeValue(ref.fVariable.fType,
String::printf("_outer.%s()", name).c_str());
} else {
this->write(ref.fVariable.fName.c_str());
}
}
}
void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
if (f.fDeclaration.fName == "main") {
fFunctionHeader = "";
OutputStream* oldOut = fOut;
StringStream buffer;
fOut = &buffer;
for (const auto& s : ((Block&) *f.fBody).fStatements) {
this->writeStatement(*s);
this->writeLine();
}
fOut = oldOut;
this->write(fFunctionHeader);
this->write(buffer.str());
} else {
INHERITED::writeFunction(f);
}
}
void CPPCodeGenerator::writeSetting(const Setting& s) {
static constexpr const char* kPrefix = "sk_Args.";
if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) {
const char* name = s.fName.c_str() + strlen(kPrefix);
this->writeRuntimeValue(s.fType, HCodeGenerator::FieldName(name).c_str());
} else {
this->write(s.fName.c_str());
}
}
void CPPCodeGenerator::writeSection(const char* name, const char* prefix) {
const auto found = fSectionAndParameterHelper.fSections.find(String(name));
if (found != fSectionAndParameterHelper.fSections.end()) {
this->writef("%s%s", prefix, found->second->fText.c_str());
}
}
void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
if (p.fKind == ProgramElement::kSection_Kind) {
return;
}
if (p.fKind == ProgramElement::kVar_Kind) {
const VarDeclarations& decls = (const VarDeclarations&) p;
if (!decls.fVars.size()) {
return;
}
const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
-1 != var.fModifiers.fLayout.fBuiltin) {
return;
}
}
INHERITED::writeProgramElement(p);
}
void CPPCodeGenerator::addUniform(const Variable& var) {
if (!needs_uniform_var(var)) {
return;
}
const char* precision;
if (var.fModifiers.fFlags & Modifiers::kHighp_Flag) {
precision = "kHigh_GrSLPrecision";
} else if (var.fModifiers.fFlags & Modifiers::kMediump_Flag) {
precision = "kMedium_GrSLPrecision";
} else if (var.fModifiers.fFlags & Modifiers::kLowp_Flag) {
precision = "kLow_GrSLPrecision";
} else {
precision = "kDefault_GrSLPrecision";
}
const char* type;
if (var.fType == *fContext.fFloat_Type) {
type = "kFloat_GrSLType";
} else if (var.fType == *fContext.fVec2_Type) {
type = "kVec2f_GrSLType";
} else if (var.fType == *fContext.fVec4_Type) {
type = "kVec4f_GrSLType";
} else if (var.fType == *fContext.fMat4x4_Type ||
var.fType == *fContext.fColorSpaceXform_Type) {
type = "kMat44f_GrSLType";
} else {
ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str());
}
if (var.fModifiers.fLayout.fWhen.size()) {
this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str());
}
const char* name = var.fName.c_str();
this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
"%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name);
if (var.fModifiers.fLayout.fWhen.size()) {
this->write(" }\n");
}
}
void CPPCodeGenerator::writePrivateVars() {
for (const auto& p : fProgram.fElements) {
if (ProgramElement::kVar_Kind == p->fKind) {
const VarDeclarations* decls = (const VarDeclarations*) p.get();
for (const auto& raw : decls->fVars) {
VarDeclaration& decl = (VarDeclaration&) *raw;
if (is_private(*decl.fVar)) {
this->writef("%s %s;\n",
HCodeGenerator::FieldType(decl.fVar->fType).c_str(),
decl.fVar->fName.c_str());
}
}
}
}
}
void CPPCodeGenerator::writePrivateVarValues() {
for (const auto& p : fProgram.fElements) {
if (ProgramElement::kVar_Kind == p->fKind) {
const VarDeclarations* decls = (const VarDeclarations*) p.get();
for (const auto& raw : decls->fVars) {
VarDeclaration& decl = (VarDeclaration&) *raw;
if (is_private(*decl.fVar) && decl.fValue) {
this->writef("%s = %s;\n",
decl.fVar->fName.c_str(),
decl.fValue->description().c_str());
}
}
}
}
}
bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
this->write(" void emitCode(EmitArgs& args) override {\n"
" GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n");
this->writef(" const %s& _outer = args.fFp.cast<%s>();\n"
" (void) _outer;\n",
fFullName.c_str(), fFullName.c_str());
this->writePrivateVarValues();
for (const auto u : uniforms) {
this->addUniform(*u);
if (u->fType == *fContext.fColorSpaceXform_Type) {
if (fNeedColorSpaceHelper) {
fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported");
}
fNeedColorSpaceHelper = true;
this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, "
"_outer.%s().get());\n",
u->fName.c_str());
}
}
this->writeSection(EMIT_CODE_SECTION);
OutputStream* old = fOut;
StringStream mainBuffer;
fOut = &mainBuffer;
bool result = INHERITED::generateCode();
fOut = old;
this->writef("%s fragBuilder->codeAppendf(\"%s\"", fExtraEmitCodeCode.c_str(),
mainBuffer.str().c_str());
for (const auto& s : fFormatArgs) {
this->writef(", %s", s.c_str());
}
this->write(");\n"
" }\n");
return result;
}
void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
const char* fullName = fFullName.c_str();
auto section = fSectionAndParameterHelper.fSections.find(String(SET_DATA_SECTION));
const char* pdman = section != fSectionAndParameterHelper.fSections.end() ?
section->second->fArgument.c_str() :
"pdman";
this->writef(" void onSetData(const GrGLSLProgramDataManager& %s, "
"const GrFragmentProcessor& _proc) override {\n",
pdman);
bool wroteProcessor = false;
for (const auto u : uniforms) {
if (u->fModifiers.fFlags & Modifiers::kIn_Flag) {
if (!wroteProcessor) {
this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName);
wroteProcessor = true;
this->writef(" {\n");
}
const char* name = u->fName.c_str();
if (u->fType == *fContext.fVec4_Type) {
this->writef(" const SkRect %sValue = _outer.%s();\n"
" %s.set4fv(%sVar, 4, (float*) &%sValue);\n",
name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
} else if (u->fType == *fContext.fMat4x4_Type) {
this->writef(" float %sValue[16];\n"
" _outer.%s().asColMajorf(%sValue);\n"
" %s.setMatrix4f(%sVar, %sValue);\n",
name, name, name, pdman, HCodeGenerator::FieldName(name).c_str(),
name);
} else if (u->fType == *fContext.fColorSpaceXform_Type) {
ASSERT(fNeedColorSpaceHelper);
this->writef(" if (fColorSpaceHelper.isValid()) {\n"
" fColorSpaceHelper.setData(%s, _outer.%s().get());\n"
" }\n",
pdman, name);
} else {
this->writef(" %s.set1f(%sVar, _outer.%s());\n",
pdman, HCodeGenerator::FieldName(name).c_str(), name);
}
}
}
if (wroteProcessor) {
this->writef(" }\n");
}
if (section != fSectionAndParameterHelper.fSections.end()) {
for (const auto& p : fProgram.fElements) {
if (ProgramElement::kVar_Kind == p->fKind) {
const VarDeclarations* decls = (const VarDeclarations*) p.get();
for (const auto& raw : decls->fVars) {
VarDeclaration& decl = (VarDeclaration&) *raw;
if (needs_uniform_var(*decl.fVar)) {
const char* name = decl.fVar->fName.c_str();
this->writef(" UniformHandle& %s = %sVar;\n"
" (void) %s;\n",
name, HCodeGenerator::FieldName(name).c_str(), name);
} else if (SectionAndParameterHelper::IsParameter(*decl.fVar)) {
const char* name = decl.fVar->fName.c_str();
if (!wroteProcessor) {
this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
fullName);
wroteProcessor = true;
}
this->writef(" auto %s = _outer.%s();\n"
" (void) %s;\n",
name, name, name);
}
}
}
}
this->writeSection(SET_DATA_SECTION);
}
this->write(" }\n");
}
void CPPCodeGenerator::writeTest() {
const auto found = fSectionAndParameterHelper.fSections.find(TEST_CODE_SECTION);
if (found == fSectionAndParameterHelper.fSections.end()) {
return;
}
const Section* test = found->second;
this->writef("GR_DEFINE_FRAGMENT_PROCESSOR_TEST(%s);\n"
"#if GR_TEST_UTILS\n"
"sk_sp<GrFragmentProcessor> %s::TestCreate(GrProcessorTestData* %s) {\n",
fFullName.c_str(),
fFullName.c_str(),
test->fArgument.c_str());
this->writeSection(TEST_CODE_SECTION);
this->write("}\n"
"#endif\n");
}
void CPPCodeGenerator::writeGetKey() {
this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
"GrProcessorKeyBuilder* b) const {\n",
fFullName.c_str());
for (const auto& param : fSectionAndParameterHelper.fParameters) {
const char* name = param->fName.c_str();
if (param->fType == *fContext.fColorSpaceXform_Type) {
this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n",
HCodeGenerator::FieldName(name).c_str());
continue;
}
if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
(param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
fErrors.error(param->fPosition,
"layout(key) may not be specified on uniforms");
}
switch (param->fModifiers.fLayout.fKey) {
case Layout::kKey_Key:
if (param->fType == *fContext.fMat4x4_Type) {
ABORT("no automatic key handling for mat4\n");
} else if (param->fType == *fContext.fVec2_Type) {
this->writef(" b->add32(%s.fX);\n",
HCodeGenerator::FieldName(name).c_str());
this->writef(" b->add32(%s.fY);\n",
HCodeGenerator::FieldName(name).c_str());
} else if (param->fType == *fContext.fVec4_Type) {
this->writef(" b->add32(%s.x());\n",
HCodeGenerator::FieldName(name).c_str());
this->writef(" b->add32(%s.y());\n",
HCodeGenerator::FieldName(name).c_str());
this->writef(" b->add32(%s.width());\n",
HCodeGenerator::FieldName(name).c_str());
this->writef(" b->add32(%s.height());\n",
HCodeGenerator::FieldName(name).c_str());
} else {
this->writef(" b->add32(%s);\n",
HCodeGenerator::FieldName(name).c_str());
}
break;
case Layout::kIdentity_Key:
if (param->fType.kind() != Type::kMatrix_Kind) {
fErrors.error(param->fPosition,
"layout(key=identity) requires matrix type");
}
this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n",
HCodeGenerator::FieldName(name).c_str());
break;
case Layout::kNo_Key:
break;
}
}
this->write("}\n");
}
bool CPPCodeGenerator::generateCode() {
std::vector<const Variable*> uniforms;
for (const auto& p : fProgram.fElements) {
if (ProgramElement::kVar_Kind == p->fKind) {
const VarDeclarations* decls = (const VarDeclarations*) p.get();
for (const auto& raw : decls->fVars) {
VarDeclaration& decl = (VarDeclaration&) *raw;
if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
decl.fVar->fType.kind() != Type::kSampler_Kind) {
uniforms.push_back(decl.fVar);
}
}
}
}
const char* baseName = fName.c_str();
const char* fullName = fFullName.c_str();
this->writef(kFragmentProcessorHeader, fullName);
this->writef("#include \"%s.h\"\n"
"#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n"
"#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
"#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
"#include \"glsl/GrGLSLProgramBuilder.h\"\n"
"#include \"GrResourceProvider.h\"\n"
"#include \"SkSLCPP.h\"\n"
"#include \"SkSLUtil.h\"\n"
"class GrGLSL%s : public GrGLSLFragmentProcessor {\n"
"public:\n"
" GrGLSL%s() {}\n",
fullName, baseName, baseName);
bool result = this->writeEmitCode(uniforms);
this->write("private:\n");
this->writeSetData(uniforms);
this->writePrivateVars();
for (const auto& u : uniforms) {
const char* name = u->fName.c_str();
if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
}
}
for (const auto& param : fSectionAndParameterHelper.fParameters) {
const char* name = param->fName.c_str();
if (needs_uniform_var(*param)) {
this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
}
}
if (fNeedColorSpaceHelper) {
this->write(" GrGLSLColorSpaceXformHelper fColorSpaceHelper;\n");
}
this->writef("};\n"
"GrGLSLFragmentProcessor* %s::onCreateGLSLInstance() const {\n"
" return new GrGLSL%s();\n"
"}\n",
fullName, baseName);
this->writeGetKey();
this->writef("bool %s::onIsEqual(const GrFragmentProcessor& other) const {\n"
" const %s& that = other.cast<%s>();\n"
" (void) that;\n",
fullName, fullName, fullName);
for (const auto& param : fSectionAndParameterHelper.fParameters) {
const char* name = param->fName.c_str();
this->writef(" if (%s != that.%s) return false;\n",
HCodeGenerator::FieldName(name).c_str(),
HCodeGenerator::FieldName(name).c_str());
}
this->write(" return true;\n"
"}\n");
this->writeSection(CPP_SECTION);
this->writeTest();
result &= 0 == fErrors.errorCount();
return result;
}
} // namespace

View File

@ -0,0 +1,80 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_CPPCODEGENERATOR
#define SKSL_CPPCODEGENERATOR
#include "SkSLGLSLCodeGenerator.h"
#include "SkSLSectionAndParameterHelper.h"
#include <set>
namespace SkSL {
class CPPCodeGenerator : public GLSLCodeGenerator {
public:
CPPCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
String name, OutputStream* out);
bool generateCode() override;
private:
void writef(const char* s, va_list va) SKSL_PRINTF_LIKE(2, 0);
void writef(const char* s, ...) SKSL_PRINTF_LIKE(2, 3);
void writeSection(const char* name, const char* prefix = "");
void writeHeader() override;
void writePrecisionModifier() override;
void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) override;
void writeIndexExpression(const IndexExpression& i) override;
void writeVariableReference(const VariableReference& ref) override;
void writeFunction(const FunctionDefinition& f) override;
void writeSetting(const Setting& s) override;
void writeProgramElement(const ProgramElement& p) override;
void addUniform(const Variable& var);
// writes a printf escape that will be filled in at runtime by the given C++ expression string
void writeRuntimeValue(const Type& type, const String& cppCode);
void writeVarInitializer(const Variable& var, const Expression& value) override;
void writePrivateVars();
void writePrivateVarValues();
bool writeEmitCode(std::vector<const Variable*>& uniforms);
void writeSetData(std::vector<const Variable*>& uniforms);
void writeGetKey();
void writeTest();
String fName;
String fFullName;
SectionAndParameterHelper fSectionAndParameterHelper;
String fExtraEmitCodeCode;
std::vector<String> fFormatArgs;
std::set<int> fWrittenTransformedCoords;
bool fNeedColorSpaceHelper = false;
typedef GLSLCodeGenerator INHERITED;
};
}
#endif

View File

@ -9,6 +9,7 @@
#define SKSL_CODEGENERATOR
#include "ir/SkSLProgram.h"
#include "SkSLOutputStream.h"
namespace SkSL {

View File

@ -8,7 +8,9 @@
#include "SkSLCompiler.h"
#include "SkSLCFGGenerator.h"
#include "SkSLCPPCodeGenerator.h"
#include "SkSLGLSLCodeGenerator.h"
#include "SkSLHCodeGenerator.h"
#include "SkSLIRGenerator.h"
#include "SkSLSPIRVCodeGenerator.h"
#include "ir/SkSLExpression.h"
@ -45,6 +47,11 @@ static const char* SKSL_GEOM_INCLUDE =
#include "sksl_geom.include"
;
static const char* SKSL_FP_INCLUDE =
#include "sksl_fp.include"
;
namespace SkSL {
Compiler::Compiler()
@ -146,12 +153,18 @@ Compiler::Compiler()
ADD_TYPE(SamplerCubeArrayShadow);
ADD_TYPE(GSampler2DArrayShadow);
ADD_TYPE(GSamplerCubeArrayShadow);
ADD_TYPE(ColorSpaceXform);
String skCapsName("sk_Caps");
Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
*fContext.fSkCaps_Type, Variable::kGlobal_Storage);
fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
String skArgsName("sk_Args");
Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName,
*fContext.fSkArgs_Type, Variable::kGlobal_Storage);
fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
Modifiers::Flag ignored1;
std::vector<std::unique_ptr<ProgramElement>> ignored2;
fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
@ -778,7 +791,6 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
}
}
// returns true if this statement could potentially execute a break at the current level (we ignore
// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
static bool contains_break(Statement& s) {
@ -1097,6 +1109,9 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
case Program::kGeometry_Kind:
fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
break;
case Program::kFragmentProcessor_Kind:
fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
break;
}
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Modifiers::Flag defaultPrecision;
@ -1127,15 +1142,16 @@ bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
bool result = cg.generateCode();
if (result) {
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
ASSERT(0 == buffer.size() % 4);
const String& data = buffer.str();
ASSERT(0 == data.size() % 4);
auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
SkDebugf("SPIR-V validation error: %s\n", m);
};
tools.SetMessageConsumer(dumpmsg);
// Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior
// to the failure to see the validation errors.
ASSERT_RESULT(tools.Validate((const uint32_t*) buffer.data(), buffer.size() / 4));
out.write(buffer.data(), buffer.size());
ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
out.write(data.c_str(), data.size());
}
#else
SPIRVCodeGenerator cg(&fContext, &program, this, &out);
@ -1149,7 +1165,7 @@ bool Compiler::toSPIRV(const Program& program, String* out) {
StringStream buffer;
bool result = this->toSPIRV(program, buffer);
if (result) {
*out = String(buffer.data(), buffer.size());
*out = buffer.str();
}
return result;
}
@ -1165,11 +1181,24 @@ bool Compiler::toGLSL(const Program& program, String* out) {
StringStream buffer;
bool result = this->toGLSL(program, buffer);
if (result) {
*out = String(buffer.data(), buffer.size());
*out = buffer.str();
}
return result;
}
bool Compiler::toCPP(const Program& program, String name, OutputStream& out) {
CPPCodeGenerator cg(&fContext, &program, this, name, &out);
bool result = cg.generateCode();
this->writeErrorCount();
return result;
}
bool Compiler::toH(const Program& program, String name, OutputStream& out) {
HCodeGenerator cg(&program, this, name, &out);
bool result = cg.generateCode();
this->writeErrorCount();
return result;
}
void Compiler::error(Position position, String msg) {
fErrorCount++;

View File

@ -18,12 +18,16 @@
#include "SkSLErrorReporter.h"
#include "SkSLIRGenerator.h"
#define SK_FRAGCOLOR_BUILTIN 10001
#define SK_IN_BUILTIN 10002
#define SK_FRAGCOORD_BUILTIN 15
#define SK_VERTEXID_BUILTIN 5
#define SK_CLIPDISTANCE_BUILTIN 3
#define SK_INVOCATIONID_BUILTIN 8
#define SK_FRAGCOLOR_BUILTIN 10001
#define SK_IN_BUILTIN 10002
#define SK_INCOLOR_BUILTIN 10003
#define SK_OUTCOLOR_BUILTIN 10004
#define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005
#define SK_TEXTURESAMPLERS_BUILTIN 10006
#define SK_FRAGCOORD_BUILTIN 15
#define SK_VERTEXID_BUILTIN 5
#define SK_CLIPDISTANCE_BUILTIN 3
#define SK_INVOCATIONID_BUILTIN 8
namespace SkSL {
@ -54,6 +58,10 @@ public:
bool toGLSL(const Program& program, String* out);
bool toCPP(const Program& program, String name, OutputStream& out);
bool toH(const Program& program, String name, OutputStream& out);
void error(Position position, String msg) override;
String errorText();

View File

@ -66,8 +66,7 @@ public:
, fSamplerExternalOES_Type(new Type(String("samplerExternalOES"), SpvDim2D, false, false,
false, true))
, fSamplerCube_Type(new Type(String("samplerCube"), SpvDimCube, false, false, false, true))
, fSampler2DRect_Type(new Type(String("sampler2DRect"), SpvDimRect, false, false, false,
true))
, fSampler2DRect_Type(new Type(String("sampler2DRect"), SpvDimRect, false, false, false, true))
, fSampler1DArray_Type(new Type(String("sampler1DArray")))
, fSampler2DArray_Type(new Type(String("sampler2DArray")))
, fSamplerCubeArray_Type(new Type(String("samplerCubeArray")))
@ -151,6 +150,8 @@ public:
, fBVec_Type(new Type(String("$bvec"), { fInvalid_Type.get(), fBVec2_Type.get(),
fBVec3_Type.get(), fBVec4_Type.get() }))
, fSkCaps_Type(new Type(String("$sk_Caps")))
, fSkArgs_Type(new Type(String("$sk_Args")))
, fColorSpaceXform_Type(new Type(String("colorSpaceXform"), *fFloat_Type, 4, 4))
, fDefined_Expression(new Defined(*fInvalid_Type)) {}
static std::vector<const Type*> static_type(const Type& t) {
@ -225,7 +226,6 @@ public:
const std::unique_ptr<Type> fSampler2DArrayShadow_Type;
const std::unique_ptr<Type> fSamplerCubeArrayShadow_Type;
const std::unique_ptr<Type> fISampler2D_Type;
const std::unique_ptr<Type> fImage2D_Type;
@ -269,6 +269,8 @@ public:
const std::unique_ptr<Type> fBVec_Type;
const std::unique_ptr<Type> fSkCaps_Type;
const std::unique_ptr<Type> fSkArgs_Type;
const std::unique_ptr<Type> fColorSpaceXform_Type;
// dummy expression used to mark that a variable has a value during dataflow analysis (when it
// could have several different values, or the analyzer is otherwise unable to assign it a
@ -281,14 +283,14 @@ private:
Defined(const Type& type)
: INHERITED(Position(), kDefined_Kind, type) {}
virtual String description() const override {
return String("<defined>");
}
bool hasSideEffects() const override {
return false;
}
String description() const override {
return String("<defined>");
}
typedef Expression INHERITED;
};
};

View File

@ -34,7 +34,7 @@ void GLSLCodeGenerator::write(const char* s) {
void GLSLCodeGenerator::writeLine(const char* s) {
this->write(s);
fOut->write8('\n');
fOut->writeText(fLineEnding);
fAtLineStart = true;
}
@ -108,6 +108,9 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren
case Expression::kPostfix_Kind:
this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
break;
case Expression::kSetting_Kind:
this->writeSetting((Setting&) expr);
break;
case Expression::kSwizzle_Kind:
this->writeSwizzle((Swizzle&) expr);
break;
@ -371,7 +374,7 @@ void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
}
}
static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) {
GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) {
switch (op) {
case Token::STAR: // fall through
case Token::SLASH: // fall through
@ -413,7 +416,7 @@ static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) {
void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
Precedence precedence = get_binary_precedence(b.fOperator);
Precedence precedence = GetBinaryPrecedence(b.fOperator);
if (precedence >= parentPrecedence) {
this->write("(");
}
@ -480,6 +483,10 @@ void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
this->write(to_string(f.fValue));
}
void GLSLCodeGenerator::writeSetting(const Setting& s) {
ABORT("internal error; setting was not folded to a constant during compilation\n");
}
void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->writeType(f.fDeclaration.fReturnType);
this->write(" " + f.fDeclaration.fName + "(");
@ -517,7 +524,7 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
fOut = oldOut;
this->write(fFunctionHeader);
this->write(String(buffer.data(), buffer.size()));
this->write(buffer.str());
}
void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
@ -617,6 +624,10 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
this->writeLine(";");
}
void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
this->writeExpression(value, kTopLevel_Precedence);
}
void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
ASSERT(decl.fVars.size() > 0);
bool wroteType = false;
@ -640,7 +651,7 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool g
}
if (var.fValue) {
this->write(" = ");
this->writeExpression(*var.fValue, kTopLevel_Precedence);
this->writeVarInitializer(*var.fVar, *var.fValue);
}
if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) {
if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) {
@ -797,10 +808,7 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
this->write(";");
}
bool GLSLCodeGenerator::generateCode() {
OutputStream* rawOut = fOut;
fOut = &fHeader;
fProgramKind = fProgram.fKind;
void GLSLCodeGenerator::writeHeader() {
this->write(fProgram.fSettings.fCaps->versionDeclString());
this->writeLine();
for (const auto& e : fProgram.fElements) {
@ -808,8 +816,9 @@ bool GLSLCodeGenerator::generateCode() {
this->writeExtension((Extension&) *e);
}
}
StringStream body;
fOut = &body;
}
void GLSLCodeGenerator::writePrecisionModifier() {
if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
this->write("precision ");
switch (fProgram.fDefaultPrecision) {
@ -828,47 +837,59 @@ bool GLSLCodeGenerator::generateCode() {
}
this->writeLine(" float;");
}
for (const auto& e : fProgram.fElements) {
switch (e->fKind) {
case ProgramElement::kExtension_Kind:
break;
case ProgramElement::kVar_Kind: {
VarDeclarations& decl = (VarDeclarations&) *e;
if (decl.fVars.size() > 0) {
ASSERT(decl.fVars[0]->fKind == Statement::kVarDeclaration_Kind);
int builtin =
((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin;
if (builtin == -1) {
// normal var
this->writeVarDeclarations(decl, true);
this->writeLine();
} else if (builtin == SK_FRAGCOLOR_BUILTIN &&
fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
this->write("out ");
if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
this->write("mediump ");
}
this->writeLine("vec4 sk_FragColor;");
}
void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
switch (e.fKind) {
case ProgramElement::kExtension_Kind:
break;
case ProgramElement::kVar_Kind: {
VarDeclarations& decl = (VarDeclarations&) e;
if (decl.fVars.size() > 0) {
int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin;
if (builtin == -1) {
// normal var
this->writeVarDeclarations(decl, true);
this->writeLine();
} else if (builtin == SK_FRAGCOLOR_BUILTIN &&
fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
this->write("out ");
if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
this->write("mediump ");
}
this->writeLine("vec4 sk_FragColor;");
}
break;
}
case ProgramElement::kInterfaceBlock_Kind:
this->writeInterfaceBlock((InterfaceBlock&) *e);
break;
case ProgramElement::kFunction_Kind:
this->writeFunction((FunctionDefinition&) *e);
break;
case ProgramElement::kModifiers_Kind:
this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true);
this->writeLine(";");
break;
default:
printf("%s\n", e->description().c_str());
ABORT("unsupported program element");
break;
}
case ProgramElement::kInterfaceBlock_Kind:
this->writeInterfaceBlock((InterfaceBlock&) e);
break;
case ProgramElement::kFunction_Kind:
this->writeFunction((FunctionDefinition&) e);
break;
case ProgramElement::kModifiers_Kind:
this->writeModifiers(((ModifiersDeclaration&) e).fModifiers, true);
this->writeLine(";");
break;
default:
printf("%s\n", e.description().c_str());
ABORT("unsupported program element");
}
fOut = nullptr;
}
bool GLSLCodeGenerator::generateCode() {
OutputStream* rawOut = fOut;
fOut = &fHeader;
fProgramKind = fProgram.fKind;
this->writeHeader();
StringStream body;
fOut = &body;
this->writePrecisionModifier();
for (const auto& e : fProgram.fElements) {
this->writeProgramElement(*e);
}
fOut = rawOut;
write_stringstream(fHeader, *rawOut);
write_stringstream(body, *rawOut);

View File

@ -13,6 +13,7 @@
#include <unordered_map>
#include "SkSLCodeGenerator.h"
#include "SkSLStringStream.h"
#include "ir/SkSLBinaryExpression.h"
#include "ir/SkSLBoolLiteral.h"
#include "ir/SkSLConstructor.h"
@ -32,6 +33,7 @@
#include "ir/SkSLPostfixExpression.h"
#include "ir/SkSLProgramElement.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLSetting.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLSwizzle.h"
@ -74,11 +76,12 @@ public:
GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
, fLineEnding("\n")
, fContext(*context) {}
virtual bool generateCode() override;
bool generateCode() override;
private:
protected:
void write(const char* s);
void writeLine();
@ -89,6 +92,10 @@ private:
void writeLine(const String& s);
virtual void writeHeader();
virtual void writePrecisionModifier();
void writeType(const Type& type);
void writeExtension(const Extension& ext);
@ -99,7 +106,7 @@ private:
void writeFunctionDeclaration(const FunctionDeclaration& f);
void writeFunction(const FunctionDefinition& f);
virtual void writeFunction(const FunctionDefinition& f);
void writeLayout(const Layout& layout);
@ -107,11 +114,13 @@ private:
void writeGlobalVars(const VarDeclaration& vs);
virtual void writeVarInitializer(const Variable& var, const Expression& value);
void writeVarDeclarations(const VarDeclarations& decl, bool global);
void writeFragCoord();
void writeVariableReference(const VariableReference& ref);
virtual void writeVariableReference(const VariableReference& ref);
void writeExpression(const Expression& expr, Precedence parentPrecedence);
@ -127,11 +136,13 @@ private:
void writeSwizzle(const Swizzle& swizzle);
void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence);
static Precedence GetBinaryPrecedence(Token::Kind op);
virtual void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence);
void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence);
void writeIndexExpression(const IndexExpression& expr);
virtual void writeIndexExpression(const IndexExpression& expr);
void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence);
@ -143,6 +154,8 @@ private:
void writeFloatLiteral(const FloatLiteral& f);
virtual void writeSetting(const Setting& s);
void writeStatement(const Statement& s);
void writeStatements(const std::vector<std::unique_ptr<Statement>>& statements);
@ -161,6 +174,9 @@ private:
void writeReturnStatement(const ReturnStatement& r);
virtual void writeProgramElement(const ProgramElement& e);
const char* fLineEnding;
const Context& fContext;
StringStream fHeader;
String fFunctionHeader;

View File

@ -0,0 +1,234 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLHCodeGenerator.h"
#include "SkSLUtil.h"
#include "ir/SkSLFunctionDeclaration.h"
#include "ir/SkSLFunctionDefinition.h"
#include "ir/SkSLSection.h"
#include "ir/SkSLVarDeclarations.h"
namespace SkSL {
HCodeGenerator::HCodeGenerator(const Program* program, ErrorReporter* errors, String name,
OutputStream* out)
: INHERITED(program, errors, out)
, fName(std::move(name))
, fFullName(String::printf("Gr%s", fName.c_str()))
, fSectionAndParameterHelper(*program, *errors) {}
String HCodeGenerator::ParameterType(const Type& type) {
if (type.fName == "vec2") {
return "SkPoint";
} else if (type.fName == "ivec4") {
return "SkIRect";
} else if (type.fName == "vec4") {
return "SkRect";
} else if (type.fName == "mat4") {
return "SkMatrix44";
} else if (type.kind() == Type::kSampler_Kind) {
return "sk_sp<GrTextureProxy>";
} else if (type.fName == "colorSpaceXform") {
return "sk_sp<GrColorSpaceXform>";
}
return type.name();
}
String HCodeGenerator::FieldType(const Type& type) {
if (type.kind() == Type::kSampler_Kind) {
return "TextureSampler";
}
return ParameterType(type);
}
void HCodeGenerator::writef(const char* s, va_list va) {
static constexpr int BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
if (length < BUFFER_SIZE) {
fOut->write(buffer, length);
} else {
std::unique_ptr<char[]> heap(new char[length + 1]);
vsprintf(heap.get(), s, va);
fOut->write(heap.get(), length);
}
}
void HCodeGenerator::writef(const char* s, ...) {
va_list va;
va_start(va, s);
this->writef(s, va);
va_end(va);
}
bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
const auto found = fSectionAndParameterHelper.fSections.find(String(name));
if (found != fSectionAndParameterHelper.fSections.end()) {
this->writef("%s%s", prefix, found->second->fText.c_str());
return true;
}
return false;
}
void HCodeGenerator::writeExtraConstructorParams(const char* separator) {
// super-simple parse, just assume the last token before a comma is the name of a parameter
// (which is true as long as there are no multi-parameter template types involved). Will replace
// this with something more robust if the need arises.
const auto found = fSectionAndParameterHelper.fSections.find(
String(CONSTRUCTOR_PARAMS_SECTION));
if (found != fSectionAndParameterHelper.fSections.end()) {
const char* s = found->second->fText.c_str();
#define BUFFER_SIZE 64
char lastIdentifier[BUFFER_SIZE];
int lastIdentifierLength = 0;
bool foundBreak = false;
while (*s) {
char c = *s;
++s;
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
c == '_') {
if (foundBreak) {
lastIdentifierLength = 0;
foundBreak = false;
}
ASSERT(lastIdentifierLength < BUFFER_SIZE);
lastIdentifier[lastIdentifierLength] = c;
++lastIdentifierLength;
} else {
foundBreak = true;
if (c == ',') {
ASSERT(lastIdentifierLength < BUFFER_SIZE);
lastIdentifier[lastIdentifierLength] = 0;
this->writef("%s%s", separator, lastIdentifier);
separator = ", ";
} else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
lastIdentifierLength = 0;
}
}
}
if (lastIdentifierLength) {
ASSERT(lastIdentifierLength < BUFFER_SIZE);
lastIdentifier[lastIdentifierLength] = 0;
this->writef("%s%s", separator, lastIdentifier);
}
}
}
void HCodeGenerator::writeMake() {
const char* separator;
if (!this->writeSection(MAKE_SECTION)) {
this->writef(" static sk_sp<GrFragmentProcessor> Make(");
separator = "";
for (const auto& param : fSectionAndParameterHelper.fParameters) {
this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(),
param->fName.c_str());
separator = ", ";
}
this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
this->writef(") {\n"
" return sk_sp<GrFragmentProcessor>(new %s(",
fFullName.c_str());
separator = "";
for (const auto& param : fSectionAndParameterHelper.fParameters) {
this->writef("%s%s", separator, param->fName.c_str());
separator = ", ";
}
this->writeExtraConstructorParams(separator);
this->writef("));\n"
" }\n");
}
}
void HCodeGenerator::writeConstructor() {
if (this->writeSection(CONSTRUCTOR_SECTION)) {
return;
}
this->writef(" %s(", fFullName.c_str());
const char* separator = "";
for (const auto& param : fSectionAndParameterHelper.fParameters) {
this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(),
param->fName.c_str());
separator = ", ";
}
this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
this->writef(")\n"
" : INHERITED(");
if (!this->writeSection(OPTIMIZATION_FLAGS_SECTION, "(OptimizationFlags) ")) {
this->writef("kNone_OptimizationFlags");
}
this->writef(")");
this->writeSection(INITIALIZERS_SECTION, "\n , ");
for (const auto& param : fSectionAndParameterHelper.fParameters) {
const char* name = param->fName.c_str();
if (param->fType.kind() == Type::kSampler_Kind) {
this->writef("\n , %s(resourceProvider, std::move(%s))", FieldName(name).c_str(),
name);
} else {
this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
}
}
this->writef(" {\n");
this->writeSection(CONSTRUCTOR_CODE_SECTION);
for (const auto& param : fSectionAndParameterHelper.fParameters) {
if (param->fType.kind() == Type::kSampler_Kind) {
this->writef(" this->addTextureSampler(&%s);\n",
FieldName(param->fName.c_str()).c_str());
}
}
this->writef(" this->initClassID<%s>();\n"
" }\n",
fFullName.c_str());
}
void HCodeGenerator::writeFields() {
this->writeSection(FIELDS_SECTION);
for (const auto& param : fSectionAndParameterHelper.fParameters) {
const char* name = param->fName.c_str();
this->writef(" %s %s;\n", FieldType(param->fType).c_str(), FieldName(name).c_str());
}
}
bool HCodeGenerator::generateCode() {
this->writef(kFragmentProcessorHeader, fFullName.c_str());
this->writef("#ifndef %s_DEFINED\n"
"#define %s_DEFINED\n"
"#include \"GrFragmentProcessor.h\"\n"
"#include \"GrCoordTransform.h\"\n"
"#include \"effects/GrProxyMove.h\"\n",
fFullName.c_str(), fFullName.c_str());
this->writeSection(HEADER_SECTION);
this->writef("class %s : public GrFragmentProcessor {\n"
"public:\n",
fFullName.c_str());
this->writeSection(CLASS_SECTION);
for (const auto& param : fSectionAndParameterHelper.fParameters) {
if (param->fType.kind() == Type::kSampler_Kind) {
continue;
}
const char* name = param->fName.c_str();
this->writef("%s %s() const { return %s; }\n",
FieldType(param->fType).c_str(), name, FieldName(name).c_str());
}
this->writeMake();
this->writef(" const char* name() const override { return \"%s\"; }\n"
"private:\n",
fName.c_str());
this->writeConstructor();
this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
" void onGetGLSLProcessorKey(const GrShaderCaps&,"
"GrProcessorKeyBuilder*) const override;\n"
" bool onIsEqual(const GrFragmentProcessor&) const override;\n"
" GR_DECLARE_FRAGMENT_PROCESSOR_TEST;\n");
this->writeFields();
this->writef(" typedef GrFragmentProcessor INHERITED;\n"
"};\n"
"#endif\n");
return 0 == fErrors.errorCount();
}
} // namespace

View File

@ -0,0 +1,73 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_HCODEGENERATOR
#define SKSL_HCODEGENERATOR
#include "SkSLCodeGenerator.h"
#include "SkSLSectionAndParameterHelper.h"
#include "ir/SkSLType.h"
#include "ir/SkSLVariable.h"
#include <cctype>
constexpr const char* kFragmentProcessorHeader =
R"(/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This file was autogenerated from %s.fp; do not modify.
*/
)";
namespace SkSL {
class HCodeGenerator : public CodeGenerator {
public:
HCodeGenerator(const Program* program, ErrorReporter* errors, String name, OutputStream* out);
bool generateCode() override;
static String ParameterType(const Type& type);
static String FieldType(const Type& type);
static String FieldName(const char* varName) {
return String::printf("f%c%s", toupper(varName[0]), varName + 1);
}
private:
void writef(const char* s, va_list va) SKSL_PRINTF_LIKE(2, 0);
void writef(const char* s, ...) SKSL_PRINTF_LIKE(2, 3);
bool writeSection(const char* name, const char* prefix = "");
// given a @constructorParams section of e.g. 'int x, float y', writes out "<separator>x, y".
// Writes nothing (not even the separator) if there is no @constructorParams section.
void writeExtraConstructorParams(const char* separator);
void writeMake();
void writeConstructor();
void writeFields();
String fName;
String fFullName;
SectionAndParameterHelper fSectionAndParameterHelper;
typedef CodeGenerator INHERITED;
};
} // namespace SkSL
#endif

View File

@ -42,6 +42,7 @@
#include "ir/SkSLPostfixExpression.h"
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLSetting.h"
#include "ir/SkSLSwitchCase.h"
#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLSwizzle.h"
@ -104,9 +105,11 @@ IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> sy
ErrorReporter& errorReporter)
: fContext(*context)
, fCurrentFunction(nullptr)
, fSymbolTable(std::move(symbolTable))
, fRootSymbolTable(symbolTable)
, fSymbolTable(symbolTable)
, fLoopLevel(0)
, fSwitchLevel(0)
, fTmpCount(0)
, fErrors(errorReporter) {}
void IRGenerator::pushSymbolTable() {
@ -117,8 +120,10 @@ void IRGenerator::popSymbolTable() {
fSymbolTable = fSymbolTable->fParent;
}
static void fill_caps(const SKSL_CAPS_CLASS& caps, std::unordered_map<String, CapValue>* capsMap) {
#define CAP(name) capsMap->insert(std::make_pair(String(#name), CapValue(caps.name())));
static void fill_caps(const SKSL_CAPS_CLASS& caps,
std::unordered_map<String, Program::Settings::Value>* capsMap) {
#define CAP(name) capsMap->insert(std::make_pair(String(#name), \
Program::Settings::Value(caps.name())));
CAP(fbFetchSupport);
CAP(fbFetchNeedsCustomOutput);
CAP(bindlessTextureSupport);
@ -135,6 +140,7 @@ static void fill_caps(const SKSL_CAPS_CLASS& caps, std::unordered_map<String, Ca
CAP(mustEnableSpecificAdvBlendEqs);
CAP(mustDeclareFragmentShaderOutput);
CAP(canUseAnyFunctionInShader);
CAP(floatPrecisionVaries);
#undef CAP
}
@ -673,7 +679,12 @@ void IRGenerator::convertFunction(const ASTFunction& f,
bool needInvocationIDWorkaround = fSettings->fCaps &&
fSettings->fCaps->mustImplementGSInvocationsWithLoop() &&
fInvocations != -1 && f.fName == "main";
ASSERT(!fExtraVars.size());
std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
for (auto& v : fExtraVars) {
body->fStatements.insert(body->fStatements.begin(), std::move(v));
}
fExtraVars.clear();
fCurrentFunction = nullptr;
if (!body) {
return;
@ -845,6 +856,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
}
case Symbol::kVariable_Kind: {
const Variable* var = (const Variable*) result;
#ifndef SKSL_STANDALONE
if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
fInputs.fFlipY = true;
if (fSettings->fFlipY &&
@ -853,6 +865,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
fInputs.fRTHeight = true;
}
}
#endif
// default to kRead_RefKind; this will be corrected later if the variable is written to
return std::unique_ptr<VariableReference>(new VariableReference(
identifier.fPosition,
@ -876,9 +889,13 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
default:
ABORT("unsupported symbol type %d\n", result->fKind);
}
}
std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) {
return std::unique_ptr<Section>(new Section(s.fPosition, s.fName, s.fArgument, s.fText));
}
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
const Type& type) {
if (!expr) {
@ -904,6 +921,9 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
ASSERT(ctor);
return this->call(Position(), std::move(ctor), std::move(args));
}
if (type == *fContext.fColorSpaceXform_Type && expr->fType == *fContext.fMat4x4_Type) {
return expr;
}
std::vector<std::unique_ptr<Expression>> args;
args.push_back(std::move(expr));
return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
@ -1332,7 +1352,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
return nullptr;
}
if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
this->markWrittenTo(*arguments[i],
this->markWrittenTo(*arguments[i],
function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag);
}
}
@ -1373,6 +1393,87 @@ bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
return true;
}
std::unique_ptr<Expression> IRGenerator::applyColorSpace(std::unique_ptr<Expression> texture,
const Variable* xform) {
// Before:
// vec4 color = texture(img, coords, xform);
// After:
// vec4 tmp;
// vec4 color = (tmp = texture(img, coords) ,
// xform != mat4(1) ?
// vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) :
// tmp);
// a few macros to keep line lengths manageable
#define EXPR std::unique_ptr<Expression>
#define REF(v) EXPR(new VariableReference(p, *v))
#define FLOAT(x) EXPR(new FloatLiteral(fContext, p, x))
using std::move;
Position p = Position();
// vec4 tmp;
Variable* tmp = new Variable(p, Modifiers(), "_tmp" + to_string(fTmpCount++), texture->fType,
Variable::kLocal_Storage);
fRootSymbolTable->takeOwnership(tmp);
std::vector<std::unique_ptr<VarDeclaration>> decls;
decls.emplace_back(new VarDeclaration(tmp, std::vector<std::unique_ptr<Expression>>(),
nullptr));
const Type& type = texture->fType;
fExtraVars.emplace_back(new VarDeclarationsStatement(std::unique_ptr<VarDeclarations>(
new VarDeclarations(p, &type, move(decls)))));
// tmp = texture
EXPR assignment = EXPR(new BinaryExpression(p,
EXPR(new VariableReference(p, *tmp,
VariableReference::kWrite_RefKind)),
Token::EQ,
move(texture), type));
// 1.0
std::vector<EXPR> matArgs;
matArgs.push_back(FLOAT(1.0));
// mat4(1.0)
EXPR mat = EXPR(new Constructor(p, *fContext.fMat4x4_Type, move(matArgs)));
// <xform> != mat4(1.0)
EXPR matNeq = EXPR(new BinaryExpression(p, REF(xform), Token::NEQ, move(mat),
*fContext.fBool_Type));
// tmp.rgb
std::vector<int> rgb { 0, 1, 2 };
EXPR tmpRgb = EXPR(new Swizzle(fContext, REF(tmp), rgb));
// vec4(tmp.rgb, 1.0)
std::vector<EXPR> tmpVecArgs;
tmpVecArgs.push_back(move(tmpRgb));
tmpVecArgs.push_back(FLOAT(1.0));
EXPR tmpVec = EXPR(new Constructor(p, *fContext.fVec4_Type, move(tmpVecArgs)));
// xform * vec4(tmp.rgb, 1.0)
EXPR mul = EXPR(new BinaryExpression(p, REF(xform), Token::STAR, move(tmpVec),
*fContext.fVec4_Type));
// (xform * vec4(tmp.rgb, 1.0)).rgb
EXPR mulRGB = EXPR(new Swizzle(fContext, std::move(mul), rgb));
// tmp.a
std::vector<int> a { 3 };
EXPR tmpA = EXPR(new Swizzle(fContext, REF(tmp), a));
// clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a)
EXPR clamp = this->convertIdentifier(ASTIdentifier(p, "clamp"));
std::vector<EXPR> clampArgs;
clampArgs.push_back(move(mulRGB));
clampArgs.push_back(FLOAT(0));
clampArgs.push_back(move(tmpA));
EXPR clampCall = this->call(p, move(clamp), move(clampArgs));
// tmp.a
tmpA = EXPR(new Swizzle(fContext, REF(tmp), a));
// vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a)
std::vector<EXPR> finalVecArgs;
finalVecArgs.push_back(move(clampCall));
finalVecArgs.push_back(move(tmpA));
EXPR finalVec = EXPR(new Constructor(p, *fContext.fVec4_Type, move(finalVecArgs)));
// xform != mat4(1) ? vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) : tmp)
EXPR ternary = EXPR(new TernaryExpression(p, move(matNeq), move(finalVec), REF(tmp)));
// (tmp = texture ,
// xform != mat4(1) ? vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) : tmp))
return EXPR(new BinaryExpression(p, move(assignment), Token::COMMA, move(ternary), type));
#undef EXPR
#undef REF
#undef FLOAT
}
std::unique_ptr<Expression> IRGenerator::call(Position position,
std::unique_ptr<Expression> functionValue,
std::vector<std::unique_ptr<Expression>> arguments) {
@ -1386,6 +1487,17 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
return nullptr;
}
FunctionReference* ref = (FunctionReference*) functionValue.get();
if (ref->fFunctions[0]->fName == "texture" &&
arguments.back()->fType == *fContext.fColorSpaceXform_Type) {
std::unique_ptr<Expression> colorspace = std::move(arguments.back());
ASSERT(colorspace->fKind == Expression::kVariableReference_Kind);
arguments.pop_back();
return this->applyColorSpace(this->call(position,
std::move(functionValue),
std::move(arguments)),
&((VariableReference&) *colorspace).fVariable);
}
int bestCost = INT_MAX;
const FunctionDeclaration* best = nullptr;
if (ref->fFunctions.size() > 1) {
@ -1451,7 +1563,7 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
args[0]->fType.description() + "')");
return nullptr;
}
return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args)));
return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
}
int component_count(const Type& type) {
@ -1473,8 +1585,7 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
args[0]->fType.kind() == Type::kMatrix_Kind) {
// matrix from matrix is always legal
return std::unique_ptr<Expression>(new Constructor(position, std::move(type),
std::move(args)));
return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
}
int actual = 0;
int expected = type.rows() * type.columns();
@ -1511,7 +1622,7 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
return nullptr;
}
}
return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args)));
return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
}
std::unique_ptr<Expression> IRGenerator::convertConstructor(
@ -1534,8 +1645,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
return nullptr;
}
}
return std::unique_ptr<Expression>(new Constructor(position, std::move(type),
std::move(args)));
return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
} else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
return this->convertCompoundConstructor(position, type, std::move(args));
} else {
@ -1727,16 +1837,21 @@ std::unique_ptr<Expression> IRGenerator::getCap(Position position, String name)
fErrors.error(position, "unknown capability flag '" + name + "'");
return nullptr;
}
switch (found->second.fKind) {
case CapValue::kBool_Kind:
return std::unique_ptr<Expression>(new BoolLiteral(fContext, position,
(bool) found->second.fValue));
case CapValue::kInt_Kind:
return std::unique_ptr<Expression>(new IntLiteral(fContext, position,
found->second.fValue));
String fullName = "sk_Caps." + name;
return std::unique_ptr<Expression>(new Setting(position, fullName,
found->second.literal(fContext, position)));
}
std::unique_ptr<Expression> IRGenerator::getArg(Position position, String name) {
auto found = fSettings->fArgs.find(name);
if (found == fSettings->fArgs.end()) {
fErrors.error(position, "unknown argument '" + name + "'");
return nullptr;
}
ASSERT(false);
return nullptr;
String fullName = "sk_Args." + name;
return std::unique_ptr<Expression>(new Setting(position,
fullName,
found->second.literal(fContext, position)));
}
std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
@ -1780,6 +1895,10 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
return this->getCap(expression.fPosition,
((ASTFieldSuffix&) *expression.fSuffix).fField);
}
if (base->fType == *fContext.fSkArgs_Type) {
return this->getArg(expression.fPosition,
((ASTFieldSuffix&) *expression.fSuffix).fField);
}
switch (base->fType.kind()) {
case Type::kVector_Kind:
return this->convertSwizzle(std::move(base),
@ -1924,6 +2043,13 @@ void IRGenerator::convertProgram(String text,
}
break;
}
case ASTDeclaration::kSection_Kind: {
std::unique_ptr<Section> s = this->convertSection((ASTSection&) decl);
if (s) {
out->push_back(std::move(s));
}
break;
}
case ASTDeclaration::kPrecision_Kind: {
*defaultPrecision = ((ASTPrecision&) decl).fPrecision;
break;

View File

@ -27,6 +27,7 @@
#include "ast/SkSLASTModifiersDeclaration.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTSection.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
#include "ast/SkSLASTSwitchStatement.h"
@ -42,6 +43,7 @@
#include "ir/SkSLModifiers.h"
#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLProgram.h"
#include "ir/SkSLSection.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLType.h"
@ -50,28 +52,6 @@
namespace SkSL {
struct CapValue {
CapValue()
: fKind(kInt_Kind)
, fValue(-1) {
ASSERT(false);
}
CapValue(bool b)
: fKind(kBool_Kind)
, fValue(b) {}
CapValue(int i)
: fKind(kInt_Kind)
, fValue(i) {}
enum {
kBool_Kind,
kInt_Kind,
} fKind;
int fValue;
};
/**
* Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
* (unoptimized) intermediate representation (IR).
@ -95,6 +75,7 @@ public:
Token::Kind op,
const Expression& right) const;
Program::Inputs fInputs;
const Program::Settings* fSettings;
const Context& fContext;
private:
@ -160,7 +141,9 @@ private:
Modifiers convertModifiers(const Modifiers& m);
std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression);
std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r);
std::unique_ptr<Section> convertSection(const ASTSection& e);
std::unique_ptr<Expression> getCap(Position position, String name);
std::unique_ptr<Expression> getArg(Position position, String name);
std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
const String& field);
@ -173,16 +156,26 @@ private:
std::unique_ptr<Block> main,
std::vector<std::unique_ptr<ProgramElement>>* out);
/**
* Wraps an expression in code that applies a colorspace transformation to it. This is used
* to implement texture(sampler, coord, colorSpaceXForm).
*/
std::unique_ptr<Expression> applyColorSpace(std::unique_ptr<Expression> texture,
const Variable* xform);
void fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments);
void checkValid(const Expression& expr);
void markWrittenTo(const Expression& expr, bool readWrite);
const FunctionDeclaration* fCurrentFunction;
const Program::Settings* fSettings;
std::unordered_map<String, CapValue> fCapsMap;
std::unordered_map<String, Program::Settings::Value> fCapsMap;
std::shared_ptr<SymbolTable> fRootSymbolTable;
std::shared_ptr<SymbolTable> fSymbolTable;
// holds extra temp variable declarations needed for the current function
std::vector<std::unique_ptr<Statement>> fExtraVars;
int fLoopLevel;
int fSwitchLevel;
// count of temporary variables we have created
int fTmpCount;
ErrorReporter& fErrors;
int fInvocations;

View File

@ -5,11 +5,28 @@
* found in the LICENSE file.
*/
#include "stdio.h"
#include <fstream>
#include "SkSLCompiler.h"
#include "SkSLFileOutputStream.h"
// Given the path to a file (e.g. src/gpu/effects/GrFooFragmentProcessor.fp) and the expected
// filename prefix and suffix (e.g. "Gr" and ".fp"), returns the "base name" of the
// file (in this case, 'FooFragmentProcessor'). If no match, returns the empty string.
static SkSL::String base_name(const char* fpPath, const char* prefix, const char* suffix) {
SkSL::String result;
const char* end = fpPath + strlen(fpPath);
const char* fileName = end;
// back up until we find a slash
while (fileName != fpPath && '/' != *(fileName - 1) && '\\' != *(fileName - 1)) {
--fileName;
}
if (!strncmp(fileName, prefix, strlen(prefix)) &&
!strncmp(end - strlen(suffix), suffix, strlen(suffix))) {
result.append(fileName + strlen(prefix), end - fileName - strlen(prefix) - strlen(suffix));
}
return result;
}
/**
* Very simple standalone executable to facilitate testing.
*/
@ -19,15 +36,17 @@ int main(int argc, const char** argv) {
exit(1);
}
SkSL::Program::Kind kind;
size_t len = strlen(argv[1]);
if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".vert")) {
SkSL::String input(argv[1]);
if (input.endsWith(".vert")) {
kind = SkSL::Program::kVertex_Kind;
} else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".frag")) {
} else if (input.endsWith(".frag")) {
kind = SkSL::Program::kFragment_Kind;
} else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".geom")) {
} else if (input.endsWith(".geom")) {
kind = SkSL::Program::kGeometry_Kind;
} else if (input.endsWith(".fp")) {
kind = SkSL::Program::kFragmentProcessor_Kind;
} else {
printf("input filename must end in '.vert', '.frag', or '.geom'\n");
printf("input filename must end in '.vert', '.frag', '.geom', or '.fp'\n");
exit(1);
}
@ -40,6 +59,7 @@ int main(int argc, const char** argv) {
exit(2);
}
SkSL::Program::Settings settings;
settings.fArgs.insert(std::make_pair("gpImplementsDistanceVector", 1));
SkSL::String name(argv[2]);
if (name.endsWith(".spirv")) {
SkSL::FileOutputStream out(argv[2]);
@ -73,7 +93,41 @@ int main(int argc, const char** argv) {
printf("error writing '%s'\n", argv[2]);
exit(4);
}
} else if (name.endsWith(".h")) {
SkSL::FileOutputStream out(argv[2]);
SkSL::Compiler compiler;
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
}
settings.fReplaceSettings = false;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
if (!program || !compiler.toH(*program, base_name(argv[1], "Gr", ".fp"), out)) {
printf("%s", compiler.errorText().c_str());
exit(3);
}
if (!out.close()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
}
} else if (name.endsWith(".cpp")) {
SkSL::FileOutputStream out(argv[2]);
SkSL::Compiler compiler;
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
}
settings.fReplaceSettings = false;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
if (!program || !compiler.toCPP(*program, base_name(argv[1], "Gr", ".fp"), out)) {
printf("%s", compiler.errorText().c_str());
exit(3);
}
if (!out.close()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
}
} else {
printf("expected output filename to end with '.spirv' or '.glsl'");
printf("expected output filename to end with '.spirv', '.glsl', '.cpp', or '.h'");
}
}

View File

@ -52,6 +52,7 @@ static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 +
#include "ast/SkSLASTPrecision.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTSection.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
#include "ast/SkSLASTSwitchCase.h"
@ -108,7 +109,7 @@ Parser::~Parser() {
layoutlex_destroy(fLayoutScanner);
}
/* (precision | directive | declaration)* END_OF_FILE */
/* (precision | directive | section | declaration)* END_OF_FILE */
std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
std::vector<std::unique_ptr<ASTDeclaration>> result;
for (;;) {
@ -129,6 +130,13 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
}
break;
}
case Token::SECTION: {
std::unique_ptr<ASTDeclaration> section = this->section();
if (section) {
result.push_back(std::move(section));
}
break;
}
default: {
std::unique_ptr<ASTDeclaration> decl = this->declaration();
if (!decl) {
@ -140,7 +148,7 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
}
}
Token Parser::nextToken() {
Token Parser::nextRawToken() {
if (fPushback.fKind != Token::INVALID_TOKEN) {
Token result = fPushback;
fPushback.fKind = Token::INVALID_TOKEN;
@ -148,25 +156,16 @@ Token Parser::nextToken() {
return result;
}
int token = sksllex(fScanner);
String text;
switch ((Token::Kind) token) {
case Token::IDENTIFIER: // fall through
case Token::INT_LITERAL: // fall through
case Token::FLOAT_LITERAL: // fall through
case Token::DIRECTIVE:
text = String(skslget_text(fScanner));
break;
default:
#ifdef SK_DEBUG
text = String(skslget_text(fScanner));
#endif
break;
}
Position p = Position(skslget_lineno(fScanner), -1);
if (token == Token::INVALID_TOKEN) {
this->error(p, "invalid token: '" + text + "'");
}
return Token(p, (Token::Kind) token, text);
return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token,
String(skslget_text(fScanner)));
}
Token Parser::nextToken() {
Token token;
do {
token = this->nextRawToken();
} while (token.fKind == Token::WHITESPACE);
return token;
}
void Parser::pushback(Token t) {
@ -291,6 +290,56 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
}
}
/* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces>
RBRACE */
std::unique_ptr<ASTDeclaration> Parser::section() {
Token start;
if (!this->expect(Token::SECTION, "a section token", &start)) {
return nullptr;
}
String argument;
if (this->peek().fKind == Token::LPAREN) {
this->nextToken();
Token argToken;
if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) {
return nullptr;
}
argument = argToken.fText;
if (!this->expect(Token::RPAREN, "')'")) {
return nullptr;
}
}
if (!this->expect(Token::LBRACE, "'{'")) {
return nullptr;
}
String text;
int level = 1;
for (;;) {
Token next = this->nextRawToken();
switch (next.fKind) {
case Token::LBRACE:
++level;
break;
case Token::RBRACE:
--level;
break;
case Token::END_OF_FILE:
this->error(start.fPosition, "reached end of file while parsing section");
return nullptr;
default:
break;
}
if (!level) {
break;
}
text += next.fText;
}
return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition,
String(start.fText.c_str() + 1),
argument,
text));
}
/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
(COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
std::unique_ptr<ASTDeclaration> Parser::declaration() {
@ -539,6 +588,61 @@ int Parser::layoutInt() {
return -1;
}
/** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */
String Parser::layoutCode() {
if (!this->expect(Token::EQ, "'='")) {
return "";
}
Token start = this->peek();
String code;
int level = 1;
bool done = false;
while (!done) {
Token next = this->peek();
switch (next.fKind) {
case Token::LPAREN:
++level;
break;
case Token::RPAREN:
--level;
break;
case Token::COMMA:
if (level == 1) {
done = true;
}
break;
case Token::END_OF_FILE:
this->error(start.fPosition, "reached end of file while parsing layout");
return nullptr;
default:
break;
}
if (!level) {
done = true;
}
if (!done) {
code += this->nextRawToken().fText;
}
}
return code;
}
/** (EQ IDENTIFIER('identity'))? */
Layout::Key Parser::layoutKey() {
if (this->peek().fKind == Token::EQ) {
this->expect(Token::EQ, "'='");
Token key;
if (this->expect(Token::IDENTIFIER, "an identifer", &key)) {
if (key.fText == "identity") {
return Layout::kIdentity_Key;
} else {
this->error(key.fPosition, "unsupported layout key");
}
}
}
return Layout::kKey_Key;
}
/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
Layout Parser::layout() {
int location = -1;
@ -556,11 +660,13 @@ Layout Parser::layout() {
Layout::Primitive primitive = Layout::kUnspecified_Primitive;
int maxVertices = -1;
int invocations = -1;
String when;
Layout::Key key = Layout::kNo_Key;
if (this->checkNext(Token::LAYOUT)) {
if (!this->expect(Token::LPAREN, "'('")) {
return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
pushConstant, primitive, maxVertices, invocations);
pushConstant, primitive, maxVertices, invocations, when, key);
}
for (;;) {
Token t = this->nextToken();
@ -630,6 +736,12 @@ Layout Parser::layout() {
case Token::INVOCATIONS:
invocations = this->layoutInt();
break;
case Token::WHEN:
when = this->layoutCode();
break;
case Token::KEY:
key = this->layoutKey();
break;
}
} else if (Layout::ReadFormat(t.fText, &format)) {
// AST::ReadFormat stored the result in 'format'.
@ -647,7 +759,7 @@ Layout Parser::layout() {
}
return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
pushConstant, primitive, maxVertices, invocations);
pushConstant, primitive, maxVertices, invocations, when, key);
}
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |

View File

@ -13,6 +13,7 @@
#include <unordered_map>
#include <unordered_set>
#include "SkSLErrorReporter.h"
#include "ir/SkSLLayout.h"
#include "SkSLToken.h"
struct yy_buffer_state;
@ -42,7 +43,6 @@ struct ASTSwitchStatement;
struct ASTType;
struct ASTWhileStatement;
struct ASTVarDeclarations;
struct Layout;
struct Modifiers;
class SymbolTable;
@ -64,7 +64,12 @@ public:
private:
/**
* Return the next token from the parse stream.
* Return the next token, including whitespace tokens, from the parse stream.
*/
Token nextRawToken();
/**
* Return the next non-whitespace token from the parse stream.
*/
Token nextToken();
@ -76,7 +81,7 @@ private:
void pushback(Token t);
/**
* Returns the next token without consuming it from the stream.
* Returns the next non-whitespace token without consuming it from the stream.
*/
Token peek();
@ -87,8 +92,8 @@ private:
bool checkNext(Token::Kind kind, Token* result = nullptr);
/**
* Reads the next token and generates an error if it is not the expected type. The 'expected'
* string is part of the error message, which reads:
* Reads the next non-whitespace token and generates an error if it is not the expected type.
* The 'expected' string is part of the error message, which reads:
*
* "expected <expected>, but found '<actual text>'"
*
@ -115,6 +120,8 @@ private:
std::unique_ptr<ASTDeclaration> directive();
std::unique_ptr<ASTDeclaration> section();
std::unique_ptr<ASTDeclaration> declaration();
std::unique_ptr<ASTVarDeclarations> varDeclarations();
@ -131,6 +138,10 @@ private:
int layoutInt();
String layoutCode();
Layout::Key layoutKey();
Layout layout();
Modifiers modifiers();

View File

@ -1906,7 +1906,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
Type intfStruct(Position(), name, fields);
Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false,
Layout::Format::kUnspecified, false, Layout::kUnspecified_Primitive, -1,
-1);
-1, "", Layout::kNo_Key);
Variable* intfVar = new Variable(Position(),
Modifiers(layout, Modifiers::kUniform_Flag),
name,
@ -2948,6 +2948,8 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
case Program::kGeometry_Kind:
this->writeWord(SpvExecutionModelGeometry, out);
break;
default:
ABORT("cannot write this kind of program to SPIR-V\n");
}
this->writeWord(fFunctionMap[main], out);
this->writeString(main->fName.c_str(), out);

View File

@ -0,0 +1,111 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SECTIONANDPARAMETERHELPER
#define SKSL_SECTIONANDPARAMETERHELPER
#include "SkSLErrorReporter.h"
#include "ir/SkSLProgram.h"
#include "ir/SkSLSection.h"
#include "ir/SkSLVarDeclarations.h"
#include <unordered_map>
#include <vector>
namespace SkSL {
#define CLASS_SECTION "class"
#define CPP_SECTION "cpp"
#define HEADER_SECTION "header"
#define CONSTRUCTOR_PARAMS_SECTION "constructorParams"
#define CONSTRUCTOR_SECTION "constructor"
#define CONSTRUCTOR_CODE_SECTION "constructorCode"
#define INITIALIZERS_SECTION "initializers"
#define EMIT_CODE_SECTION "emitCode"
#define FIELDS_SECTION "fields"
#define MAKE_SECTION "make"
#define OPTIMIZATION_FLAGS_SECTION "optimizationFlags"
#define SET_DATA_SECTION "setData"
#define TEST_CODE_SECTION "test"
class SectionAndParameterHelper {
public:
SectionAndParameterHelper(const Program& program, ErrorReporter& errors) {
for (const auto& p : program.fElements) {
switch (p->fKind) {
case ProgramElement::kVar_Kind: {
const VarDeclarations* decls = (const VarDeclarations*) p.get();
for (const auto& raw : decls->fVars) {
const VarDeclaration& decl = (VarDeclaration&) *raw;
if (IsParameter(*decl.fVar)) {
fParameters.push_back(decl.fVar);
}
}
break;
}
case ProgramElement::kSection_Kind: {
const Section* s = (const Section*) p.get();
if (IsSupportedSection(s->fName.c_str())) {
if (SectionAcceptsArgument(s->fName.c_str())) {
if (!s->fArgument.size()) {
errors.error(s->fPosition,
("section '@" + s->fName +
"' requires one parameter").c_str());
}
} else if (s->fArgument.size()) {
errors.error(s->fPosition,
("section '@" + s->fName + "' has no parameters").c_str());
}
} else {
errors.error(s->fPosition,
("unsupported section '@" + s->fName + "'").c_str());
}
if (fSections.find(s->fName) != fSections.end()) {
errors.error(s->fPosition,
("duplicate section '@" + s->fName + "'").c_str());
}
fSections[s->fName] = s;
break;
}
default:
break;
}
}
}
static bool IsParameter(const Variable& var) {
return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
-1 == var.fModifiers.fLayout.fBuiltin;
}
static bool IsSupportedSection(const char* name) {
return !strcmp(name, CLASS_SECTION) ||
!strcmp(name, CPP_SECTION) ||
!strcmp(name, HEADER_SECTION) ||
!strcmp(name, CONSTRUCTOR_SECTION) ||
!strcmp(name, CONSTRUCTOR_CODE_SECTION) ||
!strcmp(name, CONSTRUCTOR_PARAMS_SECTION) ||
!strcmp(name, EMIT_CODE_SECTION) ||
!strcmp(name, FIELDS_SECTION) ||
!strcmp(name, INITIALIZERS_SECTION) ||
!strcmp(name, MAKE_SECTION) ||
!strcmp(name, OPTIMIZATION_FLAGS_SECTION) ||
!strcmp(name, SET_DATA_SECTION) ||
!strcmp(name, TEST_CODE_SECTION);
}
static bool SectionAcceptsArgument(const char* name) {
return !strcmp(name, SET_DATA_SECTION) ||
!strcmp(name, TEST_CODE_SECTION);
}
std::vector<const Variable*> fParameters;
std::unordered_map<String, const Section*> fSections;
};
} // namespace SkSL
#endif

View File

@ -40,15 +40,16 @@ void String::vappendf(const char* fmt, va_list args) {
#endif
#define BUFFER_SIZE 256
char buffer[BUFFER_SIZE];
va_list reuse;
va_copy(reuse, args);
size_t size = VSNPRINTF(buffer, BUFFER_SIZE, fmt, args);
if (BUFFER_SIZE >= size) {
this->append(buffer, size);
} else {
auto newBuffer = std::unique_ptr<char[]>(new char[size]);
VSNPRINTF(newBuffer.get(), size, fmt, args);
auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
VSNPRINTF(newBuffer.get(), size + 1, fmt, reuse);
this->append(newBuffer.get(), size);
}
va_end(args);
}

View File

@ -28,12 +28,8 @@ public:
fBuffer.append((const char*) s, size);
}
const char* data() const {
return fBuffer.c_str();
}
size_t size() const {
return fBuffer.size();
const String& str() const {
return fBuffer;
}
void reset() {
@ -54,42 +50,33 @@ namespace SkSL {
class StringStream : public OutputStream {
public:
void write8(uint8_t b) override {
SkASSERT(!fData);
fStream.write8(b);
}
void writeText(const char* s) override {
SkASSERT(!fData);
fStream.writeText(s);
}
void write(const void* s, size_t size) override {
SkASSERT(!fData);
fStream.write(s, size);
}
const char* data() const {
if (!fData) {
fData = fStream.detachAsData();
const String& str() const {
if (!fString.size()) {
sk_sp<SkData> data = fStream.detachAsData();
fString = String((const char*) data->data(), data->size());
}
return (const char*) fData->data();
}
size_t size() const {
if (!fData) {
fData = fStream.detachAsData();
}
return fData->size();
return fString;
}
void reset() {
fStream.reset();
fData = nullptr;
fString = "";
}
private:
mutable SkDynamicMemoryWStream fStream;
mutable sk_sp<SkData> fData;
mutable String fString;
};
#endif // SKSL_STANDALONE

View File

@ -24,6 +24,7 @@ namespace SkSL {
struct Token {
enum Kind {
END_OF_FILE,
WHITESPACE,
IDENTIFIER,
INT_LITERAL,
FLOAT_LITERAL,
@ -77,6 +78,8 @@ struct Token {
LOGICALXOREQ,
LOGICALANDEQ,
SEMICOLON,
ARROW,
COLONCOLON,
IF,
STATIC_IF,
ELSE,
@ -111,6 +114,7 @@ struct Token {
STRUCT,
LAYOUT,
DIRECTIVE,
SECTION,
PRECISION,
LOCATION,
OFFSET,
@ -132,6 +136,8 @@ struct Token {
TRIANGLES_ADJACENCY,
MAX_VERTICES,
INVOCATIONS,
WHEN,
KEY,
INVALID_TOKEN
};

View File

@ -27,7 +27,7 @@ void sksl_abort() {
}
void write_stringstream(const StringStream& s, OutputStream& out) {
out.write(s.data(), s.size());
out.write(s.str().c_str(), s.str().size());
}
} // namespace

View File

@ -135,6 +135,10 @@ public:
return false;
}
bool floatPrecisionVaries() const {
return false;
}
const char* shaderDerivativeExtensionString() const {
return nullptr;
}
@ -210,6 +214,7 @@ public:
result->fVersionDeclString = "#version 400";
result->fShaderDerivativeSupport = true;
result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
result->fUsesPrecisionModifiers = true;
return result;
}

View File

@ -22,7 +22,8 @@ struct ASTDeclaration : public ASTPositionNode {
kInterfaceBlock_Kind,
kExtension_Kind,
kPrecision_Kind,
kModifiers_Kind
kModifiers_Kind,
kSection_Kind
};
ASTDeclaration(Position position, Kind kind)

View File

@ -20,7 +20,7 @@ namespace SkSL {
*/
struct ASTFunction : public ASTDeclaration {
ASTFunction(Position position, Modifiers modifiers, std::unique_ptr<ASTType> returnType,
String name, std::vector<std::unique_ptr<ASTParameter>> parameters,
String name, std::vector<std::unique_ptr<ASTParameter>> parameters,
std::unique_ptr<ASTBlock> body)
: INHERITED(position, kFunction_Kind)
, fModifiers(modifiers)

View File

@ -0,0 +1,43 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTSECTION
#define SKSL_ASTSECTION
#include "SkSLASTDeclaration.h"
namespace SkSL {
/**
* A section declaration (e.g. @body { body code here })..
*/
struct ASTSection : public ASTDeclaration {
ASTSection(Position position, String name, String arg, String text)
: INHERITED(position, kSection_Kind)
, fName(std::move(name))
, fArgument(std::move(arg))
, fText(std::move(text)) {}
String description() const override {
String result = "@" + fName;
if (fArgument.size()) {
result += "(" + fArgument + ")";
}
result += " { " + fText + " }";
return result;
}
const String fName;
const String fArgument;
const String fText;
typedef ASTDeclaration INHERITED;
};
} // namespace
#endif

View File

@ -36,6 +36,7 @@ struct Expression : public IRNode {
kIndex_Kind,
kPrefix_Kind,
kPostfix_Kind,
kSetting_Kind,
kSwizzle_Kind,
kVariableReference_Kind,
kTernary_Kind,

View File

@ -71,7 +71,7 @@ struct FunctionDeclaration : public Symbol {
bool determineFinalTypes(const std::vector<std::unique_ptr<Expression>>& arguments,
std::vector<const Type*>* outParameterTypes,
const Type** outReturnType) const {
assert(arguments.size() == fParameters.size());
ASSERT(arguments.size() == fParameters.size());
int genericIndex = -1;
for (size_t i = 0; i < arguments.size(); i++) {
if (fParameters[i]->fType.kind() == Type::kGeneric_Kind) {
@ -93,7 +93,7 @@ struct FunctionDeclaration : public Symbol {
}
}
if (fReturnType.kind() == Type::kGeneric_Kind) {
assert(genericIndex != -1);
ASSERT(genericIndex != -1);
*outReturnType = fReturnType.coercibleTypes()[genericIndex];
} else {
*outReturnType = &fReturnType;

View File

@ -8,6 +8,7 @@
#ifndef SKSL_LAYOUT
#define SKSL_LAYOUT
#include "SkSLString.h"
#include "SkSLUtil.h"
namespace SkSL {
@ -42,6 +43,16 @@ struct Layout {
kR8I,
};
// used by SkSL processors
enum Key {
// field is not a key
kNo_Key,
// field is a key
kKey_Key,
// key is 0 or 1 depending on whether the matrix is an identity matrix
kIdentity_Key,
};
static const char* FormatToStr(Format format) {
switch (format) {
case Format::kUnspecified: return "";
@ -55,7 +66,6 @@ struct Layout {
case Format::kR8I: return "r8i";
}
ABORT("Unexpected format");
return "";
}
static bool ReadFormat(String str, Format* format) {
@ -90,7 +100,7 @@ struct Layout {
Layout(int location, int offset, int binding, int index, int set, int builtin,
int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage,
bool blendSupportAllEquations, Format format, bool pushconstant, Primitive primitive,
int maxVertices, int invocations)
int maxVertices, int invocations, String when, Key key)
: fLocation(location)
, fOffset(offset)
, fBinding(binding)
@ -105,7 +115,9 @@ struct Layout {
, fPushConstant(pushconstant)
, fPrimitive(primitive)
, fMaxVertices(maxVertices)
, fInvocations(invocations) {}
, fInvocations(invocations)
, fWhen(when)
, fKey(key) {}
Layout()
: fLocation(-1)
@ -122,7 +134,8 @@ struct Layout {
, fPushConstant(false)
, fPrimitive(kUnspecified_Primitive)
, fMaxVertices(-1)
, fInvocations(-1) {}
, fInvocations(-1)
, fKey(kNo_Key) {}
String description() const {
String result;
@ -215,6 +228,22 @@ struct Layout {
result += separator + "invocations = " + to_string(fInvocations);
separator = ", ";
}
if (fWhen.size()) {
result += separator + "when = " + fWhen;
separator = ", ";
}
switch (fKey) {
case kNo_Key:
break;
case kKey_Key:
result += separator + "key";
separator = ", ";
break;
case kIdentity_Key:
result += separator + "key=identity";
separator = ", ";
break;
}
if (result.size() > 0) {
result = "layout (" + result + ")";
}
@ -261,6 +290,8 @@ struct Layout {
Primitive fPrimitive;
int fMaxVertices;
int fInvocations;
String fWhen;
Key fKey;
};
} // namespace

View File

@ -33,9 +33,8 @@ struct PrefixExpression : public Expression {
fOperand->hasSideEffects();
}
virtual std::unique_ptr<Expression> constantPropagate(
const IRGenerator& irGenerator,
const DefinitionMap& definitions) override {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override {
if (fOperand->fKind == Expression::kFloatLiteral_Kind) {
return std::unique_ptr<Expression>(new FloatLiteral(
irGenerator.fContext,

View File

@ -11,7 +11,9 @@
#include <vector>
#include <memory>
#include "SkSLContext.h"
#include "SkSLBoolLiteral.h"
#include "SkSLExpression.h"
#include "SkSLIntLiteral.h"
#include "SkSLModifiers.h"
#include "SkSLProgramElement.h"
#include "SkSLSymbolTable.h"
@ -21,11 +23,46 @@
namespace SkSL {
class Context;
/**
* Represents a fully-digested program, ready for code generation.
*/
struct Program {
struct Settings {
struct Value {
Value(bool b)
: fKind(kBool_Kind)
, fValue(b) {}
Value(int i)
: fKind(kInt_Kind)
, fValue(i) {}
std::unique_ptr<Expression> literal(const Context& context, Position position) const {
switch (fKind) {
case Program::Settings::Value::kBool_Kind:
return std::unique_ptr<Expression>(new BoolLiteral(context,
position,
fValue));
case Program::Settings::Value::kInt_Kind:
return std::unique_ptr<Expression>(new IntLiteral(context,
position,
fValue));
default:
ASSERT(false);
return nullptr;
}
}
enum {
kBool_Kind,
kInt_Kind,
} fKind;
int fValue;
};
#ifdef SKSL_STANDALONE
const StandaloneShaderCaps* fCaps = &standaloneCaps;
#else
@ -34,6 +71,10 @@ struct Program {
// if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
// must be flipped.
bool fFlipY = false;
// if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
// constant equivalents during compilation
bool fReplaceSettings = true;
std::unordered_map<String, Value> fArgs;
};
struct Inputs {
@ -57,7 +98,8 @@ struct Program {
enum Kind {
kFragment_Kind,
kVertex_Kind,
kGeometry_Kind
kGeometry_Kind,
kFragmentProcessor_Kind
};
Program(Kind kind,

View File

@ -21,7 +21,8 @@ struct ProgramElement : public IRNode {
kFunction_Kind,
kInterfaceBlock_Kind,
kExtension_Kind,
kModifiers_Kind
kModifiers_Kind,
kSection_Kind
};
ProgramElement(Position position, Kind kind)

43
src/sksl/ir/SkSLSection.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SECTION
#define SKSL_SECTION
#include "SkSLProgramElement.h"
namespace SkSL {
/**
* A section declaration (e.g. @body { body code here })..
*/
struct Section : public ProgramElement {
Section(Position position, String name, String arg, String text)
: INHERITED(position, kSection_Kind)
, fName(std::move(name))
, fArgument(std::move(arg))
, fText(std::move(text)) {}
String description() const override {
String result = "@" + fName;
if (fArgument.size()) {
result += "(" + fArgument + ")";
}
result += " { " + fText + " }";
return result;
}
const String fName;
const String fArgument;
const String fText;
typedef ProgramElement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,22 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLSetting.h"
#include "SkSLIRGenerator.h"
#include "SkSLVariableReference.h"
namespace SkSL {
std::unique_ptr<Expression> Setting::constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) {
if (irGenerator.fSettings->fReplaceSettings) {
return VariableReference::copy_constant(irGenerator, fValue.get());
}
return nullptr;
}
} // namespace

51
src/sksl/ir/SkSLSetting.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SETTING
#define SKSL_SETTING
#include "SkSLContext.h"
#include "SkSLExpression.h"
namespace SkSL {
/**
* Represents a compile-time constant setting, such as sk_Caps.fbFetchSupport. These are generally
* collapsed down to their constant representations during the compilation process.
*/
struct Setting : public Expression {
Setting(Position position, String name, std::unique_ptr<Expression> value)
: INHERITED(position, kSetting_Kind, value->fType)
, fName(std::move(name))
, fValue(std::move(value)) {
ASSERT(fValue->isConstant());
}
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override;
String description() const override {
return fName;
}
bool hasSideEffects() const override {
return false;
}
bool isConstant() const override {
return true;
}
const String fName;
std::unique_ptr<Expression> fValue;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -71,10 +71,8 @@ struct Swizzle : public Expression {
ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4);
}
virtual std::unique_ptr<Expression> constantPropagate(
const IRGenerator& irGenerator,
const DefinitionMap& definitions) override {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override {
if (fBase->fKind == Expression::kConstructor_Kind && fBase->isConstant()) {
// we're swizzling a constant vector, e.g. vec4(1).x. Simplify it.
ASSERT(fBase->fKind == Expression::kConstructor_Kind);

View File

@ -55,7 +55,7 @@ struct VarDeclaration : public Statement {
* A variable declaration statement, which may consist of one or more individual variables.
*/
struct VarDeclarations : public ProgramElement {
VarDeclarations(Position position, const Type* baseType,
VarDeclarations(Position position, const Type* baseType,
std::vector<std::unique_ptr<VarDeclaration>> vars)
: INHERITED(position, kVar_Kind)
, fBaseType(*baseType) {

View File

@ -14,6 +14,7 @@
#include "SkSLFloatLiteral.h"
#include "SkSLIRGenerator.h"
#include "SkSLIntLiteral.h"
#include "SkSLSetting.h"
namespace SkSL {
@ -104,6 +105,12 @@ struct VariableReference : public Expression {
return std::unique_ptr<Expression>(new Constructor(Position(), c->fType,
std::move(args)));
}
case Expression::kSetting_Kind: {
const Setting* s = (const Setting*) expr;
return std::unique_ptr<Expression>(new Setting(Position(), s->fName,
copy_constant(irGenerator,
s->fValue.get())));
}
default:
ABORT("unsupported constant\n");
}

View File

@ -51,6 +51,8 @@
"triangles_adjacency" { return SkSL::Token::TRIANGLES_ADJACENCY; }
"max_vertices" { return SkSL::Token::MAX_VERTICES; }
"invocations" { return SkSL::Token::INVOCATIONS; }
"when" { return SkSL::Token::WHEN; }
"key" { return SkSL::Token::KEY; }
. { return SkSL::Token::INVALID_TOKEN; }

View File

@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
#line 2 "lex.layout.c"
#line 3 "lex.layout.c"
#define YY_INT_ALIGNED short int
@ -14,81 +14,11 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 3
#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
#define yy_create_buffer layout_create_buffer
#define yy_delete_buffer layout_delete_buffer
#define yy_scan_buffer layout_scan_buffer
#define yy_scan_string layout_scan_string
#define yy_scan_bytes layout_scan_bytes
#define yy_init_buffer layout_init_buffer
#define yy_flush_buffer layout_flush_buffer
#define yy_load_buffer_state layout_load_buffer_state
#define yy_switch_to_buffer layout_switch_to_buffer
#define yypush_buffer_state layoutpush_buffer_state
#define yypop_buffer_state layoutpop_buffer_state
#define yyensure_buffer_stack layoutensure_buffer_stack
#define yylex layoutlex
#define yyrestart layoutrestart
#define yylex_init layoutlex_init
#define yylex_init_extra layoutlex_init_extra
#define yylex_destroy layoutlex_destroy
#define yyget_debug layoutget_debug
#define yyset_debug layoutset_debug
#define yyget_extra layoutget_extra
#define yyset_extra layoutset_extra
#define yyget_in layoutget_in
#define yyset_in layoutset_in
#define yyget_out layoutget_out
#define yyset_out layoutset_out
#define yyget_leng layoutget_leng
#define yyget_text layoutget_text
#define yyget_lineno layoutget_lineno
#define yyset_lineno layoutset_lineno
#define yyget_column layoutget_column
#define yyset_column layoutset_column
#define yywrap layoutwrap
#define yyalloc layoutalloc
#define yyrealloc layoutrealloc
#define yyfree layoutfree
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@ -175,10 +105,12 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
/* Promotes a possibly negative, possibly signed char to an
* integer in range [0..255] for use as an array index.
/* Promotes a possibly negative, possibly signed char to an unsigned
* integer for use as an array index. If the signed char is negative,
* we want to instead treat it as an 8-bit unsigned char, hence the
* double cast.
*/
#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
@ -202,16 +134,20 @@ typedef void* yyscan_t;
* definition of BEGIN.
*/
#define BEGIN yyg->yy_start = 1 + 2 *
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yyg->yy_start - 1) / 2)
#define YYSTATE YY_START
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE layoutrestart(yyin ,yyscanner )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@ -244,10 +180,10 @@ typedef size_t yy_size_t;
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
* access to the local variable yy_act. Since yyless() is a macro, it would break
* existing scanners that call yyless() from OUTSIDE layoutlex.
* existing scanners that call yyless() from OUTSIDE layoutlex.
* One obvious solution it to make yy_act a global. I tried that, and saw
* a 5% performance hit in a non-yylineno scanner, because yy_act is
* normally declared as a register variable-- so it is not worth it.
@ -280,6 +216,7 @@ typedef size_t yy_size_t;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@ -322,7 +259,7 @@ struct yy_buffer_state
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
@ -356,33 +293,36 @@ struct yy_buffer_state
#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
: NULL)
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
void layoutrestart ( FILE *input_file , yyscan_t yyscanner );
void layout_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
YY_BUFFER_STATE layout_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
void layout_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
void layout_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
void layoutpush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
void layoutpop_buffer_state ( yyscan_t yyscanner );
void layoutrestart (FILE *input_file ,yyscan_t yyscanner );
void layout_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
YY_BUFFER_STATE layout_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
void layout_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void layout_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void layoutpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
void layoutpop_buffer_state (yyscan_t yyscanner );
static void layoutensure_buffer_stack (yyscan_t yyscanner );
static void layout_load_buffer_state (yyscan_t yyscanner );
static void layout_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
static void layoutensure_buffer_stack ( yyscan_t yyscanner );
static void layout_load_buffer_state ( yyscan_t yyscanner );
static void layout_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
#define YY_FLUSH_BUFFER layout_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
YY_BUFFER_STATE layout_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE layout_scan_string ( const char *yy_str , yyscan_t yyscanner );
YY_BUFFER_STATE layout_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
YY_BUFFER_STATE layout_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE layout_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE layout_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
void *layoutalloc ( yy_size_t , yyscan_t yyscanner );
void *layoutrealloc ( void *, yy_size_t , yyscan_t yyscanner );
void layoutfree ( void * , yyscan_t yyscanner );
void *layoutalloc (yy_size_t ,yyscan_t yyscanner );
void *layoutrealloc (void *,yy_size_t ,yyscan_t yyscanner );
void layoutfree (void * ,yyscan_t yyscanner );
#define yy_new_buffer layout_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
@ -392,6 +332,7 @@ void layoutfree ( void * , yyscan_t yyscanner );
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
@ -401,19 +342,21 @@ void layoutfree ( void * , yyscan_t yyscanner );
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
typedef flex_uint8_t YY_CHAR;
typedef unsigned char YY_CHAR;
typedef int yy_state_type;
#define yytext_ptr yytext_r
static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
static int yy_get_next_buffer ( yyscan_t yyscanner );
static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
static int yy_get_next_buffer (yyscan_t yyscanner );
static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@ -424,8 +367,9 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
#define YY_NUM_RULES 22
#define YY_END_OF_BUFFER 23
#define YY_NUM_RULES 24
#define YY_END_OF_BUFFER 25
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@ -433,34 +377,34 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static const flex_int16_t yy_accept[204] =
static yyconst flex_int16_t yy_accept[211] =
{ 0,
0, 0, 23, 21, 22, 21, 21, 21, 21, 21,
21, 21, 21, 0, 0, 0, 0, 0, 0, 0,
0, 0, 25, 23, 24, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 22, 0, 0,
0, 0, 0, 0, 0, 0, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 21, 0, 0, 0, 4, 0,
0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 4, 0, 0, 0, 13, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 2, 0, 0, 12, 0, 0, 3,
0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 12, 0, 0, 3, 0, 6, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 16, 0, 0, 0, 14, 0, 0,
0, 0, 0, 0, 0, 0, 0, 20, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 19, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 11,
0, 0, 0, 0, 0, 0, 0, 17, 0, 0,
0, 15, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 8, 9, 0, 0, 0, 0, 0, 0,
18, 0, 0, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16, 0, 0, 0, 14, 0, 0, 0, 0, 0,
0, 0, 0, 0, 20, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 11, 0, 0, 0,
0, 0, 0, 0, 17, 0, 0, 0, 15, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 8,
9, 0, 0, 0, 0, 0, 0, 18, 0, 0,
0, 10, 0
0, 0, 0, 7, 0, 0, 0, 0, 10, 0
} ;
static const YY_CHAR yy_ec[256] =
static yyconst YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -473,9 +417,9 @@ static const YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 1, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 1, 25,
26, 1, 1, 1, 1, 1, 1, 1, 1, 1,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -492,134 +436,138 @@ static const YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
static const YY_CHAR yy_meta[27] =
static yyconst YY_CHAR yy_meta[29] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1
1, 1, 1, 1, 1, 1, 1, 1
} ;
static const flex_int16_t yy_base[205] =
static yyconst flex_uint16_t yy_base[212] =
{ 0,
0, 21, 218, 219, 219, 17, 201, 7, 212, 21,
11, 207, 194, 197, 204, 199, 30, 194, 203, 183,
198, 194, 197, 192, 182, 180, 189, 193, 183, 184,
189, 173, 178, 186, 189, 189, 170, 180, 169, 172,
176, 219, 182, 173, 177, 161, 157, 159, 174, 4,
157, 154, 169, 164, 155, 152, 170, 156, 155, 167,
157, 219, 165, 163, 145, 162, 152, 155, 140, 145,
148, 138, 152, 147, 146, 134, 138, 149, 130, 129,
146, 132, 128, 219, 144, 139, 219, 128, 130, 219,
120, 219, 120, 129, 120, 132, 122, 115, 113, 127,
0, 25, 227, 228, 228, 5, 209, 217, 13, 220,
24, 10, 215, 201, 210, 203, 211, 206, 17, 189,
199, 209, 187, 204, 200, 203, 198, 187, 185, 195,
198, 198, 187, 188, 194, 177, 182, 228, 191, 194,
194, 174, 185, 173, 176, 181, 228, 187, 173, 177,
181, 164, 159, 162, 178, 10, 160, 157, 173, 168,
158, 155, 174, 159, 228, 158, 171, 161, 228, 169,
167, 148, 166, 156, 159, 143, 148, 152, 141, 156,
151, 150, 137, 141, 153, 133, 132, 150, 135, 131,
228, 148, 143, 228, 131, 133, 228, 123, 228, 123,
118, 125, 114, 109, 113, 117, 115, 219, 115, 108,
122, 103, 6, 105, 118, 105, 102, 115, 112, 99,
110, 93, 93, 110, 95, 105, 89, 219, 103, 100,
99, 89, 101, 82, 99, 82, 90, 219, 92, 78,
78, 73, 80, 75, 87, 71, 77, 75, 219, 87,
81, 66, 75, 73, 82, 76, 77, 68, 61, 219,
62, 75, 74, 61, 50, 67, 70, 219, 67, 58,
49, 219, 61, 59, 60, 53, 63, 43, 56, 47,
59, 49, 219, 219, 54, 51, 42, 31, 37, 48,
219, 30, 44, 47, 25, 27, 219, 35, 29, 28,
133, 123, 136, 125, 118, 116, 131, 121, 129, 117,
112, 116, 121, 119, 228, 119, 111, 126, 106, 32,
108, 122, 108, 105, 119, 116, 102, 114, 96, 96,
114, 98, 109, 92, 228, 107, 104, 103, 92, 105,
85, 103, 85, 94, 228, 96, 81, 81, 76, 83,
78, 91, 74, 80, 78, 228, 91, 85, 69, 79,
77, 86, 80, 81, 71, 64, 228, 65, 79, 78,
64, 52, 71, 74, 228, 71, 61, 52, 228, 65,
63, 64, 56, 67, 46, 60, 50, 63, 53, 228,
228, 58, 55, 45, 33, 40, 52, 228, 34, 49,
11, 219, 219, 0
52, 28, 30, 228, 40, 32, 29, 16, 228, 228,
0
} ;
static const flex_int16_t yy_def[205] =
static yyconst flex_int16_t yy_def[212] =
{ 0,
204, 204, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
211, 211, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
203, 203, 0, 203
210, 210, 210, 210, 210, 210, 210, 210, 210, 0,
210
} ;
static const flex_int16_t yy_nxt[246] =
static yyconst flex_uint16_t yy_nxt[257] =
{ 0,
4, 5, 203, 203, 6, 203, 65, 203, 123, 203,
203, 7, 203, 8, 9, 203, 10, 11, 18, 203,
12, 13, 5, 19, 66, 6, 124, 24, 14, 21,
15, 202, 7, 25, 8, 9, 31, 10, 11, 16,
22, 12, 13, 201, 23, 200, 199, 32, 198, 197,
196, 195, 194, 33, 193, 192, 191, 190, 189, 188,
187, 186, 185, 184, 183, 182, 181, 180, 179, 178,
177, 176, 175, 174, 173, 172, 171, 170, 169, 168,
167, 166, 165, 164, 163, 162, 161, 160, 159, 158,
157, 156, 155, 154, 153, 152, 151, 150, 149, 148,
4, 5, 210, 210, 6, 210, 210, 210, 210, 210,
210, 7, 72, 8, 9, 10, 16, 11, 12, 17,
210, 13, 14, 35, 21, 15, 5, 27, 18, 6,
22, 73, 24, 28, 130, 36, 7, 209, 8, 9,
10, 37, 11, 12, 25, 208, 13, 14, 26, 207,
15, 206, 205, 131, 204, 203, 202, 201, 200, 199,
198, 197, 196, 195, 194, 193, 192, 191, 190, 189,
188, 187, 186, 185, 184, 183, 182, 181, 180, 179,
178, 177, 176, 175, 174, 173, 172, 171, 170, 169,
168, 167, 166, 165, 164, 163, 162, 161, 160, 159,
147, 146, 145, 144, 143, 142, 141, 140, 139, 138,
137, 136, 135, 134, 133, 132, 131, 130, 129, 128,
127, 126, 125, 122, 121, 120, 119, 118, 117, 116,
115, 114, 113, 112, 111, 110, 109, 108, 107, 106,
105, 104, 103, 102, 101, 100, 99, 98, 97, 96,
95, 94, 93, 92, 91, 90, 89, 88, 87, 86,
85, 84, 83, 82, 81, 80, 79, 78, 77, 76,
75, 74, 73, 72, 71, 70, 69, 68, 67, 64,
63, 62, 61, 60, 59, 58, 57, 56, 55, 54,
53, 52, 51, 50, 49, 48, 47, 46, 45, 44,
43, 42, 41, 40, 39, 38, 37, 36, 35, 34,
30, 29, 28, 27, 26, 20, 17, 203, 3, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203
} ;
static const flex_int16_t yy_chk[246] =
{ 0,
204, 1, 0, 0, 1, 0, 50, 0, 113, 0,
0, 1, 0, 1, 1, 0, 1, 1, 8, 0,
1, 1, 2, 8, 50, 2, 113, 11, 6, 10,
6, 201, 2, 11, 2, 2, 17, 2, 2, 6,
10, 2, 2, 200, 10, 199, 198, 17, 196, 195,
194, 193, 192, 17, 190, 189, 188, 187, 186, 185,
182, 181, 180, 179, 178, 177, 176, 175, 174, 173,
171, 170, 169, 167, 166, 165, 164, 163, 162, 161,
159, 158, 157, 156, 155, 154, 153, 152, 151, 150,
158, 157, 156, 155, 154, 153, 152, 151, 150, 149,
148, 147, 146, 145, 144, 143, 142, 141, 140, 139,
137, 136, 135, 134, 133, 132, 131, 130, 129, 127,
138, 137, 136, 135, 134, 133, 132, 129, 128, 127,
126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
116, 115, 114, 112, 111, 110, 109, 107, 106, 105,
104, 103, 102, 101, 100, 99, 98, 97, 96, 95,
94, 93, 91, 89, 88, 86, 85, 83, 82, 81,
80, 79, 78, 77, 76, 75, 74, 73, 72, 71,
70, 69, 68, 67, 66, 65, 64, 63, 61, 60,
59, 58, 57, 56, 55, 54, 53, 52, 51, 49,
48, 47, 46, 45, 44, 43, 41, 40, 39, 38,
37, 36, 35, 34, 33, 32, 31, 30, 29, 28,
116, 115, 114, 113, 112, 111, 110, 109, 108, 107,
106, 105, 104, 103, 102, 101, 100, 99, 98, 97,
96, 95, 94, 93, 92, 91, 90, 89, 88, 87,
86, 85, 84, 83, 82, 81, 80, 79, 78, 77,
76, 75, 74, 71, 70, 69, 68, 67, 66, 65,
64, 63, 62, 61, 60, 59, 58, 57, 56, 55,
27, 26, 25, 24, 23, 22, 21, 20, 19, 18,
16, 15, 14, 13, 12, 9, 7, 3, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
203, 203, 203, 203, 203
54, 53, 52, 51, 50, 49, 48, 47, 46, 45,
44, 43, 42, 41, 40, 39, 38, 34, 33, 32,
31, 30, 29, 23, 20, 19, 210, 3, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210
} ;
static yyconst flex_int16_t yy_chk[257] =
{ 0,
211, 1, 0, 0, 1, 0, 0, 0, 0, 0,
0, 1, 56, 1, 1, 1, 6, 1, 1, 6,
0, 1, 1, 19, 9, 1, 2, 12, 6, 2,
9, 56, 11, 12, 120, 19, 2, 208, 2, 2,
2, 19, 2, 2, 11, 207, 2, 2, 11, 206,
2, 205, 203, 120, 202, 201, 200, 199, 197, 196,
195, 194, 193, 192, 189, 188, 187, 186, 185, 184,
183, 182, 181, 180, 178, 177, 176, 174, 173, 172,
171, 170, 169, 168, 166, 165, 164, 163, 162, 161,
160, 159, 158, 157, 155, 154, 153, 152, 151, 150,
149, 148, 147, 146, 144, 143, 142, 141, 140, 139,
138, 137, 136, 134, 133, 132, 131, 130, 129, 128,
127, 126, 125, 124, 123, 122, 121, 119, 118, 117,
116, 114, 113, 112, 111, 110, 109, 108, 107, 106,
105, 104, 103, 102, 101, 100, 98, 96, 95, 93,
92, 90, 89, 88, 87, 86, 85, 84, 83, 82,
81, 80, 79, 78, 77, 76, 75, 74, 73, 72,
71, 70, 68, 67, 66, 64, 63, 62, 61, 60,
59, 58, 57, 55, 54, 53, 52, 51, 50, 49,
48, 46, 45, 44, 43, 42, 41, 40, 39, 37,
36, 35, 34, 33, 32, 31, 30, 29, 28, 27,
26, 25, 24, 23, 22, 21, 20, 18, 17, 16,
15, 14, 13, 10, 8, 7, 3, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
210, 210, 210, 210, 210, 210
} ;
/* Table of booleans, true if rule could match eol. */
static const flex_int32_t yy_rule_can_match_eol[23] =
static yyconst flex_int32_t yy_rule_can_match_eol[25] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, };
0, 0, 0, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@ -651,8 +599,7 @@ static const flex_int32_t yy_rule_can_match_eol[23] =
#define YY_NO_UNISTD_H 1
#line 29 "layout.flex"
#include "SkSLToken.h"
#line 648 "lex.layout.c"
#line 649 "lex.layout.c"
#line 597 "lex.layout.c"
#define INITIAL 0
@ -702,44 +649,44 @@ struct yyguts_t
}; /* end struct yyguts_t */
static int yy_init_globals ( yyscan_t yyscanner );
static int yy_init_globals (yyscan_t yyscanner );
int layoutlex_init (yyscan_t* scanner);
int layoutlex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
int layoutlex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int layoutlex_destroy ( yyscan_t yyscanner );
int layoutlex_destroy (yyscan_t yyscanner );
int layoutget_debug ( yyscan_t yyscanner );
int layoutget_debug (yyscan_t yyscanner );
void layoutset_debug ( int debug_flag , yyscan_t yyscanner );
void layoutset_debug (int debug_flag ,yyscan_t yyscanner );
YY_EXTRA_TYPE layoutget_extra ( yyscan_t yyscanner );
YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner );
void layoutset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
void layoutset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *layoutget_in ( yyscan_t yyscanner );
FILE *layoutget_in (yyscan_t yyscanner );
void layoutset_in ( FILE * _in_str , yyscan_t yyscanner );
void layoutset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *layoutget_out ( yyscan_t yyscanner );
FILE *layoutget_out (yyscan_t yyscanner );
void layoutset_out ( FILE * _out_str , yyscan_t yyscanner );
void layoutset_out (FILE * _out_str ,yyscan_t yyscanner );
int layoutget_leng ( yyscan_t yyscanner );
int layoutget_leng (yyscan_t yyscanner );
char *layoutget_text ( yyscan_t yyscanner );
char *layoutget_text (yyscan_t yyscanner );
int layoutget_lineno ( yyscan_t yyscanner );
int layoutget_lineno (yyscan_t yyscanner );
void layoutset_lineno ( int _line_number , yyscan_t yyscanner );
void layoutset_lineno (int _line_number ,yyscan_t yyscanner );
int layoutget_column ( yyscan_t yyscanner );
int layoutget_column (yyscan_t yyscanner );
void layoutset_column ( int _column_no , yyscan_t yyscanner );
void layoutset_column (int _column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@ -747,31 +694,32 @@ void layoutset_column ( int _column_no , yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int layoutwrap ( yyscan_t yyscanner );
extern "C" int layoutwrap (yyscan_t yyscanner );
#else
extern int layoutwrap ( yyscan_t yyscanner );
extern int layoutwrap (yyscan_t yyscanner );
#endif
#endif
#ifndef YY_NO_UNPUT
static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner);
static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput ( yyscan_t yyscanner );
static int yyinput (yyscan_t yyscanner );
#else
static int input ( yyscan_t yyscanner );
static int input (yyscan_t yyscanner );
#endif
#endif
@ -802,7 +750,7 @@ static int input ( yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
int n; \
size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@ -815,7 +763,7 @@ static int input ( yyscan_t yyscanner );
else \
{ \
errno=0; \
while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@ -915,7 +863,7 @@ YY_DECL
#line 32 "layout.flex"
#line 912 "lex.layout.c"
#line 861 "lex.layout.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@ -942,13 +890,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 204 )
yy_c = yy_meta[yy_c];
if ( yy_current_state >= 211 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
++yy_cp;
}
while ( yy_current_state != 203 );
while ( yy_current_state != 210 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@ -959,10 +907,10 @@ yy_find_action:
if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
{
int yyl;
yy_size_t yyl;
for ( yyl = 0; yyl < yyleng; ++yyl )
if ( yytext[yyl] == '\n' )
do{ yylineno++;
yycolumn=0;
}while(0)
@ -1082,15 +1030,25 @@ YY_RULE_SETUP
YY_BREAK
case 21:
YY_RULE_SETUP
#line 55 "layout.flex"
{ return SkSL::Token::INVALID_TOKEN; }
#line 54 "layout.flex"
{ return SkSL::Token::WHEN; }
YY_BREAK
case 22:
YY_RULE_SETUP
#line 55 "layout.flex"
{ return SkSL::Token::KEY; }
YY_BREAK
case 23:
YY_RULE_SETUP
#line 57 "layout.flex"
{ return SkSL::Token::INVALID_TOKEN; }
YY_BREAK
case 24:
YY_RULE_SETUP
#line 59 "layout.flex"
ECHO;
YY_BREAK
#line 1087 "lex.layout.c"
#line 1046 "lex.layout.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@ -1237,7 +1195,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr;
int number_to_move, i;
yy_size_t number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@ -1266,7 +1224,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@ -1302,7 +1260,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
layoutrealloc((void *) b->yy_ch_buf,(yy_size_t) (b->yy_buf_size + 2) ,yyscanner );
layoutrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
}
else
/* Can't grow it, we don't own it. */
@ -1348,10 +1306,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) layoutrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,(yy_size_t) new_size ,yyscanner );
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) layoutrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
}
@ -1386,10 +1344,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 204 )
yy_c = yy_meta[yy_c];
if ( yy_current_state >= 211 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
}
return yy_current_state;
@ -1415,11 +1373,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 204 )
yy_c = yy_meta[yy_c];
if ( yy_current_state >= 211 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 203);
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_is_jam = (yy_current_state == 210);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@ -1496,7 +1454,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@ -1543,7 +1501,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
yyg->yy_hold_char = *++yyg->yy_c_buf_p;
if ( c == '\n' )
do{ yylineno++;
yycolumn=0;
}while(0)
@ -1631,12 +1589,12 @@ static void layout_load_buffer_state (yyscan_t yyscanner)
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" );
b->yy_buf_size = size;
b->yy_buf_size = (yy_size_t)size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
b->yy_ch_buf = (char *) layoutalloc((yy_size_t) (b->yy_buf_size + 2) ,yyscanner );
b->yy_ch_buf = (char *) layoutalloc(b->yy_buf_size + 2 ,yyscanner );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" );
@ -1783,7 +1741,7 @@ void layoutpop_buffer_state (yyscan_t yyscanner)
*/
static void layoutensure_buffer_stack (yyscan_t yyscanner)
{
yy_size_t num_to_alloc;
int num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@ -1798,9 +1756,9 @@ static void layoutensure_buffer_stack (yyscan_t yyscanner)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
YY_FATAL_ERROR( "out of dynamic memory in layoutensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
yyg->yy_buffer_stack_max = num_to_alloc;
yyg->yy_buffer_stack_top = 0;
return;
@ -1829,7 +1787,7 @@ static void layoutensure_buffer_stack (yyscan_t yyscanner)
* @param base the character buffer
* @param size the size in bytes of the character buffer
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
@ -1845,7 +1803,7 @@ YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yys
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in layout_scan_buffer()" );
b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@ -1868,7 +1826,7 @@ YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yys
* @note If you want to scan bytes that may contain NUL values, then use
* layout_scan_bytes() instead.
*/
YY_BUFFER_STATE layout_scan_string (const char * yystr , yyscan_t yyscanner)
YY_BUFFER_STATE layout_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{
return layout_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
@ -1881,15 +1839,15 @@ YY_BUFFER_STATE layout_scan_string (const char * yystr , yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE layout_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
YY_BUFFER_STATE layout_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
int i;
yy_size_t i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = (yy_size_t) (_yybytes_len + 2);
n = (yy_size_t) _yybytes_len + 2;
buf = (char *) layoutalloc(n ,yyscanner );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in layout_scan_bytes()" );
@ -1915,7 +1873,7 @@ YY_BUFFER_STATE layout_scan_bytes (const char * yybytes, int _yybytes_len , yy
#define YY_EXIT_FAILURE 2
#endif
static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@ -1957,7 +1915,7 @@ YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner)
int layoutget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (! YY_CURRENT_BUFFER)
return 0;
@ -1970,7 +1928,7 @@ int layoutget_lineno (yyscan_t yyscanner)
int layoutget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (! YY_CURRENT_BUFFER)
return 0;
@ -2092,7 +2050,9 @@ void layoutset_debug (int _bdebug , yyscan_t yyscanner)
* the ONLY reentrant function that doesn't take the scanner as the last argument.
* That's why we explicitly handle the declaration, instead of using our macros.
*/
int layoutlex_init(yyscan_t* ptr_yy_globals)
{
if (ptr_yy_globals == NULL){
errno = EINVAL;
@ -2119,7 +2079,9 @@ int layoutlex_init(yyscan_t* ptr_yy_globals)
* The user defined value in the first argument will be available to layoutalloc in
* the yyextra field.
*/
int layoutlex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
{
struct yyguts_t dummy_yyguts;
@ -2129,20 +2091,20 @@ int layoutlex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals
errno = EINVAL;
return 1;
}
*ptr_yy_globals = (yyscan_t) layoutalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
return 1;
}
/* By setting to 0xAA, we expose bugs in
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
layoutset_extra (yy_user_defined, *ptr_yy_globals);
return yy_init_globals ( *ptr_yy_globals );
}
@ -2214,7 +2176,7 @@ int layoutlex_destroy (yyscan_t yyscanner)
*/
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@ -2226,7 +2188,7 @@ static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscann
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
int n;
for ( n = 0; s[n]; ++n )
@ -2267,7 +2229,8 @@ void layoutfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
#line 57 "layout.flex"
#line 59 "layout.flex"
int layoutwrap(yyscan_t scanner) {

View File

@ -7,6 +7,6 @@
#include "disable_flex_warnings.h"
#include "lex.layout.c"
static_assert(YY_FLEX_MAJOR_VERSION * 100 + YY_FLEX_MINOR_VERSION * 10 +
YY_FLEX_SUBMINOR_VERSION >= 261,
static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 +
YY_FLEX_SUBMINOR_VERSION >= 20601,
"we require Flex 2.6.1 or better for security reasons");

View File

@ -1,3 +1,9 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#line 3 "lex.sksl.c"
@ -362,8 +368,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
#define YY_NUM_RULES 96
#define YY_END_OF_BUFFER 97
#define YY_NUM_RULES 99
#define YY_END_OF_BUFFER 100
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@ -371,39 +377,39 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static yyconst flex_int16_t yy_accept[285] =
static yyconst flex_int16_t yy_accept[289] =
{ 0,
0, 0, 97, 95, 94, 94, 68, 95, 42, 58,
63, 44, 45, 56, 54, 51, 55, 50, 57, 4,
4, 70, 91, 75, 71, 74, 69, 95, 48, 49,
62, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 46,
61, 47, 64, 94, 73, 43, 42, 82, 67, 87,
80, 52, 78, 53, 79, 1, 0, 92, 81, 2,
4, 0, 0, 59, 77, 72, 76, 60, 0, 0,
86, 66, 42, 42, 42, 42, 42, 42, 13, 42,
42, 42, 42, 42, 8, 22, 42, 42, 42, 42,
0, 0, 100, 98, 95, 95, 69, 98, 42, 59,
64, 45, 46, 57, 55, 52, 56, 51, 58, 4,
4, 71, 92, 76, 72, 75, 70, 98, 49, 50,
63, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 47,
62, 48, 65, 95, 74, 43, 42, 83, 68, 88,
81, 53, 79, 54, 80, 93, 1, 0, 96, 82,
2, 4, 0, 0, 94, 60, 78, 73, 77, 61,
44, 44, 44, 87, 67, 42, 42, 42, 42, 42,
42, 13, 42, 42, 42, 42, 42, 8, 22, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 85, 65, 43, 90, 0, 0, 0, 92, 1,
0, 0, 3, 5, 83, 84, 9, 0, 89, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 11,
42, 42, 42, 42, 42, 42, 23, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 88,
0, 1, 93, 0, 0, 2, 0, 42, 42, 16,
42, 42, 42, 42, 42, 10, 42, 30, 42, 42,
42, 27, 42, 42, 42, 42, 42, 42, 42, 42,
42, 6, 42, 42, 42, 42, 0, 1, 0, 18,
42, 42, 42, 42, 86, 66, 43, 91, 0, 0,
0, 96, 1, 0, 0, 3, 5, 84, 85, 44,
9, 44, 90, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 11, 42, 42, 42, 42, 42, 42,
23, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 89, 0, 1, 97, 0, 0, 2,
44, 42, 42, 16, 42, 42, 42, 42, 42, 10,
42, 30, 42, 42, 42, 27, 42, 42, 42, 42,
42, 42, 42, 42, 42, 6, 42, 42, 42, 42,
42, 42, 26, 42, 42, 42, 7, 29, 24, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 12, 42, 0, 37, 42, 42, 42, 42, 40,
42, 42, 42, 42, 42, 21, 42, 39, 14, 42,
42, 42, 15, 42, 42, 17, 20, 28, 42, 42,
42, 42, 42, 25, 42, 42, 34, 19, 42, 42,
32, 36, 42, 35, 42, 42, 41, 42, 33, 42,
42, 42, 42, 42, 42, 31, 42, 42, 42, 42,
42, 42, 38, 0
0, 1, 44, 18, 42, 42, 26, 42, 42, 42,
7, 29, 24, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 12, 42, 44, 37, 42,
42, 42, 42, 40, 42, 42, 42, 42, 42, 21,
42, 39, 14, 42, 42, 42, 15, 42, 42, 17,
20, 28, 42, 42, 42, 42, 42, 25, 42, 42,
34, 19, 42, 42, 32, 36, 42, 35, 42, 42,
41, 42, 33, 42, 42, 42, 42, 42, 42, 31,
42, 42, 42, 42, 42, 42, 38, 0
} ;
static yyconst YY_CHAR yy_ec[256] =
@ -448,77 +454,81 @@ static yyconst YY_CHAR yy_meta[59] =
3, 3, 3, 3, 1, 1, 1, 1
} ;
static yyconst flex_uint16_t yy_base[291] =
static yyconst flex_uint16_t yy_base[297] =
{ 0,
0, 0, 353, 354, 57, 59, 330, 0, 0, 329,
55, 354, 354, 328, 52, 354, 51, 49, 59, 61,
65, 354, 354, 47, 327, 49, 354, 45, 354, 354,
64, 37, 57, 55, 306, 64, 307, 61, 58, 310,
300, 294, 296, 306, 58, 294, 296, 294, 65, 354,
86, 354, 354, 113, 354, 0, 0, 354, 316, 354,
354, 354, 354, 354, 354, 100, 326, 0, 354, 102,
107, 114, 0, 314, 354, 354, 354, 313, 297, 281,
354, 310, 295, 293, 281, 91, 291, 279, 0, 278,
283, 292, 276, 284, 0, 276, 266, 267, 283, 271,
0, 0, 360, 361, 57, 59, 337, 0, 0, 336,
55, 361, 361, 335, 52, 361, 53, 48, 57, 54,
65, 337, 361, 63, 333, 64, 361, 30, 361, 361,
66, 44, 57, 59, 312, 61, 313, 61, 65, 316,
306, 300, 302, 312, 59, 300, 302, 300, 70, 361,
90, 361, 361, 111, 361, 0, 0, 361, 322, 361,
361, 361, 361, 361, 361, 361, 98, 332, 0, 361,
101, 105, 112, 0, 361, 320, 361, 361, 361, 319,
0, 303, 287, 361, 316, 301, 299, 287, 92, 297,
285, 0, 284, 289, 298, 282, 290, 0, 282, 272,
267, 279, 91, 283, 266, 272, 261, 270, 267, 268,
267, 354, 284, 0, 354, 132, 294, 288, 0, 130,
141, 134, 143, 0, 354, 354, 354, 263, 354, 270,
264, 264, 263, 114, 266, 263, 260, 247, 245, 0,
254, 242, 246, 244, 249, 252, 0, 253, 251, 236,
234, 244, 232, 232, 244, 242, 246, 235, 227, 354,
147, 150, 354, 157, 155, 159, 226, 233, 237, 0,
225, 222, 230, 219, 236, 0, 231, 0, 220, 216,
214, 0, 213, 215, 221, 215, 212, 211, 225, 222,
221, 0, 209, 204, 216, 215, 161, 163, 216, 0,
273, 289, 277, 273, 285, 95, 289, 272, 278, 267,
276, 273, 274, 273, 361, 290, 0, 361, 121, 300,
294, 0, 130, 137, 135, 141, 0, 361, 361, 0,
0, 269, 361, 276, 270, 270, 269, 112, 272, 269,
266, 253, 251, 0, 260, 248, 252, 250, 255, 258,
0, 259, 257, 242, 240, 250, 238, 238, 250, 248,
252, 241, 233, 361, 145, 147, 361, 155, 153, 157,
232, 239, 243, 0, 231, 228, 236, 225, 242, 0,
237, 0, 226, 222, 220, 0, 219, 221, 227, 221,
218, 217, 231, 228, 227, 0, 215, 210, 222, 221,
159, 161, 222, 0, 208, 218, 0, 209, 210, 204,
0, 0, 0, 201, 206, 200, 199, 202, 205, 200,
195, 193, 202, 193, 199, 0, 193, 198, 0, 192,
185, 185, 198, 0, 186, 185, 190, 187, 194, 0,
196, 0, 0, 183, 183, 180, 0, 174, 186, 0,
0, 0, 185, 175, 165, 169, 169, 0, 180, 173,
0, 0, 180, 169, 0, 0, 172, 0, 157, 161,
0, 174, 0, 168, 171, 147, 156, 145, 132, 0,
119, 113, 109, 108, 91, 73, 0, 361, 177, 180,
183, 186, 191, 196, 198, 201
202, 212, 0, 203, 204, 198, 0, 0, 0, 195,
200, 194, 193, 196, 199, 194, 189, 187, 196, 187,
193, 0, 187, 192, 0, 186, 179, 179, 192, 0,
180, 179, 184, 181, 188, 0, 190, 0, 0, 177,
177, 174, 354, 168, 180, 0, 0, 0, 179, 169,
159, 163, 163, 0, 174, 167, 0, 0, 174, 163,
0, 0, 166, 0, 151, 155, 0, 168, 0, 157,
147, 119, 125, 118, 109, 0, 104, 100, 97, 87,
64, 63, 0, 354, 179, 182, 185, 190, 195, 197
} ;
static yyconst flex_int16_t yy_def[291] =
static yyconst flex_int16_t yy_def[297] =
{ 0,
284, 1, 284, 284, 284, 284, 284, 285, 286, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 284,
284, 284, 284, 284, 284, 287, 286, 284, 284, 284,
284, 284, 284, 284, 284, 284, 288, 289, 284, 284,
284, 284, 290, 284, 284, 284, 284, 284, 284, 284,
284, 284, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
288, 1, 288, 288, 288, 288, 288, 289, 290, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 291, 288, 288,
288, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 288,
288, 288, 288, 288, 288, 292, 290, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 293, 294, 288,
288, 288, 288, 295, 288, 288, 288, 288, 288, 288,
296, 296, 296, 288, 288, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 284, 284, 287, 284, 284, 288, 288, 289, 284,
284, 284, 284, 290, 284, 284, 284, 284, 284, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 284,
284, 284, 284, 284, 284, 284, 284, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 284, 284, 284, 286,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 288, 288, 292, 288, 288, 293,
293, 294, 288, 288, 288, 288, 295, 288, 288, 296,
296, 296, 288, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 288, 288, 288, 288, 288, 288, 288,
296, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
288, 288, 296, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 296, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 296, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
290, 290, 290, 290, 290, 290, 290, 0, 288, 288,
288, 288, 288, 288, 288, 288
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 284, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 284, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
286, 286, 286, 0, 284, 284, 284, 284, 284, 284
} ;
static yyconst flex_uint16_t yy_nxt[413] =
static yyconst flex_uint16_t yy_nxt[420] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
@ -526,49 +536,49 @@ static yyconst flex_uint16_t yy_nxt[413] =
9, 9, 32, 33, 34, 35, 36, 9, 37, 38,
9, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 9, 9, 50, 51, 52, 53, 54, 54,
54, 54, 59, 62, 64, 66, 66, 74, 75, 67,
77, 78, 65, 63, 68, 70, 60, 71, 71, 70,
69, 71, 71, 83, 79, 81, 84, 72, 85, 97,
87, 72, 80, 82, 88, 91, 72, 95, 104, 89,
54, 54, 59, 62, 67, 67, 64, 68, 71, 82,
72, 72, 69, 63, 65, 66, 60, 83, 70, 71,
73, 72, 72, 76, 77, 79, 80, 84, 88, 73,
86, 73, 94, 87, 90, 85, 100, 98, 91, 107,
72, 86, 98, 110, 96, 92, 105, 112, 93, 106,
283, 111, 282, 73, 54, 54, 66, 66, 120, 120,
281, 70, 149, 71, 71, 122, 116, 122, 121, 133,
123, 123, 280, 72, 134, 116, 279, 121, 150, 151,
278, 113, 72, 161, 277, 161, 120, 120, 162, 162,
123, 123, 165, 276, 165, 275, 164, 166, 166, 123,
123, 172, 173, 162, 162, 164, 162, 162, 197, 274,
197, 166, 166, 198, 198, 166, 166, 198, 198, 198,
198, 56, 273, 56, 57, 57, 57, 114, 114, 114,
117, 117, 117, 117, 117, 119, 272, 119, 119, 119,
73, 89, 95, 92, 99, 96, 74, 108, 113, 101,
109, 115, 54, 54, 67, 67, 114, 123, 123, 71,
287, 72, 72, 125, 119, 125, 153, 124, 126, 126,
137, 73, 165, 119, 165, 138, 124, 166, 166, 286,
73, 285, 154, 155, 284, 116, 123, 123, 169, 283,
169, 126, 126, 170, 170, 282, 168, 126, 126, 176,
177, 166, 166, 166, 166, 168, 201, 281, 201, 170,
170, 202, 202, 170, 170, 202, 202, 202, 202, 56,
280, 56, 57, 57, 57, 81, 279, 81, 117, 117,
117, 120, 120, 120, 120, 120, 122, 278, 122, 122,
124, 124, 271, 270, 269, 268, 267, 266, 265, 264,
122, 127, 127, 130, 130, 130, 277, 276, 275, 274,
273, 272, 271, 270, 269, 268, 267, 266, 265, 264,
263, 262, 261, 260, 259, 258, 257, 256, 255, 254,
253, 252, 251, 250, 249, 248, 247, 246, 245, 244,
243, 242, 241, 240, 239, 238, 237, 236, 235, 234,
233, 232, 231, 230, 229, 228, 227, 226, 225, 224,
223, 222, 221, 220, 219, 218, 217, 216, 215, 214,
213, 212, 211, 210, 209, 208, 207, 206, 205, 204,
203, 202, 201, 200, 199, 196, 195, 194, 193, 192,
203, 200, 199, 198, 197, 196, 195, 194, 193, 192,
191, 190, 189, 188, 187, 186, 185, 184, 183, 182,
181, 180, 179, 178, 177, 176, 175, 174, 171, 170,
169, 168, 167, 163, 118, 160, 159, 158, 157, 156,
155, 154, 153, 152, 148, 147, 146, 145, 144, 143,
142, 141, 140, 139, 138, 137, 136, 135, 132, 131,
130, 129, 128, 127, 126, 125, 118, 115, 109, 108,
107, 103, 102, 101, 100, 99, 94, 90, 76, 61,
58, 55, 284, 3, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
181, 180, 179, 178, 175, 174, 173, 172, 171, 167,
121, 164, 163, 162, 161, 160, 159, 158, 157, 156,
152, 151, 150, 149, 148, 147, 146, 145, 144, 143,
142, 141, 140, 139, 136, 135, 134, 133, 132, 131,
129, 128, 121, 118, 112, 111, 110, 106, 105, 104,
103, 102, 97, 93, 78, 75, 61, 58, 55, 288,
3, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288
} ;
static yyconst flex_int16_t yy_chk[413] =
static yyconst flex_int16_t yy_chk[420] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -576,56 +586,57 @@ static yyconst flex_int16_t yy_chk[413] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5,
6, 6, 11, 15, 17, 18, 18, 24, 24, 19,
26, 26, 17, 15, 19, 20, 11, 20, 20, 21,
19, 21, 21, 32, 28, 31, 32, 20, 33, 39,
34, 21, 28, 31, 34, 36, 20, 38, 45, 34,
6, 6, 11, 15, 18, 18, 17, 19, 20, 28,
20, 20, 19, 15, 17, 17, 11, 28, 19, 21,
20, 21, 21, 24, 24, 26, 26, 31, 33, 20,
32, 21, 36, 32, 34, 31, 39, 38, 34, 45,
21, 33, 39, 49, 38, 36, 45, 51, 36, 45,
282, 49, 281, 20, 54, 54, 66, 66, 70, 70,
280, 71, 103, 71, 71, 72, 66, 72, 70, 86,
72, 72, 279, 71, 86, 66, 278, 70, 103, 103,
277, 51, 71, 116, 275, 116, 120, 120, 116, 116,
122, 122, 121, 274, 121, 273, 120, 121, 121, 123,
123, 134, 134, 161, 161, 120, 162, 162, 164, 272,
164, 165, 165, 164, 164, 166, 166, 197, 197, 198,
198, 285, 271, 285, 286, 286, 286, 287, 287, 287,
288, 288, 288, 288, 288, 289, 270, 289, 289, 289,
21, 33, 36, 34, 38, 36, 20, 45, 49, 39,
45, 51, 54, 54, 67, 67, 49, 71, 71, 72,
286, 72, 72, 73, 67, 73, 106, 71, 73, 73,
89, 72, 119, 67, 119, 89, 71, 119, 119, 285,
72, 284, 106, 106, 283, 51, 123, 123, 124, 282,
124, 125, 125, 124, 124, 281, 123, 126, 126, 138,
138, 165, 165, 166, 166, 123, 168, 279, 168, 169,
169, 168, 168, 170, 170, 201, 201, 202, 202, 289,
278, 289, 290, 290, 290, 291, 277, 291, 292, 292,
292, 293, 293, 293, 293, 293, 294, 276, 294, 294,
290, 290, 268, 266, 265, 263, 260, 259, 256, 255,
253, 252, 251, 250, 249, 245, 244, 242, 241, 240,
237, 235, 234, 233, 232, 231, 229, 228, 227, 226,
224, 223, 221, 220, 219, 218, 217, 216, 215, 214,
213, 212, 211, 210, 206, 205, 204, 202, 201, 199,
196, 195, 194, 193, 191, 190, 189, 188, 187, 186,
185, 184, 183, 181, 180, 179, 177, 175, 174, 173,
172, 171, 169, 168, 167, 159, 158, 157, 156, 155,
154, 153, 152, 151, 150, 149, 148, 146, 145, 144,
143, 142, 141, 139, 138, 137, 136, 135, 133, 132,
294, 295, 295, 296, 296, 296, 275, 274, 272, 270,
269, 267, 264, 263, 260, 259, 257, 256, 255, 254,
253, 249, 248, 246, 245, 244, 241, 239, 238, 237,
236, 235, 233, 232, 231, 230, 228, 227, 225, 224,
223, 222, 221, 220, 219, 218, 217, 216, 215, 214,
210, 209, 208, 206, 205, 203, 200, 199, 198, 197,
195, 194, 193, 192, 191, 190, 189, 188, 187, 185,
184, 183, 181, 179, 178, 177, 176, 175, 173, 172,
171, 163, 162, 161, 160, 159, 158, 157, 156, 155,
154, 153, 152, 150, 149, 148, 147, 146, 145, 143,
131, 130, 128, 118, 117, 113, 111, 110, 109, 108,
107, 106, 105, 104, 102, 101, 100, 99, 98, 97,
96, 94, 93, 92, 91, 90, 88, 87, 85, 84,
83, 82, 80, 79, 78, 74, 67, 59, 48, 47,
46, 44, 43, 42, 41, 40, 37, 35, 25, 14,
10, 7, 3, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
142, 141, 140, 139, 137, 136, 135, 134, 132, 121,
120, 116, 114, 113, 112, 111, 110, 109, 108, 107,
105, 104, 103, 102, 101, 100, 99, 97, 96, 95,
94, 93, 91, 90, 88, 87, 86, 85, 83, 82,
80, 76, 68, 59, 48, 47, 46, 44, 43, 42,
41, 40, 37, 35, 25, 22, 14, 10, 7, 3,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
284, 284
288, 288, 288, 288, 288, 288, 288, 288, 288, 288,
288, 288, 288, 288, 288, 288, 288, 288, 288
} ;
/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[97] =
static yyconst flex_int32_t yy_rule_can_match_eol[100] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, };
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
};
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@ -654,7 +665,7 @@ static yyconst flex_int32_t yy_rule_can_match_eol[97] =
*/
#define YY_NO_UNISTD_H 1
#line 658 "lex.sksl.c"
#line 663 "lex.sksl.c"
#define INITIAL 0
@ -918,7 +929,7 @@ YY_DECL
#line 30 "sksl.flex"
#line 922 "lex.sksl.c"
#line 927 "lex.sksl.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@ -945,13 +956,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 285 )
if ( yy_current_state >= 289 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
++yy_cp;
}
while ( yy_current_state != 284 );
while ( yy_current_state != 288 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@ -1201,271 +1212,286 @@ YY_RULE_SETUP
case 44:
YY_RULE_SETUP
#line 118 "sksl.flex"
{ return SkSL::Token::LPAREN; }
{ return SkSL::Token::SECTION; }
YY_BREAK
case 45:
YY_RULE_SETUP
#line 120 "sksl.flex"
{ return SkSL::Token::RPAREN; }
{ return SkSL::Token::LPAREN; }
YY_BREAK
case 46:
YY_RULE_SETUP
#line 122 "sksl.flex"
{ return SkSL::Token::LBRACE; }
{ return SkSL::Token::RPAREN; }
YY_BREAK
case 47:
YY_RULE_SETUP
#line 124 "sksl.flex"
{ return SkSL::Token::RBRACE; }
{ return SkSL::Token::LBRACE; }
YY_BREAK
case 48:
YY_RULE_SETUP
#line 126 "sksl.flex"
{ return SkSL::Token::LBRACKET; }
{ return SkSL::Token::RBRACE; }
YY_BREAK
case 49:
YY_RULE_SETUP
#line 128 "sksl.flex"
{ return SkSL::Token::RBRACKET; }
{ return SkSL::Token::LBRACKET; }
YY_BREAK
case 50:
YY_RULE_SETUP
#line 130 "sksl.flex"
{ return SkSL::Token::DOT; }
{ return SkSL::Token::RBRACKET; }
YY_BREAK
case 51:
YY_RULE_SETUP
#line 132 "sksl.flex"
{ return SkSL::Token::COMMA; }
{ return SkSL::Token::DOT; }
YY_BREAK
case 52:
YY_RULE_SETUP
#line 134 "sksl.flex"
{ return SkSL::Token::PLUSPLUS; }
{ return SkSL::Token::COMMA; }
YY_BREAK
case 53:
YY_RULE_SETUP
#line 136 "sksl.flex"
{ return SkSL::Token::MINUSMINUS; }
{ return SkSL::Token::PLUSPLUS; }
YY_BREAK
case 54:
YY_RULE_SETUP
#line 138 "sksl.flex"
{ return SkSL::Token::PLUS; }
{ return SkSL::Token::MINUSMINUS; }
YY_BREAK
case 55:
YY_RULE_SETUP
#line 140 "sksl.flex"
{ return SkSL::Token::MINUS; }
{ return SkSL::Token::PLUS; }
YY_BREAK
case 56:
YY_RULE_SETUP
#line 142 "sksl.flex"
{ return SkSL::Token::STAR; }
{ return SkSL::Token::MINUS; }
YY_BREAK
case 57:
YY_RULE_SETUP
#line 144 "sksl.flex"
{ return SkSL::Token::SLASH; }
{ return SkSL::Token::STAR; }
YY_BREAK
case 58:
YY_RULE_SETUP
#line 146 "sksl.flex"
{ return SkSL::Token::PERCENT; }
{ return SkSL::Token::SLASH; }
YY_BREAK
case 59:
YY_RULE_SETUP
#line 148 "sksl.flex"
{ return SkSL::Token::SHL; }
{ return SkSL::Token::PERCENT; }
YY_BREAK
case 60:
YY_RULE_SETUP
#line 150 "sksl.flex"
{ return SkSL::Token::SHR; }
{ return SkSL::Token::SHL; }
YY_BREAK
case 61:
YY_RULE_SETUP
#line 152 "sksl.flex"
{ return SkSL::Token::BITWISEOR; }
{ return SkSL::Token::SHR; }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 154 "sksl.flex"
{ return SkSL::Token::BITWISEXOR; }
{ return SkSL::Token::BITWISEOR; }
YY_BREAK
case 63:
YY_RULE_SETUP
#line 156 "sksl.flex"
{ return SkSL::Token::BITWISEAND; }
{ return SkSL::Token::BITWISEXOR; }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 158 "sksl.flex"
{ return SkSL::Token::BITWISENOT; }
{ return SkSL::Token::BITWISEAND; }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 160 "sksl.flex"
{ return SkSL::Token::LOGICALOR; }
{ return SkSL::Token::BITWISENOT; }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 162 "sksl.flex"
{ return SkSL::Token::LOGICALXOR; }
{ return SkSL::Token::LOGICALOR; }
YY_BREAK
case 67:
YY_RULE_SETUP
#line 164 "sksl.flex"
{ return SkSL::Token::LOGICALAND; }
{ return SkSL::Token::LOGICALXOR; }
YY_BREAK
case 68:
YY_RULE_SETUP
#line 166 "sksl.flex"
{ return SkSL::Token::LOGICALNOT; }
{ return SkSL::Token::LOGICALAND; }
YY_BREAK
case 69:
YY_RULE_SETUP
#line 168 "sksl.flex"
{ return SkSL::Token::QUESTION; }
{ return SkSL::Token::LOGICALNOT; }
YY_BREAK
case 70:
YY_RULE_SETUP
#line 170 "sksl.flex"
{ return SkSL::Token::COLON; }
{ return SkSL::Token::QUESTION; }
YY_BREAK
case 71:
YY_RULE_SETUP
#line 172 "sksl.flex"
{ return SkSL::Token::EQ; }
{ return SkSL::Token::COLON; }
YY_BREAK
case 72:
YY_RULE_SETUP
#line 174 "sksl.flex"
{ return SkSL::Token::EQEQ; }
{ return SkSL::Token::EQ; }
YY_BREAK
case 73:
YY_RULE_SETUP
#line 176 "sksl.flex"
{ return SkSL::Token::NEQ; }
{ return SkSL::Token::EQEQ; }
YY_BREAK
case 74:
YY_RULE_SETUP
#line 178 "sksl.flex"
{ return SkSL::Token::GT; }
{ return SkSL::Token::NEQ; }
YY_BREAK
case 75:
YY_RULE_SETUP
#line 180 "sksl.flex"
{ return SkSL::Token::LT; }
{ return SkSL::Token::GT; }
YY_BREAK
case 76:
YY_RULE_SETUP
#line 182 "sksl.flex"
{ return SkSL::Token::GTEQ; }
{ return SkSL::Token::LT; }
YY_BREAK
case 77:
YY_RULE_SETUP
#line 184 "sksl.flex"
{ return SkSL::Token::LTEQ; }
{ return SkSL::Token::GTEQ; }
YY_BREAK
case 78:
YY_RULE_SETUP
#line 186 "sksl.flex"
{ return SkSL::Token::PLUSEQ; }
{ return SkSL::Token::LTEQ; }
YY_BREAK
case 79:
YY_RULE_SETUP
#line 188 "sksl.flex"
{ return SkSL::Token::MINUSEQ; }
{ return SkSL::Token::PLUSEQ; }
YY_BREAK
case 80:
YY_RULE_SETUP
#line 190 "sksl.flex"
{ return SkSL::Token::STAREQ; }
{ return SkSL::Token::MINUSEQ; }
YY_BREAK
case 81:
YY_RULE_SETUP
#line 192 "sksl.flex"
{ return SkSL::Token::SLASHEQ; }
{ return SkSL::Token::STAREQ; }
YY_BREAK
case 82:
YY_RULE_SETUP
#line 194 "sksl.flex"
{ return SkSL::Token::PERCENTEQ; }
{ return SkSL::Token::SLASHEQ; }
YY_BREAK
case 83:
YY_RULE_SETUP
#line 196 "sksl.flex"
{ return SkSL::Token::SHLEQ; }
{ return SkSL::Token::PERCENTEQ; }
YY_BREAK
case 84:
YY_RULE_SETUP
#line 198 "sksl.flex"
{ return SkSL::Token::SHREQ; }
{ return SkSL::Token::SHLEQ; }
YY_BREAK
case 85:
YY_RULE_SETUP
#line 200 "sksl.flex"
{ return SkSL::Token::BITWISEOREQ; }
{ return SkSL::Token::SHREQ; }
YY_BREAK
case 86:
YY_RULE_SETUP
#line 202 "sksl.flex"
{ return SkSL::Token::BITWISEXOREQ; }
{ return SkSL::Token::BITWISEOREQ; }
YY_BREAK
case 87:
YY_RULE_SETUP
#line 204 "sksl.flex"
{ return SkSL::Token::BITWISEANDEQ; }
{ return SkSL::Token::BITWISEXOREQ; }
YY_BREAK
case 88:
YY_RULE_SETUP
#line 206 "sksl.flex"
{ return SkSL::Token::LOGICALOREQ; }
{ return SkSL::Token::BITWISEANDEQ; }
YY_BREAK
case 89:
YY_RULE_SETUP
#line 208 "sksl.flex"
{ return SkSL::Token::LOGICALXOREQ; }
{ return SkSL::Token::LOGICALOREQ; }
YY_BREAK
case 90:
YY_RULE_SETUP
#line 210 "sksl.flex"
{ return SkSL::Token::LOGICALANDEQ; }
{ return SkSL::Token::LOGICALXOREQ; }
YY_BREAK
case 91:
YY_RULE_SETUP
#line 212 "sksl.flex"
{ return SkSL::Token::SEMICOLON; }
{ return SkSL::Token::LOGICALANDEQ; }
YY_BREAK
case 92:
YY_RULE_SETUP
#line 214 "sksl.flex"
/* line comment */
{ return SkSL::Token::SEMICOLON; }
YY_BREAK
case 93:
/* rule 93 can match eol */
YY_RULE_SETUP
#line 216 "sksl.flex"
/* block comment */
{ return SkSL::Token::ARROW; }
YY_BREAK
case 94:
/* rule 94 can match eol */
YY_RULE_SETUP
#line 218 "sksl.flex"
/* whitespace */
{ return SkSL::Token::COLONCOLON; }
YY_BREAK
case 95:
/* rule 95 can match eol */
YY_RULE_SETUP
#line 220 "sksl.flex"
{ return SkSL::Token::INVALID_TOKEN; }
{ return SkSL::Token::WHITESPACE; }
YY_BREAK
case 96:
YY_RULE_SETUP
#line 222 "sksl.flex"
/* line comment */
YY_BREAK
case 97:
/* rule 97 can match eol */
YY_RULE_SETUP
#line 224 "sksl.flex"
/* block comment */
YY_BREAK
case 98:
YY_RULE_SETUP
#line 226 "sksl.flex"
{ return SkSL::Token::INVALID_TOKEN; }
YY_BREAK
case 99:
YY_RULE_SETUP
#line 228 "sksl.flex"
ECHO;
YY_BREAK
#line 1469 "lex.sksl.c"
#line 1489 "lex.sksl.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@ -1761,7 +1787,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 285 )
if ( yy_current_state >= 289 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
@ -1790,11 +1816,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 285 )
if ( yy_current_state >= 289 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_is_jam = (yy_current_state == 284);
yy_is_jam = (yy_current_state == 288);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@ -2646,7 +2672,7 @@ void skslfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
#line 222 "sksl.flex"
#line 228 "sksl.flex"

View File

@ -115,6 +115,8 @@ precision { return SkSL::Token::PRECISION; }
"#"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::DIRECTIVE; }
"@"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::SECTION; }
"(" { return SkSL::Token::LPAREN; }
")" { return SkSL::Token::RPAREN; }
@ -211,12 +213,16 @@ precision { return SkSL::Token::PRECISION; }
";" { return SkSL::Token::SEMICOLON; }
"->" { return SkSL::Token::ARROW; }
"::" { return SkSL::Token::COLONCOLON; }
[ \t\r\n]+ { return SkSL::Token::WHITESPACE; }
"//".* /* line comment */
"/*"([^*]|"*"[^/])*"*/" /* block comment */
[ \t\r\n]+ /* whitespace */
. { return SkSL::Token::INVALID_TOKEN; }
%%

23
src/sksl/sksl_fp.include Normal file
View File

@ -0,0 +1,23 @@
STRINGIFY(
// defines built-in interfaces supported by SkiaSL fragment shaders
layout(builtin=15) in vec4 sk_FragCoord;
layout(builtin=3) float sk_ClipDistance[1];
// 9999 is a temporary value that causes us to ignore these declarations beyond
// adding them to the symbol table. This works fine in GLSL (where they do not
// require any further handling) but will fail in SPIR-V. We'll have a better
// solution for this soon.
layout(builtin=9999) vec4 gl_LastFragData[1];
layout(builtin=9999) vec4 gl_LastFragColor;
layout(builtin=9999) vec4 gl_LastFragColorARM;
layout(builtin=9999) int gl_SampleMaskIn[1];
layout(builtin=9999) out int gl_SampleMask[1];
layout(builtin=9999) vec4 gl_SecondaryFragColorEXT;
layout(builtin=10003) vec4 sk_InColor;
layout(builtin=10004) out vec4 sk_OutColor;
layout(builtin=10005) vec2[] sk_TransformedCoords2D;
layout(builtin=10006) sampler2D[] sk_TextureSamplers;
)

395
tests/SkSLFPTest.cpp Normal file
View File

@ -0,0 +1,395 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLCompiler.h"
#include "Test.h"
#if SK_SUPPORT_GPU
static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
SkSL::Program::Settings settings;
settings.fCaps = &caps;
SkSL::Compiler compiler;
SkSL::StringStream output;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kFragmentProcessor_Kind,
SkString(src),
settings);
if (!program) {
SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
return;
}
REPORTER_ASSERT(r, program);
bool success = compiler.toH(*program, "Test", output);
if (!success) {
SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
}
REPORTER_ASSERT(r, success);
if (success) {
for (const char* expected : expectedH) {
bool found = strstr(output.str().c_str(), expected);
if (!found) {
SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
expected, output.str().c_str());
}
REPORTER_ASSERT(r, found);
}
}
output.reset();
success = compiler.toCPP(*program, "Test", output);
if (!success) {
SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
}
REPORTER_ASSERT(r, success);
if (success) {
for (const char* expected : expectedCPP) {
bool found = strstr(output.str().c_str(), expected);
if (!found) {
SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
expected, output.str().c_str());
}
REPORTER_ASSERT(r, found);
}
}
}
DEF_TEST(SkSLFPHelloWorld, r) {
test(r,
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"/*\n"
" * Copyright 2017 Google Inc.\n"
" *\n"
" * Use of this source code is governed by a BSD-style license that can be\n"
" * found in the LICENSE file.\n"
" */\n"
"\n"
"/*\n"
" * This file was autogenerated from GrTest.fp; do not modify.\n"
" */\n"
"#ifndef GrTest_DEFINED\n"
"#define GrTest_DEFINED\n"
"#include \"GrFragmentProcessor.h\"\n"
"#include \"GrCoordTransform.h\"\n"
"#include \"effects/GrProxyMove.h\"\n"
"class GrTest : public GrFragmentProcessor {\n"
"public:\n"
" static sk_sp<GrFragmentProcessor> Make() {\n"
" return sk_sp<GrFragmentProcessor>(new GrTest());\n"
" }\n"
" const char* name() const override { return \"Test\"; }\n"
"private:\n"
" GrTest()\n"
" : INHERITED(kNone_OptimizationFlags) {\n"
" this->initClassID<GrTest>();\n"
" }\n"
" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
" void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) "
"const override;\n"
" bool onIsEqual(const GrFragmentProcessor&) const override;\n"
" GR_DECLARE_FRAGMENT_PROCESSOR_TEST;\n"
" typedef GrFragmentProcessor INHERITED;\n"
"};\n"
"#endif\n"
},
{
"/*\n"
" * Copyright 2017 Google Inc.\n"
" *\n"
" * Use of this source code is governed by a BSD-style license that can be\n"
" * found in the LICENSE file.\n"
" */\n"
"\n"
"/*\n"
" * This file was autogenerated from GrTest.fp; do not modify.\n"
" */\n"
"#include \"GrTest.h\"\n"
"#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n"
"#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
"#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
"#include \"glsl/GrGLSLProgramBuilder.h\"\n"
"#include \"GrResourceProvider.h\"\n"
"#include \"SkSLCPP.h\"\n"
"#include \"SkSLUtil.h\"\n"
"class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
"public:\n"
" GrGLSLTest() {}\n"
" void emitCode(EmitArgs& args) override {\n"
" GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
" const GrTest& _outer = args.fFp.cast<GrTest>();\n"
" (void) _outer;\n"
" fragBuilder->codeAppendf(\"%s = vec4(1.0);\\n\", args.fOutputColor);\n"
" }\n"
"private:\n"
" void onSetData(const GrGLSLProgramDataManager& pdman, "
"const GrFragmentProcessor& _proc) override {\n"
" }\n"
"};\n"
"GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
" return new GrGLSLTest();\n"
"}\n"
"void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
"GrProcessorKeyBuilder* b) const {\n"
"}\n"
"bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
" const GrTest& that = other.cast<GrTest>();\n"
" (void) that;\n"
" return true;\n"
"}\n"
});
}
DEF_TEST(SkSLFPInput, r) {
test(r,
"in vec2 point;"
"void main() {"
"sk_OutColor = vec4(point, point);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"SkPoint point() const { return fPoint; }",
"static sk_sp<GrFragmentProcessor> Make(SkPoint point) {",
"return sk_sp<GrFragmentProcessor>(new GrTest(point));",
"GrTest(SkPoint point)",
", fPoint(point)"
},
{
"fragBuilder->codeAppendf(\"%s = vec4(vec2(%f, %f), vec2(%f, %f));\\n\", "
"args.fOutputColor, _outer.point().fX, _outer.point().fY, "
"_outer.point().fX, _outer.point().fY);",
"if (fPoint != that.fPoint) return false;"
});
}
DEF_TEST(SkSLFPUniform, r) {
test(r,
"uniform vec4 color;"
"void main() {"
"sk_OutColor = color;"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"static sk_sp<GrFragmentProcessor> Make()"
},
{
"fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, "
"kDefault_GrSLPrecision, \"color\");",
});
}
DEF_TEST(SkSLFPInUniform, r) {
test(r,
"in uniform vec4 color;"
"void main() {"
"sk_OutColor = color;"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"static sk_sp<GrFragmentProcessor> Make(SkRect color) {",
},
{
"fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, "
"kDefault_GrSLPrecision, \"color\");",
"const SkRect colorValue = _outer.color();",
"pdman.set4fv(fColorVar, 4, (float*) &colorValue);"
});
}
DEF_TEST(SkSLFPSections, r) {
test(r,
"@header { header section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"header section class GrTest",
},
{});
test(r,
"@class { class section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"class GrTest : public GrFragmentProcessor {\n"
"public:\n"
" class section"
},
{});
test(r,
"@cpp { cpp section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{"cpp section"});
test(r,
"@constructorParams { int x, float y, std::vector<float> z }"
"in float w;"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"Make(float w, int x, float y, std::vector<float> z )",
"return sk_sp<GrFragmentProcessor>(new GrTest(w, x, y, z));",
"GrTest(float w, int x, float y, std::vector<float> z )",
", fW(w) {"
},
{});
test(r,
"@constructor { constructor section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"private:\n constructor section"
},
{});
test(r,
"@initializers { initializers section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
": INHERITED(kNone_OptimizationFlags)\n , initializers section"
},
{});
test(r,
"float x = 10;"
"@emitCode { fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2); }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"x = 10.0;\n"
" fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2);"
});
test(r,
"@fields { fields section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"GR_DECLARE_FRAGMENT_PROCESSOR_TEST;\n"
" fields section typedef GrFragmentProcessor INHERITED;"
},
{});
test(r,
"@make { make section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"public:\n"
" make section"
},
{});
test(r,
"uniform float calculated;"
"in float provided;"
"@setData(varName) { varName.set1f(calculated, provided * 2); }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"void onSetData(const GrGLSLProgramDataManager& varName, "
"const GrFragmentProcessor& _proc) override {\n",
"UniformHandle& calculated = fCalculatedVar;",
"auto provided = _outer.provided();",
"varName.set1f(calculated, provided * 2);"
});
test(r,
"@test(testDataName) { testDataName section }"
"void main() {"
"sk_OutColor = vec4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"#if GR_TEST_UTILS\n"
"sk_sp<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
" testDataName section }\n"
"#endif"
});
}
DEF_TEST(SkSLFPColorSpaceXform, r) {
test(r,
"in uniform sampler2D image;"
"in uniform colorSpaceXform colorXform;"
"void main() {"
"sk_OutColor = sk_InColor * texture(image, vec2(0, 0), colorXform);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"sk_sp<GrColorSpaceXform> colorXform() const { return fColorXform; }",
"GrTest(sk_sp<GrTextureProxy> image, sk_sp<GrColorSpaceXform> colorXform)",
"this->addTextureSampler(&fImage);",
"sk_sp<GrColorSpaceXform> fColorXform;"
},
{
"fragBuilder->codeAppendf(\"vec4 _tmp0;\\n%s = %s * "
"(_tmp0 = texture(%s, vec2(0.0, 0.0)) , %s != mat4(1.0) ? "
"vec4(clamp((%s * vec4(_tmp0.xyz, 1.0)).xyz, 0.0, _tmp0.w), _tmp0.w) : "
"_tmp0);\\n\", args.fOutputColor, args.fInputColor ? args.fInputColor : "
"\"vec4(1)\", fragBuilder->getProgramBuilder()->samplerVariable("
"args.fTexSamplers[0]).c_str(), fColorSpaceHelper.isValid() ? "
"args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform()) : "
"\"mat4(1.0)\", fColorSpaceHelper.isValid() ? "
"args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform()) : "
"\"mat4(1.0)\");"
});
}
DEF_TEST(SkSLFPTransformedCoords, r) {
test(r,
"void main() {"
"sk_OutColor = vec4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"SkSL::String sk_TransformedCoords2D_0 = "
"fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
"fragBuilder->codeAppendf(\"%s = vec4(%s, %s);\\n\", args.fOutputColor, "
"sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
});
}
DEF_TEST(SkSLFPLayoutWhen, r) {
test(r,
"layout(when=someExpression(someOtherExpression())) uniform float sometimes;"
"void main() {"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"if (someExpression(someOtherExpression())) {\n"
" fSometimesVar = args.fUniformHandler->addUniform"
});
}
#endif

View File

@ -487,7 +487,8 @@ DEF_TEST(SkSLDerivatives, r) {
"void main() { sk_FragColor.r = 1; }",
*SkSL::ShaderCapsFactory::ShaderDerivativeExtensionString(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"precision highp float;\n"
"out mediump vec4 sk_FragColor;\n"
"void main() {\n"
" sk_FragColor.x = 1.0;\n"
"}\n");
@ -496,7 +497,8 @@ DEF_TEST(SkSLDerivatives, r) {
*SkSL::ShaderCapsFactory::ShaderDerivativeExtensionString(),
"#version 400\n"
"#extension GL_OES_standard_derivatives : require\n"
"out vec4 sk_FragColor;\n"
"precision highp float;\n"
"out mediump vec4 sk_FragColor;\n"
"void main() {\n"
" sk_FragColor.x = dFdx(1.0);\n"
"}\n");