aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-05 16:50:39 (GMT)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-05 17:18:06 (GMT)
commit01fccdeaea087e73c933e71890908a6b6dc23ac1 (patch)
tree07cc0b86ac81cac09b580beed89ca4aeec8f125d
parent98a4baa241cfd710e27d51871f17bee3f60930cc (diff)
callbacks: use a callback to draw at GtkDrawingAreagtk3_improvements
Gtk 3 supports wayland, but there's a catch: while the current code works properly with X11, it doesn't draw anything inside the GtkDrawingArea on Wayland. The fix is trivial, but incompatible with Gtk2: instead of updating the drawing aea inside the main loop, a callback has to be used in order to handle gtk draw logic. As, at least for now, we want to keep supporting Gtk 2, let's add a compatibility code. That fixes drawing with Wayland. Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--data/camorama.ui1
-rw-r--r--src/callbacks.c103
-rw-r--r--src/callbacks.h1
-rw-r--r--src/main.c5
-rw-r--r--src/v4l.h1
5 files changed, 70 insertions, 41 deletions
diff --git a/data/camorama.ui b/data/camorama.ui
index 9f99b38..8a19cbe 100644
--- a/data/camorama.ui
+++ b/data/camorama.ui
@@ -1372,6 +1372,7 @@
<property name="height_request">240</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <signal name="draw" handler="show_buffer" swapped="no"/>
</object>
</child>
</object>
diff --git a/src/callbacks.c b/src/callbacks.c
index f8a378e..a38a1dc 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -497,12 +497,10 @@ static void apply_filters(cam_t *cam)
* https://github.com/bratsche/gtk-/blob/master/gdk/gdkcairo.c
* With a small backport.
*/
+#if GTK_MAJOR_VERSION < 3
static cairo_surface_t *create_from_pixbuf(const GdkPixbuf *pixbuf,
GdkWindow *for_window)
{
-#if GTK_MAJOR_VERSION >= 3
- return gdk_cairo_surface_create_from_pixbuf(pixbuf, 1, for_window);
-#else
gint width = gdk_pixbuf_get_width(pixbuf);
gint height = gdk_pixbuf_get_height(pixbuf);
guchar *gdk_pixels = gdk_pixbuf_get_pixels(pixbuf);
@@ -567,82 +565,92 @@ static cairo_surface_t *create_from_pixbuf(const GdkPixbuf *pixbuf,
cairo_surface_mark_dirty(surface);
return surface;
-#endif
}
static void show_buffer(cam_t *cam)
{
- GdkPixbuf *pb;
GtkWidget *widget;
GdkWindow *window;
cairo_surface_t *surface;
cairo_t *cr;
- unsigned char *pic_buf = cam->pic_buf;
-
const GdkRectangle rect = {
.x = 0, .y = 0,
.width = cam->width, .height = cam->height
};
-#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 22
- GdkDrawingContext *context;
- cairo_region_t *region;
-#endif
- /*
- * refer the frame
- */
- if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
- yuv420p_to_rgb(cam->pic_buf, cam->tmp, cam->width, cam->height,
- cam->bpp / 8);
- pic_buf = cam->tmp;
- }
-
- apply_filters(cam);
-
- /* Use cairo to display the pixel buffer */
-
- pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8,
- cam->width, cam->height,
- (cam->width * cam->bpp / 8), NULL, NULL);
+ if (!cam->pb)
+ return;
widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "da"));
window = gtk_widget_get_window(widget);
- surface = create_from_pixbuf(pb, window);
-
-#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 22
- region = cairo_region_create();
- context = gdk_window_begin_draw_frame(window, region);
- cr = gdk_drawing_context_get_cairo_context(context);
-#else
+ surface = create_from_pixbuf(cam->pb, window);
cr = gdk_cairo_create(window);
-#endif
-
cairo_set_source_surface(cr, surface, 0, 0);
+
gdk_cairo_rectangle(cr, &rect);
+
cairo_fill(cr);
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
-#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 22
- gdk_window_end_draw_frame(window, context);
+ frames++;
+ frames2++;
+}
#else
- cairo_destroy(cr);
- cairo_region_destroy(region);
-#endif
+/*
+ * GTK 3 way: use a drawing callback
+ */
+void draw_callback(GtkWidget *widget, cairo_t *cr, cam_t *cam)
+{
+ GdkWindow *window;
+ cairo_surface_t *surface;
+ const GdkRectangle rect = {
+ .x = 0, .y = 0,
+ .width = cam->width, .height = cam->height
+ };
+ if (!cam->pb)
+ return;
+
+ window = gtk_widget_get_window(widget);
+ surface = gdk_cairo_surface_create_from_pixbuf(cam->pb, 1, window);
+ cairo_set_source_surface(cr, surface, 0, 0);
+ gdk_cairo_rectangle(cr, &rect);
+ cairo_fill(cr);
cairo_surface_destroy(surface);
frames++;
frames2++;
}
+static inline void show_buffer(cam_t *cam)
+{
+ gtk_widget_queue_draw(GTK_WIDGET(gtk_builder_get_object(cam->xml, "da")));
+}
+#endif
+
/*
* get image from cam - does all the work ;)
*/
gint read_timeout_func(cam_t *cam)
{
+ unsigned char *pic_buf = cam->pic_buf;
+
v4l2_read(cam->dev, cam->pic_buf,
(cam->width * cam->height * cam->bpp / 8));
+ if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
+ yuv420p_to_rgb(cam->pic_buf, cam->tmp, cam->width, cam->height,
+ cam->bpp / 8);
+ pic_buf = cam->tmp;
+ }
+ apply_filters(cam);
+ cam->pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8,
+ cam->width, cam->height,
+ (cam->width * cam->bpp / 8),
+ NULL, NULL);
+
show_buffer(cam);
return TRUE;
@@ -650,9 +658,22 @@ gint read_timeout_func(cam_t *cam)
gint timeout_func(cam_t *cam)
{
+ unsigned char *pic_buf = cam->pic_buf;
+
capture_buffers(cam, cam->pic_buf,
cam->width * cam->height * cam->bytesperline);
+ if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
+ yuv420p_to_rgb(cam->pic_buf, cam->tmp, cam->width, cam->height,
+ cam->bpp / 8);
+ pic_buf = cam->tmp;
+ }
+ apply_filters(cam);
+ cam->pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8,
+ cam->width, cam->height,
+ (cam->width * cam->bpp / 8),
+ NULL, NULL);
+
show_buffer(cam);
return TRUE;
diff --git a/src/callbacks.h b/src/callbacks.h
index c0c2e1b..30e15b2 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -33,6 +33,7 @@ void ppm_func(GtkWidget *, cam_t *);
void rts_func(GtkWidget *, cam_t *);
void rjpg_func(GtkWidget *, cam_t *);
void rpng_func(GtkWidget *, cam_t *);
+void draw_callback(GtkWidget *, cairo_t *, cam_t *cam);
gint(*pt2Function) (cam_t *);
void rppm_func(GtkWidget *, cam_t *);
diff --git a/src/main.c b/src/main.c
index 5b434e3..257e4ee 100644
--- a/src/main.c
+++ b/src/main.c
@@ -217,6 +217,11 @@ int main(int argc, char *argv[])
load_interface(cam);
widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "da"));
+
+#if GTK_MAJOR_VERSION >= 3
+ g_signal_connect(G_OBJECT(widget), "draw", G_CALLBACK(draw_callback), cam);
+#endif
+
gtk_widget_show(widget);
cam->idle_id = g_idle_add((GSourceFunc) pt2Function, (gpointer) cam);
diff --git a/src/v4l.h b/src/v4l.h
index d991a63..1d4fa1f 100644
--- a/src/v4l.h
+++ b/src/v4l.h
@@ -79,6 +79,7 @@ typedef struct camera {
guint32 timeout_interval;
GConfClient *gc;
GtkBuilder *xml;
+ GdkPixbuf *pb;
GtkStatusIcon *tray_icon;
CamoramaFilterChain *filter_chain;

Privacy Policy