Fall back to cairo image backend and shm surface if we don't have cairo gl
This commit is contained in:
parent
6866856dfd
commit
d0c3b9da22
406
clients/window.c
406
clients/window.c
|
@ -20,6 +20,8 @@
|
|||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -33,13 +35,17 @@
|
|||
#include <glib-object.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <xf86drm.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define EGL_EGLEXT_PROTOTYPES 1
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#include <GL/gl.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#include <cairo-gl.h>
|
||||
#endif
|
||||
|
||||
#include <X11/extensions/XKBcommon.h>
|
||||
|
||||
|
@ -56,6 +62,7 @@ struct display {
|
|||
struct wl_compositor *compositor;
|
||||
struct wl_shell *shell;
|
||||
struct wl_drm *drm;
|
||||
struct wl_shm *shm;
|
||||
struct wl_output *output;
|
||||
struct rectangle screen_allocation;
|
||||
int authenticated;
|
||||
|
@ -89,6 +96,7 @@ struct window {
|
|||
struct input *grab_device;
|
||||
struct input *keyboard_device;
|
||||
uint32_t name;
|
||||
enum window_buffer_type buffer_type;
|
||||
|
||||
EGLImageKHR *image;
|
||||
cairo_surface_t *cairo_surface, *pending_surface;
|
||||
|
@ -148,33 +156,110 @@ rounded_rect(cairo_t *cr, int x0, int y0, int x1, int y1, int radius)
|
|||
cairo_close_path(cr);
|
||||
}
|
||||
|
||||
static int
|
||||
texture_from_png(const char *filename, int width, int height)
|
||||
static const cairo_user_data_key_t surface_data_key;
|
||||
struct surface_data {
|
||||
struct wl_buffer *buffer;
|
||||
};
|
||||
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
|
||||
struct drm_surface_data {
|
||||
struct surface_data data;
|
||||
EGLImageKHR image;
|
||||
GLuint texture;
|
||||
EGLDisplay dpy;
|
||||
};
|
||||
|
||||
static void
|
||||
drm_surface_data_destroy(void *p)
|
||||
{
|
||||
struct drm_surface_data *data = p;
|
||||
|
||||
glDeleteTextures(1, &data->texture);
|
||||
eglDestroyImageKHR(data->dpy, data->image);
|
||||
wl_buffer_destroy(data->data.buffer);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_drm_surface(struct display *display,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
struct drm_surface_data *data;
|
||||
EGLDisplay dpy = display->dpy;
|
||||
cairo_surface_t *surface;
|
||||
struct wl_visual *visual;
|
||||
struct wl_buffer *buffer;
|
||||
EGLint name, stride;
|
||||
|
||||
EGLint image_attribs[] = {
|
||||
EGL_WIDTH, 0,
|
||||
EGL_HEIGHT, 0,
|
||||
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
|
||||
EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
data = malloc(sizeof *data);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
image_attribs[1] = rectangle->width;
|
||||
image_attribs[3] = rectangle->height;
|
||||
data->image = eglCreateDRMImageMESA(dpy, image_attribs);
|
||||
glGenTextures(1, &data->texture);
|
||||
data->dpy = dpy;
|
||||
glBindTexture(GL_TEXTURE_2D, data->texture);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, data->image);
|
||||
|
||||
eglExportDRMImageMESA(display->dpy, data->image, &name, NULL, &stride);
|
||||
|
||||
visual = wl_display_get_premultiplied_argb_visual(display->display);
|
||||
data->data.buffer =
|
||||
wl_drm_create_buffer(display->drm, name, rectangle->width,
|
||||
rectangle->height, stride, visual);
|
||||
|
||||
surface = cairo_gl_surface_create_for_texture(display->device,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
data->texture,
|
||||
rectangle->width,
|
||||
rectangle->height);
|
||||
|
||||
cairo_surface_set_user_data (surface, &surface_data_key,
|
||||
data, drm_surface_data_destroy);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_drm_surface_from_file(struct display *display,
|
||||
const char *filename,
|
||||
struct rectangle *rect)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
GdkPixbuf *pixbuf;
|
||||
GError *error = NULL;
|
||||
int stride, i;
|
||||
unsigned char *pixels, *p, *end;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
|
||||
width, height,
|
||||
rect->width, rect->height,
|
||||
FALSE, &error);
|
||||
if (error != NULL)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
|
||||
gdk_pixbuf_get_n_channels(pixbuf) != 4) {
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
stride = gdk_pixbuf_get_rowstride(pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels(pixbuf);
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
for (i = 0; i < rect->height; i++) {
|
||||
p = pixels + i * stride;
|
||||
end = p + width * 4;
|
||||
end = p + rect->width * 4;
|
||||
while (p < end) {
|
||||
unsigned int t;
|
||||
|
||||
|
@ -189,12 +274,181 @@ texture_from_png(const char *filename, int width, int height)
|
|||
}
|
||||
}
|
||||
|
||||
surface = display_create_drm_surface(display, rect);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
rect->width, rect->height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
|
||||
return 0;
|
||||
return surface;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct wl_buffer *
|
||||
display_get_buffer_for_surface(struct display *display,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
struct surface_data *data;
|
||||
|
||||
data = cairo_surface_get_user_data (surface, &surface_data_key);
|
||||
|
||||
return data->buffer;
|
||||
}
|
||||
|
||||
struct shm_surface_data {
|
||||
struct surface_data data;
|
||||
void *map;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
void
|
||||
shm_surface_data_destroy(void *p)
|
||||
{
|
||||
struct shm_surface_data *data = p;
|
||||
|
||||
wl_buffer_destroy(data->data.buffer);
|
||||
munmap(data->map, data->length);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_shm_surface(struct display *display,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
struct shm_surface_data *data;
|
||||
cairo_surface_t *surface;
|
||||
struct wl_visual *visual;
|
||||
int stride, alloc, fd;
|
||||
char filename[] = "/tmp/wayland-shm-XXXXXX";
|
||||
|
||||
data = malloc(sizeof *data);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
|
||||
rectangle->width);
|
||||
data->length = stride * rectangle->height;
|
||||
fd = mkstemp(filename);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "open %s failed: %m", filename);
|
||||
return NULL;
|
||||
}
|
||||
if (ftruncate(fd, data->length) < 0) {
|
||||
fprintf(stderr, "ftruncate failed: %m");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->map = mmap(NULL, data->length,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
unlink(filename);
|
||||
|
||||
if (data->map == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap failed: %m");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data->map,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
rectangle->width,
|
||||
rectangle->height,
|
||||
stride);
|
||||
|
||||
cairo_surface_set_user_data (surface, &surface_data_key,
|
||||
data, shm_surface_data_destroy);
|
||||
|
||||
visual = wl_display_get_premultiplied_argb_visual(display->display);
|
||||
data->data.buffer = wl_shm_create_buffer(display->shm,
|
||||
fd,
|
||||
rectangle->width,
|
||||
rectangle->height,
|
||||
stride, visual);
|
||||
|
||||
close(fd);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_shm_surface_from_file(struct display *display,
|
||||
const char *filename,
|
||||
struct rectangle *rect)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
GdkPixbuf *pixbuf;
|
||||
GError *error = NULL;
|
||||
int stride, i;
|
||||
unsigned char *pixels, *p, *end, *dest_data;
|
||||
int dest_stride;
|
||||
uint32_t *d;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
|
||||
rect->width, rect->height,
|
||||
FALSE, &error);
|
||||
if (error != NULL)
|
||||
return NULL;
|
||||
|
||||
if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
|
||||
gdk_pixbuf_get_n_channels(pixbuf) != 4) {
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stride = gdk_pixbuf_get_rowstride(pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels(pixbuf);
|
||||
|
||||
surface = display_create_shm_surface(display, rect);
|
||||
dest_data = cairo_image_surface_get_data (surface);
|
||||
dest_stride = cairo_image_surface_get_stride (surface);
|
||||
|
||||
for (i = 0; i < rect->height; i++) {
|
||||
d = (uint32_t *) (dest_data + i * dest_stride);
|
||||
p = pixels + i * stride;
|
||||
end = p + rect->width * 4;
|
||||
while (p < end) {
|
||||
unsigned int t;
|
||||
unsigned char a, r, g, b;
|
||||
|
||||
#define MULT(_d,c,a,t) \
|
||||
do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
|
||||
|
||||
a = p[3];
|
||||
MULT(r, p[0], a, t);
|
||||
MULT(g, p[1], a, t);
|
||||
MULT(b, p[2], a, t);
|
||||
p += 4;
|
||||
*d++ = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_surface(struct display *display,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
display_create_drm_surface(display, rectangle);
|
||||
#else
|
||||
display_create_shm_surface(display, rectangle);
|
||||
#endif
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_surface_from_file(struct display *display,
|
||||
const char *filename,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
display_create_drm_surface_from_file(display, filename, rectangle);
|
||||
#else
|
||||
display_create_shm_surface_from_file(display, filename, rectangle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct {
|
||||
|
@ -229,96 +483,13 @@ create_pointer_surfaces(struct display *display)
|
|||
rect.height = height;
|
||||
for (i = 0; i < count; i++) {
|
||||
display->pointer_surfaces[i] =
|
||||
display_create_surface(display, &rect);
|
||||
texture_from_png(pointer_images[i].filename, width, height);
|
||||
display_create_surface_from_file(display,
|
||||
pointer_images[i].filename,
|
||||
&rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t surface_data_key;
|
||||
struct surface_data {
|
||||
EGLImageKHR image;
|
||||
GLuint texture;
|
||||
EGLDisplay dpy;
|
||||
struct wl_buffer *buffer;
|
||||
};
|
||||
|
||||
static void
|
||||
surface_data_destroy(void *p)
|
||||
{
|
||||
struct surface_data *data = p;
|
||||
|
||||
glDeleteTextures(1, &data->texture);
|
||||
eglDestroyImageKHR(data->dpy, data->image);
|
||||
if (data->buffer)
|
||||
wl_buffer_destroy(data->buffer);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_create_surface(struct display *display,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
struct surface_data *data;
|
||||
EGLDisplay dpy = display->dpy;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
EGLint image_attribs[] = {
|
||||
EGL_WIDTH, 0,
|
||||
EGL_HEIGHT, 0,
|
||||
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
|
||||
EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
data = malloc(sizeof *data);
|
||||
image_attribs[1] = rectangle->width;
|
||||
image_attribs[3] = rectangle->height;
|
||||
data->image = eglCreateDRMImageMESA(dpy, image_attribs);
|
||||
glGenTextures(1, &data->texture);
|
||||
data->dpy = dpy;
|
||||
glBindTexture(GL_TEXTURE_2D, data->texture);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, data->image);
|
||||
data->buffer = NULL;
|
||||
|
||||
surface = cairo_gl_surface_create_for_texture(display->device,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
data->texture,
|
||||
rectangle->width,
|
||||
rectangle->height);
|
||||
|
||||
cairo_surface_set_user_data (surface, &surface_data_key,
|
||||
data, surface_data_destroy);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
struct wl_buffer *
|
||||
display_get_buffer_for_surface(struct display *display,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
struct surface_data *data;
|
||||
struct wl_visual *visual;
|
||||
struct wl_buffer *buffer;
|
||||
EGLint name, stride;
|
||||
int width, height;
|
||||
|
||||
data = cairo_surface_get_user_data (surface, &surface_data_key);
|
||||
if (data->buffer)
|
||||
return data->buffer;
|
||||
|
||||
width = cairo_gl_surface_get_width (surface);
|
||||
height = cairo_gl_surface_get_height (surface);
|
||||
|
||||
eglExportDRMImageMESA(display->dpy, data->image, &name, NULL, &stride);
|
||||
|
||||
visual = wl_display_get_premultiplied_argb_visual(display->display);
|
||||
buffer = wl_drm_create_buffer(display->drm,
|
||||
name, width, height, stride, visual);
|
||||
data->buffer = buffer;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
display_get_pointer_surface(struct display *display, int pointer,
|
||||
int *width, int *height,
|
||||
|
@ -382,6 +553,23 @@ window_flush(struct window *window)
|
|||
window_attach_surface(window);
|
||||
}
|
||||
|
||||
static void
|
||||
window_create_surface(struct window *window, struct rectangle *allocation)
|
||||
{
|
||||
switch (window->buffer_type) {
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
case WINDOW_BUFFER_TYPE_DRM:
|
||||
window->cairo_surface =
|
||||
display_create_surface(window->display, allocation);
|
||||
break;
|
||||
#endif
|
||||
case WINDOW_BUFFER_TYPE_SHM:
|
||||
window->cairo_surface =
|
||||
display_create_shm_surface(window->display, allocation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
window_draw_decorations(struct window *window)
|
||||
{
|
||||
|
@ -391,8 +579,8 @@ window_draw_decorations(struct window *window)
|
|||
cairo_surface_t *frame;
|
||||
int width, height, shadow_dx = 3, shadow_dy = 3;
|
||||
|
||||
window->cairo_surface =
|
||||
display_create_surface(window->display, &window->allocation);
|
||||
window_create_surface(window, &window->allocation);
|
||||
|
||||
width = window->allocation.width;
|
||||
height = window->allocation.height;
|
||||
|
||||
|
@ -447,8 +635,7 @@ display_flush_cairo_device(struct display *display)
|
|||
static void
|
||||
window_draw_fullscreen(struct window *window)
|
||||
{
|
||||
window->cairo_surface =
|
||||
display_create_surface(window->display, &window->allocation);
|
||||
window_create_surface(window, &window->allocation);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -985,6 +1172,13 @@ window_move(struct window *window, int32_t x, int32_t y)
|
|||
window->allocation.height);
|
||||
}
|
||||
|
||||
void
|
||||
window_damage(struct window *window, int32_t x, int32_t y,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
wl_surface_damage(window->surface, x, y, width, height);
|
||||
}
|
||||
|
||||
struct window *
|
||||
window_create(struct display *display, const char *title,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
|
@ -1007,12 +1201,24 @@ window_create(struct display *display, const char *title,
|
|||
window->margin = 16;
|
||||
window->decoration = 1;
|
||||
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
window->buffer_type = WINDOW_BUFFER_TYPE_DRM;
|
||||
#else
|
||||
window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
|
||||
#endif
|
||||
|
||||
wl_surface_set_user_data(window->surface, window);
|
||||
wl_list_insert(display->window_list.prev, &window->link);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
void
|
||||
window_set_buffer_type(struct window *window, enum window_buffer_type type)
|
||||
{
|
||||
window->buffer_type = type;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_device(void *data, struct wl_drm *drm, const char *device)
|
||||
{
|
||||
|
@ -1091,6 +1297,8 @@ display_handle_global(struct wl_display *display, uint32_t id,
|
|||
} else if (strcmp(interface, "drm") == 0) {
|
||||
d->drm = wl_drm_create(display, id);
|
||||
wl_drm_add_listener(d->drm, &drm_listener, d);
|
||||
} else if (strcmp(interface, "shm") == 0) {
|
||||
d->shm = wl_shm_create(display, id);
|
||||
} else if (strcmp(interface, "drag_offer") == 0) {
|
||||
offer = wl_drag_offer_create(display, id);
|
||||
d->drag_offer_handler(offer, d);
|
||||
|
|
|
@ -138,6 +138,10 @@ window_schedule_redraw(struct window *window);
|
|||
void
|
||||
window_move(struct window *window, int32_t x, int32_t y);
|
||||
|
||||
void
|
||||
window_damage(struct window *window, int32_t x, int32_t y,
|
||||
int32_t width, int32_t height);
|
||||
|
||||
cairo_surface_t *
|
||||
window_get_surface(struct window *window);
|
||||
|
||||
|
@ -149,6 +153,14 @@ window_copy_surface(struct window *window,
|
|||
void
|
||||
window_flush(struct window *window);
|
||||
|
||||
enum window_buffer_type {
|
||||
WINDOW_BUFFER_TYPE_DRM,
|
||||
WINDOW_BUFFER_TYPE_SHM,
|
||||
};
|
||||
|
||||
void
|
||||
window_set_buffer_type(struct window *window, enum window_buffer_type type);
|
||||
|
||||
void
|
||||
window_set_fullscreen(struct window *window, int fullscreen);
|
||||
|
||||
|
|
|
@ -52,6 +52,12 @@ shm_buffer_attach(struct wl_buffer *buffer_base, struct wl_surface *surface)
|
|||
(struct wlsc_shm_buffer *) buffer_base;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, es->texture);
|
||||
|
||||
/* Unbind any EGLImage texture that may be bound, so we don't
|
||||
* overwrite it.*/
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
0, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
buffer->base.width, buffer->base.height, 0,
|
||||
GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data);
|
||||
|
|
|
@ -3,6 +3,7 @@ AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
|||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
|
@ -10,8 +11,12 @@ PKG_CHECK_MODULES(FFI, [libffi])
|
|||
|
||||
PKG_CHECK_MODULES(COMPOSITOR,
|
||||
[egl glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes)
|
||||
PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm])
|
||||
PKG_CHECK_MODULES(CLIENT, [egl gl cairo gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm])
|
||||
PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0])
|
||||
PKG_CHECK_MODULES(CAIRO_GL, [cairo-gl],
|
||||
[have_cairo_gl=yes], [have_cairo_gl=no])
|
||||
AS_IF([test "x$have_cairo_gl" = "xyes"],
|
||||
[AC_DEFINE([HAVE_CAIRO_GL], [1], [Have cairo-gl])])
|
||||
|
||||
if test $CC = gcc; then
|
||||
GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
|
||||
|
|
Loading…
Reference in New Issue