summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Snopek <dsnopek@gmail.com>2022-10-22 20:29:15 -0500
committerDavid Snopek <dsnopek@gmail.com>2022-11-08 18:47:11 -0600
commit23603e409c04fd0238a45552ad7b07a175b528c6 (patch)
treed47525574fbccaaa60e50e84f29603945eef607d
parent6d9546f16c505186196da677154de5f216b7eb9b (diff)
Add support for OpenGL to OpenXR
-rw-r--r--doc/classes/DisplayServer.xml8
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp24
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.cpp62
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.h3
-rw-r--r--drivers/gles3/storage/texture_storage.cpp293
-rw-r--r--drivers/gles3/storage/texture_storage.h28
-rw-r--r--modules/openxr/SCsub2
-rw-r--r--modules/openxr/extensions/openxr_opengl_extension.cpp479
-rw-r--r--modules/openxr/extensions/openxr_opengl_extension.h120
-rw-r--r--modules/openxr/openxr_api.cpp35
-rw-r--r--platform/android/display_server_android.cpp5
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp5
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp11
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h2
-rw-r--r--platform/macos/display_server_macos.mm5
-rw-r--r--platform/macos/gl_manager_macos_legacy.h2
-rw-r--r--platform/macos/gl_manager_macos_legacy.mm9
-rw-r--r--platform/windows/display_server_windows.cpp7
-rw-r--r--platform/windows/gl_manager_windows.cpp10
-rw-r--r--platform/windows/gl_manager_windows.h3
-rw-r--r--servers/display_server.cpp1
-rw-r--r--servers/display_server.h1
22 files changed, 987 insertions, 128 deletions
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 113987bb52..76c67fd704 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -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>
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 2e8c95fe61..9737639129 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -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);
}
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
index b8e4530f56..e0e78de728 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
@@ -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
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.h b/drivers/gles3/storage/render_scene_buffers_gles3.h
index dbedbd22c3..092c14e1b8 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.h
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.h
@@ -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 {
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 11151c4100..e0457a8d28 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -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);
{
- /* Front FBO */
+ Texture *texture;
+ bool use_multiview = rt->view_count > 1 && config->multiview_supported;
+ GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
- Texture *texture = get_texture(rt->texture);
- ERR_FAIL_COND(!texture);
+ /* Front FBO */
- // 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);
-
- 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);
+ if (rt->overridden.color.is_valid()) {
+ texture = get_texture(rt->overridden.color);
+ ERR_FAIL_COND(!texture);
+
+ 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);
+ }
- if (rt->view_count > 1 && config->multiview_supported) {
+ 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_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);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 35fa16c894..5dff768bd7 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -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;
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub
index b5978ab134..84542be3b9 100644
--- a/modules/openxr/SCsub
+++ b/modules/openxr/SCsub
@@ -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")
diff --git a/modules/openxr/extensions/openxr_opengl_extension.cpp b/modules/openxr/extensions/openxr_opengl_extension.cpp
new file mode 100644
index 0000000000..a25727f885
--- /dev/null
+++ b/modules/openxr/extensions/openxr_opengl_extension.cpp
@@ -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
diff --git a/modules/openxr/extensions/openxr_opengl_extension.h b/modules/openxr/extensions/openxr_opengl_extension.h
new file mode 100644
index 0000000000..b666653c8e
--- /dev/null
+++ b/modules/openxr/extensions/openxr_opengl_extension.h
@@ -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
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 8b189cf027..88111afede 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -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);
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 08369e735d..967f5c7dae 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -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;
}
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index f477787771..c3a86c69e1 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -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;
}
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index f586c57dda..893a22e75e 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -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;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 4f78c45c88..1594c82801 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -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();
};
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 4478a635a8..33d8a8dd14 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -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;
}
diff --git a/platform/macos/gl_manager_macos_legacy.h b/platform/macos/gl_manager_macos_legacy.h
index 8752086551..d7ad5b1197 100644
--- a/platform/macos/gl_manager_macos_legacy.h
+++ b/platform/macos/gl_manager_macos_legacy.h
@@ -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();
};
diff --git a/platform/macos/gl_manager_macos_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm
index dec4821b86..ea5c36da6c 100644
--- a/platform/macos/gl_manager_macos_legacy.mm
+++ b/platform/macos/gl_manager_macos_legacy.mm
@@ -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;
}
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index d6ee712a31..2c8058fdc5 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -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;
}
diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp
index 7689751f1b..900bca8258 100644
--- a/platform/windows/gl_manager_windows.cpp
+++ b/platform/windows/gl_manager_windows.cpp
@@ -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;
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h
index 5e43a3de2a..c6d5f9f855 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows.h
@@ -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();
};
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 1897612562..52d7f66203 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -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);
diff --git a/servers/display_server.h b/servers/display_server.h
index 55e9fb55dc..a796377f88 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -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);