* Allocated on first access.
*/
GLuint tmp_tex;
+
+ /*
+ * Fence that gets inserted into GL stream
+ * that comes from windowing system.
+ *
+ * 0 if no GL commands are pending.
+ */
+ GLsync fence_2d;
+
+ /*
+ * Fence that gets inserted into GL stream
+ * that comes from 3D renderer.
+ *
+ * 0 if no GL commands are pending.
+ */
+ GLsync fence_3d;
};
static __inline struct vigs_winsys_gl_surface
gl_backend->Disable(GL_BLEND);
}
+static void vigs_gl_surface_set_fence_2d(struct vigs_gl_surface *gl_sfc)
+{
+ struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
+
+ if (!gl_backend->has_arb_sync) {
+ gl_backend->Finish();
+ return;
+ }
+
+ if (gl_sfc->fence_2d) {
+ gl_backend->DeleteSync(gl_sfc->fence_2d);
+ }
+
+ gl_sfc->fence_2d = gl_backend->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ gl_backend->Flush();
+}
+
+static void vigs_gl_surface_wait_fence_2d(struct vigs_gl_surface *gl_sfc)
+{
+ struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
+
+ if (!gl_backend->has_arb_sync) {
+ return;
+ }
+
+ if (gl_sfc->fence_2d) {
+ gl_backend->WaitSync(gl_sfc->fence_2d, 0, GL_TIMEOUT_IGNORED);
+ gl_backend->DeleteSync(gl_sfc->fence_2d);
+ gl_sfc->fence_2d = 0;
+ }
+}
+
+static void vigs_gl_surface_set_fence_3d(struct vigs_gl_surface *gl_sfc)
+{
+ struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
+
+ if (!gl_backend->has_arb_sync) {
+ gl_backend->Finish();
+ return;
+ }
+
+ if (gl_sfc->fence_3d) {
+ gl_backend->DeleteSync(gl_sfc->fence_3d);
+ }
+
+ gl_sfc->fence_3d = gl_backend->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ gl_backend->Flush();
+}
+
+static void vigs_gl_surface_wait_fence_3d(struct vigs_gl_surface *gl_sfc)
+{
+ struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
+
+ if (!gl_backend->has_arb_sync) {
+ return;
+ }
+
+ if (gl_sfc->fence_3d) {
+ gl_backend->WaitSync(gl_sfc->fence_3d, 0, GL_TIMEOUT_IGNORED);
+ gl_backend->DeleteSync(gl_sfc->fence_3d);
+ gl_sfc->fence_3d = 0;
+ }
+}
+
/*
* @}
*/
return;
}
+ vigs_gl_surface_wait_fence_2d(vigs_sfc->parent);
+
vigs_sfc->backend->GetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&cur_fb);
vigs_sfc->backend->BindFramebuffer(GL_READ_FRAMEBUFFER,
vigs_sfc->backend->BindFramebuffer(GL_FRAMEBUFFER,
cur_fb);
- vigs_sfc->backend->Finish();
+ vigs_gl_surface_set_fence_3d(vigs_sfc->parent);
vigs_sfc->parent->base.is_dirty = true;
}
return;
}
+ vigs_gl_surface_wait_fence_2d(vigs_target->parent);
+
vigs_target->backend->GetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&cur_fb);
vigs_target->backend->BindFramebuffer(GL_READ_FRAMEBUFFER,
vigs_target->backend->BindFramebuffer(GL_FRAMEBUFFER,
cur_fb);
- vigs_target->backend->Finish();
+ vigs_gl_surface_set_fence_3d(vigs_target->parent);
vigs_target->parent->base.is_dirty = true;
}
goto out;
}
+ vigs_gl_surface_wait_fence_3d(gl_sfc);
+
gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_sfc->fb);
vigs_gl_surface_setup_framebuffer(gl_sfc);
ws_sfc->tex_type,
data);
- gl_backend->Finish();
+ vigs_gl_surface_set_fence_2d(gl_sfc);
sfc->is_dirty = false;
goto out;
}
+ vigs_gl_surface_wait_fence_3d(gl_sfc);
+
gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_sfc->fb);
gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
src_w = gl_src->base.width;
src_h = gl_src->base.height;
+ vigs_gl_surface_wait_fence_3d(gl_src);
+ vigs_gl_surface_wait_fence_3d(gl_dst);
+
gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_dst->fb);
vigs_gl_surface_setup_framebuffer(gl_dst);
gl_backend->DisableClientState(GL_TEXTURE_COORD_ARRAY);
gl_backend->DisableClientState(GL_VERTEX_ARRAY);
- gl_backend->Finish();
+ vigs_gl_surface_set_fence_2d(gl_dst);
gl_dst->base.is_dirty = true;
goto out;
}
+ vigs_gl_surface_wait_fence_3d(gl_sfc);
+
gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_sfc->fb);
vigs_gl_surface_setup_framebuffer(gl_sfc);
gl_backend->DisableClientState(GL_VERTEX_ARRAY);
- gl_backend->Finish();
+ vigs_gl_surface_set_fence_2d(gl_sfc);
gl_sfc->base.is_dirty = true;
goto out;
}
+ vigs_gl_surface_wait_fence_3d(gl_sfc);
+
gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_sfc->fb);
vigs_gl_surface_setup_framebuffer(gl_sfc);
ws_sfc->tex_type,
src);
- gl_backend->Finish();
+ vigs_gl_surface_set_fence_2d(gl_sfc);
gl_sfc->base.is_dirty = true;
gl_backend->DeleteTextures(1, &gl_sfc->tmp_tex);
}
+ if (gl_backend->has_arb_sync) {
+ if (gl_sfc->fence_2d) {
+ gl_backend->DeleteSync(gl_sfc->fence_2d);
+ }
+ if (gl_sfc->fence_3d) {
+ gl_backend->DeleteSync(gl_sfc->fence_3d);
+ }
+ }
+
gl_backend->make_current(gl_backend, false);
}
goto fail;
}
+ /*
+ * ARB_sync is not mandatory, but if present gives additional
+ * performance.
+ */
+ gl_backend->has_arb_sync = (strstr(extensions, "GL_ARB_sync ") != NULL) &&
+ gl_backend->FenceSync &&
+ gl_backend->DeleteSync &&
+ gl_backend->WaitSync;
+ if (gl_backend->has_arb_sync) {
+ VIGS_LOG_INFO("ARB_sync supported");
+ } else {
+ VIGS_LOG_WARN("ARB_sync not supported!");
+ }
+
gl_backend->base.create_surface = &vigs_gl_backend_create_surface;
gl_backend->make_current(gl_backend, false);
#include "vigs_backend.h"
#include "vigs_vector.h"
#include <GL/gl.h>
+#include <GL/glext.h>
#include "winsys_gl.h"
struct vigs_gl_backend
bool (*make_current)(struct vigs_gl_backend */*gl_backend*/,
bool /*enable*/);
+ /*
+ * Mandatory GL functions and extensions.
+ * @{
+ */
+
void (GLAPIENTRY *GenTextures)(GLsizei n, GLuint *textures);
void (GLAPIENTRY *DeleteTextures)(GLsizei n, const GLuint *textures);
void (GLAPIENTRY *BindTexture)(GLenum target, GLuint texture);
void (GLAPIENTRY *BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
/*
+ * @}
+ */
+
+ /*
+ * Optional GL extensions.
+ * @{
+ */
+
+ GLsync (GLAPIENTRY *FenceSync)(GLenum condition, GLbitfield flags);
+ void (GLAPIENTRY *DeleteSync)(GLsync sync);
+ void (GLAPIENTRY *WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+ /*
+ * @}
+ */
+
+ /*
* General purpose vectors.
* @{
*/
/*
* @}
*/
+
+ bool has_arb_sync;
};
bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend);