[PATCH 6/9] nested: Add a ‘renderer’ mechanism with a vtable
Neil Roberts
neil at linux.intel.com
Mon Sep 9 08:41:42 PDT 2013
Eventually the nested compositor example will want to be able to cope
with either rendering as it does now with a blit to an intermediate
surface or by attaching the client buffers directly to a subsurface
without copying. This patch moves the code that is specific to the
blitting mechanism into a separate set of functions with a vtable to
make it easier to add the second way of rendering in a later patch.
---
clients/nested.c | 218 +++++++++++++++++++++++++++++++++++++------------------
1 file changed, 147 insertions(+), 71 deletions(-)
diff --git a/clients/nested.c b/clients/nested.c
index 6f68474..d229a9b 100644
--- a/clients/nested.c
+++ b/clients/nested.c
@@ -58,6 +58,8 @@ struct nested {
struct program *texture_program;
struct wl_list surface_list;
+
+ const struct nested_renderer *renderer;
};
struct nested_region {
@@ -79,12 +81,9 @@ struct nested_buffer_reference {
struct nested_surface {
struct wl_resource *resource;
- struct nested_buffer_reference buffer_ref;
struct nested *nested;
EGLImageKHR *image;
- GLuint texture;
struct wl_list link;
- cairo_surface_t *cairo_surface;
struct wl_list frame_callback_list;
@@ -100,6 +99,15 @@ struct nested_surface {
/* wl_surface.damage */
pixman_region32_t damage;
} pending;
+
+ void *renderer_data;
+};
+
+/* Data used for the blit renderer */
+struct nested_blit_surface {
+ struct nested_buffer_reference buffer_ref;
+ GLuint texture;
+ cairo_surface_t *cairo_surface;
};
struct nested_frame_callback {
@@ -107,6 +115,16 @@ struct nested_frame_callback {
struct wl_list link;
};
+struct nested_renderer {
+ void (* surface_init)(struct nested_surface *surface);
+ void (* surface_fini)(struct nested_surface *surface);
+ void (* render_clients)(struct nested *nested, cairo_t *cr);
+ void (* surface_attach)(struct nested_surface *surface,
+ struct nested_buffer *buffer);
+};
+
+static const struct nested_renderer nested_blit_renderer;
+
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
static PFNEGLCREATEIMAGEKHRPROC create_image;
static PFNEGLDESTROYIMAGEKHRPROC destroy_image;
@@ -209,31 +227,12 @@ flush_surface_frame_callback_list (struct nested_surface *surface,
}
static void
-frame_callback(void *data, struct wl_callback *callback, uint32_t time)
-{
- struct nested *nested = data;
- struct nested_surface *surface;
-
- wl_list_for_each(surface, &nested->surface_list, link)
- flush_surface_frame_callback_list(surface, time);
-
- if (callback)
- wl_callback_destroy(callback);
-}
-
-static const struct wl_callback_listener frame_listener = {
- frame_callback
-};
-
-static void
redraw_handler(struct widget *widget, void *data)
{
struct nested *nested = data;
cairo_surface_t *surface;
cairo_t *cr;
struct rectangle allocation;
- struct wl_callback *callback;
- struct nested_surface *s;
widget_get_allocation(nested->widget, &allocation);
@@ -249,34 +248,11 @@ redraw_handler(struct widget *widget, void *data)
cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
cairo_fill(cr);
- wl_list_for_each(s, &nested->surface_list, link) {
- display_acquire_window_surface(nested->display,
- nested->window, NULL);
-
- glBindTexture(GL_TEXTURE_2D, s->texture);
- image_target_texture_2d(GL_TEXTURE_2D, s->image);
-
- display_release_window_surface(nested->display,
- nested->window);
-
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_set_source_surface(cr, s->cairo_surface,
- allocation.x + 10,
- allocation.y + 10);
- cairo_rectangle(cr, allocation.x + 10,
- allocation.y + 10,
- allocation.width - 10,
- allocation.height - 10);
-
- cairo_fill(cr);
- }
+ nested->renderer->render_clients(nested, cr);
cairo_destroy(cr);
cairo_surface_destroy(surface);
-
- callback = wl_surface_frame(window_get_wl_surface(nested->window));
- wl_callback_add_listener(callback, &frame_listener, nested);
}
static void
@@ -374,6 +350,7 @@ static void
destroy_surface(struct wl_resource *resource)
{
struct nested_surface *surface = wl_resource_get_user_data(resource);
+ struct nested *nested = surface->nested;
struct nested_frame_callback *cb, *next;
wl_list_for_each_safe(cb, next,
@@ -384,10 +361,10 @@ destroy_surface(struct wl_resource *resource)
&surface->pending.frame_callback_list, link)
wl_resource_destroy(cb->resource);
- nested_buffer_reference(&surface->buffer_ref, NULL);
-
pixman_region32_fini(&surface->pending.damage);
+ nested->renderer->surface_fini(surface);
+
free(surface);
}
@@ -451,15 +428,9 @@ nested_surface_attach(struct nested_surface *surface,
struct nested_buffer *buffer)
{
struct nested *nested = surface->nested;
- EGLint width, height;
- cairo_device_t *device;
-
- nested_buffer_reference(&surface->buffer_ref, buffer);
if (surface->image != EGL_NO_IMAGE_KHR)
destroy_image(nested->egl_display, surface->image);
- if (surface->cairo_surface)
- cairo_surface_destroy(surface->cairo_surface);
surface->image = create_image(nested->egl_display, NULL,
EGL_WAYLAND_BUFFER_WL, buffer->resource,
@@ -469,17 +440,7 @@ nested_surface_attach(struct nested_surface *surface,
return;
}
- query_buffer(nested->egl_display, buffer->resource,
- EGL_WIDTH, &width);
- query_buffer(nested->egl_display, buffer->resource,
- EGL_HEIGHT, &height);
-
- device = display_get_cairo_device(nested->display);
- surface->cairo_surface =
- cairo_gl_surface_create_for_texture(device,
- CAIRO_CONTENT_COLOR_ALPHA,
- surface->texture,
- width, height);
+ nested->renderer->surface_attach(surface, buffer);
}
static void
@@ -628,12 +589,7 @@ compositor_create_surface(struct wl_client *client,
display_acquire_window_surface(nested->display,
nested->window, NULL);
- glGenTextures(1, &surface->texture);
- glBindTexture(GL_TEXTURE_2D, surface->texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ nested->renderer->surface_init(surface);
display_release_window_surface(nested->display, nested->window);
@@ -771,6 +727,8 @@ nested_init_compositor(struct nested *nested)
return -1;
}
+ nested->renderer = &nested_blit_renderer;
+
return 0;
}
@@ -808,6 +766,124 @@ nested_destroy(struct nested *nested)
free(nested);
}
+static void
+blit_surface_init(struct nested_surface *surface)
+{
+ struct nested_blit_surface *blit_surface =
+ zalloc(sizeof *blit_surface);
+
+ glGenTextures(1, &blit_surface->texture);
+ glBindTexture(GL_TEXTURE_2D, blit_surface->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ surface->renderer_data = blit_surface;
+}
+
+static void
+blit_surface_fini(struct nested_surface *surface)
+{
+ struct nested_blit_surface *blit_surface = surface->renderer_data;
+
+ nested_buffer_reference(&blit_surface->buffer_ref, NULL);
+
+ glDeleteTextures(1, &blit_surface->texture);
+
+ free(blit_surface);
+}
+
+static void
+blit_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
+{
+ struct nested *nested = data;
+ struct nested_surface *surface;
+
+ wl_list_for_each(surface, &nested->surface_list, link)
+ flush_surface_frame_callback_list(surface, time);
+
+ if (callback)
+ wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener blit_frame_listener = {
+ blit_frame_callback
+};
+
+static void
+blit_render_clients(struct nested *nested,
+ cairo_t *cr)
+{
+ struct nested_surface *s;
+ struct rectangle allocation;
+ struct wl_callback *callback;
+
+ widget_get_allocation(nested->widget, &allocation);
+
+ wl_list_for_each(s, &nested->surface_list, link) {
+ struct nested_blit_surface *blit_surface = s->renderer_data;
+
+ display_acquire_window_surface(nested->display,
+ nested->window, NULL);
+
+ glBindTexture(GL_TEXTURE_2D, blit_surface->texture);
+ image_target_texture_2d(GL_TEXTURE_2D, s->image);
+
+ display_release_window_surface(nested->display,
+ nested->window);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_set_source_surface(cr, blit_surface->cairo_surface,
+ allocation.x + 10,
+ allocation.y + 10);
+ cairo_rectangle(cr, allocation.x + 10,
+ allocation.y + 10,
+ allocation.width - 10,
+ allocation.height - 10);
+
+ cairo_fill(cr);
+ }
+
+ callback = wl_surface_frame(window_get_wl_surface(nested->window));
+ wl_callback_add_listener(callback, &blit_frame_listener, nested);
+}
+
+static void
+blit_surface_attach(struct nested_surface *surface,
+ struct nested_buffer *buffer)
+{
+ struct nested *nested = surface->nested;
+ struct nested_blit_surface *blit_surface = surface->renderer_data;
+ EGLint width, height;
+ cairo_device_t *device;
+
+ nested_buffer_reference(&blit_surface->buffer_ref, buffer);
+
+ if (blit_surface->cairo_surface)
+ cairo_surface_destroy(blit_surface->cairo_surface);
+
+ query_buffer(nested->egl_display, buffer->resource,
+ EGL_WIDTH, &width);
+ query_buffer(nested->egl_display, buffer->resource,
+ EGL_HEIGHT, &height);
+
+ device = display_get_cairo_device(nested->display);
+ blit_surface->cairo_surface =
+ cairo_gl_surface_create_for_texture(device,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ blit_surface->texture,
+ width, height);
+}
+
+static const struct nested_renderer
+nested_blit_renderer = {
+ .surface_init = blit_surface_init,
+ .surface_fini = blit_surface_fini,
+ .render_clients = blit_render_clients,
+ .surface_attach = blit_surface_attach
+};
+
int
main(int argc, char *argv[])
{
--
1.8.3.1
More information about the wayland-devel
mailing list