Add support for OpenGL to OpenXR

This commit is contained in:
David Snopek 2022-10-22 20:29:15 -05:00
parent 6d9546f16c
commit 23603e409c
22 changed files with 986 additions and 127 deletions

View file

@ -1725,9 +1725,17 @@
</constant>
<constant name="WINDOW_VIEW" value="2" enum="HandleType">
Window view:
- Windows: [code]HDC[/code] for the window (only with the GL Compatibility renderer).
- macOS: [code]NSView*[/code] for the window main view.
- iOS: [code]UIView*[/code] for the window main view.
</constant>
<constant name="OPENGL_CONTEXT" value="3" enum="HandleType">
OpenGL context (only with the GL Compatibility renderer):
- Windows: [code]HGLRC[/code] for the window.
- Linux: [code]GLXContext*[/code] for the window.
- MacOS: [code]NSOpenGLContext*[/code] for the window.
- Android: [code]EGLContext[/code] for the window.
</constant>
<constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent">
Utterance has begun to be spoken.
</constant>

View file

@ -1642,6 +1642,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
ERR_FAIL_COND(rb.is_null());
}
GLES3::RenderTarget *rt = texture_storage->get_render_target(rb->render_target);
ERR_FAIL_COND(!rt);
// Assign render data
// Use the format from rendererRD
RenderDataGLES3 render_data;
@ -1729,8 +1732,20 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
scene_state.ubo.emissive_exposure_normalization = -1.0; // Use default exposure normalization.
bool flip_y = !render_data.reflection_probe.is_valid();
if (rt->overridden.color.is_valid()) {
// If we've overridden the render target's color texture, then don't render upside down.
// We're probably rendering directly to an XR device.
flip_y = false;
}
if (!flip_y) {
// If we're rendering right-side up, then we need to change the winding order.
glFrontFace(GL_CW);
}
_setup_lights(&render_data, false, render_data.directional_light_count, render_data.omni_light_count, render_data.spot_light_count);
_setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, !render_data.reflection_probe.is_valid(), clear_color, false);
_setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, flip_y, clear_color, false);
_fill_render_list(RENDER_LIST_OPAQUE, &render_data, PASS_MODE_COLOR);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
@ -1811,7 +1826,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}
}
glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glViewport(0, 0, rb->width, rb->height);
// Do depth prepass if it's explicitly enabled
@ -1917,6 +1932,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
if (!flip_y) {
// Restore the default winding order.
glFrontFace(GL_CCW);
}
if (rb.is_valid()) {
_render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex);
}

View file

@ -33,17 +33,12 @@
#include "render_scene_buffers_gles3.h"
#include "texture_storage.h"
#ifdef ANDROID_ENABLED
#define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR
#endif
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
free_render_buffer_data();
}
void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
//internal_size.x = p_internal_size.x; // ignore for now
//internal_size.y = p_internal_size.y;
@ -62,66 +57,9 @@ void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_inte
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
is_transparent = rt->is_transparent;
// framebuffer
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
if (view_count > 1 && config->multiview_supported) {
glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color);
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, view_count);
} else {
glBindTexture(GL_TEXTURE_2D, rt->color);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
}
glGenTextures(1, &depth_texture);
if (view_count > 1 && config->multiview_supported) {
glBindTexture(GL_TEXTURE_2D_ARRAY, depth_texture);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
if (view_count > 1 && config->multiview_supported) {
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture, 0, 0, view_count);
} else {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
free_render_buffer_data();
WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
return;
}
}
void RenderSceneBuffersGLES3::free_render_buffer_data() {
if (depth_texture) {
glDeleteTextures(1, &depth_texture);
depth_texture = 0;
}
if (framebuffer) {
glDeleteFramebuffers(1, &framebuffer);
framebuffer = 0;
}
}
#endif // GLES3_ENABLED

View file

@ -61,9 +61,6 @@ public:
bool is_transparent = false;
RID render_target;
GLuint internal_texture = 0; // Used for rendering when post effects are enabled
GLuint depth_texture = 0; // Main depth texture
GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
//built-in textures used for ping pong image processing and blurring
struct Blur {

View file

@ -614,7 +614,9 @@ void TextureStorage::texture_free(RID p_texture) {
}
if (t->tex_id != 0) {
glDeleteTextures(1, &t->tex_id);
if (!t->is_external) {
glDeleteTextures(1, &t->tex_id);
}
t->tex_id = 0;
}
@ -680,6 +682,35 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
texture_owner.initialize_rid(p_texture, proxy_tex);
}
RID TextureStorage::texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
Texture texture;
texture.active = true;
texture.is_external = true;
texture.type = p_type;
switch (p_type) {
case Texture::TYPE_2D: {
texture.target = GL_TEXTURE_2D;
} break;
case Texture::TYPE_3D: {
texture.target = GL_TEXTURE_3D;
} break;
case Texture::TYPE_LAYERED: {
texture.target = GL_TEXTURE_2D_ARRAY;
} break;
}
texture.real_format = texture.format = p_format;
texture.tex_id = p_image;
texture.alloc_width = texture.width = p_width;
texture.alloc_height = texture.height = p_height;
texture.depth = p_depth;
texture.layers = p_layers;
texture.layered_type = p_layered_type;
return texture_owner.make_rid(texture);
}
void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
texture_set_data(p_texture, p_image, p_layer);
#ifdef TOOLS_ENABLED
@ -1459,43 +1490,74 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
glDepthMask(GL_FALSE);
{
Texture *texture;
bool use_multiview = rt->view_count > 1 && config->multiview_supported;
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
/* Front FBO */
Texture *texture = get_texture(rt->texture);
ERR_FAIL_COND(!texture);
// framebuffer
glGenFramebuffers(1, &rt->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
// color
glGenTextures(1, &rt->color);
if (rt->view_count > 1 && config->multiview_supported) {
glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr);
if (rt->overridden.color.is_valid()) {
texture = get_texture(rt->overridden.color);
ERR_FAIL_COND(!texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
rt->color = texture->tex_id;
rt->size = Size2i(texture->width, texture->height);
} else {
glBindTexture(GL_TEXTURE_2D, rt->color);
glTexImage2D(GL_TEXTURE_2D, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
texture = get_texture(rt->texture);
ERR_FAIL_COND(!texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenTextures(1, &rt->color);
glBindTexture(texture_target, rt->color);
if (use_multiview) {
glTexImage3D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr);
} else {
glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
}
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
if (rt->view_count > 1 && config->multiview_supported) {
if (use_multiview) {
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, rt->view_count);
} else {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// depth
if (rt->overridden.depth.is_valid()) {
texture = get_texture(rt->overridden.depth);
ERR_FAIL_COND(!texture);
rt->depth = texture->tex_id;
} else {
glGenTextures(1, &rt->depth);
glBindTexture(texture_target, rt->depth);
if (use_multiview) {
glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
} else {
glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
}
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
if (use_multiview) {
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count);
} else {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
glDeleteFramebuffers(1, &rt->fbo);
glDeleteTextures(1, &rt->color);
@ -1503,32 +1565,38 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
rt->size.x = 0;
rt->size.y = 0;
rt->color = 0;
texture->tex_id = 0;
texture->active = false;
rt->depth = 0;
if (rt->overridden.color.is_null()) {
texture->tex_id = 0;
texture->active = false;
}
WARN_PRINT("Could not create render target, status: " + get_framebuffer_error(status));
return;
}
texture->format = rt->image_format;
texture->real_format = rt->image_format;
if (rt->view_count > 1 && config->multiview_supported) {
texture->type = Texture::TYPE_LAYERED;
texture->target = GL_TEXTURE_2D_ARRAY;
texture->layers = rt->view_count;
if (rt->overridden.color.is_valid()) {
texture->is_render_target = true;
} else {
texture->type = Texture::TYPE_2D;
texture->target = GL_TEXTURE_2D;
texture->layers = 1;
texture->format = rt->image_format;
texture->real_format = rt->image_format;
texture->target = texture_target;
if (rt->view_count > 1 && config->multiview_supported) {
texture->type = Texture::TYPE_LAYERED;
texture->layers = rt->view_count;
} else {
texture->type = Texture::TYPE_2D;
texture->layers = 1;
}
texture->gl_format_cache = rt->color_format;
texture->gl_type_cache = GL_UNSIGNED_BYTE;
texture->gl_internal_format_cache = rt->color_internal_format;
texture->tex_id = rt->color;
texture->width = rt->size.x;
texture->alloc_width = rt->size.x;
texture->height = rt->size.y;
texture->alloc_height = rt->size.y;
texture->active = true;
}
texture->gl_format_cache = rt->color_format;
texture->gl_type_cache = GL_UNSIGNED_BYTE;
texture->gl_internal_format_cache = rt->color_internal_format;
texture->tex_id = rt->color;
texture->width = rt->size.x;
texture->alloc_width = rt->size.x;
texture->height = rt->size.y;
texture->alloc_height = rt->size.y;
texture->active = true;
}
glClearColor(0, 0, 0, 0);
@ -1596,17 +1664,32 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
if (rt->fbo) {
glDeleteFramebuffers(1, &rt->fbo);
glDeleteTextures(1, &rt->color);
rt->fbo = 0;
}
if (rt->overridden.color.is_null()) {
glDeleteTextures(1, &rt->color);
rt->color = 0;
}
Texture *tex = get_texture(rt->texture);
tex->alloc_height = 0;
tex->alloc_width = 0;
tex->width = 0;
tex->height = 0;
tex->active = false;
if (rt->overridden.depth.is_null()) {
glDeleteTextures(1, &rt->depth);
rt->depth = 0;
}
if (rt->texture.is_valid()) {
Texture *tex = get_texture(rt->texture);
tex->alloc_height = 0;
tex->alloc_width = 0;
tex->width = 0;
tex->height = 0;
tex->active = false;
}
if (rt->overridden.color.is_valid()) {
Texture *tex = get_texture(rt->overridden.color);
tex->is_render_target = false;
}
if (rt->backbuffer_fbo != 0) {
glDeleteFramebuffers(1, &rt->backbuffer_fbo);
@ -1617,6 +1700,15 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
_render_target_clear_sdf(rt);
}
void TextureStorage::_clear_render_target_overridden_fbo_cache(RenderTarget *rt) {
// Dispose of the cached fbo's and the allocated textures
for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) {
glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr());
glDeleteFramebuffers(1, &E.value.fbo);
}
rt->overridden.fbo_cache.clear();
}
RID TextureStorage::render_target_create() {
RenderTarget render_target;
//render_target.was_used = false;
@ -1635,11 +1727,14 @@ RID TextureStorage::render_target_create() {
void TextureStorage::render_target_free(RID p_rid) {
RenderTarget *rt = render_target_owner.get_or_null(p_rid);
_clear_render_target(rt);
_clear_render_target_overridden_fbo_cache(rt);
Texture *t = get_texture(rt->texture);
if (t) {
t->is_render_target = false;
texture_free(rt->texture);
if (rt->overridden.color.is_null()) {
texture_free(rt->texture);
}
//memdelete(t);
}
render_target_owner.free(p_rid);
@ -1666,6 +1761,9 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
if (p_width == rt->size.x && p_height == rt->size.y && p_view_count == rt->view_count) {
return;
}
if (rt->overridden.color.is_valid()) {
return;
}
_clear_render_target(rt);
@ -1683,10 +1781,91 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
return rt->size;
}
void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
ERR_FAIL_COND(rt->direct_to_screen);
rt->overridden.velocity = p_velocity_texture;
if (rt->overridden.color == p_color_texture && rt->overridden.depth == p_depth_texture) {
return;
}
if (p_color_texture.is_null() && p_depth_texture.is_null()) {
_clear_render_target(rt);
rt->overridden.is_overridden = false;
rt->overridden.color = RID();
rt->overridden.depth = RID();
rt->size = Size2i();
_clear_render_target_overridden_fbo_cache(rt);
return;
}
if (!rt->overridden.is_overridden) {
_clear_render_target(rt);
}
rt->overridden.color = p_color_texture;
rt->overridden.depth = p_depth_texture;
rt->overridden.is_overridden = true;
uint32_t hash_key = hash_murmur3_one_64(p_color_texture.get_id());
hash_key = hash_murmur3_one_64(p_depth_texture.get_id(), hash_key);
hash_key = hash_fmix32(hash_key);
RBMap<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry>::Element *cache;
if ((cache = rt->overridden.fbo_cache.find(hash_key)) != nullptr) {
rt->fbo = cache->get().fbo;
rt->size = cache->get().size;
rt->texture = p_color_texture;
return;
}
_update_render_target(rt);
RenderTarget::RTOverridden::FBOCacheEntry new_entry;
new_entry.fbo = rt->fbo;
new_entry.size = rt->size;
// Keep track of any textures we had to allocate because they weren't overridden.
if (p_color_texture.is_null()) {
new_entry.allocated_textures.push_back(rt->color);
}
if (p_depth_texture.is_null()) {
new_entry.allocated_textures.push_back(rt->depth);
}
rt->overridden.fbo_cache.insert(hash_key, new_entry);
}
RID TextureStorage::render_target_get_override_color(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->overridden.color;
}
RID TextureStorage::render_target_get_override_depth(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->overridden.depth;
}
RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
return rt->overridden.velocity;
}
RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (rt->overridden.color.is_valid()) {
return rt->overridden.color;
}
return rt->texture;
}
@ -1696,8 +1875,10 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_t
rt->is_transparent = p_transparent;
_clear_render_target(rt);
_update_render_target(rt);
if (rt->overridden.color.is_null()) {
_clear_render_target(rt);
_update_render_target(rt);
}
}
bool TextureStorage::render_target_get_transparent(RID p_render_target) const {
@ -1718,6 +1899,11 @@ void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, boo
// those functions change how they operate depending on the value of DIRECT_TO_SCREEN
_clear_render_target(rt);
rt->direct_to_screen = p_direct_to_screen;
if (rt->direct_to_screen) {
rt->overridden.color = RID();
rt->overridden.depth = RID();
rt->overridden.velocity = RID();
}
_update_render_target(rt);
}
@ -1750,6 +1936,7 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA
}
WARN_PRINT("2D MSAA is not yet supported for GLES3.");
_clear_render_target(rt);
rt->msaa = p_msaa;
_update_render_target(rt);

View file

@ -126,6 +126,7 @@ struct Texture {
RID self;
bool is_proxy = false;
bool is_external = false;
bool is_render_target = false;
RID proxy_to = RID();
@ -187,6 +188,7 @@ struct Texture {
void copy_from(const Texture &o) {
proxy_to = o.proxy_to;
is_proxy = o.is_proxy;
is_external = o.is_external;
width = o.width;
height = o.height;
alloc_width = o.alloc_width;
@ -310,6 +312,7 @@ struct RenderTarget {
RID self;
GLuint fbo = 0;
GLuint color = 0;
GLuint depth = 0;
GLuint backbuffer_fbo = 0;
GLuint backbuffer = 0;
@ -333,6 +336,20 @@ struct RenderTarget {
bool used_in_frame = false;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
struct RTOverridden {
bool is_overridden = false;
RID color;
RID depth;
RID velocity;
struct FBOCacheEntry {
GLuint fbo;
Size2i size;
Vector<GLuint> allocated_textures;
};
RBMap<uint32_t, FBOCacheEntry> fbo_cache;
} overridden;
RID texture;
Color clear_color = Color(1, 1, 1, 1);
@ -395,6 +412,7 @@ private:
mutable RID_Owner<RenderTarget> render_target_owner;
void _clear_render_target(RenderTarget *rt);
void _clear_render_target_overridden_fbo_cache(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
void _render_target_allocate_sdf(RenderTarget *rt);
@ -454,6 +472,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
RID texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY);
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
@ -593,10 +613,10 @@ public:
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override {}
virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
virtual RID render_target_get_override_color(RID p_render_target) const override;
virtual RID render_target_get_override_depth(RID p_render_target) const override;
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
virtual RID render_target_get_texture(RID p_render_target) override;

View file

@ -90,6 +90,8 @@ if env["platform"] == "android":
env_openxr.add_source_files(module_obj, "extensions/openxr_android_extension.cpp")
if env["vulkan"]:
env_openxr.add_source_files(module_obj, "extensions/openxr_vulkan_extension.cpp")
if env["opengl3"]:
env_openxr.add_source_files(module_obj, "extensions/openxr_opengl_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_palm_pose_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_composition_layer_depth_extension.cpp")

View file

@ -0,0 +1,479 @@
/*************************************************************************/
/* openxr_opengl_extension.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef GLES3_ENABLED
#include "../extensions/openxr_opengl_extension.h"
#include "../openxr_util.h"
#include "drivers/gles3/effects/copy_effects.h"
#include "drivers/gles3/storage/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering_server.h"
OpenXROpenGLExtension::OpenXROpenGLExtension(OpenXRAPI *p_openxr_api) :
OpenXRGraphicsExtensionWrapper(p_openxr_api) {
#ifdef ANDROID_ENABLED
request_extensions[XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME] = nullptr;
#else
request_extensions[XR_KHR_OPENGL_ENABLE_EXTENSION_NAME] = nullptr;
#endif
ERR_FAIL_NULL(openxr_api);
}
OpenXROpenGLExtension::~OpenXROpenGLExtension() {
}
void OpenXROpenGLExtension::on_instance_created(const XrInstance p_instance) {
ERR_FAIL_NULL(openxr_api);
// Obtain pointers to functions we're accessing here.
#ifdef ANDROID_ENABLED
EXT_INIT_XR_FUNC(xrGetOpenGLESGraphicsRequirementsKHR);
#else
EXT_INIT_XR_FUNC(xrGetOpenGLGraphicsRequirementsKHR);
#endif
EXT_INIT_XR_FUNC(xrEnumerateSwapchainImages);
}
bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_version) {
ERR_FAIL_NULL_V(openxr_api, false);
XrSystemId system_id = openxr_api->get_system_id();
XrInstance instance = openxr_api->get_instance();
#ifdef ANDROID_ENABLED
XrGraphicsRequirementsOpenGLESKHR opengl_requirements;
opengl_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
opengl_requirements.next = nullptr;
XrResult result = xrGetOpenGLESGraphicsRequirementsKHR(instance, system_id, &opengl_requirements);
if (!openxr_api->xr_result(result, "Failed to get OpenGL graphics requirements!")) {
return false;
}
#else
XrGraphicsRequirementsOpenGLKHR opengl_requirements;
opengl_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR;
opengl_requirements.next = nullptr;
XrResult result = xrGetOpenGLGraphicsRequirementsKHR(instance, system_id, &opengl_requirements);
if (!openxr_api->xr_result(result, "Failed to get OpenGL graphics requirements!")) {
return false;
}
#endif
if (p_desired_version < opengl_requirements.minApiVersionSupported) {
print_line("OpenXR: Requested OpenGL version does not meet the minimum version this runtime supports.");
print_line("- desired_version ", OpenXRUtil::make_xr_version_string(p_desired_version));
print_line("- minApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.minApiVersionSupported));
print_line("- maxApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.maxApiVersionSupported));
return false;
}
if (p_desired_version > opengl_requirements.maxApiVersionSupported) {
print_line("OpenXR: Requested OpenGL version exceeds the maximum version this runtime has been tested on and is known to support.");
print_line("- desired_version ", OpenXRUtil::make_xr_version_string(p_desired_version));
print_line("- minApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.minApiVersionSupported));
print_line("- maxApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.maxApiVersionSupported));
}
return true;
}
#ifdef WIN32
XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl;
#elif ANDROID_ENABLED
XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl;
#else
XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl;
#endif
void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) {
XrVersion desired_version = XR_MAKE_VERSION(3, 3, 0);
if (!check_graphics_api_support(desired_version)) {
print_line("OpenXR: Trying to initialize with OpenGL anyway...");
//return p_next_pointer;
}
DisplayServer *display_server = DisplayServer::get_singleton();
#ifdef WIN32
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
graphics_binding_gl.next = p_next_pointer;
graphics_binding_gl.hDC = (HDC)display_server->window_get_native_handle(DisplayServer::WINDOW_VIEW);
graphics_binding_gl.hGLRC = (HGLRC)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
#elif ANDROID_ENABLED
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
graphics_binding_gl.next = p_next_pointer;
graphics_binding_gl.display = eglGetCurrentDisplay();
graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122
graphics_binding_gl.context = eglGetCurrentContext();
#else
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
graphics_binding_gl.next = p_next_pointer;
void *display_handle = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE);
void *glxcontext_handle = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
void *glxdrawable_handle = (void *)display_server->window_get_native_handle(DisplayServer::WINDOW_HANDLE);
graphics_binding_gl.xDisplay = (Display *)display_handle;
graphics_binding_gl.glxContext = (GLXContext)glxcontext_handle;
graphics_binding_gl.glxDrawable = (GLXDrawable)glxdrawable_handle;
if (graphics_binding_gl.xDisplay == nullptr) {
print_line("OpenXR Failed to get xDisplay from Godot, using XOpenDisplay(nullptr)");
graphics_binding_gl.xDisplay = XOpenDisplay(nullptr);
}
if (graphics_binding_gl.glxContext == nullptr) {
print_line("OpenXR Failed to get glxContext from Godot, using glXGetCurrentContext()");
graphics_binding_gl.glxContext = glXGetCurrentContext();
}
if (graphics_binding_gl.glxDrawable == 0) {
print_line("OpenXR Failed to get glxDrawable from Godot, using glXGetCurrentDrawable()");
graphics_binding_gl.glxDrawable = glXGetCurrentDrawable();
}
// spec says to use proper values but runtimes don't care
graphics_binding_gl.visualid = 0;
graphics_binding_gl.glxFBConfig = 0;
#endif
return &graphics_binding_gl;
}
void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) {
#ifdef WIN32
p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8);
p_usable_swap_chains.push_back(GL_RGBA8);
#elif ANDROID_ENABLED
p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8);
p_usable_swap_chains.push_back(GL_RGBA8);
#else
p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8_EXT);
p_usable_swap_chains.push_back(GL_RGBA8_EXT);
#endif
}
void OpenXROpenGLExtension::get_usable_depth_formats(Vector<int64_t> &p_usable_depth_formats) {
p_usable_depth_formats.push_back(GL_DEPTH_COMPONENT32F);
p_usable_depth_formats.push_back(GL_DEPTH24_STENCIL8);
p_usable_depth_formats.push_back(GL_DEPTH32F_STENCIL8);
}
bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
ERR_FAIL_NULL_V(texture_storage, false);
uint32_t swapchain_length;
XrResult result = xrEnumerateSwapchainImages(p_swapchain, 0, &swapchain_length, nullptr);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to get swapchaim image count [", openxr_api->get_error_string(result), "]");
return false;
}
#ifdef ANDROID_ENABLED
XrSwapchainImageOpenGLESKHR *images = (XrSwapchainImageOpenGLESKHR *)memalloc(sizeof(XrSwapchainImageOpenGLESKHR) * swapchain_length);
#else
XrSwapchainImageOpenGLKHR *images = (XrSwapchainImageOpenGLKHR *)memalloc(sizeof(XrSwapchainImageOpenGLKHR) * swapchain_length);
#endif
ERR_FAIL_NULL_V_MSG(images, false, "OpenXR Couldn't allocate memory for swap chain image");
for (uint64_t i = 0; i < swapchain_length; i++) {
#ifdef ANDROID_ENABLED
images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR;
#else
images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR;
#endif
images[i].next = nullptr;
images[i].image = 0;
}
result = xrEnumerateSwapchainImages(p_swapchain, swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader *)images);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to get swapchaim images [", openxr_api->get_error_string(result), "]");
memfree(images);
return false;
}
SwapchainGraphicsData *data = memnew(SwapchainGraphicsData);
if (data == nullptr) {
print_line("OpenXR: Failed to allocate memory for swapchain data");
memfree(images);
return false;
}
*r_swapchain_graphics_data = data;
data->is_multiview = (p_array_size > 1);
Image::Format format = Image::FORMAT_RGBA8;
Vector<RID> texture_rids;
for (uint64_t i = 0; i < swapchain_length; i++) {
RID texture_rid = texture_storage->texture_create_external(
p_array_size == 1 ? GLES3::Texture::TYPE_2D : GLES3::Texture::TYPE_LAYERED,
format,
images[i].image,
p_width,
p_height,
1,
p_array_size);
texture_rids.push_back(texture_rid);
}
data->texture_rids = texture_rids;
memfree(images);
return true;
}
bool OpenXROpenGLExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
XrMatrix4x4f matrix;
XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
r_camera_matrix.columns[j][i] = matrix.m[j * 4 + i];
}
}
return true;
}
RID OpenXROpenGLExtension::get_texture(void *p_swapchain_graphics_data, int p_image_index) {
SwapchainGraphicsData *data = (SwapchainGraphicsData *)p_swapchain_graphics_data;
ERR_FAIL_NULL_V(data, RID());
ERR_FAIL_INDEX_V(p_image_index, data->texture_rids.size(), RID());
return data->texture_rids[p_image_index];
}
void OpenXROpenGLExtension::cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) {
if (*p_swapchain_graphics_data == nullptr) {
return;
}
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
ERR_FAIL_NULL(texture_storage);
SwapchainGraphicsData *data = (SwapchainGraphicsData *)*p_swapchain_graphics_data;
for (int i = 0; i < data->texture_rids.size(); i++) {
texture_storage->texture_free(data->texture_rids[i]);
}
data->texture_rids.clear();
memdelete(data);
*p_swapchain_graphics_data = nullptr;
}
#define ENUM_TO_STRING_CASE(e) \
case e: { \
return String(#e); \
} break;
String OpenXROpenGLExtension::get_swapchain_format_name(int64_t p_swapchain_format) const {
// These are somewhat different per platform, will need to weed some stuff out...
switch (p_swapchain_format) {
#ifdef WIN32
// using definitions from GLAD
ENUM_TO_STRING_CASE(GL_R8_SNORM)
ENUM_TO_STRING_CASE(GL_RG8_SNORM)
ENUM_TO_STRING_CASE(GL_RGB8_SNORM)
ENUM_TO_STRING_CASE(GL_RGBA8_SNORM)
ENUM_TO_STRING_CASE(GL_R16_SNORM)
ENUM_TO_STRING_CASE(GL_RG16_SNORM)
ENUM_TO_STRING_CASE(GL_RGB16_SNORM)
ENUM_TO_STRING_CASE(GL_RGBA16_SNORM)
ENUM_TO_STRING_CASE(GL_RGB4)
ENUM_TO_STRING_CASE(GL_RGB5)
ENUM_TO_STRING_CASE(GL_RGB8)
ENUM_TO_STRING_CASE(GL_RGB10)
ENUM_TO_STRING_CASE(GL_RGB12)
ENUM_TO_STRING_CASE(GL_RGB16)
ENUM_TO_STRING_CASE(GL_RGBA2)
ENUM_TO_STRING_CASE(GL_RGBA4)
ENUM_TO_STRING_CASE(GL_RGB5_A1)
ENUM_TO_STRING_CASE(GL_RGBA8)
ENUM_TO_STRING_CASE(GL_RGB10_A2)
ENUM_TO_STRING_CASE(GL_RGBA12)
ENUM_TO_STRING_CASE(GL_RGBA16)
ENUM_TO_STRING_CASE(GL_RGBA32F)
ENUM_TO_STRING_CASE(GL_RGB32F)
ENUM_TO_STRING_CASE(GL_RGBA16F)
ENUM_TO_STRING_CASE(GL_RGB16F)
ENUM_TO_STRING_CASE(GL_RGBA32UI)
ENUM_TO_STRING_CASE(GL_RGB32UI)
ENUM_TO_STRING_CASE(GL_RGBA16UI)
ENUM_TO_STRING_CASE(GL_RGB16UI)
ENUM_TO_STRING_CASE(GL_RGBA8UI)
ENUM_TO_STRING_CASE(GL_RGB8UI)
ENUM_TO_STRING_CASE(GL_RGBA32I)
ENUM_TO_STRING_CASE(GL_RGB32I)
ENUM_TO_STRING_CASE(GL_RGBA16I)
ENUM_TO_STRING_CASE(GL_RGB16I)
ENUM_TO_STRING_CASE(GL_RGBA8I)
ENUM_TO_STRING_CASE(GL_RGB8I)
ENUM_TO_STRING_CASE(GL_RGB10_A2UI)
ENUM_TO_STRING_CASE(GL_SRGB)
ENUM_TO_STRING_CASE(GL_SRGB8)
ENUM_TO_STRING_CASE(GL_SRGB_ALPHA)
ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8)
ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16)
ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24)
ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32)
ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F)
ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32F)
ENUM_TO_STRING_CASE(GL_DEPTH32F_STENCIL8)
#elif ANDROID_ENABLED
// using definitions from GLES3/gl3.h
ENUM_TO_STRING_CASE(GL_RGBA4)
ENUM_TO_STRING_CASE(GL_RGB5_A1)
ENUM_TO_STRING_CASE(GL_RGB565)
ENUM_TO_STRING_CASE(GL_RGB8)
ENUM_TO_STRING_CASE(GL_RGBA8)
ENUM_TO_STRING_CASE(GL_RGB10_A2)
ENUM_TO_STRING_CASE(GL_RGBA32F)
ENUM_TO_STRING_CASE(GL_RGB32F)
ENUM_TO_STRING_CASE(GL_RGBA16F)
ENUM_TO_STRING_CASE(GL_RGB16F)
ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F)
ENUM_TO_STRING_CASE(GL_UNSIGNED_INT_10F_11F_11F_REV)
ENUM_TO_STRING_CASE(GL_RGB9_E5)
ENUM_TO_STRING_CASE(GL_UNSIGNED_INT_5_9_9_9_REV)
ENUM_TO_STRING_CASE(GL_RGBA32UI)
ENUM_TO_STRING_CASE(GL_RGB32UI)
ENUM_TO_STRING_CASE(GL_RGBA16UI)
ENUM_TO_STRING_CASE(GL_RGB16UI)
ENUM_TO_STRING_CASE(GL_RGBA8UI)
ENUM_TO_STRING_CASE(GL_RGB8UI)
ENUM_TO_STRING_CASE(GL_RGBA32I)
ENUM_TO_STRING_CASE(GL_RGB32I)
ENUM_TO_STRING_CASE(GL_RGBA16I)
ENUM_TO_STRING_CASE(GL_RGB16I)
ENUM_TO_STRING_CASE(GL_RGBA8I)
ENUM_TO_STRING_CASE(GL_RGB8I)
ENUM_TO_STRING_CASE(GL_RG)
ENUM_TO_STRING_CASE(GL_RG_INTEGER)
ENUM_TO_STRING_CASE(GL_R8)
ENUM_TO_STRING_CASE(GL_RG8)
ENUM_TO_STRING_CASE(GL_R16F)
ENUM_TO_STRING_CASE(GL_R32F)
ENUM_TO_STRING_CASE(GL_RG16F)
ENUM_TO_STRING_CASE(GL_RG32F)
ENUM_TO_STRING_CASE(GL_R8I)
ENUM_TO_STRING_CASE(GL_R8UI)
ENUM_TO_STRING_CASE(GL_R16I)
ENUM_TO_STRING_CASE(GL_R16UI)
ENUM_TO_STRING_CASE(GL_R32I)
ENUM_TO_STRING_CASE(GL_R32UI)
ENUM_TO_STRING_CASE(GL_RG8I)
ENUM_TO_STRING_CASE(GL_RG8UI)
ENUM_TO_STRING_CASE(GL_RG16I)
ENUM_TO_STRING_CASE(GL_RG16UI)
ENUM_TO_STRING_CASE(GL_RG32I)
ENUM_TO_STRING_CASE(GL_RG32UI)
ENUM_TO_STRING_CASE(GL_R8_SNORM)
ENUM_TO_STRING_CASE(GL_RG8_SNORM)
ENUM_TO_STRING_CASE(GL_RGB8_SNORM)
ENUM_TO_STRING_CASE(GL_RGBA8_SNORM)
ENUM_TO_STRING_CASE(GL_RGB10_A2UI)
ENUM_TO_STRING_CASE(GL_SRGB)
ENUM_TO_STRING_CASE(GL_SRGB8)
ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8)
ENUM_TO_STRING_CASE(GL_COMPRESSED_R11_EAC)
ENUM_TO_STRING_CASE(GL_COMPRESSED_SIGNED_R11_EAC)
ENUM_TO_STRING_CASE(GL_COMPRESSED_RG11_EAC)
ENUM_TO_STRING_CASE(GL_COMPRESSED_SIGNED_RG11_EAC)
ENUM_TO_STRING_CASE(GL_COMPRESSED_RGB8_ETC2)
ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_ETC2)
ENUM_TO_STRING_CASE(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2)
ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2)
ENUM_TO_STRING_CASE(GL_COMPRESSED_RGBA8_ETC2_EAC)
ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC)
ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16)
ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24)
ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
#else
// using definitions from GL/gl.h
ENUM_TO_STRING_CASE(GL_ALPHA4_EXT)
ENUM_TO_STRING_CASE(GL_ALPHA8_EXT)
ENUM_TO_STRING_CASE(GL_ALPHA12_EXT)
ENUM_TO_STRING_CASE(GL_ALPHA16_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE4_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE8_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE12_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE16_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE4_ALPHA4_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE6_ALPHA2_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE8_ALPHA8_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA4_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA12_EXT)
ENUM_TO_STRING_CASE(GL_LUMINANCE16_ALPHA16_EXT)
ENUM_TO_STRING_CASE(GL_INTENSITY_EXT)
ENUM_TO_STRING_CASE(GL_INTENSITY4_EXT)
ENUM_TO_STRING_CASE(GL_INTENSITY8_EXT)
ENUM_TO_STRING_CASE(GL_INTENSITY12_EXT)
ENUM_TO_STRING_CASE(GL_INTENSITY16_EXT)
ENUM_TO_STRING_CASE(GL_RGB2_EXT)
ENUM_TO_STRING_CASE(GL_RGB4_EXT)
ENUM_TO_STRING_CASE(GL_RGB5_EXT)
ENUM_TO_STRING_CASE(GL_RGB8_EXT)
ENUM_TO_STRING_CASE(GL_RGB10_EXT)
ENUM_TO_STRING_CASE(GL_RGB12_EXT)
ENUM_TO_STRING_CASE(GL_RGB16_EXT)
ENUM_TO_STRING_CASE(GL_RGBA2_EXT)
ENUM_TO_STRING_CASE(GL_RGBA4_EXT)
ENUM_TO_STRING_CASE(GL_RGB5_A1_EXT)
ENUM_TO_STRING_CASE(GL_RGBA8_EXT)
ENUM_TO_STRING_CASE(GL_RGB10_A2_EXT)
ENUM_TO_STRING_CASE(GL_RGBA12_EXT)
ENUM_TO_STRING_CASE(GL_RGBA16_EXT)
ENUM_TO_STRING_CASE(GL_SRGB_EXT)
ENUM_TO_STRING_CASE(GL_SRGB8_EXT)
ENUM_TO_STRING_CASE(GL_SRGB_ALPHA_EXT)
ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8_EXT)
#endif
default: {
return String("Swapchain format 0x") + String::num_int64(p_swapchain_format, 16);
} break;
}
}
#endif // GLES3_ENABLED

View file

@ -0,0 +1,120 @@
/*************************************************************************/
/* openxr_opengl_extension.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OPENXR_OPENGL_EXTENSION_H
#define OPENXR_OPENGL_EXTENSION_H
#ifdef GLES3_ENABLED
#include "core/templates/vector.h"
#include "openxr_extension_wrapper.h"
#include "../openxr_api.h"
#include "../util.h"
#ifdef ANDROID_ENABLED
#define XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#define XR_USE_GRAPHICS_API_OPENGL
#endif
#ifdef WINDOWS_ENABLED
// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
// however due to the way the openxr headers are put together, we have no choice.
#include <windows.h>
#endif
#ifdef X11_ENABLED
#include OPENGL_INCLUDE_H
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#endif
#ifdef ANDROID_ENABLED
// The jobject type from jni.h is used by openxr_platform.h on Android.
#include <jni.h>
#endif
// include platform dependent structs
#include <openxr/openxr_platform.h>
class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper {
public:
OpenXROpenGLExtension(OpenXRAPI *p_openxr_api);
virtual ~OpenXROpenGLExtension() override;
virtual void on_instance_created(const XrInstance p_instance) override;
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
virtual void get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) override;
virtual void get_usable_depth_formats(Vector<int64_t> &p_usable_swap_chains) override;
virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override;
virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override;
virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override;
virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override;
virtual RID get_texture(void *p_swapchain_graphics_data, int p_image_index) override;
private:
static OpenXROpenGLExtension *singleton;
#ifdef WIN32
static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl;
#elif ANDROID_ENABLED
static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl;
#else
static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl;
#endif
struct SwapchainGraphicsData {
bool is_multiview;
Vector<RID> texture_rids;
};
bool check_graphics_api_support(XrVersion p_desired_version);
#ifdef ANDROID_ENABLED
EXT_PROTO_XRRESULT_FUNC3(xrGetOpenGLESGraphicsRequirementsKHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsOpenGLESKHR *), p_graphics_requirements)
#else
EXT_PROTO_XRRESULT_FUNC3(xrGetOpenGLGraphicsRequirementsKHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsOpenGLKHR *), p_graphics_requirements)
#endif
EXT_PROTO_XRRESULT_FUNC4(xrEnumerateSwapchainImages, (XrSwapchain), p_swapchain, (uint32_t), p_image_capacity_input, (uint32_t *), p_image_count_output, (XrSwapchainImageBaseHeader *), p_images)
};
#endif // GLES3_ENABLED
#endif // OPENXR_OPENGL_EXTENSION_H

View file

@ -45,10 +45,40 @@
#include "extensions/openxr_android_extension.h"
#endif
// We need to have all the graphics API defines before the Vulkan or OpenGL
// extensions are included, otherwise we'll only get one graphics API.
#ifdef VULKAN_ENABLED
#define XR_USE_GRAPHICS_API_VULKAN
#endif
#ifdef GLES3_ENABLED
#ifdef ANDROID
#define XR_USE_GRAPHICS_API_OPENGL_ES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#define XR_USE_GRAPHICS_API_OPENGL
#endif // ANDROID
#ifdef X11_ENABLED
#include OPENGL_INCLUDE_H
#define GL_GLEXT_PROTOTYPES 1
#define GL3_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#endif // X11_ENABLED
#endif // GLES_ENABLED
#ifdef VULKAN_ENABLED
#include "extensions/openxr_vulkan_extension.h"
#endif
#ifdef GLES3_ENABLED
#include "extensions/openxr_opengl_extension.h"
#endif
#include "extensions/openxr_composition_layer_depth_extension.h"
#include "extensions/openxr_fb_display_refresh_rate_extension.h"
#include "extensions/openxr_fb_passthrough_extension_wrapper.h"
@ -1142,9 +1172,8 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) {
#endif
} else if (p_rendering_driver == "opengl3") {
#ifdef GLES3_ENABLED
// graphics_extension = memnew(OpenXROpenGLExtension(this));
// register_extension_wrapper(graphics_extension);
ERR_FAIL_V_MSG(false, "OpenXR: OpenGL is not supported at this time.");
graphics_extension = memnew(OpenXROpenGLExtension(this));
register_extension_wrapper(graphics_extension);
#else
// shouldn't be possible...
ERR_FAIL_V(false);

View file

@ -321,6 +321,11 @@ int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type,
case WINDOW_VIEW: {
return 0; // Not supported.
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
return eglGetCurrentContext();
}
#endif
default: {
return 0;
}

View file

@ -1309,6 +1309,11 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
case WINDOW_VIEW: {
return 0; // Not supported.
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
return (int64_t)gl_manager->get_glx_context(p_window);
}
#endif
default: {
return 0;
}

View file

@ -376,6 +376,17 @@ bool GLManager_X11::is_using_vsync() const {
return use_vsync;
}
void *GLManager_X11::get_glx_context(DisplayServer::WindowID p_window_id) {
if (p_window_id == -1) {
return nullptr;
}
const GLWindow &win = _windows[p_window_id];
const GLDisplay &disp = get_display(win.gldisplay_id);
return (void *)disp.context->glx_context;
}
GLManager_X11::GLManager_X11(const Vector2i &p_size, ContextType p_context_type) {
context_type = p_context_type;

View file

@ -116,6 +116,8 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
void *get_glx_context(DisplayServer::WindowID p_window_id);
GLManager_X11(const Vector2i &p_size, ContextType p_context_type);
~GLManager_X11();
};

View file

@ -2932,6 +2932,11 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W
case WINDOW_VIEW: {
return (int64_t)windows[p_window].window_view;
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
return (int64_t)gl_manager->get_context(p_window);
}
#endif
default: {
return 0;
}

View file

@ -89,6 +89,8 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
NSOpenGLContext *get_context(DisplayServer::WindowID p_window_id);
GLManager_MacOS(ContextType p_context_type);
~GLManager_MacOS();
};

View file

@ -215,6 +215,15 @@ bool GLManager_MacOS::is_using_vsync() const {
return use_vsync;
}
NSOpenGLContext *GLManager_MacOS::get_context(DisplayServer::WindowID p_window_id) {
if (!windows.has(p_window_id)) {
return nullptr;
}
GLWindow &win = windows[p_window_id];
return win.context;
}
GLManager_MacOS::GLManager_MacOS(ContextType p_context_type) {
context_type = p_context_type;
}

View file

@ -741,9 +741,14 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type,
case WINDOW_HANDLE: {
return (int64_t)windows[p_window].hWnd;
}
#if defined(GLES3_ENABLED)
case WINDOW_VIEW: {
return 0; // Not supported.
return (int64_t)gl_manager->get_hdc(p_window);
}
case OPENGL_CONTEXT: {
return (int64_t)gl_manager->get_hglrc(p_window);
}
#endif
default: {
return 0;
}

View file

@ -339,6 +339,16 @@ bool GLManager_Windows::is_using_vsync() const {
return use_vsync;
}
HDC GLManager_Windows::get_hdc(DisplayServer::WindowID p_window_id) {
return get_window(p_window_id).hDC;
}
HGLRC GLManager_Windows::get_hglrc(DisplayServer::WindowID p_window_id) {
const GLWindow &win = get_window(p_window_id);
const GLDisplay &disp = get_display(win.gldisplay_id);
return disp.hRC;
}
GLManager_Windows::GLManager_Windows(ContextType p_context_type) {
context_type = p_context_type;

View file

@ -113,6 +113,9 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
HDC get_hdc(DisplayServer::WindowID p_window_id);
HGLRC get_hglrc(DisplayServer::WindowID p_window_id);
GLManager_Windows(ContextType p_context_type);
~GLManager_Windows();
};

View file

@ -826,6 +826,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(DISPLAY_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_VIEW);
BIND_ENUM_CONSTANT(OPENGL_CONTEXT);
BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED);
BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED);

View file

@ -70,6 +70,7 @@ public:
DISPLAY_HANDLE,
WINDOW_HANDLE,
WINDOW_VIEW,
OPENGL_CONTEXT,
};
typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, Error &r_error);