Commit dc5bb38a authored by Christoph Haag's avatar Christoph Haag Committed by Lubosz Sarnecki

window: dynamically allocate XrdWindowData & persist during overlay scene switch

parent 30930287
......@@ -146,6 +146,11 @@ _desktop_window_process_frame (Example *self, DesktopWindow *desktop_window)
{
XrdWindow *xrd_window = xrd_client_lookup_window (self->client,
desktop_window);
if (!xrd_window)
{
g_print ("Error processing frame, window is NULL\n");
return TRUE;
}
WindowWrapper *window_wrapper;
g_object_get (xrd_window, "native", &window_wrapper, NULL);
......@@ -393,6 +398,8 @@ _cleanup (Example *self)
WindowWrapper *example_window;
g_object_get (window, "native", &example_window, NULL);
g_object_unref (example_window->gulkan_texture);
xrd_window_close (window);
}
g_object_unref (self->window_pixbuf);
......
......@@ -18,7 +18,7 @@ struct _XrdOverlayWindow
OpenVROverlay parent;
gboolean recreate;
XrdWindowData window_data;
XrdWindowData *window_data;
};
enum
......@@ -50,27 +50,27 @@ xrd_overlay_window_set_property (GObject *object,
switch (property_id)
{
case PROP_TITLE:
if (self->window_data.title)
g_string_free (self->window_data.title, TRUE);
self->window_data.title = g_string_new (g_value_get_string (value));
if (self->window_data->title)
g_string_free (self->window_data->title, TRUE);
self->window_data->title = g_string_new (g_value_get_string (value));
break;
case PROP_SCALE:
self->window_data.scale = g_value_get_float (value);
self->window_data->scale = g_value_get_float (value);
break;
case PROP_NATIVE:
self->window_data.native = g_value_get_pointer (value);
self->window_data->native = g_value_get_pointer (value);
break;
case PROP_TEXTURE_WIDTH:
self->window_data.texture_width = g_value_get_uint (value);
self->window_data->texture_width = g_value_get_uint (value);
break;
case PROP_TEXTURE_HEIGHT:
self->window_data.texture_height = g_value_get_uint (value);
self->window_data->texture_height = g_value_get_uint (value);
break;
case PROP_WIDTH_METERS:
self->window_data.initial_size_meters.x = g_value_get_float (value);
self->window_data->initial_size_meters.x = g_value_get_float (value);
break;
case PROP_HEIGHT_METERS:
self->window_data.initial_size_meters.y = g_value_get_float (value);
self->window_data->initial_size_meters.y = g_value_get_float (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
......@@ -89,25 +89,25 @@ xrd_overlay_window_get_property (GObject *object,
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, self->window_data.title->str);
g_value_set_string (value, self->window_data->title->str);
break;
case PROP_SCALE:
g_value_set_float (value, self->window_data.scale);
g_value_set_float (value, self->window_data->scale);
break;
case PROP_NATIVE:
g_value_set_pointer (value, self->window_data.native);
g_value_set_pointer (value, self->window_data->native);
break;
case PROP_TEXTURE_WIDTH:
g_value_set_uint (value, self->window_data.texture_width);
g_value_set_uint (value, self->window_data->texture_width);
break;
case PROP_TEXTURE_HEIGHT:
g_value_set_uint (value, self->window_data.texture_height);
g_value_set_uint (value, self->window_data->texture_height);
break;
case PROP_WIDTH_METERS:
g_value_set_float (value, self->window_data.initial_size_meters.x);
g_value_set_float (value, self->window_data->initial_size_meters.x);
break;
case PROP_HEIGHT_METERS:
g_value_set_float (value, self->window_data.initial_size_meters.y);
g_value_set_float (value, self->window_data->initial_size_meters.y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
......@@ -129,7 +129,7 @@ _update_dimensions (XrdOverlayWindow *self)
openvr_overlay_set_mouse_scale (OPENVR_OVERLAY (self), w, h);
if (self->window_data.child_window)
if (self->window_data->child_window)
xrd_window_update_child (XRD_WINDOW (self));
}
......@@ -177,8 +177,14 @@ _set_transformation (XrdWindow *window,
XrdOverlayWindow *self = XRD_OVERLAY_WINDOW (window);
gboolean res =
openvr_overlay_set_transform_absolute (OPENVR_OVERLAY (self), mat);
if (self->window_data.child_window)
if (self->window_data->child_window)
xrd_window_update_child (window);
XrdWindowData *data = xrd_window_get_data (window);
graphene_matrix_t transform_unscaled;
xrd_window_get_transformation_no_scale (window, &transform_unscaled);
graphene_matrix_init_from_matrix (&data->transform, &transform_unscaled);
return res;
}
......@@ -242,7 +248,10 @@ _submit_texture (XrdWindow *window,
guint new_width = gulkan_texture_get_width (texture);
guint new_height = gulkan_texture_get_height (texture);
if (current_width != new_width || current_height != new_height)
/* update overlay if there is no texture, even if the texture dims
* are already the same */
if (!self->window_data->texture ||
current_width != new_width || current_height != new_height)
{
g_object_set (self,
"texture-width", new_width,
......@@ -262,10 +271,10 @@ _submit_texture (XrdWindow *window,
openvr_overlay_submit_texture (OPENVR_OVERLAY (self), client, texture);
/* let the previous texture stay alive until this one has been submitted */
if (self->window_data.texture)
g_object_unref (self->window_data.texture);
self->window_data.texture = texture;
g_object_ref (self->window_data.texture);
if (self->window_data->texture)
g_object_unref (self->window_data->texture);
self->window_data->texture = texture;
g_object_ref (self->window_data->texture);
}
static void
......@@ -289,15 +298,18 @@ _poll_event (XrdWindow *window)
static void
xrd_overlay_window_init (XrdOverlayWindow *self)
{
self->window_data.title = NULL;
self->window_data.child_window = NULL;
self->window_data.parent_window = NULL;
self->window_data.native = NULL;
self->window_data.texture_width = 0;
self->window_data.texture_height = 0;
self->window_data.texture = NULL;
self->window_data.selected = FALSE;
graphene_matrix_init_identity (&self->window_data.reset_transform);
self->window_data = g_malloc (sizeof (XrdWindowData));
self->window_data->title = NULL;
self->window_data->child_window = NULL;
self->window_data->parent_window = NULL;
self->window_data->native = NULL;
self->window_data->texture_width = 0;
self->window_data->texture_height = 0;
self->window_data->texture = NULL;
self->window_data->selected = FALSE;
self->window_data->xrd_window = XRD_WINDOW (self);
self->window_data->pinned = FALSE;
graphene_matrix_init_identity (&self->window_data->reset_transform);
}
/** xrd_overlay_window_new:
......@@ -328,6 +340,21 @@ xrd_overlay_window_new_from_meters (const gchar *title,
return window;
}
XrdOverlayWindow *
xrd_overlay_window_new_from_data (XrdWindowData *data)
{
XrdOverlayWindow *window =
(XrdOverlayWindow*) g_object_new (XRD_TYPE_OVERLAY_WINDOW, NULL);
// TODO: avoid unnecessary allocation
g_free (window->window_data);
window->window_data = data;
_set_transformation (XRD_WINDOW (window), &data->transform);
return window;
}
XrdOverlayWindow *
xrd_overlay_window_new_from_pixels (const gchar *title,
......@@ -380,7 +407,7 @@ xrd_overlay_window_constructed (GObject *gobject)
g_sprintf (overlay_id_str, "xrd-window-%d", iface->windows_created);
openvr_overlay_create (OPENVR_OVERLAY (self), overlay_id_str,
self->window_data.title->str);
self->window_data->title->str);
/* g_print ("Created overlay %s\n", overlay_id_str); */
......@@ -404,23 +431,6 @@ xrd_overlay_window_constructed (GObject *gobject)
static void
xrd_overlay_window_finalize (GObject *gobject)
{
XrdOverlayWindow *self = XRD_OVERLAY_WINDOW (gobject);
XrdOverlayWindow *parent =
XRD_OVERLAY_WINDOW (self->window_data.parent_window);
if (parent != NULL)
parent->window_data.child_window = NULL;
XrdOverlayWindow *child = XRD_OVERLAY_WINDOW (self->window_data.child_window);
if (child)
child->window_data.parent_window = NULL;
if (self->window_data.texture)
g_object_unref (self->window_data.texture);
g_string_free (self->window_data.title, TRUE);
G_OBJECT_CLASS (xrd_overlay_window_parent_class)->finalize (gobject);
}
......@@ -428,7 +438,7 @@ static XrdWindowData*
_get_data (XrdWindow *window)
{
XrdOverlayWindow *self = XRD_OVERLAY_WINDOW (window);
return &self->window_data;
return self->window_data;
}
static void
......
......@@ -34,6 +34,9 @@ xrd_overlay_window_new_from_meters (const gchar *title,
float height,
float ppm);
XrdOverlayWindow *
xrd_overlay_window_new_from_data (XrdWindowData *data);
XrdOverlayWindow *
xrd_overlay_window_new_from_pixels (const gchar *title,
uint32_t width,
......
......@@ -45,7 +45,7 @@ typedef struct _XrdSceneWindowPrivate
GulkanUniformBuffer *shading_buffer;
XrdWindowUniformBuffer shading_buffer_data;
XrdWindowData window_data;
XrdWindowData *window_data;
} XrdSceneWindowPrivate;
G_DEFINE_TYPE_WITH_CODE (XrdSceneWindow, xrd_scene_window, XRD_TYPE_SCENE_OBJECT,
......@@ -65,27 +65,27 @@ xrd_scene_window_set_property (GObject *object,
switch (property_id)
{
case PROP_TITLE:
if (priv->window_data.title)
g_string_free (priv->window_data.title, TRUE);
priv->window_data.title = g_string_new (g_value_get_string (value));
if (priv->window_data->title)
g_string_free (priv->window_data->title, TRUE);
priv->window_data->title = g_string_new (g_value_get_string (value));
break;
case PROP_SCALE:
priv->window_data.scale = g_value_get_float (value);
priv->window_data->scale = g_value_get_float (value);
break;
case PROP_NATIVE:
priv->window_data.native = g_value_get_pointer (value);
priv->window_data->native = g_value_get_pointer (value);
break;
case PROP_TEXTURE_WIDTH:
priv->window_data.texture_width = g_value_get_uint (value);
priv->window_data->texture_width = g_value_get_uint (value);
break;
case PROP_TEXTURE_HEIGHT:
priv->window_data.texture_height = g_value_get_uint (value);
priv->window_data->texture_height = g_value_get_uint (value);
break;
case PROP_WIDTH_METERS:
priv->window_data.initial_size_meters.x = g_value_get_float (value);
priv->window_data->initial_size_meters.x = g_value_get_float (value);
break;
case PROP_HEIGHT_METERS:
priv->window_data.initial_size_meters.y = g_value_get_float (value);
priv->window_data->initial_size_meters.y = g_value_get_float (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
......@@ -105,25 +105,25 @@ xrd_scene_window_get_property (GObject *object,
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, priv->window_data.title->str);
g_value_set_string (value, priv->window_data->title->str);
break;
case PROP_SCALE:
g_value_set_float (value, priv->window_data.scale);
g_value_set_float (value, priv->window_data->scale);
break;
case PROP_NATIVE:
g_value_set_pointer (value, priv->window_data.native);
g_value_set_pointer (value, priv->window_data->native);
break;
case PROP_TEXTURE_WIDTH:
g_value_set_uint (value, priv->window_data.texture_width);
g_value_set_uint (value, priv->window_data->texture_width);
break;
case PROP_TEXTURE_HEIGHT:
g_value_set_uint (value, priv->window_data.texture_height);
g_value_set_uint (value, priv->window_data->texture_height);
break;
case PROP_WIDTH_METERS:
g_value_set_float (value, priv->window_data.initial_size_meters.x);
g_value_set_float (value, priv->window_data->initial_size_meters.x);
break;
case PROP_HEIGHT_METERS:
g_value_set_float (value, priv->window_data.initial_size_meters.y);
g_value_set_float (value, priv->window_data->initial_size_meters.y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
......@@ -157,22 +157,26 @@ static void
xrd_scene_window_init (XrdSceneWindow *self)
{
XrdSceneWindowPrivate *priv = xrd_scene_window_get_instance_private (self);
priv->window_data = g_malloc (sizeof (XrdWindowData));
priv->vertex_buffer = gulkan_vertex_buffer_new ();
priv->sampler = VK_NULL_HANDLE;
priv->aspect_ratio = 1.0;
priv->window_data.texture = NULL;
priv->window_data->texture = NULL;
priv->shading_buffer = gulkan_uniform_buffer_new ();
priv->shading_buffer_data.flip_y = false;
priv->window_data.title = NULL;
priv->window_data.child_window = NULL;
priv->window_data.parent_window = NULL;
priv->window_data.native = NULL;
priv->window_data.texture_width = 0;
priv->window_data.texture_height = 0;
priv->window_data.texture = NULL;
priv->window_data.selected = FALSE;
graphene_matrix_init_identity (&priv->window_data.reset_transform);
priv->window_data->title = NULL;
priv->window_data->child_window = NULL;
priv->window_data->parent_window = NULL;
priv->window_data->native = NULL;
priv->window_data->texture_width = 0;
priv->window_data->texture_height = 0;
priv->window_data->texture = NULL;
priv->window_data->selected = FALSE;
priv->window_data->xrd_window = XRD_WINDOW (self);
priv->window_data->pinned = FALSE;
graphene_matrix_init_identity (&priv->window_data->reset_transform);
}
XrdSceneWindow *
......@@ -198,6 +202,26 @@ xrd_scene_window_new_from_meters (const gchar *title,
return window;
}
static gboolean
_set_transformation (XrdWindow *window,
graphene_matrix_t *mat);
XrdSceneWindow *
xrd_scene_window_new_from_data (XrdWindowData *data)
{
XrdSceneWindow *window = xrd_scene_window_new (data->title->str);
XrdSceneWindowPrivate *priv = xrd_scene_window_get_instance_private (window);
// TODO: avoid unnecessary allocation
g_free (priv->window_data);
priv->window_data = data;
_set_transformation (XRD_WINDOW (window), &data->transform);
return window;
}
XrdSceneWindow *
xrd_scene_window_new_from_pixels (const gchar *title,
uint32_t width,
......@@ -240,37 +264,11 @@ xrd_scene_window_finalize (GObject *gobject)
//g_object_unref (self->texture);
XrdSceneRenderer *renderer = xrd_scene_renderer_get_instance ();
vkDestroySampler (gulkan_client_get_device_handle (GULKAN_CLIENT (renderer)),
priv->sampler, NULL);
g_object_unref (priv->vertex_buffer);
XrdSceneWindow *parent =
XRD_SCENE_WINDOW (priv->window_data.parent_window);
if (parent != NULL)
{
XrdSceneWindowPrivate *parent_priv =
xrd_scene_window_get_instance_private (parent);
parent_priv->window_data.child_window = NULL;
}
XrdSceneWindow *child = XRD_SCENE_WINDOW (priv->window_data.child_window);
if (child)
{
XrdSceneWindowPrivate *child_priv =
xrd_scene_window_get_instance_private (child);
child_priv->window_data.parent_window = NULL;
}
if (priv->window_data.texture)
g_object_unref (priv->window_data.texture);
g_object_unref (priv->shading_buffer);
g_string_free (priv->window_data.title, TRUE);
G_OBJECT_CLASS (xrd_scene_window_parent_class)->finalize (gobject);
}
......@@ -325,7 +323,7 @@ xrd_scene_window_draw (XrdSceneWindow *self,
graphene_matrix_t *vp)
{
XrdSceneWindowPrivate *priv = xrd_scene_window_get_instance_private (self);
if (!priv->window_data.texture)
if (!priv->window_data->texture)
{
/* g_warning ("Trying to draw window with no texture.\n"); */
return;
......@@ -396,7 +394,7 @@ xrd_scene_window_update_descriptors (XrdSceneWindow *self)
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &(VkDescriptorImageInfo) {
.sampler = priv->sampler,
.imageView = gulkan_texture_get_image_view (priv->window_data.texture),
.imageView = gulkan_texture_get_image_view (priv->window_data->texture),
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
},
.pBufferInfo = NULL,
......@@ -436,9 +434,14 @@ _set_transformation (XrdWindow *window,
xrd_scene_object_set_scale (XRD_SCENE_OBJECT (self), height_meters);
XrdSceneWindowPrivate *priv = xrd_scene_window_get_instance_private (self);
if (priv->window_data.child_window)
if (priv->window_data->child_window)
xrd_window_update_child (window);
XrdWindowData *data = xrd_window_get_data (window);
graphene_matrix_t transform_unscaled;
xrd_window_get_transformation_no_scale (window, &transform_unscaled);
graphene_matrix_init_from_matrix (&data->transform, &transform_unscaled);
return TRUE;
}
......@@ -468,7 +471,7 @@ _submit_texture (XrdWindow *window,
XrdSceneWindow *self = XRD_SCENE_WINDOW (window);
XrdSceneWindowPrivate *priv = xrd_scene_window_get_instance_private (self);
if (texture == priv->window_data.texture)
if (texture == priv->window_data->texture)
{
gchar *title;
g_object_get (window, "title", &title, NULL);
......@@ -497,11 +500,11 @@ _submit_texture (XrdWindow *window,
gulkan_vertex_buffer_map_array (priv->vertex_buffer);
}
if (priv->window_data.texture)
g_object_unref (priv->window_data.texture);
if (priv->window_data->texture)
g_object_unref (priv->window_data->texture);
priv->window_data.texture = texture;
g_object_ref (priv->window_data.texture);
priv->window_data->texture = texture;
g_object_ref (priv->window_data->texture);
guint mip_levels = gulkan_texture_get_mip_levels (texture);
......@@ -576,7 +579,7 @@ _get_data (XrdWindow *window)
{
XrdSceneWindow *self = XRD_SCENE_WINDOW (window);
XrdSceneWindowPrivate *priv = xrd_scene_window_get_instance_private (self);
return &priv->window_data;
return priv->window_data;
}
static void
......
......@@ -47,6 +47,9 @@ xrd_scene_window_new_from_meters (const gchar *title,
float height,
float ppm);
XrdSceneWindow *
xrd_scene_window_new_from_data (XrdWindowData *data);
XrdSceneWindow *
xrd_scene_window_new_from_pixels (const gchar *title,
uint32_t width,
......
This diff is collapsed.
......@@ -502,13 +502,13 @@ xrd_window_add_child (XrdWindow *self,
return;
XrdWindowData *data = xrd_window_get_data (self);
data->child_window = child;
XrdWindowData *child_data = xrd_window_get_data (child);
data->child_window = child_data;
graphene_point_init_from_point (&data->child_offset_center, offset_center);
xrd_window_update_child (self);
XrdWindowData *child_data = xrd_window_get_data (child);
child_data->parent_window = self;
child_data->parent_window = data;
XrdWindowInterface* iface = XRD_WINDOW_GET_IFACE (self);
iface->add_child (self, child, offset_center);
......@@ -601,7 +601,11 @@ void
xrd_window_update_child (XrdWindow *self)
{
XrdWindowData *data = xrd_window_get_data (self);
XrdWindow *child = data->child_window;
XrdWindow *child = data->child_window->xrd_window;
/* this can happen during the overlay scene switch */
if (!child)
return;
g_object_set (G_OBJECT(child), "scale", (double) data->scale, NULL);
......@@ -741,3 +745,29 @@ xrd_window_is_pinned (XrdWindow *self)
XrdWindowData *data = xrd_window_get_data (self);
return data->pinned;
}
/**
* xrd_window_close:
* @self: The #XrdWindow
* MUST be called when destroying a window to free its resources.
*/
void
xrd_window_close (XrdWindow *self)
{
XrdWindowData *data = xrd_window_get_data (self);
/* cleanup: If we are a child, we set our parent's child ptr to NULL */
if (data->parent_window != NULL)
data->parent_window->child_window = NULL;
/* cleanup: If we are a parent, we set our childs parent ptr to NULL.
* Usually we don't close parent windows while child windows still live,
* but sometimes it can happen. */
if (data->child_window)
data->child_window->parent_window = NULL;
if (data->title)
g_string_free (data->title, TRUE);
if (data->texture)
g_object_unref (data->texture);
}
......@@ -69,47 +69,6 @@ typedef struct {
guint64 controller_handle;
} XrdControllerIndexEvent;
/**
* XrdWindowState:
* @native: native
* @title: title
* @scale: scale
* @initial_width: initial_width
* @initial_height: initial_height
* @texture_width: texture_width
* @texture_height: texture_height
* @reset_transform: reset_transform
* @reset_scale: reset_scale
* @pinned: pinned
* @current_width: current_width
* @current_height: current_height
* @transform: transform
* @is_draggable: is_draggable
* @child_index: child_index
* @child_offset_center: child_offset_center
*
* The window state carried over in an overlay<->scene switch
**/
typedef struct {
gpointer native;
gchar *title;
float scale;
float initial_width;
float initial_height;
uint32_t texture_width;
uint32_t texture_height;
graphene_matrix_t reset_transform;
gboolean pinned;
float current_width;
float current_height;
graphene_matrix_t transform;
gboolean is_draggable;
int child_index;
graphene_point_t child_offset_center;
} XrdWindowState;
G_BEGIN_DECLS
#define XRD_TYPE_WINDOW xrd_window_get_type()
......@@ -124,7 +83,7 @@ G_DECLARE_INTERFACE (XrdWindow, xrd_window, XRD, WINDOW, GObject)
* @selected: A #gboolean used in selection mode.
* @initial_size_meters: The window dimensions in meters without scale.
* @scale: A user applied scale.
* @vr_transform: The transformation #graphene_matrix_t of the window.
* @transform: The transformation #graphene_matrix_t of the window.
* @child_window: A window that is pinned on top of this window and follows this window's position and scaling.
* @parent_window: The parent window, %NULL if the window does not have a parent.
* @child_offset_center: If the window is a child, this stores the 2D offset to the parent in meters.
......@@ -132,10 +91,12 @@ G_DECLARE_INTERFACE (XrdWindow, xrd_window, XRD, WINDOW, GObject)
* @reset_scale: The scale that the window will be reset to.
* @pinned: Whether the window will be visible in pinned only mode.
* @texture: Cache of the currently rendered texture.
* @xrd_window: A pointer to the #XrdWindow this XrdWindowData belongs to.
* After switching the overlay/scene mode, it will point to a new #XrdWindow.
*
* Common struct for scene and overlay windows.
**/
typedef struct {
typedef struct XrdWindowData {
gpointer native;
uint32_t texture_width;
......@@ -147,10 +108,10 @@ typedef struct {
graphene_point_t initial_size_meters;
float scale;
graphene_matrix_t vr_transform;
graphene_matrix_t transform;
XrdWindow *child_window;
XrdWindow *parent_window;
struct XrdWindowData *child_window;
struct XrdWindowData *parent_window;
graphene_point_t child_offset_center;
......@@ -159,6 +120,8 @@ typedef struct {
gboolean pinned;
GulkanTexture *texture;
XrdWindow *xrd_window;
} XrdWindowData;
/**
......@@ -396,6 +359,9 @@ xrd_window_set_pin (XrdWindow *self,
gboolean
xrd_window_is_pinned (XrdWindow *self);
void
xrd_window_close (XrdWindow *self);
G_END_DECLS
#endif /* XRD_WINDOW_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment