101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2015 Red Hat
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2001e04c3fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2101e04c3fSmrg * SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "nir.h"
2501e04c3fSmrg#include "nir_builder.h"
2601e04c3fSmrg
2701e04c3fSmrg/* Lower glBitmap().
2801e04c3fSmrg *
2901e04c3fSmrg * This is based on the logic in st_get_bitmap_shader() in TGSI compiler.
3001e04c3fSmrg * From st_cb_bitmap.c:
3101e04c3fSmrg *
3201e04c3fSmrg *    glBitmaps are drawn as textured quads.  The user's bitmap pattern
3301e04c3fSmrg *    is stored in a texture image.  An alpha8 texture format is used.
3401e04c3fSmrg *    The fragment shader samples a bit (texel) from the texture, then
3501e04c3fSmrg *    discards the fragment if the bit is off.
3601e04c3fSmrg *
3701e04c3fSmrg *    Note that we actually store the inverse image of the bitmap to
3801e04c3fSmrg *    simplify the fragment program.  An "on" bit gets stored as texel=0x0
3901e04c3fSmrg *    and an "off" bit is stored as texel=0xff.  Then we kill the
4001e04c3fSmrg *    fragment if the negated texel value is less than zero.
4101e04c3fSmrg *
4201e04c3fSmrg * Note that the texture format will be, according to what driver supports,
4301e04c3fSmrg * in order of preference (with swizzle):
4401e04c3fSmrg *
4501e04c3fSmrg *    I8_UNORM - .xxxx
4601e04c3fSmrg *    A8_UNORM - .000x
4701e04c3fSmrg *    L8_UNORM - .xxx1
4801e04c3fSmrg *
4901e04c3fSmrg * If L8_UNORM, options->swizzle_xxxx is true.  Otherwise we can just use
5001e04c3fSmrg * the .w comp.
5101e04c3fSmrg *
5201e04c3fSmrg * Run before nir_lower_io.
5301e04c3fSmrg */
5401e04c3fSmrg
5501e04c3fSmrgstatic nir_variable *
5601e04c3fSmrgget_texcoord(nir_shader *shader)
5701e04c3fSmrg{
587ec681f3Smrg   nir_variable *texcoord =
597ec681f3Smrg      nir_find_variable_with_location(shader, nir_var_shader_in,
607ec681f3Smrg                                      VARYING_SLOT_TEX0);
6101e04c3fSmrg   /* otherwise create it: */
6201e04c3fSmrg   if (texcoord == NULL) {
6301e04c3fSmrg      texcoord = nir_variable_create(shader,
6401e04c3fSmrg                                     nir_var_shader_in,
6501e04c3fSmrg                                     glsl_vec4_type(),
6601e04c3fSmrg                                     "gl_TexCoord");
6701e04c3fSmrg      texcoord->data.location = VARYING_SLOT_TEX0;
6801e04c3fSmrg   }
6901e04c3fSmrg
7001e04c3fSmrg   return texcoord;
7101e04c3fSmrg}
7201e04c3fSmrg
7301e04c3fSmrgstatic void
7401e04c3fSmrglower_bitmap(nir_shader *shader, nir_builder *b,
7501e04c3fSmrg             const nir_lower_bitmap_options *options)
7601e04c3fSmrg{
7701e04c3fSmrg   nir_ssa_def *texcoord;
7801e04c3fSmrg   nir_tex_instr *tex;
7901e04c3fSmrg   nir_ssa_def *cond;
8001e04c3fSmrg
8101e04c3fSmrg   texcoord = nir_load_var(b, get_texcoord(shader));
8201e04c3fSmrg
8301e04c3fSmrg   const struct glsl_type *sampler2D =
8401e04c3fSmrg      glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, GLSL_TYPE_FLOAT);
8501e04c3fSmrg
8601e04c3fSmrg   nir_variable *tex_var =
8701e04c3fSmrg      nir_variable_create(shader, nir_var_uniform, sampler2D, "bitmap_tex");
8801e04c3fSmrg   tex_var->data.binding = options->sampler;
897e102996Smaya   tex_var->data.explicit_binding = true;
907e102996Smaya   tex_var->data.how_declared = nir_var_hidden;
9101e04c3fSmrg
927e102996Smaya   nir_deref_instr *tex_deref = nir_build_deref_var(b, tex_var);
937e102996Smaya
947e102996Smaya   tex = nir_tex_instr_create(shader, 3);
9501e04c3fSmrg   tex->op = nir_texop_tex;
9601e04c3fSmrg   tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
9701e04c3fSmrg   tex->coord_components = 2;
987ec681f3Smrg   tex->dest_type = nir_type_float32;
997e102996Smaya   tex->src[0].src_type = nir_tex_src_texture_deref;
1007e102996Smaya   tex->src[0].src = nir_src_for_ssa(&tex_deref->dest.ssa);
1017e102996Smaya   tex->src[1].src_type = nir_tex_src_sampler_deref;
1027e102996Smaya   tex->src[1].src = nir_src_for_ssa(&tex_deref->dest.ssa);
1037e102996Smaya   tex->src[2].src_type = nir_tex_src_coord;
1047e102996Smaya   tex->src[2].src =
10501e04c3fSmrg      nir_src_for_ssa(nir_channels(b, texcoord,
10601e04c3fSmrg                                   (1 << tex->coord_components) - 1));
10701e04c3fSmrg
10801e04c3fSmrg   nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
10901e04c3fSmrg   nir_builder_instr_insert(b, &tex->instr);
11001e04c3fSmrg
11101e04c3fSmrg   /* kill if tex != 0.0.. take .x or .w channel according to format: */
11201e04c3fSmrg   cond = nir_f2b(b, nir_channel(b, &tex->dest.ssa,
11301e04c3fSmrg                  options->swizzle_xxxx ? 0 : 3));
11401e04c3fSmrg
1157ec681f3Smrg   nir_discard_if(b, cond);
11601e04c3fSmrg
11701e04c3fSmrg   shader->info.fs.uses_discard = true;
11801e04c3fSmrg}
11901e04c3fSmrg
12001e04c3fSmrgstatic void
12101e04c3fSmrglower_bitmap_impl(nir_function_impl *impl,
12201e04c3fSmrg                  const nir_lower_bitmap_options *options)
12301e04c3fSmrg{
12401e04c3fSmrg   nir_builder b;
12501e04c3fSmrg
12601e04c3fSmrg   nir_builder_init(&b, impl);
12701e04c3fSmrg   b.cursor = nir_before_cf_list(&impl->body);
12801e04c3fSmrg
12901e04c3fSmrg   lower_bitmap(impl->function->shader, &b, options);
13001e04c3fSmrg
13101e04c3fSmrg   nir_metadata_preserve(impl, nir_metadata_block_index |
13201e04c3fSmrg                               nir_metadata_dominance);
13301e04c3fSmrg}
13401e04c3fSmrg
13501e04c3fSmrgvoid
13601e04c3fSmrgnir_lower_bitmap(nir_shader *shader,
13701e04c3fSmrg                 const nir_lower_bitmap_options *options)
13801e04c3fSmrg{
13901e04c3fSmrg   assert(shader->info.stage == MESA_SHADER_FRAGMENT);
14001e04c3fSmrg
14101e04c3fSmrg   lower_bitmap_impl(nir_shader_get_entrypoint(shader), options);
14201e04c3fSmrg}
143