aboutsummaryrefslogtreecommitdiff
path: root/src/backend/dummy/dummy.c
blob: 7e06facecca4949213825a63713b2254b9115030 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <uthash.h>
#include <xcb/xcb.h>

#include "backend/backend.h"
#include "backend/backend_common.h"
#include "common.h"
#include "compiler.h"
#include "config.h"
#include "log.h"
#include "region.h"
#include "types.h"
#include "uthash_extra.h"
#include "utils.h"
#include "x.h"

struct dummy_image {
	xcb_pixmap_t pixmap;
	bool transparent;
	int *refcount;
	UT_hash_handle hh;
};

struct dummy_data {
	struct backend_base base;
	struct dummy_image *images;

	struct backend_image mask;
};

struct backend_base *dummy_init(struct session *ps attr_unused) {
	auto ret = (struct backend_base *)ccalloc(1, struct dummy_data);
	ret->c = ps->c;
	ret->loop = ps->loop;
	ret->root = ps->root;
	ret->busy = false;
	return ret;
}

void dummy_deinit(struct backend_base *data) {
	auto dummy = (struct dummy_data *)data;
	HASH_ITER2(dummy->images, img) {
		log_warn("Backend image for pixmap %#010x is not freed", img->pixmap);
		HASH_DEL(dummy->images, img);
		free(img->refcount);
		free(img);
	}
	free(dummy);
}

static void dummy_check_image(struct backend_base *base, const struct dummy_image *img) {
	auto dummy = (struct dummy_data *)base;
	if (img == (struct dummy_image *)&dummy->mask) {
		return;
	}
	struct dummy_image *tmp = NULL;
	HASH_FIND_INT(dummy->images, &img->pixmap, tmp);
	if (!tmp) {
		log_warn("Using an invalid (possibly freed) image");
		assert(false);
	}
	assert(*tmp->refcount > 0);
}

void dummy_compose(struct backend_base *base, void *image, coord_t dst attr_unused,
                   void *mask attr_unused, coord_t mask_dst attr_unused,
                   const region_t *reg_paint attr_unused,
                   const region_t *reg_visible attr_unused) {
	auto dummy attr_unused = (struct dummy_data *)base;
	dummy_check_image(base, image);
	assert(mask == NULL || mask == &dummy->mask);
}

void dummy_fill(struct backend_base *backend_data attr_unused, struct color c attr_unused,
                const region_t *clip attr_unused) {
}

bool dummy_blur(struct backend_base *backend_data attr_unused, double opacity attr_unused,
                void *blur_ctx attr_unused, void *mask attr_unused,
                coord_t mask_dst attr_unused, const region_t *reg_blur attr_unused,
                const region_t *reg_visible attr_unused) {
	return true;
}

void *dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap,
                        struct xvisual_info fmt, bool owned attr_unused) {
	auto dummy = (struct dummy_data *)base;
	struct dummy_image *img = NULL;
	HASH_FIND_INT(dummy->images, &pixmap, img);
	if (img) {
		(*img->refcount)++;
		return img;
	}

	img = ccalloc(1, struct dummy_image);
	img->pixmap = pixmap;
	img->transparent = fmt.alpha_size != 0;
	img->refcount = ccalloc(1, int);
	*img->refcount = 1;

	HASH_ADD_INT(dummy->images, pixmap, img);
	return (void *)img;
}

void dummy_release_image(backend_t *base, void *image) {
	auto dummy = (struct dummy_data *)base;
	if (image == &dummy->mask) {
		return;
	}
	auto img = (struct dummy_image *)image;
	assert(*img->refcount > 0);
	(*img->refcount)--;
	if (*img->refcount == 0) {
		HASH_DEL(dummy->images, img);
		free(img->refcount);
		free(img);
	}
}

bool dummy_is_image_transparent(struct backend_base *base, void *image) {
	auto img = (struct dummy_image *)image;
	dummy_check_image(base, img);
	return img->transparent;
}

int dummy_buffer_age(struct backend_base *base attr_unused) {
	return 2;
}

bool dummy_image_op(struct backend_base *base, enum image_operations op attr_unused,
                    void *image, const region_t *reg_op attr_unused,
                    const region_t *reg_visible attr_unused, void *args attr_unused) {
	dummy_check_image(base, image);
	return true;
}

void *dummy_make_mask(struct backend_base *base, geometry_t size attr_unused,
                      const region_t *reg attr_unused) {
	return &(((struct dummy_data *)base)->mask);
}

bool dummy_set_image_property(struct backend_base *base, enum image_properties prop attr_unused,
                              void *image, void *arg attr_unused) {
	dummy_check_image(base, image);
	return true;
}

void *dummy_clone_image(struct backend_base *base, const void *image,
                        const region_t *reg_visible attr_unused) {
	auto img = (const struct dummy_image *)image;
	dummy_check_image(base, img);
	(*img->refcount)++;
	return (void *)img;
}

void *dummy_create_blur_context(struct backend_base *base attr_unused,
                                enum blur_method method attr_unused, void *args attr_unused) {
	static int dummy_context;
	return &dummy_context;
}

void dummy_destroy_blur_context(struct backend_base *base attr_unused, void *ctx attr_unused) {
}

void dummy_get_blur_size(void *ctx attr_unused, int *width, int *height) {
	// These numbers are arbitrary, to make sure the reisze_region code path is
	// covered.
	*width = 5;
	*height = 5;
}

struct backend_operations dummy_ops = {
    .init = dummy_init,
    .deinit = dummy_deinit,
    .compose = dummy_compose,
    .fill = dummy_fill,
    .blur = dummy_blur,
    .bind_pixmap = dummy_bind_pixmap,
    .create_shadow_context = default_create_shadow_context,
    .destroy_shadow_context = default_destroy_shadow_context,
    .render_shadow = default_backend_render_shadow,
    .make_mask = dummy_make_mask,
    .release_image = dummy_release_image,
    .is_image_transparent = dummy_is_image_transparent,
    .buffer_age = dummy_buffer_age,
    .max_buffer_age = 5,

    .image_op = dummy_image_op,
    .clone_image = dummy_clone_image,
    .set_image_property = dummy_set_image_property,
    .create_blur_context = dummy_create_blur_context,
    .destroy_blur_context = dummy_destroy_blur_context,
    .get_blur_size = dummy_get_blur_size,

};