2 * Copyright © 2015 Red Hat
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #include "nir_builder.h"
29 * This is based on the logic in st_get_bitmap_shader() in TGSI compiler.
30 * From st_cb_bitmap.c:
32 * glBitmaps are drawn as textured quads. The user's bitmap pattern
33 * is stored in a texture image. An alpha8 texture format is used.
34 * The fragment shader samples a bit (texel) from the texture, then
35 * discards the fragment if the bit is off.
37 * Note that we actually store the inverse image of the bitmap to
38 * simplify the fragment program. An "on" bit gets stored as texel=0x0
39 * and an "off" bit is stored as texel=0xff. Then we kill the
40 * fragment if the negated texel value is less than zero.
42 * Note that the texture format will be, according to what driver supports,
43 * in order of preference (with swizzle):
49 * If L8_UNORM, options->swizzle_xxxx is true. Otherwise we can just use
52 * Run before nir_lower_io.
56 get_texcoord(nir_shader
*shader
)
58 nir_variable
*texcoord
= NULL
;
60 /* find gl_TexCoord, if it exists: */
61 nir_foreach_variable(var
, &shader
->inputs
) {
62 if (var
->data
.location
== VARYING_SLOT_TEX0
) {
68 /* otherwise create it: */
69 if (texcoord
== NULL
) {
70 texcoord
= nir_variable_create(shader
,
74 texcoord
->data
.location
= VARYING_SLOT_TEX0
;
81 lower_bitmap(nir_shader
*shader
, nir_builder
*b
,
82 const nir_lower_bitmap_options
*options
)
84 nir_ssa_def
*texcoord
;
87 nir_intrinsic_instr
*discard
;
89 texcoord
= nir_load_var(b
, get_texcoord(shader
));
91 const struct glsl_type
*sampler2D
=
92 glsl_sampler_type(GLSL_SAMPLER_DIM_2D
, false, false, GLSL_TYPE_FLOAT
);
94 nir_variable
*tex_var
=
95 nir_variable_create(shader
, nir_var_uniform
, sampler2D
, "bitmap_tex");
96 tex_var
->data
.binding
= options
->sampler
;
97 tex_var
->data
.explicit_binding
= true;
98 tex_var
->data
.how_declared
= nir_var_hidden
;
100 nir_deref_instr
*tex_deref
= nir_build_deref_var(b
, tex_var
);
102 tex
= nir_tex_instr_create(shader
, 3);
103 tex
->op
= nir_texop_tex
;
104 tex
->sampler_dim
= GLSL_SAMPLER_DIM_2D
;
105 tex
->coord_components
= 2;
106 tex
->dest_type
= nir_type_float
;
107 tex
->src
[0].src_type
= nir_tex_src_texture_deref
;
108 tex
->src
[0].src
= nir_src_for_ssa(&tex_deref
->dest
.ssa
);
109 tex
->src
[1].src_type
= nir_tex_src_sampler_deref
;
110 tex
->src
[1].src
= nir_src_for_ssa(&tex_deref
->dest
.ssa
);
111 tex
->src
[2].src_type
= nir_tex_src_coord
;
113 nir_src_for_ssa(nir_channels(b
, texcoord
,
114 (1 << tex
->coord_components
) - 1));
116 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
, 4, 32, NULL
);
117 nir_builder_instr_insert(b
, &tex
->instr
);
119 /* kill if tex != 0.0.. take .x or .w channel according to format: */
120 cond
= nir_f2b(b
, nir_channel(b
, &tex
->dest
.ssa
,
121 options
->swizzle_xxxx
? 0 : 3));
123 discard
= nir_intrinsic_instr_create(shader
, nir_intrinsic_discard_if
);
124 discard
->src
[0] = nir_src_for_ssa(cond
);
125 nir_builder_instr_insert(b
, &discard
->instr
);
127 shader
->info
.fs
.uses_discard
= true;
131 lower_bitmap_impl(nir_function_impl
*impl
,
132 const nir_lower_bitmap_options
*options
)
136 nir_builder_init(&b
, impl
);
137 b
.cursor
= nir_before_cf_list(&impl
->body
);
139 lower_bitmap(impl
->function
->shader
, &b
, options
);
141 nir_metadata_preserve(impl
, nir_metadata_block_index
|
142 nir_metadata_dominance
);
146 nir_lower_bitmap(nir_shader
*shader
,
147 const nir_lower_bitmap_options
*options
)
149 assert(shader
->info
.stage
== MESA_SHADER_FRAGMENT
);
151 lower_bitmap_impl(nir_shader_get_entrypoint(shader
), options
);