mirror of
https://github.com/HeyPuter/gex.git
synced 2026-11-13 20:12:43 -10:00
gex-gl: the compatibility profile, generated from the Khronos registry
tools/gen_gl_compat.py gives every OpenGL command in gl.xml (GL 1.0-4.6
with what core removed, and every extension) a wire plan derived from the
registry's own parameter metadata -- types, `len`, `class` -- unless it
cannot be carried safely (callbacks, pointers to pointers, lengths left to
prose; 2520 planned, 465 left out, listed by --report). A plan is one
token per parameter: scalars, input and output arrays with their counts
(fixed, a parameter times N, pname-sized from one shared table, strings,
unpack pixel transfers that may be unpack-buffer offsets, glBitmap,
glCallLists), and vertex/index/indirect pointers as buffer offsets.
Opcodes are 8192 plus the command's index in the registry's sorted list,
so adding a policy never renumbers one. Protocol 13.
Generated from it:
- guest/gl/gl-compat-generated.inc: the Linux guest's entry points for
every planned command gexgl.c and the 4.4 transport do not define, each
one call to gexgen_call (gexgl.c), which interprets its plan;
- web/mesa/gl-compat-generated-{decoders,cases}.inc: the host decoder, a
function per command (gcc takes thousands of cases in one switch very
badly), shared by the browser's Mesa decoder and the native host;
- guest/gl/gl-pname-counts.h, guest/gl/gexgl-plan.h: what both ends size
arrays with;
- crates/gex-gl/src/compat_plans.rs: the table, tested for well-formedness.
The native host now runs every generated command: crates/gex-gl/native
builds the same C++ cases (and the 4.4 transport's, which the native host
never decoded) against the host's GL through eglGetProcAddress, plus the
hand-written opcodes host.rs lacked, copied from the Mesa decoder
(native/hand-cases.inc); host.rs hands it whatever it does not know. The
host's context is released after each batch, so a guest may submit from
any thread (wined3d's command-stream thread and its main one).
The guest's extension list grows with its exports (+135 claimable).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FYuLCHiLKSdV6EMSoZB8cZ
This commit is contained in:
25 files changed
+49422
-12
No files matched your search
Generated
+3
@@ -490,6 +490,9 @@ version = "0.0.1"
|
||||
[[package]]
|
||||
name = "gex-gl"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gex-gpu"
|
||||
|
||||
@@ -14,6 +14,11 @@ host = []
|
||||
|
||||
[dependencies]
|
||||
|
||||
# The native host's decoder for the generated commands is C++ shared with the
|
||||
# browser's (native/gexgl-native.cpp), built here when `host` is on.
|
||||
[build-dependencies]
|
||||
cc = "1.4"
|
||||
|
||||
# The host half links against the host's own GL. There is nothing to build on
|
||||
# a target that has none, and the guest half is C, so this is the only side
|
||||
# that needs a library at all.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
//! Builds native/gexgl-native.cpp, the native host's decoder for the
|
||||
//! generated GL commands (the same cases the browser's Mesa decoder runs),
|
||||
//! when the `host` feature is on and the target has a host GL.
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=native/gexgl-native.cpp");
|
||||
println!("cargo:rerun-if-changed=native/hand-cases.inc");
|
||||
println!("cargo:rerun-if-changed=src/proto.rs");
|
||||
for f in [
|
||||
"../../web/mesa/gl44-generated-cases.inc",
|
||||
"../../web/mesa/gl-compat-generated-cases.inc",
|
||||
"../../web/mesa/gexgl-compat-host.h",
|
||||
"../../guest/gl/gexgl-plan.h",
|
||||
"../../guest/gl/gexgl-pixel.h",
|
||||
"../../guest/gl/gl-pname-counts.h",
|
||||
] {
|
||||
println!("cargo:rerun-if-changed={f}");
|
||||
}
|
||||
let host = std::env::var_os("CARGO_FEATURE_HOST").is_some();
|
||||
let wasm = std::env::var("CARGO_CFG_TARGET_ARCH").as_deref() == Ok("wasm32");
|
||||
if !host || wasm {
|
||||
return;
|
||||
}
|
||||
// The 4.4 cases call some GL functions directly, which the browser's
|
||||
// Mesa links statically; here every one goes through the proc table
|
||||
// (native/gexgl-native.cpp's GEX_GL_CALL), as the native host links only
|
||||
// EGL and GLES.
|
||||
let cases = std::fs::read_to_string("../../web/mesa/gl44-generated-cases.inc").unwrap_or_default()
|
||||
+ &std::fs::read_to_string("native/hand-cases.inc").unwrap_or_default();
|
||||
let mut direct = std::collections::BTreeSet::new();
|
||||
let b = cases.as_bytes();
|
||||
for (i, _) in cases.match_indices("gl") {
|
||||
let starts = i == 0 || !(b[i - 1].is_ascii_alphanumeric() || b[i - 1] == b'_');
|
||||
if !starts || !b.get(i + 2).is_some_and(|c| c.is_ascii_uppercase()) {
|
||||
continue;
|
||||
}
|
||||
let end = i + cases[i..].find(|c: char| !(c.is_ascii_alphanumeric() || c == '_')).unwrap_or(0);
|
||||
if b.get(end) == Some(&b'(') {
|
||||
direct.insert(&cases[i..end]);
|
||||
}
|
||||
}
|
||||
let out = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
|
||||
let header: String =
|
||||
direct.iter().map(|f| format!("#define {f}(...) GEX_GL_CALL({f}, __VA_ARGS__)\n")).collect();
|
||||
std::fs::write(out.join("gexgl-direct-calls.h"), header).unwrap();
|
||||
// The hand-written opcodes' names, from proto.rs, for hand-cases.inc.
|
||||
let proto = std::fs::read_to_string("src/proto.rs").unwrap();
|
||||
let ops = &proto[proto.find("pub mod op {").unwrap()..];
|
||||
let ops = &ops[..ops.find("\n}").unwrap()];
|
||||
let mut names = String::new();
|
||||
for line in ops.lines() {
|
||||
let line = line.trim();
|
||||
if let Some(rest) = line.strip_prefix("pub const ") {
|
||||
if let Some((name, value)) = rest.split_once(": u32 = ") {
|
||||
let value = value.split(';').next().unwrap_or("0").trim();
|
||||
names += &format!(" {name} = {value},\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
std::fs::write(out.join("gexgl-hand-ops.h"), names).unwrap();
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.include(&out)
|
||||
.std("c++17")
|
||||
.file("native/gexgl-native.cpp")
|
||||
.flag_if_supported("-Wno-unused-function")
|
||||
.flag_if_supported("-Wno-unused-variable")
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.opt_level(2)
|
||||
.compile("gexgl_native");
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/* The native host's decoder for the generated commands: the GL 4.4
|
||||
* transport (web/mesa/gl44-generated-cases.inc) and the registry's
|
||||
* compatibility-profile commands (web/mesa/gl-compat-generated-cases.inc),
|
||||
* the same cases the browser's Mesa decoder runs, here against the host's
|
||||
* GL. crates/gex-gl/src/host.rs hands this any opcode its own decoder does
|
||||
* not know (gexgl_native_one).
|
||||
*
|
||||
* Object names: the native host runs the guest's buffer, texture and other
|
||||
* names as they are (a desktop compatibility context and GLES both accept
|
||||
* names they never generated), so those tables are the identity; programs
|
||||
* and shaders are named by the host's GL, and host.rs tells this side about
|
||||
* each (gexgl_native_name). Program pipelines are generated by these cases
|
||||
* themselves and kept here. */
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "../../../guest/gl/gexgl-pixel.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void* gexgen_proc(const char* name, const char* alias);
|
||||
|
||||
/* Each call site looks its function up once. */
|
||||
#define GEX_GL_CALL(function, ...) \
|
||||
([]() { \
|
||||
static const auto p__ = reinterpret_cast<decltype(&function)>(gexgen_proc(#function, nullptr)); \
|
||||
return p__; \
|
||||
}())(__VA_ARGS__)
|
||||
|
||||
void* gexgen_proc(const char* name, const char* alias) {
|
||||
void* f = reinterpret_cast<void*>(eglGetProcAddress(name));
|
||||
if (!f && alias) f = reinterpret_cast<void*>(eglGetProcAddress(alias));
|
||||
return f;
|
||||
}
|
||||
|
||||
void gexgen_missing(const char* name) {
|
||||
static std::unordered_set<std::string> said;
|
||||
if (said.insert(name).second) fprintf(stderr, "gex-gl: the host's GL has no %s; the call does nothing\n", name);
|
||||
}
|
||||
|
||||
gexgl_pixel_store pack_store = gexgl_default_pixel_store();
|
||||
gexgl_pixel_store unpack_store = gexgl_default_pixel_store();
|
||||
|
||||
struct Reader {
|
||||
const uint8_t* p;
|
||||
const uint8_t* end;
|
||||
bool ok = true;
|
||||
uint32_t u32() {
|
||||
if (end - p < 4) { ok = false; return 0; }
|
||||
uint32_t v; std::memcpy(&v, p, 4); p += 4; return v;
|
||||
}
|
||||
int32_t i32() { return static_cast<int32_t>(u32()); }
|
||||
uint64_t u64() {
|
||||
const uint64_t low = u32();
|
||||
const uint64_t high = u32();
|
||||
return low | (high << 32);
|
||||
}
|
||||
int64_t i64() { return static_cast<int64_t>(u64()); }
|
||||
float f32() { uint32_t u = u32(); float f; std::memcpy(&f, &u, 4); return f; }
|
||||
double f64() { uint64_t u = u64(); double f; std::memcpy(&f, &u, 8); return f; }
|
||||
const uint8_t* blob(uint32_t& n) {
|
||||
n = u32();
|
||||
if (!ok || static_cast<size_t>(end - p) < n) { ok = false; n = 0; return nullptr; }
|
||||
const uint32_t padded = n <= UINT32_MAX - 3u ? (n + 3u) & ~3u : 0;
|
||||
if (padded < n || static_cast<size_t>(end - p) < padded) {
|
||||
ok = false; n = 0; return nullptr;
|
||||
}
|
||||
const uint8_t* out = p; p += padded;
|
||||
return out;
|
||||
}
|
||||
std::string string() {
|
||||
uint32_t n; const uint8_t* s = blob(n);
|
||||
return s ? std::string(reinterpret_cast<const char*>(s), n) : std::string();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "../../../web/mesa/gexgl-compat-host.h"
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<uint8_t> reply;
|
||||
|
||||
void put_u32(uint32_t v) {
|
||||
const size_t at = reply.size(); reply.resize(at + 4); std::memcpy(reply.data() + at, &v, 4);
|
||||
}
|
||||
void put_u64(uint64_t v) {
|
||||
put_u32(static_cast<uint32_t>(v));
|
||||
put_u32(static_cast<uint32_t>(v >> 32));
|
||||
}
|
||||
void put_blob(const void* p, uint32_t n) {
|
||||
const size_t padded = (static_cast<size_t>(n) + 3u) & ~size_t{3};
|
||||
put_u32(n); const size_t at = reply.size(); reply.resize(at + padded, 0);
|
||||
if (p && n) std::memcpy(reply.data() + at, p, n);
|
||||
}
|
||||
|
||||
/* Names: the guest's, unless a command that has the host generate them
|
||||
* (samplers, vertex arrays, queries, transform feedbacks, program pipelines;
|
||||
* programs and shaders, which host.rs reports) mapped them to the host's. */
|
||||
std::unordered_map<uint32_t, GLuint> buffers, textures, framebuffers, renderbuffers, queries, samplers,
|
||||
vertex_arrays, transform_feedbacks, shaders, programs, program_pipelines;
|
||||
const GLuint default_vao = 0;
|
||||
GLint current_clear_stencil = 0;
|
||||
std::vector<GLenum> current_draw_buffers;
|
||||
|
||||
GLuint lookup(const std::unordered_map<uint32_t, GLuint>& map, uint32_t name) {
|
||||
if (!name) return 0;
|
||||
auto it = map.find(name);
|
||||
return it == map.end() ? name : it->second;
|
||||
}
|
||||
GLuint lookup_program_or_shader(uint32_t name) {
|
||||
auto p = programs.find(name);
|
||||
if (p != programs.end()) return p->second;
|
||||
return lookup(shaders, name);
|
||||
}
|
||||
uint32_t external_name(const std::unordered_map<uint32_t, GLuint>& map, GLuint name) {
|
||||
if (!name) return 0;
|
||||
for (const auto& [external, internal] : map)
|
||||
if (internal == name) return external;
|
||||
return name;
|
||||
}
|
||||
template <typename Fn>
|
||||
bool gexgl_negative_count(GLsizei n, Fn call) {
|
||||
if (n >= 0) return false;
|
||||
call(n, static_cast<GLuint*>(nullptr));
|
||||
return true;
|
||||
}
|
||||
#define GEXGEN_NAME(kind, name) lookup(kind, name)
|
||||
|
||||
size_t integer_query_components(GLenum pname) {
|
||||
switch (pname) {
|
||||
case GL_VIEWPORT:
|
||||
case GL_SCISSOR_BOX:
|
||||
case GL_COLOR_WRITEMASK:
|
||||
case GL_COLOR_CLEAR_VALUE:
|
||||
case GL_BLEND_COLOR:
|
||||
return 4;
|
||||
case GL_DEPTH_RANGE:
|
||||
case GL_MAX_VIEWPORT_DIMS:
|
||||
case GL_ALIASED_POINT_SIZE_RANGE:
|
||||
case GL_ALIASED_LINE_WIDTH_RANGE:
|
||||
case GL_POINT_SIZE_RANGE:
|
||||
case GL_SMOOTH_LINE_WIDTH_RANGE:
|
||||
case GL_VIEWPORT_BOUNDS_RANGE:
|
||||
case GL_POLYGON_MODE:
|
||||
return 2;
|
||||
case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
|
||||
case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
|
||||
return 3;
|
||||
case GL_COMPRESSED_TEXTURE_FORMATS: {
|
||||
GLint count = 0;
|
||||
glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &count);
|
||||
return static_cast<size_t>(std::clamp(count, 0, 4096));
|
||||
}
|
||||
case GL_PROGRAM_BINARY_FORMATS: {
|
||||
GLint count = 0;
|
||||
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &count);
|
||||
return static_cast<size_t>(std::clamp(count, 0, 4096));
|
||||
}
|
||||
case GL_SHADER_BINARY_FORMATS: {
|
||||
GLint count = 0;
|
||||
glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &count);
|
||||
return static_cast<size_t>(std::clamp(count, 0, 4096));
|
||||
}
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gexgl_state_query_components(GLenum pname) {
|
||||
return static_cast<uint32_t>(integer_query_components(pname));
|
||||
}
|
||||
|
||||
uint32_t uniform_components(GLuint program, GLint location) {
|
||||
GLint count = 0, max_name = 0;
|
||||
GEX_GL_CALL(glGetProgramiv, program, GL_ACTIVE_UNIFORMS, &count);
|
||||
GEX_GL_CALL(glGetProgramiv, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name);
|
||||
std::vector<char> name(std::max(max_name, 1));
|
||||
GLenum type = 0;
|
||||
for (GLint i = 0; i < count; ++i) {
|
||||
GLsizei length = 0; GLint size = 0; GLenum candidate = 0;
|
||||
GEX_GL_CALL(glGetActiveUniform, program, i, (GLsizei)name.size(), &length, &size, &candidate, name.data());
|
||||
if (GEX_GL_CALL(glGetUniformLocation, program, name.data()) == location) { type = candidate; break; }
|
||||
}
|
||||
switch (type) {
|
||||
case GL_FLOAT_VEC2: case GL_INT_VEC2: case GL_UNSIGNED_INT_VEC2: case GL_BOOL_VEC2:
|
||||
case GL_DOUBLE_VEC2: return 2;
|
||||
case GL_FLOAT_VEC3: case GL_INT_VEC3: case GL_UNSIGNED_INT_VEC3: case GL_BOOL_VEC3:
|
||||
case GL_DOUBLE_VEC3: return 3;
|
||||
case GL_FLOAT_VEC4: case GL_INT_VEC4: case GL_UNSIGNED_INT_VEC4: case GL_BOOL_VEC4:
|
||||
case GL_DOUBLE_VEC4: return 4;
|
||||
case GL_FLOAT_MAT2: case GL_DOUBLE_MAT2: return 4;
|
||||
case GL_FLOAT_MAT3: case GL_DOUBLE_MAT3: return 9;
|
||||
case GL_FLOAT_MAT4: case GL_DOUBLE_MAT4: return 16;
|
||||
case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT3x2:
|
||||
case GL_DOUBLE_MAT2x3: case GL_DOUBLE_MAT3x2: return 6;
|
||||
case GL_FLOAT_MAT2x4: case GL_FLOAT_MAT4x2:
|
||||
case GL_DOUBLE_MAT2x4: case GL_DOUBLE_MAT4x2: return 8;
|
||||
case GL_FLOAT_MAT3x4: case GL_FLOAT_MAT4x3:
|
||||
case GL_DOUBLE_MAT3x4: case GL_DOUBLE_MAT4x3: return 12;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The direct calls the 4.4 cases make, through the proc table like the rest
|
||||
* (generated by build.rs): the native host links only EGL and GLES, not a
|
||||
* desktop GL library. */
|
||||
#include "gexgl-direct-calls.h"
|
||||
|
||||
#include "../../../web/mesa/gl-compat-generated-decoders.inc"
|
||||
|
||||
/* The hand-written opcodes, by name (crates/gex-gl/src/proto.rs). */
|
||||
enum Op : uint32_t {
|
||||
#include "gexgl-hand-ops.h"
|
||||
};
|
||||
|
||||
bool one(uint32_t op, Reader& a) {
|
||||
switch (op) {
|
||||
#include "hand-cases.inc"
|
||||
#include "../../../web/mesa/gl44-generated-cases.inc"
|
||||
#include "../../../web/mesa/gl-compat-generated-cases.inc"
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return a.ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/* Run one generated command. 1 if it ran (its reply, possibly empty, at
|
||||
* *reply_out), 0 if the opcode is not one of them, -1 if it was malformed. */
|
||||
extern "C" int gexgl_native_one(uint32_t op, const uint8_t* body, size_t len,
|
||||
const uint8_t** reply_out, size_t* reply_len) {
|
||||
reply.clear();
|
||||
Reader a{body, body + len};
|
||||
const bool ok = one(op, a);
|
||||
const bool known = ok || !a.ok || op >= 1024;
|
||||
*reply_out = reply.data();
|
||||
*reply_len = reply.size();
|
||||
if (!known) return 0;
|
||||
if (!ok) return a.ok ? 0 : -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A glPixelStorei host.rs ran, which pixel-sized cases here read. */
|
||||
extern "C" void gexgl_native_pixel_store(uint32_t pname, int32_t param) {
|
||||
(void)gexgl_set_pixel_store(&pack_store, &unpack_store, pname, param);
|
||||
}
|
||||
|
||||
/* A shader (kind 0) or program (kind 1) host.rs created (host != 0) or
|
||||
* deleted (host == 0). */
|
||||
extern "C" void gexgl_native_name(uint32_t kind, uint32_t guest, uint32_t host) {
|
||||
auto& map = kind == 0 ? shaders : programs;
|
||||
if (host) map[guest] = host;
|
||||
else map.erase(guest);
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
/* The hand-written wire commands crates/gex-gl/src/host.rs does not decode
|
||||
* itself, for the native host: copied from the browser's decoder
|
||||
* (web/mesa/gexgl-mesa.cpp's `one`) by the list of opcodes host.rs lacks, so
|
||||
* a Linux guest's and opengl32's batches run the same on both hosts. Keep
|
||||
* them in step with that file. Included by gexgl-native.cpp, inside its
|
||||
* switch. */
|
||||
case DEPTH_MASK: glDepthMask(a.u32()); break;
|
||||
case HINT: { GLenum target=a.u32(), mode=a.u32(); glHint(target,mode); break; }
|
||||
case COLOR_MASK: { GLboolean r=a.u32(), g=a.u32(), b=a.u32(), alpha=a.u32(); glColorMask(r,g,b,alpha); break; }
|
||||
case BLEND_EQUATION: glBlendEquation(a.u32()); break;
|
||||
case BLEND_COLOR: { GLfloat r=a.f32(), g=a.f32(), b=a.f32(), alpha=a.f32(); glBlendColor(r,g,b,alpha); break; }
|
||||
case BLEND_EQUATION_SEPARATE: { GLenum rgb=a.u32(), alpha=a.u32(); glBlendEquationSeparate(rgb,alpha); break; }
|
||||
case CLEAR_BUFFER_FV: {
|
||||
GLenum b=a.u32(); GLint d=a.i32(); GLfloat v[4]; for(float& x:v)x=a.f32();
|
||||
glClearBufferfv(b,d,v);
|
||||
break;
|
||||
}
|
||||
case CLEAR_BUFFER_IV: {
|
||||
GLenum b=a.u32(); GLint d=a.i32(); GLint v[4]; for(int& x:v)x=a.i32();
|
||||
glClearBufferiv(b,d,v);
|
||||
break;
|
||||
}
|
||||
case CLEAR_BUFFER_UIV: {
|
||||
GLenum b=a.u32(); GLint d=a.i32(); GLuint v[4]; for(unsigned& x:v)x=a.u32();
|
||||
glClearBufferuiv(b,d,v);
|
||||
break;
|
||||
}
|
||||
case CLEAR_BUFFER_FI: {
|
||||
GLenum b=a.u32(); GLint d=a.i32(); GLfloat depth=a.f32(); GLint stencil=a.i32();
|
||||
glClearBufferfi(b,d,depth,stencil);
|
||||
break;
|
||||
}
|
||||
case STENCIL_FUNC: { GLenum func=a.u32(); GLint ref=a.i32(); GLuint mask=a.u32(); glStencilFunc(func,ref,mask); break; }
|
||||
case STENCIL_FUNC_SEPARATE: { GLenum face=a.u32(), func=a.u32(); GLint ref=a.i32(); GLuint mask=a.u32(); glStencilFuncSeparate(face,func,ref,mask); break; }
|
||||
case STENCIL_MASK: glStencilMask(a.u32()); break;
|
||||
case STENCIL_MASK_SEPARATE: { GLenum face=a.u32(); GLuint mask=a.u32(); glStencilMaskSeparate(face,mask); break; }
|
||||
case STENCIL_OP: { GLenum fail=a.u32(), zfail=a.u32(), zpass=a.u32(); glStencilOp(fail,zfail,zpass); break; }
|
||||
case STENCIL_OP_SEPARATE: { GLenum face=a.u32(), fail=a.u32(), zfail=a.u32(), zpass=a.u32(); glStencilOpSeparate(face,fail,zfail,zpass); break; }
|
||||
case POLYGON_OFFSET: { GLfloat factor=a.f32(), units=a.f32(); glPolygonOffset(factor,units); break; }
|
||||
case LINE_WIDTH: glLineWidth(a.f32()); break;
|
||||
case CLEAR_STENCIL: current_clear_stencil=a.i32(); glClearStencil(current_clear_stencil); break;
|
||||
case DEPTH_RANGE: { GLfloat near_value=a.f32(), far_value=a.f32(); glDepthRangef(near_value,far_value); break; }
|
||||
case GEN_QUERIES: {
|
||||
GLsizei n = a.i32();
|
||||
if (n < 0) { glGenQueries(n, nullptr); break; }
|
||||
std::vector<GLuint> ids(static_cast<size_t>(n)); glGenQueries(n, ids.data());
|
||||
for (GLsizei i = 0; i < n; ++i) queries[a.u32()] = ids[static_cast<size_t>(i)];
|
||||
break;
|
||||
}
|
||||
case DELETE_QUERIES: {
|
||||
GLsizei n = a.i32();
|
||||
if (n < 0) { glDeleteQueries(n, nullptr); break; }
|
||||
std::vector<GLuint> ids; ids.reserve(static_cast<size_t>(n));
|
||||
for (GLsizei i = 0; i < n; ++i) { uint32_t g=a.u32(); ids.push_back(lookup(queries,g)); queries.erase(g); }
|
||||
glDeleteQueries(n, ids.data()); break;
|
||||
}
|
||||
case IS_QUERY: put_u32(glIsQuery(lookup(queries, a.u32()))); break;
|
||||
case GEN_TRANSFORM_FEEDBACKS: {
|
||||
GLsizei n = a.i32();
|
||||
if (n < 0) { glGenTransformFeedbacks(n, nullptr); break; }
|
||||
std::vector<GLuint> ids(static_cast<size_t>(n)); glGenTransformFeedbacks(n, ids.data());
|
||||
for (GLsizei i = 0; i < n; ++i) transform_feedbacks[a.u32()] = ids[static_cast<size_t>(i)];
|
||||
break;
|
||||
}
|
||||
case DELETE_TRANSFORM_FEEDBACKS: {
|
||||
GLsizei n = a.i32();
|
||||
if (n < 0) { glDeleteTransformFeedbacks(n, nullptr); break; }
|
||||
std::vector<GLuint> ids; ids.reserve(static_cast<size_t>(n));
|
||||
for (GLsizei i = 0; i < n; ++i) { uint32_t g=a.u32(); ids.push_back(lookup(transform_feedbacks,g)); transform_feedbacks.erase(g); }
|
||||
glDeleteTransformFeedbacks(n, ids.data()); break;
|
||||
}
|
||||
case BIND_TRANSFORM_FEEDBACK: {
|
||||
GLenum target=a.u32(); GLuint id=lookup(transform_feedbacks,a.u32());
|
||||
glBindTransformFeedback(target,id); break;
|
||||
}
|
||||
case IS_TRANSFORM_FEEDBACK: put_u32(glIsTransformFeedback(lookup(transform_feedbacks,a.u32()))); break;
|
||||
case PAUSE_TRANSFORM_FEEDBACK: glPauseTransformFeedback(); break;
|
||||
case RESUME_TRANSFORM_FEEDBACK: glResumeTransformFeedback(); break;
|
||||
case BIND_BUFFER_BASE: {
|
||||
GLenum target = a.u32(); GLuint index = a.u32();
|
||||
glBindBufferBase(target, index, lookup(buffers, a.u32())); break;
|
||||
}
|
||||
case GEN_SAMPLERS: {
|
||||
GLsizei n = a.i32();
|
||||
if (gexgl_negative_count(n, [](GLsizei c, GLuint *p) { glGenSamplers(c, p); })) break;
|
||||
std::vector<GLuint> ids(n); glGenSamplers(n, ids.data());
|
||||
for (uint32_t i = 0; i < n; ++i) samplers[a.u32()] = ids[i]; break;
|
||||
}
|
||||
case DELETE_SAMPLERS: {
|
||||
uint32_t n = a.u32(); std::vector<GLuint> ids; ids.reserve(n);
|
||||
for (uint32_t i = 0; i < n; ++i) { uint32_t g=a.u32(); ids.push_back(lookup(samplers,g)); samplers.erase(g); }
|
||||
glDeleteSamplers(n, ids.data()); break;
|
||||
}
|
||||
case BIND_SAMPLER: { GLuint unit=a.u32(); glBindSampler(unit, lookup(samplers,a.u32())); break; }
|
||||
case SAMPLER_PARAMETER_I: {
|
||||
GLuint sampler = lookup(samplers, a.u32()); GLenum pname = a.u32();
|
||||
GLint values[4]{}; const size_t count = pname == GL_TEXTURE_BORDER_COLOR ? 4u : 1u;
|
||||
for (size_t i = 0; i < count; ++i) values[i] = a.i32();
|
||||
if (count == 4) glSamplerParameteriv(sampler, pname, values);
|
||||
else glSamplerParameteri(sampler, pname, values[0]);
|
||||
break;
|
||||
}
|
||||
case SAMPLER_PARAMETER_F: {
|
||||
GLuint sampler = lookup(samplers, a.u32()); GLenum pname = a.u32();
|
||||
GLfloat values[4]{}; const size_t count = pname == GL_TEXTURE_BORDER_COLOR ? 4u : 1u;
|
||||
for (size_t i = 0; i < count; ++i) values[i] = a.f32();
|
||||
if (count == 4) glSamplerParameterfv(sampler, pname, values);
|
||||
else glSamplerParameterf(sampler, pname, values[0]);
|
||||
break;
|
||||
}
|
||||
case DETACH_SHADER: { GLuint p = lookup(programs, a.u32()); glDetachShader(p, lookup(shaders, a.u32())); break; }
|
||||
case GET_UNIFORM_BLOCK_INDEX: { GLuint p = lookup(programs, a.u32()); std::string n = a.string(); put_u32(glGetUniformBlockIndex(p, n.c_str())); break; }
|
||||
case UNIFORM_BLOCK_BINDING: { GLuint p = lookup(programs, a.u32()); GLuint i = a.u32(); glUniformBlockBinding(p, i, a.u32()); break; }
|
||||
case GET_ATTACHED_SHADERS: {
|
||||
uint32_t gp = a.u32(), max_count = a.u32(); GLuint p = lookup(programs, gp);
|
||||
std::vector<GLuint> ids(max_count); GLsizei count = 0;
|
||||
glGetAttachedShaders(p, max_count, &count, ids.data());
|
||||
put_u32(count);
|
||||
for (GLsizei i = 0; i < count; ++i) {
|
||||
uint32_t guest = 0;
|
||||
for (const auto &entry : shaders) if (entry.second == ids[i]) { guest = entry.first; break; }
|
||||
put_u32(guest);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UNIFORM_2I: { GLint l=a.i32(), x=a.i32(), y=a.i32(); glUniform2i(l,x,y); break; }
|
||||
case UNIFORM_3I: { GLint l=a.i32(), x=a.i32(), y=a.i32(), z=a.i32(); glUniform3i(l,x,y,z); break; }
|
||||
case UNIFORM_4I: { GLint l=a.i32(), x=a.i32(), y=a.i32(), z=a.i32(), w=a.i32(); glUniform4i(l,x,y,z,w); break; }
|
||||
case GET_ACTIVE_UNIFORM:
|
||||
case GET_ACTIVE_ATTRIB:
|
||||
case GET_TRANSFORM_FEEDBACK_VARYING: {
|
||||
GLuint program = lookup(programs, a.u32()); GLuint index = a.u32();
|
||||
GLenum length_query = op == GET_ACTIVE_UNIFORM
|
||||
? GL_ACTIVE_UNIFORM_MAX_LENGTH
|
||||
: op == GET_ACTIVE_ATTRIB
|
||||
? GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
|
||||
: GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH;
|
||||
GLint max_len = 0;
|
||||
glGetProgramiv(program, length_query, &max_len);
|
||||
std::vector<char> name(std::max(max_len, 1)); GLsizei length = 0; GLint size = 0; GLenum type = 0;
|
||||
if (op == GET_ACTIVE_UNIFORM) glGetActiveUniform(program, index, name.size(), &length, &size, &type, name.data());
|
||||
else if (op == GET_ACTIVE_ATTRIB) glGetActiveAttrib(program, index, name.size(), &length, &size, &type, name.data());
|
||||
else glGetTransformFeedbackVarying(program, index, name.size(), &length, &size, &type, name.data());
|
||||
put_u32(size); put_u32(type); put_blob(name.data(), length); break;
|
||||
}
|
||||
case GET_ACTIVE_UNIFORM_NAME:
|
||||
case GET_ACTIVE_UNIFORM_BLOCK_NAME: {
|
||||
GLuint program = lookup(programs, a.u32()); GLuint index = a.u32();
|
||||
GLint max_len = 0;
|
||||
glGetProgramiv(program,
|
||||
op == GET_ACTIVE_UNIFORM_NAME
|
||||
? GL_ACTIVE_UNIFORM_MAX_LENGTH
|
||||
: GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
|
||||
&max_len);
|
||||
std::vector<char> name(std::max(max_len, 1));
|
||||
GLsizei length = 0;
|
||||
if (op == GET_ACTIVE_UNIFORM_NAME)
|
||||
glGetActiveUniformName(program, index, name.size(), &length, name.data());
|
||||
else
|
||||
glGetActiveUniformBlockName(program, index, name.size(), &length, name.data());
|
||||
put_blob(name.data(), length); break;
|
||||
}
|
||||
case GET_ACTIVE_UNIFORM_BLOCKIV: {
|
||||
GLuint program = lookup(programs, a.u32());
|
||||
GLuint index = a.u32();
|
||||
GLenum pname = a.u32();
|
||||
/* Only one query returns more than a single integer, and its length is
|
||||
* itself a query. */
|
||||
GLint count = 1;
|
||||
if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
|
||||
glGetActiveUniformBlockiv(program, index,
|
||||
GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &count);
|
||||
std::vector<GLint> params(std::max(count, 1), 0);
|
||||
glGetActiveUniformBlockiv(program, index, pname, params.data());
|
||||
put_blob(params.data(), std::max(count, 0) * sizeof(GLint)); break;
|
||||
}
|
||||
case GET_ACTIVE_UNIFORMSIV: {
|
||||
GLuint program = lookup(programs, a.u32());
|
||||
GLenum pname = a.u32();
|
||||
uint32_t bytes = 0;
|
||||
const uint8_t* raw = a.blob(bytes);
|
||||
const GLsizei count = (GLsizei)(bytes / sizeof(GLuint));
|
||||
std::vector<GLuint> indices(count);
|
||||
if (count) memcpy(indices.data(), raw, (size_t)count * sizeof(GLuint));
|
||||
std::vector<GLint> params(std::max(count, 1), 0);
|
||||
glGetActiveUniformsiv(program, count, indices.data(), pname, params.data());
|
||||
put_blob(params.data(), (size_t)count * sizeof(GLint)); break;
|
||||
}
|
||||
case GET_UNIFORM_INDICES: {
|
||||
GLuint program = lookup(programs, a.u32());
|
||||
const GLsizei count = (GLsizei)a.u32();
|
||||
uint32_t bytes = 0;
|
||||
const uint8_t* raw = a.blob(bytes);
|
||||
/* One blob of NUL-terminated names; walk it rather than trusting a
|
||||
* separate length array the guest would have had to build. */
|
||||
std::vector<const GLchar*> names;
|
||||
const char* at = reinterpret_cast<const char*>(raw);
|
||||
const char* end = at + bytes;
|
||||
for (GLsizei i = 0; i < count && at < end; ++i) {
|
||||
names.push_back(at);
|
||||
at += strnlen(at, (size_t)(end - at)) + 1;
|
||||
}
|
||||
std::vector<GLuint> indices(std::max<size_t>(names.size(), 1),
|
||||
GL_INVALID_INDEX);
|
||||
if (!names.empty())
|
||||
glGetUniformIndices(program, (GLsizei)names.size(), names.data(),
|
||||
indices.data());
|
||||
put_blob(indices.data(), names.size() * sizeof(GLuint)); break;
|
||||
}
|
||||
case GET_SHADER_SOURCE: {
|
||||
GLuint shader = lookup(shaders, a.u32());
|
||||
GLint max_len = 0;
|
||||
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &max_len);
|
||||
std::vector<char> source(std::max(max_len, 1));
|
||||
GLsizei length = 0;
|
||||
glGetShaderSource(shader, source.size(), &length, source.data());
|
||||
put_blob(source.data(), length); break;
|
||||
}
|
||||
#define GEX_UNIFORM_VECTOR(OP, FN, TYPE) case OP: { GLint l=a.i32(); GLsizei n=a.i32(); uint32_t bytes; const uint8_t*p=a.blob(bytes); FN(l,n,reinterpret_cast<const TYPE*>(p)); break; }
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_1IV, glUniform1iv, GLint)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_1FV, glUniform1fv, GLfloat)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_2FV, glUniform2fv, GLfloat)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_3FV, glUniform3fv, GLfloat)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_4FV, glUniform4fv, GLfloat)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_2IV, glUniform2iv, GLint)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_3IV, glUniform3iv, GLint)
|
||||
GEX_UNIFORM_VECTOR(UNIFORM_4IV, glUniform4iv, GLint)
|
||||
#undef GEX_UNIFORM_VECTOR
|
||||
case UNIFORM_MATRIX2FV: {GLint l=a.i32();GLsizei n=a.i32();GLboolean t=a.u32();uint32_t bytes;const uint8_t*p=a.blob(bytes);glUniformMatrix2fv(l,n,t,reinterpret_cast<const GLfloat*>(p));break;}
|
||||
case UNIFORM_MATRIX3FV: {GLint l=a.i32();GLsizei n=a.i32();GLboolean t=a.u32();uint32_t bytes;const uint8_t*p=a.blob(bytes);glUniformMatrix3fv(l,n,t,reinterpret_cast<const GLfloat*>(p));break;}
|
||||
case VERTEX_ATTRIB_I_POINTER: {
|
||||
GLuint i = a.u32(); GLint size = a.i32(); GLenum type = a.u32();
|
||||
GLsizei stride = a.i32(); uintptr_t off = a.u32();
|
||||
glVertexAttribIPointer(i, size, type, stride, reinterpret_cast<void*>(off)); break;
|
||||
}
|
||||
case VERTEX_ATTRIB_DIVISOR: { GLuint index=a.u32(), divisor=a.u32();
|
||||
glVertexAttribDivisor(index,divisor); break; }
|
||||
case VERTEX_ATTRIB_4F: { GLuint index=a.u32(); GLfloat x=a.f32(), y=a.f32(), z=a.f32(), w=a.f32(); glVertexAttrib4f(index,x,y,z,w); break; }
|
||||
case VERTEX_ATTRIB_I4I: { GLuint index=a.u32(); GLint x=a.i32(), y=a.i32(), z=a.i32(), w=a.i32(); glVertexAttribI4i(index,x,y,z,w); break; }
|
||||
case GEN_VERTEX_ARRAYS: {
|
||||
GLsizei n = a.i32();
|
||||
if (gexgl_negative_count(n, [](GLsizei c, GLuint *p) { glGenVertexArrays(c, p); })) break;
|
||||
std::vector<GLuint> ids(n); glGenVertexArrays(n, ids.data());
|
||||
for(uint32_t i=0;i<n;++i) vertex_arrays[a.u32()]=ids[i]; break;
|
||||
}
|
||||
case DELETE_VERTEX_ARRAYS: {
|
||||
uint32_t n=a.u32(); std::vector<GLuint> ids; ids.reserve(n);
|
||||
for(uint32_t i=0;i<n;++i){uint32_t g=a.u32();ids.push_back(lookup(vertex_arrays,g));vertex_arrays.erase(g);} glDeleteVertexArrays(n,ids.data());break;
|
||||
}
|
||||
case BIND_VERTEX_ARRAY: { uint32_t g=a.u32(); glBindVertexArray(g ? lookup(vertex_arrays,g) : default_vao); break; }
|
||||
case TEX_PARAMETER_F: { GLenum target=a.u32(), pname=a.u32(); GLfloat value=a.f32(); glTexParameterf(target,pname,value); break; }
|
||||
case TEX_PARAMETER_FV: {
|
||||
GLenum target=a.u32(), pname=a.u32(); GLfloat value[4]{};
|
||||
const size_t count = (pname == GL_TEXTURE_BORDER_COLOR || pname == GL_TEXTURE_SWIZZLE_RGBA) ? 4 : 1;
|
||||
for (size_t i = 0; i < count; ++i) value[i]=a.f32();
|
||||
glTexParameterfv(target,pname,value);
|
||||
break;
|
||||
}
|
||||
case TEX_PARAMETER_IV: {
|
||||
GLenum target=a.u32(), pname=a.u32(); GLint value[4]{};
|
||||
const size_t count = (pname == GL_TEXTURE_BORDER_COLOR || pname == GL_TEXTURE_SWIZZLE_RGBA) ? 4 : 1;
|
||||
for (size_t i = 0; i < count; ++i) value[i]=a.i32();
|
||||
glTexParameteriv(target,pname,value);
|
||||
break;
|
||||
}
|
||||
case DRAW_BUFFERS: {
|
||||
GLsizei n = a.i32(); current_draw_buffers.resize(std::max(n, 0));
|
||||
for (GLsizei i = 0; i < n; ++i) current_draw_buffers[i] = a.u32();
|
||||
glDrawBuffers(n, current_draw_buffers.data()); break;
|
||||
}
|
||||
case DRAW_ARRAYS_INSTANCED: { GLenum mode=a.u32(); GLint first=a.i32(); GLsizei count=a.i32(), instances=a.i32(); glDrawArraysInstanced(mode,first,count,instances); break; }
|
||||
case DRAW_ELEMENTS_INSTANCED: {
|
||||
GLenum mode=a.u32(); GLsizei n=a.i32(); GLenum type=a.u32(); uintptr_t off=a.u32(); GLsizei instances=a.i32();
|
||||
glDrawElementsInstanced(mode,n,type,reinterpret_cast<void*>(off),instances); break;
|
||||
}
|
||||
case BLIT_FRAMEBUFFER: {
|
||||
GLint sx0=a.i32(),sy0=a.i32(),sx1=a.i32(),sy1=a.i32();
|
||||
GLint dx0=a.i32(),dy0=a.i32(),dx1=a.i32(),dy1=a.i32();
|
||||
GLbitfield mask=a.u32(); GLenum filter=a.u32();
|
||||
glBlitFramebuffer(sx0,sy0,sx1,sy1,dx0,dy0,dx1,dy1,mask,filter); break;
|
||||
}
|
||||
case GENERATE_MIPMAP: glGenerateMipmap(a.u32()); break;
|
||||
case TEX_STORAGE_2D: { GLenum target=a.u32(); GLsizei levels=a.i32(); GLenum format=a.u32(); GLsizei w=a.i32(), h=a.i32(); glTexStorage2D(target,levels,format,w,h); break; }
|
||||
case TEX_STORAGE_3D: { GLenum target=a.u32(); GLsizei levels=a.i32(); GLenum format=a.u32(); GLsizei w=a.i32(), h=a.i32(), d=a.i32(); glTexStorage3D(target,levels,format,w,h,d); break; }
|
||||
case TEX_IMAGE_3D: {
|
||||
GLenum t=a.u32();GLint l=a.i32(),in=a.i32();GLsizei w=a.i32(),h=a.i32(),d=a.i32();
|
||||
GLint border=a.i32();GLenum f=a.u32(),ty=a.u32();bool pbo=a.u32()!=0;
|
||||
uintptr_t pointer=static_cast<uintptr_t>(a.u64());uint32_t n;const uint8_t* bytes=a.blob(n);
|
||||
gexgl_pixel_layout layout{};
|
||||
const bool valid=gexgl_compute_pixel_layout(f,ty,w,h,d,&unpack_store,&layout);
|
||||
if ((pbo && n != 0) || (!pbo && pointer && (!valid || layout.end != n))) {
|
||||
a.ok=false;break;
|
||||
}
|
||||
const void* data=pbo?reinterpret_cast<const void*>(pointer):(pointer?bytes:nullptr);
|
||||
glTexImage3D(t,l,in,w,h,d,border,f,ty,data);break;
|
||||
}
|
||||
case FRAMEBUFFER_TEXTURE_LAYER: {GLenum t=a.u32(),att=a.u32();GLuint tex=lookup(textures,a.u32());GLint level=a.i32(),layer=a.i32();glFramebufferTextureLayer(t,att,tex,level,layer);break;}
|
||||
case GET_STRING_I: {
|
||||
GLenum name = a.u32(); GLuint index = a.u32();
|
||||
const char* s = reinterpret_cast<const char*>(glGetStringi(name, index));
|
||||
put_blob(s, s ? std::strlen(s) : 0);
|
||||
break;
|
||||
}
|
||||
case GET_UNIFORM_FV:
|
||||
case GET_UNIFORM_IV: {
|
||||
GLuint program=lookup_program_or_shader(a.u32()); GLint location=a.i32();
|
||||
uint32_t components=uniform_components(program,location);
|
||||
if (op == GET_UNIFORM_FV) {
|
||||
GLfloat values[16] = {}; glGetUniformfv(program,location,values);
|
||||
put_blob(values,components*sizeof(values[0]));
|
||||
} else {
|
||||
GLint values[16] = {}; glGetUniformiv(program,location,values);
|
||||
put_blob(values,components*sizeof(values[0]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -751,10 +751,23 @@ impl Gl {
|
||||
/// Run one batch. Returns the reply and, if the stream was malformed,
|
||||
/// where and why.
|
||||
pub fn run(&mut self, batch: &[u8]) -> (Reply, u32, u32) {
|
||||
let mut reply = Reply::default();
|
||||
if self.make_current().is_err() {
|
||||
return (reply, error::NO_CONTEXT, 0);
|
||||
return (Reply::default(), error::NO_CONTEXT, 0);
|
||||
}
|
||||
let r = self.run_current(batch);
|
||||
// Released after every batch: a guest may submit from any of its
|
||||
// threads (wined3d's command stream thread and the main one), and a
|
||||
// context still current on one thread cannot be made current on
|
||||
// another. Batches are already serialized by the device.
|
||||
unsafe {
|
||||
eglMakeCurrent(self.display, std::ptr::null_mut(), std::ptr::null_mut(), std::ptr::null_mut());
|
||||
}
|
||||
self.current_on = None;
|
||||
r
|
||||
}
|
||||
|
||||
fn run_current(&mut self, batch: &[u8]) -> (Reply, u32, u32) {
|
||||
let mut reply = Reply::default();
|
||||
let mut commands = Commands::new(batch);
|
||||
let mut index = 0u32;
|
||||
loop {
|
||||
@@ -939,6 +952,7 @@ impl Gl {
|
||||
if let (Some(p), Some(v)) = (a.u32(), a.i32()) {
|
||||
glPixelStorei(p, v);
|
||||
set_pixel_store(&mut self.pack_store, &mut self.unpack_store, p, v);
|
||||
native::gexgl_native_pixel_store(p, v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1007,6 +1021,7 @@ impl Gl {
|
||||
};
|
||||
let real = glCreateShader(ty);
|
||||
self.names.shaders.insert(name, real);
|
||||
native::gexgl_native_name(0, name, real);
|
||||
}
|
||||
op::SHADER_SOURCE => {
|
||||
let (Some(name), Some(src)) = (a.u32(), a.blob()) else {
|
||||
@@ -1027,6 +1042,7 @@ impl Gl {
|
||||
op::DELETE_SHADER => {
|
||||
if let Some(n) = a.u32() {
|
||||
if let Some(real) = self.names.shaders.remove(&n) {
|
||||
native::gexgl_native_name(0, n, 0);
|
||||
glDeleteShader(real);
|
||||
}
|
||||
}
|
||||
@@ -1035,6 +1051,7 @@ impl Gl {
|
||||
if let Some(name) = a.u32() {
|
||||
let real = glCreateProgram();
|
||||
self.names.programs.insert(name, real);
|
||||
native::gexgl_native_name(1, name, real);
|
||||
}
|
||||
}
|
||||
op::ATTACH_SHADER => {
|
||||
@@ -1069,6 +1086,7 @@ impl Gl {
|
||||
op::DELETE_PROGRAM => {
|
||||
if let Some(n) = a.u32() {
|
||||
if let Some(real) = self.names.programs.remove(&n) {
|
||||
native::gexgl_native_name(1, n, 0);
|
||||
glDeleteProgram(real);
|
||||
}
|
||||
}
|
||||
@@ -1555,13 +1573,33 @@ impl Gl {
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
// The generated commands (GL 4.4 and the registry's
|
||||
// compatibility profile) are decoded by the C++ shared with
|
||||
// the browser's host.
|
||||
_ => {
|
||||
let (mut out, mut len) = (std::ptr::null(), 0usize);
|
||||
if native::gexgl_native_one(opcode, body.as_ptr(), body.len(), &mut out, &mut len) != 1 {
|
||||
return false;
|
||||
}
|
||||
if len > 0 {
|
||||
reply.bytes.extend_from_slice(std::slice::from_raw_parts(out, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// native/gexgl-native.cpp (built by build.rs).
|
||||
mod native {
|
||||
extern "C" {
|
||||
pub fn gexgl_native_one(op: u32, body: *const u8, len: usize, reply: *mut *const u8, reply_len: *mut usize) -> i32;
|
||||
pub fn gexgl_native_pixel_store(pname: u32, param: i32);
|
||||
pub fn gexgl_native_name(kind: u32, guest: u32, host: u32);
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a [`Header`] out of the front of a shared buffer.
|
||||
pub fn read_header(bytes: &[u8]) -> Option<Header> {
|
||||
if bytes.len() < Header::SIZE {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//! See [`proto`] for why the split is at the API rather than at a virtual
|
||||
//! GPU, and [`host`] for what runs the commands.
|
||||
|
||||
pub mod compat_plans;
|
||||
pub mod proto;
|
||||
pub mod trace;
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
pub const MAGIC: u32 = 0x4758_4547;
|
||||
/// Version of the command ABI. A guest and host must agree before any opcode
|
||||
/// is decoded; generated opcode policy changes require incrementing this.
|
||||
pub const PROTOCOL_VERSION: u32 = 12;
|
||||
/// 13: the registry's compatibility-profile commands (tools/gen_gl_compat.py,
|
||||
/// opcodes from [`crate::compat_plans::COMPAT_BASE`]).
|
||||
pub const PROTOCOL_VERSION: u32 = 13;
|
||||
|
||||
/// The fixed header at the start of the shared buffer. `repr(C)` for the C
|
||||
/// guest half; every field 32 bits, 32 bytes total.
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//! The generated compatibility-profile plans (tools/gen_gl_compat.py) are
|
||||
//! well-formed: every opcode is its own and past the hand-written and GL 4.4
|
||||
//! ones, every token is one the encoders and decoders know, and every count
|
||||
//! names a parameter the command has.
|
||||
|
||||
use gex_gl::compat_plans::{COMPAT_BASE, PLANS};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
fn plans_are_well_formed() {
|
||||
assert!(PLANS.len() > 2000, "the registry's commands are planned");
|
||||
let mut opcodes = HashSet::new();
|
||||
for (name, opcode, plan) in PLANS {
|
||||
assert!(*opcode >= COMPAT_BASE, "{name}: opcode {opcode}");
|
||||
assert!(opcodes.insert(*opcode), "{name}: opcode {opcode} twice");
|
||||
let toks: Vec<&str> = plan.split(' ').collect();
|
||||
assert!(matches!(toks[0], "v" | "w" | "f" | "q"), "{name}: return {}", toks[0]);
|
||||
let params = toks.len() - 1;
|
||||
for t in &toks[1..] {
|
||||
match t.as_bytes()[0] {
|
||||
b'w' | b'f' | b'q' | b'P' => assert_eq!(t.len(), 1, "{name}: {t}"),
|
||||
b'i' | b'j' | b'o' => {
|
||||
let (size, spec) = t[1..].split_once(':').unwrap_or_else(|| panic!("{name}: {t}"));
|
||||
assert!(matches!(size, "1" | "2" | "4" | "8"), "{name}: element size {size}");
|
||||
let kind = spec.as_bytes()[0];
|
||||
assert!(b"npezLsSXBTU".contains(&kind), "{name}: count {spec}");
|
||||
for arg in spec[1..].split([',', '*']).filter(|a| !a.is_empty() && *a != "_") {
|
||||
let v: usize = arg.parse().unwrap_or_else(|_| panic!("{name}: {spec}"));
|
||||
// A multiplier, an element count, or a parameter.
|
||||
if kind != b'n' && !spec.contains(&format!("*{arg}")) {
|
||||
assert!(v < params, "{name}: {spec} names parameter {v} of {params}");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("{name}: token {t}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixed_function_commands_are_planned() {
|
||||
// What a GL 1.1 renderer (GoldSrc's) and wined3d's fixed-function
|
||||
// pipeline call that no hand-written command covers.
|
||||
for want in ["glOrtho", "glTexCoord2f", "glFogfv", "glClipPlane", "glMultiTexCoord2f", "glGetTexEnvfv", "glDrawPixels", "glBitmap"] {
|
||||
assert!(PLANS.iter().any(|(n, _, _)| *n == want), "{want} has no plan");
|
||||
}
|
||||
let fog = PLANS.iter().find(|(n, _, _)| *n == "glFogfv").unwrap();
|
||||
assert_eq!(fog.2, "v w i4:e0", "glFogfv: a pname-sized float vector");
|
||||
}
|
||||
@@ -28,6 +28,9 @@ fi
|
||||
# This deliberately fails closed if a pointer-shaped command has no explicit
|
||||
# wire policy in tools/gen_gl44_transport.py.
|
||||
python3 "$ROOT/tools/gen_gl44_transport.py"
|
||||
# And every other registry command with a wire plan: the guest's entry
|
||||
# points, opengl32's plans and the hosts' decoder (tools/gen_gl_compat.py).
|
||||
python3 "$ROOT/tools/gen_gl_compat.py"
|
||||
|
||||
# The opcodes come from the Rust side, so the two cannot drift.
|
||||
python3 - "$ROOT" "$HERE" <<'PYEOF'
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/* Wire plans (tools/gen_gl_compat.py): what both ends of a generated
|
||||
* command agree on. A plan is a return token then one token per parameter;
|
||||
* this parses them and sizes their arrays, for the guest's interpreter
|
||||
* (gexgl.c) and the host decoders (web/mesa/gexgl-compat-host.h), so the
|
||||
* size an encoder sends is the one a decoder checks. C and C++. */
|
||||
#ifndef GEXGL_PLAN_H
|
||||
#define GEXGL_PLAN_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gexgl-pixel.h"
|
||||
#include "gl-pname-counts.h"
|
||||
|
||||
#define GEXGEN_MAX_PARAMS 24
|
||||
/* No single array is larger than this on the wire. */
|
||||
#define GEXGEN_MAX_BYTES ((size_t)1 << 28)
|
||||
|
||||
struct gexgen_tok {
|
||||
char kind; /* w f q: scalars; i j: input arrays; o: output */
|
||||
unsigned size; /* element bytes, for arrays */
|
||||
char spec; /* n p e z L s S X B T */
|
||||
int arg[5]; /* parameter indices (-1 absent) or N / multiplier */
|
||||
};
|
||||
|
||||
/* A non-negative element count from a signed parameter, times `mult`,
|
||||
* saturating at what the wire can carry. */
|
||||
static inline size_t gexgen_count(long long value, long long mult) {
|
||||
if (value <= 0 || mult <= 0) return 0;
|
||||
if ((unsigned long long)value > GEXGEN_MAX_BYTES / (unsigned long long)mult) return GEXGEN_MAX_BYTES;
|
||||
return (size_t)(value * mult);
|
||||
}
|
||||
|
||||
/* glCallLists' element types. */
|
||||
static inline size_t gexgen_type_bytes(unsigned type) {
|
||||
switch (type) {
|
||||
case 0x1400: case 0x1401: return 1; /* BYTE, UNSIGNED_BYTE */
|
||||
case 0x1402: case 0x1403: case 0x1407: return 2; /* SHORT, UNSIGNED_SHORT, 2_BYTES */
|
||||
case 0x1408: return 3; /* 3_BYTES */
|
||||
case 0x1404: case 0x1405: case 0x1406: case 0x1409: return 4; /* INT, UNSIGNED_INT, FLOAT, 4_BYTES */
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* A glBitmap's bytes under the unpack store: rows of (row length or width)
|
||||
* bits, each padded to the alignment, after the skipped rows and pixels. */
|
||||
static inline size_t gexgen_bitmap_bytes_store(long long width, long long height,
|
||||
const struct gexgl_pixel_store *s) {
|
||||
if (width <= 0 || height <= 0 || width > 1 << 20 || height > 1 << 20) return 0;
|
||||
size_t px = s->row_length ? s->row_length : (size_t)width;
|
||||
size_t row = (px + 7) / 8, a = s->alignment ? s->alignment : 1;
|
||||
row = (row + a - 1) / a * a;
|
||||
return (s->skip_rows + (size_t)height) * row + (s->skip_pixels + 7) / 8;
|
||||
}
|
||||
|
||||
/* Parse one token at `p` into `t`; returns past it, or NULL at the end. */
|
||||
static inline const char *gexgen_parse(const char *p, struct gexgen_tok *t) {
|
||||
while (*p == ' ') p++;
|
||||
if (!*p) return NULL;
|
||||
t->kind = *p++;
|
||||
t->size = 0;
|
||||
t->spec = 0;
|
||||
for (int i = 0; i < 5; i++) t->arg[i] = -1;
|
||||
if (t->kind == 'i' || t->kind == 'j' || t->kind == 'o') {
|
||||
while (*p >= '0' && *p <= '9') t->size = t->size * 10 + (unsigned)(*p++ - '0');
|
||||
if (*p == ':') p++;
|
||||
t->spec = *p++;
|
||||
int n = 0;
|
||||
while (*p && *p != ' ' && n < 5) {
|
||||
if (*p == '_') { p++; n++; }
|
||||
else if (*p >= '0' && *p <= '9') {
|
||||
int v = 0;
|
||||
while (*p >= '0' && *p <= '9') v = v * 10 + (*p++ - '0');
|
||||
t->arg[n++] = v;
|
||||
} else if (*p != ',' && *p != '*') {
|
||||
p++;
|
||||
}
|
||||
if (*p == ',' || *p == '*') p++;
|
||||
}
|
||||
/* p<i> without a multiplier multiplies by one. */
|
||||
if (t->spec == 'p' && t->arg[1] < 0) t->arg[1] = 1;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
+105
-1
@@ -55,6 +55,7 @@
|
||||
|
||||
#include "gexgl.h"
|
||||
#include "gexgl-pixel.h"
|
||||
#include "gexgl-plan.h"
|
||||
|
||||
/* ---------------------------------------------------------------- the ring */
|
||||
|
||||
@@ -1277,7 +1278,6 @@ void glClientActiveTexture(unsigned unit) {
|
||||
client_active_texture = unit >= 0x84C0u ? unit - 0x84C0u : 0;
|
||||
CMD1(GEXGL_CLIENT_ACTIVE_TEXTURE, unit);
|
||||
}
|
||||
void glClientActiveTextureARB(unsigned unit) { glClientActiveTexture(unit); }
|
||||
/* glLockArraysEXT/glUnlockArraysEXT are a promise the arrays will not
|
||||
change between them; the uploads above already copy at every draw. */
|
||||
void glLockArraysEXT(int first, int count) { (void)first; (void)count; }
|
||||
@@ -2129,6 +2129,110 @@ void glGetSynciv(void *sync, unsigned pname, int buf_size, int *length, int *val
|
||||
as the hand-written pointer/object-aware commands above. */
|
||||
#include "gl44-generated.inc"
|
||||
|
||||
/* ------------------------------------------- the registry's other commands */
|
||||
|
||||
/* Every other registry command with a wire plan (tools/gen_gl_compat.py,
|
||||
guest/gl/gexgl-plan.h) is one call to this, its arguments as 64-bit words
|
||||
(floats and doubles as their bits, pointers as addresses): the plan says
|
||||
how each goes on the wire and how many elements an array holds. A command
|
||||
with a return value or outputs waits for the reply. */
|
||||
static uint64_t gexgen_dbits(double d) {
|
||||
uint64_t v;
|
||||
memcpy(&v, &d, 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
static size_t gexgen_elements(const struct gexgen_tok *t, const uint64_t *v) {
|
||||
const void *ptr = (const void *)(uintptr_t)0;
|
||||
switch (t->spec) {
|
||||
case 'n': return (size_t)t->arg[0];
|
||||
case 'p': return gexgen_count((int32_t)v[t->arg[0]], t->arg[1]);
|
||||
case 'e': return gexgl_pname_count((unsigned)v[t->arg[0]]);
|
||||
case 'z': return gexgen_count((long long)v[t->arg[0]], 1);
|
||||
case 'L': return gexgen_count((int32_t)v[t->arg[0]], (long long)gexgen_type_bytes((unsigned)v[t->arg[1]]));
|
||||
case 'T': return 128;
|
||||
case 'U': return 16; /* a uniform: the host says how many, at most a 4x4 matrix */
|
||||
case 'B': return gexgen_bitmap_bytes_store((int32_t)v[t->arg[0]], (int32_t)v[t->arg[1]], &unpack_store);
|
||||
case 'X': {
|
||||
struct gexgl_pixel_layout layout;
|
||||
const int w = (int32_t)v[t->arg[2]];
|
||||
const int h = t->arg[3] >= 0 ? (int32_t)v[t->arg[3]] : 1;
|
||||
const int d = t->arg[4] >= 0 ? (int32_t)v[t->arg[4]] : -1;
|
||||
return gexgl_compute_pixel_layout((uint32_t)v[t->arg[0]], (uint32_t)v[t->arg[1]], w, h, d,
|
||||
&unpack_store, &layout) ? layout.end : 0;
|
||||
}
|
||||
default: (void)ptr; return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t gexgen_call(uint32_t opcode, const char *plan, const uint64_t *v) {
|
||||
struct gexgen_tok toks[GEXGEN_MAX_PARAMS + 1];
|
||||
toks[0].kind = 'v';
|
||||
size_t bytes[GEXGEN_MAX_PARAMS];
|
||||
int mode[GEXGEN_MAX_PARAMS]; /* inputs: 0 null, 1 data, 2 unpack offset */
|
||||
int n = 0, outputs = 0;
|
||||
const char *p = gexgen_parse(plan, &toks[0]);
|
||||
const char ret = toks[0].kind;
|
||||
while (p && n < GEXGEN_MAX_PARAMS && (p = gexgen_parse(p, &toks[n + 1]))) n++;
|
||||
size_t words = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
const struct gexgen_tok *t = &toks[i + 1];
|
||||
const void *ptr = (const void *)(uintptr_t)v[i];
|
||||
switch (t->kind) {
|
||||
case 'w': case 'f': words += 1; break;
|
||||
case 'q': words += 2; break;
|
||||
case 'o': outputs++; break;
|
||||
default:
|
||||
if (t->kind == 'j' && bound_buffer(0x88ECu)) { /* GL_PIXEL_UNPACK_BUFFER */
|
||||
mode[i] = 2; words += 3; break;
|
||||
}
|
||||
if (!ptr) { mode[i] = 0; words += 1; break; }
|
||||
if (t->spec == 's') bytes[i] = strlen((const char *)ptr);
|
||||
else if (t->spec == 'S') {
|
||||
const int len = (int32_t)v[t->arg[0]];
|
||||
bytes[i] = len < 0 ? strlen((const char *)ptr) : (size_t)len;
|
||||
} else bytes[i] = gexgen_elements(t, v) * t->size;
|
||||
if (bytes[i] > GEXGEN_MAX_BYTES) bytes[i] = 0;
|
||||
mode[i] = 1;
|
||||
words += 2 + (bytes[i] + 3) / 4;
|
||||
}
|
||||
}
|
||||
uint32_t *a = begin(opcode, words, 0);
|
||||
if (!a) return 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
const struct gexgen_tok *t = &toks[i + 1];
|
||||
switch (t->kind) {
|
||||
case 'w': case 'f': *a++ = (uint32_t)v[i]; break;
|
||||
case 'q': *a++ = (uint32_t)v[i]; *a++ = (uint32_t)(v[i] >> 32); break;
|
||||
case 'o': break;
|
||||
default:
|
||||
*a++ = (uint32_t)mode[i];
|
||||
if (mode[i] == 2) { *a++ = (uint32_t)v[i]; *a++ = (uint32_t)(v[i] >> 32); }
|
||||
else if (mode[i] == 1) {
|
||||
put_blob(a, (const void *)(uintptr_t)v[i], bytes[i]);
|
||||
a += 1 + (bytes[i] + 3) / 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 'v' && !outputs) return 0;
|
||||
flush();
|
||||
uint64_t r = 0;
|
||||
if (ret == 'w' || ret == 'f') r = reply_u32();
|
||||
else if (ret == 'q') { r = reply_u32(); r |= (uint64_t)reply_u32() << 32; }
|
||||
for (int i = 0; i < n; i++) {
|
||||
const struct gexgen_tok *t = &toks[i + 1];
|
||||
if (t->kind != 'o') continue;
|
||||
uint32_t len = 0;
|
||||
const uint8_t *src = reply_blob(&len);
|
||||
const size_t want = gexgen_elements(t, v) * t->size;
|
||||
void *dst = (void *)(uintptr_t)v[i];
|
||||
if (dst && src && (len == want || (t->spec == 'U' && len <= want))) memcpy(dst, src, len);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "gl-compat-generated.inc"
|
||||
|
||||
/* --------------------------------------------------------------------- EGL */
|
||||
|
||||
/* EGL here is bookkeeping and nothing else. There is one display, one config
|
||||
|
||||
+1
-3
@@ -183,7 +183,6 @@
|
||||
#define GEXGL_END_LIST 182
|
||||
#define GEXGL_CALL_LIST 183
|
||||
#define GEXGL_DELETE_LISTS 184
|
||||
/* Protocol 11: client arrays and fixed-function matrices (proto.rs). */
|
||||
#define GEXGL_ENABLE_CLIENT_STATE 185
|
||||
#define GEXGL_DISABLE_CLIENT_STATE 186
|
||||
#define GEXGL_VERTEX_POINTER 187
|
||||
@@ -197,7 +196,6 @@
|
||||
#define GEXGL_COLOR4F 195
|
||||
#define GEXGL_TEX_ENVI 196
|
||||
#define GEXGL_ALPHA_FUNC 197
|
||||
/* Protocol 12: the attribute stack (proto.rs). */
|
||||
#define GEXGL_PUSH_ATTRIB 198
|
||||
#define GEXGL_POP_ATTRIB 199
|
||||
|
||||
@@ -208,7 +206,7 @@
|
||||
#define GEXGL_CLIENT_API_DESKTOP 1
|
||||
|
||||
#define GEXGL_MAGIC 0x47584547u
|
||||
#define GEXGL_PROTOCOL_VERSION 12u
|
||||
#define GEXGL_PROTOCOL_VERSION 13u
|
||||
#define GEXGL_SUBMIT 0xc0086701u
|
||||
#define GEXGL_SURFACE 0x40106703u
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* a different name. An extension requires the suffixed spelling even
|
||||
* when the function has been core, unsuffixed, for twenty years, and
|
||||
* an extension whose entry points are missing cannot honestly be
|
||||
* claimed -- so here are the 451 of them whose target this
|
||||
* claimed -- so here are the 594 of them whose target this
|
||||
* library already exports. Included last, where every target is
|
||||
* declared, and typed from the target so the two cannot disagree.
|
||||
*/
|
||||
@@ -18,11 +18,13 @@ extern __typeof(glBindAttribLocation) glBindAttribLocationARB __attribute__((ali
|
||||
extern __typeof(glBindBuffer) glBindBufferARB __attribute__((alias("glBindBuffer")));
|
||||
extern __typeof(glBindBufferBase) glBindBufferBaseEXT __attribute__((alias("glBindBufferBase")));
|
||||
extern __typeof(glBindBufferBase) glBindBufferBaseNV __attribute__((alias("glBindBufferBase")));
|
||||
extern __typeof(glBindBufferOffsetEXT) glBindBufferOffsetNV __attribute__((alias("glBindBufferOffsetEXT")));
|
||||
extern __typeof(glBindBufferRange) glBindBufferRangeEXT __attribute__((alias("glBindBufferRange")));
|
||||
extern __typeof(glBindBufferRange) glBindBufferRangeNV __attribute__((alias("glBindBufferRange")));
|
||||
extern __typeof(glBindFragDataLocation) glBindFragDataLocationEXT __attribute__((alias("glBindFragDataLocation")));
|
||||
extern __typeof(glBindFragDataLocationIndexed) glBindFragDataLocationIndexedEXT __attribute__((alias("glBindFragDataLocationIndexed")));
|
||||
extern __typeof(glBindFramebuffer) glBindFramebufferEXT __attribute__((alias("glBindFramebuffer")));
|
||||
extern __typeof(glBindProgramARB) glBindProgramNV __attribute__((alias("glBindProgramARB")));
|
||||
extern __typeof(glBindRenderbuffer) glBindRenderbufferEXT __attribute__((alias("glBindRenderbuffer")));
|
||||
extern __typeof(glBindTexture) glBindTextureEXT __attribute__((alias("glBindTexture")));
|
||||
extern __typeof(glBindVertexArray) glBindVertexArrayOES __attribute__((alias("glBindVertexArray")));
|
||||
@@ -57,10 +59,17 @@ extern __typeof(glClampColor) glClampColorARB __attribute__((alias("glClampColor
|
||||
extern __typeof(glClearDepthf) glClearDepthfOES __attribute__((alias("glClearDepthf")));
|
||||
extern __typeof(glClearTexImage) glClearTexImageEXT __attribute__((alias("glClearTexImage")));
|
||||
extern __typeof(glClearTexSubImage) glClearTexSubImageEXT __attribute__((alias("glClearTexSubImage")));
|
||||
extern __typeof(glClientActiveTexture) glClientActiveTextureARB __attribute__((alias("glClientActiveTexture")));
|
||||
extern __typeof(glClientWaitSync) glClientWaitSyncAPPLE __attribute__((alias("glClientWaitSync")));
|
||||
extern __typeof(glClipControl) glClipControlEXT __attribute__((alias("glClipControl")));
|
||||
extern __typeof(glColorMaski) glColorMaskIndexedEXT __attribute__((alias("glColorMaski")));
|
||||
extern __typeof(glColorMaski) glColorMaskiEXT __attribute__((alias("glColorMaski")));
|
||||
extern __typeof(glColorMaski) glColorMaskiOES __attribute__((alias("glColorMaski")));
|
||||
extern __typeof(glColorSubTable) glColorSubTableEXT __attribute__((alias("glColorSubTable")));
|
||||
extern __typeof(glColorTable) glColorTableEXT __attribute__((alias("glColorTable")));
|
||||
extern __typeof(glColorTableParameterfv) glColorTableParameterfvSGI __attribute__((alias("glColorTableParameterfv")));
|
||||
extern __typeof(glColorTableParameteriv) glColorTableParameterivSGI __attribute__((alias("glColorTableParameteriv")));
|
||||
extern __typeof(glColorTable) glColorTableSGI __attribute__((alias("glColorTable")));
|
||||
extern __typeof(glCompileShader) glCompileShaderARB __attribute__((alias("glCompileShader")));
|
||||
extern __typeof(glCompressedTexImage1D) glCompressedTexImage1DARB __attribute__((alias("glCompressedTexImage1D")));
|
||||
extern __typeof(glCompressedTexImage2D) glCompressedTexImage2DARB __attribute__((alias("glCompressedTexImage2D")));
|
||||
@@ -68,7 +77,17 @@ extern __typeof(glCompressedTexImage3D) glCompressedTexImage3DARB __attribute__(
|
||||
extern __typeof(glCompressedTexSubImage1D) glCompressedTexSubImage1DARB __attribute__((alias("glCompressedTexSubImage1D")));
|
||||
extern __typeof(glCompressedTexSubImage2D) glCompressedTexSubImage2DARB __attribute__((alias("glCompressedTexSubImage2D")));
|
||||
extern __typeof(glCompressedTexSubImage3D) glCompressedTexSubImage3DARB __attribute__((alias("glCompressedTexSubImage3D")));
|
||||
extern __typeof(glConvolutionFilter1D) glConvolutionFilter1DEXT __attribute__((alias("glConvolutionFilter1D")));
|
||||
extern __typeof(glConvolutionFilter2D) glConvolutionFilter2DEXT __attribute__((alias("glConvolutionFilter2D")));
|
||||
extern __typeof(glConvolutionParameterf) glConvolutionParameterfEXT __attribute__((alias("glConvolutionParameterf")));
|
||||
extern __typeof(glConvolutionParameterfv) glConvolutionParameterfvEXT __attribute__((alias("glConvolutionParameterfv")));
|
||||
extern __typeof(glConvolutionParameteri) glConvolutionParameteriEXT __attribute__((alias("glConvolutionParameteri")));
|
||||
extern __typeof(glConvolutionParameteriv) glConvolutionParameterivEXT __attribute__((alias("glConvolutionParameteriv")));
|
||||
extern __typeof(glCopyBufferSubData) glCopyBufferSubDataNV __attribute__((alias("glCopyBufferSubData")));
|
||||
extern __typeof(glCopyColorSubTable) glCopyColorSubTableEXT __attribute__((alias("glCopyColorSubTable")));
|
||||
extern __typeof(glCopyColorTable) glCopyColorTableSGI __attribute__((alias("glCopyColorTable")));
|
||||
extern __typeof(glCopyConvolutionFilter1D) glCopyConvolutionFilter1DEXT __attribute__((alias("glCopyConvolutionFilter1D")));
|
||||
extern __typeof(glCopyConvolutionFilter2D) glCopyConvolutionFilter2DEXT __attribute__((alias("glCopyConvolutionFilter2D")));
|
||||
extern __typeof(glCopyImageSubData) glCopyImageSubDataEXT __attribute__((alias("glCopyImageSubData")));
|
||||
extern __typeof(glCopyImageSubData) glCopyImageSubDataOES __attribute__((alias("glCopyImageSubData")));
|
||||
extern __typeof(glCopyTexImage1D) glCopyTexImage1DEXT __attribute__((alias("glCopyTexImage1D")));
|
||||
@@ -78,6 +97,10 @@ extern __typeof(glCopyTexSubImage2D) glCopyTexSubImage2DEXT __attribute__((alias
|
||||
extern __typeof(glCopyTexSubImage3D) glCopyTexSubImage3DEXT __attribute__((alias("glCopyTexSubImage3D")));
|
||||
extern __typeof(glCreateProgram) glCreateProgramObjectARB __attribute__((alias("glCreateProgram")));
|
||||
extern __typeof(glCreateShader) glCreateShaderObjectARB __attribute__((alias("glCreateShader")));
|
||||
extern __typeof(glDebugMessageControl) glDebugMessageControlARB __attribute__((alias("glDebugMessageControl")));
|
||||
extern __typeof(glDebugMessageControl) glDebugMessageControlKHR __attribute__((alias("glDebugMessageControl")));
|
||||
extern __typeof(glDebugMessageInsert) glDebugMessageInsertARB __attribute__((alias("glDebugMessageInsert")));
|
||||
extern __typeof(glDebugMessageInsert) glDebugMessageInsertKHR __attribute__((alias("glDebugMessageInsert")));
|
||||
extern __typeof(glDeleteBuffers) glDeleteBuffersARB __attribute__((alias("glDeleteBuffers")));
|
||||
extern __typeof(glDeleteFramebuffers) glDeleteFramebuffersEXT __attribute__((alias("glDeleteFramebuffers")));
|
||||
extern __typeof(glDeleteQueries) glDeleteQueriesARB __attribute__((alias("glDeleteQueries")));
|
||||
@@ -131,12 +154,17 @@ extern __typeof(glEndTransformFeedback) glEndTransformFeedbackNV __attribute__((
|
||||
extern __typeof(glFenceSync) glFenceSyncAPPLE __attribute__((alias("glFenceSync")));
|
||||
extern __typeof(glFlushMappedBufferRange) glFlushMappedBufferRangeAPPLE __attribute__((alias("glFlushMappedBufferRange")));
|
||||
extern __typeof(glFlushMappedBufferRange) glFlushMappedBufferRangeEXT __attribute__((alias("glFlushMappedBufferRange")));
|
||||
extern __typeof(glFogCoordd) glFogCoorddEXT __attribute__((alias("glFogCoordd")));
|
||||
extern __typeof(glFogCoorddv) glFogCoorddvEXT __attribute__((alias("glFogCoorddv")));
|
||||
extern __typeof(glFogCoordf) glFogCoordfEXT __attribute__((alias("glFogCoordf")));
|
||||
extern __typeof(glFogCoordfv) glFogCoordfvEXT __attribute__((alias("glFogCoordfv")));
|
||||
extern __typeof(glFramebufferRenderbuffer) glFramebufferRenderbufferEXT __attribute__((alias("glFramebufferRenderbuffer")));
|
||||
extern __typeof(glFramebufferTexture1D) glFramebufferTexture1DEXT __attribute__((alias("glFramebufferTexture1D")));
|
||||
extern __typeof(glFramebufferTexture2D) glFramebufferTexture2DEXT __attribute__((alias("glFramebufferTexture2D")));
|
||||
extern __typeof(glFramebufferTexture3D) glFramebufferTexture3DEXT __attribute__((alias("glFramebufferTexture3D")));
|
||||
extern __typeof(glFramebufferTexture) glFramebufferTextureARB __attribute__((alias("glFramebufferTexture")));
|
||||
extern __typeof(glFramebufferTexture) glFramebufferTextureEXT __attribute__((alias("glFramebufferTexture")));
|
||||
extern __typeof(glFramebufferTextureFaceARB) glFramebufferTextureFaceEXT __attribute__((alias("glFramebufferTextureFaceARB")));
|
||||
extern __typeof(glFramebufferTextureLayer) glFramebufferTextureLayerARB __attribute__((alias("glFramebufferTextureLayer")));
|
||||
extern __typeof(glFramebufferTextureLayer) glFramebufferTextureLayerEXT __attribute__((alias("glFramebufferTextureLayer")));
|
||||
extern __typeof(glFramebufferTexture) glFramebufferTextureOES __attribute__((alias("glFramebufferTexture")));
|
||||
@@ -156,7 +184,11 @@ extern __typeof(glGetBufferParameteriv) glGetBufferParameterivARB __attribute__(
|
||||
extern __typeof(glGetBufferPointerv) glGetBufferPointervARB __attribute__((alias("glGetBufferPointerv")));
|
||||
extern __typeof(glGetBufferPointerv) glGetBufferPointervOES __attribute__((alias("glGetBufferPointerv")));
|
||||
extern __typeof(glGetBufferSubData) glGetBufferSubDataARB __attribute__((alias("glGetBufferSubData")));
|
||||
extern __typeof(glGetColorTableParameterfv) glGetColorTableParameterfvEXT __attribute__((alias("glGetColorTableParameterfv")));
|
||||
extern __typeof(glGetColorTableParameteriv) glGetColorTableParameterivEXT __attribute__((alias("glGetColorTableParameteriv")));
|
||||
extern __typeof(glGetCompressedTexImage) glGetCompressedTexImageARB __attribute__((alias("glGetCompressedTexImage")));
|
||||
extern __typeof(glGetDebugMessageLog) glGetDebugMessageLogARB __attribute__((alias("glGetDebugMessageLog")));
|
||||
extern __typeof(glGetDebugMessageLog) glGetDebugMessageLogKHR __attribute__((alias("glGetDebugMessageLog")));
|
||||
extern __typeof(glGetDoublei_v) glGetDoubleIndexedvEXT __attribute__((alias("glGetDoublei_v")));
|
||||
extern __typeof(glGetDoublei_v) glGetDoublei_vEXT __attribute__((alias("glGetDoublei_v")));
|
||||
extern __typeof(glGetFloati_v) glGetFloatIndexedvEXT __attribute__((alias("glGetFloati_v")));
|
||||
@@ -172,6 +204,8 @@ extern __typeof(glGetInteger64v) glGetInteger64vAPPLE __attribute__((alias("glGe
|
||||
extern __typeof(glGetInteger64v) glGetInteger64vEXT __attribute__((alias("glGetInteger64v")));
|
||||
extern __typeof(glGetIntegeri_v) glGetIntegerIndexedvEXT __attribute__((alias("glGetIntegeri_v")));
|
||||
extern __typeof(glGetMultisamplefv) glGetMultisamplefvNV __attribute__((alias("glGetMultisamplefv")));
|
||||
extern __typeof(glGetObjectLabel) glGetObjectLabelKHR __attribute__((alias("glGetObjectLabel")));
|
||||
extern __typeof(glGetProgramBinary) glGetProgramBinaryOES __attribute__((alias("glGetProgramBinary")));
|
||||
extern __typeof(glGetQueryObjecti64v) glGetQueryObjecti64vEXT __attribute__((alias("glGetQueryObjecti64v")));
|
||||
extern __typeof(glGetQueryObjectiv) glGetQueryObjectivARB __attribute__((alias("glGetQueryObjectiv")));
|
||||
extern __typeof(glGetQueryObjectiv) glGetQueryObjectivEXT __attribute__((alias("glGetQueryObjectiv")));
|
||||
@@ -189,6 +223,8 @@ extern __typeof(glGetTexParameterIiv) glGetTexParameterIivEXT __attribute__((ali
|
||||
extern __typeof(glGetTexParameterIiv) glGetTexParameterIivOES __attribute__((alias("glGetTexParameterIiv")));
|
||||
extern __typeof(glGetTexParameterIuiv) glGetTexParameterIuivEXT __attribute__((alias("glGetTexParameterIuiv")));
|
||||
extern __typeof(glGetTexParameterIuiv) glGetTexParameterIuivOES __attribute__((alias("glGetTexParameterIuiv")));
|
||||
extern __typeof(glGetTextureHandleARB) glGetTextureHandleIMG __attribute__((alias("glGetTextureHandleARB")));
|
||||
extern __typeof(glGetTextureSamplerHandleARB) glGetTextureSamplerHandleIMG __attribute__((alias("glGetTextureSamplerHandleARB")));
|
||||
extern __typeof(glGetTransformFeedbackVarying) glGetTransformFeedbackVaryingEXT __attribute__((alias("glGetTransformFeedbackVarying")));
|
||||
extern __typeof(glGetUniformLocation) glGetUniformLocationARB __attribute__((alias("glGetUniformLocation")));
|
||||
extern __typeof(glGetUniformfv) glGetUniformfvARB __attribute__((alias("glGetUniformfv")));
|
||||
@@ -205,12 +241,14 @@ extern __typeof(glGetVertexAttribfv) glGetVertexAttribfvARB __attribute__((alias
|
||||
extern __typeof(glGetVertexAttribfv) glGetVertexAttribfvNV __attribute__((alias("glGetVertexAttribfv")));
|
||||
extern __typeof(glGetVertexAttribiv) glGetVertexAttribivARB __attribute__((alias("glGetVertexAttribiv")));
|
||||
extern __typeof(glGetVertexAttribiv) glGetVertexAttribivNV __attribute__((alias("glGetVertexAttribiv")));
|
||||
extern __typeof(glHistogram) glHistogramEXT __attribute__((alias("glHistogram")));
|
||||
extern __typeof(glIsBuffer) glIsBufferARB __attribute__((alias("glIsBuffer")));
|
||||
extern __typeof(glIsEnabledi) glIsEnabledIndexedEXT __attribute__((alias("glIsEnabledi")));
|
||||
extern __typeof(glIsEnabledi) glIsEnablediEXT __attribute__((alias("glIsEnabledi")));
|
||||
extern __typeof(glIsEnabledi) glIsEnablediNV __attribute__((alias("glIsEnabledi")));
|
||||
extern __typeof(glIsEnabledi) glIsEnablediOES __attribute__((alias("glIsEnabledi")));
|
||||
extern __typeof(glIsFramebuffer) glIsFramebufferEXT __attribute__((alias("glIsFramebuffer")));
|
||||
extern __typeof(glIsProgramARB) glIsProgramNV __attribute__((alias("glIsProgramARB")));
|
||||
extern __typeof(glIsQuery) glIsQueryARB __attribute__((alias("glIsQuery")));
|
||||
extern __typeof(glIsRenderbuffer) glIsRenderbufferEXT __attribute__((alias("glIsRenderbuffer")));
|
||||
extern __typeof(glIsSync) glIsSyncAPPLE __attribute__((alias("glIsSync")));
|
||||
@@ -218,12 +256,18 @@ extern __typeof(glIsTransformFeedback) glIsTransformFeedbackNV __attribute__((al
|
||||
extern __typeof(glIsVertexArray) glIsVertexArrayAPPLE __attribute__((alias("glIsVertexArray")));
|
||||
extern __typeof(glIsVertexArray) glIsVertexArrayOES __attribute__((alias("glIsVertexArray")));
|
||||
extern __typeof(glLinkProgram) glLinkProgramARB __attribute__((alias("glLinkProgram")));
|
||||
extern __typeof(glLoadTransposeMatrixd) glLoadTransposeMatrixdARB __attribute__((alias("glLoadTransposeMatrixd")));
|
||||
extern __typeof(glLoadTransposeMatrixf) glLoadTransposeMatrixfARB __attribute__((alias("glLoadTransposeMatrixf")));
|
||||
extern __typeof(glMapBuffer) glMapBufferARB __attribute__((alias("glMapBuffer")));
|
||||
extern __typeof(glMapBuffer) glMapBufferOES __attribute__((alias("glMapBuffer")));
|
||||
extern __typeof(glMapBufferRange) glMapBufferRangeEXT __attribute__((alias("glMapBufferRange")));
|
||||
extern __typeof(glMaxShaderCompilerThreadsKHR) glMaxShaderCompilerThreadsARB __attribute__((alias("glMaxShaderCompilerThreadsKHR")));
|
||||
extern __typeof(glMemoryBarrier) glMemoryBarrierEXT __attribute__((alias("glMemoryBarrier")));
|
||||
extern __typeof(glMinSampleShading) glMinSampleShadingARB __attribute__((alias("glMinSampleShading")));
|
||||
extern __typeof(glMinSampleShading) glMinSampleShadingOES __attribute__((alias("glMinSampleShading")));
|
||||
extern __typeof(glMinmax) glMinmaxEXT __attribute__((alias("glMinmax")));
|
||||
extern __typeof(glMultTransposeMatrixd) glMultTransposeMatrixdARB __attribute__((alias("glMultTransposeMatrixd")));
|
||||
extern __typeof(glMultTransposeMatrixf) glMultTransposeMatrixfARB __attribute__((alias("glMultTransposeMatrixf")));
|
||||
extern __typeof(glMultiDrawArrays) glMultiDrawArraysEXT __attribute__((alias("glMultiDrawArrays")));
|
||||
extern __typeof(glMultiDrawArraysIndirect) glMultiDrawArraysIndirectAMD __attribute__((alias("glMultiDrawArraysIndirect")));
|
||||
extern __typeof(glMultiDrawArraysIndirect) glMultiDrawArraysIndirectEXT __attribute__((alias("glMultiDrawArraysIndirect")));
|
||||
@@ -231,6 +275,41 @@ extern __typeof(glMultiDrawElementsBaseVertex) glMultiDrawElementsBaseVertexEXT
|
||||
extern __typeof(glMultiDrawElements) glMultiDrawElementsEXT __attribute__((alias("glMultiDrawElements")));
|
||||
extern __typeof(glMultiDrawElementsIndirect) glMultiDrawElementsIndirectAMD __attribute__((alias("glMultiDrawElementsIndirect")));
|
||||
extern __typeof(glMultiDrawElementsIndirect) glMultiDrawElementsIndirectEXT __attribute__((alias("glMultiDrawElementsIndirect")));
|
||||
extern __typeof(glMultiTexCoord1d) glMultiTexCoord1dARB __attribute__((alias("glMultiTexCoord1d")));
|
||||
extern __typeof(glMultiTexCoord1dv) glMultiTexCoord1dvARB __attribute__((alias("glMultiTexCoord1dv")));
|
||||
extern __typeof(glMultiTexCoord1f) glMultiTexCoord1fARB __attribute__((alias("glMultiTexCoord1f")));
|
||||
extern __typeof(glMultiTexCoord1fv) glMultiTexCoord1fvARB __attribute__((alias("glMultiTexCoord1fv")));
|
||||
extern __typeof(glMultiTexCoord1i) glMultiTexCoord1iARB __attribute__((alias("glMultiTexCoord1i")));
|
||||
extern __typeof(glMultiTexCoord1iv) glMultiTexCoord1ivARB __attribute__((alias("glMultiTexCoord1iv")));
|
||||
extern __typeof(glMultiTexCoord1s) glMultiTexCoord1sARB __attribute__((alias("glMultiTexCoord1s")));
|
||||
extern __typeof(glMultiTexCoord1sv) glMultiTexCoord1svARB __attribute__((alias("glMultiTexCoord1sv")));
|
||||
extern __typeof(glMultiTexCoord2d) glMultiTexCoord2dARB __attribute__((alias("glMultiTexCoord2d")));
|
||||
extern __typeof(glMultiTexCoord2dv) glMultiTexCoord2dvARB __attribute__((alias("glMultiTexCoord2dv")));
|
||||
extern __typeof(glMultiTexCoord2f) glMultiTexCoord2fARB __attribute__((alias("glMultiTexCoord2f")));
|
||||
extern __typeof(glMultiTexCoord2fv) glMultiTexCoord2fvARB __attribute__((alias("glMultiTexCoord2fv")));
|
||||
extern __typeof(glMultiTexCoord2i) glMultiTexCoord2iARB __attribute__((alias("glMultiTexCoord2i")));
|
||||
extern __typeof(glMultiTexCoord2iv) glMultiTexCoord2ivARB __attribute__((alias("glMultiTexCoord2iv")));
|
||||
extern __typeof(glMultiTexCoord2s) glMultiTexCoord2sARB __attribute__((alias("glMultiTexCoord2s")));
|
||||
extern __typeof(glMultiTexCoord2sv) glMultiTexCoord2svARB __attribute__((alias("glMultiTexCoord2sv")));
|
||||
extern __typeof(glMultiTexCoord3d) glMultiTexCoord3dARB __attribute__((alias("glMultiTexCoord3d")));
|
||||
extern __typeof(glMultiTexCoord3dv) glMultiTexCoord3dvARB __attribute__((alias("glMultiTexCoord3dv")));
|
||||
extern __typeof(glMultiTexCoord3f) glMultiTexCoord3fARB __attribute__((alias("glMultiTexCoord3f")));
|
||||
extern __typeof(glMultiTexCoord3fv) glMultiTexCoord3fvARB __attribute__((alias("glMultiTexCoord3fv")));
|
||||
extern __typeof(glMultiTexCoord3i) glMultiTexCoord3iARB __attribute__((alias("glMultiTexCoord3i")));
|
||||
extern __typeof(glMultiTexCoord3iv) glMultiTexCoord3ivARB __attribute__((alias("glMultiTexCoord3iv")));
|
||||
extern __typeof(glMultiTexCoord3s) glMultiTexCoord3sARB __attribute__((alias("glMultiTexCoord3s")));
|
||||
extern __typeof(glMultiTexCoord3sv) glMultiTexCoord3svARB __attribute__((alias("glMultiTexCoord3sv")));
|
||||
extern __typeof(glMultiTexCoord4d) glMultiTexCoord4dARB __attribute__((alias("glMultiTexCoord4d")));
|
||||
extern __typeof(glMultiTexCoord4dv) glMultiTexCoord4dvARB __attribute__((alias("glMultiTexCoord4dv")));
|
||||
extern __typeof(glMultiTexCoord4f) glMultiTexCoord4fARB __attribute__((alias("glMultiTexCoord4f")));
|
||||
extern __typeof(glMultiTexCoord4fv) glMultiTexCoord4fvARB __attribute__((alias("glMultiTexCoord4fv")));
|
||||
extern __typeof(glMultiTexCoord4i) glMultiTexCoord4iARB __attribute__((alias("glMultiTexCoord4i")));
|
||||
extern __typeof(glMultiTexCoord4iv) glMultiTexCoord4ivARB __attribute__((alias("glMultiTexCoord4iv")));
|
||||
extern __typeof(glMultiTexCoord4s) glMultiTexCoord4sARB __attribute__((alias("glMultiTexCoord4s")));
|
||||
extern __typeof(glMultiTexCoord4sv) glMultiTexCoord4svARB __attribute__((alias("glMultiTexCoord4sv")));
|
||||
extern __typeof(glNamedBufferStorage) glNamedBufferStorageEXT __attribute__((alias("glNamedBufferStorage")));
|
||||
extern __typeof(glNamedBufferSubData) glNamedBufferSubDataEXT __attribute__((alias("glNamedBufferSubData")));
|
||||
extern __typeof(glObjectLabel) glObjectLabelKHR __attribute__((alias("glObjectLabel")));
|
||||
extern __typeof(glPatchParameteri) glPatchParameteriEXT __attribute__((alias("glPatchParameteri")));
|
||||
extern __typeof(glPatchParameteri) glPatchParameteriOES __attribute__((alias("glPatchParameteri")));
|
||||
extern __typeof(glPauseTransformFeedback) glPauseTransformFeedbackNV __attribute__((alias("glPauseTransformFeedback")));
|
||||
@@ -243,7 +322,9 @@ extern __typeof(glPointParameterfv) glPointParameterfvSGIS __attribute__((alias(
|
||||
extern __typeof(glPointParameteri) glPointParameteriNV __attribute__((alias("glPointParameteri")));
|
||||
extern __typeof(glPointParameteriv) glPointParameterivNV __attribute__((alias("glPointParameteriv")));
|
||||
extern __typeof(glPolygonMode) glPolygonModeNV __attribute__((alias("glPolygonMode")));
|
||||
extern __typeof(glPolygonOffsetClamp) glPolygonOffsetClampEXT __attribute__((alias("glPolygonOffsetClamp")));
|
||||
extern __typeof(glPopDebugGroup) glPopDebugGroupKHR __attribute__((alias("glPopDebugGroup")));
|
||||
extern __typeof(glProgramBinary) glProgramBinaryOES __attribute__((alias("glProgramBinary")));
|
||||
extern __typeof(glProgramParameteri) glProgramParameteriARB __attribute__((alias("glProgramParameteri")));
|
||||
extern __typeof(glProgramParameteri) glProgramParameteriEXT __attribute__((alias("glProgramParameteri")));
|
||||
extern __typeof(glProgramUniform1f) glProgramUniform1fEXT __attribute__((alias("glProgramUniform1f")));
|
||||
@@ -270,6 +351,8 @@ extern __typeof(glProgramUniform4i) glProgramUniform4iEXT __attribute__((alias("
|
||||
extern __typeof(glProgramUniform4iv) glProgramUniform4ivEXT __attribute__((alias("glProgramUniform4iv")));
|
||||
extern __typeof(glProgramUniform4ui) glProgramUniform4uiEXT __attribute__((alias("glProgramUniform4ui")));
|
||||
extern __typeof(glProgramUniform4uiv) glProgramUniform4uivEXT __attribute__((alias("glProgramUniform4uiv")));
|
||||
extern __typeof(glProgramUniformHandleui64ARB) glProgramUniformHandleui64IMG __attribute__((alias("glProgramUniformHandleui64ARB")));
|
||||
extern __typeof(glProgramUniformHandleui64vARB) glProgramUniformHandleui64vIMG __attribute__((alias("glProgramUniformHandleui64vARB")));
|
||||
extern __typeof(glProgramUniformMatrix2fv) glProgramUniformMatrix2fvEXT __attribute__((alias("glProgramUniformMatrix2fv")));
|
||||
extern __typeof(glProgramUniformMatrix2x3fv) glProgramUniformMatrix2x3fvEXT __attribute__((alias("glProgramUniformMatrix2x3fv")));
|
||||
extern __typeof(glProgramUniformMatrix2x4fv) glProgramUniformMatrix2x4fvEXT __attribute__((alias("glProgramUniformMatrix2x4fv")));
|
||||
@@ -280,12 +363,20 @@ extern __typeof(glProgramUniformMatrix4fv) glProgramUniformMatrix4fvEXT __attrib
|
||||
extern __typeof(glProgramUniformMatrix4x2fv) glProgramUniformMatrix4x2fvEXT __attribute__((alias("glProgramUniformMatrix4x2fv")));
|
||||
extern __typeof(glProgramUniformMatrix4x3fv) glProgramUniformMatrix4x3fvEXT __attribute__((alias("glProgramUniformMatrix4x3fv")));
|
||||
extern __typeof(glProvokingVertex) glProvokingVertexEXT __attribute__((alias("glProvokingVertex")));
|
||||
extern __typeof(glPushDebugGroup) glPushDebugGroupKHR __attribute__((alias("glPushDebugGroup")));
|
||||
extern __typeof(glQueryCounter) glQueryCounterEXT __attribute__((alias("glQueryCounter")));
|
||||
extern __typeof(glReadnPixels) glReadnPixelsARB __attribute__((alias("glReadnPixels")));
|
||||
extern __typeof(glReadnPixels) glReadnPixelsEXT __attribute__((alias("glReadnPixels")));
|
||||
extern __typeof(glReadnPixels) glReadnPixelsKHR __attribute__((alias("glReadnPixels")));
|
||||
extern __typeof(glRenderbufferStorage) glRenderbufferStorageEXT __attribute__((alias("glRenderbufferStorage")));
|
||||
extern __typeof(glRenderbufferStorageMultisample) glRenderbufferStorageMultisampleEXT __attribute__((alias("glRenderbufferStorageMultisample")));
|
||||
extern __typeof(glRenderbufferStorageMultisample) glRenderbufferStorageMultisampleNV __attribute__((alias("glRenderbufferStorageMultisample")));
|
||||
extern __typeof(glResetHistogram) glResetHistogramEXT __attribute__((alias("glResetHistogram")));
|
||||
extern __typeof(glResetMinmax) glResetMinmaxEXT __attribute__((alias("glResetMinmax")));
|
||||
extern __typeof(glResumeTransformFeedback) glResumeTransformFeedbackNV __attribute__((alias("glResumeTransformFeedback")));
|
||||
extern __typeof(glSampleCoverage) glSampleCoverageARB __attribute__((alias("glSampleCoverage")));
|
||||
extern __typeof(glSampleMaskEXT) glSampleMaskSGIS __attribute__((alias("glSampleMaskEXT")));
|
||||
extern __typeof(glSamplePatternEXT) glSamplePatternSGIS __attribute__((alias("glSamplePatternEXT")));
|
||||
extern __typeof(glSamplerParameterIiv) glSamplerParameterIivEXT __attribute__((alias("glSamplerParameterIiv")));
|
||||
extern __typeof(glSamplerParameterIiv) glSamplerParameterIivOES __attribute__((alias("glSamplerParameterIiv")));
|
||||
extern __typeof(glSamplerParameterIuiv) glSamplerParameterIuivEXT __attribute__((alias("glSamplerParameterIuiv")));
|
||||
@@ -296,7 +387,24 @@ extern __typeof(glScissorIndexed) glScissorIndexedNV __attribute__((alias("glSci
|
||||
extern __typeof(glScissorIndexed) glScissorIndexedOES __attribute__((alias("glScissorIndexed")));
|
||||
extern __typeof(glScissorIndexedv) glScissorIndexedvNV __attribute__((alias("glScissorIndexedv")));
|
||||
extern __typeof(glScissorIndexedv) glScissorIndexedvOES __attribute__((alias("glScissorIndexedv")));
|
||||
extern __typeof(glSecondaryColor3b) glSecondaryColor3bEXT __attribute__((alias("glSecondaryColor3b")));
|
||||
extern __typeof(glSecondaryColor3bv) glSecondaryColor3bvEXT __attribute__((alias("glSecondaryColor3bv")));
|
||||
extern __typeof(glSecondaryColor3d) glSecondaryColor3dEXT __attribute__((alias("glSecondaryColor3d")));
|
||||
extern __typeof(glSecondaryColor3dv) glSecondaryColor3dvEXT __attribute__((alias("glSecondaryColor3dv")));
|
||||
extern __typeof(glSecondaryColor3f) glSecondaryColor3fEXT __attribute__((alias("glSecondaryColor3f")));
|
||||
extern __typeof(glSecondaryColor3fv) glSecondaryColor3fvEXT __attribute__((alias("glSecondaryColor3fv")));
|
||||
extern __typeof(glSecondaryColor3i) glSecondaryColor3iEXT __attribute__((alias("glSecondaryColor3i")));
|
||||
extern __typeof(glSecondaryColor3iv) glSecondaryColor3ivEXT __attribute__((alias("glSecondaryColor3iv")));
|
||||
extern __typeof(glSecondaryColor3s) glSecondaryColor3sEXT __attribute__((alias("glSecondaryColor3s")));
|
||||
extern __typeof(glSecondaryColor3sv) glSecondaryColor3svEXT __attribute__((alias("glSecondaryColor3sv")));
|
||||
extern __typeof(glSecondaryColor3ub) glSecondaryColor3ubEXT __attribute__((alias("glSecondaryColor3ub")));
|
||||
extern __typeof(glSecondaryColor3ubv) glSecondaryColor3ubvEXT __attribute__((alias("glSecondaryColor3ubv")));
|
||||
extern __typeof(glSecondaryColor3ui) glSecondaryColor3uiEXT __attribute__((alias("glSecondaryColor3ui")));
|
||||
extern __typeof(glSecondaryColor3uiv) glSecondaryColor3uivEXT __attribute__((alias("glSecondaryColor3uiv")));
|
||||
extern __typeof(glSecondaryColor3us) glSecondaryColor3usEXT __attribute__((alias("glSecondaryColor3us")));
|
||||
extern __typeof(glSecondaryColor3usv) glSecondaryColor3usvEXT __attribute__((alias("glSecondaryColor3usv")));
|
||||
extern __typeof(glShaderSource) glShaderSourceARB __attribute__((alias("glShaderSource")));
|
||||
extern __typeof(glSpecializeShader) glSpecializeShaderARB __attribute__((alias("glSpecializeShader")));
|
||||
extern __typeof(glStencilOpSeparate) glStencilOpSeparateATI __attribute__((alias("glStencilOpSeparate")));
|
||||
extern __typeof(glTexBuffer) glTexBufferARB __attribute__((alias("glTexBuffer")));
|
||||
extern __typeof(glTexBuffer) glTexBufferEXT __attribute__((alias("glTexBuffer")));
|
||||
@@ -304,6 +412,7 @@ extern __typeof(glTexBuffer) glTexBufferOES __attribute__((alias("glTexBuffer"))
|
||||
extern __typeof(glTexBufferRange) glTexBufferRangeEXT __attribute__((alias("glTexBufferRange")));
|
||||
extern __typeof(glTexBufferRange) glTexBufferRangeOES __attribute__((alias("glTexBufferRange")));
|
||||
extern __typeof(glTexImage3D) glTexImage3DEXT __attribute__((alias("glTexImage3D")));
|
||||
extern __typeof(glTexPageCommitmentARB) glTexPageCommitmentEXT __attribute__((alias("glTexPageCommitmentARB")));
|
||||
extern __typeof(glTexParameterIiv) glTexParameterIivEXT __attribute__((alias("glTexParameterIiv")));
|
||||
extern __typeof(glTexParameterIiv) glTexParameterIivOES __attribute__((alias("glTexParameterIiv")));
|
||||
extern __typeof(glTexParameterIuiv) glTexParameterIuivEXT __attribute__((alias("glTexParameterIuiv")));
|
||||
@@ -342,6 +451,8 @@ extern __typeof(glUniform4i) glUniform4iARB __attribute__((alias("glUniform4i"))
|
||||
extern __typeof(glUniform4iv) glUniform4ivARB __attribute__((alias("glUniform4iv")));
|
||||
extern __typeof(glUniform4ui) glUniform4uiEXT __attribute__((alias("glUniform4ui")));
|
||||
extern __typeof(glUniform4uiv) glUniform4uivEXT __attribute__((alias("glUniform4uiv")));
|
||||
extern __typeof(glUniformHandleui64ARB) glUniformHandleui64IMG __attribute__((alias("glUniformHandleui64ARB")));
|
||||
extern __typeof(glUniformHandleui64vARB) glUniformHandleui64vIMG __attribute__((alias("glUniformHandleui64vARB")));
|
||||
extern __typeof(glUniformMatrix2fv) glUniformMatrix2fvARB __attribute__((alias("glUniformMatrix2fv")));
|
||||
extern __typeof(glUniformMatrix2x3fv) glUniformMatrix2x3fvNV __attribute__((alias("glUniformMatrix2x3fv")));
|
||||
extern __typeof(glUniformMatrix2x4fv) glUniformMatrix2x4fvNV __attribute__((alias("glUniformMatrix2x4fv")));
|
||||
@@ -459,3 +570,35 @@ extern __typeof(glViewportIndexedf) glViewportIndexedfOES __attribute__((alias("
|
||||
extern __typeof(glViewportIndexedfv) glViewportIndexedfvNV __attribute__((alias("glViewportIndexedfv")));
|
||||
extern __typeof(glViewportIndexedfv) glViewportIndexedfvOES __attribute__((alias("glViewportIndexedfv")));
|
||||
extern __typeof(glWaitSync) glWaitSyncAPPLE __attribute__((alias("glWaitSync")));
|
||||
extern __typeof(glWindowPos2d) glWindowPos2dARB __attribute__((alias("glWindowPos2d")));
|
||||
extern __typeof(glWindowPos2d) glWindowPos2dMESA __attribute__((alias("glWindowPos2d")));
|
||||
extern __typeof(glWindowPos2dv) glWindowPos2dvARB __attribute__((alias("glWindowPos2dv")));
|
||||
extern __typeof(glWindowPos2dv) glWindowPos2dvMESA __attribute__((alias("glWindowPos2dv")));
|
||||
extern __typeof(glWindowPos2f) glWindowPos2fARB __attribute__((alias("glWindowPos2f")));
|
||||
extern __typeof(glWindowPos2f) glWindowPos2fMESA __attribute__((alias("glWindowPos2f")));
|
||||
extern __typeof(glWindowPos2fv) glWindowPos2fvARB __attribute__((alias("glWindowPos2fv")));
|
||||
extern __typeof(glWindowPos2fv) glWindowPos2fvMESA __attribute__((alias("glWindowPos2fv")));
|
||||
extern __typeof(glWindowPos2i) glWindowPos2iARB __attribute__((alias("glWindowPos2i")));
|
||||
extern __typeof(glWindowPos2i) glWindowPos2iMESA __attribute__((alias("glWindowPos2i")));
|
||||
extern __typeof(glWindowPos2iv) glWindowPos2ivARB __attribute__((alias("glWindowPos2iv")));
|
||||
extern __typeof(glWindowPos2iv) glWindowPos2ivMESA __attribute__((alias("glWindowPos2iv")));
|
||||
extern __typeof(glWindowPos2s) glWindowPos2sARB __attribute__((alias("glWindowPos2s")));
|
||||
extern __typeof(glWindowPos2s) glWindowPos2sMESA __attribute__((alias("glWindowPos2s")));
|
||||
extern __typeof(glWindowPos2sv) glWindowPos2svARB __attribute__((alias("glWindowPos2sv")));
|
||||
extern __typeof(glWindowPos2sv) glWindowPos2svMESA __attribute__((alias("glWindowPos2sv")));
|
||||
extern __typeof(glWindowPos3d) glWindowPos3dARB __attribute__((alias("glWindowPos3d")));
|
||||
extern __typeof(glWindowPos3d) glWindowPos3dMESA __attribute__((alias("glWindowPos3d")));
|
||||
extern __typeof(glWindowPos3dv) glWindowPos3dvARB __attribute__((alias("glWindowPos3dv")));
|
||||
extern __typeof(glWindowPos3dv) glWindowPos3dvMESA __attribute__((alias("glWindowPos3dv")));
|
||||
extern __typeof(glWindowPos3f) glWindowPos3fARB __attribute__((alias("glWindowPos3f")));
|
||||
extern __typeof(glWindowPos3f) glWindowPos3fMESA __attribute__((alias("glWindowPos3f")));
|
||||
extern __typeof(glWindowPos3fv) glWindowPos3fvARB __attribute__((alias("glWindowPos3fv")));
|
||||
extern __typeof(glWindowPos3fv) glWindowPos3fvMESA __attribute__((alias("glWindowPos3fv")));
|
||||
extern __typeof(glWindowPos3i) glWindowPos3iARB __attribute__((alias("glWindowPos3i")));
|
||||
extern __typeof(glWindowPos3i) glWindowPos3iMESA __attribute__((alias("glWindowPos3i")));
|
||||
extern __typeof(glWindowPos3iv) glWindowPos3ivARB __attribute__((alias("glWindowPos3iv")));
|
||||
extern __typeof(glWindowPos3iv) glWindowPos3ivMESA __attribute__((alias("glWindowPos3iv")));
|
||||
extern __typeof(glWindowPos3s) glWindowPos3sARB __attribute__((alias("glWindowPos3s")));
|
||||
extern __typeof(glWindowPos3s) glWindowPos3sMESA __attribute__((alias("glWindowPos3s")));
|
||||
extern __typeof(glWindowPos3sv) glWindowPos3svARB __attribute__((alias("glWindowPos3sv")));
|
||||
extern __typeof(glWindowPos3sv) glWindowPos3svMESA __attribute__((alias("glWindowPos3sv")));
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,13 +2,14 @@
|
||||
*
|
||||
* Extensions the guest may repeat from the host: every command the
|
||||
* Khronos registry says they require is exported by this library.
|
||||
* 581 claimable, 279 withheld for missing entry
|
||||
* 714 claimable, 146 withheld for missing entry
|
||||
* points, out of the registry's whole extension set. A host
|
||||
* extension absent from this table is not advertised to the guest,
|
||||
* which is why adding a driver capability can need a rebuild here.
|
||||
*/
|
||||
static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_3DFX_multisample",
|
||||
"GL_3DFX_tbuffer",
|
||||
"GL_3DFX_texture_compression_FXT1",
|
||||
"GL_AMD_blend_minmax_factor",
|
||||
"GL_AMD_compressed_3DC_texture",
|
||||
@@ -16,13 +17,18 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_AMD_conservative_depth",
|
||||
"GL_AMD_depth_clamp_separate",
|
||||
"GL_AMD_draw_buffers_blend",
|
||||
"GL_AMD_framebuffer_multisample_advanced",
|
||||
"GL_AMD_gcn_shader",
|
||||
"GL_AMD_gpu_shader_half_float",
|
||||
"GL_AMD_gpu_shader_int16",
|
||||
"GL_AMD_gpu_shader_int64",
|
||||
"GL_AMD_interleaved_elements",
|
||||
"GL_AMD_multi_draw_indirect",
|
||||
"GL_AMD_occlusion_query_event",
|
||||
"GL_AMD_pinned_memory",
|
||||
"GL_AMD_program_binary_Z400",
|
||||
"GL_AMD_query_buffer_object",
|
||||
"GL_AMD_sample_positions",
|
||||
"GL_AMD_seamless_cubemap_per_texture",
|
||||
"GL_AMD_shader_atomic_counter_ops",
|
||||
"GL_AMD_shader_ballot",
|
||||
@@ -31,11 +37,14 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_AMD_shader_image_load_store_lod",
|
||||
"GL_AMD_shader_stencil_export",
|
||||
"GL_AMD_shader_trinary_minmax",
|
||||
"GL_AMD_sparse_texture",
|
||||
"GL_AMD_stencil_operation_extended",
|
||||
"GL_AMD_texture_gather_bias_lod",
|
||||
"GL_AMD_texture_texture4",
|
||||
"GL_AMD_transform_feedback3_lines_triangles",
|
||||
"GL_AMD_transform_feedback4",
|
||||
"GL_AMD_vertex_shader_layer",
|
||||
"GL_AMD_vertex_shader_tessellator",
|
||||
"GL_AMD_vertex_shader_viewport_index",
|
||||
"GL_ANDROID_extension_pack_es31a",
|
||||
"GL_ANGLE_depth_texture",
|
||||
@@ -50,6 +59,8 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_APPLE_clip_distance",
|
||||
"GL_APPLE_color_buffer_packed_float",
|
||||
"GL_APPLE_float_pixels",
|
||||
"GL_APPLE_flush_buffer_range",
|
||||
"GL_APPLE_object_purgeable",
|
||||
"GL_APPLE_rgb_422",
|
||||
"GL_APPLE_row_bytes",
|
||||
"GL_APPLE_specular_vector",
|
||||
@@ -59,7 +70,10 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_APPLE_texture_max_level",
|
||||
"GL_APPLE_texture_packed_float",
|
||||
"GL_APPLE_transform_hint",
|
||||
"GL_APPLE_vertex_array_object",
|
||||
"GL_APPLE_vertex_array_range",
|
||||
"GL_APPLE_ycbcr_422",
|
||||
"GL_ARB_ES3_1_compatibility",
|
||||
"GL_ARB_ES3_compatibility",
|
||||
"GL_ARB_arrays_of_arrays",
|
||||
"GL_ARB_base_instance",
|
||||
@@ -67,10 +81,12 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_buffer_storage",
|
||||
"GL_ARB_clear_buffer_object",
|
||||
"GL_ARB_clear_texture",
|
||||
"GL_ARB_clip_control",
|
||||
"GL_ARB_color_buffer_float",
|
||||
"GL_ARB_compatibility",
|
||||
"GL_ARB_compressed_texture_pixel_storage",
|
||||
"GL_ARB_compute_shader",
|
||||
"GL_ARB_compute_variable_group_size",
|
||||
"GL_ARB_conditional_render_inverted",
|
||||
"GL_ARB_conservative_depth",
|
||||
"GL_ARB_copy_buffer",
|
||||
@@ -96,6 +112,10 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_framebuffer_no_attachments",
|
||||
"GL_ARB_framebuffer_object",
|
||||
"GL_ARB_framebuffer_sRGB",
|
||||
"GL_ARB_geometry_shader4",
|
||||
"GL_ARB_get_program_binary",
|
||||
"GL_ARB_get_texture_sub_image",
|
||||
"GL_ARB_gl_spirv",
|
||||
"GL_ARB_gpu_shader5",
|
||||
"GL_ARB_gpu_shader_fp64",
|
||||
"GL_ARB_half_float_pixel",
|
||||
@@ -104,17 +124,21 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_instanced_arrays",
|
||||
"GL_ARB_internalformat_query",
|
||||
"GL_ARB_internalformat_query2",
|
||||
"GL_ARB_invalidate_subdata",
|
||||
"GL_ARB_map_buffer_alignment",
|
||||
"GL_ARB_map_buffer_range",
|
||||
"GL_ARB_multi_bind",
|
||||
"GL_ARB_multi_draw_indirect",
|
||||
"GL_ARB_multisample",
|
||||
"GL_ARB_multitexture",
|
||||
"GL_ARB_occlusion_query",
|
||||
"GL_ARB_occlusion_query2",
|
||||
"GL_ARB_parallel_shader_compile",
|
||||
"GL_ARB_pipeline_statistics_query",
|
||||
"GL_ARB_pixel_buffer_object",
|
||||
"GL_ARB_point_parameters",
|
||||
"GL_ARB_point_sprite",
|
||||
"GL_ARB_polygon_offset_clamp",
|
||||
"GL_ARB_post_depth_coverage",
|
||||
"GL_ARB_program_interface_query",
|
||||
"GL_ARB_provoking_vertex",
|
||||
@@ -137,6 +161,7 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_shader_precision",
|
||||
"GL_ARB_shader_stencil_export",
|
||||
"GL_ARB_shader_storage_buffer_object",
|
||||
"GL_ARB_shader_subroutine",
|
||||
"GL_ARB_shader_texture_image_samples",
|
||||
"GL_ARB_shader_texture_lod",
|
||||
"GL_ARB_shader_viewport_layer_array",
|
||||
@@ -145,12 +170,15 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_shading_language_packing",
|
||||
"GL_ARB_shadow",
|
||||
"GL_ARB_shadow_ambient",
|
||||
"GL_ARB_sparse_buffer",
|
||||
"GL_ARB_sparse_texture",
|
||||
"GL_ARB_sparse_texture2",
|
||||
"GL_ARB_sparse_texture_clamp",
|
||||
"GL_ARB_spirv_extensions",
|
||||
"GL_ARB_stencil_texturing",
|
||||
"GL_ARB_sync",
|
||||
"GL_ARB_tessellation_shader",
|
||||
"GL_ARB_texture_barrier",
|
||||
"GL_ARB_texture_border_clamp",
|
||||
"GL_ARB_texture_buffer_object",
|
||||
"GL_ARB_texture_buffer_object_rgb32",
|
||||
@@ -187,6 +215,7 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_transform_feedback3",
|
||||
"GL_ARB_transform_feedback_instanced",
|
||||
"GL_ARB_transform_feedback_overflow_query",
|
||||
"GL_ARB_transpose_matrix",
|
||||
"GL_ARB_uniform_buffer_object",
|
||||
"GL_ARB_vertex_array_bgra",
|
||||
"GL_ARB_vertex_array_object",
|
||||
@@ -196,6 +225,7 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARB_vertex_shader",
|
||||
"GL_ARB_vertex_type_10f_11f_11f_rev",
|
||||
"GL_ARB_vertex_type_2_10_10_10_rev",
|
||||
"GL_ARB_window_pos",
|
||||
"GL_ARM_mali_program_binary",
|
||||
"GL_ARM_mali_shader_binary",
|
||||
"GL_ARM_rgba8",
|
||||
@@ -203,12 +233,18 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_ARM_shader_framebuffer_fetch_depth_stencil",
|
||||
"GL_ARM_texture_unnormalized_coordinates",
|
||||
"GL_ATI_draw_buffers",
|
||||
"GL_ATI_envmap_bumpmap",
|
||||
"GL_ATI_meminfo",
|
||||
"GL_ATI_pixel_format_float",
|
||||
"GL_ATI_pn_triangles",
|
||||
"GL_ATI_separate_stencil",
|
||||
"GL_ATI_text_fragment_shader",
|
||||
"GL_ATI_texture_env_combine3",
|
||||
"GL_ATI_texture_float",
|
||||
"GL_ATI_texture_mirror_once",
|
||||
"GL_ATI_vertex_array_object",
|
||||
"GL_ATI_vertex_attrib_array_object",
|
||||
"GL_ATI_vertex_streams",
|
||||
"GL_DMP_program_binary",
|
||||
"GL_DMP_shader_binary",
|
||||
"GL_EXT_422_pixels",
|
||||
@@ -227,14 +263,21 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_blend_subtract",
|
||||
"GL_EXT_buffer_storage",
|
||||
"GL_EXT_clear_texture",
|
||||
"GL_EXT_clip_control",
|
||||
"GL_EXT_clip_cull_distance",
|
||||
"GL_EXT_clip_volume_hint",
|
||||
"GL_EXT_cmyka",
|
||||
"GL_EXT_color_buffer_float",
|
||||
"GL_EXT_color_buffer_half_float",
|
||||
"GL_EXT_color_subtable",
|
||||
"GL_EXT_compiled_vertex_array",
|
||||
"GL_EXT_conservative_depth",
|
||||
"GL_EXT_copy_image",
|
||||
"GL_EXT_copy_texture",
|
||||
"GL_EXT_cull_vertex",
|
||||
"GL_EXT_debug_label",
|
||||
"GL_EXT_debug_marker",
|
||||
"GL_EXT_depth_bounds_test",
|
||||
"GL_EXT_depth_clamp",
|
||||
"GL_EXT_draw_buffers",
|
||||
"GL_EXT_draw_buffers2",
|
||||
@@ -244,7 +287,9 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_draw_range_elements",
|
||||
"GL_EXT_draw_transform_feedback",
|
||||
"GL_EXT_float_blend",
|
||||
"GL_EXT_fragment_shading_rate",
|
||||
"GL_EXT_framebuffer_blit",
|
||||
"GL_EXT_framebuffer_blit_layers",
|
||||
"GL_EXT_framebuffer_multisample",
|
||||
"GL_EXT_framebuffer_multisample_blit_scaled",
|
||||
"GL_EXT_framebuffer_object",
|
||||
@@ -252,15 +297,22 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_geometry_point_size",
|
||||
"GL_EXT_geometry_shader",
|
||||
"GL_EXT_geometry_shader4",
|
||||
"GL_EXT_gpu_program_parameters",
|
||||
"GL_EXT_gpu_shader4",
|
||||
"GL_EXT_gpu_shader5",
|
||||
"GL_EXT_index_array_formats",
|
||||
"GL_EXT_index_func",
|
||||
"GL_EXT_index_material",
|
||||
"GL_EXT_index_texture",
|
||||
"GL_EXT_instanced_arrays",
|
||||
"GL_EXT_light_texture",
|
||||
"GL_EXT_map_buffer_range",
|
||||
"GL_EXT_memory_object_fd",
|
||||
"GL_EXT_mesh_shader",
|
||||
"GL_EXT_misc_attribute",
|
||||
"GL_EXT_multi_draw_arrays",
|
||||
"GL_EXT_multi_draw_indirect",
|
||||
"GL_EXT_multisample",
|
||||
"GL_EXT_multisampled_compatibility",
|
||||
"GL_EXT_multisampled_render_to_texture2",
|
||||
"GL_EXT_multiview_tessellation_geometry_shader",
|
||||
@@ -270,22 +322,29 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_packed_float",
|
||||
"GL_EXT_packed_pixels",
|
||||
"GL_EXT_pixel_buffer_object",
|
||||
"GL_EXT_pixel_transform",
|
||||
"GL_EXT_pixel_transform_color_table",
|
||||
"GL_EXT_point_parameters",
|
||||
"GL_EXT_polygon_offset",
|
||||
"GL_EXT_polygon_offset_clamp",
|
||||
"GL_EXT_post_depth_coverage",
|
||||
"GL_EXT_protected_textures",
|
||||
"GL_EXT_provoking_vertex",
|
||||
"GL_EXT_pvrtc_sRGB",
|
||||
"GL_EXT_raster_multisample",
|
||||
"GL_EXT_read_format_bgra",
|
||||
"GL_EXT_render_snorm",
|
||||
"GL_EXT_rescale_normal",
|
||||
"GL_EXT_sRGB",
|
||||
"GL_EXT_sRGB_write_control",
|
||||
"GL_EXT_semaphore_fd",
|
||||
"GL_EXT_separate_depth_stencil",
|
||||
"GL_EXT_separate_specular_color",
|
||||
"GL_EXT_shader_framebuffer_fetch",
|
||||
"GL_EXT_shader_framebuffer_fetch_non_coherent",
|
||||
"GL_EXT_shader_group_vote",
|
||||
"GL_EXT_shader_image_load_formatted",
|
||||
"GL_EXT_shader_image_load_store",
|
||||
"GL_EXT_shader_implicit_conversions",
|
||||
"GL_EXT_shader_integer_mix",
|
||||
"GL_EXT_shader_io_blocks",
|
||||
@@ -297,7 +356,10 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_shadow_funcs",
|
||||
"GL_EXT_shadow_samplers",
|
||||
"GL_EXT_shared_texture_palette",
|
||||
"GL_EXT_sparse_texture",
|
||||
"GL_EXT_sparse_texture2",
|
||||
"GL_EXT_stencil_clear_tag",
|
||||
"GL_EXT_stencil_two_side",
|
||||
"GL_EXT_stencil_wrap",
|
||||
"GL_EXT_subtexture",
|
||||
"GL_EXT_tessellation_point_size",
|
||||
@@ -324,10 +386,12 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_texture_filter_minmax",
|
||||
"GL_EXT_texture_format_BGRA8888",
|
||||
"GL_EXT_texture_format_sRGB_override",
|
||||
"GL_EXT_texture_integer",
|
||||
"GL_EXT_texture_lod_bias",
|
||||
"GL_EXT_texture_mirror_clamp",
|
||||
"GL_EXT_texture_mirror_clamp_to_edge",
|
||||
"GL_EXT_texture_norm16",
|
||||
"GL_EXT_texture_perturb_normal",
|
||||
"GL_EXT_texture_query_lod",
|
||||
"GL_EXT_texture_rg",
|
||||
"GL_EXT_texture_sRGB",
|
||||
@@ -337,22 +401,30 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_EXT_texture_shadow_lod",
|
||||
"GL_EXT_texture_shared_exponent",
|
||||
"GL_EXT_texture_snorm",
|
||||
"GL_EXT_texture_storage",
|
||||
"GL_EXT_texture_swizzle",
|
||||
"GL_EXT_texture_type_2_10_10_10_REV",
|
||||
"GL_EXT_texture_view",
|
||||
"GL_EXT_timer_query",
|
||||
"GL_EXT_transform_feedback",
|
||||
"GL_EXT_unpack_subimage",
|
||||
"GL_EXT_vertex_array_bgra",
|
||||
"GL_EXT_vertex_attrib_64bit",
|
||||
"GL_EXT_win32_keyed_mutex",
|
||||
"GL_FJ_shader_binary_GCCSO",
|
||||
"GL_GREMEDY_frame_terminator",
|
||||
"GL_GREMEDY_string_marker",
|
||||
"GL_HP_convolution_border_modes",
|
||||
"GL_HP_image_transform",
|
||||
"GL_HP_occlusion_test",
|
||||
"GL_HP_texture_lighting",
|
||||
"GL_HUAWEI_program_binary",
|
||||
"GL_HUAWEI_shader_binary",
|
||||
"GL_IBM_cull_vertex",
|
||||
"GL_IBM_rasterpos_clip",
|
||||
"GL_IBM_static_data",
|
||||
"GL_IBM_texture_mirrored_repeat",
|
||||
"GL_IMG_bindless_texture",
|
||||
"GL_IMG_program_binary",
|
||||
"GL_IMG_read_format",
|
||||
"GL_IMG_shader_binary",
|
||||
@@ -366,9 +438,11 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_INTEL_blackhole_render",
|
||||
"GL_INTEL_conservative_rasterization",
|
||||
"GL_INTEL_fragment_shader_ordering",
|
||||
"GL_INTEL_framebuffer_CMAA",
|
||||
"GL_KHR_blend_equation_advanced_coherent",
|
||||
"GL_KHR_context_flush_control",
|
||||
"GL_KHR_no_error",
|
||||
"GL_KHR_parallel_shader_compile",
|
||||
"GL_KHR_robust_buffer_access_behavior",
|
||||
"GL_KHR_shader_subgroup",
|
||||
"GL_KHR_texture_compression_astc_hdr",
|
||||
@@ -377,35 +451,51 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_MESAX_texture_stack",
|
||||
"GL_MESA_bgra",
|
||||
"GL_MESA_framebuffer_flip_x",
|
||||
"GL_MESA_framebuffer_flip_y",
|
||||
"GL_MESA_framebuffer_swap_xy",
|
||||
"GL_MESA_pack_invert",
|
||||
"GL_MESA_program_binary_formats",
|
||||
"GL_MESA_resize_buffers",
|
||||
"GL_MESA_sampler_objects",
|
||||
"GL_MESA_shader_integer_functions",
|
||||
"GL_MESA_texture_const_bandwidth",
|
||||
"GL_MESA_tile_raster_order",
|
||||
"GL_MESA_window_pos",
|
||||
"GL_MESA_ycbcr_texture",
|
||||
"GL_NVX_blend_equation_advanced_multi_draw_buffers",
|
||||
"GL_NVX_conditional_render",
|
||||
"GL_NVX_gpu_memory_info",
|
||||
"GL_NV_alpha_to_coverage_dither_control",
|
||||
"GL_NV_bindless_texture",
|
||||
"GL_NV_blend_equation_advanced_coherent",
|
||||
"GL_NV_blend_minmax_factor",
|
||||
"GL_NV_blend_square",
|
||||
"GL_NV_clip_space_w_scaling",
|
||||
"GL_NV_compute_program5",
|
||||
"GL_NV_compute_shader_derivatives",
|
||||
"GL_NV_conditional_render",
|
||||
"GL_NV_conservative_raster",
|
||||
"GL_NV_conservative_raster_dilate",
|
||||
"GL_NV_conservative_raster_pre_snap",
|
||||
"GL_NV_conservative_raster_pre_snap_triangles",
|
||||
"GL_NV_conservative_raster_underestimation",
|
||||
"GL_NV_copy_buffer",
|
||||
"GL_NV_copy_depth_to_color",
|
||||
"GL_NV_copy_image",
|
||||
"GL_NV_deep_texture3D",
|
||||
"GL_NV_depth_buffer_float",
|
||||
"GL_NV_depth_clamp",
|
||||
"GL_NV_depth_nonlinear",
|
||||
"GL_NV_draw_instanced",
|
||||
"GL_NV_draw_texture",
|
||||
"GL_NV_explicit_attrib_location",
|
||||
"GL_NV_explicit_multisample",
|
||||
"GL_NV_fbo_color_attachments",
|
||||
"GL_NV_fill_rectangle",
|
||||
"GL_NV_float_buffer",
|
||||
"GL_NV_fog_distance",
|
||||
"GL_NV_fragment_coverage_to_color",
|
||||
"GL_NV_fragment_program",
|
||||
"GL_NV_fragment_program2",
|
||||
"GL_NV_fragment_program4",
|
||||
"GL_NV_fragment_program_option",
|
||||
@@ -413,28 +503,43 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_NV_fragment_shader_interlock",
|
||||
"GL_NV_framebuffer_blit",
|
||||
"GL_NV_framebuffer_multisample",
|
||||
"GL_NV_framebuffer_multisample_coverage",
|
||||
"GL_NV_generate_mipmap_sRGB",
|
||||
"GL_NV_geometry_program4",
|
||||
"GL_NV_geometry_shader4",
|
||||
"GL_NV_geometry_shader_passthrough",
|
||||
"GL_NV_gpu_program4",
|
||||
"GL_NV_gpu_program5_mem_extended",
|
||||
"GL_NV_gpu_shader5",
|
||||
"GL_NV_half_float",
|
||||
"GL_NV_image_formats",
|
||||
"GL_NV_instanced_arrays",
|
||||
"GL_NV_internalformat_sample_query",
|
||||
"GL_NV_light_max_exponent",
|
||||
"GL_NV_memory_object_sparse",
|
||||
"GL_NV_mesh_shader",
|
||||
"GL_NV_multisample_coverage",
|
||||
"GL_NV_multisample_filter_hint",
|
||||
"GL_NV_non_square_matrices",
|
||||
"GL_NV_pack_subimage",
|
||||
"GL_NV_packed_depth_stencil",
|
||||
"GL_NV_parameter_buffer_object",
|
||||
"GL_NV_parameter_buffer_object2",
|
||||
"GL_NV_path_rendering_shared_edge",
|
||||
"GL_NV_pixel_buffer_object",
|
||||
"GL_NV_pixel_data_range",
|
||||
"GL_NV_point_sprite",
|
||||
"GL_NV_polygon_mode",
|
||||
"GL_NV_present_video",
|
||||
"GL_NV_primitive_restart",
|
||||
"GL_NV_primitive_shading_rate",
|
||||
"GL_NV_query_resource",
|
||||
"GL_NV_read_buffer_front",
|
||||
"GL_NV_read_depth",
|
||||
"GL_NV_read_depth_stencil",
|
||||
"GL_NV_read_stencil",
|
||||
"GL_NV_register_combiners",
|
||||
"GL_NV_register_combiners2",
|
||||
"GL_NV_representative_fragment_test",
|
||||
"GL_NV_robustness_video_memory_purge",
|
||||
"GL_NV_sRGB_formats",
|
||||
@@ -457,27 +562,33 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_NV_tessellation_program5",
|
||||
"GL_NV_texgen_emboss",
|
||||
"GL_NV_texgen_reflection",
|
||||
"GL_NV_texture_barrier",
|
||||
"GL_NV_texture_border_clamp",
|
||||
"GL_NV_texture_compression_s3tc_update",
|
||||
"GL_NV_texture_compression_vtc",
|
||||
"GL_NV_texture_env_combine4",
|
||||
"GL_NV_texture_expand_normal",
|
||||
"GL_NV_texture_multisample",
|
||||
"GL_NV_texture_npot_2D_mipmap",
|
||||
"GL_NV_texture_rectangle",
|
||||
"GL_NV_texture_rectangle_compressed",
|
||||
"GL_NV_texture_shader",
|
||||
"GL_NV_texture_shader2",
|
||||
"GL_NV_texture_shader3",
|
||||
"GL_NV_transform_feedback2",
|
||||
"GL_NV_uniform_buffer_std430_layout",
|
||||
"GL_NV_uniform_buffer_unified_memory",
|
||||
"GL_NV_vertex_array_range2",
|
||||
"GL_NV_vertex_attrib_integer_64bit",
|
||||
"GL_NV_vertex_program1_1",
|
||||
"GL_NV_vertex_program2",
|
||||
"GL_NV_vertex_program2_option",
|
||||
"GL_NV_vertex_program3",
|
||||
"GL_NV_vertex_program4",
|
||||
"GL_NV_viewport_array2",
|
||||
"GL_NV_viewport_swizzle",
|
||||
"GL_OES_EGL_image_external_essl3",
|
||||
"GL_OES_byte_coordinates",
|
||||
"GL_OES_compressed_ETC1_RGB8_sub_texture",
|
||||
"GL_OES_compressed_ETC1_RGB8_texture",
|
||||
"GL_OES_compressed_paletted_texture",
|
||||
@@ -493,11 +604,13 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_OES_fragment_precision_high",
|
||||
"GL_OES_geometry_point_size",
|
||||
"GL_OES_geometry_shader",
|
||||
"GL_OES_get_program_binary",
|
||||
"GL_OES_gpu_shader5",
|
||||
"GL_OES_mapbuffer",
|
||||
"GL_OES_matrix_get",
|
||||
"GL_OES_packed_depth_stencil",
|
||||
"GL_OES_point_sprite",
|
||||
"GL_OES_query_matrix",
|
||||
"GL_OES_read_format",
|
||||
"GL_OES_required_internalformat",
|
||||
"GL_OES_rgb8_rgba8",
|
||||
@@ -506,6 +619,7 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_OES_shader_image_atomic",
|
||||
"GL_OES_shader_io_blocks",
|
||||
"GL_OES_shader_multisample_interpolation",
|
||||
"GL_OES_single_precision",
|
||||
"GL_OES_standard_derivatives",
|
||||
"GL_OES_stencil1",
|
||||
"GL_OES_stencil4",
|
||||
@@ -534,7 +648,9 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_OML_interlace",
|
||||
"GL_OML_resample",
|
||||
"GL_OML_subsample",
|
||||
"GL_OVR_multiview",
|
||||
"GL_OVR_multiview2",
|
||||
"GL_PGI_misc_hints",
|
||||
"GL_PGI_vertex_hints",
|
||||
"GL_QCOM_YUV_texture_gather",
|
||||
"GL_QCOM_binning_control",
|
||||
@@ -550,9 +666,12 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_REND_screen_coordinates",
|
||||
"GL_S3_s3tc",
|
||||
"GL_SGIS_generate_mipmap",
|
||||
"GL_SGIS_multisample",
|
||||
"GL_SGIS_pixel_texture",
|
||||
"GL_SGIS_point_line_texgen",
|
||||
"GL_SGIS_point_parameters",
|
||||
"GL_SGIS_texture_border_clamp",
|
||||
"GL_SGIS_texture_color_mask",
|
||||
"GL_SGIS_texture_edge_clamp",
|
||||
"GL_SGIS_texture_lod",
|
||||
"GL_SGIS_texture_select",
|
||||
@@ -564,15 +683,25 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_SGIX_convolution_accuracy",
|
||||
"GL_SGIX_depth_pass_instrument",
|
||||
"GL_SGIX_depth_texture",
|
||||
"GL_SGIX_flush_raster",
|
||||
"GL_SGIX_fog_offset",
|
||||
"GL_SGIX_fragment_lighting",
|
||||
"GL_SGIX_framezoom",
|
||||
"GL_SGIX_igloo_interface",
|
||||
"GL_SGIX_instruments",
|
||||
"GL_SGIX_interlace",
|
||||
"GL_SGIX_ir_instrument1",
|
||||
"GL_SGIX_list_priority",
|
||||
"GL_SGIX_pixel_texture",
|
||||
"GL_SGIX_pixel_tiles",
|
||||
"GL_SGIX_reference_plane",
|
||||
"GL_SGIX_resample",
|
||||
"GL_SGIX_scalebias_hint",
|
||||
"GL_SGIX_shadow",
|
||||
"GL_SGIX_shadow_ambient",
|
||||
"GL_SGIX_sprite",
|
||||
"GL_SGIX_subsample",
|
||||
"GL_SGIX_tag_sample_buffer",
|
||||
"GL_SGIX_texture_add_env",
|
||||
"GL_SGIX_texture_coordinate_clamp",
|
||||
"GL_SGIX_texture_lod_bias",
|
||||
@@ -584,8 +713,12 @@ static const char *const gexgl_claimable_extensions[] = {
|
||||
"GL_SGIX_ycrcba",
|
||||
"GL_SGI_color_matrix",
|
||||
"GL_SGI_texture_color_table",
|
||||
"GL_SUNX_constant_data",
|
||||
"GL_SUN_convolution_border_modes",
|
||||
"GL_SUN_global_alpha",
|
||||
"GL_SUN_mesh_array",
|
||||
"GL_SUN_slice_accum",
|
||||
"GL_SUN_vertex",
|
||||
"GL_VIV_shader_binary",
|
||||
"GL_WIN_phong_shading",
|
||||
"GL_WIN_specular_fog",
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Generated by tools/gen_gl_compat.py; do not edit.
|
||||
*
|
||||
* How many values a pname-sized parameter vector holds (COMPSIZE(pname)
|
||||
* in the registry): the guest encoders, opengl32's and every host
|
||||
* decoder size those vectors with this one table. */
|
||||
#ifndef GEXGL_PNAME_COUNTS_H
|
||||
#define GEXGL_PNAME_COUNTS_H
|
||||
|
||||
static inline unsigned gexgl_pname_count(unsigned pname) {
|
||||
switch (pname) {
|
||||
case 0x0B00u: return 4u;
|
||||
case 0x0B02u: return 3u;
|
||||
case 0x0B03u: return 4u;
|
||||
case 0x0B04u: return 4u;
|
||||
case 0x0B06u: return 4u;
|
||||
case 0x0B07u: return 4u;
|
||||
case 0x0B12u: return 2u;
|
||||
case 0x0B22u: return 2u;
|
||||
case 0x0B40u: return 2u;
|
||||
case 0x0B53u: return 4u;
|
||||
case 0x0B66u: return 4u;
|
||||
case 0x0B70u: return 2u;
|
||||
case 0x0B80u: return 4u;
|
||||
case 0x0BA2u: return 4u;
|
||||
case 0x0BA6u: return 16u;
|
||||
case 0x0BA7u: return 16u;
|
||||
case 0x0BA8u: return 16u;
|
||||
case 0x0C10u: return 4u;
|
||||
case 0x0C22u: return 4u;
|
||||
case 0x0C23u: return 4u;
|
||||
case 0x0D3Au: return 2u;
|
||||
case 0x0DD0u: return 2u;
|
||||
case 0x0DD2u: return 4u;
|
||||
case 0x0DD3u: return 2u;
|
||||
case 0x1004u: return 4u;
|
||||
case 0x1200u: return 4u;
|
||||
case 0x1201u: return 4u;
|
||||
case 0x1202u: return 4u;
|
||||
case 0x1203u: return 4u;
|
||||
case 0x1204u: return 3u;
|
||||
case 0x1600u: return 4u;
|
||||
case 0x1602u: return 4u;
|
||||
case 0x1603u: return 3u;
|
||||
case 0x1800u: return 4u;
|
||||
case 0x2201u: return 4u;
|
||||
case 0x2501u: return 4u;
|
||||
case 0x2502u: return 4u;
|
||||
case 0x8005u: return 4u;
|
||||
case 0x8014u: return 4u;
|
||||
case 0x8015u: return 4u;
|
||||
case 0x80B1u: return 16u;
|
||||
case 0x80D1u: return 4u;
|
||||
case 0x80D6u: return 4u;
|
||||
case 0x80D7u: return 4u;
|
||||
case 0x8129u: return 3u;
|
||||
case 0x8154u: return 4u;
|
||||
case 0x8171u: return 4u;
|
||||
case 0x825Du: return 2u;
|
||||
case 0x8459u: return 4u;
|
||||
case 0x846Du: return 2u;
|
||||
case 0x846Eu: return 2u;
|
||||
case 0x84E3u: return 16u;
|
||||
case 0x84E4u: return 16u;
|
||||
case 0x84E5u: return 16u;
|
||||
case 0x84E6u: return 16u;
|
||||
case 0x852Au: return 4u;
|
||||
case 0x852Bu: return 4u;
|
||||
case 0x8626u: return 4u;
|
||||
case 0x8891u: return 4u;
|
||||
case 0x8E46u: return 4u;
|
||||
case 0x91BEu: return 3u;
|
||||
case 0x91BFu: return 3u;
|
||||
default: return 1u;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -156,7 +156,9 @@ impl GlDevice {
|
||||
}
|
||||
// No GL is reported in the header, not as a failed ioctl, so the
|
||||
// guest falls back as it would for a driver that refused to load.
|
||||
Err(_) => {
|
||||
Err(e) => {
|
||||
static SAID: std::sync::Once = std::sync::Once::new();
|
||||
SAID.call_once(|| eprintln!("gex-gl: no host GL context: {e}"));
|
||||
write_status(m, ring, error::NO_CONTEXT, 0, 0)?;
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,762 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate gex-gl's compatibility-profile transport from the Khronos registry.
|
||||
|
||||
tools/gen_gl_compat.py [--check]
|
||||
|
||||
Every OpenGL command in third_party/opengl-registry/xml/gl.xml -- GL 1.0
|
||||
through 4.6 including what the core profile removed, and every extension
|
||||
command -- gets a wire *plan* derived from the registry's own parameter
|
||||
metadata (types, `len`, `class`), unless something about it cannot be
|
||||
carried safely (a callback, a pointer to pointers, a length the registry
|
||||
leaves to prose); those are listed in the generated files with the reason.
|
||||
|
||||
The plan is a short string, one token per parameter, that both encoders
|
||||
interpret and the host decoders are generated from:
|
||||
|
||||
v | w | f | q the return: none, a 32-bit word, a float, 64 bits
|
||||
w a 32-bit scalar parameter: one word
|
||||
q a 64-bit scalar (doubles, 64-bit integers, and
|
||||
GLintptr/GLsizeiptr, sign-extended): two words
|
||||
i<size>:<count> an input array of <size>-byte elements
|
||||
j<size>:<count> the same, pixel data: an offset into the bound
|
||||
unpack buffer when there is one
|
||||
o<size>:<count> an output array (comes back in the reply)
|
||||
|
||||
and a count is
|
||||
|
||||
n<N> N elements p<i>[*<M>] parameter i, times M
|
||||
e<i> pname-sized (gl-pname-counts.h) on parameter i
|
||||
s a NUL-terminated string S<i> a string of length
|
||||
parameter i (<0: NUL)
|
||||
z<i> parameter i bytes L<i>,<j> parameter i elements
|
||||
of GL type parameter j
|
||||
X<f>,<t>,<w>,<h>,<d> an unpack pixel transfer (format, type, width,
|
||||
height, depth; `_` for absent): from the unpack buffer when
|
||||
one is bound
|
||||
B<w>,<h> a glBitmap bitmap T glPolygonStipple's
|
||||
32x32 bits
|
||||
|
||||
On the wire a command is its scalars in order, each input array as a tag
|
||||
word (0 null, 1 a blob follows: length then bytes padded to four, 2 an
|
||||
offset into the bound unpack buffer: two words) and nothing for outputs;
|
||||
the reply is the return value then each output as a blob. Opcodes are
|
||||
COMPAT_BASE plus the command's index in the registry's sorted command list,
|
||||
so a policy change never renumbers one.
|
||||
|
||||
Outputs:
|
||||
guest/gl/gl-compat-generated.inc the Linux guest's entry points
|
||||
guest/gl/gl-pname-counts.h the pname-sized counts (C, both ends)
|
||||
crates/gex-kernel/src/nt/opengl/generated.rs opengl32's plans (NT)
|
||||
crates/gex-gl/src/compat_plans.rs the opcode table, for the hosts' tests
|
||||
web/mesa/gl-compat-generated-cases.inc the host decoder (C++; the
|
||||
browser's Mesa and the native host)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
REGISTRY = ROOT / "third_party/opengl-registry/xml/gl.xml"
|
||||
COMPAT_BASE = 8192
|
||||
|
||||
# Scalar types: (wire token, guest C type, host C type, element bytes).
|
||||
SCALARS = {
|
||||
"GLenum": ("w", "unsigned", "GLenum", 4),
|
||||
"GLuint": ("w", "unsigned", "GLuint", 4),
|
||||
"GLbitfield": ("w", "unsigned", "GLbitfield", 4),
|
||||
"GLint": ("w", "int", "GLint", 4),
|
||||
"GLsizei": ("w", "int", "GLsizei", 4),
|
||||
"GLfixed": ("w", "int", "GLint", 4),
|
||||
"GLclampx": ("w", "int", "GLint", 4),
|
||||
"GLhandleARB": ("w", "unsigned", "GLuint", 4),
|
||||
"GLshort": ("w", "short", "GLshort", 2),
|
||||
"GLushort": ("w", "unsigned short", "GLushort", 2),
|
||||
"GLhalfNV": ("w", "unsigned short", "GLushort", 2),
|
||||
"GLbyte": ("w", "signed char", "GLbyte", 1),
|
||||
"GLubyte": ("w", "unsigned char", "GLubyte", 1),
|
||||
"GLboolean": ("w", "unsigned char", "GLboolean", 1),
|
||||
"GLchar": ("w", "char", "GLchar", 1),
|
||||
"GLcharARB": ("w", "char", "GLchar", 1),
|
||||
"GLfloat": ("f", "float", "GLfloat", 4),
|
||||
"GLclampf": ("f", "float", "GLfloat", 4),
|
||||
"GLdouble": ("q", "double", "GLdouble", 8),
|
||||
"GLclampd": ("q", "double", "GLdouble", 8),
|
||||
"GLint64": ("q", "long long", "GLint64", 8),
|
||||
"GLint64EXT": ("q", "long long", "GLint64", 8),
|
||||
"GLuint64": ("q", "unsigned long long", "GLuint64", 8),
|
||||
"GLuint64EXT": ("q", "unsigned long long", "GLuint64", 8),
|
||||
"GLintptr": ("q", "long", "ptrdiff_t", None),
|
||||
"GLsizeiptr": ("q", "long", "ptrdiff_t", None),
|
||||
"GLintptrARB": ("q", "long", "ptrdiff_t", None),
|
||||
"GLsizeiptrARB": ("q", "long", "ptrdiff_t", None),
|
||||
}
|
||||
# Array element types (pointer-sized integers are not carried in arrays).
|
||||
ELEMENTS = {k: v for k, v in SCALARS.items() if v[3]}
|
||||
ELEMENTS["void"] = ("w", "void", "void", 1)
|
||||
|
||||
# The object kinds a host maps from the guest's names (`class` in gl.xml).
|
||||
CLASSES = {
|
||||
"buffer": "buffers", "texture": "textures", "framebuffer": "framebuffers",
|
||||
"renderbuffer": "renderbuffers", "query": "queries", "sampler": "samplers",
|
||||
"vertex array": "vertex_arrays", "transform feedback": "transform_feedbacks",
|
||||
"program pipeline": "program_pipelines", "program": "programs", "shader": "shaders",
|
||||
"display list": None,
|
||||
}
|
||||
|
||||
# Parameter vectors whose length a pname decides (`COMPSIZE(pname)`): the
|
||||
# multi-valued ones; everything else is one value. Shared by every end, so
|
||||
# what an encoder sends is what a decoder expects.
|
||||
PNAME_COUNTS = {
|
||||
16: ["GL_MODELVIEW_MATRIX", "GL_PROJECTION_MATRIX", "GL_TEXTURE_MATRIX", "GL_COLOR_MATRIX",
|
||||
"GL_TRANSPOSE_MODELVIEW_MATRIX", "GL_TRANSPOSE_PROJECTION_MATRIX",
|
||||
"GL_TRANSPOSE_TEXTURE_MATRIX", "GL_TRANSPOSE_COLOR_MATRIX"],
|
||||
4: ["GL_CURRENT_COLOR", "GL_CURRENT_TEXTURE_COORDS", "GL_CURRENT_RASTER_POSITION",
|
||||
"GL_CURRENT_RASTER_COLOR", "GL_CURRENT_RASTER_TEXTURE_COORDS", "GL_CURRENT_SECONDARY_COLOR",
|
||||
"GL_FOG_COLOR", "GL_LIGHT_MODEL_AMBIENT", "GL_ACCUM_CLEAR_VALUE", "GL_COLOR_CLEAR_VALUE",
|
||||
"GL_COLOR_WRITEMASK", "GL_BLEND_COLOR", "GL_VIEWPORT", "GL_SCISSOR_BOX",
|
||||
"GL_MAP2_GRID_DOMAIN", "GL_TEXTURE_ENV_COLOR", "GL_TEXTURE_BORDER_COLOR",
|
||||
"GL_TEXTURE_SWIZZLE_RGBA", "GL_AMBIENT", "GL_DIFFUSE", "GL_SPECULAR", "GL_EMISSION",
|
||||
"GL_POSITION", "GL_AMBIENT_AND_DIFFUSE", "GL_OBJECT_PLANE", "GL_EYE_PLANE",
|
||||
"GL_CONVOLUTION_BORDER_COLOR", "GL_CONVOLUTION_FILTER_SCALE", "GL_CONVOLUTION_FILTER_BIAS",
|
||||
"GL_COLOR_TABLE_SCALE", "GL_COLOR_TABLE_BIAS", "GL_CURRENT_VERTEX_ATTRIB",
|
||||
"GL_CONSTANT_COLOR0_NV", "GL_CONSTANT_COLOR1_NV", "GL_TEXTURE_CLIPMAP_CENTER_SGIX",
|
||||
"GL_POST_CONVOLUTION_COLOR_TABLE", "GL_DEPTH_BOUNDS_EXT", "GL_COLOR"],
|
||||
3: ["GL_CURRENT_NORMAL", "GL_SPOT_DIRECTION", "GL_COLOR_INDEXES", "GL_POINT_DISTANCE_ATTENUATION",
|
||||
"GL_MAX_COMPUTE_WORK_GROUP_COUNT", "GL_MAX_COMPUTE_WORK_GROUP_SIZE"],
|
||||
2: ["GL_DEPTH_RANGE", "GL_MAX_VIEWPORT_DIMS", "GL_POINT_SIZE_RANGE", "GL_LINE_WIDTH_RANGE",
|
||||
"GL_ALIASED_POINT_SIZE_RANGE", "GL_ALIASED_LINE_WIDTH_RANGE", "GL_POLYGON_MODE",
|
||||
"GL_MAP1_GRID_DOMAIN", "GL_MAP2_GRID_SEGMENTS", "GL_VIEWPORT_BOUNDS_RANGE",
|
||||
"GL_DEPTH_BOUNDS_EXT"],
|
||||
}
|
||||
|
||||
# Commands left to the hand-written halves on every end even where a plan
|
||||
# would fit, because the encoder keeps state about them or a host must
|
||||
# allocate on their behalf: names a host maps, client arrays and their
|
||||
# pointers, mapping a buffer, the pixel store, strings handed back.
|
||||
HAND = {
|
||||
"glBindBuffer", "glPixelStorei", "glPixelStoref", "glGetError", "glGetString", "glGetStringi",
|
||||
"glFinish", "glFlush", "glGetIntegerv", "glGetPointerv", "glGenLists", "glNewList", "glEndList",
|
||||
"glFenceSync", "glDeleteSync", "glClientWaitSync", "glWaitSync", "glIsSync", "glGetSynciv",
|
||||
"glDebugMessageCallback", "glDebugMessageCallbackARB", "glDebugMessageCallbackAMD",
|
||||
"glReadPixels", "glGetTexImage", "glArrayElement", "glInterleavedArrays",
|
||||
"glEnableClientState", "glDisableClientState", "glClientActiveTexture",
|
||||
"glEnableVertexAttribArray", "glDisableVertexAttribArray",
|
||||
"glEnableClientStateiEXT", "glDisableClientStateiEXT", "glEnableClientStateIndexedEXT",
|
||||
"glDisableClientStateIndexedEXT", "glBindVertexArray", "glLockArraysEXT", "glUnlockArraysEXT",
|
||||
"glCreateShader", "glCreateProgram", "glCreateShaderProgramv", "glCreateShaderProgramEXT",
|
||||
"glCreateShaderObjectARB", "glCreateProgramObjectARB", "glDeleteObjectARB",
|
||||
"glShaderSource", "glShaderSourceARB", "glGetShaderSource", "glGetShaderSourceARB",
|
||||
}
|
||||
# Commands whose untyped input is pixel data: an unpack buffer offset when
|
||||
# one is bound.
|
||||
PIXEL_COMMAND = re.compile(r"(Tex|Texture|MultiTex)(Sub)?Image|CompressedTex|CompressedMultiTex|"
|
||||
r"DrawPixels|ColorTable|ColorSubTable|ConvolutionFilter|SeparableFilter")
|
||||
HAND_PREFIXES = ("glDelete", "glCreate", "glMapBuffer", "glMapNamedBuffer", "glUnmap", "glFlushMapped",
|
||||
"glGetBufferPointer", "glGetNamedBufferPointer")
|
||||
# glGen<objects>: the encoders choose the names.
|
||||
GEN_OBJECTS = re.compile(r"^glGen(?!erate)[A-Z]\w*")
|
||||
|
||||
|
||||
def text(e):
|
||||
return "".join(e.itertext())
|
||||
|
||||
|
||||
class Param:
|
||||
def __init__(self, e):
|
||||
self.name = e.find("name").text
|
||||
decl = re.sub(r"\s+", " ", text(e)).strip()
|
||||
self.decl = decl
|
||||
pt = e.find("ptype")
|
||||
self.base = pt.text if pt is not None else ("void" if "void" in decl else decl.rsplit(" ", 1)[0])
|
||||
before = decl[: decl.rfind(self.name)]
|
||||
self.ptr = before.count("*")
|
||||
self.const = bool(re.search(r"\bconst\b", before))
|
||||
self.len = e.get("len")
|
||||
self.cls = e.get("class")
|
||||
|
||||
|
||||
class Command:
|
||||
def __init__(self, e):
|
||||
proto = e.find("proto")
|
||||
self.name = proto.find("name").text
|
||||
ret = re.sub(r"\s+", " ", text(proto)).strip()
|
||||
self.ret = ret[: ret.rfind(self.name)].strip()
|
||||
self.params = [Param(p) for p in e.findall("param")]
|
||||
a = e.find("alias")
|
||||
self.alias = a.get("name") if a is not None else None
|
||||
|
||||
|
||||
def load():
|
||||
root = ET.parse(REGISTRY).getroot()
|
||||
commands = {}
|
||||
for e in root.find("commands"):
|
||||
c = Command(e)
|
||||
commands[c.name] = c
|
||||
# The suffixed spellings guest/gl serves as the core command although the
|
||||
# registry does not mark them aliases (tools/gen_gl_extensions.py).
|
||||
sys.path.insert(0, str(ROOT / "tools"))
|
||||
from gen_gl_extensions import CURATED_ALIASES
|
||||
for name, target in CURATED_ALIASES.items():
|
||||
commands[name].alias = target
|
||||
enums = {}
|
||||
for group in root.findall("enums"):
|
||||
for e in group.findall("enum"):
|
||||
if e.get("api") in (None, "gl"):
|
||||
enums.setdefault(e.get("name"), int(e.get("value"), 0))
|
||||
wanted = set()
|
||||
for f in root.findall("feature"):
|
||||
if f.get("api") == "gl":
|
||||
for req in f.findall("require"):
|
||||
wanted |= {c.get("name") for c in req.findall("command")}
|
||||
for ext in root.find("extensions"):
|
||||
sup = (ext.get("supported") or "").split("|")
|
||||
if not {"gl", "glcore"} & set(sup):
|
||||
continue
|
||||
for req in ext.findall("require"):
|
||||
if req.get("api") in (None, "gl"):
|
||||
wanted |= {c.get("name") for c in req.findall("command")}
|
||||
return commands, enums, wanted
|
||||
|
||||
|
||||
class Skip(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def count_spec(cmd, p, index_of):
|
||||
"""The count token for pointer parameter p, or Skip."""
|
||||
L = p.len
|
||||
names = [q.name for q in cmd.params]
|
||||
scalars = {q.name for q in cmd.params if q.ptr == 0}
|
||||
if p.base in ("GLchar", "GLcharARB") and p.const:
|
||||
if L is None or L in ("COMPSIZE(name)", "COMPSIZE()"):
|
||||
return "s"
|
||||
m = re.fullmatch(r"COMPSIZE\((\w+),(\w+)\)", L)
|
||||
if m and m.group(2) in scalars and m.group(1) == p.name:
|
||||
return f"S{index_of[m.group(2)]}"
|
||||
if L in scalars:
|
||||
return f"S{index_of[L]}"
|
||||
raise Skip(f"string length {L}")
|
||||
if L is None:
|
||||
raise Skip(f"{p.name} has no length")
|
||||
if L.isdigit():
|
||||
if int(L) == 0:
|
||||
raise Skip("zero-length array")
|
||||
return f"n{L}"
|
||||
m = re.fullmatch(r"(\w+)\s*\*\s*(\d+)", L)
|
||||
if m and m.group(1) in scalars:
|
||||
return f"p{index_of[m.group(1)]}*{m.group(2)}"
|
||||
if L in scalars:
|
||||
if p.base == "void":
|
||||
return f"z{index_of[L]}"
|
||||
return f"p{index_of[L]}"
|
||||
m = re.fullmatch(r"COMPSIZE\(([\w,]*)\)", L)
|
||||
if not m:
|
||||
raise Skip(f"length {L}")
|
||||
args = [a for a in m.group(1).split(",") if a]
|
||||
if args and args[-1] in ("pname",) and args[-1] in scalars and (len(args) == 1 or cmd.name.startswith(("glGetTexLevelParameter",))):
|
||||
return f"e{index_of[args[-1]]}"
|
||||
if len(args) == 1 and args[0] == "pname" and "pname" in scalars:
|
||||
return f"e{index_of['pname']}"
|
||||
if p.const and p.base == "void" and args and args[0] == "format" and args[1:2] == ["type"] and 3 <= len(args) <= 5:
|
||||
idx = [index_of[a] if a in index_of else "_" for a in args[2:]]
|
||||
while len(idx) < 3:
|
||||
idx.append("_")
|
||||
return "X%d,%d,%s" % (index_of["format"], index_of["type"], ",".join(str(i) for i in idx))
|
||||
if args == ["width", "height"] and p.base == "GLubyte" and cmd.name == "glBitmap":
|
||||
return f"B{index_of['width']},{index_of['height']}"
|
||||
if args == [] and cmd.name == "glPolygonStipple":
|
||||
return "T"
|
||||
if len(args) == 2 and p.const and args[1] == "type" and args[0] in scalars and p.name == "lists":
|
||||
return f"L{index_of[args[0]]},{index_of['type']}"
|
||||
if len(args) == 1 and args[0] in scalars and p.base == "void" and args[0] == "size":
|
||||
return f"z{index_of['size']}"
|
||||
# Indexed state (glGetIntegeri_v): sized as that state is.
|
||||
if args == ["target"] and not p.const and re.search(r"i_v|Indexedv", cmd.name):
|
||||
return f"e{index_of['target']}"
|
||||
# glClearBuffer*v: four for GL_COLOR, one for depth or stencil.
|
||||
if args == ["buffer"] and "buffer" in scalars:
|
||||
return f"e{index_of['buffer']}"
|
||||
# One value per uniform.
|
||||
if args == ["uniformCount", "pname"] and "uniformCount" in scalars:
|
||||
return f"p{index_of['uniformCount']}"
|
||||
# A uniform's value: as many as its type holds, which the host knows.
|
||||
if len(args) == 2 and args[1] == "location" and not p.const and args[0] in scalars:
|
||||
return f"U{index_of[args[0]]},{index_of['location']}"
|
||||
raise Skip(f"length {L}")
|
||||
|
||||
|
||||
def offset_pointer(cmd, p):
|
||||
"""A vertex, index or indirect pointer: an offset into a bound buffer, or
|
||||
client memory the encoder uploads to one first. Never carried as data."""
|
||||
if p.base != "void" or not p.const or p.ptr != 1:
|
||||
return False
|
||||
if p.name == "indirect":
|
||||
return True
|
||||
if p.name == "pointer" and re.search(r"Pointer", cmd.name):
|
||||
return p.len is None or p.len.startswith("COMPSIZE(")
|
||||
if p.name == "indices" and re.match(r"glDraw(Range)?Elements", cmd.name):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Commands whose pointers are buffer offsets (offset_pointer): planned for
|
||||
# the hosts, which take the offset; the encoders keep the client-memory case
|
||||
# by hand and call these by opcode.
|
||||
POINTER_COMMANDS = re.compile(r"^gl((Vertex|Color|TexCoord|Normal|SecondaryColor|FogCoord|EdgeFlag|Index)Pointer"
|
||||
r"|VertexAttrib[IL]?Pointer|Draw(Range)?Elements\w*|Draw(Arrays|Elements)Indirect"
|
||||
r"|MultiDraw(Arrays|Elements)Indirect)(ARB|EXT)?$")
|
||||
|
||||
|
||||
def plan_of(cmd):
|
||||
"""(plan, reason): the wire plan, or None and why not."""
|
||||
try:
|
||||
pointer_command = bool(POINTER_COMMANDS.match(cmd.name))
|
||||
if not pointer_command and (cmd.name in HAND or cmd.name.startswith(HAND_PREFIXES) or GEN_OBJECTS.match(cmd.name)):
|
||||
raise Skip("hand-written")
|
||||
ret = cmd.ret.replace("const", "").strip()
|
||||
if ret == "void":
|
||||
r = "v"
|
||||
elif ret in SCALARS and "*" not in ret:
|
||||
r = SCALARS[ret][0]
|
||||
if r == "q" and SCALARS[ret][3] is None:
|
||||
raise Skip("pointer-sized return")
|
||||
else:
|
||||
raise Skip(f"returns {cmd.ret}")
|
||||
index_of = {q.name: i for i, q in enumerate(cmd.params)}
|
||||
toks = []
|
||||
for p in cmd.params:
|
||||
if p.ptr == 0:
|
||||
if p.base not in SCALARS:
|
||||
raise Skip(f"{p.name} is a {p.base}")
|
||||
if p.cls and p.cls not in CLASSES:
|
||||
raise Skip(f"{p.name} is a {p.cls}")
|
||||
toks.append(SCALARS[p.base][0])
|
||||
continue
|
||||
if p.ptr != 1:
|
||||
raise Skip(f"{p.name} is a pointer to pointers")
|
||||
if p.base not in ELEMENTS:
|
||||
raise Skip(f"{p.name} points to {p.base}")
|
||||
if p.cls:
|
||||
raise Skip(f"{p.name} is an array of {p.cls} names")
|
||||
if offset_pointer(cmd, p):
|
||||
toks.append("P")
|
||||
continue
|
||||
spec = count_spec(cmd, p, index_of)
|
||||
size = ELEMENTS[p.base][3]
|
||||
if not p.const:
|
||||
if spec[0] in "XBTLsSz" and not (spec[0] == "z"):
|
||||
raise Skip(f"output {p.name} sized {spec}")
|
||||
if p.base == "void" and spec[0] != "z":
|
||||
raise Skip(f"untyped output {p.name}")
|
||||
toks.append(f"o{size}:{spec}")
|
||||
else:
|
||||
if spec[0] in "XBTLsSz":
|
||||
size = 1
|
||||
# Pixel data may be an offset into the bound unpack buffer.
|
||||
pbo = spec[0] in "XBT" or (p.base == "void" and PIXEL_COMMAND.search(cmd.name))
|
||||
toks.append(f"{'j' if pbo else 'i'}{size}:{spec}")
|
||||
if "P" in toks and not pointer_command:
|
||||
raise Skip("an offset pointer in a command the encoders do not track")
|
||||
return r + " " + " ".join(toks) if toks else r, None
|
||||
except Skip as e:
|
||||
return None, str(e)
|
||||
|
||||
|
||||
def guest_type(p):
|
||||
if p.ptr:
|
||||
base = ELEMENTS.get(p.base, ("", "void"))[1] if p.base in ELEMENTS else "void"
|
||||
return ("const " if p.const else "") + base + " *"
|
||||
return SCALARS[p.base][1]
|
||||
|
||||
|
||||
def host_type(p):
|
||||
if p.ptr:
|
||||
base = ELEMENTS[p.base][2]
|
||||
return ("const " if p.const else "") + base + "*"
|
||||
return SCALARS[p.base][2]
|
||||
|
||||
|
||||
def guest_ret(cmd):
|
||||
r = cmd.ret.replace("const", "").strip()
|
||||
return "void" if r == "void" else SCALARS[r][1]
|
||||
|
||||
|
||||
def host_ret(cmd):
|
||||
r = cmd.ret.replace("const", "").strip()
|
||||
return "void" if r == "void" else SCALARS[r][2]
|
||||
|
||||
|
||||
def guest_value(p):
|
||||
"""The parameter as the uint64 the guest interpreter takes."""
|
||||
n = p.name + "_"
|
||||
if p.ptr:
|
||||
return f"(uint64_t)(uintptr_t){n}"
|
||||
t = SCALARS[p.base]
|
||||
if t[0] == "f":
|
||||
return f"(uint64_t)as_bits({n})"
|
||||
if p.base in ("GLdouble", "GLclampd"):
|
||||
return f"gexgen_dbits({n})"
|
||||
if t[0] == "q":
|
||||
return f"(uint64_t)(int64_t){n}" if t[1] in ("long", "long long") else f"(uint64_t){n}"
|
||||
if t[1] in ("int", "short", "signed char", "char"):
|
||||
return f"(uint64_t)(uint32_t)(int32_t){n}"
|
||||
return f"(uint64_t)(uint32_t){n}"
|
||||
|
||||
|
||||
def defined_in(path):
|
||||
"""C function definitions in a source file (to leave hand-written ones be)."""
|
||||
src = path.read_text() if path.exists() else ""
|
||||
names = set(re.findall(r"^[A-Za-z_][\w \*]*?\b(gl[A-Z]\w*)\s*\([^;{]*\)\s*\{", src, re.M))
|
||||
names |= set(re.findall(r"__typeof\(\w+\)\s+(gl[A-Z]\w*)", src))
|
||||
return names
|
||||
|
||||
|
||||
def emit_guest(cmds, plans, opcodes):
|
||||
hand = set()
|
||||
for f in ("gexgl.c", "gl44-generated.inc", "gexgl-glx.inc"):
|
||||
hand |= defined_in(ROOT / "guest/gl" / f)
|
||||
out = ["/* Generated by tools/gen_gl_compat.py from the Khronos registry; do not edit.",
|
||||
" *",
|
||||
" * The Linux guest's compatibility-profile entry points: every registry",
|
||||
" * command with a wire plan that gexgl.c and gl44-generated.inc do not",
|
||||
" * define, each a call to gexgen_call (gexgl.c) with its plan. Aliases",
|
||||
" * of exported commands come from gl-aliases-generated.inc. */", ""]
|
||||
n = 0
|
||||
for name in sorted(plans):
|
||||
c = cmds[name]
|
||||
if name in hand or " P" in plans[name]:
|
||||
continue
|
||||
# An alias of a command that will be exported is left to the alias
|
||||
# file, which spells it as that command.
|
||||
if c.alias and (c.alias in hand or c.alias in plans):
|
||||
continue
|
||||
params = ", ".join(f"{guest_type(p)} {p.name}_" for p in c.params) or "void"
|
||||
vals = ", ".join(guest_value(p) for p in c.params)
|
||||
rt = guest_ret(c)
|
||||
body = f"uint64_t args__[{max(len(c.params), 1)}] = {{{vals or '0'}}};\n "
|
||||
call = f"gexgen_call({opcodes[name]}u, \"{plans[name]}\", args__)"
|
||||
r = plans[name].split(" ")[0]
|
||||
if rt == "void":
|
||||
body += call + ";"
|
||||
elif r == "f":
|
||||
body += f"uint32_t ret__ = (uint32_t){call}; float f__; memcpy(&f__, &ret__, 4); return f__;"
|
||||
else:
|
||||
body += f"return ({rt}){call};"
|
||||
out.append(f"{rt} {name}({params}) {{\n {body}\n}}")
|
||||
n += 1
|
||||
out.insert(6, f"/* {n} entry points. */")
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
def emit_pname_counts(enums):
|
||||
lines = ["/* Generated by tools/gen_gl_compat.py; do not edit.",
|
||||
" *",
|
||||
" * How many values a pname-sized parameter vector holds (COMPSIZE(pname)",
|
||||
" * in the registry): the guest encoders, opengl32's and every host",
|
||||
" * decoder size those vectors with this one table. */",
|
||||
"#ifndef GEXGL_PNAME_COUNTS_H", "#define GEXGL_PNAME_COUNTS_H", "",
|
||||
"static inline unsigned gexgl_pname_count(unsigned pname) {", " switch (pname) {"]
|
||||
seen = {}
|
||||
for count in sorted(PNAME_COUNTS, reverse=True):
|
||||
for e in PNAME_COUNTS[count]:
|
||||
v = enums.get(e)
|
||||
if v is None or v in seen:
|
||||
continue
|
||||
seen[v] = count
|
||||
for v, count in sorted(seen.items()):
|
||||
lines.append(f" case 0x{v:04X}u: return {count}u;")
|
||||
lines += [" default: return 1u;", " }", "}", "", "#endif", ""]
|
||||
rust = ["/// What `gexgl_pname_count` says (guest/gl/gl-pname-counts.h).",
|
||||
"pub fn pname_count(pname: u32) -> u32 {", " match pname {"]
|
||||
for v, count in sorted(seen.items()):
|
||||
rust.append(f" 0x{v:04X} => {count},")
|
||||
rust += [" _ => 1,", " }", "}"]
|
||||
return "\n".join(lines), "\n".join(rust)
|
||||
|
||||
|
||||
def nt_table():
|
||||
"""opengl32's unix calls and their params signatures (table.rs)."""
|
||||
src = (ROOT / "crates/gex-kernel/src/nt/opengl/table.rs").read_text()
|
||||
return dict(re.findall(r'\("(\w+)", "(\w*)"\)', src))
|
||||
|
||||
|
||||
# Commands opengl32 does not serve that do not keep the version it reports
|
||||
# down (a call still fails loudly by name): evaluators, pixel maps, feedback
|
||||
# and selection, which nothing this serves draws with.
|
||||
NT_TOLERATED = {
|
||||
"glMap1d", "glMap1f", "glMap2d", "glMap2f", "glGetMapdv", "glGetMapfv", "glGetMapiv",
|
||||
"glMapGrid1d", "glMapGrid1f", "glMapGrid2d", "glMapGrid2f",
|
||||
"glGetPixelMapfv", "glGetPixelMapuiv", "glGetPixelMapusv", "glGetPolygonStipple",
|
||||
"glFeedbackBuffer", "glSelectBuffer", "glInterleavedArrays", "glArrayElement", "glEdgeFlagPointer",
|
||||
"glIndexPointer", "glGetPointerv", "glAreTexturesResident", "glPrioritizeTextures",
|
||||
"glMultiDrawElements", "glGetVertexAttribPointerv", "glGetShaderSource", "glGetAttachedShaders",
|
||||
"glTransformFeedbackVaryings", "glGetUniformIndices", "glGetActiveUniformBlockiv",
|
||||
"glMultiDrawElementsBaseVertex",
|
||||
}
|
||||
# Extensions opengl32 does not claim even with every command served: what it
|
||||
# serves differs from what they promise (a persistent mapping is a copy here,
|
||||
# not coherent memory).
|
||||
NT_UNCLAIMABLE = {"GL_ARB_buffer_storage", "GL_EXT_buffer_storage"}
|
||||
# The newest version whose promise includes nothing in NT_UNCLAIMABLE.
|
||||
NT_VERSION_LIMIT = (4, 3)
|
||||
|
||||
|
||||
def emit_nt(cmds, plans, opcodes, pname_rust):
|
||||
funcs = nt_table()
|
||||
hand = set(re.findall(r'"(gl\w+)"\s*(?:\||=>)', (ROOT / "crates/gex-kernel/src/nt/opengl/mod.rs").read_text()))
|
||||
rows, aliases, skipped, pointer_rows = [], [], [], []
|
||||
served = set(hand)
|
||||
for name in sorted(funcs):
|
||||
if not name.startswith("gl"):
|
||||
continue
|
||||
c = cmds.get(name)
|
||||
if c is None:
|
||||
continue
|
||||
if name not in plans:
|
||||
if name not in hand and c.alias and (c.alias in plans or c.alias in hand):
|
||||
# Same parameters under another name: served as that command.
|
||||
if [p.base for p in c.params] == [p.base for p in cmds[c.alias].params]:
|
||||
aliases.append((name, c.alias))
|
||||
served.add(name)
|
||||
continue
|
||||
sig = funcs[name]
|
||||
want = 1 + len(c.params) + (0 if plans[name][0] == "v" else 1)
|
||||
if len(sig) != want or (sig and sig[0] != "p"):
|
||||
skipped.append(f"{name} (params struct {sig!r})")
|
||||
continue
|
||||
if " P" in plans[name]:
|
||||
pointer_rows.append((name, opcodes[name], plans[name]))
|
||||
continue
|
||||
rows.append((name, opcodes[name], plans[name]))
|
||||
served.add(name)
|
||||
# What opengl32 can honestly report: the newest version, and the
|
||||
# extensions, whose every command it serves.
|
||||
root = ET.parse(REGISTRY).getroot()
|
||||
required, version = set(), (1, 0)
|
||||
for f in root.findall("feature"):
|
||||
if f.get("api") != "gl":
|
||||
continue
|
||||
for r in f.findall("require"):
|
||||
required |= {x.get("name") for x in r.findall("command")}
|
||||
number = tuple(int(x) for x in f.get("number").split("."))
|
||||
if number > NT_VERSION_LIMIT or required - served - NT_TOLERATED:
|
||||
break
|
||||
version = number
|
||||
claimable = []
|
||||
for e in root.find("extensions"):
|
||||
if not {"gl", "glcore"} & set((e.get("supported") or "").split("|")):
|
||||
continue
|
||||
need = {x.get("name") for r in e.findall("require") if r.get("api") in (None, "gl")
|
||||
for x in r.findall("command")}
|
||||
if e.get("name") not in NT_UNCLAIMABLE and not need - served:
|
||||
claimable.append(e.get("name"))
|
||||
out = ["// Generated by tools/gen_gl_compat.py from the Khronos registry and",
|
||||
"// table.rs; do not edit.", "",
|
||||
"/// opengl32 calls with a wire plan (`tools/gen_gl_compat.py`), by name:",
|
||||
"/// the opcode and the plan, which `super::planned` interprets.",
|
||||
"pub const PLANS: &[(&str, u32, &str)] = &["]
|
||||
out += [f' ("{n}", {o}, "{p}"),' for n, o, p in rows]
|
||||
out += ["];", "",
|
||||
"/// The pointer commands (vertex, index and indirect pointers as buffer",
|
||||
"/// offsets), which `super` sends itself once client memory is uploaded.",
|
||||
"pub const POINTER_PLANS: &[(&str, u32, &str)] = &["]
|
||||
out += [f' ("{n}", {o}, "{p}"),' for n, o, p in pointer_rows]
|
||||
out += ["];", "", "/// opengl32 calls that are another command under another name.",
|
||||
"pub const ALIASES: &[(&str, &str)] = &["]
|
||||
out += [f' ("{a}", "{b}"),' for a, b in aliases]
|
||||
out += ["];", "",
|
||||
"/// The newest GL version every command of which opengl32 serves (or",
|
||||
"/// tolerates missing: `NT_TOLERATED` in the generator).",
|
||||
f"pub const MAX_VERSION: (i32, i32) = {version};",
|
||||
"/// The registry extensions every command of which it serves.",
|
||||
"pub const CLAIMABLE: &[&str] = &["]
|
||||
out += [f' "{e}",' for e in sorted(claimable)]
|
||||
out += ["];", "", pname_rust, ""]
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def host_case(c, opcode, plan):
|
||||
toks = plan.split(" ")
|
||||
r, ptoks = toks[0], toks[1:]
|
||||
L = [f"/* {c.name} */", f"template <typename R> static bool gexgen_{opcode}(R& a) {{"]
|
||||
args = []
|
||||
post = []
|
||||
check = []
|
||||
names = [p.name + "_" for p in c.params]
|
||||
for i, (p, t) in enumerate(zip(c.params, ptoks)):
|
||||
n = names[i]
|
||||
if t == "P":
|
||||
L.append(f" const void* {n} = reinterpret_cast<const void*>(static_cast<uintptr_t>(a.u64()));")
|
||||
args.append(n)
|
||||
continue
|
||||
if t in ("w", "f", "q"):
|
||||
ht = host_type(p)
|
||||
rd = {"w": "a.u32()", "f": "a.f32()", "q": "a.u64()"}[t]
|
||||
if p.base in ("GLdouble", "GLclampd"):
|
||||
rd = "a.f64()"
|
||||
elif t == "q":
|
||||
rd = "a.i64()" if ht in ("GLint64", "ptrdiff_t") else "a.u64()"
|
||||
elif t == "w" and ht in ("GLint", "GLsizei", "GLshort", "GLbyte"):
|
||||
rd = "a.i32()"
|
||||
if p.cls and CLASSES.get(p.cls):
|
||||
L.append(f" const {ht} {n} = ({ht})GEXGEN_NAME({CLASSES[p.cls]}, {rd});")
|
||||
else:
|
||||
L.append(f" const {ht} {n} = ({ht}){rd};")
|
||||
args.append(n)
|
||||
continue
|
||||
kind, rest = t[0], t[1:]
|
||||
pbo = kind == "j"
|
||||
kind = "i" if pbo else kind
|
||||
size, spec = rest.split(":", 1)
|
||||
size = int(size)
|
||||
et = ELEMENTS[p.base][2]
|
||||
if spec[0] == "n":
|
||||
count = spec[1:]
|
||||
elif spec[0] == "p":
|
||||
m = re.fullmatch(r"p(\d+)(?:\*(\d+))?", spec)
|
||||
count = f"gexgen_count({names[int(m.group(1))]}, {m.group(2) or 1})"
|
||||
elif spec[0] == "e":
|
||||
count = f"gexgl_pname_count((unsigned){names[int(spec[1:])]})"
|
||||
elif spec[0] == "z":
|
||||
count = f"gexgen_count({names[int(spec[1:])]}, 1)"
|
||||
elif spec[0] == "U":
|
||||
pi, li = spec[1:].split(",")
|
||||
count = f"uniform_components({names[int(pi)]}, {names[int(li)]})"
|
||||
else:
|
||||
count = None
|
||||
if kind == "o":
|
||||
check.append(f" const size_t {n}count = {count};")
|
||||
check.append(f" std::vector<uint64_t> {n}store(gexgen_words({n}count < 16 ? 16 : {n}count, {size}), 0);")
|
||||
check.append(f" {et}* {n} = reinterpret_cast<{et}*>({n}store.data());")
|
||||
post.append(f" put_blob({n}, (uint32_t)({n}count * {size}));")
|
||||
args.append(n)
|
||||
continue
|
||||
L.append(f" gexgen_raw {n}raw; std::vector<uint64_t> {n}store;")
|
||||
L.append(f" if (!gexgen_take(a, {n}raw, {'true' if pbo else 'false'})) return false;")
|
||||
if spec[0] in "sS":
|
||||
check.append(f" const char* {n}s = nullptr;")
|
||||
check.append(f" if (!gexgen_check_string({n}raw, {n}store, &{n}s)) {{ a.ok = false; return false; }}")
|
||||
check.append(f" const {et}* {n} = reinterpret_cast<const {et}*>({n}s);")
|
||||
args.append(n)
|
||||
continue
|
||||
check.append(f" const void* {n}v = nullptr;")
|
||||
if spec[0] == "X":
|
||||
f_, t_, w_, h_, d_ = spec[1:].split(",")
|
||||
dim = lambda x, dflt: names[int(x)] if x != "_" else dflt
|
||||
test = (f"gexgen_check_pixels({n}raw, {n}store, &{n}v, {names[int(f_)]}, {names[int(t_)]}, "
|
||||
f"{dim(w_, '1')}, {dim(h_, '1')}, {dim(d_, '-1')})")
|
||||
else:
|
||||
if spec[0] == "B":
|
||||
w_, h_ = spec[1:].split(",")
|
||||
bytes_ = f"gexgen_bitmap_bytes({names[int(w_)]}, {names[int(h_)]})"
|
||||
elif spec[0] == "T":
|
||||
bytes_ = "128"
|
||||
elif spec[0] == "L":
|
||||
ni, ti = spec[1:].split(",")
|
||||
bytes_ = f"gexgen_count({names[int(ni)]}, (long long)gexgen_type_bytes({names[int(ti)]}))"
|
||||
else:
|
||||
bytes_ = f"{count} * {size}"
|
||||
test = f"gexgen_check({n}raw, {n}store, &{n}v, {bytes_})"
|
||||
check.append(f" if (!{test}) {{ a.ok = false; return false; }}")
|
||||
check.append(f" const {et}* {n} = reinterpret_cast<const {et}*>({n}v);")
|
||||
args.append(n)
|
||||
L.append(" if (!a.ok) return false;")
|
||||
L += check
|
||||
ftype = f"{host_ret(c)} (*)({', '.join(host_type(p) for p in c.params)})"
|
||||
alias = f'"{c.alias}"' if c.alias else "nullptr"
|
||||
L.append(f" using F__ = {ftype};")
|
||||
L.append(f" static F__ f__ = reinterpret_cast<F__>(gexgen_proc(\"{c.name}\", {alias}));")
|
||||
call = f"f__({', '.join(args)})"
|
||||
missing = "put_u32(0); " if r in ("w", "f") else "put_u64(0); " if r == "q" else ""
|
||||
L.append(f" if (!f__) {{ gexgen_missing(\"{c.name}\"); {missing}" +
|
||||
"".join(f"put_blob(nullptr, 0); " for t in ptoks if t[0] == "o") + "return true; }")
|
||||
if r == "v":
|
||||
L.append(f" {call};")
|
||||
elif r == "f":
|
||||
L.append(f" const float ret__ = {call}; uint32_t bits__; memcpy(&bits__, &ret__, 4); put_u32(bits__);")
|
||||
elif r == "q":
|
||||
L.append(f" put_u64((uint64_t){call});")
|
||||
else:
|
||||
L.append(f" put_u32((uint32_t){call});")
|
||||
L += post
|
||||
L.append(" return true;")
|
||||
L.append("}")
|
||||
return "\n".join(L)
|
||||
|
||||
|
||||
def emit_host(cmds, plans, opcodes):
|
||||
"""The decoders (a function per command, which a compiler takes far
|
||||
better than one switch of thousands of cases) and the cases."""
|
||||
out = ["/* Generated by tools/gen_gl_compat.py from the Khronos registry; do not edit.",
|
||||
" *",
|
||||
" * The host half of every planned command: decode, map the guest's object",
|
||||
" * names (GEXGEN_NAME), call the host's GL through gexgen_proc, reply;",
|
||||
" * false for a malformed command. The includer defines the Reader,",
|
||||
" * put_u32/put_u64/put_blob, GEXGEN_NAME, uniform_components,",
|
||||
" * gexgen_proc/gexgen_missing, and includes web/mesa/gexgl-compat-host.h;",
|
||||
" * the cases (gl-compat-generated-cases.inc) go in its switch. */"]
|
||||
cases = ["/* Generated by tools/gen_gl_compat.py; do not edit. The decoders are",
|
||||
" * gl-compat-generated-decoders.inc. */"]
|
||||
for name in sorted(plans):
|
||||
out.append(host_case(cmds[name], opcodes[name], plans[name]))
|
||||
cases.append(f"case {opcodes[name]}: if (!gexgen_{opcodes[name]}(a)) return false; break;")
|
||||
return "\n".join(out) + "\n", "\n".join(cases) + "\n"
|
||||
|
||||
|
||||
def emit_rust_table(plans, opcodes):
|
||||
out = ["// Generated by tools/gen_gl_compat.py; do not edit.", "",
|
||||
"/// The first opcode of the generated compatibility-profile commands.",
|
||||
f"pub const COMPAT_BASE: u32 = {COMPAT_BASE};",
|
||||
"/// Every planned command: name, opcode and plan.",
|
||||
"pub const PLANS: &[(&str, u32, &str)] = &["]
|
||||
out += [f' ("{n}", {opcodes[n]}, "{plans[n]}"),' for n in sorted(plans)]
|
||||
out += ["];", ""]
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--check", action="store_true", help="fail if a checked-in output differs")
|
||||
ap.add_argument("--report", action="store_true", help="list the commands left out, and why")
|
||||
args = ap.parse_args()
|
||||
cmds, enums, wanted = load()
|
||||
allnames = sorted(cmds)
|
||||
opcodes = {n: COMPAT_BASE + allnames.index(n) for n in allnames}
|
||||
plans, skipped = {}, {}
|
||||
for n in sorted(wanted):
|
||||
p, why = plan_of(cmds[n])
|
||||
if p is None:
|
||||
skipped[n] = why
|
||||
else:
|
||||
plans[n] = p
|
||||
pname_c, pname_rust = emit_pname_counts(enums)
|
||||
host_decoders, host_cases = emit_host(cmds, plans, opcodes)
|
||||
outputs = {
|
||||
ROOT / "guest/gl/gl-compat-generated.inc": emit_guest(cmds, plans, opcodes),
|
||||
ROOT / "guest/gl/gl-pname-counts.h": pname_c,
|
||||
ROOT / "crates/gex-kernel/src/nt/opengl/generated.rs": emit_nt(cmds, plans, opcodes, pname_rust),
|
||||
ROOT / "crates/gex-gl/src/compat_plans.rs": emit_rust_table(plans, opcodes),
|
||||
ROOT / "web/mesa/gl-compat-generated-decoders.inc": host_decoders,
|
||||
ROOT / "web/mesa/gl-compat-generated-cases.inc": host_cases,
|
||||
}
|
||||
if args.report:
|
||||
for n, why in sorted(skipped.items()):
|
||||
print(f"{n}: {why}")
|
||||
print(f"{len(plans)} planned, {len(skipped)} left out", file=sys.stderr)
|
||||
if args.check:
|
||||
stale = [str(p.relative_to(ROOT)) for p, v in outputs.items() if not p.is_file() or p.read_text() != v]
|
||||
if stale:
|
||||
ap.error("stale generated files: " + ", ".join(stale))
|
||||
return 0
|
||||
for p, v in outputs.items():
|
||||
p.write_text(v)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,86 @@
|
||||
/* The host side of the generated compatibility-profile commands
|
||||
* (tools/gen_gl_compat.py, gl-compat-generated-cases.inc): reading a plan's
|
||||
* input arrays off the wire and checking them against the size the plan
|
||||
* gives, which is computed here exactly as the guest computed it
|
||||
* (guest/gl/gexgl-plan.h). Shared by the browser's Mesa decoder
|
||||
* (gexgl-mesa.cpp) and the native host's (crates/gex-gl/native).
|
||||
*
|
||||
* The includer provides, before this header: a `Reader` with u32/u64/blob
|
||||
* and `ok`; `unpack_store`, the unpack pixel store its pixel commands
|
||||
* track; and, before the cases, put_u32/put_u64/put_blob, GEXGEN_NAME(kind,
|
||||
* name), `void* gexgen_proc(const char* name, const char* alias)` and
|
||||
* `void gexgen_missing(const char* name)`. */
|
||||
#ifndef GEXGL_COMPAT_HOST_H
|
||||
#define GEXGL_COMPAT_HOST_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "../../guest/gl/gexgl-plan.h"
|
||||
|
||||
/* 64-bit words enough for `count` elements of `size` bytes. */
|
||||
static inline size_t gexgen_words(size_t count, size_t size) {
|
||||
if (count > GEXGEN_MAX_BYTES / (size ? size : 1)) count = GEXGEN_MAX_BYTES / (size ? size : 1);
|
||||
return (count * size + 7) / 8 + 1;
|
||||
}
|
||||
|
||||
/* An input array as it came off the wire: read in parameter order, checked
|
||||
* once every parameter (its count among them) has been read. */
|
||||
struct gexgen_raw {
|
||||
uint32_t tag = 0; /* 0 NULL, 1 bytes, 2 an unpack buffer offset */
|
||||
const uint8_t* p = nullptr;
|
||||
uint32_t n = 0;
|
||||
uint64_t offset = 0;
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
static bool gexgen_take(R& a, gexgen_raw& r, bool unpack) {
|
||||
r.tag = a.u32();
|
||||
if (!a.ok) return false;
|
||||
if (r.tag == 1) r.p = a.blob(r.n);
|
||||
else if (r.tag == 2 && unpack) r.offset = a.u64();
|
||||
else if (r.tag != 0) a.ok = false;
|
||||
return a.ok;
|
||||
}
|
||||
|
||||
/* Bytes, which must be exactly `bytes` long: copied to 8-byte-aligned
|
||||
* storage, zero-padded to at least 64 bytes (a pname-sized vector GL may read
|
||||
* more of than the shared table says). An unpack offset is passed as the
|
||||
* pointer GL takes for one. */
|
||||
static inline bool gexgen_check(const gexgen_raw& r, std::vector<uint64_t>& store, const void** out, size_t bytes) {
|
||||
*out = nullptr;
|
||||
if (r.tag == 0) return true;
|
||||
if (r.tag == 2) { *out = reinterpret_cast<const void*>(static_cast<uintptr_t>(r.offset)); return true; }
|
||||
if (r.n != bytes) return false;
|
||||
store.assign((r.n + 7) / 8 < 8 ? 8 : (r.n + 7) / 8, 0);
|
||||
if (r.n) memcpy(store.data(), r.p, r.n);
|
||||
*out = store.data();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* An unpack pixel transfer, sized by this end's unpack store. */
|
||||
static inline bool gexgen_check_pixels(const gexgen_raw& r, std::vector<uint64_t>& store, const void** out,
|
||||
uint32_t format, uint32_t type, int w, int h, int d) {
|
||||
struct gexgl_pixel_layout layout;
|
||||
const size_t bytes = gexgl_compute_pixel_layout(format, type, w, h, d, &unpack_store, &layout) ? layout.end : 0;
|
||||
return gexgen_check(r, store, out, bytes);
|
||||
}
|
||||
|
||||
static inline size_t gexgen_bitmap_bytes(long long w, long long h) {
|
||||
return gexgen_bitmap_bytes_store(w, h, &unpack_store);
|
||||
}
|
||||
|
||||
/* A string: any length, NUL-terminated here. */
|
||||
static inline bool gexgen_check_string(const gexgen_raw& r, std::vector<uint64_t>& store, const char** out) {
|
||||
*out = nullptr;
|
||||
if (r.tag == 0) return true;
|
||||
if (r.tag != 1) return false;
|
||||
store.assign(r.n / 8 + 1, 0);
|
||||
if (r.n) memcpy(store.data(), r.p, r.n);
|
||||
*out = reinterpret_cast<const char*>(store.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -481,6 +481,7 @@ static bool gexgl_negative_count(GLsizei n, Fn call)
|
||||
|
||||
gexgl_pixel_store pack_store = gexgl_default_pixel_store();
|
||||
gexgl_pixel_store unpack_store = gexgl_default_pixel_store();
|
||||
#include "gexgl-compat-host.h"
|
||||
|
||||
int get_frontend_param(struct pipe_frontend_screen* fscreen,
|
||||
enum st_manager_param param) {
|
||||
@@ -1591,6 +1592,21 @@ uint32_t uniform_components(GLuint program, GLint location) {
|
||||
}
|
||||
}
|
||||
|
||||
/* For the generated compatibility-profile cases (gexgl-compat-host.h). */
|
||||
#define GEXGEN_NAME(kind, name) lookup(kind, name)
|
||||
void* gexgen_proc(const char* name, const char* alias) {
|
||||
void* f = reinterpret_cast<void*>(_mesa_glapi_get_proc_address(name));
|
||||
if (!f && alias) f = reinterpret_cast<void*>(_mesa_glapi_get_proc_address(alias));
|
||||
return f;
|
||||
}
|
||||
void gexgen_missing(const char* name) {
|
||||
static std::unordered_set<std::string> said;
|
||||
if (said.insert(name).second)
|
||||
fprintf(stderr, "gexgl: Mesa has no %s; the call does nothing\n", name);
|
||||
}
|
||||
|
||||
#include "gl-compat-generated-decoders.inc"
|
||||
|
||||
bool one(uint32_t op, Reader& a) {
|
||||
switch (op) {
|
||||
case CONTEXT_CREATE: {
|
||||
@@ -2497,6 +2513,7 @@ bool one(uint32_t op, Reader& a) {
|
||||
case PUSH_ATTRIB: glPushAttrib(a.u32()); break;
|
||||
case POP_ATTRIB: glPopAttrib(); break;
|
||||
#include "gl44-generated-cases.inc"
|
||||
#include "gl-compat-generated-cases.inc"
|
||||
default:
|
||||
/* Named, once. A command the host does not know aborts the whole
|
||||
* batch -- the guest discards every queued byte, including the
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -198,7 +198,7 @@ export const op = {
|
||||
};
|
||||
|
||||
export const MAGIC = 0x47584547;
|
||||
export const PROTOCOL_VERSION = 12;
|
||||
export const PROTOCOL_VERSION = 13;
|
||||
export const HEADER_BYTES = 32;
|
||||
|
||||
export const error = {
|
||||
|
||||
Reference in new issue
Block a user