2
* Copyright Ā© 2014 Keith Packard
4
* Permission to use, copy, modify, distribute, and sell this software and its
5
* documentation for any purpose is hereby granted without fee, provided that
6
* the above copyright notice appear in all copies and that both that copyright
7
* notice and this permission notice appear in supporting documentation, and
8
* that the name of the copyright holders not be used in advertising or
9
* publicity pertaining to distribution of the software without specific,
10
* written prior permission. The copyright holders make no representations
11
* about the suitability of this software for any purpose. It is provided "as
12
* is" without express or implied warranty.
14
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23
#include "glamor_priv.h"
24
#include "glamor_transform.h"
25
#include "glamor_program.h"
28
use_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
30
return glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform);
33
const glamor_facet glamor_fill_solid = {
35
.fs_exec = " gl_FragColor = fg;\n",
36
.locations = glamor_program_location_fg,
41
use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
43
return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform, prog->fill_size_uniform);
46
static const glamor_facet glamor_fill_tile = {
48
.vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
49
.fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n",
50
.locations = glamor_program_location_fill,
56
use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog)
58
return glamor_set_stippled(pixmap, gc, prog->fg_uniform, prog->fill_offset_uniform, prog->fill_size_uniform);
61
static const glamor_facet glamor_fill_stipple = {
64
.vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n";
65
.fs_exec = (" if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
67
" gl_FragColor = fg;\n")
68
.locations = glamor_program_location_fg | glamor_program_location_fill
72
static const glamor_facet glamor_fill_opaque_stipple = {
73
.name = "opaque_stipple",
75
.vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n";
76
.fs_exec = (" if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
77
" gl_FragColor = bg;\n"
79
" gl_FragColor = fg;\n"),
80
.locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill
81
.use = use_opaque_stipple
85
static const glamor_facet *glamor_facet_fill[4] = {
93
glamor_program_location location;
96
} glamor_location_var;
98
static glamor_location_var location_vars[] = {
100
.location = glamor_program_location_fg,
101
.fs_vars = "uniform vec4 fg;\n"
104
.location = glamor_program_location_bg,
105
.fs_vars = "uniform vec4 bg;\n"
108
.location = glamor_program_location_fill,
109
.vs_vars = ("uniform vec2 fill_offset;\n"
110
"uniform vec2 fill_size;\n"
111
"varying vec2 fill_pos;\n"),
112
.fs_vars = ("uniform sampler2D sampler;\n"
113
"uniform vec2 fill_size;\n"
114
"varying vec2 fill_pos;\n")
117
.location = glamor_program_location_font,
118
.fs_vars = "uniform usampler2D font;\n",
122
#define NUM_LOCATION_VARS (sizeof location_vars / sizeof location_vars[0])
125
add_var(char *cur, const char *add)
132
new = realloc(cur, strlen(cur) + strlen(add) + 1);
142
vs_location_vars(glamor_program_location locations)
145
char *vars = strdup("");
147
for (l = 0; vars && l < NUM_LOCATION_VARS; l++)
148
if (locations & location_vars[l].location)
149
vars = add_var(vars, location_vars[l].vs_vars);
154
fs_location_vars(glamor_program_location locations)
157
char *vars = strdup("");
159
for (l = 0; vars && l < NUM_LOCATION_VARS; l++)
160
if (locations & location_vars[l].location)
161
vars = add_var(vars, location_vars[l].fs_vars);
165
static const char vs_template[] =
167
"%s" /* prim vs_vars */
168
"%s" /* fill vs_vars */
169
"%s" /* location vs_vars */
170
GLAMOR_DECLARE_MATRIX
172
"%s" /* prim vs_exec, outputs 'pos' and gl_Position */
173
"%s" /* fill vs_exec */
176
static const char fs_template[] =
178
GLAMOR_DEFAULT_PRECISION
179
"%s" /* prim fs_vars */
180
"%s" /* fill fs_vars */
181
"%s" /* location fs_vars */
183
"%s" /* prim fs_exec */
184
"%s" /* fill fs_exec */
195
static const glamor_facet facet_null_fill = {
200
glamor_get_uniform(glamor_program *prog,
201
glamor_program_location location,
205
if (location && (prog->locations & location) == 0)
207
uniform = glGetUniformLocation(prog->prog, name);
209
ErrorF("%s uniform %d\n", name, uniform);
215
glamor_build_program(ScreenPtr screen,
216
glamor_program *prog,
217
const glamor_facet *prim,
218
const glamor_facet *fill)
220
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
222
glamor_program_location locations = prim->locations;
223
glamor_program_flag flags = prim->flags;
225
int version = prim->version;
226
char *version_string = NULL;
228
char *fs_vars = NULL;
229
char *vs_vars = NULL;
231
char *vs_prog_string;
232
char *fs_prog_string;
234
GLint fs_prog, vs_prog;
237
fill = &facet_null_fill;
239
locations |= fill->locations;
240
flags |= fill->flags;
241
version = MAX(version, fill->version);
243
if (version > glamor_priv->glsl_version)
246
vs_vars = vs_location_vars(locations);
247
fs_vars = fs_location_vars(locations);
255
if (asprintf(&version_string, "#version %d\n", version) < 0)
256
version_string = NULL;
261
if (asprintf(&vs_prog_string,
268
str(fill->vs_exec)) < 0)
269
vs_prog_string = NULL;
271
if (asprintf(&fs_prog_string,
278
str(fill->fs_exec)) < 0)
279
fs_prog_string = NULL;
281
if (!vs_prog_string || !fs_prog_string)
286
ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s",
287
prim->name, fill->name, vs_prog_string, fs_prog_string);
290
prog->prog = glCreateProgram();
292
prog->locations = locations;
293
prog->prim_use = prim->use;
294
prog->fill_use = fill->use;
296
vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string);
297
fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string);
298
free(vs_prog_string);
299
free(fs_prog_string);
300
glAttachShader(prog->prog, vs_prog);
301
glDeleteShader(vs_prog);
302
glAttachShader(prog->prog, fs_prog);
303
glDeleteShader(fs_prog);
304
glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive");
306
if (prim->source_name) {
308
ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", prim->source_name);
310
glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name);
313
glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name);
315
prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix");
316
prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg");
317
prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg");
318
prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_offset");
319
prog->fill_size_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_size");
320
prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
322
if (glGetError() != GL_NO_ERROR)
325
free(version_string);
332
glDeleteProgram(prog->prog);
335
free(version_string);
342
glamor_use_program(PixmapPtr pixmap,
344
glamor_program *prog,
347
glUseProgram(prog->prog);
349
if (prog->prim_use && !prog->prim_use(pixmap, gc, prog, arg))
352
if (prog->fill_use && !prog->fill_use(pixmap, gc, prog, arg))
359
glamor_use_program_fill(PixmapPtr pixmap,
361
glamor_program_fill *program_fill,
362
const glamor_facet *prim)
364
ScreenPtr screen = pixmap->drawable.pScreen;
365
glamor_program *prog = &program_fill->progs[gc->fillStyle];
367
int fill_style = gc->fillStyle;
368
const glamor_facet *fill;
374
fill = glamor_facet_fill[fill_style];
378
if (!glamor_build_program(screen, prog, prim, fill))
382
if (!glamor_use_program(pixmap, gc, prog, NULL))