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 tex
= nir_tex_instr_create(shader
, 1);
92 tex
->op
= nir_texop_tex
;
93 tex
->sampler_dim
= GLSL_SAMPLER_DIM_2D
;
94 tex
->coord_components
= 2;
95 tex
->sampler_index
= options
->sampler
;
96 tex
->texture_index
= options
->sampler
;
97 tex
->dest_type
= nir_type_float
;
98 tex
->src
[0].src_type
= nir_tex_src_coord
;
100 nir_src_for_ssa(nir_channels(b
, texcoord
,
101 (1 << tex
->coord_components
) - 1));
103 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
, 4, 32, NULL
);
104 nir_builder_instr_insert(b
, &tex
->instr
);
106 /* kill if tex != 0.0.. take .x or .w channel according to format: */
107 cond
= nir_f2b(b
, nir_channel(b
, &tex
->dest
.ssa
,
108 options
->swizzle_xxxx
? 0 : 3));
110 discard
= nir_intrinsic_instr_create(shader
, nir_intrinsic_discard_if
);
111 discard
->src
[0] = nir_src_for_ssa(cond
);
112 nir_builder_instr_insert(b
, &discard
->instr
);
114 shader
->info
.fs
.uses_discard
= true;
118 lower_bitmap_impl(nir_function_impl
*impl
,
119 const nir_lower_bitmap_options
*options
)
123 nir_builder_init(&b
, impl
);
124 b
.cursor
= nir_before_cf_list(&impl
->body
);
126 lower_bitmap(impl
->function
->shader
, &b
, options
);
128 nir_metadata_preserve(impl
, nir_metadata_block_index
|
129 nir_metadata_dominance
);
133 nir_lower_bitmap(nir_shader
*shader
,
134 const nir_lower_bitmap_options
*options
)
136 assert(shader
->info
.stage
== MESA_SHADER_FRAGMENT
);
138 lower_bitmap_impl(nir_shader_get_entrypoint(shader
), options
);