Add off-screen GL context
This commit is contained in:
parent
25f01cb09d
commit
abdf931832
25 changed files with 252 additions and 23 deletions
|
@ -719,6 +719,12 @@ const char *OS::get_video_driver_name(int p_driver) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool OS::is_offscreen_gl_available() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OS::set_offscreen_gl_current(bool p_current) {}
|
||||
|
||||
int OS::get_audio_driver_count() const {
|
||||
return AudioDriverManager::get_driver_count();
|
||||
}
|
||||
|
|
|
@ -191,6 +191,9 @@ public:
|
|||
virtual const char *get_video_driver_name(int p_driver) const;
|
||||
virtual int get_current_video_driver() const = 0;
|
||||
|
||||
virtual bool is_offscreen_gl_available() const;
|
||||
virtual void set_offscreen_gl_current(bool p_current);
|
||||
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||
|
||||
|
|
|
@ -407,6 +407,18 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
}
|
||||
}
|
||||
|
||||
public boolean createOffscreenGL() {
|
||||
return mView.createOffscreenGL();
|
||||
}
|
||||
|
||||
public void destroyOffscreenGL() {
|
||||
mView.destroyOffscreenGL();
|
||||
}
|
||||
|
||||
public void setOffscreenGLCurrent(boolean p_current) {
|
||||
mView.setOffscreenGLCurrent(p_current);
|
||||
}
|
||||
|
||||
public void setKeepScreenOn(final boolean p_enabled) {
|
||||
runOnUiThread(() -> {
|
||||
if (p_enabled) {
|
||||
|
|
|
@ -72,10 +72,9 @@ public class GodotLib {
|
|||
|
||||
/**
|
||||
* Invoked on the GL thread when the underlying Android surface is created or recreated.
|
||||
* @param p_32_bits
|
||||
* @see android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(GL10, EGLConfig)
|
||||
*/
|
||||
public static native void newcontext(boolean p_32_bits);
|
||||
public static native void newcontext();
|
||||
|
||||
/**
|
||||
* Forward {@link Activity#onBackPressed()} event from the main thread to the GL thread.
|
||||
|
|
|
@ -76,7 +76,7 @@ class GodotRenderer implements GLSurfaceView.Renderer {
|
|||
}
|
||||
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
GodotLib.newcontext(GLUtils.use_32);
|
||||
GodotLib.newcontext();
|
||||
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||
plugin.onGLSurfaceCreated(gl, config);
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ import android.view.GestureDetector;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
|
||||
/**
|
||||
* A simple GLSurfaceView sub-class that demonstrate how to perform
|
||||
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
|
||||
|
@ -75,6 +79,10 @@ public class GodotView extends GLSurfaceView {
|
|||
private final GestureDetector detector;
|
||||
private final GodotRenderer godotRenderer;
|
||||
|
||||
private EGLConfigChooser eglConfigChooser;
|
||||
private EGLContextFactory eglContextFactory;
|
||||
private EGLContext eglSecondaryContext;
|
||||
|
||||
public GodotView(Context context, Godot godot, XRMode xrMode, boolean p_use_gl3,
|
||||
boolean p_use_32_bits, boolean p_use_debug_opengl, boolean p_translucent) {
|
||||
super(context);
|
||||
|
@ -123,10 +131,10 @@ public class GodotView extends GLSurfaceView {
|
|||
switch (xrMode) {
|
||||
case OVR:
|
||||
// Replace the default egl config chooser.
|
||||
setEGLConfigChooser(new OvrConfigChooser());
|
||||
eglConfigChooser = new OvrConfigChooser();
|
||||
|
||||
// Replace the default context factory.
|
||||
setEGLContextFactory(new OvrContextFactory());
|
||||
eglContextFactory = new OvrContextFactory();
|
||||
|
||||
// Replace the default window surface factory.
|
||||
setEGLWindowSurfaceFactory(new OvrWindowSurfaceFactory());
|
||||
|
@ -147,7 +155,7 @@ public class GodotView extends GLSurfaceView {
|
|||
/* Setup the context factory for 2.0 rendering.
|
||||
* See ContextFactory class definition below
|
||||
*/
|
||||
setEGLContextFactory(new RegularContextFactory());
|
||||
eglContextFactory = new RegularContextFactory();
|
||||
|
||||
/* We need to choose an EGLConfig that matches the format of
|
||||
* our surface exactly. This is going to be done in our
|
||||
|
@ -156,24 +164,49 @@ public class GodotView extends GLSurfaceView {
|
|||
*/
|
||||
|
||||
if (GLUtils.use_32) {
|
||||
setEGLConfigChooser(translucent
|
||||
eglConfigChooser = translucent
|
||||
? new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil,
|
||||
new RegularConfigChooser(8, 8, 8, 8, 16, stencil))
|
||||
: new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil,
|
||||
new RegularConfigChooser(5, 6, 5, 0, 16, stencil)));
|
||||
new RegularConfigChooser(5, 6, 5, 0, 16, stencil));
|
||||
|
||||
} else {
|
||||
setEGLConfigChooser(translucent
|
||||
eglConfigChooser = translucent
|
||||
? new RegularConfigChooser(8, 8, 8, 8, 16, stencil)
|
||||
: new RegularConfigChooser(5, 6, 5, 0, 16, stencil));
|
||||
: new RegularConfigChooser(5, 6, 5, 0, 16, stencil);
|
||||
}
|
||||
break;
|
||||
}
|
||||
setEGLConfigChooser(eglConfigChooser);
|
||||
setEGLContextFactory(eglContextFactory);
|
||||
|
||||
/* Set the renderer responsible for frame rendering */
|
||||
setRenderer(godotRenderer);
|
||||
}
|
||||
|
||||
public boolean createOffscreenGL() {
|
||||
EGL10 egl = (EGL10)EGLContext.getEGL();
|
||||
EGLConfig eglConfig = eglConfigChooser.chooseConfig(egl, egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY));
|
||||
eglSecondaryContext = eglContextFactory.createContext(egl, egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY), eglConfig);
|
||||
if (eglSecondaryContext == EGL10.EGL_NO_CONTEXT) {
|
||||
eglSecondaryContext = null;
|
||||
}
|
||||
return eglSecondaryContext != null;
|
||||
}
|
||||
|
||||
public void setOffscreenGLCurrent(boolean p_current) {
|
||||
EGL10 egl = (EGL10)EGLContext.getEGL();
|
||||
egl.eglMakeCurrent(egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY), EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, p_current ? eglSecondaryContext : EGL10.EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
public void destroyOffscreenGL() {
|
||||
if (eglSecondaryContext != null) {
|
||||
EGL10 egl = (EGL10)EGLContext.getEGL();
|
||||
eglContextFactory.destroyContext(egl, egl.eglGetCurrentDisplay(), eglSecondaryContext);
|
||||
eglSecondaryContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
godot.onBackPressed();
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env
|
|||
delete godot_io_java;
|
||||
}
|
||||
if (godot_java) {
|
||||
godot_java->destroy_offscreen_gl(env);
|
||||
delete godot_java;
|
||||
}
|
||||
if (input_handler) {
|
||||
|
@ -212,11 +213,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j
|
|||
os_android->set_display_size(Size2(width, height));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits) {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz) {
|
||||
if (os_android) {
|
||||
if (step.get() == 0) {
|
||||
// During startup
|
||||
os_android->set_context_is_16_bits(!p_32_bits);
|
||||
os_android->set_offscreen_gl_available(godot_java->create_offscreen_gl(env));
|
||||
} else {
|
||||
// GL context recreated because it was lost; restart app to let it reload everything
|
||||
step.set(-1); // Ensure no further steps are attempted and no further events are sent
|
||||
|
|
|
@ -41,7 +41,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
|
|||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
|
||||
void touch_preprocessing(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask = 0, jfloat vertical_factor = 0, jfloat horizontal_factor = 0);
|
||||
|
|
|
@ -59,6 +59,9 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
|
|||
|
||||
// get some Godot method pointers...
|
||||
_on_video_init = p_env->GetMethodID(godot_class, "onVideoInit", "()V");
|
||||
_create_offscreen_gl = p_env->GetMethodID(godot_class, "createOffscreenGL", "()Z");
|
||||
_destroy_offscreen_gl = p_env->GetMethodID(godot_class, "destroyOffscreenGL", "()V");
|
||||
_set_offscreen_gl_current = p_env->GetMethodID(godot_class, "setOffscreenGLCurrent", "(Z)V");
|
||||
_restart = p_env->GetMethodID(godot_class, "restart", "()V");
|
||||
_finish = p_env->GetMethodID(godot_class, "forceQuit", "()V");
|
||||
_set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V");
|
||||
|
@ -131,6 +134,29 @@ void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
|
|||
}
|
||||
}
|
||||
|
||||
bool GodotJavaWrapper::create_offscreen_gl(JNIEnv *p_env) {
|
||||
if (_create_offscreen_gl) {
|
||||
return p_env->CallBooleanMethod(godot_instance, _create_offscreen_gl);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::destroy_offscreen_gl(JNIEnv *p_env) {
|
||||
if (_destroy_offscreen_gl) {
|
||||
p_env->CallBooleanMethod(godot_instance, _destroy_offscreen_gl);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::set_offscreen_gl_current(JNIEnv *p_env, bool p_current) {
|
||||
if (_set_offscreen_gl_current) {
|
||||
if (p_env == NULL)
|
||||
p_env = get_jni_env();
|
||||
ERR_FAIL_COND(p_env == nullptr);
|
||||
p_env->CallVoidMethod(godot_instance, _set_offscreen_gl_current, p_current);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::on_godot_setup_completed(JNIEnv *p_env) {
|
||||
if (_on_godot_setup_completed) {
|
||||
if (p_env == NULL) {
|
||||
|
|
|
@ -48,6 +48,9 @@ private:
|
|||
jclass activity_class;
|
||||
|
||||
jmethodID _on_video_init = 0;
|
||||
jmethodID _create_offscreen_gl = 0;
|
||||
jmethodID _destroy_offscreen_gl = 0;
|
||||
jmethodID _set_offscreen_gl_current = 0;
|
||||
jmethodID _restart = 0;
|
||||
jmethodID _finish = 0;
|
||||
jmethodID _set_keep_screen_on = 0;
|
||||
|
@ -77,6 +80,9 @@ public:
|
|||
jobject get_class_loader();
|
||||
|
||||
void gfx_init(bool gl2);
|
||||
bool create_offscreen_gl(JNIEnv *p_env);
|
||||
void destroy_offscreen_gl(JNIEnv *p_env);
|
||||
void set_offscreen_gl_current(JNIEnv *p_env, bool p_current);
|
||||
void on_video_init(JNIEnv *p_env = NULL);
|
||||
void on_godot_setup_completed(JNIEnv *p_env = NULL);
|
||||
void on_godot_main_loop_started(JNIEnv *p_env = NULL);
|
||||
|
|
|
@ -484,10 +484,18 @@ String OS_Android::get_system_dir(SystemDir p_dir, bool p_shared_storage) const
|
|||
return godot_io_java->get_system_dir(p_dir, p_shared_storage);
|
||||
}
|
||||
|
||||
void OS_Android::set_context_is_16_bits(bool p_is_16) {
|
||||
//use_16bits_fbo = p_is_16;
|
||||
//if (rasterizer)
|
||||
// rasterizer->set_force_16_bits_fbo(p_is_16);
|
||||
void OS_Android::set_offscreen_gl_available(bool p_available) {
|
||||
secondary_gl_available = p_available;
|
||||
}
|
||||
|
||||
bool OS_Android::is_offscreen_gl_available() const {
|
||||
return secondary_gl_available;
|
||||
}
|
||||
|
||||
void OS_Android::set_offscreen_gl_current(bool p_current) {
|
||||
if (secondary_gl_available) {
|
||||
godot_java->set_offscreen_gl_current(nullptr, p_current);
|
||||
}
|
||||
}
|
||||
|
||||
bool OS_Android::is_joy_known(int p_device) {
|
||||
|
|
|
@ -45,7 +45,7 @@ class OS_Android : public OS_Unix {
|
|||
bool use_gl2;
|
||||
bool use_apk_expansion;
|
||||
|
||||
bool use_16bits_fbo;
|
||||
bool secondary_gl_available = false;
|
||||
|
||||
VisualServer *visual_server;
|
||||
|
||||
|
@ -137,7 +137,9 @@ public:
|
|||
void set_opengl_extensions(const char *p_gl_extensions);
|
||||
void set_display_size(Size2 p_size);
|
||||
|
||||
void set_context_is_16_bits(bool p_is_16);
|
||||
void set_offscreen_gl_available(bool p_available);
|
||||
virtual bool is_offscreen_gl_available() const;
|
||||
virtual void set_offscreen_gl_current(bool p_current);
|
||||
|
||||
virtual void set_screen_orientation(ScreenOrientation p_orientation);
|
||||
virtual ScreenOrientation get_screen_orientation() const;
|
||||
|
|
|
@ -53,6 +53,7 @@ bool gles3_available = true;
|
|||
GLint backingHeight;
|
||||
|
||||
EAGLContext *context;
|
||||
EAGLContext *context_offscreen;
|
||||
GLuint viewRenderbuffer, viewFramebuffer;
|
||||
GLuint depthRenderbuffer;
|
||||
}
|
||||
|
@ -75,6 +76,9 @@ bool gles3_available = true;
|
|||
gles3_available = false;
|
||||
fallback_gl2 = true;
|
||||
NSLog(@"Failed to create OpenGL ES 3.0 context. Falling back to OpenGL ES 2.0");
|
||||
} else {
|
||||
context_offscreen = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
|
||||
OSIPhone::get_singleton()->set_offscreen_gl_context(context_offscreen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +134,9 @@ bool gles3_available = true;
|
|||
if (context) {
|
||||
context = nil;
|
||||
}
|
||||
if (context_offscreen) {
|
||||
context_offscreen = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)createFramebuffer {
|
||||
|
|
|
@ -61,6 +61,8 @@ private:
|
|||
|
||||
VideoMode video_mode;
|
||||
|
||||
EAGLContext *offscreen_gl_context;
|
||||
|
||||
virtual int get_video_driver_count() const;
|
||||
virtual const char *get_video_driver_name(int p_driver) const;
|
||||
|
||||
|
@ -162,6 +164,10 @@ public:
|
|||
|
||||
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
|
||||
|
||||
void set_offscreen_gl_context(EAGLContext *p_context);
|
||||
virtual bool is_offscreen_gl_available() const;
|
||||
virtual void set_offscreen_gl_current(bool p_current);
|
||||
|
||||
virtual void set_keep_screen_on(bool p_enabled);
|
||||
|
||||
virtual bool can_draw() const;
|
||||
|
|
|
@ -417,6 +417,22 @@ void OSIPhone::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) c
|
|||
p_list->push_back(video_mode);
|
||||
}
|
||||
|
||||
void OSIPhone::set_offscreen_gl_context(EAGLContext *p_context) {
|
||||
offscreen_gl_context = p_context;
|
||||
}
|
||||
|
||||
bool OSIPhone::is_offscreen_gl_available() const {
|
||||
return offscreen_gl_context;
|
||||
}
|
||||
|
||||
void OSIPhone::set_offscreen_gl_current(bool p_current) {
|
||||
if (p_current) {
|
||||
[EAGLContext setCurrentContext:offscreen_gl_context];
|
||||
} else {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
bool OSIPhone::can_draw() const {
|
||||
if (native_video_is_playing())
|
||||
return false;
|
||||
|
@ -683,6 +699,7 @@ OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) {
|
|||
|
||||
main_loop = NULL;
|
||||
visual_server = NULL;
|
||||
offscreen_gl_context = NULL;
|
||||
|
||||
// can't call set_data_dir from here, since it requires DirAccess
|
||||
// which is initialized in initialize_core
|
||||
|
|
|
@ -115,6 +115,7 @@ public:
|
|||
id cursor;
|
||||
NSOpenGLPixelFormat *pixelFormat;
|
||||
NSOpenGLContext *context;
|
||||
NSOpenGLContext *context_offscreen;
|
||||
|
||||
Vector<Vector2> mpath;
|
||||
bool layered_window;
|
||||
|
@ -250,6 +251,9 @@ public:
|
|||
virtual VideoMode get_video_mode(int p_screen = 0) const;
|
||||
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
|
||||
|
||||
virtual bool is_offscreen_gl_available() const;
|
||||
virtual void set_offscreen_gl_current(bool p_current);
|
||||
|
||||
virtual String get_executable_path() const;
|
||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
|
||||
|
||||
|
|
|
@ -1666,6 +1666,8 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
|
|||
|
||||
[window_view setOpenGLContext:context];
|
||||
|
||||
context_offscreen = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
|
||||
|
||||
[context makeCurrentContext];
|
||||
|
||||
GLint dim[2];
|
||||
|
@ -2427,6 +2429,18 @@ OS::VideoMode OS_OSX::get_video_mode(int p_screen) const {
|
|||
void OS_OSX::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
|
||||
}
|
||||
|
||||
bool OS_OSX::is_offscreen_gl_available() const {
|
||||
return context_offscreen != nil;
|
||||
}
|
||||
|
||||
void OS_OSX::set_offscreen_gl_current(bool p_current) {
|
||||
if (p_current) {
|
||||
[context makeCurrentContext];
|
||||
} else {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
}
|
||||
|
||||
int OS_OSX::get_screen_count() const {
|
||||
NSArray *screenArray = [NSScreen screens];
|
||||
return [screenArray count];
|
||||
|
@ -3426,6 +3440,7 @@ OS_OSX *OS_OSX::singleton = NULL;
|
|||
|
||||
OS_OSX::OS_OSX() {
|
||||
context = nullptr;
|
||||
context_offscreen = nullptr;
|
||||
|
||||
memset(cursors, 0, sizeof(cursors));
|
||||
key_event_pos = 0;
|
||||
|
|
|
@ -58,6 +58,18 @@ void ContextGL_Windows::make_current() {
|
|||
wglMakeCurrent(hDC, hRC);
|
||||
}
|
||||
|
||||
bool ContextGL_Windows::is_offscreen_available() const {
|
||||
return hRC_offscreen != NULL;
|
||||
}
|
||||
|
||||
void ContextGL_Windows::make_offscreen_current() {
|
||||
ERR_FAIL_COND(!wglMakeCurrent(hDC, hRC_offscreen));
|
||||
}
|
||||
|
||||
void ContextGL_Windows::release_offscreen_current() {
|
||||
ERR_FAIL_COND(!wglMakeCurrent(hDC, NULL));
|
||||
}
|
||||
|
||||
HDC ContextGL_Windows::get_hdc() {
|
||||
return hDC;
|
||||
}
|
||||
|
@ -205,6 +217,8 @@ Error ContextGL_Windows::initialize() {
|
|||
{
|
||||
return ERR_CANT_CREATE; // Return FALSE
|
||||
}
|
||||
|
||||
hRC_offscreen = wglCreateContextAttribsARB(hDC, 0, attribs);
|
||||
}
|
||||
|
||||
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
|
||||
|
@ -217,6 +231,7 @@ Error ContextGL_Windows::initialize() {
|
|||
ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) {
|
||||
opengl_3_context = p_opengl_3_context;
|
||||
hWnd = hwnd;
|
||||
hRC_offscreen = NULL;
|
||||
use_vsync = false;
|
||||
vsync_via_compositor = false;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef int(APIENTRY *PFNWGLGETSWAPINTERVALEXTPROC)(void);
|
|||
class ContextGL_Windows {
|
||||
HDC hDC;
|
||||
HGLRC hRC;
|
||||
HGLRC hRC_offscreen;
|
||||
unsigned int pixel_format;
|
||||
HWND hWnd;
|
||||
bool opengl_3_context;
|
||||
|
@ -63,6 +64,10 @@ public:
|
|||
|
||||
void make_current();
|
||||
|
||||
bool is_offscreen_available() const;
|
||||
void make_offscreen_current();
|
||||
void release_offscreen_current();
|
||||
|
||||
HDC get_hdc();
|
||||
HGLRC get_hglrc();
|
||||
|
||||
|
|
|
@ -1672,6 +1672,24 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
|
|||
return OK;
|
||||
}
|
||||
|
||||
bool OS_Windows::is_offscreen_gl_available() const {
|
||||
#if defined(OPENGL_ENABLED)
|
||||
return gl_context->is_offscreen_available();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS_Windows::set_offscreen_gl_current(bool p_current) {
|
||||
#if defined(OPENGL_ENABLED)
|
||||
if (p_current) {
|
||||
return gl_context->make_offscreen_current();
|
||||
} else {
|
||||
return gl_context->release_offscreen_current();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS_Windows::set_clipboard(const String &p_text) {
|
||||
// Convert LF line endings to CRLF in clipboard content
|
||||
// Otherwise, line endings won't be visible when pasted in other software
|
||||
|
|
|
@ -386,6 +386,9 @@ protected:
|
|||
virtual void initialize_core();
|
||||
virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
|
||||
virtual bool is_offscreen_gl_available() const;
|
||||
virtual void set_offscreen_gl_current(bool p_current);
|
||||
|
||||
virtual void set_main_loop(MainLoop *p_main_loop);
|
||||
virtual void delete_main_loop();
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLX
|
|||
|
||||
struct ContextGL_X11_Private {
|
||||
::GLXContext glx_context;
|
||||
::GLXContext glx_context_offscreen;
|
||||
};
|
||||
|
||||
void ContextGL_X11::release_current() {
|
||||
|
@ -57,6 +58,18 @@ void ContextGL_X11::make_current() {
|
|||
glXMakeCurrent(x11_display, x11_window, p->glx_context);
|
||||
}
|
||||
|
||||
bool ContextGL_X11::is_offscreen_available() const {
|
||||
return p->glx_context_offscreen;
|
||||
}
|
||||
|
||||
void ContextGL_X11::make_offscreen_current() {
|
||||
glXMakeCurrent(x11_display, x11_window, p->glx_context_offscreen);
|
||||
}
|
||||
|
||||
void ContextGL_X11::release_offscreen_current() {
|
||||
glXMakeCurrent(x11_display, None, NULL);
|
||||
}
|
||||
|
||||
void ContextGL_X11::swap_buffers() {
|
||||
glXSwapBuffers(x11_display, x11_window);
|
||||
}
|
||||
|
@ -181,6 +194,7 @@ Error ContextGL_X11::initialize() {
|
|||
|
||||
p->glx_context = glXCreateContextAttribsARB(x11_display, fbconfig, nullptr, true, context_attribs);
|
||||
ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED);
|
||||
p->glx_context_offscreen = glXCreateContextAttribsARB(x11_display, fbconfig, nullptr, true, context_attribs);
|
||||
} break;
|
||||
}
|
||||
|
||||
|
@ -275,12 +289,16 @@ ContextGL_X11::ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, c
|
|||
glx_minor = glx_major = 0;
|
||||
p = memnew(ContextGL_X11_Private);
|
||||
p->glx_context = nullptr;
|
||||
p->glx_context_offscreen = nullptr;
|
||||
use_vsync = false;
|
||||
}
|
||||
|
||||
ContextGL_X11::~ContextGL_X11() {
|
||||
release_current();
|
||||
glXDestroyContext(x11_display, p->glx_context);
|
||||
if (p->glx_context_offscreen) {
|
||||
glXDestroyContext(x11_display, p->glx_context_offscreen);
|
||||
}
|
||||
memdelete(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,10 @@ public:
|
|||
int get_window_height();
|
||||
void *get_glx_context();
|
||||
|
||||
bool is_offscreen_available() const;
|
||||
void make_offscreen_current();
|
||||
void release_offscreen_current();
|
||||
|
||||
Error initialize();
|
||||
|
||||
void set_use_vsync(bool p_use);
|
||||
|
|
|
@ -869,6 +869,24 @@ void OS_X11::finalize() {
|
|||
args.clear();
|
||||
}
|
||||
|
||||
bool OS_X11::is_offscreen_gl_available() const {
|
||||
#if defined(OPENGL_ENABLED)
|
||||
return context_gl->is_offscreen_available();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS_X11::set_offscreen_gl_current(bool p_current) {
|
||||
#if defined(OPENGL_ENABLED)
|
||||
if (p_current) {
|
||||
return context_gl->make_offscreen_current();
|
||||
} else {
|
||||
return context_gl->release_offscreen_current();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS_X11::set_mouse_mode(MouseMode p_mode) {
|
||||
if (p_mode == mouse_mode) {
|
||||
return;
|
||||
|
|
|
@ -239,6 +239,9 @@ protected:
|
|||
virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
virtual void finalize();
|
||||
|
||||
virtual bool is_offscreen_gl_available() const;
|
||||
virtual void set_offscreen_gl_current(bool p_current);
|
||||
|
||||
virtual void set_main_loop(MainLoop *p_main_loop);
|
||||
|
||||
void _window_changed(XEvent *event);
|
||||
|
|
Loading…
Reference in a new issue