зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 12 changesets (bug 1612941) for causing bustages CLOSED TREE
Backed out changeset 29f9f745ff65 (bug 1612941) Backed out changeset d92e03315f8d (bug 1612941) Backed out changeset 9b1360daa75a (bug 1612941) Backed out changeset ad7f43d72b08 (bug 1612941) Backed out changeset 30b28118362a (bug 1612941) Backed out changeset 76f80dce8875 (bug 1612941) Backed out changeset 375896f494ae (bug 1612941) Backed out changeset bd8ba66dc2ac (bug 1612941) Backed out changeset 54ec5a6e8e45 (bug 1612941) Backed out changeset 419105739e53 (bug 1612941) Backed out changeset c198dedeaa1b (bug 1612941) Backed out changeset 87ddcdfc5fcf (bug 1612941)
This commit is contained in:
Родитель
9bf1ae5b21
Коммит
0830b5e7f8
|
@ -1715,9 +1715,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.10.0"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77b1fd76468fff720bad31016688b805c6442ebf2d7c29123e10e4984aa61986"
|
||||
checksum = "332d1f4e6c6181ed07178f84a552b2387d43ecf6821a86c22cfb3883ea3fb1b9"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
]
|
||||
|
@ -1758,22 +1758,6 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "glsl"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "766443890761b3c4edcce86cafaac97971b200662fbdd0446eb7c6b99b4401ea"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glsl-to-cxx"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glsl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.1.2"
|
||||
|
@ -4153,15 +4137,6 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c666f0fed8e1e20e057af770af9077d72f3d5a33157b8537c1475dd8ffd6d32b"
|
||||
|
||||
[[package]]
|
||||
name = "swgl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"gleam",
|
||||
"glsl-to-cxx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.5"
|
||||
|
@ -4870,7 +4845,6 @@ dependencies = [
|
|||
"nsstring",
|
||||
"num_cpus",
|
||||
"rayon",
|
||||
"swgl",
|
||||
"thin-vec",
|
||||
"thread_profiler",
|
||||
"uuid",
|
||||
|
|
|
@ -49,7 +49,6 @@ class gfxVarReceiver;
|
|||
_(WebRenderMaxPartialPresentRects, int32_t, 0) \
|
||||
_(WebRenderDebugFlags, int32_t, 0) \
|
||||
_(WebRenderBatchingLookback, int32_t, 10) \
|
||||
_(UseSoftwareWebRender, bool, false) \
|
||||
_(ScreenDepth, int32_t, 0) \
|
||||
_(GREDirectory, nsString, nsString()) \
|
||||
_(ProfDirectory, nsString, nsString()) \
|
||||
|
|
|
@ -2950,10 +2950,6 @@ void gfxPlatform::InitWebRenderConfig() {
|
|||
gfxConfig::IsEnabled(Feature::WEBRENDER));
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("gfx.webrender.software", false)) {
|
||||
gfxVars::SetUseSoftwareWebRender(gfxConfig::IsEnabled(Feature::WEBRENDER));
|
||||
}
|
||||
|
||||
// gfxFeature is not usable in the GPU process, so we use gfxVars to transmit
|
||||
// this feature
|
||||
if (gfxConfig::IsEnabled(Feature::WEBRENDER)) {
|
||||
|
|
|
@ -13,14 +13,13 @@ num_cpus = "1.7.0"
|
|||
thread_profiler = "0.1.1"
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
app_units = "0.7"
|
||||
gleam = "0.10.0"
|
||||
gleam = "0.9.2"
|
||||
log = "0.4"
|
||||
nsstring = { path = "../../xpcom/rust/nsstring" }
|
||||
bincode = "1.0"
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
fxhash = "0.2.1"
|
||||
thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
|
||||
swgl = { path = "../wr/swgl" }
|
||||
|
||||
[dependencies.webrender]
|
||||
path = "../wr/webrender"
|
||||
|
|
|
@ -87,11 +87,6 @@ void wr_compositor_unbind(void* aCompositor) {
|
|||
compositor->Unbind();
|
||||
}
|
||||
|
||||
void wr_compositor_deinit(void* aCompositor) {
|
||||
RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
|
||||
compositor->DeInit();
|
||||
}
|
||||
|
||||
/* static */
|
||||
UniquePtr<RenderCompositor> RenderCompositor::Create(
|
||||
RefPtr<widget::CompositorWidget>&& aWidget) {
|
||||
|
|
|
@ -100,7 +100,6 @@ class RenderCompositor {
|
|||
virtual void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
wr::DeviceIntRect aClipRect) {}
|
||||
virtual void EnableNativeCompositor(bool aEnable) {}
|
||||
virtual void DeInit() {}
|
||||
virtual CompositorCapabilities GetCompositorCapabilities() = 0;
|
||||
|
||||
// Interface for partial present
|
||||
|
|
|
@ -754,8 +754,7 @@ void RenderThread::InitDeviceTask() {
|
|||
MOZ_ASSERT(!mSharedGL);
|
||||
|
||||
mSharedGL = CreateGLContext();
|
||||
if (gfx::gfxVars::UseWebRenderProgramBinaryDisk() &&
|
||||
!gfx::gfxVars::UseSoftwareWebRender()) {
|
||||
if (gfx::gfxVars::UseWebRenderProgramBinaryDisk()) {
|
||||
mProgramCache = MakeUnique<WebRenderProgramCache>(ThreadPool().Raw());
|
||||
}
|
||||
// Query the shared GL context to force the
|
||||
|
@ -843,7 +842,7 @@ gl::GLContext* RenderThread::SharedGL() {
|
|||
mSharedGL = CreateGLContext();
|
||||
mShaders = nullptr;
|
||||
}
|
||||
if (mSharedGL && !mShaders && !gfx::gfxVars::UseSoftwareWebRender()) {
|
||||
if (mSharedGL && !mShaders) {
|
||||
mShaders = MakeUnique<WebRenderShaders>(mSharedGL, mProgramCache.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -48,14 +48,12 @@ void wr_renderer_unlock_external_image(void* aObj, wr::ExternalImageId aId,
|
|||
RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
|
||||
UniquePtr<RenderCompositor> aCompositor,
|
||||
wr::WindowId aWindowId, wr::Renderer* aRenderer,
|
||||
layers::CompositorBridgeParent* aBridge,
|
||||
void* aSoftwareContext)
|
||||
layers::CompositorBridgeParent* aBridge)
|
||||
: mThread(aThread),
|
||||
mCompositor(std::move(aCompositor)),
|
||||
mRenderer(aRenderer),
|
||||
mBridge(aBridge),
|
||||
mWindowId(aWindowId),
|
||||
mSoftwareContext(aSoftwareContext),
|
||||
mDisableNativeCompositor(false) {
|
||||
MOZ_ASSERT(mThread);
|
||||
MOZ_ASSERT(mCompositor);
|
||||
|
@ -66,19 +64,13 @@ RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
|
|||
|
||||
RendererOGL::~RendererOGL() {
|
||||
MOZ_COUNT_DTOR(RendererOGL);
|
||||
if (mSoftwareContext) {
|
||||
wr_swgl_make_current(mSoftwareContext);
|
||||
}
|
||||
if (!mCompositor->MakeCurrent()) {
|
||||
gfxCriticalNote
|
||||
<< "Failed to make render context current during destroying.";
|
||||
// Leak resources!
|
||||
} else {
|
||||
wr_renderer_delete(mRenderer);
|
||||
}
|
||||
if (mSoftwareContext) {
|
||||
wr_swgl_destroy_context(mSoftwareContext);
|
||||
return;
|
||||
}
|
||||
wr_renderer_delete(mRenderer);
|
||||
}
|
||||
|
||||
wr::WrExternalImageHandler RendererOGL::GetExternalImageHandler() {
|
||||
|
@ -131,13 +123,6 @@ RenderedFrameId RendererOGL::UpdateAndRender(
|
|||
return RenderedFrameId();
|
||||
}
|
||||
|
||||
auto size = mCompositor->GetBufferSize();
|
||||
|
||||
if (mSoftwareContext) {
|
||||
wr_swgl_make_current(mSoftwareContext);
|
||||
wr_swgl_init_default_framebuffer(mSoftwareContext, size.width, size.height);
|
||||
}
|
||||
|
||||
wr_renderer_update(mRenderer);
|
||||
|
||||
bool fullRender = mCompositor->RequestFullRender();
|
||||
|
@ -150,6 +135,8 @@ RenderedFrameId RendererOGL::UpdateAndRender(
|
|||
wr_renderer_force_redraw(mRenderer);
|
||||
}
|
||||
|
||||
auto size = mCompositor->GetBufferSize();
|
||||
|
||||
nsTArray<DeviceIntRect> dirtyRects;
|
||||
if (!wr_renderer_render(mRenderer, size.width, size.height, aHadSlowFrame,
|
||||
aOutStats, &dirtyRects)) {
|
||||
|
|
|
@ -84,8 +84,7 @@ class RendererOGL {
|
|||
/// This can be called on the render thread only.
|
||||
RendererOGL(RefPtr<RenderThread>&& aThread,
|
||||
UniquePtr<RenderCompositor> aCompositor, wr::WindowId aWindowId,
|
||||
wr::Renderer* aRenderer, layers::CompositorBridgeParent* aBridge,
|
||||
void* aSoftwareContext = nullptr);
|
||||
wr::Renderer* aRenderer, layers::CompositorBridgeParent* aBridge);
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
void Pause();
|
||||
|
@ -118,7 +117,6 @@ class RendererOGL {
|
|||
wr::Renderer* mRenderer;
|
||||
layers::CompositorBridgeParent* mBridge;
|
||||
wr::WindowId mWindowId;
|
||||
void* mSoftwareContext;
|
||||
TimeStamp mFrameStartTime;
|
||||
|
||||
bool mDisableNativeCompositor;
|
||||
|
|
|
@ -70,11 +70,6 @@ class NewRenderer : public RendererEvent {
|
|||
*mUseDComp = compositor->UseDComp();
|
||||
*mUseTripleBuffering = compositor->UseTripleBuffering();
|
||||
|
||||
void* swCtx = nullptr;
|
||||
if (gfx::gfxVars::UseSoftwareWebRender()) {
|
||||
swCtx = wr_swgl_create_context();
|
||||
}
|
||||
|
||||
// Only allow the panic on GL error functionality in nightly builds,
|
||||
// since it (deliberately) crashes the GPU process if any GL call
|
||||
// returns an error code.
|
||||
|
@ -103,7 +98,7 @@ class NewRenderer : public RendererEvent {
|
|||
#else
|
||||
false,
|
||||
#endif
|
||||
swCtx, compositor->gl(), compositor->SurfaceOriginIsTopLeft(),
|
||||
compositor->gl(), compositor->SurfaceOriginIsTopLeft(),
|
||||
aRenderThread.GetProgramCache()
|
||||
? aRenderThread.GetProgramCache()->Raw()
|
||||
: nullptr,
|
||||
|
@ -121,9 +116,6 @@ class NewRenderer : public RendererEvent {
|
|||
StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(),
|
||||
panic_on_gl_error)) {
|
||||
// wr_window_new puts a message into gfxCriticalNote if it returns false
|
||||
if (swCtx) {
|
||||
wr_swgl_destroy_context(swCtx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(wrRenderer);
|
||||
|
@ -131,7 +123,7 @@ class NewRenderer : public RendererEvent {
|
|||
RefPtr<RenderThread> thread = &aRenderThread;
|
||||
auto renderer =
|
||||
MakeUnique<RendererOGL>(std::move(thread), std::move(compositor),
|
||||
aWindowId, wrRenderer, mBridge, swCtx);
|
||||
aWindowId, wrRenderer, mBridge);
|
||||
if (wrRenderer && renderer) {
|
||||
wr::WrExternalImageHandler handler = renderer->GetExternalImageHandler();
|
||||
wr_renderer_set_external_image_handler(wrRenderer, &handler);
|
||||
|
|
|
@ -31,7 +31,6 @@ use nsstring::nsAString;
|
|||
use num_cpus;
|
||||
use program_cache::{remove_disk_cache, WrProgramCache};
|
||||
use rayon;
|
||||
use swgl_bindings::SwCompositor;
|
||||
use thread_profiler::register_thread_with_profiler;
|
||||
use webrender::{
|
||||
api::*, api::units::*, ApiRecordingReceiver, AsyncPropertySampler, AsyncScreenshotHandle,
|
||||
|
@ -1217,7 +1216,6 @@ extern "C" {
|
|||
compositor: *mut c_void,
|
||||
enable: bool,
|
||||
);
|
||||
fn wr_compositor_deinit(compositor: *mut c_void);
|
||||
fn wr_compositor_get_capabilities(
|
||||
compositor: *mut c_void,
|
||||
) -> CompositorCapabilities;
|
||||
|
@ -1312,12 +1310,6 @@ impl Compositor for WrCompositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn deinit(&mut self) {
|
||||
unsafe {
|
||||
wr_compositor_deinit(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> CompositorCapabilities {
|
||||
unsafe {
|
||||
wr_compositor_get_capabilities(self.0)
|
||||
|
@ -1336,7 +1328,6 @@ pub extern "C" fn wr_window_new(
|
|||
allow_texture_swizzling: bool,
|
||||
enable_picture_caching: bool,
|
||||
start_debug_server: bool,
|
||||
swgl_context: *mut c_void,
|
||||
gl_context: *mut c_void,
|
||||
surface_origin_is_top_left: bool,
|
||||
program_cache: Option<&mut WrProgramCache>,
|
||||
|
@ -1364,20 +1355,12 @@ pub extern "C" fn wr_window_new(
|
|||
None
|
||||
};
|
||||
|
||||
let native_gl = if unsafe { is_glcontext_gles(gl_context) } {
|
||||
unsafe { gl::GlesFns::load_with(|symbol| get_proc_address(gl_context, symbol)) }
|
||||
let gl;
|
||||
if unsafe { is_glcontext_gles(gl_context) } {
|
||||
gl = unsafe { gl::GlesFns::load_with(|symbol| get_proc_address(gl_context, symbol)) };
|
||||
} else {
|
||||
unsafe { gl::GlFns::load_with(|symbol| get_proc_address(gl_context, symbol)) }
|
||||
};
|
||||
|
||||
let software = swgl_context != ptr::null_mut();
|
||||
let (gl, sw_gl) = if software {
|
||||
let ctx = swgl::Context::from(swgl_context);
|
||||
ctx.make_current();
|
||||
(Rc::new(ctx.clone()) as Rc<dyn gl::Gl>, Some(ctx))
|
||||
} else {
|
||||
(native_gl.clone(), None)
|
||||
};
|
||||
gl = unsafe { gl::GlFns::load_with(|symbol| get_proc_address(gl_context, symbol)) };
|
||||
}
|
||||
|
||||
let version = gl.get_string(gl::VERSION);
|
||||
|
||||
|
@ -1416,17 +1399,7 @@ pub extern "C" fn wr_window_new(
|
|||
ColorF::new(0.0, 0.0, 0.0, 0.0)
|
||||
};
|
||||
|
||||
let compositor_config = if software {
|
||||
let wr_compositor: Option<Box<dyn Compositor>> = if compositor != ptr::null_mut() {
|
||||
Some(Box::new(WrCompositor(compositor)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
CompositorConfig::Native {
|
||||
max_update_rects: 1,
|
||||
compositor: Box::new(SwCompositor::new(sw_gl.unwrap(), Some(native_gl), wr_compositor))
|
||||
}
|
||||
} else if compositor != ptr::null_mut() {
|
||||
let compositor_config = if compositor != ptr::null_mut() {
|
||||
CompositorConfig::Native {
|
||||
max_update_rects,
|
||||
compositor: Box::new(WrCompositor(compositor)),
|
||||
|
@ -1475,7 +1448,7 @@ pub extern "C" fn wr_window_new(
|
|||
enable_picture_caching,
|
||||
allow_pixel_local_storage_support: false,
|
||||
start_debug_server,
|
||||
surface_origin_is_top_left: !software && surface_origin_is_top_left,
|
||||
surface_origin_is_top_left,
|
||||
compositor_config,
|
||||
enable_gpu_markers,
|
||||
panic_on_gl_error,
|
||||
|
|
|
@ -12,7 +12,6 @@ extern crate gleam;
|
|||
extern crate nsstring;
|
||||
extern crate num_cpus;
|
||||
extern crate rayon;
|
||||
extern crate swgl;
|
||||
extern crate thin_vec;
|
||||
extern crate thread_profiler;
|
||||
extern crate uuid;
|
||||
|
@ -38,5 +37,3 @@ mod program_cache;
|
|||
#[allow(non_snake_case)]
|
||||
pub mod bindings;
|
||||
pub mod moz2d_renderer;
|
||||
mod swgl_bindings;
|
||||
|
||||
|
|
|
@ -1,610 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use gleam::{gl, gl::Gl};
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use webrender::{api::units::*, Compositor, CompositorCapabilities, NativeSurfaceId, NativeSurfaceInfo, NativeTileId};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_swgl_create_context() -> *mut c_void {
|
||||
swgl::Context::create().into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_swgl_destroy_context(ctx: *mut c_void) {
|
||||
swgl::Context::from(ctx).destroy();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_swgl_make_current(ctx: *mut c_void) {
|
||||
swgl::Context::from(ctx).make_current();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_swgl_init_default_framebuffer(ctx: *mut c_void, width: i32, height: i32) {
|
||||
swgl::Context::from(ctx).init_default_framebuffer(width, height);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SwTile {
|
||||
x: i32,
|
||||
y: i32,
|
||||
fbo_id: u32,
|
||||
color_id: u32,
|
||||
depth_id: u32,
|
||||
tex_id: u32,
|
||||
pbo_id: u32,
|
||||
dirty_rect: DeviceIntRect,
|
||||
valid_rect: DeviceIntRect,
|
||||
}
|
||||
|
||||
pub struct SwSurface {
|
||||
tile_size: DeviceIntSize,
|
||||
is_opaque: bool,
|
||||
tiles: Vec<SwTile>,
|
||||
}
|
||||
|
||||
struct DrawTileHelper {
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
prog: u32,
|
||||
quad_vbo: u32,
|
||||
quad_vao: u32,
|
||||
dest_matrix_loc: i32,
|
||||
tex_matrix_loc: i32,
|
||||
}
|
||||
|
||||
impl DrawTileHelper {
|
||||
fn new(gl: Rc<dyn gl::Gl>) -> Self {
|
||||
let quad_vbo = gl.gen_buffers(1)[0];
|
||||
gl.bind_buffer(gl::ARRAY_BUFFER, quad_vbo);
|
||||
let quad_data: [f32; 8] = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
|
||||
gl::buffer_data(&*gl, gl::ARRAY_BUFFER, &quad_data, gl::STATIC_DRAW);
|
||||
|
||||
let quad_vao = gl.gen_vertex_arrays(1)[0];
|
||||
gl.bind_vertex_array(quad_vao);
|
||||
gl.enable_vertex_attrib_array(0);
|
||||
gl.vertex_attrib_pointer(0, 2, gl::FLOAT, false, 0, 0);
|
||||
gl.bind_vertex_array(0);
|
||||
|
||||
let version = match gl.get_type() {
|
||||
gl::GlType::Gl => "#version 150",
|
||||
gl::GlType::Gles => "#version 300 es",
|
||||
};
|
||||
let vert_source = "
|
||||
in vec2 aVert;
|
||||
uniform mat3 uDestMatrix;
|
||||
uniform mat3 uTexMatrix;
|
||||
out vec2 vTexCoord;
|
||||
void main(void) {
|
||||
gl_Position = vec4((uDestMatrix * vec3(aVert, 1.0)).xy, 0.0, 1.0);
|
||||
vTexCoord = (uTexMatrix * vec3(aVert, 1.0)).xy;
|
||||
}
|
||||
";
|
||||
let vs = gl.create_shader(gl::VERTEX_SHADER);
|
||||
gl.shader_source(vs, &[version.as_bytes(), vert_source.as_bytes()]);
|
||||
gl.compile_shader(vs);
|
||||
let frag_source = "
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#endif
|
||||
in vec2 vTexCoord;
|
||||
out vec4 oFragColor;
|
||||
uniform sampler2D uTex;
|
||||
void main(void) {
|
||||
oFragColor = texture(uTex, vTexCoord);
|
||||
}
|
||||
";
|
||||
let fs = gl.create_shader(gl::FRAGMENT_SHADER);
|
||||
gl.shader_source(fs, &[version.as_bytes(), frag_source.as_bytes()]);
|
||||
gl.compile_shader(fs);
|
||||
|
||||
let prog = gl.create_program();
|
||||
gl.attach_shader(prog, vs);
|
||||
gl.attach_shader(prog, fs);
|
||||
gl.bind_attrib_location(prog, 0, "aVert");
|
||||
gl.link_program(prog);
|
||||
|
||||
let mut status = [0];
|
||||
unsafe {
|
||||
gl.get_program_iv(prog, gl::LINK_STATUS, &mut status);
|
||||
}
|
||||
assert!(status[0] != 0);
|
||||
|
||||
//println!("vert: {}", gl.get_shader_info_log(vs));
|
||||
//println!("frag: {}", gl.get_shader_info_log(fs));
|
||||
//println!("status: {}, {}", status[0], gl.get_program_info_log(prog));
|
||||
|
||||
gl.use_program(prog);
|
||||
let dest_matrix_loc = gl.get_uniform_location(prog, "uDestMatrix");
|
||||
assert!(dest_matrix_loc != -1);
|
||||
let tex_matrix_loc = gl.get_uniform_location(prog, "uTexMatrix");
|
||||
assert!(tex_matrix_loc != -1);
|
||||
let tex_loc = gl.get_uniform_location(prog, "uTex");
|
||||
assert!(tex_loc != -1);
|
||||
gl.uniform_1i(tex_loc, 0);
|
||||
gl.use_program(0);
|
||||
|
||||
gl.delete_shader(vs);
|
||||
gl.delete_shader(fs);
|
||||
|
||||
DrawTileHelper {
|
||||
gl,
|
||||
prog,
|
||||
quad_vao,
|
||||
quad_vbo,
|
||||
dest_matrix_loc,
|
||||
tex_matrix_loc,
|
||||
}
|
||||
}
|
||||
|
||||
fn deinit(&self) {
|
||||
self.gl.delete_program(self.prog);
|
||||
self.gl.delete_vertex_arrays(&[self.quad_vao]);
|
||||
self.gl.delete_buffers(&[self.quad_vbo]);
|
||||
}
|
||||
|
||||
fn enable(&self, viewport: &DeviceIntRect) {
|
||||
self.gl.viewport(
|
||||
viewport.origin.x,
|
||||
viewport.origin.y,
|
||||
viewport.size.width,
|
||||
viewport.size.height,
|
||||
);
|
||||
self.gl.bind_vertex_array(self.quad_vao);
|
||||
self.gl.use_program(self.prog);
|
||||
self.gl.active_texture(gl::TEXTURE0);
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
viewport: &DeviceIntRect,
|
||||
dest: &DeviceIntRect,
|
||||
src: &DeviceIntRect,
|
||||
surface: &SwSurface,
|
||||
tile: &SwTile,
|
||||
) {
|
||||
let dx = dest.origin.x as f32 / viewport.size.width as f32;
|
||||
let dy = dest.origin.y as f32 / viewport.size.height as f32;
|
||||
let dw = dest.size.width as f32 / viewport.size.width as f32;
|
||||
let dh = dest.size.height as f32 / viewport.size.height as f32;
|
||||
self.gl.uniform_matrix_3fv(
|
||||
self.dest_matrix_loc,
|
||||
false,
|
||||
&[
|
||||
2.0 * dw,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
-2.0 * dh,
|
||||
0.0,
|
||||
-1.0 + 2.0 * dx,
|
||||
1.0 - 2.0 * dy,
|
||||
1.0,
|
||||
],
|
||||
);
|
||||
let sx = src.origin.x as f32 / surface.tile_size.width as f32;
|
||||
let sy = src.origin.y as f32 / surface.tile_size.height as f32;
|
||||
let sw = src.size.width as f32 / surface.tile_size.width as f32;
|
||||
let sh = src.size.height as f32 / surface.tile_size.height as f32;
|
||||
self.gl
|
||||
.uniform_matrix_3fv(self.tex_matrix_loc, false, &[sw, 0.0, 0.0, 0.0, sh, 0.0, sx, sy, 1.0]);
|
||||
self.gl.bind_texture(gl::TEXTURE_2D, tile.tex_id);
|
||||
self.gl.draw_arrays(gl::TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
fn disable(&self) {
|
||||
self.gl.use_program(0);
|
||||
self.gl.bind_vertex_array(0);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SwCompositor {
|
||||
gl: swgl::Context,
|
||||
native_gl: Option<Rc<dyn gl::Gl>>,
|
||||
compositor: Option<Box<dyn Compositor>>,
|
||||
surfaces: HashMap<NativeSurfaceId, SwSurface>,
|
||||
frame_surfaces: Vec<(NativeSurfaceId, DeviceIntPoint, DeviceIntRect)>,
|
||||
cur_tile: NativeTileId,
|
||||
draw_tile: Option<DrawTileHelper>,
|
||||
}
|
||||
|
||||
impl SwCompositor {
|
||||
pub fn new(gl: swgl::Context, native_gl: Option<Rc<dyn gl::Gl>>, compositor: Option<Box<dyn Compositor>>) -> Self {
|
||||
SwCompositor {
|
||||
gl,
|
||||
compositor,
|
||||
surfaces: HashMap::new(),
|
||||
frame_surfaces: Vec::new(),
|
||||
cur_tile: NativeTileId {
|
||||
surface_id: NativeSurfaceId(0),
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
draw_tile: native_gl.as_ref().map(|gl| DrawTileHelper::new(gl.clone())),
|
||||
native_gl,
|
||||
}
|
||||
}
|
||||
|
||||
fn deinit_shader(&mut self) {
|
||||
if let Some(draw_tile) = &self.draw_tile {
|
||||
draw_tile.deinit();
|
||||
}
|
||||
self.draw_tile = None;
|
||||
}
|
||||
|
||||
fn deinit_tile(&self, tile: &SwTile) {
|
||||
self.gl.delete_framebuffers(&[tile.fbo_id]);
|
||||
self.gl.delete_textures(&[tile.color_id]);
|
||||
self.gl.delete_textures(&[tile.depth_id]);
|
||||
if let Some(native_gl) = &self.native_gl {
|
||||
native_gl.delete_textures(&[tile.tex_id]);
|
||||
native_gl.delete_buffers(&[tile.pbo_id]);
|
||||
}
|
||||
}
|
||||
|
||||
fn deinit_surface(&self, surface: &SwSurface) {
|
||||
for tile in &surface.tiles {
|
||||
self.deinit_tile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Compositor for SwCompositor {
|
||||
fn create_surface(
|
||||
&mut self,
|
||||
id: NativeSurfaceId,
|
||||
virtual_offset: DeviceIntPoint,
|
||||
tile_size: DeviceIntSize,
|
||||
is_opaque: bool,
|
||||
) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.create_surface(id, virtual_offset, tile_size, is_opaque);
|
||||
}
|
||||
self.surfaces.insert(
|
||||
id,
|
||||
SwSurface {
|
||||
tile_size,
|
||||
is_opaque,
|
||||
tiles: Vec::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn destroy_surface(&mut self, id: NativeSurfaceId) {
|
||||
if let Some(surface) = self.surfaces.remove(&id) {
|
||||
self.deinit_surface(&surface);
|
||||
}
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.destroy_surface(id);
|
||||
}
|
||||
}
|
||||
|
||||
fn deinit(&mut self) {
|
||||
for surface in self.surfaces.values() {
|
||||
self.deinit_surface(surface);
|
||||
}
|
||||
|
||||
self.deinit_shader();
|
||||
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
fn create_tile(&mut self, id: NativeTileId) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.create_tile(id);
|
||||
}
|
||||
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
|
||||
let texs = self.gl.gen_textures(2);
|
||||
let color_id = texs[0];
|
||||
self.gl.set_texture_buffer(
|
||||
color_id,
|
||||
gl::RGBA8,
|
||||
surface.tile_size.width,
|
||||
surface.tile_size.height,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
let depth_id = texs[1];
|
||||
self.gl.set_texture_buffer(
|
||||
depth_id,
|
||||
gl::DEPTH_COMPONENT16,
|
||||
surface.tile_size.width,
|
||||
surface.tile_size.height,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
let fbo_id = self.gl.gen_framebuffers(1)[0];
|
||||
self.gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, fbo_id);
|
||||
self.gl
|
||||
.framebuffer_texture_2d(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, color_id, 0);
|
||||
self.gl
|
||||
.framebuffer_texture_2d(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, gl::TEXTURE_2D, depth_id, 0);
|
||||
self.gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
let mut tex_id = 0;
|
||||
let mut pbo_id = 0;
|
||||
if let Some(native_gl) = &self.native_gl {
|
||||
tex_id = native_gl.gen_textures(1)[0];
|
||||
native_gl.bind_texture(gl::TEXTURE_2D, tex_id);
|
||||
native_gl.tex_image_2d(
|
||||
gl::TEXTURE_2D,
|
||||
0,
|
||||
gl::RGBA8 as gl::GLint,
|
||||
surface.tile_size.width,
|
||||
surface.tile_size.height,
|
||||
0,
|
||||
gl::RGBA,
|
||||
gl::UNSIGNED_BYTE,
|
||||
None,
|
||||
);
|
||||
native_gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as gl::GLint);
|
||||
native_gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as gl::GLint);
|
||||
native_gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as gl::GLint);
|
||||
native_gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as gl::GLint);
|
||||
native_gl.bind_texture(gl::TEXTURE_2D, 0);
|
||||
|
||||
pbo_id = native_gl.gen_buffers(1)[0];
|
||||
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, pbo_id);
|
||||
native_gl.buffer_data_untyped(
|
||||
gl::PIXEL_UNPACK_BUFFER,
|
||||
surface.tile_size.width as isize * surface.tile_size.height as isize * 4,
|
||||
ptr::null(),
|
||||
gl::DYNAMIC_DRAW,
|
||||
);
|
||||
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
surface.tiles.push(SwTile {
|
||||
x: id.x,
|
||||
y: id.y,
|
||||
fbo_id,
|
||||
color_id,
|
||||
depth_id,
|
||||
tex_id,
|
||||
pbo_id,
|
||||
dirty_rect: DeviceIntRect::zero(),
|
||||
valid_rect: DeviceIntRect::zero(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_tile(&mut self, id: NativeTileId) {
|
||||
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
|
||||
if let Some(idx) = surface.tiles.iter().position(|t| t.x == id.x && t.y == id.y) {
|
||||
let tile = surface.tiles.remove(idx);
|
||||
self.deinit_tile(&tile);
|
||||
}
|
||||
}
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.destroy_tile(id);
|
||||
}
|
||||
}
|
||||
|
||||
fn bind(&mut self, id: NativeTileId, dirty_rect: DeviceIntRect, valid_rect: DeviceIntRect) -> NativeSurfaceInfo {
|
||||
let mut surface_info = NativeSurfaceInfo {
|
||||
origin: DeviceIntPoint::zero(),
|
||||
fbo_id: 0,
|
||||
};
|
||||
|
||||
self.cur_tile = id;
|
||||
|
||||
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
|
||||
if let Some(tile) = surface.tiles.iter_mut().find(|t| t.x == id.x && t.y == id.y) {
|
||||
tile.dirty_rect = dirty_rect;
|
||||
tile.valid_rect = valid_rect;
|
||||
if valid_rect.is_empty() {
|
||||
return surface_info;
|
||||
}
|
||||
|
||||
let mut buf = ptr::null_mut();
|
||||
if let Some(native_gl) = &self.native_gl {
|
||||
if tile.pbo_id != 0 {
|
||||
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, tile.pbo_id);
|
||||
buf = native_gl.map_buffer_range(
|
||||
gl::PIXEL_UNPACK_BUFFER,
|
||||
0,
|
||||
valid_rect.size.area() as isize * 4,
|
||||
gl::MAP_WRITE_BIT | gl::MAP_INVALIDATE_BUFFER_BIT,
|
||||
); // | gl::MAP_UNSYNCHRONIZED_BIT);
|
||||
if buf == ptr::null_mut() {
|
||||
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, 0);
|
||||
native_gl.delete_buffers(&[tile.pbo_id]);
|
||||
tile.pbo_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.gl.set_texture_buffer(
|
||||
tile.color_id,
|
||||
gl::RGBA8,
|
||||
valid_rect.size.width,
|
||||
valid_rect.size.height,
|
||||
buf,
|
||||
surface.tile_size.width,
|
||||
surface.tile_size.height,
|
||||
);
|
||||
self.gl.set_texture_buffer(
|
||||
tile.depth_id,
|
||||
gl::DEPTH_COMPONENT16,
|
||||
valid_rect.size.width,
|
||||
valid_rect.size.height,
|
||||
ptr::null_mut(),
|
||||
surface.tile_size.width,
|
||||
surface.tile_size.height,
|
||||
);
|
||||
surface_info.fbo_id = tile.fbo_id;
|
||||
surface_info.origin -= valid_rect.origin.to_vector();
|
||||
}
|
||||
}
|
||||
|
||||
surface_info
|
||||
}
|
||||
|
||||
fn unbind(&mut self) {
|
||||
let native_gl = match &self.native_gl {
|
||||
Some(native_gl) => native_gl,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let id = self.cur_tile;
|
||||
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
|
||||
if let Some(tile) = surface.tiles.iter().find(|t| t.x == id.x && t.y == id.y) {
|
||||
if tile.valid_rect.is_empty() {
|
||||
return;
|
||||
}
|
||||
let (swbuf, w, _) = self.gl.get_color_buffer(tile.fbo_id, true);
|
||||
let buf = if tile.pbo_id != 0 {
|
||||
native_gl.unmap_buffer(gl::PIXEL_UNPACK_BUFFER);
|
||||
0 as *mut c_void
|
||||
} else {
|
||||
swbuf
|
||||
};
|
||||
let dirty = tile.dirty_rect;
|
||||
let src = unsafe {
|
||||
(buf as *mut u32).offset(
|
||||
(dirty.origin.y - tile.valid_rect.origin.y) as isize * w as isize
|
||||
+ (dirty.origin.x - tile.valid_rect.origin.x) as isize,
|
||||
)
|
||||
};
|
||||
native_gl.active_texture(gl::TEXTURE0);
|
||||
native_gl.bind_texture(gl::TEXTURE_2D, tile.tex_id);
|
||||
native_gl.pixel_store_i(gl::UNPACK_ROW_LENGTH, w);
|
||||
native_gl.tex_sub_image_2d_pbo(
|
||||
gl::TEXTURE_2D,
|
||||
0,
|
||||
dirty.origin.x,
|
||||
dirty.origin.y,
|
||||
dirty.size.width,
|
||||
dirty.size.height,
|
||||
gl::BGRA,
|
||||
gl::UNSIGNED_BYTE,
|
||||
src as _,
|
||||
);
|
||||
native_gl.pixel_store_i(gl::UNPACK_ROW_LENGTH, 0);
|
||||
if tile.pbo_id != 0 {
|
||||
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
let info = compositor.bind(id, tile.dirty_rect, tile.valid_rect);
|
||||
native_gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, info.fbo_id);
|
||||
|
||||
let viewport = dirty.translate(info.origin.to_vector());
|
||||
let draw_tile = self.draw_tile.as_ref().unwrap();
|
||||
draw_tile.enable(&viewport);
|
||||
draw_tile.draw(&viewport, &viewport, &dirty, surface, tile);
|
||||
draw_tile.disable();
|
||||
|
||||
native_gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
compositor.unbind();
|
||||
}
|
||||
|
||||
native_gl.bind_texture(gl::TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn begin_frame(&mut self) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.begin_frame();
|
||||
}
|
||||
self.frame_surfaces.clear();
|
||||
}
|
||||
|
||||
fn add_surface(&mut self, id: NativeSurfaceId, position: DeviceIntPoint, clip_rect: DeviceIntRect) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.add_surface(id, position, clip_rect);
|
||||
}
|
||||
self.frame_surfaces.push((id, position, clip_rect));
|
||||
}
|
||||
|
||||
fn end_frame(&mut self) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.end_frame();
|
||||
} else if let Some(native_gl) = &self.native_gl {
|
||||
let (_, fw, fh) = self.gl.get_color_buffer(0, false);
|
||||
let viewport = DeviceIntRect::from_size(DeviceIntSize::new(fw, fh));
|
||||
let draw_tile = self.draw_tile.as_ref().unwrap();
|
||||
draw_tile.enable(&viewport);
|
||||
let mut blend = false;
|
||||
native_gl.blend_func(gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
|
||||
for &(ref id, position, ref clip_rect) in &self.frame_surfaces {
|
||||
if let Some(surface) = self.surfaces.get(id) {
|
||||
if surface.is_opaque {
|
||||
if blend {
|
||||
native_gl.disable(gl::BLEND);
|
||||
blend = false;
|
||||
}
|
||||
} else if !blend {
|
||||
native_gl.enable(gl::BLEND);
|
||||
blend = true;
|
||||
}
|
||||
for tile in &surface.tiles {
|
||||
let tile_pos =
|
||||
DeviceIntPoint::new(tile.x * surface.tile_size.width, tile.y * surface.tile_size.height)
|
||||
+ position.to_vector();
|
||||
if let Some(rect) = tile.valid_rect.translate(tile_pos.to_vector()).intersection(clip_rect) {
|
||||
draw_tile.draw(&viewport, &rect, &rect.translate(-tile_pos.to_vector()), surface, tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if blend {
|
||||
native_gl.disable(gl::BLEND);
|
||||
}
|
||||
draw_tile.disable();
|
||||
} else {
|
||||
for &(ref id, position, ref clip_rect) in &self.frame_surfaces {
|
||||
if let Some(surface) = self.surfaces.get(id) {
|
||||
for tile in &surface.tiles {
|
||||
let tile_pos =
|
||||
DeviceIntPoint::new(tile.x * surface.tile_size.width, tile.y * surface.tile_size.height)
|
||||
+ position.to_vector();
|
||||
let valid = tile.valid_rect.translate(tile_pos.to_vector());
|
||||
if let Some(rect) = valid.intersection(clip_rect) {
|
||||
self.gl.composite(
|
||||
tile.color_id,
|
||||
rect.min_x() - valid.origin.x,
|
||||
rect.min_y() - valid.origin.y,
|
||||
rect.size.width,
|
||||
rect.size.height,
|
||||
rect.min_x(),
|
||||
rect.min_y(),
|
||||
surface.is_opaque,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enable_native_compositor(&mut self, enable: bool) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.enable_native_compositor(enable);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> CompositorCapabilities {
|
||||
if let Some(compositor) = &self.compositor {
|
||||
compositor.get_capabilities()
|
||||
} else {
|
||||
CompositorCapabilities {
|
||||
virtual_surface_size: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
euclid = "0.20"
|
||||
gleam = "0.10.0"
|
||||
gleam = "0.9.2"
|
||||
mozangle = {version = "0.3.1", features = ["egl"]}
|
||||
webrender = {path = "../webrender"}
|
||||
winapi = {version = "0.3", features = ["winerror", "d3d11", "dcomp"]}
|
||||
|
|
|
@ -7,7 +7,7 @@ license = "MPL-2.0"
|
|||
|
||||
[dependencies]
|
||||
webrender = { path = "../../webrender" }
|
||||
gleam = "0.10.0"
|
||||
gleam = "0.9.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
compositor-windows = { path = "../compositor-windows" }
|
||||
|
|
|
@ -61,7 +61,7 @@ debug = ["webrender/capture", "webrender/debugger", "webrender/profiler"]
|
|||
app_units = "0.7"
|
||||
env_logger = "0.5"
|
||||
euclid = "0.20"
|
||||
gleam = "0.10.0"
|
||||
gleam = "0.9.2"
|
||||
glutin = "0.21"
|
||||
rayon = "1"
|
||||
webrender = { path = "../webrender" }
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[package]
|
||||
name = "glsl-to-cxx"
|
||||
version = "0.1.0"
|
||||
license = "MPL-2.0"
|
||||
authors = ["The Mozilla Project Developers"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
glsl = "4.0"
|
|
@ -1,3 +0,0 @@
|
|||
A GLSL to C++ translator.
|
||||
|
||||
Translates GLSL to vectorized C++. Intended for use with WebRender software backend.
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,4 +0,0 @@
|
|||
use glsl_to_cxx::translate;
|
||||
fn main() {
|
||||
println!("{}", translate(&mut std::env::args()));
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "swgl"
|
||||
version = "0.1.0"
|
||||
license = "MPL-2.0"
|
||||
authors = ["The Mozilla Project Developers"]
|
||||
build = "build.rs"
|
||||
description = "Software OpenGL implementation for WebRender."
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.46"
|
||||
glsl-to-cxx = { path = "../glsl-to-cxx" }
|
||||
|
||||
[dependencies]
|
||||
gleam = "0.10.0"
|
|
@ -1,4 +0,0 @@
|
|||
swgl
|
||||
========
|
||||
|
||||
Software OpenGL implementation for WebRender
|
|
@ -1,175 +0,0 @@
|
|||
extern crate cc;
|
||||
extern crate glsl_to_cxx;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
|
||||
fn write_load_shader(shaders: &[&str]) {
|
||||
let mut load_shader = String::new();
|
||||
for s in shaders {
|
||||
let _ = write!(load_shader, "#include \"{}.h\"\n", s);
|
||||
}
|
||||
load_shader.push_str("ProgramLoader load_shader(const char* name) {\n");
|
||||
for s in shaders {
|
||||
let _ = write!(load_shader, " if (!strcmp(name, \"{}\")) {{ return {}_program::loader; }}\n", s, s);
|
||||
}
|
||||
load_shader.push_str(" return nullptr;\n}\n");
|
||||
std::fs::write(std::env::var("OUT_DIR").unwrap() + "/load_shader.h", load_shader).unwrap();
|
||||
}
|
||||
|
||||
fn process_imports(shader_dir: &str, shader: &str, included: &mut HashSet<String>, output: &mut String) {
|
||||
if !included.insert(shader.into()) {
|
||||
return;
|
||||
}
|
||||
println!("cargo:rerun-if-changed={}/{}.glsl", shader_dir, shader);
|
||||
let source = std::fs::read_to_string(format!("{}/{}.glsl", shader_dir, shader)).unwrap();
|
||||
for line in source.lines() {
|
||||
if line.starts_with("#include ") {
|
||||
let imports = line["#include ".len() ..].split(',');
|
||||
for import in imports {
|
||||
process_imports(shader_dir, import, included, output);
|
||||
}
|
||||
} else if line.starts_with("#version ") || line.starts_with("#extension ") {
|
||||
// ignore
|
||||
} else {
|
||||
output.push_str(line);
|
||||
output.push('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_shader(shader: &str, shader_dir: &str) {
|
||||
let mut imported = String::new();
|
||||
imported.push_str("#define SWGL 1\n");
|
||||
imported.push_str("#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024U\n");
|
||||
let basename = if let Some(feature_start) = shader.find(char::is_uppercase) {
|
||||
let feature_end = shader.rfind(char::is_uppercase).unwrap();
|
||||
let features = shader[feature_start..feature_end+1].split('.');
|
||||
for feature in features {
|
||||
let _ = write!(imported, "#define WR_FEATURE_{}\n", feature);
|
||||
}
|
||||
&shader[0..feature_start]
|
||||
} else {
|
||||
shader
|
||||
};
|
||||
|
||||
process_imports(shader_dir, basename, &mut HashSet::new(), &mut imported);
|
||||
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
let imp_name = format!("{}/{}.c", out_dir, shader);
|
||||
std::fs::write(&imp_name, imported).unwrap();
|
||||
|
||||
let mut build = cc::Build::new();
|
||||
if build.get_compiler().is_like_msvc() {
|
||||
build.flag("/EP");
|
||||
} else {
|
||||
build.flag("-xc").flag("-P");
|
||||
}
|
||||
build.file(&imp_name);
|
||||
let vs = build.clone()
|
||||
.define("WR_VERTEX_SHADER", Some("1"))
|
||||
.expand();
|
||||
let fs = build.clone()
|
||||
.define("WR_FRAGMENT_SHADER", Some("1"))
|
||||
.expand();
|
||||
let vs_name = format!("{}/{}.vert", out_dir, shader);
|
||||
let fs_name = format!("{}/{}.frag", out_dir, shader);
|
||||
std::fs::write(&vs_name, vs).unwrap();
|
||||
std::fs::write(&fs_name, fs).unwrap();
|
||||
|
||||
let mut args = vec![
|
||||
"glsl_to_cxx".to_string(),
|
||||
vs_name,
|
||||
fs_name,
|
||||
];
|
||||
let frag_include = format!("{}/{}.frag.h", shader_dir, shader);
|
||||
if std::path::Path::new(&frag_include).exists() {
|
||||
println!("cargo:rerun-if-changed={}/{}.frag.h", shader_dir, shader);
|
||||
args.push(frag_include);
|
||||
}
|
||||
let result = glsl_to_cxx::translate(&mut args.into_iter());
|
||||
std::fs::write(format!("{}/{}.h", out_dir, shader), result).unwrap();
|
||||
}
|
||||
|
||||
const WR_SHADERS: &'static [&'static str] = &[
|
||||
"brush_blendALPHA_PASS",
|
||||
"brush_blend",
|
||||
"brush_imageALPHA_PASS",
|
||||
"brush_image",
|
||||
"brush_imageREPETITION_ANTIALIASING_ALPHA_PASS",
|
||||
"brush_imageREPETITION_ANTIALIASING",
|
||||
"brush_linear_gradientALPHA_PASS",
|
||||
"brush_linear_gradientDITHERING_ALPHA_PASS",
|
||||
"brush_linear_gradientDITHERING",
|
||||
"brush_linear_gradient",
|
||||
"brush_mix_blendALPHA_PASS",
|
||||
"brush_mix_blend",
|
||||
"brush_opacityALPHA_PASS",
|
||||
"brush_radial_gradientALPHA_PASS",
|
||||
"brush_radial_gradientDITHERING_ALPHA_PASS",
|
||||
"brush_radial_gradientDITHERING",
|
||||
"brush_radial_gradient",
|
||||
"brush_solidALPHA_PASS",
|
||||
"brush_solid",
|
||||
"brush_yuv_image",
|
||||
"brush_yuv_imageTEXTURE_2D_YUV_NV12",
|
||||
"brush_yuv_imageYUV",
|
||||
"brush_yuv_imageYUV_INTERLEAVED",
|
||||
"brush_yuv_imageYUV_NV12_ALPHA_PASS",
|
||||
"brush_yuv_imageYUV_NV12",
|
||||
"brush_yuv_imageYUV_PLANAR",
|
||||
"composite",
|
||||
"cs_blurALPHA_TARGET",
|
||||
"cs_blurCOLOR_TARGET",
|
||||
"cs_border_segment",
|
||||
"cs_border_solid",
|
||||
"cs_clip_box_shadow",
|
||||
"cs_clip_image",
|
||||
"cs_clip_rectangleFAST_PATH",
|
||||
"cs_clip_rectangle",
|
||||
"cs_gradient",
|
||||
"cs_line_decoration",
|
||||
"cs_scale",
|
||||
"cs_svg_filter",
|
||||
"debug_color",
|
||||
"debug_font",
|
||||
"ps_split_composite",
|
||||
"ps_text_runDUAL_SOURCE_BLENDING",
|
||||
"ps_text_runGLYPH_TRANSFORM",
|
||||
"ps_text_runDUAL_SOURCE_BLENDING_GLYPH_TRANSFORM",
|
||||
"ps_text_run",
|
||||
];
|
||||
|
||||
fn main() {
|
||||
let shader_dir = match std::env::var("MOZ_SRC") {
|
||||
Ok(dir) => dir + "/gfx/wr/webrender/res",
|
||||
Err(_) => std::env::var("CARGO_MANIFEST_DIR").unwrap() + "/../webrender/res",
|
||||
};
|
||||
|
||||
for shader in WR_SHADERS {
|
||||
translate_shader(shader, &shader_dir);
|
||||
}
|
||||
|
||||
write_load_shader(WR_SHADERS);
|
||||
|
||||
println!("cargo:rerun-if-changed=src/gl_defs.h");
|
||||
println!("cargo:rerun-if-changed=src/glsl.h");
|
||||
println!("cargo:rerun-if-changed=src/program.h");
|
||||
println!("cargo:rerun-if-changed=src/texture.h");
|
||||
println!("cargo:rerun-if-changed=src/vector_type.h");
|
||||
println!("cargo:rerun-if-changed=src/gl.cc");
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.file("src/gl.cc")
|
||||
.flag("-std=c++14")
|
||||
.flag("-UMOZILLA_CONFIG_H")
|
||||
.flag("-fno-exceptions")
|
||||
.flag("-fno-rtti")
|
||||
.flag("-fno-math-errno")
|
||||
.cpp_link_stdlib(None)
|
||||
.define("_GLIBCXX_USE_CXX11_ABI", Some("0"))
|
||||
.include(shader_dir)
|
||||
.include("src")
|
||||
.include(std::env::var("OUT_DIR").unwrap())
|
||||
.compile("gl_cc");
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,171 +0,0 @@
|
|||
typedef int8_t GLbyte;
|
||||
typedef uint8_t GLubyte;
|
||||
typedef int16_t GLshort;
|
||||
typedef uint16_t GLushort;
|
||||
typedef int32_t GLint;
|
||||
typedef uint32_t GLuint;
|
||||
typedef int64_t GLint64;
|
||||
typedef uint64_t GLuint64;
|
||||
|
||||
typedef float GLfloat;
|
||||
typedef double GLdouble;
|
||||
|
||||
typedef uint32_t GLenum;
|
||||
typedef int32_t GLboolean;
|
||||
typedef uint32_t GLbitfield;
|
||||
|
||||
typedef int32_t GLsizei;
|
||||
typedef size_t GLsizeiptr;
|
||||
typedef intptr_t GLintptr;
|
||||
|
||||
#define GL_NO_ERROR 0
|
||||
|
||||
#define GL_RGBA32F 0x8814
|
||||
#define GL_RGBA8 0x8058
|
||||
#define GL_R8 0x8229
|
||||
#define GL_RGBA32I 0x8D82
|
||||
#define GL_BGRA8 0x93A1
|
||||
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_SHORT 0x1402
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_INT 0x1404
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
|
||||
#define GL_RED 0x1903
|
||||
#define GL_GREEN 0x1904
|
||||
#define GL_BLUE 0x1905
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_RGBA_INTEGER 0x8D99
|
||||
#define GL_BGRA 0x80E1
|
||||
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_DEPTH_COMPONENT24 0x81A6
|
||||
#define GL_DEPTH_COMPONENT32 0x81A7
|
||||
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
|
||||
#define GL_READ_FRAMEBUFFER 0x8CA8
|
||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
|
||||
#define GL_RENDERBUFFER 0x8D41
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT 0x8D20
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
|
||||
#define GL_PIXEL_PACK_BUFFER 0x88EB
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
|
||||
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
|
||||
#define GL_QUERY_RESULT 0x8866
|
||||
#define GL_QUERY_RESULT_AVAILABLE 0x8867
|
||||
#define GL_TIME_ELAPSED 0x88BF
|
||||
#define GL_SAMPLES_PASSED 0x8914
|
||||
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
|
||||
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#define GL_TEXTURE_2D_ARRAY 0x8C1A
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_TEXTURE2 0x84C2
|
||||
#define GL_TEXTURE3 0x84C3
|
||||
#define GL_TEXTURE4 0x84C4
|
||||
#define GL_TEXTURE5 0x84C5
|
||||
#define GL_TEXTURE6 0x84C6
|
||||
#define GL_TEXTURE7 0x84C7
|
||||
#define GL_TEXTURE8 0x84C8
|
||||
#define GL_TEXTURE9 0x84C9
|
||||
#define GL_TEXTURE10 0x84CA
|
||||
#define GL_TEXTURE11 0x84CB
|
||||
#define GL_TEXTURE12 0x84CC
|
||||
#define GL_TEXTURE13 0x84CD
|
||||
#define GL_TEXTURE14 0x84CE
|
||||
#define GL_TEXTURE15 0x84CF
|
||||
#define GL_MAX_TEXTURE_UNITS 0x84E2
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
|
||||
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_ZERO 0
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
#define GL_ONE_MINUS_SRC_COLOR 0x0301
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_CONSTANT_COLOR 0x8001
|
||||
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
|
||||
#define GL_CONSTANT_ALPHA 0x8003
|
||||
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
|
||||
#define GL_SRC1_ALPHA 0x8589
|
||||
#define GL_SRC1_COLOR 0x88F9
|
||||
#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
|
||||
#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
|
||||
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
|
||||
#define GL_NEVER 0x0200
|
||||
#define GL_LESS 0x0201
|
||||
#define GL_EQUAL 0x0202
|
||||
#define GL_LEQUAL 0x0203
|
||||
#define GL_GREATER 0x0204
|
||||
#define GL_NOTEQUAL 0x0205
|
||||
#define GL_GEQUAL 0x0206
|
||||
#define GL_ALWAYS 0x0207
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_DEPTH_WRITEMASK 0x0B72
|
||||
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
#define GL_LINE_STRIP 0x0003
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
#define GL_QUADS 0x0007
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,12 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![crate_name = "swgl"]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
extern crate gleam;
|
||||
|
||||
mod swgl_fns;
|
||||
|
||||
pub use crate::swgl_fns::*;
|
|
@ -1,138 +0,0 @@
|
|||
struct VertexAttrib;
|
||||
|
||||
namespace glsl {
|
||||
|
||||
struct VertexShaderImpl;
|
||||
struct FragmentShaderImpl;
|
||||
|
||||
struct ProgramImpl {
|
||||
virtual ~ProgramImpl() {}
|
||||
virtual int get_uniform(const char* name) const = 0;
|
||||
virtual bool set_sampler(int index, int value) = 0;
|
||||
virtual void bind_attrib(const char* name, int index) = 0;
|
||||
virtual int get_attrib(const char* name) const = 0;
|
||||
virtual VertexShaderImpl* get_vertex_shader() = 0;
|
||||
virtual FragmentShaderImpl* get_fragment_shader() = 0;
|
||||
};
|
||||
|
||||
typedef ProgramImpl* (*ProgramLoader)();
|
||||
|
||||
struct ShaderImpl {
|
||||
typedef void (*SetUniform1iFunc)(ShaderImpl*, int index, int value);
|
||||
typedef void (*SetUniform4fvFunc)(ShaderImpl*, int index, const float* value);
|
||||
typedef void (*SetUniformMatrix4fvFunc)(ShaderImpl*, int index,
|
||||
const float* value);
|
||||
|
||||
SetUniform1iFunc set_uniform_1i_func = nullptr;
|
||||
SetUniform4fvFunc set_uniform_4fv_func = nullptr;
|
||||
SetUniformMatrix4fvFunc set_uniform_matrix4fv_func = nullptr;
|
||||
|
||||
void set_uniform_1i(int index, int value) {
|
||||
(*set_uniform_1i_func)(this, index, value);
|
||||
}
|
||||
|
||||
void set_uniform_4fv(int index, const float* value) {
|
||||
(*set_uniform_4fv_func)(this, index, value);
|
||||
}
|
||||
|
||||
void set_uniform_matrix4fv(int index, const float* value) {
|
||||
(*set_uniform_matrix4fv_func)(this, index, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct VertexShaderImpl : ShaderImpl {
|
||||
typedef void (*InitBatchFunc)(VertexShaderImpl*, ProgramImpl* prog);
|
||||
typedef void (*LoadAttribsFunc)(VertexShaderImpl*, ProgramImpl* prog,
|
||||
VertexAttrib* attribs,
|
||||
unsigned short* indices, int start,
|
||||
int instance, int count);
|
||||
typedef void (*RunFunc)(VertexShaderImpl*, char* flats, char* interps,
|
||||
size_t interp_stride);
|
||||
|
||||
InitBatchFunc init_batch_func = nullptr;
|
||||
LoadAttribsFunc load_attribs_func = nullptr;
|
||||
RunFunc run_func = nullptr;
|
||||
|
||||
vec4 gl_Position;
|
||||
|
||||
void init_batch(ProgramImpl* prog) { (*init_batch_func)(this, prog); }
|
||||
|
||||
ALWAYS_INLINE void load_attribs(ProgramImpl* prog, VertexAttrib* attribs,
|
||||
unsigned short* indices, int start,
|
||||
int instance, int count) {
|
||||
(*load_attribs_func)(this, prog, attribs, indices, start, instance, count);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void run(char* flats, char* interps, size_t interp_stride) {
|
||||
(*run_func)(this, flats, interps, interp_stride);
|
||||
}
|
||||
};
|
||||
|
||||
struct FragmentShaderImpl : ShaderImpl {
|
||||
typedef void (*InitBatchFunc)(FragmentShaderImpl*, ProgramImpl* prog);
|
||||
typedef void (*InitPrimitiveFunc)(FragmentShaderImpl*, const void* flats);
|
||||
typedef void (*InitSpanFunc)(FragmentShaderImpl*, const void* interps,
|
||||
const void* step, float step_width);
|
||||
typedef void (*RunFunc)(FragmentShaderImpl*);
|
||||
typedef void (*SkipFunc)(FragmentShaderImpl*, int chunks);
|
||||
typedef bool (*UseDiscardFunc)(FragmentShaderImpl*);
|
||||
typedef void (*DrawSpanRGBA8Func)(FragmentShaderImpl*, uint32_t* buf,
|
||||
int len);
|
||||
typedef void (*DrawSpanR8Func)(FragmentShaderImpl*, uint8_t* buf, int len);
|
||||
|
||||
InitBatchFunc init_batch_func = nullptr;
|
||||
InitPrimitiveFunc init_primitive_func = nullptr;
|
||||
InitSpanFunc init_span_func = nullptr;
|
||||
RunFunc run_func = nullptr;
|
||||
SkipFunc skip_func = nullptr;
|
||||
UseDiscardFunc use_discard_func = nullptr;
|
||||
DrawSpanRGBA8Func draw_span_RGBA8_func = nullptr;
|
||||
DrawSpanR8Func draw_span_R8_func = nullptr;
|
||||
|
||||
vec2 gl_FragCoordXY;
|
||||
vec2_scalar gl_FragCoordZW;
|
||||
Bool isPixelDiscarded;
|
||||
vec4 gl_FragColor;
|
||||
vec4 gl_SecondaryFragColor;
|
||||
|
||||
ALWAYS_INLINE void step_fragcoord() { gl_FragCoordXY.x += 4; }
|
||||
|
||||
ALWAYS_INLINE void step_fragcoord(int chunks) {
|
||||
gl_FragCoordXY.x += 4 * chunks;
|
||||
}
|
||||
|
||||
void init_batch(ProgramImpl* prog) { (*init_batch_func)(this, prog); }
|
||||
|
||||
void init_primitive(const void* flats) {
|
||||
(*init_primitive_func)(this, flats);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void init_span(const void* interps, const void* step,
|
||||
float step_width) {
|
||||
(*init_span_func)(this, interps, step, step_width);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void run() { (*run_func)(this); }
|
||||
|
||||
ALWAYS_INLINE void skip(int chunks = 1) { (*skip_func)(this, chunks); }
|
||||
|
||||
ALWAYS_INLINE bool use_discard() { return (*use_discard_func)(this); }
|
||||
|
||||
ALWAYS_INLINE void draw_span(uint32_t* buf, int len) {
|
||||
(*draw_span_RGBA8_func)(this, buf, len);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool has_draw_span(uint32_t*) {
|
||||
return draw_span_RGBA8_func != nullptr;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void draw_span(uint8_t* buf, int len) {
|
||||
(*draw_span_R8_func)(this, buf, len);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool has_draw_span(uint8_t*) {
|
||||
return draw_span_R8_func != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace glsl
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,117 +0,0 @@
|
|||
template <typename S>
|
||||
void textureLinearCommit4(S sampler, ivec2 i, int zoffset, uint32_t* buf) {
|
||||
assert(sampler->format == TextureFormat::RGBA8);
|
||||
ivec2 frac = i & 0x7F;
|
||||
i >>= 7;
|
||||
|
||||
I32 row0 = clampCoord(i.x, sampler->width) +
|
||||
clampCoord(i.y, sampler->height) * sampler->stride + zoffset;
|
||||
I32 row1 = row0 + ((i.y > 0 && i.y < int32_t(sampler->height) - 1) &
|
||||
I32(sampler->stride));
|
||||
I16 fracx =
|
||||
CONVERT(frac.x & (i.x > 0 && i.x < int32_t(sampler->width) - 1), I16);
|
||||
I16 fracy = CONVERT(frac.y, I16);
|
||||
|
||||
auto a0 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row0.x]), V8<int16_t>);
|
||||
auto a1 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row1.x]), V8<int16_t>);
|
||||
a0 += ((a1 - a0) * fracy.x) >> 7;
|
||||
|
||||
auto b0 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row0.y]), V8<int16_t>);
|
||||
auto b1 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row1.y]), V8<int16_t>);
|
||||
b0 += ((b1 - b0) * fracy.y) >> 7;
|
||||
|
||||
auto abl = combine(lowHalf(a0), lowHalf(b0));
|
||||
auto abh = combine(highHalf(a0), highHalf(b0));
|
||||
abl += ((abh - abl) * fracx.xxxxyyyy) >> 7;
|
||||
|
||||
auto c0 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row0.z]), V8<int16_t>);
|
||||
auto c1 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row1.z]), V8<int16_t>);
|
||||
c0 += ((c1 - c0) * fracy.z) >> 7;
|
||||
|
||||
auto d0 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row0.w]), V8<int16_t>);
|
||||
auto d1 =
|
||||
CONVERT(unaligned_load<V8<uint8_t>>(&sampler->buf[row1.w]), V8<int16_t>);
|
||||
d0 += ((d1 - d0) * fracy.w) >> 7;
|
||||
|
||||
auto cdl = combine(lowHalf(c0), lowHalf(d0));
|
||||
auto cdh = combine(highHalf(c0), highHalf(d0));
|
||||
cdl += ((cdh - cdl) * fracx.zzzzwwww) >> 7;
|
||||
|
||||
commit_span(buf, pack(combine(HalfRGBA8(abl), HalfRGBA8(cdl))));
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
void textureLinearCommit8(S sampler, ivec2_scalar i, int zoffset,
|
||||
uint32_t* buf) {
|
||||
assert(sampler->format == TextureFormat::RGBA8);
|
||||
ivec2_scalar frac = i & 0x7F;
|
||||
i >>= 7;
|
||||
|
||||
uint32_t* row0 =
|
||||
&sampler
|
||||
->buf[clampCoord(i.x, sampler->width) +
|
||||
clampCoord(i.y, sampler->height) * sampler->stride + zoffset];
|
||||
uint32_t* row1 =
|
||||
row0 +
|
||||
((i.y > 0 && i.y < int32_t(sampler->height) - 1) ? sampler->stride : 0);
|
||||
int16_t fracx = i.x > 0 && i.x < int32_t(sampler->width) - 1 ? frac.x : 0;
|
||||
int16_t fracy = frac.y;
|
||||
|
||||
U32 pix0 = unaligned_load<U32>(row0);
|
||||
U32 pix0n = unaligned_load<U32>(row0 + 4);
|
||||
uint32_t pix0x = row0[8];
|
||||
U32 pix1 = unaligned_load<U32>(row1);
|
||||
U32 pix1n = unaligned_load<U32>(row1 + 4);
|
||||
uint32_t pix1x = row1[8];
|
||||
|
||||
{
|
||||
auto ab0 = CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix0, pix0, 0, 1, 1, 2)),
|
||||
V16<int16_t>);
|
||||
auto ab1 = CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix1, pix1, 0, 1, 1, 2)),
|
||||
V16<int16_t>);
|
||||
ab0 += ((ab1 - ab0) * fracy) >> 7;
|
||||
|
||||
auto cd0 = CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix0, pix0n, 2, 3, 3, 4)),
|
||||
V16<int16_t>);
|
||||
auto cd1 = CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix1, pix1n, 2, 3, 3, 4)),
|
||||
V16<int16_t>);
|
||||
cd0 += ((cd1 - cd0) * fracy) >> 7;
|
||||
|
||||
auto abcdl = combine(lowHalf(ab0), lowHalf(cd0));
|
||||
auto abcdh = combine(highHalf(ab0), highHalf(cd0));
|
||||
abcdl += ((abcdh - abcdl) * fracx) >> 7;
|
||||
|
||||
commit_span(buf, pack(WideRGBA8(abcdl)));
|
||||
}
|
||||
|
||||
{
|
||||
auto ab0 =
|
||||
CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix0n, pix0n, 0, 1, 1, 2)),
|
||||
V16<int16_t>);
|
||||
auto ab1 =
|
||||
CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix1n, pix1n, 0, 1, 1, 2)),
|
||||
V16<int16_t>);
|
||||
ab0 += ((ab1 - ab0) * fracy) >> 7;
|
||||
|
||||
auto cd0 =
|
||||
CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix0n, U32(pix0x), 2, 3, 3, 4)),
|
||||
V16<int16_t>);
|
||||
auto cd1 =
|
||||
CONVERT(bit_cast<V16<uint8_t>>(SHUFFLE(pix1n, U32(pix1x), 2, 3, 3, 4)),
|
||||
V16<int16_t>);
|
||||
cd0 += ((cd1 - cd0) * fracy) >> 7;
|
||||
|
||||
auto abcdl = combine(lowHalf(ab0), lowHalf(cd0));
|
||||
auto abcdh = combine(highHalf(ab0), highHalf(cd0));
|
||||
abcdl += ((abcdh - abcdl) * fracx) >> 7;
|
||||
|
||||
commit_span(buf + 4, pack(WideRGBA8(abcdl)));
|
||||
}
|
||||
}
|
|
@ -1,469 +0,0 @@
|
|||
#ifdef __clang__
|
||||
# ifdef __SSE2__
|
||||
# include <xmmintrin.h>
|
||||
# define USE_SSE2 1
|
||||
# endif
|
||||
# ifdef __ARM_NEON
|
||||
# include <arm_neon.h>
|
||||
# define USE_NEON 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace glsl {
|
||||
|
||||
#ifdef __clang__
|
||||
template <typename T, int N>
|
||||
using VectorType = T __attribute__((ext_vector_type(N)));
|
||||
|
||||
# define CONVERT(vector, type) __builtin_convertvector(vector, type)
|
||||
# define SHUFFLE(a, b, ...) __builtin_shufflevector(a, b, __VA_ARGS__)
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 4> combine(VectorType<T, 2> a, VectorType<T, 2> b) {
|
||||
return __builtin_shufflevector(a, b, 0, 1, 2, 3);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> combine(VectorType<T, 4> a, VectorType<T, 4> b) {
|
||||
return __builtin_shufflevector(a, b, 0, 1, 2, 3, 4, 5, 6, 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 16> combine(VectorType<T, 8> a, VectorType<T, 8> b) {
|
||||
return __builtin_shufflevector(a, b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 4> lowHalf(VectorType<T, 8> a) {
|
||||
return __builtin_shufflevector(a, a, 0, 1, 2, 3);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 4> highHalf(VectorType<T, 8> a) {
|
||||
return __builtin_shufflevector(a, a, 4, 5, 6, 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> lowHalf(VectorType<T, 16> a) {
|
||||
return __builtin_shufflevector(a, a, 0, 1, 2, 3, 4, 5, 6, 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> highHalf(VectorType<T, 16> a) {
|
||||
return __builtin_shufflevector(a, a, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> expand(VectorType<T, 4> a) {
|
||||
return __builtin_shufflevector(a, a, 0, 1, 2, 3, -1, -1, -1, -1);
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
struct VectorMask {
|
||||
typedef T type;
|
||||
};
|
||||
template <>
|
||||
struct VectorMask<uint32_t> {
|
||||
typedef int32_t type;
|
||||
};
|
||||
template <>
|
||||
struct VectorMask<uint16_t> {
|
||||
typedef int16_t type;
|
||||
};
|
||||
template <>
|
||||
struct VectorMask<uint8_t> {
|
||||
typedef int8_t type;
|
||||
};
|
||||
template <>
|
||||
struct VectorMask<float> {
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <typename T, int N>
|
||||
struct VectorType {
|
||||
enum { SIZE = N };
|
||||
|
||||
typedef T data_type __attribute__((vector_size(sizeof(T) * N)));
|
||||
typedef typename VectorMask<T>::type mask_index;
|
||||
typedef mask_index mask_type
|
||||
__attribute__((vector_size(sizeof(mask_index) * N)));
|
||||
typedef T half_type __attribute__((vector_size(sizeof(T) * (N / 2))));
|
||||
union {
|
||||
data_type data;
|
||||
struct {
|
||||
T x, y, z, w;
|
||||
};
|
||||
T elements[N];
|
||||
struct {
|
||||
half_type low_half, high_half;
|
||||
};
|
||||
};
|
||||
|
||||
VectorType() = default;
|
||||
constexpr VectorType(T n) : data{n, n, n, n} {}
|
||||
constexpr VectorType(T a, T b, T c, T d) : data{a, b, c, d} {}
|
||||
constexpr VectorType(T a, T b, T c, T d, T e, T f, T g, T h)
|
||||
: data{a, b, c, d, e, f, g, h} {}
|
||||
constexpr VectorType(T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k,
|
||||
T l, T m, T n, T o, T p)
|
||||
: data{a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p} {}
|
||||
|
||||
SI VectorType wrap(data_type data) {
|
||||
VectorType v;
|
||||
v.data = data;
|
||||
return v;
|
||||
}
|
||||
|
||||
T& operator[](size_t i) { return elements[i]; }
|
||||
T operator[](size_t i) const { return elements[i]; }
|
||||
|
||||
template <typename U>
|
||||
operator VectorType<U, 2>() const {
|
||||
return VectorType<U, 2>::wrap(
|
||||
(typename VectorType<U, N>::data_type){U(x), U(y)});
|
||||
}
|
||||
template <typename U>
|
||||
operator VectorType<U, 4>() const {
|
||||
return VectorType<U, 4>::wrap(
|
||||
(typename VectorType<U, N>::data_type){U(x), U(y), U(z), U(w)});
|
||||
}
|
||||
template <typename U>
|
||||
operator VectorType<U, 8>() const {
|
||||
return VectorType<U, 8>::wrap((typename VectorType<U, N>::data_type){
|
||||
U(elements[0]), U(elements[1]), U(elements[2]), U(elements[3]),
|
||||
U(elements[4]), U(elements[5]), U(elements[6]), U(elements[7])});
|
||||
}
|
||||
template <typename U>
|
||||
operator VectorType<U, 16>() const {
|
||||
return VectorType<U, 16>::wrap((typename VectorType<U, N>::data_type){
|
||||
U(elements[0]),
|
||||
U(elements[1]),
|
||||
U(elements[2]),
|
||||
U(elements[3]),
|
||||
U(elements[4]),
|
||||
U(elements[5]),
|
||||
U(elements[6]),
|
||||
U(elements[7]),
|
||||
U(elements[8]),
|
||||
U(elements[9]),
|
||||
U(elements[10]),
|
||||
U(elements[11]),
|
||||
U(elements[12]),
|
||||
U(elements[13]),
|
||||
U(elements[14]),
|
||||
U(elements[15]),
|
||||
});
|
||||
}
|
||||
|
||||
VectorType operator-() const { return wrap(-data); }
|
||||
VectorType operator~() const { return wrap(~data); }
|
||||
|
||||
VectorType operator&(VectorType x) const { return wrap(data & x.data); }
|
||||
VectorType operator&(T x) const { return wrap(data & x); }
|
||||
VectorType operator|(VectorType x) const { return wrap(data | x.data); }
|
||||
VectorType operator|(T x) const { return wrap(data | x); }
|
||||
VectorType operator^(VectorType x) const { return wrap(data ^ x.data); }
|
||||
VectorType operator^(T x) const { return wrap(data ^ x); }
|
||||
VectorType operator<<(int x) const { return wrap(data << x); }
|
||||
VectorType operator>>(int x) const { return wrap(data >> x); }
|
||||
VectorType operator+(VectorType x) const { return wrap(data + x.data); }
|
||||
VectorType operator+(T x) const { return wrap(data + x); }
|
||||
friend VectorType operator+(T x, VectorType y) { return wrap(x + y.data); }
|
||||
VectorType operator-(VectorType x) const { return wrap(data - x.data); }
|
||||
VectorType operator-(T x) const { return wrap(data - x); }
|
||||
friend VectorType operator-(T x, VectorType y) { return wrap(x - y.data); }
|
||||
VectorType operator*(VectorType x) const { return wrap(data * x.data); }
|
||||
VectorType operator*(T x) const { return wrap(data * x); }
|
||||
friend VectorType operator*(T x, VectorType y) { return wrap(x * y.data); }
|
||||
VectorType operator/(VectorType x) const { return wrap(data / x.data); }
|
||||
VectorType operator/(T x) const { return wrap(data / x); }
|
||||
friend VectorType operator/(T x, VectorType y) { return wrap(x / y.data); }
|
||||
VectorType operator%(int x) const { return wrap(data % x); }
|
||||
|
||||
VectorType& operator&=(VectorType x) {
|
||||
data &= x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator|=(VectorType x) {
|
||||
data |= x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator^=(VectorType x) {
|
||||
data ^= x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator<<=(int x) {
|
||||
data <<= x;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator>>=(int x) {
|
||||
data >>= x;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator+=(VectorType x) {
|
||||
data += x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator-=(VectorType x) {
|
||||
data -= x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator*=(VectorType x) {
|
||||
data *= x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator/=(VectorType x) {
|
||||
data /= x.data;
|
||||
return *this;
|
||||
}
|
||||
VectorType& operator%=(int x) {
|
||||
data %= x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VectorType<mask_type, N> operator==(VectorType x) const {
|
||||
return VectorType<mask_type, N>::wrap(data == x.data);
|
||||
}
|
||||
VectorType<mask_type, N> operator!=(VectorType x) const {
|
||||
return VectorType<mask_type, N>::wrap(data != x.data);
|
||||
}
|
||||
VectorType<mask_type, N> operator<(VectorType x) const {
|
||||
return VectorType<mask_type, N>::wrap(data < x.data);
|
||||
}
|
||||
VectorType<mask_type, N> operator>(VectorType x) const {
|
||||
return VectorType<mask_type, N>::wrap(data > x.data);
|
||||
}
|
||||
VectorType<mask_type, N> operator<=(VectorType x) const {
|
||||
return VectorType<mask_type, N>::wrap(data <= x.data);
|
||||
}
|
||||
VectorType<mask_type, N> operator>=(VectorType x) const {
|
||||
return VectorType<mask_type, N>::wrap(data >= x.data);
|
||||
}
|
||||
|
||||
VectorType operator!() const { return wrap(!data); }
|
||||
VectorType operator&&(VectorType x) const { return wrap(data & x.data); }
|
||||
VectorType operator||(VectorType x) const { return wrap(data | x.data); }
|
||||
|
||||
VectorType& operator=(VectorType x) {
|
||||
data = x.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VectorType<T, 4> shuffle(VectorType b, mask_index x, mask_index y,
|
||||
mask_index z, mask_index w) const {
|
||||
return VectorType<T, 4>::wrap(__builtin_shuffle(
|
||||
data, b.data, (typename VectorType<T, 4>::mask_type){x, y, z, w}));
|
||||
}
|
||||
VectorType<T, 8> shuffle(VectorType b, mask_index x, mask_index y,
|
||||
mask_index z, mask_index w, mask_index s,
|
||||
mask_index t, mask_index u, mask_index v) const {
|
||||
return VectorType<T, 8>::wrap(__builtin_shuffle(
|
||||
data, b.data,
|
||||
(typename VectorType<T, 8>::mask_type){x, y, z, w, s, t, u, v}));
|
||||
}
|
||||
VectorType<T, 16> shuffle(VectorType b, mask_index x, mask_index y,
|
||||
mask_index z, mask_index w, mask_index s,
|
||||
mask_index t, mask_index u, mask_index v,
|
||||
mask_index i, mask_index j, mask_index k,
|
||||
mask_index l, mask_index m, mask_index n,
|
||||
mask_index o, mask_index p) const {
|
||||
return VectorType<T, 16>::wrap(
|
||||
__builtin_shuffle(data, b.data,
|
||||
(typename VectorType<T, 16>::mask_type){
|
||||
x, y, z, w, s, t, u, v, i, j, k, l, m, n, o, p}));
|
||||
}
|
||||
|
||||
VectorType<T, 4> swizzle(mask_index x, mask_index y, mask_index z,
|
||||
mask_index w) const {
|
||||
return VectorType<T, 4>::wrap(__builtin_shuffle(
|
||||
data, (typename VectorType<T, 4>::mask_type){x, y, z, w}));
|
||||
}
|
||||
VectorType<T, 8> swizzle(mask_index x, mask_index y, mask_index z,
|
||||
mask_index w, mask_index s, mask_index t,
|
||||
mask_index u, mask_index v) const {
|
||||
return VectorType<T, 8>::wrap(__builtin_shuffle(
|
||||
data, (typename VectorType<T, 8>::mask_type){x, y, z, w, s, t, u, v}));
|
||||
}
|
||||
|
||||
SI VectorType wrap(half_type low, half_type high) {
|
||||
VectorType v;
|
||||
v.low_half = low;
|
||||
v.high_half = high;
|
||||
return v;
|
||||
}
|
||||
|
||||
VectorType<T, N * 2> combine(VectorType high) const {
|
||||
return VectorType<T, N * 2>::wrap(data, high.data);
|
||||
}
|
||||
|
||||
# define xyxy swizzle(0, 1, 0, 1)
|
||||
# define zwzw swizzle(2, 3, 2, 3)
|
||||
# define zyxw swizzle(2, 1, 0, 3)
|
||||
# define xxxxyyyy XXXXYYYY()
|
||||
VectorType<T, 8> XXXXYYYY() const {
|
||||
return swizzle(0, 0, 0, 0).combine(swizzle(1, 1, 1, 1));
|
||||
}
|
||||
# define zzzzwwww ZZZZWWWW()
|
||||
VectorType<T, 8> ZZZZWWWW() const {
|
||||
return swizzle(2, 2, 2, 2).combine(swizzle(3, 3, 3, 3));
|
||||
}
|
||||
# define xyzwxyzw XYZWXYZW()
|
||||
VectorType<T, 8> XYZWXYZW() const { return combine(*this); }
|
||||
# define xyxyxyxy XYXYXYXY()
|
||||
VectorType<T, 8> XYXYXYXY() const {
|
||||
return swizzle(0, 1, 0, 1).combine(swizzle(0, 1, 0, 1));
|
||||
}
|
||||
# define zwzwzwzw ZWZWZWZW()
|
||||
VectorType<T, 8> ZWZWZWZW() const {
|
||||
return swizzle(2, 3, 2, 3).combine(swizzle(2, 3, 2, 3));
|
||||
}
|
||||
# define xxyyzzww XXYYZZWW()
|
||||
VectorType<T, 8> XXYYZZWW() const {
|
||||
return swizzle(0, 0, 1, 1).combine(swizzle(2, 2, 3, 3));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VectorType<T, 2> {
|
||||
typedef T data_type __attribute__((vector_size(sizeof(T) * 2)));
|
||||
union {
|
||||
data_type data;
|
||||
struct {
|
||||
T x, y;
|
||||
};
|
||||
T elements[2];
|
||||
};
|
||||
};
|
||||
|
||||
# define CONVERT(vector, type) ((type)(vector))
|
||||
# define SHUFFLE(a, b, ...) a.shuffle(b, __VA_ARGS__)
|
||||
|
||||
template <typename T, int N>
|
||||
SI VectorType<T, N * 2> combine(VectorType<T, N> a, VectorType<T, N> b) {
|
||||
return VectorType<T, N * 2>::wrap(a.data, b.data);
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
SI VectorType<T, N / 2> lowHalf(VectorType<T, N> a) {
|
||||
return VectorType<T, N / 2>::wrap(a.low_half);
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
SI VectorType<T, N / 2> highHalf(VectorType<T, N> a) {
|
||||
return VectorType<T, N / 2>::wrap(a.high_half);
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
SI VectorType<T, N * 2> expand(VectorType<T, N> a) {
|
||||
return combine(a, a);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 4> zipLow(VectorType<T, 4> a, VectorType<T, 4> b) {
|
||||
return SHUFFLE(a, b, 0, 4, 1, 5);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 4> zipHigh(VectorType<T, 4> a, VectorType<T, 4> b) {
|
||||
return SHUFFLE(a, b, 2, 6, 3, 7);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> zipLow(VectorType<T, 8> a, VectorType<T, 8> b) {
|
||||
return SHUFFLE(a, b, 0, 8, 1, 9, 2, 10, 3, 11);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> zipHigh(VectorType<T, 8> a, VectorType<T, 8> b) {
|
||||
return SHUFFLE(a, b, 4, 12, 5, 13, 6, 14, 7, 15);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 16> zipLow(VectorType<T, 16> a, VectorType<T, 16> b) {
|
||||
return SHUFFLE(a, b, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 16> zipHigh(VectorType<T, 16> a, VectorType<T, 16> b) {
|
||||
return SHUFFLE(a, b, 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30,
|
||||
31);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> zip2Low(VectorType<T, 8> a, VectorType<T, 8> b) {
|
||||
return SHUFFLE(a, b, 0, 1, 8, 9, 2, 3, 10, 11);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SI VectorType<T, 8> zip2High(VectorType<T, 8> a, VectorType<T, 8> b) {
|
||||
return SHUFFLE(a, b, 4, 5, 12, 13, 6, 7, 14, 15);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct Unaligned {
|
||||
template <typename P>
|
||||
SI T load(const P* p) {
|
||||
T v;
|
||||
memcpy(&v, p, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
SI void store(P* p, T v) {
|
||||
memcpy(p, &v, sizeof(v));
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef __clang__
|
||||
template <typename T, int N>
|
||||
struct Unaligned<VectorType<T, N>> {
|
||||
template <typename P>
|
||||
SI VectorType<T, N> load(const P* p) {
|
||||
VectorType<T, N> v;
|
||||
memcpy(v.elements, p, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
SI void store(P* p, VectorType<T, N> v) {
|
||||
memcpy(p, v.elements, sizeof(v));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, typename P>
|
||||
SI T unaligned_load(const P* p) {
|
||||
return Unaligned<T>::load(p);
|
||||
}
|
||||
|
||||
template <typename T, typename P>
|
||||
SI void unaligned_store(P* p, T v) {
|
||||
Unaligned<T>::store(p, v);
|
||||
}
|
||||
|
||||
template <typename D, typename S>
|
||||
SI D bit_cast(const S& src) {
|
||||
static_assert(sizeof(D) == sizeof(S), "");
|
||||
return unaligned_load<D>(&src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using V2 = VectorType<T, 2>;
|
||||
template <typename T>
|
||||
using V4 = VectorType<T, 4>;
|
||||
using Float = V4<float>;
|
||||
using I32 = V4<int32_t>;
|
||||
using I16 = V4<int16_t>;
|
||||
using U64 = V4<uint64_t>;
|
||||
using U32 = V4<uint32_t>;
|
||||
using U16 = V4<uint16_t>;
|
||||
using U8 = V4<uint8_t>;
|
||||
using Bool = V4<int>;
|
||||
template <typename T>
|
||||
using V8 = VectorType<T, 8>;
|
||||
template <typename T>
|
||||
using V16 = VectorType<T, 16>;
|
||||
|
||||
} // namespace glsl
|
|
@ -32,7 +32,7 @@ cfg-if = "0.1.2"
|
|||
cstr = "0.1.2"
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
fxhash = "0.2.1"
|
||||
gleam = "0.10.0"
|
||||
gleam = "0.9.2"
|
||||
image_loader = { optional = true, version = "0.23", package = "image", default-features = false, features = ["png"] }
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
|
|
|
@ -36,14 +36,6 @@
|
|||
#endif
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
#ifdef SWGL
|
||||
// Annotate a vertex attribute as being flat per each drawn primitive instance.
|
||||
// SWGL can use this information to avoid redundantly loading the attribute in all SIMD lanes.
|
||||
#define PER_INSTANCE flat
|
||||
#else
|
||||
#define PER_INSTANCE
|
||||
#endif
|
||||
|
||||
#define varying out
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
ALWAYS_INLINE int draw_span(uint32_t* buf, int len) {
|
||||
auto color = pack_span(buf, flat_varying_vec4_0);
|
||||
commit_solid_span(buf, color, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE int draw_span(uint8_t* buf, int len) {
|
||||
auto color = pack_span(buf, flat_varying_vec4_0.x);
|
||||
commit_solid_span(buf, color, len);
|
||||
return len;
|
||||
}
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in ivec2 aTransformIds;
|
||||
PER_INSTANCE in ivec4 aClipDataResourceAddress;
|
||||
PER_INSTANCE in vec2 aClipLocalPos;
|
||||
PER_INSTANCE in vec4 aClipTileRect;
|
||||
PER_INSTANCE in vec4 aClipDeviceArea;
|
||||
PER_INSTANCE in vec4 aClipOrigins;
|
||||
PER_INSTANCE in float aDevicePixelScale;
|
||||
in ivec2 aTransformIds;
|
||||
in ivec4 aClipDataResourceAddress;
|
||||
in vec2 aClipLocalPos;
|
||||
in vec4 aClipTileRect;
|
||||
in vec4 aClipDeviceArea;
|
||||
in vec4 aClipOrigins;
|
||||
in float aDevicePixelScale;
|
||||
|
||||
struct ClipMaskInstance {
|
||||
int clip_transform_id;
|
||||
|
|
|
@ -23,16 +23,16 @@ varying vec2 vUv;
|
|||
#endif
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
PER_INSTANCE in vec4 aDeviceRect;
|
||||
PER_INSTANCE in vec4 aDeviceClipRect;
|
||||
PER_INSTANCE in vec4 aColor;
|
||||
PER_INSTANCE in vec4 aParams;
|
||||
PER_INSTANCE in vec3 aTextureLayers;
|
||||
in vec4 aDeviceRect;
|
||||
in vec4 aDeviceClipRect;
|
||||
in vec4 aColor;
|
||||
in vec4 aParams;
|
||||
in vec3 aTextureLayers;
|
||||
|
||||
#ifdef WR_FEATURE_YUV
|
||||
PER_INSTANCE in vec4 aUvRect0;
|
||||
PER_INSTANCE in vec4 aUvRect1;
|
||||
PER_INSTANCE in vec4 aUvRect2;
|
||||
in vec4 aUvRect0;
|
||||
in vec4 aUvRect1;
|
||||
in vec4 aUvRect2;
|
||||
#endif
|
||||
|
||||
void main(void) {
|
||||
|
|
|
@ -18,9 +18,9 @@ flat varying int vSupport;
|
|||
#define DIR_HORIZONTAL 0
|
||||
#define DIR_VERTICAL 1
|
||||
|
||||
PER_INSTANCE in int aBlurRenderTaskAddress;
|
||||
PER_INSTANCE in int aBlurSourceTaskAddress;
|
||||
PER_INSTANCE in int aBlurDirection;
|
||||
in int aBlurRenderTaskAddress;
|
||||
in int aBlurSourceTaskAddress;
|
||||
in int aBlurDirection;
|
||||
|
||||
struct BlurTask {
|
||||
RenderTaskCommonData common_data;
|
||||
|
|
|
@ -72,15 +72,15 @@ varying vec2 vPos;
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in vec2 aTaskOrigin;
|
||||
PER_INSTANCE in vec4 aRect;
|
||||
PER_INSTANCE in vec4 aColor0;
|
||||
PER_INSTANCE in vec4 aColor1;
|
||||
PER_INSTANCE in int aFlags;
|
||||
PER_INSTANCE in vec2 aWidths;
|
||||
PER_INSTANCE in vec2 aRadii;
|
||||
PER_INSTANCE in vec4 aClipParams1;
|
||||
PER_INSTANCE in vec4 aClipParams2;
|
||||
in vec2 aTaskOrigin;
|
||||
in vec4 aRect;
|
||||
in vec4 aColor0;
|
||||
in vec4 aColor1;
|
||||
in int aFlags;
|
||||
in vec2 aWidths;
|
||||
in vec2 aRadii;
|
||||
in vec4 aClipParams1;
|
||||
in vec4 aClipParams2;
|
||||
|
||||
vec2 get_outer_corner_scale(int segment) {
|
||||
vec2 p;
|
||||
|
|
|
@ -45,15 +45,15 @@ varying vec2 vPos;
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in vec2 aTaskOrigin;
|
||||
PER_INSTANCE in vec4 aRect;
|
||||
PER_INSTANCE in vec4 aColor0;
|
||||
PER_INSTANCE in vec4 aColor1;
|
||||
PER_INSTANCE in int aFlags;
|
||||
PER_INSTANCE in vec2 aWidths;
|
||||
PER_INSTANCE in vec2 aRadii;
|
||||
PER_INSTANCE in vec4 aClipParams1;
|
||||
PER_INSTANCE in vec4 aClipParams2;
|
||||
in vec2 aTaskOrigin;
|
||||
in vec4 aRect;
|
||||
in vec4 aColor0;
|
||||
in vec4 aColor1;
|
||||
in int aFlags;
|
||||
in vec2 aWidths;
|
||||
in vec2 aRadii;
|
||||
in vec4 aClipParams1;
|
||||
in vec4 aClipParams2;
|
||||
|
||||
vec2 get_outer_corner_scale(int segment) {
|
||||
vec2 p;
|
||||
|
|
|
@ -13,14 +13,14 @@ flat varying vec4 vColor3;
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in vec4 aTaskRect;
|
||||
PER_INSTANCE in float aAxisSelect;
|
||||
PER_INSTANCE in vec4 aStops;
|
||||
PER_INSTANCE in vec4 aColor0;
|
||||
PER_INSTANCE in vec4 aColor1;
|
||||
PER_INSTANCE in vec4 aColor2;
|
||||
PER_INSTANCE in vec4 aColor3;
|
||||
PER_INSTANCE in vec2 aStartStop;
|
||||
in vec4 aTaskRect;
|
||||
in float aAxisSelect;
|
||||
in vec4 aStops;
|
||||
in vec4 aColor0;
|
||||
in vec4 aColor1;
|
||||
in vec4 aColor2;
|
||||
in vec4 aColor3;
|
||||
in vec2 aStartStop;
|
||||
|
||||
void main(void) {
|
||||
vPos = mix(aStartStop.x, aStartStop.y, mix(aPosition.x, aPosition.y, aAxisSelect));
|
||||
|
|
|
@ -21,22 +21,22 @@ flat varying vec4 vParams;
|
|||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
// The size of the mask tile we're rendering, in pixels.
|
||||
PER_INSTANCE in vec4 aTaskRect;
|
||||
in vec4 aTaskRect;
|
||||
|
||||
// The size of the mask tile. aLocalSize.x is always horizontal and .y vertical,
|
||||
// regardless of the line's orientation. The size is chosen by
|
||||
// prim_store::get_line_decoration_sizes.
|
||||
PER_INSTANCE in vec2 aLocalSize;
|
||||
in vec2 aLocalSize;
|
||||
|
||||
// A LINE_STYLE_* value, indicating what sort of line to draw.
|
||||
PER_INSTANCE in int aStyle;
|
||||
in int aStyle;
|
||||
|
||||
// 0.0 for a horizontal line, 1.0 for a vertical line.
|
||||
PER_INSTANCE in float aAxisSelect;
|
||||
in float aAxisSelect;
|
||||
|
||||
// The thickness of the wavy line itself, not the amplitude of the waves (i.e.,
|
||||
// the thickness of the final decorated line).
|
||||
PER_INSTANCE in float aWavyLineThickness;
|
||||
in float aWavyLineThickness;
|
||||
|
||||
void main(void) {
|
||||
vec2 size = mix(aLocalSize, aLocalSize.yx, aAxisSelect);
|
||||
|
|
|
@ -9,9 +9,9 @@ flat varying vec4 vUvRect;
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in vec4 aScaleTargetRect;
|
||||
PER_INSTANCE in ivec4 aScaleSourceRect;
|
||||
PER_INSTANCE in int aScaleSourceLayer;
|
||||
in vec4 aScaleTargetRect;
|
||||
in ivec4 aScaleSourceRect;
|
||||
in int aScaleSourceLayer;
|
||||
|
||||
void main(void) {
|
||||
RectWithSize src_rect = RectWithSize(vec2(aScaleSourceRect.xy), vec2(aScaleSourceRect.zw));
|
||||
|
|
|
@ -39,13 +39,13 @@ flat varying int vFuncs[4];
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in int aFilterRenderTaskAddress;
|
||||
PER_INSTANCE in int aFilterInput1TaskAddress;
|
||||
PER_INSTANCE in int aFilterInput2TaskAddress;
|
||||
PER_INSTANCE in int aFilterKind;
|
||||
PER_INSTANCE in int aFilterInputCount;
|
||||
PER_INSTANCE in int aFilterGenericInt;
|
||||
PER_INSTANCE in ivec2 aFilterExtraDataAddress;
|
||||
in int aFilterRenderTaskAddress;
|
||||
in int aFilterInput1TaskAddress;
|
||||
in int aFilterInput2TaskAddress;
|
||||
in int aFilterKind;
|
||||
in int aFilterInputCount;
|
||||
in int aFilterGenericInt;
|
||||
in ivec2 aFilterExtraDataAddress;
|
||||
|
||||
struct FilterTask {
|
||||
RenderTaskCommonData common_data;
|
||||
|
|
|
@ -11,7 +11,7 @@ in vec4 aColor;
|
|||
|
||||
void main(void) {
|
||||
vColor = vec4(aColor.rgb * aColor.a, aColor.a);
|
||||
vec4 pos = vec4(aPosition, 0.0, 1.0);
|
||||
vec4 pos = vec4(aPosition, 1.0);
|
||||
pos.xy = floor(pos.xy + 0.5);
|
||||
gl_Position = uTransform * pos;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ in vec2 aColorTexCoord;
|
|||
void main(void) {
|
||||
vColor = aColor;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vec4 pos = vec4(aPosition, 0.0, 1.0);
|
||||
vec4 pos = vec4(aPosition, 1.0);
|
||||
pos.xy = floor(pos.xy + 0.5);
|
||||
gl_Position = uTransform * pos;
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in ivec4 aTargetRect;
|
||||
PER_INSTANCE in ivec2 aStencilOrigin;
|
||||
PER_INSTANCE in int aSubpixel;
|
||||
PER_INSTANCE in int aPad;
|
||||
in ivec4 aTargetRect;
|
||||
in ivec2 aStencilOrigin;
|
||||
in int aSubpixel;
|
||||
in int aPad;
|
||||
|
||||
out vec2 vStencilUV;
|
||||
flat out int vSubpixel;
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
PER_INSTANCE in vec2 aFromPosition;
|
||||
PER_INSTANCE in vec2 aCtrlPosition;
|
||||
PER_INSTANCE in vec2 aToPosition;
|
||||
PER_INSTANCE in vec2 aFromNormal;
|
||||
PER_INSTANCE in vec2 aCtrlNormal;
|
||||
PER_INSTANCE in vec2 aToNormal;
|
||||
PER_INSTANCE in int aPathID;
|
||||
PER_INSTANCE in int aPad;
|
||||
in vec2 aFromPosition;
|
||||
in vec2 aCtrlPosition;
|
||||
in vec2 aToPosition;
|
||||
in vec2 aFromNormal;
|
||||
in vec2 aCtrlNormal;
|
||||
in vec2 aToNormal;
|
||||
in int aPathID;
|
||||
in int aPad;
|
||||
|
||||
out vec2 vFrom;
|
||||
out vec2 vCtrl;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include shared
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
PER_INSTANCE in vec4 aRect;
|
||||
in vec4 aRect;
|
||||
|
||||
void main(void) {
|
||||
vec2 pos = aRect.xy + aPosition.xy * aRect.zw;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include shared
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
PER_INSTANCE in vec4 aRect;
|
||||
in vec4 aRect;
|
||||
|
||||
void main(void) {
|
||||
vec2 pos = aRect.xy + aPosition.xy * aRect.zw;
|
||||
|
|
|
@ -45,7 +45,7 @@ uniform HIGHP_SAMPLER_FLOAT sampler2D sPrimitiveHeadersF;
|
|||
uniform HIGHP_SAMPLER_FLOAT isampler2D sPrimitiveHeadersI;
|
||||
|
||||
// Instanced attributes
|
||||
PER_INSTANCE in ivec4 aData;
|
||||
in ivec4 aData;
|
||||
|
||||
#define VECS_PER_PRIM_HEADER_F 2U
|
||||
#define VECS_PER_PRIM_HEADER_I 2U
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
uniform mat4 uTransform; // Orthographic projection
|
||||
|
||||
// Attribute inputs
|
||||
in vec2 aPosition;
|
||||
in vec3 aPosition;
|
||||
|
||||
// get_fetch_uv is a macro to work around a macOS Intel driver parsing bug.
|
||||
// TODO: convert back to a function once the driver issues are resolved, if ever.
|
||||
|
|
|
@ -321,7 +321,6 @@ impl CompositeState {
|
|||
compositor_kind: CompositorKind,
|
||||
mut picture_caching_is_enabled: bool,
|
||||
global_device_pixel_scale: DevicePixelScale,
|
||||
max_depth_ids: i32,
|
||||
) -> Self {
|
||||
// The native compositor interface requires picture caching to work, so
|
||||
// force it here and warn if it was disabled.
|
||||
|
@ -336,7 +335,7 @@ impl CompositeState {
|
|||
opaque_tiles: Vec::new(),
|
||||
alpha_tiles: Vec::new(),
|
||||
clear_tiles: Vec::new(),
|
||||
z_generator: ZBufferIdGenerator::new(0, max_depth_ids),
|
||||
z_generator: ZBufferIdGenerator::new(0),
|
||||
dirty_rects_are_valid: true,
|
||||
compositor_kind,
|
||||
picture_caching_is_enabled,
|
||||
|
@ -757,9 +756,6 @@ pub trait Compositor {
|
|||
/// Enable/disable native compositor usage
|
||||
fn enable_native_compositor(&mut self, enable: bool);
|
||||
|
||||
/// Safely deinitialize any remaining resources owned by the compositor.
|
||||
fn deinit(&mut self);
|
||||
|
||||
/// Get the capabilities struct for this compositor. This is used to
|
||||
/// specify what features a compositor supports, depending on the
|
||||
/// underlying platform
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::debug_font_data;
|
|||
use crate::device::{Device, Program, Texture, TextureSlot, VertexDescriptor, ShaderError, VAO};
|
||||
use crate::device::{TextureFilter, VertexAttribute, VertexAttributeKind, VertexUsageHint};
|
||||
use euclid::{Point2D, Rect, Size2D, Transform3D, default};
|
||||
use crate::internal_types::Swizzle;
|
||||
use crate::internal_types::{ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, Swizzle};
|
||||
use std::f32;
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -333,8 +333,8 @@ impl DebugRenderer {
|
|||
viewport_size.width as f32 * scale,
|
||||
bottom,
|
||||
top,
|
||||
device.ortho_near_plane(),
|
||||
device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
// Triangles
|
||||
|
|
|
@ -270,21 +270,8 @@ fn build_shader_prefix_string<F: FnMut(&str)>(
|
|||
// GLSL requires that the version number comes first.
|
||||
output(gl_version_string);
|
||||
|
||||
let mut features_key = String::new();
|
||||
for feat in features.lines() {
|
||||
const PREFIX: &'static str = "#define WR_FEATURE_";
|
||||
if let Some(i) = feat.find(PREFIX) {
|
||||
if i + PREFIX.len() < feat.len() {
|
||||
if !features_key.is_empty() {
|
||||
features_key.push_str("_");
|
||||
}
|
||||
features_key.push_str(&feat[i + PREFIX.len() ..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the shader name to make debugging easier.
|
||||
let name_string = format!("// shader: {} {}\n", base_filename, features_key);
|
||||
let name_string = format!("// {}\n", base_filename);
|
||||
output(&name_string);
|
||||
|
||||
// Define a constant depending on whether we are compiling VS or FS.
|
||||
|
@ -1031,11 +1018,6 @@ enum TexStorageUsage {
|
|||
Always,
|
||||
}
|
||||
|
||||
// We get 24 bits of Z value - use up 22 bits of it to give us
|
||||
// 4 bits to account for GPU issues. This seems to manifest on
|
||||
// some GPUs under certain perspectives due to z interpolation
|
||||
// precision problems.
|
||||
const RESERVE_DEPTH_BITS: i32 = 2;
|
||||
|
||||
pub struct Device {
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
|
@ -1066,7 +1048,6 @@ pub struct Device {
|
|||
color_formats: TextureFormatPair<ImageFormat>,
|
||||
bgra_formats: TextureFormatPair<gl::GLuint>,
|
||||
swizzle_settings: SwizzleSettings,
|
||||
depth_format: gl::GLuint,
|
||||
|
||||
/// Map from texture dimensions to shared depth buffers for render targets.
|
||||
///
|
||||
|
@ -1415,19 +1396,13 @@ impl Device {
|
|||
let is_emulator = renderer_name.starts_with("Android Emulator");
|
||||
let avoid_tex_image = is_emulator;
|
||||
|
||||
let supports_texture_storage = allow_texture_storage_support &&
|
||||
match gl.get_type() {
|
||||
gl::GlType::Gl => supports_extension(&extensions, "GL_ARB_texture_storage"),
|
||||
// ES 3 technically always supports glTexStorage, but only check here for the extension
|
||||
// necessary to interact with BGRA.
|
||||
gl::GlType::Gles => supports_extension(&extensions, "GL_EXT_texture_storage"),
|
||||
};
|
||||
let supports_texture_swizzle = allow_texture_swizzling &&
|
||||
(gl.get_type() == gl::GlType::Gles || supports_extension(&extensions, "GL_ARB_texture_swizzle"));
|
||||
|
||||
let (color_formats, bgra_formats, bgra8_sampling_swizzle, texture_storage_usage) = match gl.get_type() {
|
||||
// There is `glTexStorage`, use it and expect RGBA on the input.
|
||||
gl::GlType::Gl if supports_texture_storage && supports_texture_swizzle => (
|
||||
gl::GlType::Gl if
|
||||
allow_texture_storage_support &&
|
||||
allow_texture_swizzling &&
|
||||
supports_extension(&extensions, "GL_ARB_texture_storage")
|
||||
=> (
|
||||
TextureFormatPair::from(ImageFormat::RGBA8),
|
||||
TextureFormatPair { internal: gl::RGBA8, external: gl::RGBA },
|
||||
Swizzle::Bgra, // pretend it's RGBA, rely on swizzling
|
||||
|
@ -1441,7 +1416,7 @@ impl Device {
|
|||
TexStorageUsage::Never
|
||||
),
|
||||
// We can use glTexStorage with BGRA8 as the internal format.
|
||||
gl::GlType::Gles if supports_gles_bgra && supports_texture_storage => (
|
||||
gl::GlType::Gles if supports_gles_bgra && allow_texture_storage_support && supports_extension(&extensions, "GL_EXT_texture_storage") => (
|
||||
TextureFormatPair::from(ImageFormat::BGRA8),
|
||||
TextureFormatPair { internal: gl::BGRA8_EXT, external: gl::BGRA_EXT },
|
||||
Swizzle::Rgba, // no conversion needed
|
||||
|
@ -1449,7 +1424,7 @@ impl Device {
|
|||
),
|
||||
// For BGRA8 textures we must use the unsized BGRA internal
|
||||
// format and glTexImage. If texture storage is supported we can
|
||||
// use it for other formats, which is always the case for ES 3.
|
||||
// use it for other formats.
|
||||
// We can't use glTexStorage with BGRA8 as the internal format.
|
||||
gl::GlType::Gles if supports_gles_bgra && !avoid_tex_image => (
|
||||
TextureFormatPair::from(ImageFormat::RGBA8),
|
||||
|
@ -1459,7 +1434,7 @@ impl Device {
|
|||
),
|
||||
// BGRA is not supported as an internal format, therefore we will
|
||||
// use RGBA. The swizzling will happen at the texture unit.
|
||||
gl::GlType::Gles if supports_texture_swizzle => (
|
||||
gl::GlType::Gles if allow_texture_swizzling => (
|
||||
TextureFormatPair::from(ImageFormat::RGBA8),
|
||||
TextureFormatPair { internal: gl::RGBA8, external: gl::RGBA },
|
||||
Swizzle::Bgra, // pretend it's RGBA, rely on swizzling
|
||||
|
@ -1474,14 +1449,8 @@ impl Device {
|
|||
),
|
||||
};
|
||||
|
||||
let (depth_format, upload_method) = if renderer_name.starts_with("Software WebRender") {
|
||||
(gl::DEPTH_COMPONENT16, UploadMethod::Immediate)
|
||||
} else {
|
||||
(gl::DEPTH_COMPONENT24, upload_method)
|
||||
};
|
||||
|
||||
info!("GL texture cache {:?}, bgra {:?} swizzle {:?}, texture storage {:?}, depth {:?}",
|
||||
color_formats, bgra_formats, bgra8_sampling_swizzle, texture_storage_usage, depth_format);
|
||||
info!("GL texture cache {:?}, bgra {:?} swizzle {:?}, texture storage {:?}",
|
||||
color_formats, bgra_formats, bgra8_sampling_swizzle, texture_storage_usage);
|
||||
let supports_copy_image_sub_data = supports_extension(&extensions, "GL_EXT_copy_image") ||
|
||||
supports_extension(&extensions, "GL_ARB_copy_image");
|
||||
|
||||
|
@ -1509,6 +1478,10 @@ impl Device {
|
|||
supports_extension(&extensions, "GL_KHR_blend_equation_advanced") &&
|
||||
!is_adreno;
|
||||
|
||||
let supports_texture_swizzle = allow_texture_swizzling &&
|
||||
(gl.get_type() == gl::GlType::Gles || supports_extension(&extensions, "GL_ARB_texture_storage"));
|
||||
|
||||
|
||||
// On the android emulator, glShaderSource can crash if the source
|
||||
// strings are not null-terminated. See bug 1591945.
|
||||
let requires_null_terminated_shader_source = is_emulator;
|
||||
|
@ -1553,7 +1526,6 @@ impl Device {
|
|||
swizzle_settings: SwizzleSettings {
|
||||
bgra8_sampling_swizzle,
|
||||
},
|
||||
depth_format,
|
||||
|
||||
depth_targets: FastHashMap::default(),
|
||||
|
||||
|
@ -1634,28 +1606,6 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn depth_bits(&self) -> i32 {
|
||||
match self.depth_format {
|
||||
gl::DEPTH_COMPONENT16 => 16,
|
||||
gl::DEPTH_COMPONENT24 => 24,
|
||||
_ => panic!("Unknown depth format {:?}", self.depth_format),
|
||||
}
|
||||
}
|
||||
|
||||
// See gpu_types.rs where we declare the number of possible documents and
|
||||
// number of items per document. This should match up with that.
|
||||
pub fn max_depth_ids(&self) -> i32 {
|
||||
return 1 << (self.depth_bits() - RESERVE_DEPTH_BITS);
|
||||
}
|
||||
|
||||
pub fn ortho_near_plane(&self) -> f32 {
|
||||
return -self.max_depth_ids() as f32;
|
||||
}
|
||||
|
||||
pub fn ortho_far_plane(&self) -> f32 {
|
||||
return (self.max_depth_ids() - 1) as f32;
|
||||
}
|
||||
|
||||
pub fn optimal_pbo_stride(&self) -> NonZeroUsize {
|
||||
self.optimal_pbo_stride
|
||||
}
|
||||
|
@ -2452,14 +2402,13 @@ impl Device {
|
|||
|
||||
fn acquire_depth_target(&mut self, dimensions: DeviceIntSize) -> RBOId {
|
||||
let gl = &self.gl;
|
||||
let depth_format = self.depth_format;
|
||||
let target = self.depth_targets.entry(dimensions).or_insert_with(|| {
|
||||
let renderbuffer_ids = gl.gen_renderbuffers(1);
|
||||
let depth_rb = renderbuffer_ids[0];
|
||||
gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
|
||||
gl.renderbuffer_storage(
|
||||
gl::RENDERBUFFER,
|
||||
depth_format,
|
||||
gl::DEPTH_COMPONENT24,
|
||||
dimensions.width as _,
|
||||
dimensions.height as _,
|
||||
);
|
||||
|
|
|
@ -66,7 +66,6 @@ pub struct FrameBuilderConfig {
|
|||
pub background_color: Option<ColorF>,
|
||||
pub compositor_kind: CompositorKind,
|
||||
pub tile_size_override: Option<DeviceIntSize>,
|
||||
pub max_depth_ids: i32,
|
||||
}
|
||||
|
||||
/// A set of common / global resources that are retained between
|
||||
|
@ -570,7 +569,6 @@ impl FrameBuilder {
|
|||
scene.config.compositor_kind,
|
||||
picture_caching_is_enabled,
|
||||
global_device_pixel_scale,
|
||||
scene.config.max_depth_ids,
|
||||
);
|
||||
|
||||
let main_render_task_id = self.build_layer_screen_rects_and_cull_layers(
|
||||
|
@ -607,7 +605,7 @@ impl FrameBuilder {
|
|||
);
|
||||
|
||||
// Used to generated a unique z-buffer value per primitive.
|
||||
let mut z_generator = ZBufferIdGenerator::new(layer, scene.config.max_depth_ids);
|
||||
let mut z_generator = ZBufferIdGenerator::new(layer);
|
||||
let use_dual_source_blending = scene.config.dual_source_blending_is_enabled &&
|
||||
scene.config.dual_source_blending_is_supported;
|
||||
|
||||
|
|
|
@ -25,7 +25,12 @@ pub const VECS_PER_TRANSFORM: usize = 8;
|
|||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ZBufferId(pub i32);
|
||||
|
||||
// We get 24 bits of Z value - use up 22 bits of it to give us
|
||||
// 4 bits to account for GPU issues. This seems to manifest on
|
||||
// some GPUs under certain perspectives due to z interpolation
|
||||
// precision problems.
|
||||
const MAX_DOCUMENT_LAYERS : i8 = 1 << 3;
|
||||
const MAX_ITEMS_PER_DOCUMENT_LAYER : i32 = 1 << 19;
|
||||
const MAX_DOCUMENT_LAYER_VALUE : i8 = MAX_DOCUMENT_LAYERS / 2 - 1;
|
||||
const MIN_DOCUMENT_LAYER_VALUE : i8 = -MAX_DOCUMENT_LAYERS / 2;
|
||||
|
||||
|
@ -41,23 +46,20 @@ impl ZBufferId {
|
|||
pub struct ZBufferIdGenerator {
|
||||
base: i32,
|
||||
next: i32,
|
||||
max_items_per_document_layer: i32,
|
||||
}
|
||||
|
||||
impl ZBufferIdGenerator {
|
||||
pub fn new(layer: DocumentLayer, max_depth_ids: i32) -> Self {
|
||||
pub fn new(layer: DocumentLayer) -> Self {
|
||||
debug_assert!(layer >= MIN_DOCUMENT_LAYER_VALUE);
|
||||
debug_assert!(layer <= MAX_DOCUMENT_LAYER_VALUE);
|
||||
let max_items_per_document_layer = max_depth_ids / MAX_DOCUMENT_LAYERS as i32;
|
||||
ZBufferIdGenerator {
|
||||
base: layer as i32 * max_items_per_document_layer,
|
||||
next: 0,
|
||||
max_items_per_document_layer,
|
||||
base: layer as i32 * MAX_ITEMS_PER_DOCUMENT_LAYER,
|
||||
next: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> ZBufferId {
|
||||
debug_assert!(self.next < self.max_items_per_document_layer);
|
||||
debug_assert!(self.next < MAX_ITEMS_PER_DOCUMENT_LAYER);
|
||||
let id = ZBufferId(self.next + self.base);
|
||||
self.next += 1;
|
||||
id
|
||||
|
|
|
@ -299,6 +299,11 @@ pub enum TextureSource {
|
|||
Dummy,
|
||||
}
|
||||
|
||||
// See gpu_types.rs where we declare the number of possible documents and
|
||||
// number of items per document. This should match up with that.
|
||||
pub const ORTHO_NEAR_PLANE: f32 = -(1 << 22) as f32;
|
||||
pub const ORTHO_FAR_PLANE: f32 = ((1 << 22) - 1) as f32;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
|
|
@ -69,7 +69,7 @@ use crate::gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList};
|
|||
use crate::gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
|
||||
use crate::gpu_types::{PrimitiveHeaderI, PrimitiveHeaderF, ScalingInstance, SvgFilterInstance, TransformData};
|
||||
use crate::gpu_types::{CompositeInstance, ResolveInstanceData, ZBufferId};
|
||||
use crate::internal_types::{TextureSource, ResourceCacheError};
|
||||
use crate::internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
|
||||
use crate::internal_types::{CacheTextureId, DebugOutput, FastHashMap, FastHashSet, LayerIndex, RenderedDocument, ResultMsg};
|
||||
use crate::internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource};
|
||||
use crate::internal_types::{RenderTargetInfo, SavedTargetIndex, Swizzle};
|
||||
|
@ -1308,38 +1308,17 @@ struct CacheRow {
|
|||
/// Mirrored block data on CPU for this row. We store a copy of
|
||||
/// the data on the CPU side to improve upload batching.
|
||||
cpu_blocks: Box<[GpuBlockData; MAX_VERTEX_TEXTURE_WIDTH]>,
|
||||
/// The first offset in this row that is dirty.
|
||||
min_dirty: u16,
|
||||
/// The last offset in this row that is dirty.
|
||||
max_dirty: u16,
|
||||
/// True if this row is dirty.
|
||||
is_dirty: bool,
|
||||
}
|
||||
|
||||
impl CacheRow {
|
||||
fn new() -> Self {
|
||||
CacheRow {
|
||||
cpu_blocks: Box::new([GpuBlockData::EMPTY; MAX_VERTEX_TEXTURE_WIDTH]),
|
||||
min_dirty: MAX_VERTEX_TEXTURE_WIDTH as _,
|
||||
max_dirty: 0,
|
||||
is_dirty: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
return self.min_dirty < self.max_dirty;
|
||||
}
|
||||
|
||||
fn clear_dirty(&mut self) {
|
||||
self.min_dirty = MAX_VERTEX_TEXTURE_WIDTH as _;
|
||||
self.max_dirty = 0;
|
||||
}
|
||||
|
||||
fn add_dirty(&mut self, block_offset: usize, block_count: usize) {
|
||||
self.min_dirty = self.min_dirty.min(block_offset as _);
|
||||
self.max_dirty = self.max_dirty.max((block_offset + block_count) as _);
|
||||
}
|
||||
|
||||
fn dirty_blocks(&self) -> &[GpuBlockData] {
|
||||
return &self.cpu_blocks[self.min_dirty as usize .. self.max_dirty as usize];
|
||||
}
|
||||
}
|
||||
|
||||
/// The bus over which CPU and GPU versions of the GPU cache
|
||||
|
@ -1527,15 +1506,15 @@ impl GpuCacheTexture {
|
|||
rows.push(CacheRow::new());
|
||||
}
|
||||
|
||||
// This row is dirty (needs to be updated in GPU texture).
|
||||
rows[row].is_dirty = true;
|
||||
|
||||
// Copy the blocks from the patch array in the shadow CPU copy.
|
||||
let block_offset = address.u as usize;
|
||||
let data = &mut rows[row].cpu_blocks;
|
||||
for i in 0 .. block_count {
|
||||
data[block_offset + i] = updates.blocks[block_index + i];
|
||||
}
|
||||
|
||||
// This row is dirty (needs to be updated in GPU texture).
|
||||
rows[row].add_dirty(block_offset, block_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1582,7 +1561,7 @@ impl GpuCacheTexture {
|
|||
GpuCacheBus::PixelBuffer { ref buffer, ref mut rows } => {
|
||||
let rows_dirty = rows
|
||||
.iter()
|
||||
.filter(|row| row.is_dirty())
|
||||
.filter(|row| row.is_dirty)
|
||||
.count();
|
||||
if rows_dirty == 0 {
|
||||
return 0
|
||||
|
@ -1600,19 +1579,18 @@ impl GpuCacheTexture {
|
|||
);
|
||||
|
||||
for (row_index, row) in rows.iter_mut().enumerate() {
|
||||
if !row.is_dirty() {
|
||||
if !row.is_dirty {
|
||||
continue;
|
||||
}
|
||||
|
||||
let blocks = row.dirty_blocks();
|
||||
let rect = DeviceIntRect::new(
|
||||
DeviceIntPoint::new(row.min_dirty as i32, row_index as i32),
|
||||
DeviceIntSize::new(blocks.len() as i32, 1),
|
||||
DeviceIntPoint::new(0, row_index as i32),
|
||||
DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as i32, 1),
|
||||
);
|
||||
|
||||
uploader.upload(rect, 0, None, None, blocks.as_ptr(), blocks.len());
|
||||
uploader.upload(rect, 0, None, None, row.cpu_blocks.as_ptr(), row.cpu_blocks.len());
|
||||
|
||||
row.clear_dirty();
|
||||
row.is_dirty = false;
|
||||
}
|
||||
|
||||
rows_dirty
|
||||
|
@ -1729,15 +1707,12 @@ impl<T> VertexDataTexture<T> {
|
|||
// (like Intel iGPUs) that prefers power-of-two sizes of textures ([1]).
|
||||
//
|
||||
// [1] https://software.intel.com/en-us/articles/opengl-performance-tips-power-of-two-textures-have-better-performance
|
||||
let logical_width = if needed_height == 1 {
|
||||
data.len() * texels_per_item
|
||||
} else {
|
||||
MAX_VERTEX_TEXTURE_WIDTH - (MAX_VERTEX_TEXTURE_WIDTH % texels_per_item)
|
||||
};
|
||||
let logical_width =
|
||||
(MAX_VERTEX_TEXTURE_WIDTH - (MAX_VERTEX_TEXTURE_WIDTH % texels_per_item)) as i32;
|
||||
|
||||
let rect = DeviceIntRect::new(
|
||||
DeviceIntPoint::zero(),
|
||||
DeviceIntSize::new(logical_width as i32, needed_height),
|
||||
DeviceIntSize::new(logical_width, needed_height),
|
||||
);
|
||||
|
||||
debug_assert!(len <= data.capacity(), "CPU copy will read out of bounds");
|
||||
|
@ -1745,11 +1720,9 @@ impl<T> VertexDataTexture<T> {
|
|||
rect.size,
|
||||
self.texture().get_format(),
|
||||
);
|
||||
if upload_size > 0 {
|
||||
device
|
||||
.upload_texture(self.texture(), &self.pbo, upload_size)
|
||||
.upload(rect, 0, None, None, data.as_ptr(), len);
|
||||
}
|
||||
device
|
||||
.upload_texture(self.texture(), &self.pbo, upload_size)
|
||||
.upload(rect, 0, None, None, data.as_ptr(), len);
|
||||
}
|
||||
|
||||
fn deinit(mut self, device: &mut Device) {
|
||||
|
@ -2268,7 +2241,6 @@ impl Renderer {
|
|||
background_color: options.clear_color,
|
||||
compositor_kind,
|
||||
tile_size_override: None,
|
||||
max_depth_ids: device.max_depth_ids(),
|
||||
};
|
||||
info!("WR {:?}", config);
|
||||
|
||||
|
@ -2988,7 +2960,7 @@ impl Renderer {
|
|||
GpuCacheBus::PixelBuffer { ref mut rows, .. } => {
|
||||
info!("Invalidating GPU caches");
|
||||
for row in rows {
|
||||
row.add_dirty(0, MAX_VERTEX_TEXTURE_WIDTH);
|
||||
row.is_dirty = true;
|
||||
}
|
||||
}
|
||||
GpuCacheBus::Scatter { .. } => {
|
||||
|
@ -4342,8 +4314,8 @@ impl Renderer {
|
|||
surface_size.width as f32,
|
||||
0.0,
|
||||
surface_size.height as f32,
|
||||
self.device.ortho_near_plane(),
|
||||
self.device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
// Bind an appropriate YUV shader for the texture format kind
|
||||
|
@ -5125,8 +5097,8 @@ impl Renderer {
|
|||
target_size.width as f32,
|
||||
0.0,
|
||||
target_size.height as f32,
|
||||
self.device.ortho_near_plane(),
|
||||
self.device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -5587,8 +5559,8 @@ impl Renderer {
|
|||
offset.x + size.width,
|
||||
bottom,
|
||||
top,
|
||||
self.device.ortho_near_plane(),
|
||||
self.device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
let fb_scale = Scale::<_, _, FramebufferPixel>::new(1i32);
|
||||
|
@ -5725,8 +5697,8 @@ impl Renderer {
|
|||
draw_target.dimensions().width as f32,
|
||||
0.0,
|
||||
draw_target.dimensions().height as f32,
|
||||
self.device.ortho_near_plane(),
|
||||
self.device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
self.draw_picture_cache_target(
|
||||
|
@ -5766,8 +5738,8 @@ impl Renderer {
|
|||
draw_target.dimensions().width as f32,
|
||||
0.0,
|
||||
draw_target.dimensions().height as f32,
|
||||
self.device.ortho_near_plane(),
|
||||
self.device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
self.draw_alpha_target(
|
||||
|
@ -5792,8 +5764,8 @@ impl Renderer {
|
|||
draw_target.dimensions().width as f32,
|
||||
0.0,
|
||||
draw_target.dimensions().height as f32,
|
||||
self.device.ortho_near_plane(),
|
||||
self.device.ortho_far_plane(),
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
let clear_depth = if target.needs_depth() {
|
||||
|
@ -6340,7 +6312,6 @@ impl Renderer {
|
|||
if self.debug_overlay_state.current_size.is_some() {
|
||||
compositor.destroy_surface(NativeSurfaceId::DEBUG_OVERLAY);
|
||||
}
|
||||
compositor.deinit();
|
||||
}
|
||||
self.gpu_cache_texture.deinit(&mut self.device);
|
||||
if let Some(dither_matrix_texture) = self.dither_matrix_texture {
|
||||
|
|
|
@ -296,7 +296,6 @@ impl BuiltScene {
|
|||
background_color: None,
|
||||
compositor_kind: CompositorKind::default(),
|
||||
tile_size_override: None,
|
||||
max_depth_ids: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ bincode = "1.0"
|
|||
byteorder = "1.0"
|
||||
env_logger = { version = "0.5", optional = true }
|
||||
euclid = "0.20"
|
||||
gleam = "0.10.0"
|
||||
gleam = "0.9.2"
|
||||
glutin = "0.21"
|
||||
app_units = "0.7"
|
||||
clap = { version = "2", features = ["yaml"] }
|
||||
|
@ -29,7 +29,6 @@ webrender_api = {path = "../webrender_api", features=["serialize","deserialize"]
|
|||
winit = "0.19"
|
||||
serde = {version = "1.0", features = ["derive"] }
|
||||
semver = "0.9.0"
|
||||
swgl = { path = "../swgl" }
|
||||
|
||||
[dependencies.image]
|
||||
version = "0.23"
|
||||
|
|
|
@ -46,9 +46,6 @@ args:
|
|||
- angle:
|
||||
long: angle
|
||||
help: Enable ANGLE rendering (on Windows only)
|
||||
- software:
|
||||
long: software
|
||||
help: Enable software rendering
|
||||
- dp_ratio:
|
||||
short: p
|
||||
long: device-pixel-ratio
|
||||
|
|
|
@ -29,7 +29,7 @@ mod yaml_helper;
|
|||
mod cgfont_to_data;
|
||||
|
||||
use crate::binary_frame_reader::BinaryFrameReader;
|
||||
use gleam::{gl, gl::Gl};
|
||||
use gleam::gl;
|
||||
use crate::perf::PerfHarness;
|
||||
use crate::png::save_flipped;
|
||||
use crate::rawtest::RawtestHarness;
|
||||
|
@ -44,7 +44,6 @@ use std::path::{Path, PathBuf};
|
|||
use std::process;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
use webrender::DebugFlags;
|
||||
use webrender::api::*;
|
||||
|
@ -131,46 +130,21 @@ impl HeadlessContext {
|
|||
}
|
||||
|
||||
pub enum WindowWrapper {
|
||||
WindowedContext(glutin::WindowedContext<glutin::PossiblyCurrent>, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
||||
Angle(winit::Window, angle::Context, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
||||
Headless(HeadlessContext, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
||||
WindowedContext(glutin::WindowedContext<glutin::PossiblyCurrent>, Rc<dyn gl::Gl>),
|
||||
Angle(winit::Window, angle::Context, Rc<dyn gl::Gl>),
|
||||
Headless(HeadlessContext, Rc<dyn gl::Gl>),
|
||||
}
|
||||
|
||||
pub struct HeadlessEventIterater;
|
||||
|
||||
impl WindowWrapper {
|
||||
fn upload_software_to_native(&self) {
|
||||
match *self {
|
||||
WindowWrapper::Headless(..) => return,
|
||||
_ => {}
|
||||
}
|
||||
let swgl = match self.software_gl() {
|
||||
Some(swgl) => swgl,
|
||||
None => return,
|
||||
};
|
||||
swgl.finish();
|
||||
let gl = self.native_gl();
|
||||
let tex = gl.gen_textures(1)[0];
|
||||
gl.bind_texture(gl::TEXTURE_2D, tex);
|
||||
let (data_ptr, width, height) = swgl.get_color_buffer(0, true);
|
||||
let buffer = unsafe { slice::from_raw_parts(data_ptr as *const u8, width as usize * height as usize * 4) };
|
||||
gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGBA8 as gl::GLint, width, height, 0, gl::BGRA, gl::UNSIGNED_BYTE, Some(buffer));
|
||||
let fb = gl.gen_framebuffers(1)[0];
|
||||
gl.bind_framebuffer(gl::READ_FRAMEBUFFER, fb);
|
||||
gl.framebuffer_texture_2d(gl::READ_FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, tex, 0);
|
||||
gl.blit_framebuffer(0, 0, width, height, 0, 0, width, height, gl::COLOR_BUFFER_BIT, gl::NEAREST);
|
||||
gl.delete_framebuffers(&[fb]);
|
||||
gl.delete_textures(&[tex]);
|
||||
gl.finish();
|
||||
}
|
||||
|
||||
fn swap_buffers(&self) {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, _, _) => {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, _) => {
|
||||
windowed_context.swap_buffers().unwrap()
|
||||
}
|
||||
WindowWrapper::Angle(_, ref context, _, _) => context.swap_buffers().unwrap(),
|
||||
WindowWrapper::Headless(_, _, _) => {}
|
||||
WindowWrapper::Angle(_, ref context, _) => context.swap_buffers().unwrap(),
|
||||
WindowWrapper::Headless(_, _) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,92 +157,62 @@ impl WindowWrapper {
|
|||
DeviceIntSize::new(size.width as i32, size.height as i32)
|
||||
}
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, ..) => {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, _) => {
|
||||
inner_size(windowed_context.window())
|
||||
}
|
||||
WindowWrapper::Angle(ref window, ..) => inner_size(window),
|
||||
WindowWrapper::Headless(ref context, ..) => DeviceIntSize::new(context.width, context.height),
|
||||
WindowWrapper::Headless(ref context, _) => DeviceIntSize::new(context.width, context.height),
|
||||
}
|
||||
}
|
||||
|
||||
fn hidpi_factor(&self) -> f32 {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, ..) => {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, _) => {
|
||||
windowed_context.window().get_hidpi_factor() as f32
|
||||
}
|
||||
WindowWrapper::Angle(ref window, ..) => window.get_hidpi_factor() as f32,
|
||||
WindowWrapper::Headless(..) => 1.0,
|
||||
WindowWrapper::Headless(_, _) => 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, size: DeviceIntSize) {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(ref mut windowed_context, ..) => {
|
||||
WindowWrapper::WindowedContext(ref mut windowed_context, _) => {
|
||||
windowed_context.window()
|
||||
.set_inner_size(LogicalSize::new(size.width as f64, size.height as f64))
|
||||
},
|
||||
WindowWrapper::Angle(ref mut window, ..) => {
|
||||
window.set_inner_size(LogicalSize::new(size.width as f64, size.height as f64))
|
||||
},
|
||||
WindowWrapper::Headless(..) => unimplemented!(), // requites Glutin update
|
||||
WindowWrapper::Headless(_, _) => unimplemented!(), // requites Glutin update
|
||||
}
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: &str) {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, ..) => {
|
||||
WindowWrapper::WindowedContext(ref windowed_context, _) => {
|
||||
windowed_context.window().set_title(title)
|
||||
}
|
||||
WindowWrapper::Angle(ref window, ..) => window.set_title(title),
|
||||
WindowWrapper::Headless(..) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn software_gl(&self) -> Option<&swgl::Context> {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(_, _, ref swgl) |
|
||||
WindowWrapper::Angle(_, _, _, ref swgl) |
|
||||
WindowWrapper::Headless(_, _, ref swgl) => swgl.as_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn native_gl(&self) -> &dyn gl::Gl {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(_, ref gl, _) |
|
||||
WindowWrapper::Angle(_, _, ref gl, _) |
|
||||
WindowWrapper::Headless(_, ref gl, _) => &**gl,
|
||||
WindowWrapper::Headless(_, _) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gl(&self) -> &dyn gl::Gl {
|
||||
if let Some(swgl) = self.software_gl() {
|
||||
swgl
|
||||
} else {
|
||||
self.native_gl()
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(_, ref gl) |
|
||||
WindowWrapper::Angle(_, _, ref gl) |
|
||||
WindowWrapper::Headless(_, ref gl) => &**gl,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_gl(&self) -> Rc<dyn gl::Gl> {
|
||||
match *self {
|
||||
WindowWrapper::WindowedContext(_, ref gl, ref swgl) |
|
||||
WindowWrapper::Angle(_, _, ref gl, ref swgl) |
|
||||
WindowWrapper::Headless(_, ref gl, ref swgl) => {
|
||||
if let Some(ref swgl) = swgl {
|
||||
Rc::new(swgl.clone())
|
||||
} else {
|
||||
gl.clone()
|
||||
}
|
||||
}
|
||||
WindowWrapper::WindowedContext(_, ref gl) |
|
||||
WindowWrapper::Angle(_, _, ref gl) |
|
||||
WindowWrapper::Headless(_, ref gl) => gl.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&self, wrench: &mut Wrench) {
|
||||
let dim = self.get_inner_size();
|
||||
if let Some(swgl) = self.software_gl() {
|
||||
swgl.init_default_framebuffer(dim.width, dim.height);
|
||||
}
|
||||
wrench.update(dim);
|
||||
}
|
||||
}
|
||||
|
||||
fn make_window(
|
||||
|
@ -278,16 +222,7 @@ fn make_window(
|
|||
events_loop: &Option<winit::EventsLoop>,
|
||||
angle: bool,
|
||||
gl_request: glutin::GlRequest,
|
||||
software: bool,
|
||||
) -> WindowWrapper {
|
||||
let sw_ctx = if software {
|
||||
let ctx = swgl::Context::create();
|
||||
ctx.make_current();
|
||||
Some(ctx)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let wrapper = match *events_loop {
|
||||
Some(ref events_loop) => {
|
||||
let context_builder = glutin::ContextBuilder::new()
|
||||
|
@ -319,7 +254,7 @@ fn make_window(
|
|||
glutin::Api::WebGl => unimplemented!(),
|
||||
};
|
||||
|
||||
WindowWrapper::Angle(_window, _context, gl, sw_ctx)
|
||||
WindowWrapper::Angle(_window, _context, gl)
|
||||
} else {
|
||||
let windowed_context = context_builder
|
||||
.build_windowed(window_builder, events_loop)
|
||||
|
@ -345,36 +280,30 @@ fn make_window(
|
|||
glutin::Api::WebGl => unimplemented!(),
|
||||
};
|
||||
|
||||
WindowWrapper::WindowedContext(windowed_context, gl, sw_ctx)
|
||||
WindowWrapper::WindowedContext(windowed_context, gl)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let gl = if let Some(ref sw_ctx) = sw_ctx {
|
||||
Rc::new(sw_ctx.clone())
|
||||
} else {
|
||||
match gl::GlType::default() {
|
||||
gl::GlType::Gl => unsafe {
|
||||
gl::GlFns::load_with(|symbol| {
|
||||
HeadlessContext::get_proc_address(symbol) as *const _
|
||||
})
|
||||
},
|
||||
gl::GlType::Gles => unsafe {
|
||||
gl::GlesFns::load_with(|symbol| {
|
||||
HeadlessContext::get_proc_address(symbol) as *const _
|
||||
})
|
||||
},
|
||||
}
|
||||
let gl = match gl::GlType::default() {
|
||||
gl::GlType::Gl => unsafe {
|
||||
gl::GlFns::load_with(|symbol| {
|
||||
HeadlessContext::get_proc_address(symbol) as *const _
|
||||
})
|
||||
},
|
||||
gl::GlType::Gles => unsafe {
|
||||
gl::GlesFns::load_with(|symbol| {
|
||||
HeadlessContext::get_proc_address(symbol) as *const _
|
||||
})
|
||||
},
|
||||
};
|
||||
WindowWrapper::Headless(HeadlessContext::new(size.width, size.height), gl, sw_ctx)
|
||||
WindowWrapper::Headless(HeadlessContext::new(size.width, size.height), gl)
|
||||
}
|
||||
};
|
||||
|
||||
let gl = wrapper.gl();
|
||||
wrapper.gl().clear_color(0.3, 0.0, 0.0, 1.0);
|
||||
|
||||
gl.clear_color(0.3, 0.0, 0.0, 1.0);
|
||||
|
||||
let gl_version = gl.get_string(gl::VERSION);
|
||||
let gl_renderer = gl.get_string(gl::RENDERER);
|
||||
let gl_version = wrapper.gl().get_string(gl::VERSION);
|
||||
let gl_renderer = wrapper.gl().get_string(gl::RENDERER);
|
||||
|
||||
let dp_ratio = dp_ratio.unwrap_or(wrapper.hidpi_factor());
|
||||
println!("OpenGL version {}, {}", gl_version, gl_renderer);
|
||||
|
@ -583,8 +512,6 @@ fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
let software = args.is_present("software");
|
||||
|
||||
let mut window = make_window(
|
||||
size,
|
||||
dp_ratio,
|
||||
|
@ -592,7 +519,6 @@ fn main() {
|
|||
&events_loop,
|
||||
args.is_present("angle"),
|
||||
gl_request,
|
||||
software,
|
||||
);
|
||||
let dp_ratio = dp_ratio.unwrap_or(window.hidpi_factor());
|
||||
let dim = window.get_inner_size();
|
||||
|
@ -627,7 +553,6 @@ fn main() {
|
|||
dump_shader_source,
|
||||
notifier,
|
||||
);
|
||||
window.update(&mut wrench);
|
||||
|
||||
if let Some(window_title) = wrench.take_title() {
|
||||
if !cfg!(windows) {
|
||||
|
@ -723,7 +648,8 @@ fn render<'a>(
|
|||
let mut cpu_profile_index = 0;
|
||||
let mut cursor_position = WorldPoint::zero();
|
||||
|
||||
window.update(wrench);
|
||||
let dim = window.get_inner_size();
|
||||
wrench.update(dim);
|
||||
thing.do_frame(wrench);
|
||||
|
||||
let mut debug_flags = DebugFlags::empty();
|
||||
|
@ -921,7 +847,8 @@ fn render<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
window.update(wrench);
|
||||
let dim = window.get_inner_size();
|
||||
wrench.update(dim);
|
||||
|
||||
if do_frame {
|
||||
let frame_num = thing.do_frame(wrench);
|
||||
|
@ -936,7 +863,6 @@ fn render<'a>(
|
|||
}
|
||||
|
||||
wrench.render();
|
||||
window.upload_software_to_native();
|
||||
window.swap_buffers();
|
||||
|
||||
if do_loop {
|
||||
|
|
|
@ -182,7 +182,6 @@ Please commit or stash these changes before vendoring, or re-run with `--ignore-
|
|||
'fuchsia-zircon',
|
||||
'fuchsia-zircon-sys',
|
||||
'fuchsia-cprng',
|
||||
'glsl',
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7fd2d6695ffe34ceef70faf02bd5df9d17d650951f038a84bcfe8c09d714a2be","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"1acb12040be43a3582d5897f11870b3ffdcd7ce0f4f32de158175bb6b33ec0b7","build.rs":"b6b30972ee2be2e151af0ca93b30ccc3c8bce2cfeef4217244d6b413b6bd0c9d","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/gl.rs":"89e61e0ecb0c8c1d3dbd8cdf3f26270d4cdf8bf6832c9b356ed5694620271967","src/gl_fns.rs":"517f195005a45f13fb9928a684c1e0c831136404ec7eeac1b5f0c0dbef1ac64a","src/gles_fns.rs":"bd46d068d41d4fd405a99e9b5a966a69fc186195da9fb3e9dcbd73f62f95f73a","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"77b1fd76468fff720bad31016688b805c6442ebf2d7c29123e10e4984aa61986"}
|
||||
{"files":{"COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"834f409ac81917f5b5730483c90611e3193a8fb7400c87d30e7988d866bc5740","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"1acb12040be43a3582d5897f11870b3ffdcd7ce0f4f32de158175bb6b33ec0b7","build.rs":"b6b30972ee2be2e151af0ca93b30ccc3c8bce2cfeef4217244d6b413b6bd0c9d","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/gl.rs":"e923f4ccfeae5112e6cea8f78ff279e8a26c041dcfb5cfb63d9713e733d249c3","src/gl_fns.rs":"67b5eac2a686f4a58201b8d51fc27db1aca6d597dfaa5c8ad4007170ffb18887","src/gles_fns.rs":"1c206adf96e6b9767d526aad54ddfb48e99aa0f5766d3cb72019470f4bdd88f9","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"332d1f4e6c6181ed07178f84a552b2387d43ecf6821a86c22cfb3883ea3fb1b9"}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "gleam"
|
||||
version = "0.10.0"
|
||||
version = "0.9.2"
|
||||
authors = ["The Servo Project Developers"]
|
||||
build = "build.rs"
|
||||
description = "Generated OpenGL bindings and wrapper for Servo."
|
||||
|
|
|
@ -74,13 +74,22 @@ pub struct DebugMessage {
|
|||
pub severity: GLenum,
|
||||
}
|
||||
|
||||
mod private {
|
||||
// Private marker trait extended by the Gl public trait so that no one
|
||||
// else outside this crate can implement Gl. Why? So that adding new methods
|
||||
// to it don't lead to a breaking change.
|
||||
pub trait Sealed {}
|
||||
}
|
||||
use self::private::Sealed;
|
||||
|
||||
macro_rules! declare_gl_apis {
|
||||
// garbo is a hack to handle unsafe methods.
|
||||
($($(unsafe $([$garbo:expr])*)* fn $name:ident(&self $(, $arg:ident: $t:ty)* $(,)*) $(-> $retty:ty)* ;)+) => {
|
||||
pub trait Gl {
|
||||
pub trait Gl: Sealed {
|
||||
$($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* ;)+
|
||||
}
|
||||
|
||||
impl Sealed for ErrorCheckingGl {}
|
||||
impl Gl for ErrorCheckingGl {
|
||||
$($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* {
|
||||
let rv = self.gl.$name($($arg,)*);
|
||||
|
@ -89,6 +98,7 @@ macro_rules! declare_gl_apis {
|
|||
})+
|
||||
}
|
||||
|
||||
impl<F> Sealed for ErrorReactingGl<F> {}
|
||||
impl<F: Fn(&dyn Gl, &str, GLenum)> Gl for ErrorReactingGl<F> {
|
||||
$($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* {
|
||||
let rv = self.gl.$name($($arg,)*);
|
||||
|
@ -100,6 +110,7 @@ macro_rules! declare_gl_apis {
|
|||
})+
|
||||
}
|
||||
|
||||
impl<F> Sealed for ProfilingGl<F> {}
|
||||
impl<F: Fn(&str, Duration)> Gl for ProfilingGl<F> {
|
||||
$($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* {
|
||||
let start = Instant::now();
|
||||
|
|
|
@ -21,6 +21,7 @@ impl GlFns {
|
|||
}
|
||||
}
|
||||
|
||||
impl Sealed for GlFns {}
|
||||
impl Gl for GlFns {
|
||||
fn get_type(&self) -> GlType {
|
||||
GlType::Gl
|
||||
|
|
|
@ -21,6 +21,7 @@ impl GlesFns {
|
|||
}
|
||||
}
|
||||
|
||||
impl Sealed for GlesFns {}
|
||||
impl Gl for GlesFns {
|
||||
fn get_type(&self) -> GlType {
|
||||
GlType::Gles
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
{"files":{"CHANGELOG.md":"59a3fb395bdfc3f41a2c9111797ff1686b74b0d4bb0c62beee5b01b56ff84b8f","Cargo.toml":"00f31c7fc51a327fcccefb7a3b54899191ff8bf274eb317540b48eba863de07e","LICENSE":"09719a44ba10012b20e7a36e7f2e7806a89476813668b66067e0e5dbcc9ce34c","README.md":"42336a3535b2623375349950931860716369e1c3fd4a61b36785c9276427cd16","data/tests/buffer_block_0.glsl":"335b2b5360635eb0a1c994e44a33787d43ea6ce84da4c0a795e7526da64b37bd","data/tests/layout_buffer_block_0.glsl":"d64c27188cd27b7fc81413e8afe621d6f44ddcdeddb115d62661358b2131e8a3","src/lib.rs":"f630de25bc1d7264037c0e07ecacc766aae67388c4077f5c3156bf7021705161","src/parse_tests.rs":"1cfcc2fe92d757aef3c5b0acb81f90a60d5f04a3ff2ebc50dc1abea4c50b61af","src/parser.rs":"6ed2ac80114c1f4c7859d7c78817bab997493ebf16dca2ce54fac28c8d4827e5","src/parsers.rs":"fdd69e02a2be8ae9807fba465a5bda5d345ef46afa36d99d729a64c3400ea46d","src/parsers/nom_helpers.rs":"07cfaef9ee01bda7ead0587e21a58626ad97a33cb942c2dd2d7693c9daa41f79","src/syntax.rs":"4ac6a1a5e6de4753efbeec4ce73eccde97f052eb19929a935723e472f746bd10","src/transpiler/glsl.rs":"c42ca794c4c326d52e9d0d29fe54c287ae4fb1bc1b3ef26b13bfcbdf5fd25974","src/transpiler/mod.rs":"244cc5d9ab4c6e6ac4a30d42df81f4718b79fe653cc04e138071ae5905aa9e28","src/transpiler/spirv.rs":"8c777f0f5717a3e269f9062b187da3e66706705a81a392f6aeea0630ed498deb","src/visitor.rs":"68161858479f39c81fa71e73397ec178407bdcede7b6f9a75af6c9dc5b890c54","tests/incorrect_statement.rs":"6b182e705421450d016d6a078cf8fcc0b748bf6208dfbf2fd3474467261241fd","tests/left_associativity.rs":"c5390754390ea262cf11a088584d74511fedc314146c51670c46ddbf90a9992c","tests/missing_zero_float.rs":"1bb2fa7c55354ecec8fb5e82b1cb821b052c2047c32edc030ed0e529d77af3d2"},"package":"766443890761b3c4edcce86cafaac97971b200662fbdd0446eb7c6b99b4401ea"}
|
|
@ -1,397 +0,0 @@
|
|||
# 4.0.3
|
||||
|
||||
> Fri Mar 6th 2020
|
||||
|
||||
- Move all the unit tests code into their ow module to prevent rustc from parsing them if we
|
||||
don’t build with tests.
|
||||
|
||||
# 4.0.2
|
||||
|
||||
> Mon 10th Feb 2020
|
||||
|
||||
- Remove the `lexical` feature from `nom`. It’s useful only when using functions such as the
|
||||
`float` combinator, which we don’t use.
|
||||
|
||||
# 4.0.1
|
||||
|
||||
> Tue 21st Jan 2020
|
||||
|
||||
- Fix a bug occurring in the function-like `#define` parser (i.e. `#define foo(x) (y)`) that
|
||||
would prevent the use of whitespaces in the argument list.
|
||||
|
||||
# 4.0
|
||||
|
||||
> Mon 6th Jan 2020
|
||||
|
||||
## Major changes
|
||||
|
||||
- Add support for `attribute` and `varying` keyword as a backward-compatible parser.
|
||||
- Fix binary operator associativity. They were (_erroneously_) right-associative. They’re now
|
||||
parsed as left-associative.
|
||||
|
||||
# 3.0
|
||||
|
||||
> Wed 14th Nov 2019
|
||||
|
||||
## Major changes
|
||||
|
||||
- `JumpStatement::Return` now takes an optional `Expr` instead of an `Expr` directly. That allows
|
||||
for parsing statements such as `return;`, which should have
|
||||
been supported from the beginning.
|
||||
- Support for missing preprocessor directives:
|
||||
- `#if`.
|
||||
- `#ifdef`.
|
||||
- `#ifndef`.
|
||||
- `#elseif`.
|
||||
- `#else`.
|
||||
- `#endif`.
|
||||
- `#error`.
|
||||
- `#include`.
|
||||
- `#line`.
|
||||
- `#pragma`.
|
||||
- `#undef`.
|
||||
|
||||
## Patch changes
|
||||
|
||||
- Add a `rustfmt.toml` to reformat everything and stay consistent. If you want contribute, ensure
|
||||
you are correctly using `rustfmt` (either by running `cargo fmt` before submitting a PR or by
|
||||
configuring your editor to format the code for you). This is important, as not respecting the
|
||||
formatting would make your contribution impossible to merge due to a CI check.
|
||||
- Support for _multiline_ annotations (`\`). Multiline annotations are currently supported as
|
||||
part of _spaces_ — i.e. you cannot use them to break an identifier on two lines for instance.
|
||||
This choice makes it faster to parse without too much compromises (after all, `\` is mostly used
|
||||
in CPP directives in GLSL).
|
||||
- Fix a bug with _recoverable parsers_ that would produce parent parsers to ignore GLSL grammar
|
||||
errors. That fix also implies a boost in performance due to short-circuiting optimizations.
|
||||
|
||||
# 2.0.1
|
||||
|
||||
> Fri 8th Nov 2019
|
||||
|
||||
- Improve performance of expression parsers.
|
||||
|
||||
# 2.0
|
||||
|
||||
> Thu 24th Oct 2019
|
||||
|
||||
## Major changes
|
||||
|
||||
- Add `ShaderKind::Compute`.
|
||||
- Remove `NonEmpty::from_iter` and `TranslationUnit::from_iter` as they were deprecated. Use
|
||||
`*::from_non_empty_iter` instead.
|
||||
|
||||
## Patch changes
|
||||
|
||||
- Fix tokenizer of `Block`.
|
||||
- Fix a bug while parsing floating-point numbers.
|
||||
- Reformat with `rustfmt`.
|
||||
|
||||
# 1.2
|
||||
|
||||
> Wed 18th Sep 2019
|
||||
|
||||
## Deprecations
|
||||
|
||||
- `NonEmpty::from_iter` and `TranslationUnit::from_iter` are deprecated in favor of
|
||||
`*::from_non_empty_iter`.
|
||||
|
||||
## Minor changes
|
||||
|
||||
- Add binary SPIR-V transpilation. That enables to transpile GLSL directly into a SPIR-V buffer.
|
||||
- Add `NonEmpty::from_non_empty_iter` and `TranslationUnit::from_non_empty_iter`.
|
||||
|
||||
# 1.1.1
|
||||
|
||||
> Tue 17th Sep 2019
|
||||
|
||||
- Update internal code for Rust edition 2018.
|
||||
|
||||
# 1.1
|
||||
|
||||
> Tue 30th of July 2019
|
||||
|
||||
- Add the `ShaderStage` type alias to `TranslationUnit`.
|
||||
- Enhance the front documentation to showcase how to use how to use the crate.
|
||||
|
||||
# 1.0.2
|
||||
|
||||
> Tue 23rd of July 2019
|
||||
|
||||
- Change the description of the project and update documentation.
|
||||
|
||||
# 1.0.1
|
||||
|
||||
> Tue 23rd of July 2019
|
||||
|
||||
- Change the `external_declaration` parser so that it can also accept _GLSL460_. That should be a
|
||||
breaking change because now, _GLSL450_ formatted input accepts feature from _GLSL460_, which
|
||||
shouldn’t be allowed. Nevertheless, the added feature (being able to use semicolons (`;`) on
|
||||
empty lines at top-level) is not really an interesting property and no breakage should happen.
|
||||
|
||||
# 1.0
|
||||
|
||||
> Thu 18th of July 2019
|
||||
|
||||
- Migrate all parsers to [nom-5](https://crates.io/crates/nom/5.0.0).
|
||||
- Improve and add unit and integration tests.
|
||||
- Improve overall documentation.
|
||||
- Enhance some allocation scheme (removed them by using more adapted parsers).
|
||||
- Completely remove the byte (`&[u8]`) parsing. That was a bad idea, for both its impractical
|
||||
aspect and error removing. Parsing is done on string slices now (`&str`).
|
||||
|
||||
# 0.13.5
|
||||
|
||||
> Sun 9th of December 2018
|
||||
|
||||
- Add the SPIR-V transpiler. Currently, it’s feature-gated and *very* experimental. Feel free to
|
||||
try and provide feedback about it.
|
||||
- Add simple accessors for `ParseResult`.
|
||||
- Fix a typo in the documentation of syntax.
|
||||
- Add some unit and integration tests.
|
||||
- Add `Identifier::as_str` and `TypeName::as_str`
|
||||
|
||||
# 0.13.4
|
||||
|
||||
> Wed 25nd of November 2018
|
||||
|
||||
- Add `NonEmpty::push` and `NonEmpty::pop`.
|
||||
- Implement `Deref` and `DerefMut` for `TranslationUnit`.
|
||||
|
||||
# 0.13.3
|
||||
|
||||
> Wed 24nd of November 2018
|
||||
|
||||
- Add `NonEmpty::from_iter` and `TranslationUnit::from_iter`.
|
||||
- Implement `IntoIterator` for `NonEmpty` and `TranslationUnit`.
|
||||
|
||||
# 0.13.2
|
||||
|
||||
> Wed 22nd of November 2018
|
||||
|
||||
- Fix a typo in documentation.
|
||||
|
||||
# 0.13.1
|
||||
|
||||
> Wed 22nd of November 2018
|
||||
|
||||
- Fix a link in documentation.
|
||||
|
||||
# 0.13
|
||||
|
||||
> Wed 21st of November 2018
|
||||
|
||||
- Update/reset hyperlinks in all the documentation for types, traits, methods, etc.
|
||||
- General enhancement of the documentation.
|
||||
- `ExternalDeclaration::new_struct` can now fail. Check the doc for further details.
|
||||
- `NonEmpty`, `Identifier` and `TypeName` and `TranslationUnit` are now plain types and not
|
||||
aliases anymore.
|
||||
- Add AST visitors. Visitors allow for traversing through an AST and on-the-fly mutation,
|
||||
filtering, etc.
|
||||
- The `#define` preprocessor pragma is now supported in a limited form (it can only be used in
|
||||
the global scope).
|
||||
|
||||
# 0.12
|
||||
|
||||
> Sun 11th of November 2018
|
||||
|
||||
- Fix the type of identifier stored in `Block`: it now uses the new encoding for arrayed
|
||||
identifiers.
|
||||
- `Block` parsers update for the arrayd identifier change.
|
||||
|
||||
# 0.11
|
||||
|
||||
> Sat 10th of November 2018
|
||||
|
||||
- Add helper functions to build objects form the `syntax` module. Those are intended to be a
|
||||
simple way to build ASTs out of Rust code instead of parsing.
|
||||
- Enhance the documentation of the `Preprocessor` type.
|
||||
|
||||
# 0.10.1
|
||||
|
||||
> Fri 2nd of November 2018
|
||||
|
||||
- Add some missing implementors of `Parse` for types from `glsl::syntax`.
|
||||
|
||||
# 0.10
|
||||
|
||||
> Fri 2nd of November 2018
|
||||
|
||||
- Hide the `parsers` module. It’s not exposed anymore as it was mostly
|
||||
[nom](https://crates.io/crates/nom) parsers and we don’t like leaking internals.
|
||||
- Introduce the `Parser` trait, acting as an abstraction over the internal parsers. Implementors
|
||||
provide a type-driven parsing experience that is very similar to the one as
|
||||
[FromStr](https://doc.rust-lang.org/std/str/trait.FromStr.html). This change is actually
|
||||
mandatory for the [glsl-quasiquote](https://crates.io/crates/glsl-quasiquote) crate’s `glsl!`
|
||||
proc-macro to allow people use it for any GLSL item (and not only `TranslationUnit`).
|
||||
- Enhance the overall documentation.
|
||||
|
||||
# 0.9.2
|
||||
|
||||
> Wed 3rd of October 2018
|
||||
|
||||
- Fix GLSL transpiled representation of `IVec*`. It was plain wrong.
|
||||
|
||||
# 0.9.1
|
||||
|
||||
> Sat 7th of July 2018
|
||||
|
||||
- Fix unit testing in transpilers.
|
||||
|
||||
# 0.9
|
||||
|
||||
> Sat 7th of July 2018
|
||||
|
||||
- Big cleanup of the module hierarchy.
|
||||
- Enhanced the documentation.
|
||||
|
||||
# 0.8.1
|
||||
|
||||
> Sun, 17th of June 2018
|
||||
|
||||
- Add the `README.md` path to the `Cargo.toml` manifest.
|
||||
|
||||
# 0.8
|
||||
|
||||
> Sun 17th of June 2018
|
||||
|
||||
This version introduces breaking changes because public types used in return positions have changed.
|
||||
These concern only intermediate `nom` functions, so if you do not make a fancy use of this crate,
|
||||
you souldn’t have to worry too much when migrating.
|
||||
|
||||
- Fix the roundtrip issue with the GLSL writer (precedence wasn’t correctly respected).
|
||||
- Simplify internal code.
|
||||
- Error instead of panicking when parsing overflowing integer literals.
|
||||
- Fix panic trying to parse literals starting with whitespace.
|
||||
- Add fuzzing to find out panics.
|
||||
|
||||
# 0.7.2
|
||||
|
||||
> Wed 13th of December 2017
|
||||
|
||||
- Fix the `show_expr` when the `Expr` is a `Expr::UIntConst`.
|
||||
|
||||
# 0.7.1
|
||||
|
||||
> Mon 20th of November 2017
|
||||
|
||||
- `std::error::Error` is now implemented for `ParseError`.
|
||||
|
||||
# 0.7
|
||||
|
||||
> Wed 27th of September 2017
|
||||
|
||||
- Add support for postfix expressions as function identifiers.
|
||||
|
||||
# 0.6.5
|
||||
|
||||
> Mon 4th of September 2017
|
||||
|
||||
- Fix the formatting of floating values when the fractional part is `0`.
|
||||
|
||||
# 0.6.4
|
||||
|
||||
> Mon 4th of September 2017
|
||||
|
||||
- Fix the output for `show_struct_specifier`.
|
||||
|
||||
# 0.6.3
|
||||
|
||||
> Mon 4th of September 2017
|
||||
|
||||
- Fix the output for `show_struct_specifier`.
|
||||
|
||||
# 0.6.2
|
||||
|
||||
> Mon 4th of September 2017
|
||||
|
||||
- Remove a warning.
|
||||
|
||||
# 0.6.1
|
||||
|
||||
> Mon 4th of September 2017
|
||||
|
||||
- Fix `show_struct_specifier`.
|
||||
|
||||
# 0.6
|
||||
|
||||
> Fri 1st of September 2017
|
||||
|
||||
- The `TypeSpecifier` type was wrong as it didn’t carry any `ArraySpecifier` information while the
|
||||
GLSL specification’s grammar about type specifiers states they should. Fixed.
|
||||
|
||||
# 0.5
|
||||
|
||||
> Mon 7th of August 2017
|
||||
|
||||
- The `parse` and `parse_str` functions now take as second argument the parser to run. This enables
|
||||
using those functions and all the neat logic the wrap in dependent projects.
|
||||
|
||||
# 0.4.2
|
||||
|
||||
> Fri 4th of August 2017
|
||||
|
||||
- A GLSL writer is now available.
|
||||
- Some parsers yield non-empty list of syntax trees. Those had the incorrect `Vec` type. They were
|
||||
replaced by `NonEmpty`, which is an alias to `Vec`, but carry the semantic that it has at least
|
||||
one element in it.
|
||||
|
||||
# 0.4.1
|
||||
|
||||
> Thu 3rd of August 2017
|
||||
|
||||
- Uni/multi-line comments are now supported.
|
||||
|
||||
# 0.4
|
||||
|
||||
> Wed 2nd of August 2017
|
||||
|
||||
- The `Declaration::Block` variant was refactored for a better usage.
|
||||
- Dot field selections and, in a mory general way, postfix expressions completely fixed. The
|
||||
`syntax` module was altered to make it easier to work with dot field selection. Also related,
|
||||
the function identifier syntax is now isomorphic to an identifier.
|
||||
|
||||
# 0.3.1
|
||||
|
||||
> Tue 1st of August 2017
|
||||
|
||||
- Fix the `preprocessor` parser so that it eats surrounding blanks.
|
||||
|
||||
# 0.3
|
||||
|
||||
> Mon 31st of July 2017
|
||||
|
||||
- Add a very minimalistic yet working preprocessor. It parses `#version` and `#extension`
|
||||
commands. Those have to be declared at the top of your file, even though this implementation
|
||||
accepts them at any place an external declaration could be defined. Feel free to submit a PR
|
||||
if you want to change that behavior, I don’t really mind.
|
||||
- Enhance the runtime error reporting. It’s not perfect, but it’s way better than before!
|
||||
- `void` is now recognized as `TypeSpecifier::Void` instead of the erroneous
|
||||
`TypeSpecifier::TypeName("void")`.
|
||||
|
||||
# 0.2.2
|
||||
|
||||
> Mon 31st of July 2017
|
||||
|
||||
- The `layout` parser had a nasty bug that would treat a list of key-value pairs as an expression
|
||||
assignment. This was fixed and it now treats it as a list of pairs of identifier associated with a
|
||||
possible constant expression.
|
||||
- The `StructFieldSpecifier` type and its associated parser were wrong. Was missing:
|
||||
+ the type qualifier
|
||||
+ for each identifier defined in the field specifier, its optional array specifier, as in
|
||||
`float foo[3];` or `vec3 bar[];` for unsized ones.
|
||||
|
||||
# 0.2.1
|
||||
|
||||
> Sun 30th of July 2017
|
||||
|
||||
- More documentation to help people to get their feet wet.
|
||||
|
||||
# 0.2
|
||||
|
||||
> Sat 29th of July 2017
|
||||
|
||||
- The whole parsing API is public.
|
||||
|
||||
# 0.1
|
||||
|
||||
- Initial revision.
|
|
@ -1,39 +0,0 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "glsl"
|
||||
version = "4.0.3"
|
||||
authors = ["Dimitri Sabadie <dimitri.sabadie@gmail.com>"]
|
||||
description = "A GLSL450/GLSL460 parser."
|
||||
homepage = "https://github.com/phaazon/glsl"
|
||||
documentation = "https://docs.rs/glsl"
|
||||
readme = "README.md"
|
||||
keywords = ["GLSL", "OpenGL", "SPIR-V", "parser"]
|
||||
categories = ["parsing", "rendering"]
|
||||
license = "BSD-3-Clause"
|
||||
repository = "https://github.com/phaazon/glsl"
|
||||
[dependencies.nom]
|
||||
version = "5"
|
||||
features = ["std"]
|
||||
default-features = false
|
||||
|
||||
[dependencies.shaderc]
|
||||
version = "0.6"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
spirv = ["shaderc"]
|
||||
[badges.travis-ci]
|
||||
branch = "master"
|
||||
repository = "phaazon/glsl"
|
|
@ -1,30 +0,0 @@
|
|||
Copyright (c) 2018, Dimitri Sabadie <dimitri.sabadie@gmail.com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Dimitri Sabadie <dimitri.sabadie@gmail.com> nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,127 +0,0 @@
|
|||
[![Talk on IRC!](https://img.shields.io/badge/chat-%23glsl--rs%40irc.freenode.net-blueviolet)](https://webchat.freenode.net)
|
||||
[![Build Status](https://travis-ci.org/phaazon/glsl.svg?branch=master)](https://travis-ci.org/phaazon/glsl)
|
||||
[![crates.io](https://img.shields.io/crates/v/glsl.svg)](https://crates.io/crates/glsl)
|
||||
[![docs.rs](https://docs.rs/glsl/badge.svg)](https://docs.rs/glsl)
|
||||
![License](https://img.shields.io/badge/license-BSD3-blue.svg?style=flat)
|
||||
|
||||
<!-- cargo-sync-readme start -->
|
||||
|
||||
This crate is a GLSL450/GLSL460 compiler. It’s able to parse valid GLSL formatted source into
|
||||
an abstract syntax tree (AST). That AST can then be transformed into SPIR-V, your own format or
|
||||
even folded back to a raw GLSL [`String`] (think of a minifier, for instance).
|
||||
|
||||
You’ll find several modules:
|
||||
|
||||
- [`parser`], which exports the parsing interface. This is the place you will get most
|
||||
interesting types and traits, such as [`Parse`] and [`ParseError`].
|
||||
- [`syntax`], which exports the AST and language definitions. If you look into destructuring,
|
||||
transpiling or getting information on the GLSL code that got parsed, you will likely
|
||||
manipulate objects which types are defined in this module.
|
||||
- [`transpiler`], which provides you with GLSL transpilers. For instance, you will find _GLSL
|
||||
to GLSL_ transpiler, _GLSL to SPIR-V_ transpiler, etc.
|
||||
- [`visitor`](visitor), which gives you a way to visit AST nodes and mutate them, both with
|
||||
inner and outer mutation.
|
||||
|
||||
Feel free to inspect those modules for further information.
|
||||
|
||||
# GLSL parsing and transpiling
|
||||
|
||||
Parsing is the most common operation you will do. It is not required per-se (you can still
|
||||
create your AST by hand or use [glsl-quasiquote] to create it at compile-time by using the GLSL
|
||||
syntax directly in Rust). However, in this section, we are going to see how we can parse from a
|
||||
string to several GLSL types.
|
||||
|
||||
## Parsing architecture
|
||||
|
||||
Basically, the [`Parse`] trait gives you all you need to start parsing. This crate is designed
|
||||
around the concept of type-driven parsing: parsers are hidden and you just have to state what
|
||||
result type you expect.
|
||||
|
||||
The most common type you want to parse to is [`TranslationUnit`], which represents a set of
|
||||
[`ExternalDeclaration`]s. An [`ExternalDeclaration`] is just a declaration at the top-most level
|
||||
of a shader. It can be a global, uniform declarations, vertex attributes, a function, a
|
||||
structure, etc. In that sense, a [`TranslationUnit`] is akin to a shader stage (vertex shader,
|
||||
fragment shader, etc.).
|
||||
|
||||
You can parse any type that implements [`Parse`]. Parsers are mostly sensible to external
|
||||
blanks, which means that parsing an [`Expr`] starting with a blank will not work (this is not
|
||||
true for a [`TranslationUnit`] as it’s exceptionnally more permissive).
|
||||
|
||||
## Parsing an expression
|
||||
|
||||
Let’s try to parse an expression.
|
||||
|
||||
```rust
|
||||
use glsl::parser::Parse;
|
||||
use glsl::syntax::Expr;
|
||||
|
||||
let glsl = "(vec3(r, g, b) * cos(t * PI * .5)).xxz";
|
||||
let expr = Expr::parse(glsl);
|
||||
assert!(expr.is_ok());
|
||||
```
|
||||
|
||||
Here, `expr` is an AST which type is `Result<Expr, ParseError>` that represents the GLSL
|
||||
expression `(vec3(r, g, b) * cos(t * PI * .5)).xxz`, which is an outer (scalar) multiplication
|
||||
of an RGB color by a cosine of a time, the whole thing being
|
||||
[swizzled](https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)) with XXZ. It is your
|
||||
responsibility to check if the parsing process has succeeded.
|
||||
|
||||
In the previous example, the GLSL string is a constant and hardcoded. It could come from a file,
|
||||
network or built on the fly, but in the case of constant GLSL code, it would be preferable not
|
||||
to parse the string at runtime, right? Well, [glsl-quasiquote] is there exactly for that. You
|
||||
can ask **rustc** to parse that string and, if the parsing has succeeded, inject the AST
|
||||
directly into your code. No [`Result`], just the pure AST. Have a look at [glsl-quasiquote] for
|
||||
further details.
|
||||
|
||||
## Parsing a whole shader
|
||||
|
||||
Vertex shaders, geometry shaders, fragment shaders and control and evaluation tessellation
|
||||
shaders can be parsed the same way by using one of the `TranslationUnit` or `ShaderStage` types.
|
||||
|
||||
Here, a simple vertex shader being parsed.
|
||||
|
||||
```rust
|
||||
use glsl::parser::Parse;
|
||||
use glsl::syntax::ShaderStage;
|
||||
|
||||
let glsl = "
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec4 col;
|
||||
|
||||
out vec4 v_col;
|
||||
|
||||
uniform mat4 projview;
|
||||
|
||||
void main() {
|
||||
v_col = col; // pass color to the next stage
|
||||
gl_Position = projview * vec4(pos, 1.);
|
||||
}
|
||||
";
|
||||
let stage = ShaderStage::parse(glsl);
|
||||
assert!(stage.is_ok());
|
||||
```
|
||||
|
||||
## Visiting AST nodes
|
||||
|
||||
The crate is also getting more and more combinators and functions to transform the AST or create
|
||||
nodes with regular Rust. The [`Visitor`] trait will be a great friend of yours when you will
|
||||
want to cope with deep mutation, filtering and validation. Have a look at the
|
||||
[`visitor`](visitor) module for a tutorial on how to use visitors.
|
||||
|
||||
# About the GLSL versions…
|
||||
|
||||
This crate can parse both GLSL450 and GLSL460 formatted input sources. At the language level,
|
||||
the difference between GLSL450 and GLSL460 is pretty much nothing, so both cases are covered.
|
||||
|
||||
> If you’re wondering, the only difference between both versions is that in GLSL460, it’s
|
||||
> authorized to have semicolons (`;`) on empty lines at top-level in a shader.
|
||||
|
||||
[glsl-quasiquote]: https://crates.io/crates/glsl-quasiquote
|
||||
[`Parse`]: crate::parser::Parse
|
||||
[`ParseError`]: crate::parser::ParseError
|
||||
[`ExternalDeclaration`]: crate::syntax::ExternalDeclaration
|
||||
[`TranslationUnit`]: crate::syntax::TranslationUnit
|
||||
[`Expr`]: crate::syntax::Expr
|
||||
[`Visitor`]: crate::visitor::Visitor
|
||||
|
||||
<!-- cargo-sync-readme end -->
|
|
@ -1,6 +0,0 @@
|
|||
buffer Foo {
|
||||
char tiles[];
|
||||
} main_tiles;
|
||||
|
||||
void main() {
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
layout(set = 0, binding = 0) buffer Foo {
|
||||
char a;
|
||||
} foo;
|
|
@ -1,125 +0,0 @@
|
|||
//! This crate is a GLSL450/GLSL460 compiler. It’s able to parse valid GLSL formatted source into
|
||||
//! an abstract syntax tree (AST). That AST can then be transformed into SPIR-V, your own format or
|
||||
//! even folded back to a raw GLSL [`String`] (think of a minifier, for instance).
|
||||
//!
|
||||
//! You’ll find several modules:
|
||||
//!
|
||||
//! - [`parser`], which exports the parsing interface. This is the place you will get most
|
||||
//! interesting types and traits, such as [`Parse`] and [`ParseError`].
|
||||
//! - [`syntax`], which exports the AST and language definitions. If you look into destructuring,
|
||||
//! transpiling or getting information on the GLSL code that got parsed, you will likely
|
||||
//! manipulate objects which types are defined in this module.
|
||||
//! - [`transpiler`], which provides you with GLSL transpilers. For instance, you will find _GLSL
|
||||
//! to GLSL_ transpiler, _GLSL to SPIR-V_ transpiler, etc.
|
||||
//! - [`visitor`](visitor), which gives you a way to visit AST nodes and mutate them, both with
|
||||
//! inner and outer mutation.
|
||||
//!
|
||||
//! Feel free to inspect those modules for further information.
|
||||
//!
|
||||
//! # GLSL parsing and transpiling
|
||||
//!
|
||||
//! Parsing is the most common operation you will do. It is not required per-se (you can still
|
||||
//! create your AST by hand or use [glsl-quasiquote] to create it at compile-time by using the GLSL
|
||||
//! syntax directly in Rust). However, in this section, we are going to see how we can parse from a
|
||||
//! string to several GLSL types.
|
||||
//!
|
||||
//! ## Parsing architecture
|
||||
//!
|
||||
//! Basically, the [`Parse`] trait gives you all you need to start parsing. This crate is designed
|
||||
//! around the concept of type-driven parsing: parsers are hidden and you just have to state what
|
||||
//! result type you expect.
|
||||
//!
|
||||
//! The most common type you want to parse to is [`TranslationUnit`], which represents a set of
|
||||
//! [`ExternalDeclaration`]s. An [`ExternalDeclaration`] is just a declaration at the top-most level
|
||||
//! of a shader. It can be a global, uniform declarations, vertex attributes, a function, a
|
||||
//! structure, etc. In that sense, a [`TranslationUnit`] is akin to a shader stage (vertex shader,
|
||||
//! fragment shader, etc.).
|
||||
//!
|
||||
//! You can parse any type that implements [`Parse`]. Parsers are mostly sensible to external
|
||||
//! blanks, which means that parsing an [`Expr`] starting with a blank will not work (this is not
|
||||
//! true for a [`TranslationUnit`] as it’s exceptionnally more permissive).
|
||||
//!
|
||||
//! ## Parsing an expression
|
||||
//!
|
||||
//! Let’s try to parse an expression.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use glsl::parser::Parse;
|
||||
//! use glsl::syntax::Expr;
|
||||
//!
|
||||
//! let glsl = "(vec3(r, g, b) * cos(t * PI * .5)).xxz";
|
||||
//! let expr = Expr::parse(glsl);
|
||||
//! assert!(expr.is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! Here, `expr` is an AST which type is `Result<Expr, ParseError>` that represents the GLSL
|
||||
//! expression `(vec3(r, g, b) * cos(t * PI * .5)).xxz`, which is an outer (scalar) multiplication
|
||||
//! of an RGB color by a cosine of a time, the whole thing being
|
||||
//! [swizzled](https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)) with XXZ. It is your
|
||||
//! responsibility to check if the parsing process has succeeded.
|
||||
//!
|
||||
//! In the previous example, the GLSL string is a constant and hardcoded. It could come from a file,
|
||||
//! network or built on the fly, but in the case of constant GLSL code, it would be preferable not
|
||||
//! to parse the string at runtime, right? Well, [glsl-quasiquote] is there exactly for that. You
|
||||
//! can ask **rustc** to parse that string and, if the parsing has succeeded, inject the AST
|
||||
//! directly into your code. No [`Result`], just the pure AST. Have a look at [glsl-quasiquote] for
|
||||
//! further details.
|
||||
//!
|
||||
//! ## Parsing a whole shader
|
||||
//!
|
||||
//! Vertex shaders, geometry shaders, fragment shaders and control and evaluation tessellation
|
||||
//! shaders can be parsed the same way by using one of the `TranslationUnit` or `ShaderStage` types.
|
||||
//!
|
||||
//! Here, a simple vertex shader being parsed.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use glsl::parser::Parse;
|
||||
//! use glsl::syntax::ShaderStage;
|
||||
//!
|
||||
//! let glsl = "
|
||||
//! layout (location = 0) in vec3 pos;
|
||||
//! layout (location = 1) in vec4 col;
|
||||
//!
|
||||
//! out vec4 v_col;
|
||||
//!
|
||||
//! uniform mat4 projview;
|
||||
//!
|
||||
//! void main() {
|
||||
//! v_col = col; // pass color to the next stage
|
||||
//! gl_Position = projview * vec4(pos, 1.);
|
||||
//! }
|
||||
//! ";
|
||||
//! let stage = ShaderStage::parse(glsl);
|
||||
//! assert!(stage.is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! ## Visiting AST nodes
|
||||
//!
|
||||
//! The crate is also getting more and more combinators and functions to transform the AST or create
|
||||
//! nodes with regular Rust. The [`Visitor`] trait will be a great friend of yours when you will
|
||||
//! want to cope with deep mutation, filtering and validation. Have a look at the
|
||||
//! [`visitor`](visitor) module for a tutorial on how to use visitors.
|
||||
//!
|
||||
//! # About the GLSL versions…
|
||||
//!
|
||||
//! This crate can parse both GLSL450 and GLSL460 formatted input sources. At the language level,
|
||||
//! the difference between GLSL450 and GLSL460 is pretty much nothing, so both cases are covered.
|
||||
//!
|
||||
//! > If you’re wondering, the only difference between both versions is that in GLSL460, it’s
|
||||
//! > authorized to have semicolons (`;`) on empty lines at top-level in a shader.
|
||||
//!
|
||||
//! [glsl-quasiquote]: https://crates.io/crates/glsl-quasiquote
|
||||
//! [`Parse`]: crate::parser::Parse
|
||||
//! [`ParseError`]: crate::parser::ParseError
|
||||
//! [`ExternalDeclaration`]: crate::syntax::ExternalDeclaration
|
||||
//! [`TranslationUnit`]: crate::syntax::TranslationUnit
|
||||
//! [`Expr`]: crate::syntax::Expr
|
||||
//! [`Visitor`]: crate::visitor::Visitor
|
||||
|
||||
#[cfg(test)]
|
||||
mod parse_tests;
|
||||
pub mod parser;
|
||||
mod parsers;
|
||||
pub mod syntax;
|
||||
pub mod transpiler;
|
||||
pub mod visitor;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,119 +0,0 @@
|
|||
//! GLSL parsing.
|
||||
//!
|
||||
//! This module gives you several functions and types to deal with GLSL parsing, transforming an
|
||||
//! input source into an AST. The AST is defined in the [`syntax`] module.
|
||||
//!
|
||||
//! You want to use the [`Parse`]’s methods to get starting with parsing and pattern match on
|
||||
//! the resulting [`Result`]. In case of an error, you can inspect the content of the [`ParseError`]
|
||||
//! object in the `Err` variant.
|
||||
//!
|
||||
//! [`Parse`]: crate::parser::Parse
|
||||
//! [`ParseError`]: crate::parser::ParseError
|
||||
|
||||
use nom::error::convert_error;
|
||||
use nom::Err as NomErr;
|
||||
use std::fmt;
|
||||
|
||||
use crate::parsers::ParserResult;
|
||||
use crate::syntax;
|
||||
|
||||
/// A parse error. It contains a [`String`] giving information on the reason why the parser failed.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ParseError {
|
||||
pub info: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "error: {}", self.info)
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a parser `P` on a given `[&str`] input.
|
||||
pub(crate) fn run_parser<P, T>(source: &str, parser: P) -> Result<T, ParseError>
|
||||
where
|
||||
P: FnOnce(&str) -> ParserResult<T>,
|
||||
{
|
||||
match parser(source) {
|
||||
Ok((_, x)) => Ok(x),
|
||||
|
||||
Err(e) => match e {
|
||||
NomErr::Incomplete(_) => Err(ParseError {
|
||||
info: "incomplete parser".to_owned(),
|
||||
}),
|
||||
|
||||
NomErr::Error(err) | NomErr::Failure(err) => {
|
||||
let info = convert_error(source, err);
|
||||
Err(ParseError { info })
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Class of types that can be parsed.
|
||||
///
|
||||
/// This trait exposes the [`Parse::parse`] function that can be used to parse GLSL types.
|
||||
///
|
||||
/// The methods from this trait are the standard way to parse data into GLSL ASTs.
|
||||
pub trait Parse: Sized {
|
||||
/// Parse from a string slice.
|
||||
fn parse<B>(source: B) -> Result<Self, ParseError>
|
||||
where
|
||||
B: AsRef<str>;
|
||||
}
|
||||
|
||||
/// Macro to implement Parse for a given type.
|
||||
macro_rules! impl_parse {
|
||||
($type_name:ty, $parser_name:ident) => {
|
||||
impl Parse for $type_name {
|
||||
fn parse<B>(source: B) -> Result<Self, ParseError>
|
||||
where
|
||||
B: AsRef<str>,
|
||||
{
|
||||
run_parser(source.as_ref(), $crate::parsers::$parser_name)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_parse!(syntax::Identifier, identifier);
|
||||
impl_parse!(syntax::TypeSpecifierNonArray, type_specifier_non_array);
|
||||
impl_parse!(syntax::TypeSpecifier, type_specifier);
|
||||
impl_parse!(syntax::UnaryOp, unary_op);
|
||||
impl_parse!(syntax::StructFieldSpecifier, struct_field_specifier);
|
||||
impl_parse!(syntax::StructSpecifier, struct_specifier);
|
||||
impl_parse!(syntax::StorageQualifier, storage_qualifier);
|
||||
impl_parse!(syntax::LayoutQualifier, layout_qualifier);
|
||||
impl_parse!(syntax::PrecisionQualifier, precision_qualifier);
|
||||
impl_parse!(syntax::InterpolationQualifier, interpolation_qualifier);
|
||||
impl_parse!(syntax::TypeQualifier, type_qualifier);
|
||||
impl_parse!(syntax::TypeQualifierSpec, type_qualifier_spec);
|
||||
impl_parse!(syntax::FullySpecifiedType, fully_specified_type);
|
||||
impl_parse!(syntax::ArraySpecifier, array_specifier);
|
||||
impl_parse!(syntax::Expr, expr);
|
||||
impl_parse!(syntax::Declaration, declaration);
|
||||
impl_parse!(syntax::FunctionPrototype, function_prototype);
|
||||
impl_parse!(syntax::InitDeclaratorList, init_declarator_list);
|
||||
impl_parse!(syntax::SingleDeclaration, single_declaration);
|
||||
impl_parse!(syntax::Initializer, initializer);
|
||||
impl_parse!(syntax::FunIdentifier, function_identifier);
|
||||
impl_parse!(syntax::AssignmentOp, assignment_op);
|
||||
impl_parse!(syntax::SimpleStatement, simple_statement);
|
||||
impl_parse!(syntax::ExprStatement, expr_statement);
|
||||
impl_parse!(syntax::SelectionStatement, selection_statement);
|
||||
impl_parse!(syntax::SwitchStatement, switch_statement);
|
||||
impl_parse!(syntax::CaseLabel, case_label);
|
||||
impl_parse!(syntax::IterationStatement, iteration_statement);
|
||||
impl_parse!(syntax::JumpStatement, jump_statement);
|
||||
impl_parse!(syntax::Condition, condition);
|
||||
impl_parse!(syntax::Statement, statement);
|
||||
impl_parse!(syntax::CompoundStatement, compound_statement);
|
||||
impl_parse!(syntax::FunctionDefinition, function_definition);
|
||||
impl_parse!(syntax::ExternalDeclaration, external_declaration);
|
||||
impl_parse!(syntax::TranslationUnit, translation_unit);
|
||||
impl_parse!(syntax::Preprocessor, preprocessor);
|
||||
impl_parse!(syntax::PreprocessorVersion, pp_version);
|
||||
impl_parse!(syntax::PreprocessorVersionProfile, pp_version_profile);
|
||||
impl_parse!(syntax::PreprocessorExtensionName, pp_extension_name);
|
||||
impl_parse!(syntax::PreprocessorExtensionBehavior, pp_extension_behavior);
|
||||
impl_parse!(syntax::PreprocessorExtension, pp_extension);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,95 +0,0 @@
|
|||
//! Various nom parser helpers.
|
||||
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::{anychar, multispace1, newline};
|
||||
use nom::combinator::{map, recognize, value};
|
||||
use nom::error::{ErrorKind, VerboseError, VerboseErrorKind};
|
||||
use nom::multi::fold_many0;
|
||||
use nom::{Err as NomErr, IResult};
|
||||
|
||||
pub type ParserResult<'a, O> = IResult<&'a str, O, VerboseError<&'a str>>;
|
||||
|
||||
// A constant parser that just forwards the value it’s parametered with without reading anything
|
||||
// from the input. Especially useful as “fallback” in an alternative parser.
|
||||
pub fn cnst<'a, T, E>(t: T) -> impl Fn(&'a str) -> Result<(&'a str, T), E>
|
||||
where
|
||||
T: 'a + Clone,
|
||||
{
|
||||
move |i| Ok((i, t.clone()))
|
||||
}
|
||||
|
||||
// End-of-input parser.
|
||||
//
|
||||
// Yields `()` if the parser is at the end of the input; an error otherwise.
|
||||
pub fn eoi(i: &str) -> ParserResult<()> {
|
||||
if i.is_empty() {
|
||||
Ok((i, ()))
|
||||
} else {
|
||||
Err(NomErr::Error(VerboseError {
|
||||
errors: vec![(i, VerboseErrorKind::Nom(ErrorKind::Eof))],
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
// A newline parser that accepts:
|
||||
//
|
||||
// - A newline.
|
||||
// - The end of input.
|
||||
pub fn eol(i: &str) -> ParserResult<()> {
|
||||
alt((
|
||||
eoi, // this one goes first because it’s very cheap
|
||||
value((), newline),
|
||||
))(i)
|
||||
}
|
||||
|
||||
// Apply the `f` parser until `g` succeeds. Both parsers consume the input.
|
||||
pub fn till<'a, A, B, F, G>(f: F, g: G) -> impl Fn(&'a str) -> ParserResult<'a, ()>
|
||||
where
|
||||
F: Fn(&'a str) -> ParserResult<'a, A>,
|
||||
G: Fn(&'a str) -> ParserResult<'a, B>,
|
||||
{
|
||||
move |mut i| loop {
|
||||
if let Ok((i2, _)) = g(i) {
|
||||
break Ok((i2, ()));
|
||||
}
|
||||
|
||||
let (i2, _) = f(i)?;
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
|
||||
// A version of many0 that discards the result of the parser, preventing allocating.
|
||||
pub fn many0_<'a, A, F>(f: F) -> impl Fn(&'a str) -> ParserResult<'a, ()>
|
||||
where
|
||||
F: Fn(&'a str) -> ParserResult<'a, A>,
|
||||
{
|
||||
move |i| fold_many0(&f, (), |_, _| ())(i)
|
||||
}
|
||||
|
||||
/// Parse a string until the end of line.
|
||||
///
|
||||
/// This parser accepts the multiline annotation (\) to break the string on several lines.
|
||||
///
|
||||
/// Discard any leading newline.
|
||||
pub fn str_till_eol(i: &str) -> ParserResult<&str> {
|
||||
map(
|
||||
recognize(till(alt((value((), tag("\\\n")), value((), anychar))), eol)),
|
||||
|i| {
|
||||
if i.as_bytes().last() == Some(&b'\n') {
|
||||
&i[0..i.len() - 1]
|
||||
} else {
|
||||
i
|
||||
}
|
||||
},
|
||||
)(i)
|
||||
}
|
||||
|
||||
// Blank base parser.
|
||||
//
|
||||
// This parser succeeds with multispaces and multiline annotation.
|
||||
//
|
||||
// Taylor Swift loves it.
|
||||
pub fn blank_space(i: &str) -> ParserResult<&str> {
|
||||
recognize(many0_(alt((multispace1, tag("\\\n")))))(i)
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,8 +0,0 @@
|
|||
//! GLSL transpilers – i.e. going from GLSL to anything else.
|
||||
//!
|
||||
//! There’s no public interface / trait to define what a transpiler is. It depends on the target
|
||||
//! representation you aim.
|
||||
|
||||
pub mod glsl;
|
||||
#[cfg(feature = "spirv")]
|
||||
pub mod spirv;
|
|
@ -1,95 +0,0 @@
|
|||
//! SPIR-V transpiler.
|
||||
//!
|
||||
//! The current implementation uses the [shaderc](https://crates.io/crates/shaderc) crate to
|
||||
//! transpile GLSL to SPIR-V. This is not ideal but will provide a default and starting
|
||||
//! implementation.
|
||||
|
||||
use shaderc;
|
||||
|
||||
use crate::syntax;
|
||||
use crate::transpiler::glsl as glsl_transpiler;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum ShaderKind {
|
||||
TessControl,
|
||||
TessEvaluation,
|
||||
Vertex,
|
||||
Geometry,
|
||||
Fragment,
|
||||
Compute,
|
||||
}
|
||||
|
||||
impl From<ShaderKind> for shaderc::ShaderKind {
|
||||
fn from(kind: ShaderKind) -> Self {
|
||||
match kind {
|
||||
ShaderKind::TessControl => shaderc::ShaderKind::TessControl,
|
||||
ShaderKind::TessEvaluation => shaderc::ShaderKind::TessEvaluation,
|
||||
ShaderKind::Vertex => shaderc::ShaderKind::Vertex,
|
||||
ShaderKind::Geometry => shaderc::ShaderKind::Geometry,
|
||||
ShaderKind::Fragment => shaderc::ShaderKind::Fragment,
|
||||
ShaderKind::Compute => shaderc::ShaderKind::Compute,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Transpile a GLSL AST into a SPIR-V internal buffer and write it to the given buffer.
|
||||
///
|
||||
/// The current implementation is highly inefficient as it relies on internal allocations and
|
||||
/// [shaderc](https://crates.io/crates/shaderc).
|
||||
///
|
||||
/// If any error happens while transpiling, they’re returned as an opaque string.
|
||||
pub fn transpile_translation_unit_to_binary<F>(
|
||||
f: &mut F,
|
||||
tu: &syntax::TranslationUnit,
|
||||
kind: ShaderKind,
|
||||
) -> Result<(), String>
|
||||
where
|
||||
F: std::io::Write,
|
||||
{
|
||||
// write as GLSL in an intermediate buffer
|
||||
let mut glsl_buffer = String::new();
|
||||
glsl_transpiler::show_translation_unit(&mut glsl_buffer, tu);
|
||||
|
||||
// pass the GLSL-formatted string to shaderc
|
||||
let mut compiler = shaderc::Compiler::new().unwrap();
|
||||
let options = shaderc::CompileOptions::new().unwrap();
|
||||
let kind = kind.into();
|
||||
let output = compiler
|
||||
.compile_into_spirv(&glsl_buffer, kind, "glsl input", "main", Some(&options))
|
||||
.map_err(|e| format!("{}", e))?;
|
||||
|
||||
let _ = f.write_all(output.as_binary_u8());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Transpile a GLSL AST into a SPIR-V internal buffer and write it to the given buffer.
|
||||
///
|
||||
/// The current implementation is highly inefficient as it relies on internal allocations and
|
||||
/// [shaderc](https://crates.io/crates/shaderc).
|
||||
///
|
||||
/// If any error happens while transpiling, they’re returned as an opaque string.
|
||||
pub fn transpile_translation_unit<F>(
|
||||
f: &mut F,
|
||||
tu: &syntax::TranslationUnit,
|
||||
kind: ShaderKind,
|
||||
) -> Result<(), String>
|
||||
where
|
||||
F: std::fmt::Write,
|
||||
{
|
||||
// write as GLSL in an intermediate buffer
|
||||
let mut glsl_buffer = String::new();
|
||||
glsl_transpiler::show_translation_unit(&mut glsl_buffer, tu);
|
||||
|
||||
// pass the GLSL-formatted string to shaderc
|
||||
let mut compiler = shaderc::Compiler::new().unwrap();
|
||||
let options = shaderc::CompileOptions::new().unwrap();
|
||||
let kind = kind.into();
|
||||
let output = compiler
|
||||
.compile_into_spirv_assembly(&glsl_buffer, kind, "glsl input", "main", Some(&options))
|
||||
.map_err(|e| format!("{}", e))?;
|
||||
|
||||
let _ = f.write_str(&output.as_text());
|
||||
|
||||
Ok(())
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,19 +0,0 @@
|
|||
use glsl::parser::Parse;
|
||||
use glsl::syntax;
|
||||
|
||||
#[test]
|
||||
fn incorrect_statement() {
|
||||
let r = syntax::TranslationUnit::parse(
|
||||
"
|
||||
int fetch_transform(int id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
bool ray_plane() {
|
||||
if 1 {
|
||||
}
|
||||
",
|
||||
);
|
||||
|
||||
assert!(r.is_err());
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
use glsl::parser::Parse;
|
||||
use glsl::syntax;
|
||||
|
||||
#[test]
|
||||
fn left_associativity() {
|
||||
let r = syntax::TranslationUnit::parse(
|
||||
"
|
||||
void main() {
|
||||
x = a + b + c;
|
||||
}
|
||||
",
|
||||
);
|
||||
|
||||
let expected = syntax::TranslationUnit::from_non_empty_iter(vec![
|
||||
syntax::ExternalDeclaration::FunctionDefinition(syntax::FunctionDefinition {
|
||||
prototype: syntax::FunctionPrototype {
|
||||
ty: syntax::FullySpecifiedType {
|
||||
qualifier: None,
|
||||
ty: syntax::TypeSpecifier {
|
||||
ty: syntax::TypeSpecifierNonArray::Void,
|
||||
array_specifier: None,
|
||||
},
|
||||
},
|
||||
name: "main".into(),
|
||||
parameters: Vec::new(),
|
||||
},
|
||||
statement: syntax::CompoundStatement {
|
||||
statement_list: vec![syntax::Statement::Simple(Box::new(
|
||||
syntax::SimpleStatement::Expression(Some(syntax::Expr::Assignment(
|
||||
Box::new(syntax::Expr::Variable("x".into())),
|
||||
syntax::AssignmentOp::Equal,
|
||||
Box::new(syntax::Expr::Binary(
|
||||
syntax::BinaryOp::Add,
|
||||
Box::new(syntax::Expr::Binary(
|
||||
syntax::BinaryOp::Add,
|
||||
Box::new(syntax::Expr::Variable("a".into())),
|
||||
Box::new(syntax::Expr::Variable("b".into())),
|
||||
)),
|
||||
Box::new(syntax::Expr::Variable("c".into())),
|
||||
)),
|
||||
))),
|
||||
))],
|
||||
},
|
||||
}),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(r, Ok(expected));
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
extern crate glsl;
|
||||
|
||||
use glsl::parser::Parse;
|
||||
use glsl::syntax::TranslationUnit;
|
||||
|
||||
#[test]
|
||||
fn missing_zero_float_is_valid() {
|
||||
let r = TranslationUnit::parse(
|
||||
"
|
||||
void main() {
|
||||
float x = 1. * .5;
|
||||
}",
|
||||
);
|
||||
|
||||
assert!(r.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_exp_is_valid() {
|
||||
let r = TranslationUnit::parse(
|
||||
"
|
||||
void main() {
|
||||
float x = 1e-5;
|
||||
}",
|
||||
);
|
||||
|
||||
assert!(r.is_ok());
|
||||
}
|
Загрузка…
Ссылка в новой задаче